Commit 4d1826dd by tonihei Committed by Oliver Woodman

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
parent 3a5548d7
......@@ -96,6 +96,11 @@ import java.util.Locale;
}
@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 "?";
}
}
}
......@@ -425,6 +425,11 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
if (needRetrySource) {
// This will only occur if the user has performed a seek whilst in the error state. Update the
......
......@@ -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();
......
......@@ -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();
......
......@@ -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();
......
......@@ -341,6 +341,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));
sourceInfoCountDownLatch.countDown();
......
......@@ -155,6 +155,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
* {@link #release()} must still be called on the player should it no longer be required.
......@@ -262,7 +269,7 @@ public interface ExoPlayer {
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({REPEAT_MODE_OFF})
@interface RepeatMode {}
public @interface RepeatMode {}
/**
* Normal playback without repetition.
*/
......@@ -329,6 +336,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.
*
* @return Whether the player is currently loading the source.
......
......@@ -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
......@@ -165,6 +167,22 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
@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;
}
......
......@@ -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()) {
......
......@@ -515,6 +515,16 @@ public class SimpleExoPlayer implements ExoPlayer {
}
@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();
}
......
......@@ -87,6 +87,11 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
updateAndPost();
}
......
......@@ -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) {
......@@ -909,6 +907,11 @@ public class PlaybackControlView extends FrameLayout {
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPositionDiscontinuity() {
updateNavigation();
updateProgress();
......
......@@ -807,6 +807,11 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public void onPlayerError(ExoPlaybackException e) {
// Do nothing.
}
......
......@@ -214,6 +214,11 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
}
@Override
public void onRepeatModeChanged(int repeatMode) {
// Do nothing.
}
@Override
public final void onPlayerError(ExoPlaybackException error) {
playerWasPrepared = true;
playerError = error;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment