From fd98d70a113baf67d173714ae781bc0315e2f2f6 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 7 Nov 2018 08:39:05 -0800 Subject: [PATCH] Make TimelineQueueNavigator shuffle aware Issue: #5065 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=220468285 --- RELEASENOTES.md | 2 + .../mediasession/TimelineQueueNavigator.java | 51 +++++++++++-------- .../source/ClippingMediaSource.java | 2 +- .../exoplayer2/ui/PlayerControlView.java | 11 ++-- 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fef5e3ddb7..9eae825c61 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -29,6 +29,8 @@ * Fix issue with blind seeking to windows with non-zero offset in a `ConcatenatingMediaSource` ([#4873](https://github.com/google/ExoPlayer/issues/4873)). +* Fix logic for enabling next and previous actions in `TimelineQueueNavigator` + ([#5065](https://github.com/google/ExoPlayer/issues/5065)). * Fix issue where audio focus handling could not be disabled after enabling it ([#5055](https://github.com/google/ExoPlayer/issues/5055)). * Fix issue where subtitles were positioned incorrectly if `SubtitleView` had a diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java index 6671add7e5..d55f8e04f0 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/TimelineQueueNavigator.java @@ -39,6 +39,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu public static final int DEFAULT_MAX_QUEUE_SIZE = 10; private final MediaSessionCompat mediaSession; + private final Timeline.Window window; protected final int maxQueueSize; private long activeQueueItemId; @@ -68,6 +69,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu this.mediaSession = mediaSession; this.maxQueueSize = maxQueueSize; activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID; + window = new Timeline.Window(); } /** @@ -81,25 +83,24 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @Override public long getSupportedQueueNavigatorActions(Player player) { - if (player == null || player.getCurrentTimeline().getWindowCount() < 2) { + if (player == null) { return 0; } - if (player.getRepeatMode() != Player.REPEAT_MODE_OFF) { - return PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS - | PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM; + Timeline timeline = player.getCurrentTimeline(); + if (timeline.isEmpty() || player.isPlayingAd()) { + return 0; } - - int currentWindowIndex = player.getCurrentWindowIndex(); - long actions; - if (currentWindowIndex == 0) { - actions = PlaybackStateCompat.ACTION_SKIP_TO_NEXT; - } else if (currentWindowIndex == player.getCurrentTimeline().getWindowCount() - 1) { - actions = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; - } else { - actions = PlaybackStateCompat.ACTION_SKIP_TO_NEXT - | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; + long actions = 0; + if (timeline.getWindowCount() > 1) { + actions |= PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM; } - return actions | PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM; + if (window.isSeekable || !window.isDynamic || player.hasPrevious()) { + actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; + } + if (window.isDynamic || player.hasNext()) { + actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT; + } + return actions; } @Override @@ -125,22 +126,25 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @Override public void onSkipToPrevious(Player player) { Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty()) { + if (timeline.isEmpty() || player.isPlayingAd()) { return; } + int windowIndex = player.getCurrentWindowIndex(); + timeline.getWindow(windowIndex, window); int previousWindowIndex = player.getPreviousWindowIndex(); - if (player.getCurrentPosition() > MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || previousWindowIndex == C.INDEX_UNSET) { - player.seekTo(0); - } else { + if (previousWindowIndex != C.INDEX_UNSET + && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS + || (window.isDynamic && !window.isSeekable))) { player.seekTo(previousWindowIndex, C.TIME_UNSET); + } else { + player.seekTo(0); } } @Override public void onSkipToQueueItem(Player player, long id) { Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty()) { + if (timeline.isEmpty() || player.isPlayingAd()) { return; } int windowIndex = (int) id; @@ -152,12 +156,15 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu @Override public void onSkipToNext(Player player) { Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty()) { + if (timeline.isEmpty() || player.isPlayingAd()) { return; } + int windowIndex = player.getCurrentWindowIndex(); int nextWindowIndex = player.getNextWindowIndex(); if (nextWindowIndex != C.INDEX_UNSET) { player.seekTo(nextWindowIndex, C.TIME_UNSET); + } else if (timeline.getWindow(windowIndex, window).isDynamic) { + player.seekTo(windowIndex, C.TIME_UNSET); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java index 5f80725805..78e37c1869 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java @@ -348,7 +348,7 @@ public final class ClippingMediaSource extends CompositeMediaSource { if (timeline.getPeriodCount() != 1) { throw new IllegalClippingException(IllegalClippingException.REASON_INVALID_PERIOD_COUNT); } - Window window = timeline.getWindow(0, new Window(), false); + Window window = timeline.getWindow(0, new Window()); startUs = Math.max(0, startUs); long resolvedEndUs = endUs == C.TIME_END_OF_SOURCE ? window.durationUs : Math.max(0, endUs); if (window.durationUs != C.TIME_UNSET) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index f0e824afed..8ab4210465 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -634,9 +634,8 @@ public class PlayerControlView extends FrameLayout { int windowIndex = player.getCurrentWindowIndex(); timeline.getWindow(windowIndex, window); isSeekable = window.isSeekable; - enablePrevious = - isSeekable || !window.isDynamic || player.getPreviousWindowIndex() != C.INDEX_UNSET; - enableNext = window.isDynamic || player.getNextWindowIndex() != C.INDEX_UNSET; + enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); + enableNext = window.isDynamic || player.hasNext(); } setButtonEnabled(enablePrevious, previousButton); setButtonEnabled(enableNext, nextButton); @@ -831,7 +830,7 @@ public class PlayerControlView extends FrameLayout { private void previous() { Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty()) { + if (timeline.isEmpty() || player.isPlayingAd()) { return; } int windowIndex = player.getCurrentWindowIndex(); @@ -848,14 +847,14 @@ public class PlayerControlView extends FrameLayout { private void next() { Timeline timeline = player.getCurrentTimeline(); - if (timeline.isEmpty()) { + if (timeline.isEmpty() || player.isPlayingAd()) { return; } int windowIndex = player.getCurrentWindowIndex(); int nextWindowIndex = player.getNextWindowIndex(); if (nextWindowIndex != C.INDEX_UNSET) { seekTo(nextWindowIndex, C.TIME_UNSET); - } else if (timeline.getWindow(windowIndex, window, false).isDynamic) { + } else if (timeline.getWindow(windowIndex, window).isDynamic) { seekTo(windowIndex, C.TIME_UNSET); } }