diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/PlaylistAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/PlaylistAdapter.java index ecb9e1b8..868f4448 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/PlaylistAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/PlaylistAdapter.java @@ -22,6 +22,7 @@ import com.kabouzeid.gramophone.helper.menu.PlaylistMenuHelper; import com.kabouzeid.gramophone.helper.menu.SongsMenuHelper; import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.loader.PlaylistSongLoader; +import com.kabouzeid.gramophone.model.AbsCustomPlaylist; import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist; @@ -157,8 +158,8 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter getSongList(@NonNull List playlists) { final ArrayList songs = new ArrayList<>(); for (Playlist playlist : playlists) { - if (playlist instanceof AbsSmartPlaylist) { - songs.addAll(((AbsSmartPlaylist) playlist).getSongs(activity)); + if (playlist instanceof AbsCustomPlaylist) { + songs.addAll(((AbsCustomPlaylist) playlist).getSongs(activity)); } else { songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id)); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/CustomPlaylistSongAdapter.java similarity index 83% rename from app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java rename to app/src/main/java/com/kabouzeid/gramophone/adapter/song/CustomPlaylistSongAdapter.java index 69715276..b6a325ca 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/CustomPlaylistSongAdapter.java @@ -18,11 +18,11 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid) */ -public class SmartPlaylistSongAdapter extends SongAdapter { +public class CustomPlaylistSongAdapter extends SongAdapter { - public static final String TAG = SmartPlaylistSongAdapter.class.getSimpleName(); + public static final String TAG = CustomPlaylistSongAdapter.class.getSimpleName(); - public SmartPlaylistSongAdapter(AppCompatActivity activity, @NonNull ArrayList dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) { + public CustomPlaylistSongAdapter(AppCompatActivity activity, @NonNull ArrayList dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) { super(activity, dataSet, itemLayoutRes, usePalette, cabHolder); overrideMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/AppShortcutLauncherActivity.java b/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/AppShortcutLauncherActivity.java index b6b72cc8..03bbdb79 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/AppShortcutLauncherActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/AppShortcutLauncherActivity.java @@ -3,21 +3,16 @@ package com.kabouzeid.gramophone.appshortcuts; import android.app.Activity; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.IntDef; import com.kabouzeid.gramophone.appshortcuts.shortcuttype.LastAddedShortcutType; import com.kabouzeid.gramophone.appshortcuts.shortcuttype.ShuffleAllShortcutType; import com.kabouzeid.gramophone.appshortcuts.shortcuttype.TopTracksShortcutType; -import com.kabouzeid.gramophone.loader.LastAddedLoader; -import com.kabouzeid.gramophone.loader.SongLoader; -import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader; -import com.kabouzeid.gramophone.model.Song; +import com.kabouzeid.gramophone.model.Playlist; +import com.kabouzeid.gramophone.model.smartplaylist.LastAddedPlaylist; +import com.kabouzeid.gramophone.model.smartplaylist.MyTopTracksPlaylist; +import com.kabouzeid.gramophone.model.smartplaylist.ShuffleAllPlaylist; import com.kabouzeid.gramophone.service.MusicService; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; - /** * @author Adrian Campos */ @@ -34,7 +29,6 @@ public class AppShortcutLauncherActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - @ShortcutType int shortcutType = SHORTCUT_TYPE_NONE; //Set shortcutType from the intent extras @@ -46,18 +40,18 @@ public class AppShortcutLauncherActivity extends Activity { switch (shortcutType) { case SHORTCUT_TYPE_SHUFFLE_ALL: - startServiceWithSongs(MusicService.SHUFFLE_MODE_SHUFFLE, - SongLoader.getAllSongs(getApplicationContext())); + startServiceWithPlaylist(MusicService.SHUFFLE_MODE_SHUFFLE, + new ShuffleAllPlaylist(getApplicationContext())); DynamicShortcutManager.reportShortcutUsed(this, ShuffleAllShortcutType.getId()); break; case SHORTCUT_TYPE_TOP_TRACKS: - startServiceWithSongs(MusicService.SHUFFLE_MODE_NONE, - TopAndRecentlyPlayedTracksLoader.getTopTracks(getApplicationContext())); + startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE, + new MyTopTracksPlaylist(getApplicationContext())); DynamicShortcutManager.reportShortcutUsed(this, TopTracksShortcutType.getId()); break; case SHORTCUT_TYPE_LAST_ADDED: - startServiceWithSongs(MusicService.SHUFFLE_MODE_NONE, - LastAddedLoader.getLastAddedSongs(getApplicationContext())); + startServiceWithPlaylist(MusicService.SHUFFLE_MODE_NONE, + new LastAddedPlaylist(getApplicationContext())); DynamicShortcutManager.reportShortcutUsed(this, LastAddedShortcutType.getId()); break; } @@ -65,21 +59,16 @@ public class AppShortcutLauncherActivity extends Activity { finish(); } - private void startServiceWithSongs(int shuffleMode, ArrayList songs) { + private void startServiceWithPlaylist(int shuffleMode, Playlist playlist) { Intent intent = new Intent(this, MusicService.class); - intent.setAction(MusicService.ACTION_PLAY); + intent.setAction(MusicService.ACTION_PLAY_PLAYLIST); Bundle bundle = new Bundle(); - bundle.putParcelableArrayList(MusicService.INTENT_EXTRA_SONGS, songs); + bundle.putParcelable(MusicService.INTENT_EXTRA_PLAYLIST, playlist); bundle.putInt(MusicService.INTENT_EXTRA_SHUFFLE_MODE, shuffleMode); intent.putExtras(bundle); startService(intent); } - - @Retention(RetentionPolicy.SOURCE) - @IntDef({SHORTCUT_TYPE_SHUFFLE_ALL, SHORTCUT_TYPE_TOP_TRACKS, SHORTCUT_TYPE_LAST_ADDED, SHORTCUT_TYPE_NONE}) - public @interface ShortcutType { - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/shortcuttype/BaseShortcutType.java b/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/shortcuttype/BaseShortcutType.java index ca44f21a..53733d9f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/shortcuttype/BaseShortcutType.java +++ b/app/src/main/java/com/kabouzeid/gramophone/appshortcuts/shortcuttype/BaseShortcutType.java @@ -26,7 +26,7 @@ public abstract class BaseShortcutType { abstract ShortcutInfo getShortcutInfo(); - static public String getId(){ + static public String getId() { return ID_PREFIX + "invalid"; } @@ -37,7 +37,7 @@ public abstract class BaseShortcutType { * @param shortcutType Describes the type of shortcut to create (ShuffleAll, TopTracks, custom playlist, etc.) * @return */ - Intent getPlaySongsIntent(@AppShortcutLauncherActivity.ShortcutType int shortcutType) { + Intent getPlaySongsIntent(int shortcutType) { Intent intent = new Intent(context, AppShortcutLauncherActivity.class); intent.setAction(Intent.ACTION_VIEW); diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java index 6e37b020..7ef920ea 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java @@ -14,9 +14,9 @@ import com.kabouzeid.gramophone.dialogs.DeletePlaylistDialog; import com.kabouzeid.gramophone.dialogs.RenamePlaylistDialog; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.loader.PlaylistSongLoader; +import com.kabouzeid.gramophone.model.AbsCustomPlaylist; import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Song; -import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist; import com.kabouzeid.gramophone.util.PlaylistsUtil; import java.io.IOException; @@ -77,8 +77,8 @@ public class PlaylistMenuHelper { @NonNull private static ArrayList getPlaylistSongs(@NonNull Activity activity, Playlist playlist) { - return playlist instanceof AbsSmartPlaylist ? - ((AbsSmartPlaylist) playlist).getSongs(activity) : + return playlist instanceof AbsCustomPlaylist ? + ((AbsCustomPlaylist) playlist).getSongs(activity) : PlaylistSongLoader.getPlaylistSongList(activity, playlist.id); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/AbsCustomPlaylist.java b/app/src/main/java/com/kabouzeid/gramophone/model/AbsCustomPlaylist.java new file mode 100644 index 00000000..ccc3af4a --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/model/AbsCustomPlaylist.java @@ -0,0 +1,27 @@ +package com.kabouzeid.gramophone.model; + +import android.content.Context; +import android.os.Parcel; +import android.support.annotation.NonNull; + +import java.util.ArrayList; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ + +public abstract class AbsCustomPlaylist extends Playlist { + public AbsCustomPlaylist(int id, String name) { + super(id, name); + } + + public AbsCustomPlaylist() { + } + + public AbsCustomPlaylist(Parcel in) { + super(in); + } + + @NonNull + public abstract ArrayList getSongs(Context context); +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/AbsSmartPlaylist.java b/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/AbsSmartPlaylist.java index 8a89f8c3..d21e39b3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/AbsSmartPlaylist.java +++ b/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/AbsSmartPlaylist.java @@ -6,15 +6,12 @@ import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.model.Playlist; -import com.kabouzeid.gramophone.model.Song; - -import java.util.ArrayList; +import com.kabouzeid.gramophone.model.AbsCustomPlaylist; /** * @author Karim Abou Zeid (kabouzeid) */ -public abstract class AbsSmartPlaylist extends Playlist { +public abstract class AbsSmartPlaylist extends AbsCustomPlaylist { @DrawableRes public final int iconRes; @@ -28,8 +25,6 @@ public abstract class AbsSmartPlaylist extends Playlist { this.iconRes = R.drawable.ic_queue_music_white_24dp; } - public abstract ArrayList getSongs(Context context); - public abstract void clear(Context context); @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/ShuffleAllPlaylist.java b/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/ShuffleAllPlaylist.java new file mode 100644 index 00000000..bf8c818d --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/model/smartplaylist/ShuffleAllPlaylist.java @@ -0,0 +1,53 @@ +package com.kabouzeid.gramophone.model.smartplaylist; + +import android.content.Context; +import android.os.Parcel; +import android.support.annotation.NonNull; + +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.loader.SongLoader; +import com.kabouzeid.gramophone.model.Song; + +import java.util.ArrayList; + +public class ShuffleAllPlaylist extends AbsSmartPlaylist { + + public ShuffleAllPlaylist(@NonNull Context context) { + super(context.getString(R.string.action_shuffle_all), R.drawable.ic_shuffle_white_24dp); + } + + @NonNull + @Override + public ArrayList getSongs(@NonNull Context context) { + return SongLoader.getAllSongs(context); + } + + @Override + public void clear(@NonNull Context context) { + // Shuffle all is not a real "Smart Playlist" + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + } + + protected ShuffleAllPlaylist(Parcel in) { + super(in); + } + + public static final Creator CREATOR = new Creator() { + public ShuffleAllPlaylist createFromParcel(Parcel source) { + return new ShuffleAllPlaylist(source); + } + + public ShuffleAllPlaylist[] newArray(int size) { + return new ShuffleAllPlaylist[size]; + } + }; +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java index a5bd9076..1b8a5e1f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java @@ -46,6 +46,9 @@ import com.kabouzeid.gramophone.glide.BlurTransformation; import com.kabouzeid.gramophone.glide.SongGlideRequest; import com.kabouzeid.gramophone.helper.ShuffleHelper; import com.kabouzeid.gramophone.helper.StopWatch; +import com.kabouzeid.gramophone.loader.PlaylistSongLoader; +import com.kabouzeid.gramophone.model.AbsCustomPlaylist; +import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.provider.HistoryStore; import com.kabouzeid.gramophone.provider.MusicPlaybackQueueStore; @@ -74,12 +77,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP public static final String ACTION_TOGGLE_PAUSE = PHONOGRAPH_PACKAGE_NAME + ".togglepause"; public static final String ACTION_PLAY = PHONOGRAPH_PACKAGE_NAME + ".play"; + public static final String ACTION_PLAY_PLAYLIST = PHONOGRAPH_PACKAGE_NAME + ".play.playlist"; public static final String ACTION_PAUSE = PHONOGRAPH_PACKAGE_NAME + ".pause"; public static final String ACTION_STOP = PHONOGRAPH_PACKAGE_NAME + ".stop"; public static final String ACTION_SKIP = PHONOGRAPH_PACKAGE_NAME + ".skip"; public static final String ACTION_REWIND = PHONOGRAPH_PACKAGE_NAME + ".rewind"; public static final String ACTION_QUIT = PHONOGRAPH_PACKAGE_NAME + ".quitservice"; - public static final String INTENT_EXTRA_SONGS = PHONOGRAPH_PACKAGE_NAME + ".intentextra.songs"; + public static final String INTENT_EXTRA_PLAYLIST = PHONOGRAPH_PACKAGE_NAME + "intentextra.playlist"; public static final String INTENT_EXTRA_SHUFFLE_MODE = PHONOGRAPH_PACKAGE_NAME + ".intentextra.shufflemode"; public static final String APP_WIDGET_UPDATE = PHONOGRAPH_PACKAGE_NAME + ".appwidgetupdate"; @@ -297,22 +301,37 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP pause(); break; case ACTION_PLAY: - ArrayList songs = intent.getParcelableArrayListExtra(INTENT_EXTRA_SONGS); - if (songs != null) { - int shuffleMode = intent.getIntExtra(INTENT_EXTRA_SHUFFLE_MODE, getShuffleMode()); - if (intent.hasExtra(INTENT_EXTRA_SHUFFLE_MODE) && intent.getIntExtra(INTENT_EXTRA_SHUFFLE_MODE, 0) == SHUFFLE_MODE_SHUFFLE) { - int startPosition = 0; - if (!songs.isEmpty()) { - startPosition = new Random().nextInt(songs.size()); - } - openQueue(songs, startPosition, false); - setShuffleMode(shuffleMode); - } else { - openQueue(songs, 0, false); - } - } play(); break; + case ACTION_PLAY_PLAYLIST: + Playlist playlist = intent.getParcelableExtra(INTENT_EXTRA_PLAYLIST); + int shuffleMode = intent.getIntExtra(INTENT_EXTRA_SHUFFLE_MODE, getShuffleMode()); + if (playlist != null) { + ArrayList playlistSongs; + if (playlist instanceof AbsCustomPlaylist) { + playlistSongs = ((AbsCustomPlaylist) playlist).getSongs(getApplicationContext()); + } else { + //noinspection unchecked + playlistSongs = (ArrayList) (List) PlaylistSongLoader.getPlaylistSongList(getApplicationContext(), playlist.id); + } + if (!playlistSongs.isEmpty()) { + if (shuffleMode == SHUFFLE_MODE_SHUFFLE) { + int startPosition = 0; + if (!playlistSongs.isEmpty()) { + startPosition = new Random().nextInt(playlistSongs.size()); + } + openQueue(playlistSongs, startPosition, true); + setShuffleMode(shuffleMode); + } else { + openQueue(playlistSongs, 0, true); + } + } else { + Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show(); + } + } else { + Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show(); + } + break; case ACTION_REWIND: back(true); break; @@ -858,6 +877,24 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP } } + public void playSongs(ArrayList songs, int shuffleMode) { + if (songs != null && !songs.isEmpty()) { + if (shuffleMode == SHUFFLE_MODE_SHUFFLE) { + int startPosition = 0; + if (!songs.isEmpty()) { + startPosition = new Random().nextInt(songs.size()); + } + openQueue(songs, startPosition, false); + setShuffleMode(shuffleMode); + } else { + openQueue(songs, 0, false); + } + play(); + } else { + Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show(); + } + } + public void playPreviousSong(boolean force) { playSongAt(getPreviousPosition(force)); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java index ad403225..21d6ca3d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java @@ -20,8 +20,8 @@ import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropM import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; import com.kabouzeid.appthemehelper.ThemeStore; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.adapter.song.CustomPlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.PlaylistSongAdapter; -import com.kabouzeid.gramophone.adapter.song.SmartPlaylistSongAdapter; import com.kabouzeid.gramophone.adapter.song.SongAdapter; import com.kabouzeid.gramophone.dialogs.SleepTimerDialog; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; @@ -29,10 +29,10 @@ import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.LoaderIds; import com.kabouzeid.gramophone.loader.PlaylistSongLoader; import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader; +import com.kabouzeid.gramophone.model.AbsCustomPlaylist; import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.PlaylistSong; import com.kabouzeid.gramophone.model.Song; -import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.util.PhonographColorUtil; @@ -94,8 +94,8 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme private void setUpRecyclerView() { recyclerView.setLayoutManager(new LinearLayoutManager(this)); - if (playlist instanceof AbsSmartPlaylist) { - adapter = new SmartPlaylistSongAdapter(this, new ArrayList(), R.layout.item_list, false, this); + if (playlist instanceof AbsCustomPlaylist) { + adapter = new CustomPlaylistSongAdapter(this, new ArrayList(), R.layout.item_list, false, this); recyclerView.setAdapter(adapter); } else { recyclerViewDragDropManager = new RecyclerViewDragDropManager(); @@ -251,8 +251,8 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme @Override public ArrayList loadInBackground() { - if (playlist instanceof AbsSmartPlaylist) { - return ((AbsSmartPlaylist) playlist).getSongs(getContext()); + if (playlist instanceof AbsCustomPlaylist) { + return ((AbsCustomPlaylist) playlist).getSongs(getContext()); } else { //noinspection unchecked return (ArrayList) (List) PlaylistSongLoader.getPlaylistSongList(getContext(), playlist.id); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6eef7d46..74a2614c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -288,4 +288,6 @@ @string/last_added @string/last_added + + Playlist is empty