change protocol for episode transition on PlaybackService
This commit is contained in:
parent
8e281890dd
commit
e94219ce26
|
@ -20,6 +20,7 @@ import de.danoeh.antennapod.core.feed.Feed;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||||
|
import de.danoeh.antennapod.core.feed.MediaType;
|
||||||
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
|
import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
|
||||||
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
|
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
|
||||||
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
|
||||||
|
@ -196,10 +197,19 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
|
||||||
|
@ -275,8 +285,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -357,8 +377,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -440,8 +470,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -517,8 +557,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -595,8 +645,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -675,8 +735,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -758,8 +828,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -814,8 +894,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -896,8 +986,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -1012,8 +1112,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -1103,8 +1213,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
@ -1207,8 +1327,18 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
|
||||||
|
|
|
@ -143,7 +143,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
|
||||||
setPlayerStatus(PlayerStatus.PAUSED, media);
|
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);
|
setPlayerStatus(PlayerStatus.INDETERMINATE, null);
|
||||||
}
|
}
|
||||||
|
@ -762,13 +765,47 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
|
||||||
if (playerStatus != PlayerStatus.INDETERMINATE) {
|
if (playerStatus != PlayerStatus.INDETERMINATE) {
|
||||||
setPlayerStatus(PlayerStatus.INDETERMINATE, media);
|
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) {
|
if (mediaPlayer != null) {
|
||||||
mediaPlayer.reset();
|
mediaPlayer.reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
audioManager.abandonAudioFocus(audioFocusChangeListener);
|
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();
|
playerLock.unlock();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -700,121 +700,138 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean endPlayback(Playable media, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
public void onPostPlayback(Playable media, boolean ended, boolean playingNext) {
|
||||||
PlaybackService.this.endPlayback(media, playNextEpisode, wasSkipped, switchingPlayers);
|
PlaybackService.this.onPostPlayback(media, ended, playingNext);
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Playable getNextInQueue(Playable currentMedia) {
|
||||||
|
return PlaybackService.this.getNextInQueue(currentMedia);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlaybackEnded(MediaType mediaType, boolean stopPlaying) {
|
||||||
|
PlaybackService.this.onPlaybackEnded(mediaType, stopPlaying);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private void endPlayback(final Playable playable, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
|
private Playable getNextInQueue(final Playable currentMedia) {
|
||||||
Log.d(TAG, "Playback ended" + (switchingPlayers ? " from switching players": ""));
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
if (playable == null) {
|
||||||
Log.e(TAG, "Cannot end playback: media was null");
|
Log.e(TAG, "Cannot do post-playback processing: media was null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Log.d(TAG, "onPostPlayback(): media=" + playable.getEpisodeTitle());
|
||||||
|
|
||||||
taskManager.cancelPositionSaver();
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
boolean isInQueue = false;
|
// auto-flattr if enabled
|
||||||
FeedItem nextItem = null;
|
if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
|
||||||
|
DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
|
||||||
|
}
|
||||||
|
|
||||||
if (playable instanceof FeedMedia && ((FeedMedia) playable).getItem() != null) {
|
// gpodder play action
|
||||||
FeedMedia media = (FeedMedia) playable;
|
if (GpodnetPreferences.loggedIn()) {
|
||||||
FeedItem item = media.getItem();
|
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 (!switchingPlayers) {
|
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 {
|
try {
|
||||||
final List<FeedItem> queue = taskManager.getQueue();
|
final List<FeedItem> queue = taskManager.getQueue();
|
||||||
isInQueue = QueueAccess.ItemListAccess(queue).contains(item.getId());
|
if (QueueAccess.ItemListAccess(queue).contains(item.getId())) {
|
||||||
nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue);
|
// 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) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
// isInQueue remains false
|
// isInQueue remains false
|
||||||
}
|
}
|
||||||
|
// Delete episode if enabled
|
||||||
boolean shouldKeep = wasSkipped && UserPreferences.shouldSkipKeepEpisode();
|
if (item.getFeed().getPreferences().getCurrentAutoDelete()) {
|
||||||
|
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
|
||||||
if (!shouldKeep) {
|
Log.d(TAG, "Episode Deleted");
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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) {
|
if (ended || playingNext) {
|
||||||
// Load next episode if previous episode was in the queue and if there
|
DBWriter.addItemToPlaybackHistory(media);
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,7 @@ import android.util.Pair;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.feed.Chapter;
|
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.feed.MediaType;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
|
||||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,26 +288,6 @@ public abstract class PlaybackServiceMediaPlayer {
|
||||||
callback.statusChanged(new PSMPInfo(playerStatus, getPlayable()));
|
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 {
|
public interface PSMPCallback {
|
||||||
void statusChanged(PSMPInfo newInfo);
|
void statusChanged(PSMPInfo newInfo);
|
||||||
|
|
||||||
|
@ -328,7 +305,11 @@ public abstract class PlaybackServiceMediaPlayer {
|
||||||
|
|
||||||
boolean onMediaPlayerError(Object inObj, int what, int extra);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue