aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2015-01-12 15:30:35 -0800
committerScott Jackson <daneren2005@gmail.com>2015-01-12 15:30:35 -0800
commitbd95555df0a465df1112a6178dcf213c6f73174b (patch)
tree00f62d77fa277e467507f2fd662ad9007d92e450 /src
parent2602d6405f53e9f3923dcb941b9f68e0df1f593a (diff)
downloaddsub-bd95555df0a465df1112a6178dcf213c6f73174b.tar.gz
dsub-bd95555df0a465df1112a6178dcf213c6f73174b.tar.bz2
dsub-bd95555df0a465df1112a6178dcf213c6f73174b.zip
Start of displaying artist info as a header
Diffstat (limited to 'src')
-rw-r--r--src/github/daneren2005/dsub/fragments/NowPlayingFragment.java4
-rw-r--r--src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java240
-rw-r--r--src/github/daneren2005/dsub/service/CachedMusicService.java5
-rw-r--r--src/github/daneren2005/dsub/service/MusicService.java2
-rw-r--r--src/github/daneren2005/dsub/service/OfflineMusicService.java5
-rw-r--r--src/github/daneren2005/dsub/service/RESTMusicService.java63
-rw-r--r--src/github/daneren2005/dsub/util/FileUtil.java27
-rw-r--r--src/github/daneren2005/dsub/util/ImageLoader.java89
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;