diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 43adc42112..29241b69e9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -6,6 +6,12 @@ * Add support for MP4 and QuickTime meta atoms that are not full atoms. * UI: * Add builder for `PlayerNotificationManager`. + * Make conditions to enable UI actions consistent in + `DefaultControlDispatcher`, `PlayerControlView`, + `StyledPlayerControlView`, `PlayerNotificationManager` and + `TimelineQueueNavigator` + * Fix conditions to enable seeking to next/previous media item to handle + the case where a live stream has ended. * Audio: * Fix `SimpleExoPlayer` reporting audio session ID as 0 in some cases ([#8585](https://github.com/google/ExoPlayer/issues/8585)). 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 203479a7ed..4c737268a2 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 @@ -98,8 +98,10 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu if (!timeline.isEmpty() && !player.isPlayingAd()) { timeline.getWindow(player.getCurrentWindowIndex(), window); enableSkipTo = timeline.getWindowCount() > 1; - enablePrevious = window.isSeekable || !window.isDynamic || player.hasPrevious(); - enableNext = window.isDynamic || player.hasNext(); + enablePrevious = window.isSeekable || !window.isLive() || player.hasPrevious(); + enableNext = + (window.isLive() && window.isDynamic) + || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } long actions = 0; diff --git a/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java b/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java index fe23f28db7..03f03d5903 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/DefaultControlDispatcher.java @@ -79,11 +79,12 @@ public class DefaultControlDispatcher implements ControlDispatcher { int windowIndex = player.getCurrentWindowIndex(); timeline.getWindow(windowIndex, window); int previousWindowIndex = player.getPreviousWindowIndex(); + boolean isUnseekableLiveStream = window.isLive() && !window.isSeekable; if (previousWindowIndex != C.INDEX_UNSET && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS - || (window.isDynamic && !window.isSeekable))) { + || isUnseekableLiveStream)) { player.seekTo(previousWindowIndex, C.TIME_UNSET); - } else { + } else if (!isUnseekableLiveStream) { player.seekTo(windowIndex, /* positionMs= */ 0); } return true; @@ -96,10 +97,11 @@ public class DefaultControlDispatcher implements ControlDispatcher { return true; } int windowIndex = player.getCurrentWindowIndex(); + timeline.getWindow(windowIndex, window); int nextWindowIndex = player.getNextWindowIndex(); if (nextWindowIndex != C.INDEX_UNSET) { player.seekTo(nextWindowIndex, C.TIME_UNSET); - } else if (timeline.getWindow(windowIndex, window).isLive()) { + } else if (window.isLive() && window.isDynamic) { player.seekTo(windowIndex, C.TIME_UNSET); } return true; 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 2759a61bb9..d7633f6c56 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 @@ -913,11 +913,12 @@ public class PlayerControlView extends FrameLayout { timeline.getWindow(player.getCurrentWindowIndex(), window); boolean isSeekable = window.isSeekable; enableSeeking = isSeekable; - enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); + enablePrevious = isSeekable || !window.isLive() || player.hasPrevious(); enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); enableNext = - window.isLive() || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + (window.isLive() && window.isDynamic) + || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java index a1183c8a3f..42933a66ea 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerNotificationManager.java @@ -1437,10 +1437,13 @@ public class PlayerNotificationManager { Timeline timeline = player.getCurrentTimeline(); if (!timeline.isEmpty() && !player.isPlayingAd()) { timeline.getWindow(player.getCurrentWindowIndex(), window); - enablePrevious = window.isSeekable || !window.isDynamic || player.hasPrevious(); - enableRewind = controlDispatcher.isRewindEnabled(); - enableFastForward = controlDispatcher.isFastForwardEnabled(); - enableNext = window.isDynamic || player.hasNext(); + boolean isSeekable = window.isSeekable; + enablePrevious = isSeekable || !window.isLive() || player.hasPrevious(); + enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); + enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); + enableNext = + (window.isLive() && window.isDynamic) + || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } List stringActions = new ArrayList<>(); diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java index 678d844038..252fcab0fb 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java @@ -1141,11 +1141,12 @@ public class StyledPlayerControlView extends FrameLayout { timeline.getWindow(player.getCurrentWindowIndex(), window); boolean isSeekable = window.isSeekable; enableSeeking = isSeekable; - enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); + enablePrevious = isSeekable || !window.isLive() || player.hasPrevious(); enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); enableNext = - window.isLive() || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + (window.isLive() && window.isDynamic) + || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } }