Re-order seekBack and seekForward in Player

This is more consistent with other Player methods like previous and
next.

PiperOrigin-RevId: 383832298
This commit is contained in:
kimvde 2021-07-09 14:14:27 +01:00 committed by Oliver Woodman
parent 699579fd4e
commit bc0f3935d6
14 changed files with 244 additions and 244 deletions

View file

@ -4,8 +4,8 @@
* Core Library:
* Add `needsReconfiguration` API to the `MediaCodecAdapter` interface.
* Add `getSeekForwardIncrement`, `seekForward`, `getSeekBackIncrement`
and `seekBack` methods to `Player`.
* Add `getSeekBackIncrement`, `seekBack`, `getSeekForwardIncrement` and
`seekForward` methods to `Player`.
* Add `getMaxSeekToPreviousPosition`, `seekToPrevious` and `seekToNext`
methods to `Player`.
* Rename `Player` commands `COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM`,

View file

@ -115,8 +115,8 @@ public final class CastPlayer extends BasePlayer {
private final CastContext castContext;
private final MediaItemConverter mediaItemConverter;
private final long seekForwardIncrementMs;
private final long seekBackIncrementMs;
private final long seekForwardIncrementMs;
// TODO: Allow custom implementations of CastTimelineTracker.
private final CastTimelineTracker timelineTracker;
private final Timeline.Period period;
@ -151,8 +151,8 @@ public final class CastPlayer extends BasePlayer {
* <p>The returned player uses a {@link DefaultMediaItemConverter} and
*
* <p>{@code mediaItemConverter} is set to a {@link DefaultMediaItemConverter}, {@code
* seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS} and {@code
* seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS}.
* seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS} and {@code
* seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}.
*
* @param castContext The context from which the cast session is obtained.
*/
@ -163,8 +163,8 @@ public final class CastPlayer extends BasePlayer {
/**
* Creates a new cast player.
*
* <p>{@code seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS} and
* {@code seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS}.
* <p>{@code seekBackIncrementMs} is set to {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS} and {@code
* seekForwardIncrementMs} is set to {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}.
*
* @param castContext The context from which the cast session is obtained.
* @param mediaItemConverter The {@link MediaItemConverter} to use.
@ -173,8 +173,8 @@ public final class CastPlayer extends BasePlayer {
this(
castContext,
mediaItemConverter,
C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
C.DEFAULT_SEEK_BACK_INCREMENT_MS);
C.DEFAULT_SEEK_BACK_INCREMENT_MS,
C.DEFAULT_SEEK_FORWARD_INCREMENT_MS);
}
/**
@ -182,21 +182,21 @@ public final class CastPlayer extends BasePlayer {
*
* @param castContext The context from which the cast session is obtained.
* @param mediaItemConverter The {@link MediaItemConverter} to use.
* @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds.
* @param seekBackIncrementMs The {@link #seekBack()} increment, in milliseconds.
* @throws IllegalArgumentException If {@code seekForwardIncrementMs} or {@code
* seekBackIncrementMs} is non-positive.
* @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds.
* @throws IllegalArgumentException If {@code seekBackIncrementMs} or {@code
* seekForwardIncrementMs} is non-positive.
*/
public CastPlayer(
CastContext castContext,
MediaItemConverter mediaItemConverter,
long seekForwardIncrementMs,
long seekBackIncrementMs) {
checkArgument(seekForwardIncrementMs > 0 && seekBackIncrementMs > 0);
long seekBackIncrementMs,
long seekForwardIncrementMs) {
checkArgument(seekBackIncrementMs > 0 && seekForwardIncrementMs > 0);
this.castContext = castContext;
this.mediaItemConverter = mediaItemConverter;
this.seekForwardIncrementMs = seekForwardIncrementMs;
this.seekBackIncrementMs = seekBackIncrementMs;
this.seekForwardIncrementMs = seekForwardIncrementMs;
timelineTracker = new CastTimelineTracker();
period = new Timeline.Period();
statusListener = new StatusListener();
@ -449,13 +449,13 @@ public final class CastPlayer extends BasePlayer {
}
@Override
public long getSeekForwardIncrement() {
return seekForwardIncrementMs;
public long getSeekBackIncrement() {
return seekBackIncrementMs;
}
@Override
public long getSeekBackIncrement() {
return seekBackIncrementMs;
public long getSeekForwardIncrement() {
return seekForwardIncrementMs;
}
@Override

View file

@ -1102,52 +1102,6 @@ public class CastPlayerTest {
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
@Test
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
public void seekForward_notifiesPositionDiscontinuity() {
when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult);
int[] mediaQueueItemIds = new int[] {1};
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
int currentItemId = 1;
int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_BUFFERED};
long[] durationsMs = new long[] {2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS};
long positionMs = 0;
castPlayer.addMediaItems(mediaItems);
updateTimeLine(
mediaItems, mediaQueueItemIds, currentItemId, streamTypes, durationsMs, positionMs);
castPlayer.seekForward();
Player.PositionInfo oldPosition =
new Player.PositionInfo(
/* windowUid= */ 1,
/* windowIndex= */ 0,
/* periodUid= */ 1,
/* periodIndex= */ 0,
/* positionMs= */ 0,
/* contentPositionMs= */ 0,
/* adGroupIndex= */ C.INDEX_UNSET,
/* adIndexInAdGroup= */ C.INDEX_UNSET);
Player.PositionInfo newPosition =
new Player.PositionInfo(
/* windowUid= */ 1,
/* windowIndex= */ 0,
/* periodUid= */ 1,
/* periodIndex= */ 0,
/* positionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
/* contentPositionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
/* adGroupIndex= */ C.INDEX_UNSET,
/* adIndexInAdGroup= */ C.INDEX_UNSET);
InOrder inOrder = Mockito.inOrder(mockListener);
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK));
inOrder
.verify(mockListener)
.onPositionDiscontinuity(
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK));
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
@Test
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
public void seekBack_notifiesPositionDiscontinuity() {
@ -1194,6 +1148,52 @@ public class CastPlayerTest {
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
@Test
@SuppressWarnings("deprecation") // Mocks deprecated method used by the CastPlayer.
public void seekForward_notifiesPositionDiscontinuity() {
when(mockRemoteMediaClient.seek(anyLong())).thenReturn(mockPendingResult);
int[] mediaQueueItemIds = new int[] {1};
List<MediaItem> mediaItems = createMediaItems(mediaQueueItemIds);
int currentItemId = 1;
int[] streamTypes = new int[] {MediaInfo.STREAM_TYPE_BUFFERED};
long[] durationsMs = new long[] {2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS};
long positionMs = 0;
castPlayer.addMediaItems(mediaItems);
updateTimeLine(
mediaItems, mediaQueueItemIds, currentItemId, streamTypes, durationsMs, positionMs);
castPlayer.seekForward();
Player.PositionInfo oldPosition =
new Player.PositionInfo(
/* windowUid= */ 1,
/* windowIndex= */ 0,
/* periodUid= */ 1,
/* periodIndex= */ 0,
/* positionMs= */ 0,
/* contentPositionMs= */ 0,
/* adGroupIndex= */ C.INDEX_UNSET,
/* adIndexInAdGroup= */ C.INDEX_UNSET);
Player.PositionInfo newPosition =
new Player.PositionInfo(
/* windowUid= */ 1,
/* windowIndex= */ 0,
/* periodUid= */ 1,
/* periodIndex= */ 0,
/* positionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
/* contentPositionMs= */ C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
/* adGroupIndex= */ C.INDEX_UNSET,
/* adIndexInAdGroup= */ C.INDEX_UNSET);
InOrder inOrder = Mockito.inOrder(mockListener);
inOrder.verify(mockListener).onPositionDiscontinuity(eq(Player.DISCONTINUITY_REASON_SEEK));
inOrder
.verify(mockListener)
.onPositionDiscontinuity(
eq(oldPosition), eq(newPosition), eq(Player.DISCONTINUITY_REASON_SEEK));
inOrder.verify(mockListener, never()).onPositionDiscontinuity(anyInt());
inOrder.verify(mockListener, never()).onPositionDiscontinuity(any(), any(), anyInt());
}
@Test
public void isCommandAvailable_isTrueForAvailableCommands() {
int[] mediaQueueItemIds = new int[] {1, 2};
@ -1209,8 +1209,8 @@ public class CastPlayerTest {
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isTrue();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isTrue();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isTrue();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_BACK)).isTrue();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isTrue();
assertThat(castPlayer.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SET_REPEAT_MODE)).isTrue();
@ -1247,8 +1247,8 @@ public class CastPlayerTest {
/* positionMs= */ C.TIME_UNSET);
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse();
assertThat(castPlayer.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
}
@Test
@ -1661,8 +1661,8 @@ public class CastPlayerTest {
Player.Commands.Builder builder = new Player.Commands.Builder();
builder.addAll(CastPlayer.PERMANENT_AVAILABLE_COMMANDS);
builder.add(COMMAND_SEEK_IN_CURRENT_WINDOW);
builder.add(COMMAND_SEEK_FORWARD);
builder.add(COMMAND_SEEK_BACK);
builder.add(COMMAND_SEEK_FORWARD);
builder.addAll(additionalCommands);
return builder.build();
}

View file

@ -122,13 +122,13 @@ public abstract class BasePlayer implements Player {
}
@Override
public final void seekForward() {
seekToOffset(getSeekForwardIncrement());
public final void seekBack() {
seekToOffset(-getSeekBackIncrement());
}
@Override
public final void seekBack() {
seekToOffset(-getSeekBackIncrement());
public final void seekForward() {
seekToOffset(getSeekForwardIncrement());
}
@Override
@ -298,8 +298,8 @@ public abstract class BasePlayer implements Player {
.addIf(COMMAND_SEEK_TO_NEXT_WINDOW, hasNext() && !isPlayingAd())
.addIf(COMMAND_SEEK_TO_PREVIOUS_WINDOW, hasPrevious() && !isPlayingAd())
.addIf(COMMAND_SEEK_TO_WINDOW, !isPlayingAd())
.addIf(COMMAND_SEEK_FORWARD, isCurrentWindowSeekable() && !isPlayingAd())
.addIf(COMMAND_SEEK_BACK, isCurrentWindowSeekable() && !isPlayingAd())
.addIf(COMMAND_SEEK_FORWARD, isCurrentWindowSeekable() && !isPlayingAd())
.build();
}

View file

@ -646,10 +646,10 @@ public final class C {
/** A default size in bytes for an individual allocation that forms part of a larger buffer. */
public static final int DEFAULT_BUFFER_SEGMENT_SIZE = 64 * 1024;
/** A default seek forward increment, in milliseconds. */
public static final long DEFAULT_SEEK_FORWARD_INCREMENT_MS = 15_000;
/** A default seek back increment, in milliseconds. */
public static final long DEFAULT_SEEK_BACK_INCREMENT_MS = 5000;
/** A default seek forward increment, in milliseconds. */
public static final long DEFAULT_SEEK_FORWARD_INCREMENT_MS = 15_000;
/**
* A default maximum position for which a seek to previous will seek to the previous window, in

View file

@ -247,16 +247,6 @@ public class ForwardingPlayer implements Player {
player.seekTo(windowIndex, positionMs);
}
@Override
public long getSeekForwardIncrement() {
return player.getSeekForwardIncrement();
}
@Override
public void seekForward() {
player.seekForward();
}
@Override
public long getSeekBackIncrement() {
return player.getSeekBackIncrement();
@ -267,6 +257,16 @@ public class ForwardingPlayer implements Player {
player.seekBack();
}
@Override
public long getSeekForwardIncrement() {
return player.getSeekForwardIncrement();
}
@Override
public void seekForward() {
player.seekForward();
}
@Override
public boolean hasPrevious() {
return player.hasPrevious();
@ -712,13 +712,13 @@ public class ForwardingPlayer implements Player {
}
@Override
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
eventListener.onSeekForwardIncrementChanged(seekForwardIncrementMs);
public void onSeekBackIncrementChanged(long seekBackIncrementMs) {
eventListener.onSeekBackIncrementChanged(seekBackIncrementMs);
}
@Override
public void onSeekBackIncrementChanged(long seekBackIncrementMs) {
eventListener.onSeekBackIncrementChanged(seekBackIncrementMs);
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
eventListener.onSeekForwardIncrementChanged(seekForwardIncrementMs);
}
@Override

View file

@ -322,16 +322,6 @@ public interface Player {
*/
default void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {}
/**
* Called when the value of {@link #getSeekForwardIncrement()} changes.
*
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration.
*
* @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds.
*/
default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {}
/**
* Called when the value of {@link #getSeekBackIncrement()} changes.
*
@ -342,6 +332,16 @@ public interface Player {
*/
default void onSeekBackIncrementChanged(long seekBackIncrementMs) {}
/**
* Called when the value of {@link #getSeekForwardIncrement()} changes.
*
* <p>{@link #onEvents(Player, Events)} will also be called to report this event along with
* other events that happen in the same {@link Looper} message queue iteration.
*
* @param seekForwardIncrementMs The {@link #seekForward()} increment, in milliseconds.
*/
default void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {}
/**
* Called when the value of {@link #getMaxSeekToPreviousPosition()} changes.
*
@ -640,8 +640,8 @@ public interface Player {
COMMAND_SEEK_TO_NEXT_WINDOW,
COMMAND_SEEK_TO_PREVIOUS_WINDOW,
COMMAND_SEEK_TO_WINDOW,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_BACK,
COMMAND_SEEK_FORWARD,
COMMAND_SET_SPEED_AND_PITCH,
COMMAND_SET_SHUFFLE_MODE,
COMMAND_SET_REPEAT_MODE,
@ -1106,8 +1106,8 @@ public interface Player {
EVENT_AVAILABLE_COMMANDS_CHANGED,
EVENT_MEDIA_METADATA_CHANGED,
EVENT_PLAYLIST_METADATA_CHANGED,
EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
EVENT_SEEK_BACK_INCREMENT_CHANGED,
EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED
})
@interface Event {}
@ -1148,10 +1148,10 @@ public interface Player {
int EVENT_MEDIA_METADATA_CHANGED = 15;
/** {@link #getPlaylistMetadata()} changed. */
int EVENT_PLAYLIST_METADATA_CHANGED = 16;
/** {@link #getSeekForwardIncrement()} changed. */
int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = 17;
/** {@link #getSeekBackIncrement()} changed. */
int EVENT_SEEK_BACK_INCREMENT_CHANGED = 18;
int EVENT_SEEK_BACK_INCREMENT_CHANGED = 17;
/** {@link #getSeekForwardIncrement()} changed. */
int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = 18;
/** {@link #getMaxSeekToPreviousPosition()} changed. */
int EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED = 19;
@ -1159,9 +1159,9 @@ public interface Player {
* Commands that can be executed on a {@code Player}. One of {@link #COMMAND_PLAY_PAUSE}, {@link
* #COMMAND_PREPARE_STOP}, {@link #COMMAND_SEEK_TO_DEFAULT_POSITION}, {@link
* #COMMAND_SEEK_IN_CURRENT_WINDOW}, {@link #COMMAND_SEEK_TO_NEXT_WINDOW}, {@link
* #COMMAND_SEEK_TO_PREVIOUS_WINDOW}, {@link #COMMAND_SEEK_TO_WINDOW}, {@link
* #COMMAND_SEEK_FORWARD}, {@link #COMMAND_SEEK_BACK}, {@link #COMMAND_SET_SPEED_AND_PITCH},
* {@link #COMMAND_SET_SHUFFLE_MODE}, {@link #COMMAND_SET_REPEAT_MODE}, {@link
* #COMMAND_SEEK_TO_PREVIOUS_WINDOW}, {@link #COMMAND_SEEK_TO_WINDOW}, {@link #COMMAND_SEEK_BACK},
* {@link #COMMAND_SEEK_FORWARD}, {@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_SET_MEDIA_ITEMS_METADATA}, {@link
* #COMMAND_CHANGE_MEDIA_ITEMS}, {@link #COMMAND_GET_AUDIO_ATTRIBUTES}, {@link
@ -1180,8 +1180,8 @@ public interface Player {
COMMAND_SEEK_TO_NEXT_WINDOW,
COMMAND_SEEK_TO_PREVIOUS_WINDOW,
COMMAND_SEEK_TO_WINDOW,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_BACK,
COMMAND_SEEK_FORWARD,
COMMAND_SET_SPEED_AND_PITCH,
COMMAND_SET_SHUFFLE_MODE,
COMMAND_SET_REPEAT_MODE,
@ -1214,10 +1214,10 @@ public interface Player {
int COMMAND_SEEK_TO_PREVIOUS_WINDOW = 6;
/** Command to seek anywhere in any window. */
int COMMAND_SEEK_TO_WINDOW = 7;
/** Command to seek forward into the current window. */
int COMMAND_SEEK_FORWARD = 8;
/** Command to seek back into the current window. */
int COMMAND_SEEK_BACK = 9;
int COMMAND_SEEK_BACK = 8;
/** Command to seek forward into the current window. */
int COMMAND_SEEK_FORWARD = 9;
/** Command to set the playback speed and pitch. */
int COMMAND_SET_SPEED_AND_PITCH = 10;
/** Command to enable shuffling. */
@ -1623,17 +1623,6 @@ public interface Player {
*/
void seekTo(int windowIndex, long positionMs);
/**
* Returns the {@link #seekForward()} increment.
*
* @return The seek forward increment, in milliseconds.
* @see Listener#onSeekForwardIncrementChanged(long)
*/
long getSeekForwardIncrement();
/** Seeks forward in the current window by {@link #getSeekForwardIncrement()} milliseconds. */
void seekForward();
/**
* Returns the {@link #seekBack()} increment.
*
@ -1645,6 +1634,17 @@ public interface Player {
/** Seeks back in the current window by {@link #getSeekBackIncrement()} milliseconds. */
void seekBack();
/**
* Returns the {@link #seekForward()} increment.
*
* @return The seek forward increment, in milliseconds.
* @see Listener#onSeekForwardIncrementChanged(long)
*/
long getSeekForwardIncrement();
/** Seeks forward in the current window by {@link #getSeekForwardIncrement()} milliseconds. */
void seekForward();
/**
* Returns whether a previous window exists, which may depend on the current repeat mode and
* whether shuffle mode is enabled.

View file

@ -828,8 +828,8 @@ public interface ExoPlayer extends Player {
analyticsCollector,
useLazyPreparation,
seekParameters,
C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
C.DEFAULT_SEEK_BACK_INCREMENT_MS,
C.DEFAULT_SEEK_FORWARD_INCREMENT_MS,
livePlaybackSpeedControl,
releaseTimeoutMs,
pauseAtEndOfMediaItems,

View file

@ -88,8 +88,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Nullable private final AnalyticsCollector analyticsCollector;
private final Looper applicationLooper;
private final BandwidthMeter bandwidthMeter;
private final long seekForwardIncrementMs;
private final long seekBackIncrementMs;
private final long seekForwardIncrementMs;
private final Clock clock;
@RepeatMode private int repeatMode;
@ -127,8 +127,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
* loads and other initial preparation steps happen immediately. If true, these initial
* preparations are triggered only when the player starts buffering the media.
* @param seekParameters The {@link SeekParameters}.
* @param seekForwardIncrementMs The {@link #seekForward()} increment in milliseconds.
* @param seekBackIncrementMs The {@link #seekBack()} increment in milliseconds.
* @param seekForwardIncrementMs The {@link #seekForward()} increment in milliseconds.
* @param livePlaybackSpeedControl The {@link LivePlaybackSpeedControl}.
* @param releaseTimeoutMs The timeout for calls to {@link #release()} in milliseconds.
* @param pauseAtEndOfMediaItems Whether to pause playback at the end of each media item.
@ -150,8 +150,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Nullable AnalyticsCollector analyticsCollector,
boolean useLazyPreparation,
SeekParameters seekParameters,
long seekForwardIncrementMs,
long seekBackIncrementMs,
long seekForwardIncrementMs,
LivePlaybackSpeedControl livePlaybackSpeedControl,
long releaseTimeoutMs,
boolean pauseAtEndOfMediaItems,
@ -176,8 +176,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
this.analyticsCollector = analyticsCollector;
this.useLazyPreparation = useLazyPreparation;
this.seekParameters = seekParameters;
this.seekForwardIncrementMs = seekForwardIncrementMs;
this.seekBackIncrementMs = seekBackIncrementMs;
this.seekForwardIncrementMs = seekForwardIncrementMs;
this.pauseAtEndOfMediaItems = pauseAtEndOfMediaItems;
this.applicationLooper = applicationLooper;
this.clock = clock;
@ -721,13 +721,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
@Override
public long getSeekForwardIncrement() {
return seekForwardIncrementMs;
public long getSeekBackIncrement() {
return seekBackIncrementMs;
}
@Override
public long getSeekBackIncrement() {
return seekBackIncrementMs;
public long getSeekForwardIncrement() {
return seekForwardIncrementMs;
}
@Override

View file

@ -129,8 +129,8 @@ public class SimpleExoPlayer extends BasePlayer
@C.VideoScalingMode private int videoScalingMode;
private boolean useLazyPreparation;
private SeekParameters seekParameters;
private long seekForwardIncrementMs;
private long seekBackIncrementMs;
private long seekForwardIncrementMs;
private LivePlaybackSpeedControl livePlaybackSpeedControl;
private long releaseTimeoutMs;
private long detachSurfaceTimeoutMs;
@ -167,8 +167,8 @@ public class SimpleExoPlayer extends BasePlayer
* <li>{@link C.VideoScalingMode}: {@link C#VIDEO_SCALING_MODE_DEFAULT}
* <li>{@code useLazyPreparation}: {@code true}
* <li>{@link SeekParameters}: {@link SeekParameters#DEFAULT}
* <li>{@code seekForwardIncrementMs}: {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}
* <li>{@code seekBackIncrementMs}: {@link C#DEFAULT_SEEK_BACK_INCREMENT_MS}
* <li>{@code seekForwardIncrementMs}: {@link C#DEFAULT_SEEK_FORWARD_INCREMENT_MS}
* <li>{@code releaseTimeoutMs}: {@link ExoPlayer#DEFAULT_RELEASE_TIMEOUT_MS}
* <li>{@code detachSurfaceTimeoutMs}: {@link #DEFAULT_DETACH_SURFACE_TIMEOUT_MS}
* <li>{@code pauseAtEndOfMediaItems}: {@code false}
@ -266,8 +266,8 @@ public class SimpleExoPlayer extends BasePlayer
videoScalingMode = C.VIDEO_SCALING_MODE_DEFAULT;
useLazyPreparation = true;
seekParameters = SeekParameters.DEFAULT;
seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS;
seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS;
seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS;
livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder().build();
clock = Clock.DEFAULT;
releaseTimeoutMs = ExoPlayer.DEFAULT_RELEASE_TIMEOUT_MS;
@ -503,21 +503,6 @@ public class SimpleExoPlayer extends BasePlayer
return this;
}
/**
* Sets the {@link #seekForward()} increment.
*
* @param seekForwardIncrementMs The seek forward increment, in milliseconds.
* @return This builder.
* @throws IllegalArgumentException If {@code seekForwardIncrementMs} is non-positive.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public Builder setSeekForwardIncrementMs(@IntRange(from = 1) long seekForwardIncrementMs) {
checkArgument(seekForwardIncrementMs > 0);
Assertions.checkState(!buildCalled);
this.seekForwardIncrementMs = seekForwardIncrementMs;
return this;
}
/**
* Sets the {@link #seekBack()} increment.
*
@ -533,6 +518,21 @@ public class SimpleExoPlayer extends BasePlayer
return this;
}
/**
* Sets the {@link #seekForward()} increment.
*
* @param seekForwardIncrementMs The seek forward increment, in milliseconds.
* @return This builder.
* @throws IllegalArgumentException If {@code seekForwardIncrementMs} is non-positive.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
public Builder setSeekForwardIncrementMs(@IntRange(from = 1) long seekForwardIncrementMs) {
checkArgument(seekForwardIncrementMs > 0);
Assertions.checkState(!buildCalled);
this.seekForwardIncrementMs = seekForwardIncrementMs;
return this;
}
/**
* Sets a timeout for calls to {@link #release} and {@link #setForegroundMode}.
*
@ -762,8 +762,8 @@ public class SimpleExoPlayer extends BasePlayer
analyticsCollector,
builder.useLazyPreparation,
builder.seekParameters,
builder.seekForwardIncrementMs,
builder.seekBackIncrementMs,
builder.seekForwardIncrementMs,
builder.livePlaybackSpeedControl,
builder.releaseTimeoutMs,
builder.pauseAtEndOfMediaItems,
@ -1602,18 +1602,18 @@ public class SimpleExoPlayer extends BasePlayer
player.seekTo(windowIndex, positionMs);
}
@Override
public long getSeekForwardIncrement() {
verifyApplicationThread();
return player.getSeekForwardIncrement();
}
@Override
public long getSeekBackIncrement() {
verifyApplicationThread();
return player.getSeekBackIncrement();
}
@Override
public long getSeekForwardIncrement() {
verifyApplicationThread();
return player.getSeekForwardIncrement();
}
@Override
public int getMaxSeekToPreviousPosition() {
verifyApplicationThread();

View file

@ -742,15 +742,6 @@ public class AnalyticsCollector
listener -> listener.onPlaybackParametersChanged(eventTime, playbackParameters));
}
@Override
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
sendEvent(
eventTime,
AnalyticsListener.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
listener -> listener.onSeekForwardIncrementChanged(eventTime, seekForwardIncrementMs));
}
@Override
public void onSeekBackIncrementChanged(long seekBackIncrementMs) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
@ -760,6 +751,15 @@ public class AnalyticsCollector
listener -> listener.onSeekBackIncrementChanged(eventTime, seekBackIncrementMs));
}
@Override
public void onSeekForwardIncrementChanged(long seekForwardIncrementMs) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
sendEvent(
eventTime,
AnalyticsListener.EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
listener -> listener.onSeekForwardIncrementChanged(eventTime, seekForwardIncrementMs));
}
@Override
public void onMaxSeekToPreviousPositionChanged(int maxSeekToPreviousPositionMs) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();

View file

@ -172,8 +172,8 @@ public interface AnalyticsListener {
EVENT_AVAILABLE_COMMANDS_CHANGED,
EVENT_MEDIA_METADATA_CHANGED,
EVENT_PLAYLIST_METADATA_CHANGED,
EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
EVENT_SEEK_BACK_INCREMENT_CHANGED,
EVENT_SEEK_FORWARD_INCREMENT_CHANGED,
EVENT_LOAD_STARTED,
EVENT_LOAD_COMPLETED,
EVENT_LOAD_CANCELED,
@ -256,10 +256,10 @@ public interface AnalyticsListener {
int EVENT_MEDIA_METADATA_CHANGED = Player.EVENT_MEDIA_METADATA_CHANGED;
/** {@link Player#getPlaylistMetadata()} changed. */
int EVENT_PLAYLIST_METADATA_CHANGED = Player.EVENT_PLAYLIST_METADATA_CHANGED;
/** {@link Player#getSeekForwardIncrement()} changed. */
int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED;
/** {@link Player#getSeekBackIncrement()} changed. */
int EVENT_SEEK_BACK_INCREMENT_CHANGED = Player.EVENT_SEEK_BACK_INCREMENT_CHANGED;
/** {@link Player#getSeekForwardIncrement()} changed. */
int EVENT_SEEK_FORWARD_INCREMENT_CHANGED = Player.EVENT_SEEK_FORWARD_INCREMENT_CHANGED;
/** {@link Player#getMaxSeekToPreviousPosition()} changed. */
int EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED =
Player.EVENT_MAX_SEEK_TO_PREVIOUS_POSITION_CHANGED;
@ -598,14 +598,6 @@ public interface AnalyticsListener {
default void onPlaybackParametersChanged(
EventTime eventTime, PlaybackParameters playbackParameters) {}
/**
* Called when the seek forward increment changed.
*
* @param eventTime The event time.
* @param seekForwardIncrementMs The seek forward increment, in milliseconds.
*/
default void onSeekForwardIncrementChanged(EventTime eventTime, long seekForwardIncrementMs) {}
/**
* Called when the seek back increment changed.
*
@ -614,6 +606,14 @@ public interface AnalyticsListener {
*/
default void onSeekBackIncrementChanged(EventTime eventTime, long seekBackIncrementMs) {}
/**
* Called when the seek forward increment changed.
*
* @param eventTime The event time.
* @param seekForwardIncrementMs The seek forward increment, in milliseconds.
*/
default void onSeekForwardIncrementChanged(EventTime eventTime, long seekForwardIncrementMs) {}
/**
* Called when the maximum position for which {@link Player#seekToPrevious()} seeks to the
* previous window changes.

View file

@ -8167,8 +8167,8 @@ public final class ExoPlayerTest {
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isTrue();
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isTrue();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SET_SPEED_AND_PITCH)).isTrue();
assertThat(player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE)).isTrue();
assertThat(player.isCommandAvailable(COMMAND_SET_REPEAT_MODE)).isTrue();
@ -8216,8 +8216,8 @@ public final class ExoPlayerTest {
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT_WINDOW)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS_WINDOW)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
}
@Test
@ -8236,8 +8236,8 @@ public final class ExoPlayerTest {
runUntilPlaybackState(player, Player.STATE_READY);
assertThat(player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_BACK)).isFalse();
assertThat(player.isCommandAvailable(COMMAND_SEEK_FORWARD)).isFalse();
}
@Test
@ -8325,20 +8325,20 @@ public final class ExoPlayerTest {
Player.Commands commandsWithSeekInCurrentAndToNext =
createWithDefaultCommands(
COMMAND_SEEK_IN_CURRENT_WINDOW,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_BACK,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_TO_NEXT_WINDOW);
Player.Commands commandsWithSeekInCurrentAndToPrevious =
createWithDefaultCommands(
COMMAND_SEEK_IN_CURRENT_WINDOW,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_BACK,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_TO_PREVIOUS_WINDOW);
Player.Commands commandsWithSeekAnywhere =
createWithDefaultCommands(
COMMAND_SEEK_IN_CURRENT_WINDOW,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_BACK,
COMMAND_SEEK_FORWARD,
COMMAND_SEEK_TO_NEXT_WINDOW,
COMMAND_SEEK_TO_PREVIOUS_WINDOW);
Player.Listener mockListener = mock(Player.Listener.class);
@ -10381,65 +10381,6 @@ public final class ExoPlayerTest {
player.release();
}
@Test
public void seekForward_callsOnPositionDiscontinuity() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Player.Listener listener = mock(Player.Listener.class);
player.addListener(listener);
Timeline fakeTimeline =
new FakeTimeline(
new TimelineWindowDefinition(
/* isSeekable= */ true,
/* isDynamic= */ true,
/* durationUs= */ C.msToUs(2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
player.seekForward();
ArgumentCaptor<Player.PositionInfo> oldPosition =
ArgumentCaptor.forClass(Player.PositionInfo.class);
ArgumentCaptor<Player.PositionInfo> newPosition =
ArgumentCaptor.forClass(Player.PositionInfo.class);
verify(listener, never())
.onPositionDiscontinuity(any(), any(), not(eq(Player.DISCONTINUITY_REASON_SEEK)));
verify(listener)
.onPositionDiscontinuity(
oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK));
List<Player.PositionInfo> oldPositions = oldPosition.getAllValues();
List<Player.PositionInfo> newPositions = newPosition.getAllValues();
assertThat(oldPositions.get(0).windowIndex).isEqualTo(0);
assertThat(oldPositions.get(0).positionMs).isEqualTo(0);
assertThat(oldPositions.get(0).contentPositionMs).isEqualTo(0);
assertThat(newPositions.get(0).windowIndex).isEqualTo(0);
assertThat(newPositions.get(0).positionMs).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS);
assertThat(newPositions.get(0).contentPositionMs)
.isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS);
player.release();
}
@Test
public void seekForward_pastDuration_seeksToDuration() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Timeline fakeTimeline =
new FakeTimeline(
new TimelineWindowDefinition(
/* isSeekable= */ true,
/* isDynamic= */ true,
/* durationUs= */ C.msToUs(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
player.seekForward();
assertThat(player.getCurrentPosition()).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2);
player.release();
}
@Test
public void seekBack_callsOnPositionDiscontinuity() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
@ -10510,6 +10451,65 @@ public final class ExoPlayerTest {
player.release();
}
@Test
public void seekForward_callsOnPositionDiscontinuity() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Player.Listener listener = mock(Player.Listener.class);
player.addListener(listener);
Timeline fakeTimeline =
new FakeTimeline(
new TimelineWindowDefinition(
/* isSeekable= */ true,
/* isDynamic= */ true,
/* durationUs= */ C.msToUs(2 * C.DEFAULT_SEEK_FORWARD_INCREMENT_MS)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
player.seekForward();
ArgumentCaptor<Player.PositionInfo> oldPosition =
ArgumentCaptor.forClass(Player.PositionInfo.class);
ArgumentCaptor<Player.PositionInfo> newPosition =
ArgumentCaptor.forClass(Player.PositionInfo.class);
verify(listener, never())
.onPositionDiscontinuity(any(), any(), not(eq(Player.DISCONTINUITY_REASON_SEEK)));
verify(listener)
.onPositionDiscontinuity(
oldPosition.capture(), newPosition.capture(), eq(Player.DISCONTINUITY_REASON_SEEK));
List<Player.PositionInfo> oldPositions = oldPosition.getAllValues();
List<Player.PositionInfo> newPositions = newPosition.getAllValues();
assertThat(oldPositions.get(0).windowIndex).isEqualTo(0);
assertThat(oldPositions.get(0).positionMs).isEqualTo(0);
assertThat(oldPositions.get(0).contentPositionMs).isEqualTo(0);
assertThat(newPositions.get(0).windowIndex).isEqualTo(0);
assertThat(newPositions.get(0).positionMs).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS);
assertThat(newPositions.get(0).contentPositionMs)
.isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS);
player.release();
}
@Test
public void seekForward_pastDuration_seeksToDuration() throws Exception {
ExoPlayer player = new TestExoPlayerBuilder(context).build();
Timeline fakeTimeline =
new FakeTimeline(
new TimelineWindowDefinition(
/* isSeekable= */ true,
/* isDynamic= */ true,
/* durationUs= */ C.msToUs(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2)));
player.setMediaSource(new FakeMediaSource(fakeTimeline));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
player.seekForward();
assertThat(player.getCurrentPosition()).isEqualTo(C.DEFAULT_SEEK_FORWARD_INCREMENT_MS / 2);
player.release();
}
@Test
public void seekToPrevious_withPreviousWindowAndCloseToStart_seeksToPreviousWindow() {
ExoPlayer player = new TestExoPlayerBuilder(context).build();

View file

@ -300,12 +300,12 @@ public class StubExoPlayer extends BasePlayer implements ExoPlayer {
}
@Override
public long getSeekForwardIncrement() {
public long getSeekBackIncrement() {
throw new UnsupportedOperationException();
}
@Override
public long getSeekBackIncrement() {
public long getSeekForwardIncrement() {
throw new UnsupportedOperationException();
}