diff --git a/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java b/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java index d99a320e32..e402fa7306 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/BasePlayer.java @@ -71,6 +71,14 @@ public abstract class BasePlayer implements Player { removeMediaItems(/* fromIndex= */ index, /* toIndex= */ index + 1); } + @Override + public boolean isCommandAvailable(@Command int command) { + if (command == COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) { + return hasNext(); + } + throw new IllegalArgumentException(); + } + @Override public final void play() { setPlayWhenReady(true); diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Player.java b/library/common/src/main/java/com/google/android/exoplayer2/Player.java index c12f72b89f..ad4875a5fe 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Player.java @@ -929,6 +929,17 @@ public interface Player { /** {@link #getPlaybackParameters()} changed. */ int EVENT_PLAYBACK_PARAMETERS_CHANGED = 13; + /** + * Commands that can be executed on a {@code Player}. One of {@link + * #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}) + @interface Command {} + /** Command to seek to the next {@link MediaItem} in the playlist. */ + int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 0; + /** Returns the component of this player for audio output, or null if audio is not supported. */ @Nullable AudioComponent getAudioComponent(); @@ -1100,6 +1111,19 @@ public interface Player { /** Clears the playlist. */ void clearMediaItems(); + /** + * Returns whether the provided {@link Command} is available. + * + *

This method does not execute the command. + * + *

Executing a command that is not available (for example, calling {@link #next()} if {@link + * #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} is unavailable) is a no-op. + * + * @param command A {@link Command}. + * @return Whether the {@link Command} is available. + */ + boolean isCommandAvailable(@Command int command); + /** Prepares the player. */ void prepare(); 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 57479ac960..2759a61bb9 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 @@ -916,7 +916,8 @@ public class PlayerControlView extends FrameLayout { enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); - enableNext = window.isLive() || player.hasNext(); + enableNext = + window.isLive() || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } } 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 0a0e2c4cc4..678d844038 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 @@ -1144,7 +1144,8 @@ public class StyledPlayerControlView extends FrameLayout { enablePrevious = isSeekable || !window.isDynamic || player.hasPrevious(); enableRewind = isSeekable && controlDispatcher.isRewindEnabled(); enableFastForward = isSeekable && controlDispatcher.isFastForwardEnabled(); - enableNext = window.isLive() || player.hasNext(); + enableNext = + window.isLive() || player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); } }