From 76db66656df5df9644f9b848fe1562d1b141eb85 Mon Sep 17 00:00:00 2001 From: Yannick Kurtovic Date: Tue, 16 Apr 2024 22:19:44 +0200 Subject: [PATCH] "Play next" for artists and albums --- .../IOdysseyPlaybackService.aidl | 4 +- .../fragments/AlbumTracksFragment.java | 2 +- .../odyssey/fragments/AlbumsFragment.java | 5 +- .../fragments/ArtistAlbumsFragment.java | 17 +++--- .../odyssey/fragments/ArtistsFragment.java | 10 ++-- .../fragments/GenericAlbumsFragment.java | 5 +- .../fragments/RecentAlbumsFragment.java | 8 ++- .../playbackservice/ControlObject.java | 15 ++++++ .../OdysseyPlaybackServiceInterface.java | 9 ++-- .../playbackservice/PlaybackService.java | 53 ++++++++++++++++--- .../PlaybackServiceHandler.java | 4 +- .../res/menu/context_menu_albums_fragment.xml | 8 +++ .../context_menu_artist_albums_fragment.xml | 5 ++ .../menu/context_menu_artists_fragment.xml | 5 +- 14 files changed, 120 insertions(+), 30 deletions(-) diff --git a/app/src/main/aidl/org/gateshipone/odyssey/playbackservice/IOdysseyPlaybackService.aidl b/app/src/main/aidl/org/gateshipone/odyssey/playbackservice/IOdysseyPlaybackService.aidl index 1c28d6f3..f207396b 100644 --- a/app/src/main/aidl/org/gateshipone/odyssey/playbackservice/IOdysseyPlaybackService.aidl +++ b/app/src/main/aidl/org/gateshipone/odyssey/playbackservice/IOdysseyPlaybackService.aidl @@ -47,14 +47,14 @@ interface IOdysseyPlaybackService { void playPlaylist(in PlaylistModel playlist, int position); // enqueue all tracks of an album from mediastore - void enqueueAlbum(long albumId, String orderKey); + void enqueueAlbum(long albumId, String orderKey, boolean asNext); void playAlbum(long albumId, String orderKey, int position); void enqueueRecentAlbums(); void playRecentAlbums(); // enqueue all tracks of an artist from mediastore - void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey); + void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey, boolean asNext); void playArtist(long artistId, String albumOrderKey, String trackOrderKey); /** diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumTracksFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumTracksFragment.java index df898a4d..9749bc6c 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumTracksFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumTracksFragment.java @@ -404,7 +404,7 @@ private void enqueueAlbum() { String trackOrderKey = sharedPref.getString(getString(R.string.pref_album_tracks_sort_order_key), getString(R.string.pref_album_tracks_sort_default)); try { - ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(mAlbum.getAlbumId(), trackOrderKey); + ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(mAlbum.getAlbumId(), trackOrderKey, false); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumsFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumsFragment.java index c4f70785..f344ea56 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumsFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/AlbumsFragment.java @@ -131,7 +131,10 @@ public boolean onContextItemSelected(@NonNull MenuItem item) { final int itemId = item.getItemId(); if (itemId == R.id.fragment_albums_action_enqueue) { - enqueueAlbum(info.position); + enqueueAlbum(info.position, false); + return true; + } else if (itemId == R.id.fragment_albums_action_enqueueasnext) { + enqueueAlbum(info.position, true); return true; } else if (itemId == R.id.fragment_albums_action_play) { playAlbum(info.position); diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistAlbumsFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistAlbumsFragment.java index 0ab9d130..240e4c1e 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistAlbumsFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistAlbumsFragment.java @@ -290,8 +290,9 @@ public void onItemClick(int position) { * Call the PBS to enqueue the selected album. * * @param position the position of the selected album in the adapter + * @param asNext */ - protected void enqueueAlbum(int position) { + protected void enqueueAlbum(int position, boolean asNext) { // identify current album AlbumModel clickedAlbum = mRecyclerAdapter.getItem(position); long albumId = clickedAlbum.getAlbumId(); @@ -302,7 +303,7 @@ protected void enqueueAlbum(int position) { // enqueue album try { - ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(albumId, trackOrderKey); + ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(albumId, trackOrderKey, asNext); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -359,11 +360,15 @@ public boolean onContextItemSelected(@NonNull MenuItem item) { } final int itemId = item.getItemId(); - if (itemId == R.id.fragment_artist_albums_action_enqueue) { - enqueueAlbum(info.position); + enqueueAlbum(info.position, false); + return true; + + } else if (itemId == R.id.fragment_artist_albums_action_enqueueasnext) { + enqueueAlbum(info.position, true); return true; - } else if (itemId == R.id.fragment_artist_albums_action_play) { + } + else if (itemId == R.id.fragment_artist_albums_action_play) { playAlbum(info.position); return true; } @@ -433,7 +438,7 @@ private void enqueueArtist() { // enqueue artist try { - ((GenericActivity) requireActivity()).getPlaybackService().enqueueArtist(mArtist.getArtistID(), albumOrderKey, trackOrderKey); + ((GenericActivity) requireActivity()).getPlaybackService().enqueueArtist(mArtist.getArtistID(), albumOrderKey, trackOrderKey, false); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistsFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistsFragment.java index a853c5f8..9d6134eb 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistsFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/ArtistsFragment.java @@ -224,7 +224,10 @@ public boolean onContextItemSelected(@NonNull MenuItem item) { final int itemId = item.getItemId(); if (itemId == R.id.fragment_artist_action_enqueue) { - enqueueArtist(info.position); + enqueueArtist(info.position, false); + return true; + } else if (itemId == R.id.fragment_artist_action_enqueueasnext) { + enqueueArtist(info.position, true); return true; } else if (itemId == R.id.fragment_artist_action_play) { playArtist(info.position); @@ -238,8 +241,9 @@ public boolean onContextItemSelected(@NonNull MenuItem item) { * Call the PBS to enqueue the selected artist * * @param position the position of the selected artist in the adapter + * @param asNext */ - private void enqueueArtist(int position) { + private void enqueueArtist(int position, boolean asNext) { // identify current artist ArtistModel currentArtist = mAdapter.getItem(position); @@ -259,7 +263,7 @@ private void enqueueArtist(int position) { // enqueue artist try { - ((GenericActivity) requireActivity()).getPlaybackService().enqueueArtist(artistId, albumOrderKey, trackOrderKey); + ((GenericActivity) requireActivity()).getPlaybackService().enqueueArtist(artistId, albumOrderKey, trackOrderKey, asNext); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/GenericAlbumsFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/GenericAlbumsFragment.java index c9b49067..19d5958b 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/GenericAlbumsFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/GenericAlbumsFragment.java @@ -174,8 +174,9 @@ public void onItemClick(AdapterView parent, View view, int position, long id) * Call the PBS to enqueue the selected album. * * @param position the position of the selected album in the adapter + * @param asNext */ - protected void enqueueAlbum(int position) { + protected void enqueueAlbum(int position, boolean asNext) { // identify current album AlbumModel clickedAlbum = mAdapter.getItem(position); long albumId = clickedAlbum.getAlbumId(); @@ -186,7 +187,7 @@ protected void enqueueAlbum(int position) { // enqueue album try { - ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(albumId, trackOrderKey); + ((GenericActivity) requireActivity()).getPlaybackService().enqueueAlbum(albumId, trackOrderKey, asNext); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/app/src/main/java/org/gateshipone/odyssey/fragments/RecentAlbumsFragment.java b/app/src/main/java/org/gateshipone/odyssey/fragments/RecentAlbumsFragment.java index 5364ef7b..20ab9def 100644 --- a/app/src/main/java/org/gateshipone/odyssey/fragments/RecentAlbumsFragment.java +++ b/app/src/main/java/org/gateshipone/odyssey/fragments/RecentAlbumsFragment.java @@ -144,9 +144,13 @@ public boolean onContextItemSelected(@NonNull MenuItem item) { final int itemId = item.getItemId(); if (itemId == R.id.fragment_albums_action_enqueue) { - enqueueAlbum(info.position); + enqueueAlbum(info.position, false); return true; - } else if (itemId == R.id.fragment_albums_action_play) { + } else if (itemId == R.id.fragment_albums_action_enqueueasnext) { + enqueueAlbum(info.position, true); + return true; + } + else if (itemId == R.id.fragment_albums_action_play) { playAlbum(info.position); return true; } else if (itemId == R.id.fragment_albums_action_showartist) { diff --git a/app/src/main/java/org/gateshipone/odyssey/playbackservice/ControlObject.java b/app/src/main/java/org/gateshipone/odyssey/playbackservice/ControlObject.java index 48fab071..b35904de 100644 --- a/app/src/main/java/org/gateshipone/odyssey/playbackservice/ControlObject.java +++ b/app/src/main/java/org/gateshipone/odyssey/playbackservice/ControlObject.java @@ -84,6 +84,13 @@ public ControlObject(PLAYBACK_ACTION action, long longParam, String param) { mAction = action; } + public ControlObject(PLAYBACK_ACTION action, long longParam, String param, boolean asNext) { + mLongParam = longParam; + mStringparam = param; + mBoolparam = asNext; + mAction = action; + } + public ControlObject(PLAYBACK_ACTION action, long longParam, String param, int intParam) { mLongParam = longParam; mStringparam = param; @@ -128,6 +135,14 @@ public ControlObject(PLAYBACK_ACTION action, long longParam, String stringParam, mSecondStringParam = stringParam2; } + public ControlObject(PLAYBACK_ACTION action, long longParam, String stringParam, String stringParam2, boolean boolParam) { + mAction = action; + mLongParam = longParam; + mStringparam = stringParam; + mSecondStringParam = stringParam2; + mBoolparam = boolParam; + } + public ControlObject(PLAYBACK_ACTION action, String stringParam, int intParam) { mAction = action; mStringparam = stringParam; diff --git a/app/src/main/java/org/gateshipone/odyssey/playbackservice/OdysseyPlaybackServiceInterface.java b/app/src/main/java/org/gateshipone/odyssey/playbackservice/OdysseyPlaybackServiceInterface.java index 99ed0617..9d9fd4b7 100644 --- a/app/src/main/java/org/gateshipone/odyssey/playbackservice/OdysseyPlaybackServiceInterface.java +++ b/app/src/main/java/org/gateshipone/odyssey/playbackservice/OdysseyPlaybackServiceInterface.java @@ -274,9 +274,10 @@ public void playPlaylist(PlaylistModel playlist, int position) throws RemoteExce mService.get().getHandler().sendMessage(msg); } + @Override - public void enqueueAlbum(long albumId, String orderKey) { - ControlObject obj = new ControlObject(ControlObject.PLAYBACK_ACTION.ODYSSEY_ENQUEUEALBUM, albumId, orderKey); + public void enqueueAlbum(long albumId, String orderKey, boolean asNext) { + ControlObject obj = new ControlObject(ControlObject .PLAYBACK_ACTION.ODYSSEY_ENQUEUEALBUM, albumId, orderKey, asNext); Message msg = mService.get().getHandler().obtainMessage(); msg.obj = obj; mService.get().getHandler().sendMessage(msg); @@ -307,8 +308,8 @@ public void playRecentAlbums() { } @Override - public void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey) { - ControlObject obj = new ControlObject(ControlObject.PLAYBACK_ACTION.ODYSSEY_ENQUEUEARTIST, artistId, albumOrderKey, trackOrderKey); + public void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey, boolean asNext) { + ControlObject obj = new ControlObject(ControlObject.PLAYBACK_ACTION.ODYSSEY_ENQUEUEARTIST, artistId, albumOrderKey, trackOrderKey, asNext); Message msg = mService.get().getHandler().obtainMessage(); msg.obj = obj; mService.get().getHandler().sendMessage(msg); diff --git a/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackService.java b/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackService.java index 79c1e52f..b942b672 100644 --- a/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackService.java +++ b/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackService.java @@ -968,8 +968,9 @@ public void enqueueTracks(List tracklist) { * * @param albumId The id of the album * @param orderKey String to specify the order of the tracks + * @param asNext flag if the tracks should be enqueued as next */ - public void enqueueAlbum(long albumId, String orderKey) { + public void enqueueAlbum(long albumId, String orderKey, boolean asNext) { mPlaybackServiceStatusHelper.broadcastPlaybackServiceState(PLAYBACKSERVICESTATE.WORKING); mBusy = true; @@ -977,12 +978,47 @@ public void enqueueAlbum(long albumId, String orderKey) { List tracks = MusicLibraryHelper.getTracksForAlbum(albumId, orderKey, getApplicationContext()); // add tracks to current playlist - enqueueTracks(tracks); + if(asNext){ + enqueueAsNextTracks(tracks); + }else{ + enqueueTracks(tracks); + } + + mPlaybackServiceStatusHelper.broadcastPlaybackServiceState(PLAYBACKSERVICESTATE.IDLE); mBusy = false; } + private void enqueueAsNextTracks(List tracklist) { + // Saved to check if we played the last song of the list + int oldSize = mCurrentList.size(); + + // Add the tracks to the actual list + if(mCurrentPlayingIndex >= 0){ + // Enqueue in list structure + mCurrentList.addAll(mCurrentPlayingIndex + 1, tracklist); + mNextPlayingIndex = mCurrentPlayingIndex + 1; + setNextTrackForMP(); + } else { + // If track is the first to be added, set playing index to 0 + mCurrentList.addAll(0, tracklist); + mCurrentPlayingIndex = 0; + } + + if (mCurrentPlayingIndex == oldSize - 1) { + // Next song for MP has to be set for gapless mediaplayback + mNextPlayingIndex = mCurrentPlayingIndex + 1; + setNextTrackForMP(); + } + + // Inform the helper that the state has changed + mPlaybackServiceStatusHelper.updateStatus(); + + // update trackRandomGenerator + updateTrackRandomGenerator(); + } + /** * Play all tracks of an album identified by the albumId. * A previous playlist will be cleared. @@ -994,7 +1030,7 @@ public void enqueueAlbum(long albumId, String orderKey) { public void playAlbum(long albumId, String orderKey, int position) { clearPlaylist(); - enqueueAlbum(albumId, orderKey); + enqueueAlbum(albumId, orderKey, false); jumpToIndex(position); } @@ -1032,8 +1068,9 @@ public void playRecentAlbums() { * @param artistId The id of the artist * @param albumOrderKey String to specify the order of the artist albums * @param trackOrderKey String to specify the order of the tracks + * @param asNext */ - public void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey) { + public void enqueueArtist(long artistId, String albumOrderKey, String trackOrderKey, boolean asNext) { mPlaybackServiceStatusHelper.broadcastPlaybackServiceState(PLAYBACKSERVICESTATE.WORKING); mBusy = true; @@ -1041,7 +1078,11 @@ public void enqueueArtist(long artistId, String albumOrderKey, String trackOrder List tracks = MusicLibraryHelper.getTracksForArtist(artistId, albumOrderKey, trackOrderKey, getApplicationContext()); // add tracks to current playlist - enqueueTracks(tracks); + if(asNext){ + enqueueAsNextTracks(tracks); + } else { + enqueueTracks(tracks); + } mPlaybackServiceStatusHelper.broadcastPlaybackServiceState(PLAYBACKSERVICESTATE.IDLE); mBusy = false; @@ -1058,7 +1099,7 @@ public void enqueueArtist(long artistId, String albumOrderKey, String trackOrder public void playArtist(long artistId, String albumOrderKey, String trackOrderKey) { clearPlaylist(); - enqueueArtist(artistId, albumOrderKey, trackOrderKey); + enqueueArtist(artistId, albumOrderKey, trackOrderKey, false); jumpToIndex(0); } diff --git a/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackServiceHandler.java b/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackServiceHandler.java index 43de5ec5..db8bb786 100644 --- a/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackServiceHandler.java +++ b/app/src/main/java/org/gateshipone/odyssey/playbackservice/PlaybackServiceHandler.java @@ -133,13 +133,13 @@ public void handleMessage(@Nullable Message msg) { mService.get().playDirectoryAndSubDirectories(msgObj.getStringParam(), msgObj.getSecondStringParam()); break; case ODYSSEY_ENQUEUEALBUM: - mService.get().enqueueAlbum(msgObj.getLongParam(), msgObj.getStringParam()); + mService.get().enqueueAlbum(msgObj.getLongParam(), msgObj.getStringParam(), msgObj.getBoolParam()); break; case ODYSSEY_PLAYALBUM: mService.get().playAlbum(msgObj.getLongParam(), msgObj.getStringParam(), msgObj.getIntParam()); break; case ODYSSEY_ENQUEUEARTIST: - mService.get().enqueueArtist(msgObj.getLongParam(), msgObj.getStringParam(), msgObj.getSecondStringParam()); + mService.get().enqueueArtist(msgObj.getLongParam(), msgObj.getStringParam(), msgObj.getSecondStringParam(),msgObj.getBoolParam()); break; case ODYSSEY_PLAYARTIST: mService.get().playArtist(msgObj.getLongParam(), msgObj.getStringParam(), msgObj.getSecondStringParam()); diff --git a/app/src/main/res/menu/context_menu_albums_fragment.xml b/app/src/main/res/menu/context_menu_albums_fragment.xml index 333303b6..74e44e97 100644 --- a/app/src/main/res/menu/context_menu_albums_fragment.xml +++ b/app/src/main/res/menu/context_menu_albums_fragment.xml @@ -27,11 +27,19 @@ android:title="@string/context_menu_action_enqueue" app:showAsAction="never" /> + + + + + + + - +