Add available commands to prepare/play/pause/stop/release.
PiperOrigin-RevId: 362292208
This commit is contained in:
parent
c7bcacdeba
commit
9d2d334091
@ -140,14 +140,13 @@ public final class CastPlayer extends BasePlayer {
|
||||
Looper.getMainLooper(),
|
||||
Clock.DEFAULT,
|
||||
(listener, flags) -> listener.onEvents(/* player= */ this, new Events(flags)));
|
||||
|
||||
playWhenReady = new StateHolder<>(false);
|
||||
repeatMode = new StateHolder<>(REPEAT_MODE_OFF);
|
||||
playbackState = STATE_IDLE;
|
||||
currentTimeline = CastTimeline.EMPTY_CAST_TIMELINE;
|
||||
currentTrackGroups = TrackGroupArray.EMPTY;
|
||||
currentTrackSelection = EMPTY_TRACK_SELECTION_ARRAY;
|
||||
availableCommands = Commands.EMPTY;
|
||||
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
||||
pendingSeekWindowIndex = C.INDEX_UNSET;
|
||||
pendingSeekPositionMs = C.TIME_UNSET;
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.ext.cast;
|
||||
|
||||
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_TO_NEXT_MEDIA_ITEM;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@ -592,6 +594,12 @@ public class CastPlayerTest {
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCommandAvailable_containsPermanentCommands() {
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue();
|
||||
assertThat(castPlayer.isCommandAvailable(COMMAND_PREPARE_STOP_RELEASE)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seekTo_nextWindow_notifiesAvailableCommandsChanged() {
|
||||
when(mockRemoteMediaClient.queueJumpToItem(anyInt(), anyLong(), eq(null)))
|
||||
@ -728,6 +736,7 @@ public class CastPlayerTest {
|
||||
@Test
|
||||
public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() {
|
||||
Player.Commands commandsWithSeekToNext = createCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3);
|
||||
@ -752,7 +761,7 @@ public class CastPlayerTest {
|
||||
ImmutableList.of(mediaItem1),
|
||||
/* mediaQueueItemIds= */ new int[] {1},
|
||||
/* currentItemId= */ 1);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
|
||||
castPlayer.removeMediaItem(/* index= */ 0);
|
||||
@ -769,6 +778,7 @@ public class CastPlayerTest {
|
||||
.thenReturn(mockPendingResult);
|
||||
Player.Commands commandsWithSeekToPrevious =
|
||||
createCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
MediaItem mediaItem3 = createMediaItem(/* mediaQueueItemId= */ 3);
|
||||
@ -793,7 +803,7 @@ public class CastPlayerTest {
|
||||
ImmutableList.of(mediaItem3),
|
||||
/* mediaQueueItemIds= */ new int[] {3},
|
||||
/* currentItemId= */ 3);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
|
||||
castPlayer.removeMediaItem(/* index= */ 0);
|
||||
@ -807,6 +817,7 @@ public class CastPlayerTest {
|
||||
@Test
|
||||
public void removeMediaItem_current_notifiesAvailableCommandsChanged() {
|
||||
Player.Commands commandsWithSeekToNext = createCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
MediaItem mediaItem1 = createMediaItem(/* mediaQueueItemId= */ 1);
|
||||
MediaItem mediaItem2 = createMediaItem(/* mediaQueueItemId= */ 2);
|
||||
|
||||
@ -823,7 +834,7 @@ public class CastPlayerTest {
|
||||
ImmutableList.of(mediaItem2),
|
||||
/* mediaQueueItemIds= */ new int[] {2},
|
||||
/* currentItemId= */ 2);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
}
|
||||
|
||||
@ -912,6 +923,7 @@ public class CastPlayerTest {
|
||||
|
||||
private static Player.Commands createCommands(@Player.Command int... commands) {
|
||||
Player.Commands.Builder builder = new Player.Commands.Builder();
|
||||
builder.addAll(COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP_RELEASE);
|
||||
for (int command : commands) {
|
||||
builder.add(command);
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ import java.util.List;
|
||||
/** Abstract base {@link Player} which implements common implementation independent methods. */
|
||||
public abstract class BasePlayer implements Player {
|
||||
|
||||
protected static final int[] PERMANENT_AVAILABLE_COMMANDS =
|
||||
new int[] {COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP_RELEASE};
|
||||
|
||||
protected final Timeline.Window window;
|
||||
|
||||
public BasePlayer() {
|
||||
@ -322,6 +325,7 @@ public abstract class BasePlayer implements Player {
|
||||
|
||||
protected Commands getAvailableCommands() {
|
||||
return new Commands.Builder()
|
||||
.addAll(PERMANENT_AVAILABLE_COMMANDS)
|
||||
.addIf(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, hasNext() && !isPlayingAd())
|
||||
.addIf(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM, hasPrevious() && !isPlayingAd())
|
||||
.build();
|
||||
|
@ -757,6 +757,18 @@ public interface Player {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link Command commands}.
|
||||
*
|
||||
* @param commands The {@link Command commands} to add.
|
||||
* @return This builder.
|
||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||
*/
|
||||
public Builder addAll(@Command int... commands) {
|
||||
flagsBuilder.addAll(commands);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link Commands} instance.
|
||||
*
|
||||
@ -767,9 +779,6 @@ public interface Player {
|
||||
}
|
||||
}
|
||||
|
||||
/** An empty set of commands. */
|
||||
public static final Commands EMPTY = new Builder().build();
|
||||
|
||||
private final ExoFlags flags;
|
||||
|
||||
private Commands(ExoFlags flags) {
|
||||
@ -1037,17 +1046,27 @@ public interface Player {
|
||||
int EVENT_AVAILABLE_COMMANDS_CHANGED = 14;
|
||||
|
||||
/**
|
||||
* Commands that can be executed on a {@code Player}. One of {@link
|
||||
* #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} or {@link #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}.
|
||||
* Commands that can be executed on a {@code Player}. One of {@link #COMMAND_PLAY_PAUSE}, {@link
|
||||
* #COMMAND_PREPARE_STOP_RELEASE}, {@link #COMMAND_SEEK_TO_NEXT_MEDIA_ITEM} or {@link
|
||||
* #COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM}.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({COMMAND_SEEK_TO_NEXT_MEDIA_ITEM, COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM})
|
||||
@IntDef({
|
||||
COMMAND_PLAY_PAUSE,
|
||||
COMMAND_PREPARE_STOP_RELEASE,
|
||||
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM,
|
||||
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM
|
||||
})
|
||||
@interface Command {}
|
||||
/** Command to start, pause or resume playback. */
|
||||
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 to the next {@link MediaItem} in the playlist. */
|
||||
int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 0;
|
||||
int COMMAND_SEEK_TO_NEXT_MEDIA_ITEM = 3;
|
||||
/** Command to seek to the previous {@link MediaItem} in the playlist. */
|
||||
int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 1;
|
||||
int COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM = 4;
|
||||
|
||||
/** Returns the component of this player for audio output, or null if audio is not supported. */
|
||||
@Nullable
|
||||
|
@ -70,6 +70,20 @@ public final class ExoFlags {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds flags.
|
||||
*
|
||||
* @param flags The flags to add.
|
||||
* @return This builder.
|
||||
* @throws IllegalStateException If {@link #build()} has already been called.
|
||||
*/
|
||||
public Builder addAll(int... flags) {
|
||||
for (int flag : flags) {
|
||||
add(flag);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link ExoFlags} instance.
|
||||
*
|
||||
|
@ -174,7 +174,7 @@ import java.util.List;
|
||||
new ExoTrackSelection[renderers.length],
|
||||
/* info= */ null);
|
||||
period = new Timeline.Period();
|
||||
availableCommands = Commands.EMPTY;
|
||||
availableCommands = new Commands.Builder().addAll(PERMANENT_AVAILABLE_COMMANDS).build();
|
||||
maskingWindowIndex = C.INDEX_UNSET;
|
||||
playbackInfoUpdateHandler = clock.createHandler(applicationLooper, /* callback= */ null);
|
||||
playbackInfoUpdateListener =
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
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_TO_NEXT_MEDIA_ITEM;
|
||||
import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM;
|
||||
import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil;
|
||||
@ -8080,6 +8082,14 @@ public final class ExoPlayerTest {
|
||||
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCommandAvailable_containsPermanentCommands() {
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
|
||||
assertThat(player.isCommandAvailable(COMMAND_PLAY_PAUSE)).isTrue();
|
||||
assertThat(player.isCommandAvailable(COMMAND_PREPARE_STOP_RELEASE)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isCommandAvailable_whenPlayingAd_isFalseForSeekCommands() throws Exception {
|
||||
AdPlaybackState adPlaybackState =
|
||||
@ -8262,6 +8272,7 @@ public final class ExoPlayerTest {
|
||||
@Test
|
||||
public void removeMediaItem_atTheEnd_notifiesAvailableCommandsChanged() {
|
||||
Player.Commands commandsWithSeekToNext = createCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
Player.EventListener mockListener = mock(Player.EventListener.class);
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
player.addListener(mockListener);
|
||||
@ -8275,7 +8286,7 @@ public final class ExoPlayerTest {
|
||||
verify(mockListener).onAvailableCommandsChanged(any());
|
||||
|
||||
player.removeMediaItem(/* index= */ 1);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
|
||||
player.removeMediaItem(/* index= */ 0);
|
||||
@ -8286,6 +8297,7 @@ public final class ExoPlayerTest {
|
||||
public void removeMediaItem_atTheStart_notifiesAvailableCommandsChanged() {
|
||||
Player.Commands commandsWithSeekToPrevious =
|
||||
createCommands(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
Player.EventListener mockListener = mock(Player.EventListener.class);
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
player.addListener(mockListener);
|
||||
@ -8300,7 +8312,7 @@ public final class ExoPlayerTest {
|
||||
verify(mockListener).onAvailableCommandsChanged(any());
|
||||
|
||||
player.removeMediaItem(/* index= */ 0);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
|
||||
player.removeMediaItem(/* index= */ 0);
|
||||
@ -8310,6 +8322,7 @@ public final class ExoPlayerTest {
|
||||
@Test
|
||||
public void removeMediaItem_current_notifiesAvailableCommandsChanged() {
|
||||
Player.Commands commandsWithSeekToNext = createCommands(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM);
|
||||
Player.Commands commandsWithoutSeek = createCommands();
|
||||
Player.EventListener mockListener = mock(Player.EventListener.class);
|
||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||
player.addListener(mockListener);
|
||||
@ -8319,7 +8332,7 @@ public final class ExoPlayerTest {
|
||||
verify(mockListener).onAvailableCommandsChanged(any());
|
||||
|
||||
player.removeMediaItem(/* index= */ 0);
|
||||
verify(mockListener).onAvailableCommandsChanged(Player.Commands.EMPTY);
|
||||
verify(mockListener).onAvailableCommandsChanged(commandsWithoutSeek);
|
||||
verify(mockListener, times(2)).onAvailableCommandsChanged(any());
|
||||
}
|
||||
|
||||
@ -9313,6 +9326,7 @@ public final class ExoPlayerTest {
|
||||
|
||||
private static Player.Commands createCommands(@Player.Command int... commands) {
|
||||
Player.Commands.Builder builder = new Player.Commands.Builder();
|
||||
builder.addAll(COMMAND_PLAY_PAUSE, COMMAND_PREPARE_STOP_RELEASE);
|
||||
for (int command : commands) {
|
||||
builder.add(command);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user