summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
authorDomingos Lopes <domingos86lopes+github@gmail.com>2016-04-30 01:50:35 -0400
committerDomingos Lopes <domingos86lopes+github@gmail.com>2016-07-25 23:16:28 -0400
commite94219ce26084fba304e7dc87fab074b74d8de1b (patch)
tree6745723511be262ca02c9c4c7117f1a4ff3f3367 /core/src/main
parent8e281890dd1a41cbb969e32c16d57f6ecff93953 (diff)
downloadAntennaPod-e94219ce26084fba304e7dc87fab074b74d8de1b.zip
change protocol for episode transition on PlaybackService
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java43
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java211
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java29
3 files changed, 159 insertions, 124 deletions
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 8bacac1ef..6fbc722b6 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
@@ -143,7 +143,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.PAUSED, media);
}
- smartMarkAsPlayed(media);
+ if (!media.getIdentifier().equals(playable.getIdentifier())) {
+ final Playable oldMedia = media;
+ executor.submit(() -> callback.onPostPlayback(oldMedia, false, true));
+ }
setPlayerStatus(PlayerStatus.INDETERMINATE, null);
}
@@ -762,13 +765,47 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
if (playerStatus != PlayerStatus.INDETERMINATE) {
setPlayerStatus(PlayerStatus.INDETERMINATE, media);
}
+ // we're relying on the position stored in the Playable object for post-playback processing
+ if (media != null) {
+ int position = getPosition();
+ if (position >= 0) {
+ media.setPosition(position);
+ }
+ }
+
if (mediaPlayer != null) {
mediaPlayer.reset();
-
}
audioManager.abandonAudioFocus(audioFocusChangeListener);
- callback.endPlayback(media, isPlaying, wasSkipped, switchingPlayers);
+ // 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();
+
+ 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);
+ } else {
+ callback.onPlaybackEnded(null, true);
+ stop();
+ }
+ executor.submit(() -> callback.onPostPlayback(currentMedia, !wasSkipped, nextMedia != null));
playerLock.unlock();
});
}
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 e3557f5f8..14fa28eed 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
@@ -700,121 +700,138 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
- public boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
- PlaybackService.this.endPlayback(media, playNextEpisode, wasSkipped, switchingPlayers);
- return true;
+ public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
+ PlaybackService.this.onPostPlayback(media, ended, playingNext);
}
- };
- private void endPlayback(final Playable playable, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
- Log.d(TAG, "Playback ended" + (switchingPlayers ? " from switching players": ""));
+ @Override
+ public Playable getNextInQueue(Playable currentMedia) {
+ return PlaybackService.this.getNextInQueue(currentMedia);
+ }
- if (playable == null) {
- Log.e(TAG, "Cannot end playback: media was null");
- return;
+ @Override
+ public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
+ PlaybackService.this.onPlaybackEnded(mediaType, stopPlaying);
}
+ };
- taskManager.cancelPositionSaver();
+ private Playable getNextInQueue(final Playable currentMedia) {
+ if (!(currentMedia instanceof FeedMedia)) {
+ Log.d(TAG, "getNextInQueue(), but playable not an instance of FeedMedia, so not proceeding");
+ return null;
+ }
+ if (!ClientConfig.playbackServiceCallbacks.useQueue()) {
+ Log.d(TAG, "getNextInQueue(), but queue not in use by this app");
+ return null;
+ }
+ Log.d(TAG, "getNextInQueue()");
+ FeedMedia media = (FeedMedia) currentMedia;
+ try {
+ media.loadMetadata();
+ } catch (Playable.PlayableException e) {
+ Log.e(TAG, "Unable to load metadata to get next in queue", e);
+ return null;
+ }
+ FeedItem item = media.getItem();
+ if (item == null) {
+ Log.w(TAG, "getNextInQueue() with FeedMedia object whose FeedItem is null");
+ return null;
+ }
+ FeedItem nextItem;
+ try {
+ final List<FeedItem> queue = taskManager.getQueue();
+ nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Error handling the queue in order to retrieve the next item", e);
+ return null;
+ }
+ return (nextItem != null)? nextItem.getMedia() : null;
- boolean isInQueue = false;
- FeedItem nextItem = null;
+ }
- if (playable instanceof FeedMedia && ((FeedMedia) playable).getItem() != null) {
- FeedMedia media = (FeedMedia) playable;
- FeedItem item = media.getItem();
+ /**
+ * Set of instructions to be performed when playback ends.
+ */
+ private void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
+ Log.d(TAG, "Playback ended");
+ if (stopPlaying) {
+ taskManager.cancelPositionSaver();
+ writePlaybackPreferencesNoMediaPlaying();
+ if (!isCasting) {
+ stopForeground(true);
+ }
+ stopWidgetUpdater();
+ }
+ if (mediaType == null) {
+ sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
+ } else {
+ sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
+ isCasting ? EXTRA_CODE_CAST :
+ (mediaType == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
+ }
+ }
+
+ //TODO add javadoc, that is is assumed that the playable object contains info about its position and duration
+ private void onPostPlayback(final Playable playable, boolean ended, boolean playingNext) {
+ if (playable == null) {
+ Log.e(TAG, "Cannot do post-playback processing: media was null");
+ return;
+ }
+ Log.d(TAG, "onPostPlayback(): media=" + playable.getEpisodeTitle());
- if (!switchingPlayers) {
+ if (!(playable instanceof FeedMedia)) {
+ Log.d(TAG, "Not doing post-playback processing: media not of type FeedMedia");
+ return;
+ }
+ FeedMedia media = (FeedMedia) playable;
+ FeedItem item = media.getItem();
+ boolean smartMarkAsPlayed = playingNext && media.hasAlmostEnded();
+ if (!ended && smartMarkAsPlayed) {
+ Log.d(TAG, "smart mark as played");
+ }
+
+ // auto-flattr if enabled
+ if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
+ DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
+ }
+
+ // gpodder play action
+ if (GpodnetPreferences.loggedIn()) {
+ GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.PLAY)
+ .currentDeviceId()
+ .currentTimestamp()
+ .started(startPosition / 1000)
+ .position(((ended || smartMarkAsPlayed) ? media.getDuration() : media.getPosition()) / 1000)
+ .total(media.getDuration() / 1000)
+ .build();
+ GpodnetPreferences.enqueueEpisodeAction(action);
+ }
+
+ if (item != null) {
+ if (ended || smartMarkAsPlayed ||
+ !UserPreferences.shouldSkipKeepEpisode()) {
+ // only mark the item as played if we're not keeping it anyways
+ DBWriter.markItemPlayed(item, FeedItem.PLAYED, ended);
try {
final List<FeedItem> queue = taskManager.getQueue();
- isInQueue = QueueAccess.ItemListAccess(queue).contains(item.getId());
- nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue);
+ if (QueueAccess.ItemListAccess(queue).contains(item.getId())) {
+ // don't know if it actually matters to not autodownload when smart mark as played is triggered
+ DBWriter.removeQueueItem(PlaybackService.this, item, ended);
+ }
} catch (InterruptedException e) {
e.printStackTrace();
// isInQueue remains false
}
-
- boolean shouldKeep = wasSkipped && UserPreferences.shouldSkipKeepEpisode();
-
- if (!shouldKeep) {
- // only mark the item as played if we're not keeping it anyways
- DBWriter.markItemPlayed(item, FeedItem.PLAYED, true);
-
- if (isInQueue) {
- DBWriter.removeQueueItem(PlaybackService.this, item, true);
- }
-
- // Delete episode if enabled
- if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
- DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
- Log.d(TAG, "Episode Deleted");
- }
+ // Delete episode if enabled
+ if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
+ Log.d(TAG, "Episode Deleted");
}
}
-
-
- DBWriter.addItemToPlaybackHistory(media);
-
- // auto-flattr if enabled
- if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
- DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
- }
-
- // gpodder play action
- if(GpodnetPreferences.loggedIn()) {
- GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, Action.PLAY)
- .currentDeviceId()
- .currentTimestamp()
- .started(startPosition / 1000)
- .position(getDuration() / 1000)
- .total(getDuration() / 1000)
- .build();
- GpodnetPreferences.enqueueEpisodeAction(action);
- }
}
- if (!switchingPlayers) {
- // 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
- Playable nextMedia = null;
- boolean loadNextItem = ClientConfig.playbackServiceCallbacks.useQueue() &&
- isInQueue &&
- nextItem != null;
-
- playNextEpisode = playNextEpisode &&
- loadNextItem &&
- UserPreferences.isFollowQueue();
-
- if (loadNextItem) {
- Log.d(TAG, "Loading next item in queue");
- nextMedia = nextItem.getMedia();
- }
- final boolean prepareImmediately;
- final boolean startWhenPrepared;
- final boolean stream;
-
- if (playNextEpisode) {
- Log.d(TAG, "Playback of next episode will start immediately.");
- prepareImmediately = startWhenPrepared = true;
- } else {
- Log.d(TAG, "No more episodes available to play");
- prepareImmediately = startWhenPrepared = false;
- stopForeground(true);
- stopWidgetUpdater();
- }
-
- writePlaybackPreferencesNoMediaPlaying();
- if (nextMedia != null) {
- stream = !nextMedia.localFileAvailable();
- mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately);
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD,
- isCasting ? EXTRA_CODE_CAST :
- (nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO);
- } else {
- sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
- mediaPlayer.stop();
- //stopSelf();
- }
+ if (ended || playingNext) {
+ DBWriter.addItemToPlaybackHistory(media);
}
}
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 e05733135..51742b27e 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
@@ -9,10 +9,7 @@ import android.util.Pair;
import android.view.SurfaceHolder;
import de.danoeh.antennapod.core.feed.Chapter;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
-import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.Playable;
@@ -291,26 +288,6 @@ public abstract class PlaybackServiceMediaPlayer {
callback.statusChanged(new PSMPInfo(playerStatus, getPlayable()));
}
- protected void smartMarkAsPlayed(Playable media) {
- if(media != null && media instanceof FeedMedia) {
- FeedMedia oldMedia = (FeedMedia) media;
- if(oldMedia.hasAlmostEnded()) {
- Log.d(TAG, "smart mark as read");
- FeedItem item = oldMedia.getItem();
- if (item == null) {
- return;
- }
- DBWriter.markItemPlayed(item, FeedItem.PLAYED, false);
- DBWriter.removeQueueItem(context, item, false);
- DBWriter.addItemToPlaybackHistory(oldMedia);
- if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
- Log.d(TAG, "Delete " + oldMedia.toString());
- DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId());
- }
- }
- }
- }
-
public interface PSMPCallback {
void statusChanged(PSMPInfo newInfo);
@@ -328,7 +305,11 @@ public abstract class PlaybackServiceMediaPlayer {
boolean onMediaPlayerError(Object inObj, int what, int extra);
- boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers);
+ void onPostPlayback(Playable media, boolean ended, boolean playingNext);
+
+ Playable getNextInQueue(Playable currentMedia);
+
+ void onPlaybackEnded(MediaType mediaType, boolean stopPlaying);
}
/**