From c17723816b9fd69bf3c541b177e48d195a69b28f Mon Sep 17 00:00:00 2001 From: Domingos Lopes Date: Fri, 13 May 2016 01:33:05 -0400 Subject: adapt media player switch into the new protocol --- .../core/service/playback/LocalPSMP.java | 69 +++++++++++++--------- .../core/service/playback/PlaybackService.java | 7 ++- .../playback/PlaybackServiceMediaPlayer.java | 41 ++++++++++--- 3 files changed, 80 insertions(+), 37 deletions(-) (limited to 'core/src/main/java/de/danoeh') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 2567cd6f5..0871758d0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -13,6 +13,7 @@ import org.antennapod.audio.MediaPlayer; import java.io.IOException; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -754,8 +755,8 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { @Override - protected void endPlayback(final boolean wasSkipped) { - executor.submit(() -> { + protected Future endPlayback(final boolean wasSkipped, final boolean shouldContinue, final boolean toStoppedState) { + return executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -776,35 +777,46 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { mediaPlayer.reset(); } audioManager.abandonAudioFocus(audioFocusChangeListener); - // Load next episode if previous episode was in the queue and if there - // is an episode in the queue left. - // Start playback immediately if continuous playback is enabled - final Playable currentMedia = media; - Playable nextMedia = callback.getNextInQueue(currentMedia); - boolean playNextEpisode = isPlaying && - nextMedia != null && - UserPreferences.isFollowQueue(); + final Playable currentMedia = media; + Playable nextMedia = null; + + if (shouldContinue) { + // Load next episode if previous episode was in the queue and if there + // is an episode in the queue left. + // Start playback immediately if continuous playback is enabled + nextMedia = callback.getNextInQueue(currentMedia); + + boolean playNextEpisode = isPlaying && + nextMedia != null && + UserPreferences.isFollowQueue(); + + if (playNextEpisode) { + Log.d(TAG, "Playback of next episode will start immediately."); + } else if (nextMedia == null){ + Log.d(TAG, "No more episodes available to play"); + } else { + Log.d(TAG, "Loading next episode, but not playing automatically."); + } - if (playNextEpisode) { - Log.d(TAG, "Playback of next episode will start immediately."); - } else if (nextMedia == null){ - Log.d(TAG, "No more episodes available to play"); - } else { - Log.d(TAG, "Loading next episode, but not playing automatically."); + if (nextMedia != null) { + callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode); + // setting media to null signals to playMediaObject() that we're taking care of post-playback processing + media = null; + playMediaObject(nextMedia, false, !nextMedia.localFileAvailable(), playNextEpisode, playNextEpisode); + } } + if (shouldContinue || toStoppedState) { + if (nextMedia == null) { + callback.onPlaybackEnded(null, true); + stop(); + } + final boolean hasNext = nextMedia != null; - if (nextMedia != null) { - callback.onPlaybackEnded(nextMedia.getMediaType(), !playNextEpisode); - // setting media to null signals to playMediaObject() that we're taking care of post-playback processing - media = null; - playMediaObject(nextMedia, false, !nextMedia.localFileAvailable(), playNextEpisode, playNextEpisode); - } else { - callback.onPlaybackEnded(null, true); - stop(); + executor.submit(() -> callback.onPostPlayback(currentMedia, !wasSkipped, hasNext)); + } else if (isPlaying) { + callback.onPlaybackPause(currentMedia, currentMedia.getPosition()); } - - executor.submit(() -> callback.onPostPlayback(currentMedia, !wasSkipped, nextMedia != null)); playerLock.unlock(); }); } @@ -815,8 +827,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { * This method will only take care of changing the PlayerStatus of this object! Other tasks like * abandoning audio focus have to be done with other methods. */ - @Override - public void stop() { + private void stop() { executor.submit(() -> { playerLock.lock(); releaseWifiLockIfNecessary(); @@ -869,7 +880,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { mp -> genericOnCompletion(); private void genericOnCompletion() { - endPlayback(false); + endPlayback(false, true, true); } private final MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 71d0abf07..04b5b676d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -786,6 +786,11 @@ public class PlaybackService extends MediaBrowserServiceCompat { if (!(playable instanceof FeedMedia)) { Log.d(TAG, "Not doing post-playback processing: media not of type FeedMedia"); + if (ended) { + playable.onPlaybackCompleted(getApplicationContext()); + } else { + playable.onPlaybackPause(getApplicationContext()); + } return; } FeedMedia media = (FeedMedia) playable; @@ -1587,7 +1592,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { @Override public void onStop() { Log.d(TAG, "onStop()"); - mediaPlayer.stop(); + mediaPlayer.stopPlayback(true); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 5940a463a..aec059ca0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -8,6 +8,8 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; +import java.util.concurrent.Future; + import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.util.playback.Playable; @@ -226,18 +228,43 @@ public abstract class PlaybackServiceMediaPlayer { protected abstract void setPlayable(Playable playable); public void skip() { - endPlayback(true); + endPlayback(true, true, true); } - protected abstract void endPlayback(boolean wasSkipped); + /** + * Ends playback of current media (if any) and moves into INDETERMINATE state, unless + * {@param toStoppedState} is set to true, in which case it moves into STOPPED state. + * + * @see #endPlayback(boolean, boolean, boolean) + */ + public Future stopPlayback(boolean toStoppedState) { + return endPlayback(true, false, toStoppedState); + } /** - * Moves the PSMP into STOPPED state. This call is only valid if the player is currently in - * INDETERMINATE state, for example after a call to endPlayback. - * This method will only take care of changing the PlayerStatus of this object! Other tasks like - * abandoning audio focus have to be done with other methods. + * Internal method that handles end of playback. + * + * Currently, it has 4 use cases: + * + * + * @param wasSkipped If true, we assume the current media's playback has ended, for + * purposes of post playback processing. + * @param shouldContinue If true, the media player should try to load, and possibly play, + * the next item, based on the user preferences and whether such item + * exists. + * @param toStoppedState If true, the playback state gets set to STOPPED if the media player + * is not loading/playing after this call, and the UI will reflect that. + * Only relevant if {@param shouldContinue} is set to false, otherwise + * this method's behavior defaults as if this parameter was true. + * + * @return a Future, just for the purpose of tracking its execution. */ - public abstract void stop(); + protected abstract Future endPlayback(boolean wasSkipped, boolean shouldContinue, boolean toStoppedState); /** * @return {@code true} if the WifiLock feature should be used, {@code false} otherwise. -- cgit v1.2.3