Add repeat mode mechanics to Exoplayer.

(Relating to GitHub Issue #2577)

All getter, setter and callbacks have been added and value of repeatMode is
passed to getNextXXXIndex methods.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=155071985
This commit is contained in:
tonihei 2017-05-04 06:11:12 -07:00 committed by Oliver Woodman
parent 3a5548d72a
commit 4d1826dd3d
14 changed files with 134 additions and 16 deletions

View File

@ -95,6 +95,11 @@ import java.util.Locale;
+ getStateString(state) + "]");
}
@Override
public void onRepeatModeChanged(@ExoPlayer.RepeatMode int repeatMode) {
Log.d(TAG, "repeatMode [" + getRepeatModeString(repeatMode) + "]");
}
@Override
public void onPositionDiscontinuity() {
Log.d(TAG, "positionDiscontinuity");
@ -461,4 +466,12 @@ import java.util.Locale;
return enabled ? "[X]" : "[ ]";
}
private static String getRepeatModeString(@ExoPlayer.RepeatMode int repeatMode) {
switch (repeatMode) {
case ExoPlayer.REPEAT_MODE_OFF:
return "OFF";
default:
return "?";
}
}
}

View File

@ -424,6 +424,11 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
updateButtonVisibilities();
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
if (needRetrySource) {

View File

@ -126,6 +126,11 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
private void releasePlayerAndQuitLooper() {
player.release();
Looper.myLooper().quit();

View File

@ -126,6 +126,11 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
private void releasePlayerAndQuitLooper() {
player.release();
Looper.myLooper().quit();

View File

@ -158,6 +158,11 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
private void releasePlayerAndQuitLooper() {
player.release();
Looper.myLooper().quit();

View File

@ -340,6 +340,11 @@ public final class ExoPlayerTest extends TestCase {
}
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
sourceInfos.add(Pair.create(timeline, manifest));

View File

@ -154,6 +154,13 @@ public interface ExoPlayer {
*/
void onPlayerStateChanged(boolean playWhenReady, int playbackState);
/**
* Called when the value of {@link #getRepeatMode()} changes.
*
* @param repeatMode The {@link RepeatMode} used for playback.
*/
void onRepeatModeChanged(@RepeatMode int repeatMode);
/**
* Called when an error occurs. The playback state will transition to {@link #STATE_IDLE}
* immediately after this method is called. The player instance can still be used, and
@ -262,7 +269,7 @@ public interface ExoPlayer {
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({REPEAT_MODE_OFF})
@interface RepeatMode {}
public @interface RepeatMode {}
/**
* Normal playback without repetition.
*/
@ -328,6 +335,20 @@ public interface ExoPlayer {
*/
boolean getPlayWhenReady();
/**
* Sets the {@link RepeatMode} to be used for playback.
*
* @param repeatMode A repeat mode.
*/
void setRepeatMode(@RepeatMode int repeatMode);
/**
* Returns the current {@link RepeatMode} used for playback.
*
* @return The current repeat mode.
*/
@RepeatMode int getRepeatMode();
/**
* Whether the player is currently loading the source.
*

View File

@ -51,6 +51,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
private boolean tracksSelected;
private boolean playWhenReady;
@RepeatMode int repeatMode;
private int playbackState;
private int pendingSeekAcks;
private int pendingPrepareAcks;
@ -83,6 +84,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
this.renderers = Assertions.checkNotNull(renderers);
this.trackSelector = Assertions.checkNotNull(trackSelector);
this.playWhenReady = false;
this.repeatMode = REPEAT_MODE_OFF;
this.playbackState = STATE_IDLE;
this.listeners = new CopyOnWriteArraySet<>();
emptyTrackSelections = new TrackSelectionArray(new TrackSelection[renderers.length]);
@ -101,7 +103,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
};
playbackInfo = new ExoPlayerImplInternal.PlaybackInfo(0, 0);
internalPlayer = new ExoPlayerImplInternal(renderers, trackSelector, loadControl, playWhenReady,
eventHandler, playbackInfo, this);
repeatMode, eventHandler, playbackInfo, this);
}
@Override
@ -164,6 +166,22 @@ import java.util.concurrent.CopyOnWriteArraySet;
return playWhenReady;
}
@Override
public void setRepeatMode(@RepeatMode int repeatMode) {
if (this.repeatMode != repeatMode) {
this.repeatMode = repeatMode;
internalPlayer.setRepeatMode(repeatMode);
for (EventListener listener : listeners) {
listener.onRepeatModeChanged(repeatMode);
}
}
}
@Override
public @RepeatMode int getRepeatMode() {
return repeatMode;
}
@Override
public boolean isLoading() {
return isLoading;

View File

@ -112,6 +112,7 @@ import java.io.IOException;
private static final int MSG_SOURCE_CONTINUE_LOADING_REQUESTED = 9;
private static final int MSG_TRACK_SELECTION_INVALIDATED = 10;
private static final int MSG_CUSTOM = 11;
private static final int MSG_SET_REPEAT_MODE = 12;
private static final int PREPARING_SOURCE_INTERVAL_MS = 10;
private static final int RENDERING_INTERVAL_MS = 10;
@ -155,6 +156,7 @@ import java.io.IOException;
private boolean rebuffering;
private boolean isLoading;
private int state;
private @ExoPlayer.RepeatMode int repeatMode;
private int customMessagesSent;
private int customMessagesProcessed;
private long elapsedRealtimeUs;
@ -170,12 +172,13 @@ import java.io.IOException;
private Timeline timeline;
public ExoPlayerImplInternal(Renderer[] renderers, TrackSelector trackSelector,
LoadControl loadControl, boolean playWhenReady, Handler eventHandler,
PlaybackInfo playbackInfo, ExoPlayer player) {
LoadControl loadControl, boolean playWhenReady, @ExoPlayer.RepeatMode int repeatMode,
Handler eventHandler, PlaybackInfo playbackInfo, ExoPlayer player) {
this.renderers = renderers;
this.trackSelector = trackSelector;
this.loadControl = loadControl;
this.playWhenReady = playWhenReady;
this.repeatMode = repeatMode;
this.eventHandler = eventHandler;
this.state = ExoPlayer.STATE_IDLE;
this.playbackInfo = playbackInfo;
@ -210,6 +213,10 @@ import java.io.IOException;
handler.obtainMessage(MSG_SET_PLAY_WHEN_READY, playWhenReady ? 1 : 0, 0).sendToTarget();
}
public void setRepeatMode(@ExoPlayer.RepeatMode int repeatMode) {
handler.obtainMessage(MSG_SET_REPEAT_MODE, repeatMode, 0).sendToTarget();
}
public void seekTo(Timeline timeline, int windowIndex, long positionUs) {
handler.obtainMessage(MSG_SEEK_TO, new SeekPosition(timeline, windowIndex, positionUs))
.sendToTarget();
@ -304,6 +311,10 @@ import java.io.IOException;
setPlayWhenReadyInternal(msg.arg1 != 0);
return true;
}
case MSG_SET_REPEAT_MODE: {
setRepeatModeInternal(msg.arg1);
return true;
}
case MSG_DO_SOME_WORK: {
doSomeWork();
return true;
@ -411,6 +422,10 @@ import java.io.IOException;
}
}
private void setRepeatModeInternal(@ExoPlayer.RepeatMode int repeatMode) {
this.repeatMode = repeatMode;
}
private void startRenderers() throws ExoPlaybackException {
rebuffering = false;
standaloneMediaClock.start();
@ -959,8 +974,7 @@ import java.io.IOException;
while (periodHolder.next != null) {
MediaPeriodHolder previousPeriodHolder = periodHolder;
periodHolder = periodHolder.next;
periodIndex = timeline.getNextPeriodIndex(periodIndex, period, window,
ExoPlayer.REPEAT_MODE_OFF);
periodIndex = timeline.getNextPeriodIndex(periodIndex, period, window, repeatMode);
boolean isLastPeriod = isLastPeriod(periodIndex);
timeline.getPeriod(periodIndex, period, true);
if (periodHolder.uid.equals(period.uid)) {
@ -1022,8 +1036,7 @@ import java.io.IOException;
int newPeriodIndex = C.INDEX_UNSET;
int maxIterations = oldTimeline.getPeriodCount();
for (int i = 0; i < maxIterations && newPeriodIndex == C.INDEX_UNSET; i++) {
oldPeriodIndex = oldTimeline.getNextPeriodIndex(oldPeriodIndex, period, window,
ExoPlayer.REPEAT_MODE_OFF);
oldPeriodIndex = oldTimeline.getNextPeriodIndex(oldPeriodIndex, period, window, repeatMode);
newPeriodIndex = newTimeline.getIndexOfPeriod(
oldTimeline.getPeriod(oldPeriodIndex, period, true).uid);
}
@ -1033,7 +1046,7 @@ import java.io.IOException;
private boolean isLastPeriod(int periodIndex) {
int windowIndex = timeline.getPeriod(periodIndex, period).windowIndex;
return !timeline.getWindow(windowIndex, window).isDynamic
&& timeline.isLastPeriod(periodIndex, period, window, ExoPlayer.REPEAT_MODE_OFF);
&& timeline.isLastPeriod(periodIndex, period, window, repeatMode);
}
/**
@ -1247,7 +1260,7 @@ import java.io.IOException;
return;
}
newLoadingPeriodIndex = timeline.getNextPeriodIndex(loadingPeriodHolder.index, period, window,
ExoPlayer.REPEAT_MODE_OFF);
repeatMode);
}
if (newLoadingPeriodIndex >= timeline.getPeriodCount()) {

View File

@ -514,6 +514,16 @@ public class SimpleExoPlayer implements ExoPlayer {
return player.getPlayWhenReady();
}
@Override
public @RepeatMode int getRepeatMode() {
return player.getRepeatMode();
}
@Override
public void setRepeatMode(@RepeatMode int repeatMode) {
player.setRepeatMode(repeatMode);
}
@Override
public boolean isLoading() {
return player.isLoading();

View File

@ -86,6 +86,11 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
updateAndPost();
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
updateAndPost();

View File

@ -529,10 +529,9 @@ public class PlaybackControlView extends FrameLayout {
int windowIndex = player.getCurrentWindowIndex();
timeline.getWindow(windowIndex, window);
isSeekable = window.isSeekable;
enablePrevious = !timeline.isFirstWindow(windowIndex, ExoPlayer.REPEAT_MODE_OFF)
enablePrevious = !timeline.isFirstWindow(windowIndex, player.getRepeatMode())
|| isSeekable || !window.isDynamic;
enableNext = !timeline.isLastWindow(windowIndex, ExoPlayer.REPEAT_MODE_OFF)
|| window.isDynamic;
enableNext = !timeline.isLastWindow(windowIndex, player.getRepeatMode()) || window.isDynamic;
if (timeline.getPeriod(player.getCurrentPeriodIndex(), period).isAd) {
// Always hide player controls during ads.
hide();
@ -682,8 +681,7 @@ public class PlaybackControlView extends FrameLayout {
}
int windowIndex = player.getCurrentWindowIndex();
timeline.getWindow(windowIndex, window);
int previousWindowIndex = timeline.getPreviousWindowIndex(windowIndex,
ExoPlayer.REPEAT_MODE_OFF);
int previousWindowIndex = timeline.getPreviousWindowIndex(windowIndex, player.getRepeatMode());
if (previousWindowIndex != C.INDEX_UNSET
&& (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS
|| (window.isDynamic && !window.isSeekable))) {
@ -699,7 +697,7 @@ public class PlaybackControlView extends FrameLayout {
return;
}
int windowIndex = player.getCurrentWindowIndex();
int nextWindowIndex = timeline.getNextWindowIndex(windowIndex, ExoPlayer.REPEAT_MODE_OFF);
int nextWindowIndex = timeline.getNextWindowIndex(windowIndex, player.getRepeatMode());
if (nextWindowIndex != C.INDEX_UNSET) {
seekTo(nextWindowIndex, C.TIME_UNSET);
} else if (timeline.getWindow(windowIndex, window, false).isDynamic) {
@ -908,6 +906,11 @@ public class PlaybackControlView extends FrameLayout {
updateProgress();
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
updateNavigation();

View File

@ -806,6 +806,11 @@ public final class SimpleExoPlayerView extends FrameLayout {
maybeShowController(false);
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPlayerError(ExoPlaybackException e) {
// Do nothing.

View File

@ -213,6 +213,11 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
this.playing = playing;
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public final void onPlayerError(ExoPlaybackException error) {
playerWasPrepared = true;