diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java index 836e0b06ca..411479fac2 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java @@ -80,6 +80,7 @@ public final class CastPlayer extends BasePlayer { .addAll( COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP_RELEASE, + COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_MEDIA_ITEM, COMMAND_SET_REPEAT_MODE, COMMAND_GET_CURRENT_MEDIA_ITEM, diff --git a/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java b/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java index 746d5bf77b..49e7bd38e9 100644 --- a/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java +++ b/extensions/cast/src/test/java/com/google/android/exoplayer2/ext/cast/CastPlayerTest.java @@ -26,6 +26,7 @@ import static com.google.android.exoplayer2.Player.COMMAND_GET_VOLUME; import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; import static com.google.android.exoplayer2.Player.COMMAND_PREPARE_STOP_RELEASE; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; @@ -601,6 +602,7 @@ public class CastPlayerTest { assertThat(castPlayer.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_PREPARE_STOP_RELEASE)).isTrue(); + assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)).isTrue(); assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse(); 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 ac99cc96ab..6a77b67db3 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 @@ -331,6 +331,7 @@ public abstract class BasePlayer implements Player { protected Commands getAvailableCommands(Commands permanentAvailableCommands) { return new Commands.Builder() .addAll(permanentAvailableCommands) + .addIf(COMMAND_SEEK_TO_DEFAULT_POSITION, !isPlayingAd()) .addIf(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, isCurrentWindowSeekable() && !isPlayingAd()) .addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNext() && !isPlayingAd()) .addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPrevious() && !isPlayingAd()) 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 fae8ef5030..e5882543cd 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 @@ -1044,21 +1044,23 @@ public interface Player { /** * Commands that can be executed on a {@code Player}. One of {@link #COMMAND_PLAY_PAUSE}, {@link - * #COMMAND_PREPARE_STOP_RELEASE}, {@link #COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM}, {@link - * #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}, {@link #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}, {@link - * #COMMAND_SEEK_TO_MEDIA_ITEM}, {@link #COMMAND_SET_SPEED_AND_PITCH}, {@link - * #COMMAND_SET_SHUFFLE_MODE}, {@link #COMMAND_SET_REPEAT_MODE}, {@link - * #COMMAND_GET_CURRENT_MEDIA_ITEM}, {@link #COMMAND_GET_MEDIA_ITEMS}, {@link - * #COMMAND_GET_MEDIA_ITEMS_METADATA}, {@link #COMMAND_CHANGE_MEDIA_ITEMS}, {@link - * #COMMAND_GET_VOLUME}, {@link #COMMAND_GET_DEVICE_VOLUME}, {@link #COMMAND_SET_VOLUME}, {@link - * #COMMAND_SET_DEVICE_VOLUME}, {@link #COMMAND_ADJUST_DEVICE_VOLUME}, {@link - * #COMMAND_SET_VIDEO_SURFACE} or {@link #COMMAND_GET_TEXT}. + * #COMMAND_PREPARE_STOP_RELEASE}, {@link #COMMAND_SEEK_TO_DEFAULT_POSITION}, {@link + * #COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM}, {@link #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM}, {@link + * #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}, {@link #COMMAND_SEEK_TO_MEDIA_ITEM}, {@link + * #COMMAND_SET_SPEED_AND_PITCH}, {@link #COMMAND_SET_SHUFFLE_MODE}, {@link + * #COMMAND_SET_REPEAT_MODE}, {@link #COMMAND_GET_CURRENT_MEDIA_ITEM}, {@link + * #COMMAND_GET_MEDIA_ITEMS}, {@link #COMMAND_GET_MEDIA_ITEMS_METADATA}, {@link + * #COMMAND_CHANGE_MEDIA_ITEMS}, {@link #COMMAND_GET_VOLUME}, {@link #COMMAND_GET_DEVICE_VOLUME}, + * {@link #COMMAND_SET_VOLUME}, {@link #COMMAND_SET_DEVICE_VOLUME}, {@link + * #COMMAND_ADJUST_DEVICE_VOLUME}, {@link #COMMAND_SET_VIDEO_SURFACE} or {@link + * #COMMAND_GET_TEXT}. */ @Documented @Retention(RetentionPolicy.SOURCE) @IntDef({ COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP_RELEASE, + COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, @@ -1083,42 +1085,44 @@ public interface Player { int COMMAND_PLAY_PAUSE = 1; /** Command to prepare the player, stop playback or release the player. */ int COMMAND_PREPARE_STOP_RELEASE = 2; - /** Command to seek into the current window. */ - int COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM = 3; + /** Command to seek to the default position of the current window. */ + int COMMAND_SEEK_TO_DEFAULT_POSITION = 3; + /** Command to seek anywhere into the current window. */ + int COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM = 4; /** Command to seek to the default position of the next window. */ - int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 4; + int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 5; /** Command to seek to the default position of the previous window. */ - int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 5; + int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 6; /** Command to seek anywhere in any window. */ - int COMMAND_SEEK_TO_MEDIA_ITEM = 6; + int COMMAND_SEEK_TO_MEDIA_ITEM = 7; /** Command to set the playback speed and pitch. */ - int COMMAND_SET_SPEED_AND_PITCH = 7; + int COMMAND_SET_SPEED_AND_PITCH = 8; /** Command to enable shuffling. */ - int COMMAND_SET_SHUFFLE_MODE = 8; + int COMMAND_SET_SHUFFLE_MODE = 9; /** Command to set the repeat mode. */ - int COMMAND_SET_REPEAT_MODE = 9; + int COMMAND_SET_REPEAT_MODE = 10; /** Command to get the {@link MediaItem} of the current window. */ - int COMMAND_GET_CURRENT_MEDIA_ITEM = 10; + int COMMAND_GET_CURRENT_MEDIA_ITEM = 11; /** Command to get the current timeline and its {@link MediaItem MediaItems}. */ - int COMMAND_GET_MEDIA_ITEMS = 11; + int COMMAND_GET_MEDIA_ITEMS = 12; /** Command to get the {@link MediaItem MediaItems} metadata. */ - int COMMAND_GET_MEDIA_ITEMS_METADATA = 12; + int COMMAND_GET_MEDIA_ITEMS_METADATA = 13; /** Command to change the {@link MediaItem MediaItems} in the playlist. */ - int COMMAND_CHANGE_MEDIA_ITEMS = 13; + int COMMAND_CHANGE_MEDIA_ITEMS = 14; /** Command to get the player volume. */ - int COMMAND_GET_VOLUME = 14; + int COMMAND_GET_VOLUME = 15; /** Command to get the device volume and whether it is muted. */ - int COMMAND_GET_DEVICE_VOLUME = 15; + int COMMAND_GET_DEVICE_VOLUME = 16; /** Command to set the player volume. */ - int COMMAND_SET_VOLUME = 16; + int COMMAND_SET_VOLUME = 17; /** Command to set the device volume and mute it. */ - int COMMAND_SET_DEVICE_VOLUME = 17; + int COMMAND_SET_DEVICE_VOLUME = 18; /** Command to increase and decrease the device volume and mute it. */ - int COMMAND_ADJUST_DEVICE_VOLUME = 18; + int COMMAND_ADJUST_DEVICE_VOLUME = 19; /** Command to set and clear the surface on which to render the video. */ - int COMMAND_SET_VIDEO_SURFACE = 19; + int COMMAND_SET_VIDEO_SURFACE = 20; /** Command to get the text that should currently be displayed by the player. */ - int COMMAND_GET_TEXT = 20; + int COMMAND_GET_TEXT = 21; /** Returns the component of this player for audio output, or null if audio is not supported. */ @Nullable diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 568fa1c400..8580272827 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -198,6 +198,7 @@ import java.util.concurrent.CopyOnWriteArraySet; availableCommands = new Commands.Builder() .addAll(permanentAvailableCommands) + .add(COMMAND_SEEK_TO_DEFAULT_POSITION) .add(COMMAND_SEEK_TO_MEDIA_ITEM) .build(); maskingWindowIndex = C.INDEX_UNSET; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index 0f849ec25c..7a94ae6492 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -26,6 +26,7 @@ import static com.google.android.exoplayer2.Player.COMMAND_GET_VOLUME; import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; import static com.google.android.exoplayer2.Player.COMMAND_PREPARE_STOP_RELEASE; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_DEFAULT_POSITION; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM; import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM; @@ -8061,6 +8062,7 @@ public final class ExoPlayerTest { assertThat(player.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_PREPARE_STOP_RELEASE)).isTrue(); + assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_DEFAULT_POSITION)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)).isFalse(); assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)).isTrue(); assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse(); @@ -8132,11 +8134,11 @@ public final class ExoPlayerTest { @Test public void seekTo_nextWindow_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.Commands commandsWithSeekToPrevious = - createWithPermanentCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.Commands commandsWithSeekToNextAndPrevious = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); @@ -8167,11 +8169,11 @@ public final class ExoPlayerTest { @Test public void seekTo_previousWindow_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.Commands commandsWithSeekToPrevious = - createWithPermanentCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.Commands commandsWithSeekToNextAndPrevious = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); @@ -8215,15 +8217,15 @@ public final class ExoPlayerTest { @Test public void automaticWindowTransition_notifiesAvailableCommandsChanged() throws Exception { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.Commands commandsWithSeekInCurrentAndToNext = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.Commands commandsWithSeekInCurrentAndToPrevious = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.Commands commandsWithSeekAnywhere = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM, COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); @@ -8264,7 +8266,7 @@ public final class ExoPlayerTest { @Test public void addMediaSource_atTheEnd_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8284,7 +8286,7 @@ public final class ExoPlayerTest { @Test public void addMediaSource_atTheStart_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToPrevious = - createWithPermanentCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8304,8 +8306,8 @@ public final class ExoPlayerTest { @Test public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithPermanentCommands(); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands commandsWithoutSeek = createWithDefaultCommands(); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8330,8 +8332,8 @@ public final class ExoPlayerTest { @Test public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToPrevious = - createWithPermanentCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithPermanentCommands(); + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + Player.Commands commandsWithoutSeek = createWithDefaultCommands(); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8357,8 +8359,8 @@ public final class ExoPlayerTest { @Test public void removeMediaItem_current_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); - Player.Commands commandsWithoutSeek = createWithPermanentCommands(); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + Player.Commands commandsWithoutSeek = createWithDefaultCommands(); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -8376,7 +8378,7 @@ public final class ExoPlayerTest { @Test public void setRepeatMode_all_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNextAndPrevious = - createWithPermanentCommands( + createWithDefaultCommands( COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); @@ -8405,9 +8407,9 @@ public final class ExoPlayerTest { @Test public void setShuffleModeEnabled_notifiesAvailableCommandsChanged() { Player.Commands commandsWithSeekToNext = - createWithPermanentCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM); Player.Commands commandsWithSeekToPrevious = - createWithPermanentCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); + createWithDefaultCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM); Player.EventListener mockListener = mock(Player.EventListener.class); ExoPlayer player = new TestExoPlayerBuilder(context).build(); player.addListener(mockListener); @@ -9377,7 +9379,7 @@ public final class ExoPlayerTest { return false; } - private static Player.Commands createWithPermanentCommands( + private static Player.Commands createWithDefaultCommands( @Player.Command int... additionalCommands) { Player.Commands.Builder builder = new Player.Commands.Builder(); builder.addAll( @@ -9397,6 +9399,7 @@ public final class ExoPlayerTest { COMMAND_ADJUST_DEVICE_VOLUME, COMMAND_SET_VIDEO_SURFACE, COMMAND_GET_TEXT, + COMMAND_SEEK_TO_DEFAULT_POSITION, COMMAND_SEEK_TO_MEDIA_ITEM); builder.addAll(additionalCommands); return builder.build();