diff options
Diffstat (limited to 'src')
8 files changed, 325 insertions, 110 deletions
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<Pair<MusicDirectory, Boolean>> {
+ 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<MusicDirectory, Boolean>(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<Entry> 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 @@ -908,6 +908,11 @@ public class CachedMusicService implements MusicService { } @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 @@ -789,6 +789,11 @@ public class OfflineMusicService implements MusicService { } @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 @@ -1392,6 +1392,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<Void> 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<Void> task = new ViewUrlTask(view.getContext(), view, url, size); + task.execute(); + return task; + } + public SilentBackgroundTask<Void> 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<Void> { + 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<Void> { private final Context mContext; private final String mUsername; |