From bd95555df0a465df1112a6178dcf213c6f73174b Mon Sep 17 00:00:00 2001 From: Scott Jackson Date: Mon, 12 Jan 2015 15:30:35 -0800 Subject: Start of displaying artist info as a header --- .../dsub/fragments/NowPlayingFragment.java | 4 +- .../dsub/fragments/SelectDirectoryFragment.java | 240 +++++++++++++-------- .../dsub/service/CachedMusicService.java | 5 + .../daneren2005/dsub/service/MusicService.java | 2 + .../dsub/service/OfflineMusicService.java | 5 + .../daneren2005/dsub/service/RESTMusicService.java | 63 +++++- src/github/daneren2005/dsub/util/FileUtil.java | 27 +++ src/github/daneren2005/dsub/util/ImageLoader.java | 89 +++++++- 8 files changed, 325 insertions(+), 110 deletions(-) (limited to 'src') diff --git a/src/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/src/github/daneren2005/dsub/fragments/NowPlayingFragment.java index 06c88863..d3dea3bd 100644 --- a/src/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/src/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -869,7 +869,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis updateButtons(); if(currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) { - getImageLoader().loadImage(albumArtImageView, null, true, false); + getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false); } if(downloadService != null) { downloadService.startRemoteScan(); @@ -1226,7 +1226,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis bookmarkButton.setImageResource(bookmark); } else { songTitleTextView.setText(null); - getImageLoader().loadImage(albumArtImageView, null, true, false); + getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false); starButton.setImageResource(android.R.drawable.btn_star_big_off); setSubtitle(null); } diff --git a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index ae02c40f..9cb8c582 100644 --- a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -9,6 +9,9 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; +import android.text.Html; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -26,6 +29,7 @@ import android.widget.ListView; import android.widget.RatingBar; import android.widget.TextView; import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.ArtistInfo; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.ServerInfo; import github.daneren2005.dsub.domain.Share; @@ -69,6 +73,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private boolean albumContext = false; private boolean addAlbumHeader = false; private LoadTask currentTask; + ArtistInfo artistInfo; String id; String name; @@ -89,7 +94,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter boolean largeAlbums = false; boolean topTracks = false; String lookupEntry; - + public SelectDirectoryFragment() { super(); } @@ -475,7 +480,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getMusicDirectory(final String id, final String name, final boolean refresh) { setTitle(name); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { MusicDirectory dir = getMusicDirectory(id, name, refresh, service, this); @@ -512,7 +517,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getRecursiveMusicDirectory(final String id, final String name, final boolean refresh) { setTitle(name); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { MusicDirectory root; @@ -554,7 +559,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getPlaylist(final String playlistId, final String playlistName, final boolean refresh) { setTitle(playlistName); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { return service.getPlaylist(refresh, playlistId, playlistName, context, this); @@ -565,7 +570,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getPodcast(final String podcastId, final String podcastName, final boolean refresh) { setTitle(podcastName); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { return service.getPodcastEpisodes(refresh, podcastId, context, this); @@ -576,7 +581,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getShare(final Share share, final boolean refresh) { setTitle(share.getName()); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { return share.getMusicDirectory(); @@ -587,7 +592,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void getTopTracks(final String id, final String name, final boolean refresh) { setTitle(name); - new LoadTask() { + new LoadTask(refresh) { @Override protected MusicDirectory load(MusicService service) throws Exception { return service.getTopTrackSongs(name, 20, context, this); @@ -612,7 +617,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter setTitle(albumListExtra); } - new LoadTask() { + new LoadTask(true) { @Override protected MusicDirectory load(MusicService service) throws Exception { MusicDirectory result; @@ -635,9 +640,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } private abstract class LoadTask extends TabBackgroundTask> { + private boolean refresh; - public LoadTask() { + public LoadTask(boolean refresh) { super(SelectDirectoryFragment.this); + this.refresh = refresh; currentTask = this; } @@ -661,6 +668,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter if(albums.size() == 0) { artist = false; } + + // If artist, we want to load the artist info to use later + if(artist) { + artistInfo = musicService.getArtistInfo(id, refresh, context, this); + } return new Pair(dir, licenseValid); } @@ -674,8 +686,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private void finishLoading() { // Show header if not album list type and not root and not artist - if(albumListType == null && !"root".equals(id) && !artist) { - View header = createHeader(entries); + // For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists + if(albumListType == null && !"root".equals(id) && (!artist || (ServerInfo.checkServerVersion(context, "1.11") && artistInfo != null))) { + View header = createHeader(); if(header != null && entryList != null) { entryList.addHeaderView(header, null, false); } @@ -1220,7 +1233,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter replaceFragment(fragment, true); } - private View createHeader(List entries) { + private View createHeader() { View header = entryList.findViewById(R.id.select_album_header); boolean add = false; if(header == null) { @@ -1228,36 +1241,75 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter add = true; } - final ImageLoader imageLoader = getImageLoader(); - - // Try a few times to get a random cover art - Entry coverArt = null; - for(int i = 0; (i < 3) && (coverArt == null || coverArt.getCoverArt() == null); i++) { - coverArt = entries.get(random.nextInt(entries.size())); + setupCoverArt(header); + setupTextDisplay(header); + + if(add) { + setupButtonEvents(header); } - - final Entry albumRep = coverArt; + + if(add) { + return header; + } else { + return null; + } + } + + private void setupCoverArt(View header) { + final ImageLoader imageLoader = getImageLoader(); View coverArtView = header.findViewById(R.id.select_album_art); - coverArtView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if(albumRep.getCoverArt() == null) { - return; - } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - ImageView fullScreenView = new ImageView(context); - imageLoader.loadImage(fullScreenView, albumRep, true, true); - builder.setCancelable(true); - - AlertDialog imageDialog = builder.create(); - // Set view here with unecessary 0's to remove top/bottom border - imageDialog.setView(fullScreenView, 0, 0, 0, 0); - imageDialog.show(); + // Try a few times to get a random cover art + if(artistInfo != null) { + final String url = artistInfo.getImageUrl(); + coverArtView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (url == null) { + return; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + ImageView fullScreenView = new ImageView(context); + imageLoader.loadImage(fullScreenView, url, true); + builder.setCancelable(true); + + AlertDialog imageDialog = builder.create(); + // Set view here with unecessary 0's to remove top/bottom border + imageDialog.setView(fullScreenView, 0, 0, 0, 0); + imageDialog.show(); + } + }); + imageLoader.loadImage(coverArtView, url, false); + } else if(entries.size() > 0) { + Entry coverArt = null; + for (int i = 0; (i < 3) && (coverArt == null || coverArt.getCoverArt() == null); i++) { + coverArt = entries.get(random.nextInt(entries.size())); } - }); - imageLoader.loadImage(coverArtView, albumRep, false, true); + final Entry albumRep = coverArt; + coverArtView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (albumRep.getCoverArt() == null) { + return; + } + + AlertDialog.Builder builder = new AlertDialog.Builder(context); + ImageView fullScreenView = new ImageView(context); + imageLoader.loadImage(fullScreenView, albumRep, true, true); + builder.setCancelable(true); + + AlertDialog imageDialog = builder.create(); + // Set view here with unecessary 0's to remove top/bottom border + imageDialog.setView(fullScreenView, 0, 0, 0, 0); + imageDialog.show(); + } + }); + imageLoader.loadImage(coverArtView, albumRep, false, true); + } + } + private void setupTextDisplay(View header) { TextView titleView = (TextView) header.findViewById(R.id.select_album_title); if(playlistName != null) { titleView.setText(playlistName); @@ -1266,6 +1318,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter titleView.setPadding(0, 6, 4, 8); } else if(name != null) { titleView.setText(name); + + if(artistInfo != null) { + titleView.setPadding(0, 6, 4, 8); + } } else if(share != null) { titleView.setVisibility(View.GONE); } @@ -1290,13 +1346,15 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } } } - if(songCount == 0) { - return null; - } final TextView artistView = (TextView) header.findViewById(R.id.select_album_artist); - if(podcastDescription != null) { - artistView.setText(podcastDescription); + if(podcastDescription != null || artistInfo != null) { + String text = podcastDescription != null ? podcastDescription : artistInfo.getBiography(); + Spanned spanned = null; + if(text != null) { + spanned = Html.fromHtml(text); + } + artistView.setText(spanned); artistView.setSingleLine(false); artistView.setLines(5); artistView.setTextAppearance(context, android.R.style.TextAppearance_Small); @@ -1312,6 +1370,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter } } }); + artistView.setMovementMethod(LinkMovementMethod.getInstance()); } else if(topTracks) { artistView.setText(R.string.menu_top_tracks); artistView.setVisibility(View.VISIBLE); @@ -1339,62 +1398,55 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter songCountView.setVisibility(View.GONE); songLengthView.setVisibility(View.GONE); } + } + private void setupButtonEvents(View header) { + ImageView shareButton = (ImageView) header.findViewById(R.id.select_album_share); + if(share != null || podcastId != null || !Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_SHARED, true) || Util.isOffline(context) || !UserUtil.canShare()) { + shareButton.setVisibility(View.GONE); + } else { + shareButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createShare(SelectDirectoryFragment.this.entries); + } + }); + } - if(add) { - ImageView shareButton = (ImageView) header.findViewById(R.id.select_album_share); - if(share != null || podcastId != null || !Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_SHARED, true) || Util.isOffline(context) || !UserUtil.canShare()) { - shareButton.setVisibility(View.GONE); - } else { - shareButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - createShare(SelectDirectoryFragment.this.entries); - } - }); - } - - final ImageButton starButton = (ImageButton) header.findViewById(R.id.select_album_star); - if(directory != null && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_STAR, true)) { - starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); - starButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - toggleStarred(directory, new OnStarChange() { - @Override - void starChange(boolean starred) { - starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); - } - }); - } - }); - } else { - starButton.setVisibility(View.GONE); - } - - View ratingBarWrapper = header.findViewById(R.id.select_album_rate_wrapper); - final RatingBar ratingBar = (RatingBar) header.findViewById(R.id.select_album_rate); - if(directory != null && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_RATING, true) && !Util.isOffline(context)) { - ratingBar.setRating(directory.getRating()); - ratingBarWrapper.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - setRating(directory, new OnRatingChange() { - @Override - void ratingChange(int rating) { - ratingBar.setRating(directory.getRating()); - } - }); - } - }); - } else { - ratingBar.setVisibility(View.GONE); - } + final ImageButton starButton = (ImageButton) header.findViewById(R.id.select_album_star); + if(directory != null && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_STAR, true)) { + starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); + starButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toggleStarred(directory, new OnStarChange() { + @Override + void starChange(boolean starred) { + starButton.setImageResource(directory.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off); + } + }); + } + }); + } else { + starButton.setVisibility(View.GONE); } - if(add) { - return header; + View ratingBarWrapper = header.findViewById(R.id.select_album_rate_wrapper); + final RatingBar ratingBar = (RatingBar) header.findViewById(R.id.select_album_rate); + if(directory != null && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_MENU_RATING, true) && !Util.isOffline(context)) { + ratingBar.setRating(directory.getRating()); + ratingBarWrapper.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setRating(directory, new OnRatingChange() { + @Override + void ratingChange(int rating) { + ratingBar.setRating(directory.getRating()); + } + }); + } + }); } else { - return null; + ratingBar.setVisibility(View.GONE); } } } diff --git a/src/github/daneren2005/dsub/service/CachedMusicService.java b/src/github/daneren2005/dsub/service/CachedMusicService.java index f3e91b38..232d0acf 100644 --- a/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -907,6 +907,11 @@ public class CachedMusicService implements MusicService { return info; } + @Override + public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + return musicService.getBitmap(url, size, context, progressListener, task); + } + @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ return musicService.processOfflineSyncs(context, progressListener); diff --git a/src/github/daneren2005/dsub/service/MusicService.java b/src/github/daneren2005/dsub/service/MusicService.java index 64061191..854a0aa4 100644 --- a/src/github/daneren2005/dsub/service/MusicService.java +++ b/src/github/daneren2005/dsub/service/MusicService.java @@ -180,6 +180,8 @@ public interface MusicService { Bitmap getAvatar(String username, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception; ArtistInfo getArtistInfo(String id, boolean refresh, Context context, ProgressListener progressListener) throws Exception; + + Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception; int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception; diff --git a/src/github/daneren2005/dsub/service/OfflineMusicService.java b/src/github/daneren2005/dsub/service/OfflineMusicService.java index dc4651d2..4bd90d09 100644 --- a/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -788,6 +788,11 @@ public class OfflineMusicService implements MusicService { throw new OfflineException(ERRORMSG); } + @Override + public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + throw new OfflineException(ERRORMSG); + } + @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ throw new OfflineException(ERRORMSG); diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java index 239b2b43..cd0ae376 100644 --- a/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -1391,6 +1391,54 @@ public class RESTMusicService implements MusicService { } } + @Override + public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { + // Synchronize on the url so that we don't download concurrently + synchronized (url) { + // Use cached file, if existing. + Bitmap bitmap = FileUtil.getMiscBitmap(context, url, size); + if(bitmap != null) { + return bitmap; + } + + InputStream in = null; + try { + HttpEntity entity = getEntityForURL(context, url, null, null, null, progressListener, task); + in = entity.getContent(); + Header contentEncoding = entity.getContentEncoding(); + if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) { + in = new GZIPInputStream(in); + } + + // If content type is XML, an error occurred. Get it. + String contentType = Util.getContentType(entity); + if (contentType != null && contentType.startsWith("text/xml")) { + new ErrorParser(context, getInstance(context)).parse(new InputStreamReader(in, Constants.UTF_8)); + return null; // Never reached. + } + + byte[] bytes = Util.toByteArray(in); + if(task != null && task.isCancelled()) { + // Handle case where partial is downloaded and cancelled + return null; + } + + OutputStream out = null; + try { + out = new FileOutputStream(FileUtil.getMiscFile(context, url)); + out.write(bytes); + } finally { + Util.close(out); + } + + return FileUtil.getSampledBitmap(bytes, size, false); + } + finally { + Util.close(in); + } + } + } + @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ return processOfflineScrobbles(context, progressListener) + processOfflineStars(context, progressListener); @@ -1683,14 +1731,17 @@ public class RESTMusicService implements MusicService { redirectedUrl = request.getURI().toString(); } - redirectFrom = originalUrl.substring(0, originalUrl.indexOf("/rest/")); - redirectTo = redirectedUrl.substring(0, redirectedUrl.indexOf("/rest/")); + int index = originalUrl.indexOf("/rest/"); + if(index != -1) { + redirectFrom = originalUrl.substring(0, index); + redirectTo = redirectedUrl.substring(0, redirectedUrl.indexOf("/rest/")); - if(redirectFrom.compareTo(redirectTo) != 0) { - Log.i(TAG, redirectFrom + " redirects to " + redirectTo); + if (redirectFrom.compareTo(redirectTo) != 0) { + Log.i(TAG, redirectFrom + " redirects to " + redirectTo); + } + redirectionLastChecked = System.currentTimeMillis(); + redirectionNetworkType = getCurrentNetworkType(context); } - redirectionLastChecked = System.currentTimeMillis(); - redirectionNetworkType = getCurrentNetworkType(context); } private String rewriteUrlWithRedirect(Context context, String url) { diff --git a/src/github/daneren2005/dsub/util/FileUtil.java b/src/github/daneren2005/dsub/util/FileUtil.java index f59f9363..34838f33 100644 --- a/src/github/daneren2005/dsub/util/FileUtil.java +++ b/src/github/daneren2005/dsub/util/FileUtil.java @@ -250,6 +250,33 @@ public class FileUtil { return null; } + public static File getMiscDirectory(Context context) { + File dir = new File(getSubsonicDirectory(context), "misc"); + ensureDirectoryExistsAndIsReadWritable(dir); + ensureDirectoryExistsAndIsReadWritable(new File(dir, ".nomedia")); + return dir; + } + + public static File getMiscFile(Context context, String url) { + return new File(getMiscDirectory(context), Util.md5Hex(url) + ".jpeg"); + } + + public static Bitmap getMiscBitmap(Context context, String url, int size) { + File avatarFile = getMiscFile(context, url); + if (avatarFile.exists()) { + final BitmapFactory.Options opt = new BitmapFactory.Options(); + opt.inJustDecodeBounds = true; + BitmapFactory.decodeFile(avatarFile.getPath(), opt); + opt.inPurgeable = true; + opt.inSampleSize = Util.calculateInSampleSize(opt, size, Util.getScaledHeight(opt.outHeight, opt.outWidth, size)); + opt.inJustDecodeBounds = false; + + Bitmap bitmap = BitmapFactory.decodeFile(avatarFile.getPath(), opt); + return bitmap == null ? null : getScaledBitmap(bitmap, size, false); + } + return null; + } + public static Bitmap getSampledBitmap(byte[] bytes, int size) { return getSampledBitmap(bytes, size, true); } diff --git a/src/github/daneren2005/dsub/util/ImageLoader.java b/src/github/daneren2005/dsub/util/ImageLoader.java index be3f7d1b..5adf5e34 100644 --- a/src/github/daneren2005/dsub/util/ImageLoader.java +++ b/src/github/daneren2005/dsub/util/ImageLoader.java @@ -108,9 +108,11 @@ public class ImageLoader { if(entry == null) { key = getKey("unknown", size); color = COLORS[0]; + + return getUnknownImage(key, size, color, null, null); } else { key = getKey(entry.getId() + "unknown", size); - + String hash; if(entry.getAlbum() != null) { hash = entry.getAlbum(); @@ -120,16 +122,20 @@ public class ImageLoader { hash = entry.getId(); } color = COLORS[Math.abs(hash.hashCode()) % COLORS.length]; + + return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist()); } + } + private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) { Bitmap bitmap = cache.get(key); if(bitmap == null) { - bitmap = createUnknownImage(entry, size, color); + bitmap = createUnknownImage(size, color, topText, bottomText); cache.put(key, bitmap); } return bitmap; } - private Bitmap createUnknownImage(MusicDirectory.Entry entry, int size, int primaryColor) { + private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) { Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); @@ -140,18 +146,18 @@ public class ImageLoader { color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR)); canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color); - if(entry != null) { + if(topText != null || bottomText != null) { Paint font = new Paint(); font.setFlags(Paint.ANTI_ALIAS_FLAG); font.setColor(Color.WHITE); font.setTextSize(3.0f + size * 0.07f); - if(entry.getAlbum() != null) { - canvas.drawText(entry.getAlbum(), size * 0.05f, size * 0.6f, font); + if(topText != null) { + canvas.drawText(topText, size * 0.05f, size * 0.6f, font); } - if(entry.getArtist() != null) { - canvas.drawText(entry.getArtist(), size * 0.05f, size * 0.8f, font); + if(bottomText != null) { + canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font); } } @@ -210,6 +216,29 @@ public class ImageLoader { return task; } + public SilentBackgroundTask loadImage(View view, String url, boolean large) { + Bitmap bitmap; + int size = large ? imageSizeLarge : imageSizeDefault; + if (url == null) { + String key = getKey(url + "unknown", size); + int color = COLORS[Math.abs(key.hashCode()) % COLORS.length]; + bitmap = getUnknownImage(key, size, color, null, null); + setImage(view, Util.createDrawableFromBitmap(context, bitmap), true); + return null; + } + + bitmap = cache.get(getKey(url, size)); + if (bitmap != null && !bitmap.isRecycled()) { + final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap); + setImage(view, drawable, true); + return null; + } + + SilentBackgroundTask task = new ViewUrlTask(view.getContext(), view, url, size); + task.execute(); + return task; + } + public SilentBackgroundTask loadImage(Context context, RemoteControlClient remoteControl, MusicDirectory.Entry entry) { Bitmap bitmap; if (entry == null || entry.getCoverArt() == null) { @@ -382,6 +411,50 @@ public class ImageLoader { } } + private class ViewUrlTask extends SilentBackgroundTask { + private final Context mContext; + private final String mUrl; + private final ImageView mView; + private Drawable mDrawable; + private int mSize; + + public ViewUrlTask(Context context, View view, String url, int size) { + super(context); + mContext = context; + mView = (ImageView) view; + mUrl = url; + mSize = size; + } + + @Override + protected Void doInBackground() throws Throwable { + try { + MusicService musicService = MusicServiceFactory.getMusicService(mContext); + Bitmap bitmap = musicService.getBitmap(mUrl, mSize, mContext, null, this); + if(bitmap != null) { + String key = getKey(mUrl, mSize); + cache.put(key, bitmap); + // Make sure key is the most recently "used" + cache.get(key); + + mDrawable = Util.createDrawableFromBitmap(mContext, bitmap); + } + } catch (Throwable x) { + Log.e(TAG, "Failed to download from url " + mUrl, x); + cancelled.set(true); + } + + return null; + } + + @Override + protected void done(Void result) { + if(mDrawable != null) { + mView.setImageDrawable(mDrawable); + } + } + } + private class AvatarTask extends SilentBackgroundTask { private final Context mContext; private final String mUsername; -- cgit v1.2.3