aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java8
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java179
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java13
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java226
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java73
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/UpdateHelper.java263
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java60
-rw-r--r--app/src/main/res/values/strings.xml2
8 files changed, 449 insertions, 375 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
index 8d3bf099..f32c5255 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
@@ -819,8 +819,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void onSongsChanged(List<DownloadFile> songs, DownloadFile currentPlaying, int currentPlayingIndex) {
- if(this.currentPlaying != currentPlaying || currentPlaying == null) {
+ if(this.currentPlaying != currentPlaying || this.currentPlaying == null) {
onSongChanged(currentPlaying, currentPlayingIndex);
+ onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL);
}
}
@@ -836,4 +837,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
startButton.setImageResource(typedArray.getResourceId(0, 0));
typedArray.recycle();
}
+
+ @Override
+ public void onMetadataUpdate(MusicDirectory.Entry entry, int fieldChange) {
+
+ }
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
index 892891d2..a6517bf6 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
@@ -61,6 +61,7 @@ import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.audiofx.EqualizerController;
import github.daneren2005.dsub.domain.Bookmark;
+import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.domain.RepeatMode;
import github.daneren2005.dsub.domain.ServerInfo;
@@ -196,24 +197,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
starButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- DownloadFile currentDownload = getDownloadService().getCurrentPlaying();
- if (currentDownload != null) {
- final Entry currentSong = currentDownload.getSong();
- toggleStarred(currentSong, new OnStarChange() {
- @Override
- void starChange(boolean starred) {
- if(currentSong.isStarred()) {
- starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star));
- } else {
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline));
- } else {
- starButton.setImageResource(R.drawable.ic_toggle_star_outline_dark);
- }
- }
- }
- });
- }
+ getDownloadService().toggleStarred();
}
});
} else {
@@ -360,37 +344,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(downloadService == null) {
return;
}
-
- DownloadFile downloadFile = downloadService.getCurrentPlaying();
- if(downloadFile == null) {
- return;
- }
- Entry entry = downloadFile.getSong();
-
- // If rating == 1, already set so unset
- if(entry.getRating() == 1) {
- setRating(entry, 0);
-
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- rateBadButton.setImageResource(R.drawable.ic_action_rating_bad_dark);
- } else {
- rateBadButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.rating_bad));
- }
- } else {
- // Immediately skip to the next song
- downloadService.next(true);
-
- // Otherwise set rating to 1
- setRating(entry, 1);
- rateBadButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_bad_selected));
-
- // Make sure good rating is blank
- if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- rateGoodButton.setImageResource(R.drawable.ic_action_rating_good_dark);
- } else {
- rateGoodButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.rating_good));
- }
- }
+ downloadService.toggleRating(1);
}
});
rateGoodButton.setOnClickListener(new View.OnClickListener() {
@@ -400,34 +354,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if(downloadService == null) {
return;
}
-
- DownloadFile downloadFile = downloadService.getCurrentPlaying();
- if(downloadFile == null) {
- return;
- }
- Entry entry = downloadFile.getSong();
-
- // If rating == 5, already set so unset
- if(entry.getRating() == 5) {
- setRating(entry, 0);
-
- if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- rateGoodButton.setImageResource(R.drawable.ic_action_rating_good_dark);
- } else {
- rateGoodButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.rating_good));
- }
- } else {
- // Otherwise set rating to maximum
- setRating(entry, 5);
- rateGoodButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_good_selected));
-
- // Make sure bad rating is blank
- if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- rateBadButton.setImageResource(R.drawable.ic_action_rating_bad_dark);
- } else {
- rateBadButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.rating_bad));
- }
- }
+ downloadService.toggleRating(5);
}
});
@@ -694,10 +621,10 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
createNewPlaylist(entries, true);
return true;
case R.id.menu_star:
- toggleStarred(song.getSong());
+ UpdateHelper.toggleStarred(context, song.getSong());
return true;
case R.id.menu_rate:
- setRating(song.getSong());
+ UpdateHelper.setRating(context, song.getSong());
return true;
case R.id.menu_toggle_timer:
if(getDownloadService().getSleepTimer()) {
@@ -1093,7 +1020,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.createBookmark(currentSong, position, comment, context, null);
- new EntryInstanceUpdater(currentSong) {
+ new UpdateHelper.EntryInstanceUpdater(currentSong) {
@Override
public void update(Entry found) {
found.setBookmark(new Bookmark(position));
@@ -1235,54 +1162,10 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
Entry song = currentPlaying.getSong();
songTitleTextView.setText(song.getTitle());
getImageLoader().loadImage(albumArtImageView, song, true, true);
- if(song.isStarred()) {
- starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star));
- } else {
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline));
- } else {
- starButton.setImageResource(R.drawable.ic_toggle_star_outline_dark);
- }
- }
setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
-
- int badRating, goodRating, bookmark;
- if(song.getRating() == 1) {
- rateBadButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_bad_selected));
- } else {
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- badRating = R.drawable.ic_action_rating_bad_dark;
- } else {
- badRating = DrawableTint.getDrawableRes(context, R.attr.rating_bad);
- }
- rateBadButton.setImageResource(badRating);
- }
-
- if(song.getRating() == 5) {
- rateGoodButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_good_selected));
- } else {
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- goodRating = R.drawable.ic_action_rating_good_dark;
- } else {
- goodRating = DrawableTint.getDrawableRes(context, R.attr.rating_good);
- }
- rateGoodButton.setImageResource(goodRating);
- }
-
- if(song.getBookmark() != null) {
- bookmarkButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_menu_bookmark_selected));
- } else {
- if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
- bookmark = R.drawable.ic_menu_bookmark_dark;
- } else {
- bookmark = DrawableTint.getDrawableRes(context, R.attr.bookmark);
- }
- bookmarkButton.setImageResource(bookmark);
- }
} else {
songTitleTextView.setText(null);
getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false);
- starButton.setImageResource(R.drawable.ic_toggle_star_outline_dark);
setSubtitle(null);
}
}
@@ -1319,6 +1202,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize));
if(this.currentPlaying != currentPlaying) {
onSongChanged(currentPlaying, currentPlayingIndex);
+ onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL);
}
}
@@ -1401,6 +1285,53 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
}
+ @Override
+ public void onMetadataUpdate(Entry song, int fieldChange) {
+ if(song != null && song.isStarred()) {
+ starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star));
+ } else {
+ if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline));
+ } else {
+ starButton.setImageResource(R.drawable.ic_toggle_star_outline_dark);
+ }
+ }
+
+ int badRating, goodRating, bookmark;
+ if(song != null && song.getRating() == 1) {
+ rateBadButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_bad_selected));
+ } else {
+ if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ badRating = R.drawable.ic_action_rating_bad_dark;
+ } else {
+ badRating = DrawableTint.getDrawableRes(context, R.attr.rating_bad);
+ }
+ rateBadButton.setImageResource(badRating);
+ }
+
+ if(song != null && song.getRating() == 5) {
+ rateGoodButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_action_rating_good_selected));
+ } else {
+ if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ goodRating = R.drawable.ic_action_rating_good_dark;
+ } else {
+ goodRating = DrawableTint.getDrawableRes(context, R.attr.rating_good);
+ }
+ rateGoodButton.setImageResource(goodRating);
+ }
+
+ if(song != null && song.getBookmark() != null) {
+ bookmarkButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_menu_bookmark_selected));
+ } else {
+ if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+ bookmark = R.drawable.ic_menu_bookmark_dark;
+ } else {
+ bookmark = DrawableTint.getDrawableRes(context, R.attr.bookmark);
+ }
+ bookmarkButton.setImageResource(bookmark);
+ }
+ }
+
public void updateRepeatButton() {
DownloadService downloadService = getDownloadService();
switch (downloadService.getRepeatMode()) {
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
index 2db10c2e..9e6fec45 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -57,6 +57,7 @@ import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.util.Pair;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.TabBackgroundTask;
+import github.daneren2005.dsub.util.UpdateHelper;
import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.FastScroller;
@@ -1037,7 +1038,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
musicService.setStarred(entries, artists, albums, false, this, context);
for(Entry entry: unstar) {
- new EntryInstanceUpdater(entry) {
+ new UpdateHelper.EntryInstanceUpdater(entry) {
@Override
public void update(Entry found) {
found.setStarred(false);
@@ -1382,10 +1383,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
starButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- toggleStarred(directory, new OnStarChange() {
+ UpdateHelper.toggleStarred(context, directory, new UpdateHelper.OnStarChange() {
@Override
- void starChange(boolean starred) {
- if(directory.isStarred()) {
+ public void starChange(boolean starred) {
+ if (directory.isStarred()) {
starButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.star_outline));
starButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_star));
} else {
@@ -1406,9 +1407,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
ratingBarWrapper.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- setRating(directory, new OnRatingChange() {
+ UpdateHelper.setRating(context, directory, new UpdateHelper.OnRatingChange() {
@Override
- void ratingChange(int rating) {
+ public void ratingChange(int rating) {
ratingBar.setRating(directory.getRating());
}
});
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
index 8672f534..7baf9009 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -77,6 +77,7 @@ import github.daneren2005.dsub.util.MenuUtil;
import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.LoadingTask;
+import github.daneren2005.dsub.util.UpdateHelper;
import github.daneren2005.dsub.util.UserUtil;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.AlbumView;
@@ -327,7 +328,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
deleteRecursively(artist);
break;
case R.id.artist_menu_star:
- toggleStarred(artist);
+ UpdateHelper.toggleStarred(context, artist);
break;
case R.id.album_menu_play_now:
artistOverride = true;
@@ -354,7 +355,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
downloadRecursively(entry.getId(), true, true, false, false, true);
break;
case R.id.album_menu_star:
- toggleStarred(entry);
+ UpdateHelper.toggleStarred(context, entry);
break;
case R.id.album_menu_delete:
deleteRecursively(entry);
@@ -387,7 +388,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
addToPlaylist(songs);
break;
case R.id.song_menu_star:
- toggleStarred(entry);
+ UpdateHelper.toggleStarred(context, entry);
break;
case R.id.song_menu_play_external:
playExternalPlayer(entry);
@@ -411,7 +412,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
deleteBookmark(entry, null);
break;
case R.id.menu_rate:
- setRating(entry);
+ UpdateHelper.setRating(context, entry);
break;
default:
return false;
@@ -790,106 +791,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
dialog.show();
}
- public void toggleStarred(Entry entry) {
- toggleStarred(entry, null);
- }
-
- public void toggleStarred(final Entry entry, final OnStarChange onStarChange) {
- final boolean starred = !entry.isStarred();
- entry.setStarred(starred);
- if(onStarChange != null) {
- onStarChange.starChange(starred);
- }
-
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(context);
- if(entry.isDirectory() && Util.isTagBrowsing(context) && !Util.isOffline(context)) {
- if(entry.isAlbum()) {
- musicService.setStarred(null, null, Arrays.asList(entry), starred, null, context);
- } else {
- musicService.setStarred(null, Arrays.asList(entry), null, starred, null, context);
- }
- } else {
- musicService.setStarred(Arrays.asList(entry), null, null, starred, null, context);
- }
-
- new EntryInstanceUpdater(entry) {
- @Override
- public void update(Entry found) {
- found.setStarred(starred);
- }
- }.execute();
-
- return null;
- }
-
- @Override
- protected void done(Void result) {
- // UpdateView
- Util.toast(context, context.getResources().getString(starred ? R.string.starring_content_starred : R.string.starring_content_unstarred, entry.getTitle()));
- }
-
- @Override
- protected void error(Throwable error) {
- Log.w(TAG, "Failed to star", error);
- entry.setStarred(!starred);
- if(onStarChange != null) {
- onStarChange.starChange(!starred);
- }
-
- String msg;
- if (error instanceof OfflineException || error instanceof ServerTooOldException) {
- msg = getErrorMessage(error);
- } else {
- msg = context.getResources().getString(R.string.starring_content_error, entry.getTitle()) + " " + getErrorMessage(error);
- }
-
- Util.toast(context, msg, false);
- }
- }.execute();
- }
-
- public void toggleStarred(final Artist entry) {
- final boolean starred = !entry.isStarred();
- entry.setStarred(starred);
-
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(context);
- if(Util.isTagBrowsing(context) && !Util.isOffline(context)) {
- musicService.setStarred(null, Arrays.asList(new Entry(entry)), null, starred, null, context);
- } else {
- musicService.setStarred(Arrays.asList(new Entry(entry)), null, null, starred, null, context);
- }
- return null;
- }
-
- @Override
- protected void done(Void result) {
- // UpdateView
- Util.toast(context, context.getResources().getString(starred ? R.string.starring_content_starred : R.string.starring_content_unstarred, entry.getName()));
- }
-
- @Override
- protected void error(Throwable error) {
- Log.w(TAG, "Failed to star", error);
- entry.setStarred(!starred);
-
- String msg;
- if (error instanceof OfflineException || error instanceof ServerTooOldException) {
- msg = getErrorMessage(error);
- } else {
- msg = context.getResources().getString(R.string.starring_content_error, entry.getName()) + " " + getErrorMessage(error);
- }
-
- Util.toast(context, msg, false);
- }
- }.execute();
- }
-
protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background) {
downloadRecursively(id, "", true, save, append, autoplay, shuffle, background);
}
@@ -1737,7 +1638,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.deleteBookmark(entry, context, null);
- new EntryInstanceUpdater(entry) {
+ new UpdateHelper.EntryInstanceUpdater(entry) {
@Override
public void update(Entry found) {
found.setBookmark(null);
@@ -1773,80 +1674,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
});
}
- protected void setRating(Entry entry) {
- setRating(entry, null);
- }
- protected void setRating(final Entry entry, final OnRatingChange onRatingChange) {
- View layout = context.getLayoutInflater().inflate(R.layout.rating, null);
- final RatingBar ratingBar = (RatingBar) layout.findViewById(R.id.rating_bar);
- ratingBar.setRating((float) entry.getRating());
-
- AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(context.getResources().getString(R.string.rating_title, entry.getTitle()))
- .setView(layout)
- .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- int rating = (int) ratingBar.getRating();
- setRating(entry, rating, onRatingChange);
- }
- })
- .setNegativeButton(R.string.common_cancel, null);
-
- AlertDialog dialog = builder.create();
- dialog.show();
- }
-
- protected void setRating(Entry entry, int rating) {
- setRating(entry, rating, null);
- }
- protected void setRating(final Entry entry, final int rating, final OnRatingChange onRatingChange) {
- final int oldRating = entry.getRating();
- entry.setRating(rating);
-
- if(onRatingChange != null) {
- onRatingChange.ratingChange(rating);
- }
-
- new SilentBackgroundTask<Void>(context) {
- @Override
- protected Void doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(context);
- musicService.setRating(entry, rating, context, null);
-
- new EntryInstanceUpdater(entry) {
- @Override
- public void update(Entry found) {
- found.setRating(rating);
- }
- }.execute();
- return null;
- }
-
- @Override
- protected void done(Void result) {
- Util.toast(context, context.getResources().getString(rating > 0 ? R.string.rating_set_rating : R.string.rating_remove_rating, entry.getTitle()));
- }
-
- @Override
- protected void error(Throwable error) {
- entry.setRating(oldRating);
- if(onRatingChange != null) {
- onRatingChange.ratingChange(oldRating);
- }
-
- String msg;
- if (error instanceof OfflineException || error instanceof ServerTooOldException) {
- msg = getErrorMessage(error);
- } else {
- msg = context.getResources().getString(rating > 0 ? R.string.rating_set_rating_failed : R.string.rating_remove_rating_failed, entry.getTitle()) + " " + getErrorMessage(error);
- }
-
- Util.toast(context, msg, false);
- }
- }.execute();
- }
-
public SectionAdapter getCurrentAdapter() { return null; }
public void stopActionMode() {
SectionAdapter adapter = getCurrentAdapter();
@@ -1965,47 +1792,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
}
}
- protected abstract class EntryInstanceUpdater {
- private Entry entry;
-
- public EntryInstanceUpdater(Entry entry) {
- this.entry = entry;
- }
-
- public abstract void update(Entry found);
-
- public void execute() {
- DownloadService downloadService = getDownloadService();
- if(downloadService != null && !entry.isDirectory()) {
- boolean serializeChanges = false;
- List<DownloadFile> downloadFiles = downloadService.getDownloads();
- for(DownloadFile file: downloadFiles) {
- Entry check = file.getSong();
- if(entry.getId().equals(check.getId())) {
- update(entry);
- serializeChanges = true;
- }
- }
-
- if(serializeChanges) {
- downloadService.serializeQueue();
- }
- }
-
- Entry find = UpdateView.findEntry(entry);
- if(find != null) {
- update(find);
- }
- }
- }
-
- public abstract class OnRatingChange {
- abstract void ratingChange(int rating);
- }
- public abstract class OnStarChange {
- abstract void starChange(boolean starred);
- }
-
public abstract class RecursiveLoader extends LoadingTask<Boolean> {
protected MusicService musicService;
protected static final int MAX_SONGS = 500;
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
index 6dedca29..576791b2 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -48,6 +48,7 @@ import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.MediaRouteManager;
import github.daneren2005.dsub.util.ShufflePlayBuffer;
import github.daneren2005.dsub.util.SimpleServiceBinder;
+import github.daneren2005.dsub.util.UpdateHelper;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.util.compat.RemoteControlClientBase;
import github.daneren2005.dsub.util.tags.BastpUtil;
@@ -106,6 +107,11 @@ public class DownloadService extends Service {
private static final int SHUFFLE_MODE_ALL = 1;
private static final int SHUFFLE_MODE_ARTIST = 2;
+ public static final int METADATA_UPDATED_ALL = 0;
+ public static final int METADATA_UPDATED_STAR = 1;
+ public static final int METADATA_UPDATED_RATING = 2;
+ public static final int METADATA_UPDATED_BOOKMARK = 4;
+
private RemoteControlClientBase mRemoteControl;
private final IBinder binder = new SimpleServiceBinder<DownloadService>(this);
@@ -2465,6 +2471,55 @@ public class DownloadService extends Service {
}
}
+ public void toggleStarred() {
+ final DownloadFile currentPlaying = this.currentPlaying;
+ if(currentPlaying == null) {
+ return;
+ }
+
+ UpdateHelper.toggleStarred(this, currentPlaying.getSong(), new UpdateHelper.OnStarChange() {
+ @Override
+ public void starChange(boolean starred) {
+ if(currentPlaying == DownloadService.this.currentPlaying) {
+ onMetadataUpdate(METADATA_UPDATED_STAR);
+ }
+ }
+ });
+ }
+ public void toggleRating(int rating) {
+ if(currentPlaying == null) {
+ return;
+ }
+
+ MusicDirectory.Entry entry = currentPlaying.getSong();
+ if(entry.getRating() == rating) {
+ setRating(0);
+ } else {
+ setRating(rating);
+ }
+ }
+ public void setRating(int rating) {
+ final DownloadFile currentPlaying = this.currentPlaying;
+ if(currentPlaying == null) {
+ return;
+ }
+ MusicDirectory.Entry entry = currentPlaying.getSong();
+
+ // Immediately skip to the next song if down thumbed
+ if(rating == 1) {
+ next(true);
+ }
+
+ UpdateHelper.setRating(this, entry, rating, new UpdateHelper.OnRatingChange() {
+ @Override
+ public void ratingChange(int rating) {
+ if(currentPlaying == DownloadService.this.currentPlaying) {
+ onMetadataUpdate(METADATA_UPDATED_RATING);
+ }
+ }
+ });
+ }
+
public void addOnSongChangedListener(OnSongChangedListener listener) {
addOnSongChangedListener(listener, false);
}
@@ -2504,6 +2559,9 @@ public class DownloadService extends Service {
public void run() {
if(revision == atRevision) {
listener.onSongChanged(currentPlaying, currentPlayingIndex);
+
+ MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
+ listener.onMetadataUpdate(entry, METADATA_UPDATED_ALL);
}
}
});
@@ -2560,6 +2618,20 @@ public class DownloadService extends Service {
});
}
}
+ private synchronized void onMetadataUpdate() {
+ onMetadataUpdate(METADATA_UPDATED_ALL);
+ }
+ private synchronized void onMetadataUpdate(final int updateType) {
+ for(final OnSongChangedListener listener: onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
+ listener.onMetadataUpdate(entry, updateType);
+ }
+ });
+ }
+ }
private class BufferTask extends SilentBackgroundTask<Void> {
private final DownloadFile downloadFile;
@@ -2672,5 +2744,6 @@ public class DownloadService extends Service {
void onSongsChanged(List<DownloadFile> songs, DownloadFile currentPlaying, int currentPlayingIndex);
void onSongProgress(DownloadFile currentPlaying, int millisPlayed, Integer duration, boolean isSeekable);
void onStateUpdate(DownloadFile downloadFile, PlayerState playerState);
+ void onMetadataUpdate(MusicDirectory.Entry entry, int fieldChange);
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/UpdateHelper.java b/app/src/main/java/github/daneren2005/dsub/util/UpdateHelper.java
new file mode 100644
index 00000000..c7e0a04b
--- /dev/null
+++ b/app/src/main/java/github/daneren2005/dsub/util/UpdateHelper.java
@@ -0,0 +1,263 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2015 (C) Scott Jackson
+*/
+
+package github.daneren2005.dsub.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+import android.view.View;
+import android.widget.RatingBar;
+
+import java.util.Arrays;
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.Artist;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
+import github.daneren2005.dsub.fragments.SubsonicFragment;
+import github.daneren2005.dsub.service.DownloadFile;
+import github.daneren2005.dsub.service.DownloadService;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.service.OfflineException;
+import github.daneren2005.dsub.service.ServerTooOldException;
+import github.daneren2005.dsub.view.UpdateView;
+
+public final class UpdateHelper {
+ private static final String TAG = UpdateHelper.class.getSimpleName();
+
+ public static void toggleStarred(Context context, Entry entry) {
+ toggleStarred(context, entry, null);
+ }
+
+ public static void toggleStarred(final Context context, final Entry entry, final OnStarChange onStarChange) {
+ final boolean starred = !entry.isStarred();
+ entry.setStarred(starred);
+ if(onStarChange != null) {
+ onStarChange.starChange(starred);
+ }
+
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ if(entry.isDirectory() && Util.isTagBrowsing(context) && !Util.isOffline(context)) {
+ if(entry.isAlbum()) {
+ musicService.setStarred(null, null, Arrays.asList(entry), starred, null, context);
+ } else {
+ musicService.setStarred(null, Arrays.asList(entry), null, starred, null, context);
+ }
+ } else {
+ musicService.setStarred(Arrays.asList(entry), null, null, starred, null, context);
+ }
+
+ new EntryInstanceUpdater(entry) {
+ @Override
+ public void update(Entry found) {
+ found.setStarred(starred);
+ }
+ }.execute();
+
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ // UpdateView
+ Util.toast(context, context.getResources().getString(starred ? R.string.starring_content_starred : R.string.starring_content_unstarred, entry.getTitle()));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ Log.w(TAG, "Failed to star", error);
+ entry.setStarred(!starred);
+ if(onStarChange != null) {
+ onStarChange.starChange(!starred);
+ }
+
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = context.getResources().getString(R.string.starring_content_error, entry.getTitle()) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(context, msg, false);
+ }
+ }.execute();
+ }
+
+ public static void toggleStarred(final Context context, final Artist entry) {
+ final boolean starred = !entry.isStarred();
+ entry.setStarred(starred);
+
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ if(Util.isTagBrowsing(context) && !Util.isOffline(context)) {
+ musicService.setStarred(null, Arrays.asList(new Entry(entry)), null, starred, null, context);
+ } else {
+ musicService.setStarred(Arrays.asList(new Entry(entry)), null, null, starred, null, context);
+ }
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ // UpdateView
+ Util.toast(context, context.getResources().getString(starred ? R.string.starring_content_starred : R.string.starring_content_unstarred, entry.getName()));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ Log.w(TAG, "Failed to star", error);
+ entry.setStarred(!starred);
+
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = context.getResources().getString(R.string.starring_content_error, entry.getName()) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(context, msg, false);
+ }
+ }.execute();
+ }
+
+ public static void setRating(Activity context, Entry entry) {
+ setRating(context, entry, null);
+ }
+ public static void setRating(final Activity context, final Entry entry, final OnRatingChange onRatingChange) {
+ View layout = context.getLayoutInflater().inflate(R.layout.rating, null);
+ final RatingBar ratingBar = (RatingBar) layout.findViewById(R.id.rating_bar);
+ ratingBar.setRating((float) entry.getRating());
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(context.getResources().getString(R.string.rating_title, entry.getTitle()))
+ .setView(layout)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ int rating = (int) ratingBar.getRating();
+ setRating(context, entry, rating, onRatingChange);
+ }
+ })
+ .setNegativeButton(R.string.common_cancel, null);
+
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+
+ public static void setRating(Context context, Entry entry, int rating) {
+ setRating(context, entry, rating, null);
+ }
+ public static void setRating(final Context context, final Entry entry, final int rating, final OnRatingChange onRatingChange) {
+ final int oldRating = entry.getRating();
+ entry.setRating(rating);
+
+ if(onRatingChange != null) {
+ onRatingChange.ratingChange(rating);
+ }
+
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ musicService.setRating(entry, rating, context, null);
+
+ new EntryInstanceUpdater(entry) {
+ @Override
+ public void update(Entry found) {
+ found.setRating(rating);
+ }
+ }.execute();
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ Util.toast(context, context.getResources().getString(rating > 0 ? R.string.rating_set_rating : R.string.rating_remove_rating, entry.getTitle()));
+ }
+
+ @Override
+ protected void error(Throwable error) {
+ entry.setRating(oldRating);
+ if(onRatingChange != null) {
+ onRatingChange.ratingChange(oldRating);
+ }
+
+ String msg;
+ if (error instanceof OfflineException || error instanceof ServerTooOldException) {
+ msg = getErrorMessage(error);
+ } else {
+ msg = context.getResources().getString(rating > 0 ? R.string.rating_set_rating_failed : R.string.rating_remove_rating_failed, entry.getTitle()) + " " + getErrorMessage(error);
+ }
+
+ Util.toast(context, msg, false);
+ }
+ }.execute();
+ }
+
+ public static abstract class EntryInstanceUpdater {
+ private Entry entry;
+
+ public EntryInstanceUpdater(Entry entry) {
+ this.entry = entry;
+ }
+
+ public abstract void update(Entry found);
+
+ public void execute() {
+ DownloadService downloadService = DownloadService.getInstance();
+ if(downloadService != null && !entry.isDirectory()) {
+ boolean serializeChanges = false;
+ List<DownloadFile> downloadFiles = downloadService.getDownloads();
+ for(DownloadFile file: downloadFiles) {
+ Entry check = file.getSong();
+ if(entry.getId().equals(check.getId())) {
+ update(entry);
+ serializeChanges = true;
+ }
+ }
+
+ if(serializeChanges) {
+ downloadService.serializeQueue();
+ }
+ }
+
+ Entry find = UpdateView.findEntry(entry);
+ if(find != null) {
+ update(find);
+ }
+ }
+ }
+
+ public static abstract class OnStarChange {
+ public abstract void starChange(boolean starred);
+ }
+ public static abstract class OnRatingChange {
+ public abstract void ratingChange(int rating);
+ }
+}
diff --git a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
index 8ebbc9de..e2cbb307 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
@@ -31,26 +31,31 @@ import android.media.RemoteControlClient;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Build;
+import android.os.Bundle;
import android.support.v7.media.MediaRouter;
import android.util.Log;
+import github.daneren2005.dsub.R;
import github.daneren2005.dsub.activity.SubsonicActivity;
import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ImageLoader;
+import github.daneren2005.dsub.util.UpdateHelper;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class RemoteControlClientLP extends RemoteControlClientBase {
private static final String TAG = RemoteControlClientLP.class.getSimpleName();
+ private static final String CUSTOM_ACTION_THUMBS_UP = "github.daneren2005.dsub.THUMBS_UP";
+ private static final String CUSTOM_ACTION_THUMBS_DOWN = "github.daneren2005.dsub.THUMBS_DOWN";
+ private static final String CUSTOM_ACTION_STAR = "github.daneren2005.dsub.STAR";
protected MediaSession mediaSession;
protected DownloadService downloadService;
protected ImageLoader imageLoader;
- private PlaybackState previousState;
-
@Override
public void register(Context context, ComponentName mediaButtonReceiverComponent) {
downloadService = (DownloadService) context;
@@ -90,12 +95,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
@Override
public void setPlaybackState(int state) {
- PlaybackState.Builder builder;
- if(previousState == null) {
- builder = new PlaybackState.Builder();
- } else {
- builder = new PlaybackState.Builder(previousState);
- }
+ PlaybackState.Builder builder = new PlaybackState.Builder();
int newState = PlaybackState.STATE_NONE;
switch(state) {
@@ -120,9 +120,13 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
builder.setState(newState, position, 1.0f);
builder.setActions(getPlaybackActions());
+ DownloadFile downloadFile = downloadService.getCurrentPlaying();
+ if(downloadFile != null) {
+ addCustomActions(downloadFile.getSong(), builder);
+ }
+
PlaybackState playbackState = builder.build();
mediaSession.setPlaybackState(playbackState);
- previousState = playbackState;
}
@Override
@@ -188,8 +192,22 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
PlaybackState.ACTION_PAUSE |
PlaybackState.ACTION_SEEK_TO |
PlaybackState.ACTION_SKIP_TO_NEXT |
- PlaybackState.ACTION_SKIP_TO_PREVIOUS |
- PlaybackState.ACTION_SET_RATING;
+ PlaybackState.ACTION_SKIP_TO_PREVIOUS;
+ }
+ protected void addCustomActions(MusicDirectory.Entry currentSong, PlaybackState.Builder builder) {
+ PlaybackState.CustomAction thumbsUp = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_THUMBS_UP,
+ downloadService.getString(R.string.download_thumbs_up),
+ R.drawable.ic_action_rating_good_selected).build();
+
+ PlaybackState.CustomAction thumbsDown = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_THUMBS_DOWN,
+ downloadService.getString(R.string.download_thumbs_down),
+ R.drawable.ic_action_rating_bad_selected).build();
+
+ PlaybackState.CustomAction star = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_STAR,
+ downloadService.getString(R.string.common_star),
+ R.drawable.ic_toggle_star).build();
+
+ builder.addCustomAction(star).addCustomAction(thumbsDown).addCustomAction(thumbsUp);
}
private class EventCallback extends MediaSession.Callback {
@@ -223,19 +241,13 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
}
@Override
- public void onSetRating(Rating rating) {
- if(rating.getRatingStyle() != Rating.RATING_THUMB_UP_DOWN) {
- return;
- }
-
- if(rating.isRated()) {
- if(rating.isThumbUp()) {
-
- } else {
-
- }
- } else {
-
+ public void onCustomAction(String action, Bundle extras) {
+ if(CUSTOM_ACTION_THUMBS_UP.equals(action)) {
+ downloadService.toggleRating(5);
+ } else if(CUSTOM_ACTION_THUMBS_DOWN.equals(action)) {
+ downloadService.toggleRating(1);
+ } else if(CUSTOM_ACTION_STAR.equals(action)) {
+ downloadService.toggleStarred();
}
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7c682930..6d000734 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -223,6 +223,8 @@
\nEstimated Size: %2$s</string>
<string name="download.failed_to_load">Failed to load</string>
<string name="download.restore_play_queue">continue from where you left off on another device at</string>
+ <string name="download.thumbs_up">Thumbs Up</string>
+ <string name="download.thumbs_down">Thumbs Down</string>
<string name="sync.new_podcasts">New podcasts available</string>
<string name="sync.new_playlists">New songs in playlists</string>