From 4f5ac9e04f192ebacc425754e494a9f380a1b79f Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Tue, 18 Jul 2017 10:04:10 -0700 Subject: [PATCH] Extract Player interface from ExoPlayer This is the first step towards facilitating Cast integration to ExoPlayer. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=162366198 --- .../exoplayer2/demo/PlayerActivity.java | 3 +- .../mediasession/MediaSessionConnector.java | 19 +- .../RepeatModeActionProvider.java | 7 +- .../DynamicConcatenatingMediaSourceTest.java | 5 +- .../google/android/exoplayer2/ExoPlayer.java | 379 ++--------------- .../android/exoplayer2/ExoPlayerImpl.java | 32 +- .../exoplayer2/MediaPeriodInfoSequence.java | 2 +- .../com/google/android/exoplayer2/Player.java | 395 ++++++++++++++++++ .../android/exoplayer2/SimpleExoPlayer.java | 4 +- .../source/ClippingMediaSource.java | 2 +- .../exoplayer2/ui/PlaybackControlView.java | 73 ++-- 11 files changed, 497 insertions(+), 424 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/Player.java diff --git a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index c59ef40cdb..d498b8f0c4 100644 --- a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -39,6 +39,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player.EventListener; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; @@ -82,7 +83,7 @@ import java.util.UUID; /** * An activity that plays media using {@link SimpleExoPlayer}. */ -public class PlayerActivity extends Activity implements OnClickListener, ExoPlayer.EventListener, +public class PlayerActivity extends Activity implements OnClickListener, EventListener, PlaybackControlView.VisibilityListener { public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid"; diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index 55f056aec0..0f96e5104f 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -35,6 +35,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.TrackGroupArray; @@ -484,7 +485,7 @@ public final class MediaSessionConnector { Pair message = errorMessageProvider.getErrorMessage(playbackException); builder.setErrorMessage(message.first, message.second); } - if (player.getPlaybackState() != ExoPlayer.STATE_IDLE) { + if (player.getPlaybackState() != Player.STATE_IDLE) { playbackException = null; } } @@ -507,7 +508,7 @@ public final class MediaSessionConnector { if (queue == null || queue.size() < 2) { removePlaybackActions(PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS); - } else if (player.getRepeatMode() != ExoPlayer.REPEAT_MODE_OFF) { + } else if (player.getRepeatMode() != Player.REPEAT_MODE_OFF) { addPlaybackActions(PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS); } else if (activeQueueItemId == queue.get(0).getQueueId()) { @@ -576,11 +577,11 @@ public final class MediaSessionConnector { private int mapPlaybackState(int exoPlayerPlaybackState, boolean playWhenReady) { switch (exoPlayerPlaybackState) { - case ExoPlayer.STATE_BUFFERING: + case Player.STATE_BUFFERING: return PlaybackStateCompat.STATE_BUFFERING; - case ExoPlayer.STATE_READY: + case Player.STATE_READY: return playWhenReady ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED; - case ExoPlayer.STATE_ENDED: + case Player.STATE_ENDED: return PlaybackStateCompat.STATE_PAUSED; default: return PlaybackStateCompat.STATE_NONE; @@ -599,7 +600,7 @@ public final class MediaSessionConnector { return playbackPreparer != null && isActionPublished(action); } - private class ExoPlayerEventListener implements ExoPlayer.EventListener { + private class ExoPlayerEventListener implements Player.EventListener { @Override public void onTimelineChanged(Timeline timeline, Object manifest) { if (queueNavigator != null) { @@ -625,9 +626,9 @@ public final class MediaSessionConnector { } @Override - public void onRepeatModeChanged(@ExoPlayer.RepeatMode int repeatMode) { - mediaSession.setRepeatMode(repeatMode == ExoPlayer.REPEAT_MODE_ONE - ? PlaybackStateCompat.REPEAT_MODE_ONE : repeatMode == ExoPlayer.REPEAT_MODE_ALL + public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { + mediaSession.setRepeatMode(repeatMode == Player.REPEAT_MODE_ONE + ? PlaybackStateCompat.REPEAT_MODE_ONE : repeatMode == Player.REPEAT_MODE_ALL ? PlaybackStateCompat.REPEAT_MODE_ALL : PlaybackStateCompat.REPEAT_MODE_NONE); updateMediaSessionPlaybackState(); } diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java index c0124d69d6..62dcb29235 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/RepeatModeActionProvider.java @@ -19,6 +19,7 @@ import android.content.Context; import android.os.Bundle; import android.support.v4.media.session.PlaybackStateCompat; import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.util.RepeatModeUtil; /** @@ -81,15 +82,15 @@ public final class RepeatModeActionProvider implements MediaSessionConnector.Cus CharSequence actionLabel; int iconResourceId; switch (player.getRepeatMode()) { - case ExoPlayer.REPEAT_MODE_ONE: + case Player.REPEAT_MODE_ONE: actionLabel = repeatOneDescription; iconResourceId = R.drawable.exo_media_action_repeat_one; break; - case ExoPlayer.REPEAT_MODE_ALL: + case Player.REPEAT_MODE_ALL: actionLabel = repeatAllDescription; iconResourceId = R.drawable.exo_media_action_repeat_all; break; - case ExoPlayer.REPEAT_MODE_OFF: + case Player.REPEAT_MODE_OFF: default: actionLabel = repeatOffDescription; iconResourceId = R.drawable.exo_media_action_repeat_off; diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java index 477577c476..daa454ad14 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/source/DynamicConcatenatingMediaSourceTest.java @@ -23,6 +23,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource.Listener; import com.google.android.exoplayer2.testutil.FakeMediaSource; @@ -352,12 +353,12 @@ public final class DynamicConcatenatingMediaSourceTest extends TestCase { } @Override - public void addListener(EventListener listener) { + public void addListener(Player.EventListener listener) { throw new UnsupportedOperationException(); } @Override - public void removeListener(EventListener listener) { + public void removeListener(Player.EventListener listener) { throw new UnsupportedOperationException(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index 84b4c8bcf3..e0f3290088 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -16,8 +16,6 @@ package com.google.android.exoplayer2; import android.os.Looper; -import android.support.annotation.IntDef; -import android.support.annotation.Nullable; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.ConcatenatingMediaSource; @@ -25,15 +23,11 @@ import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MergingMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; -import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.video.MediaCodecVideoRenderer; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; /** * An extensible media player exposing traditional high-level media player functionality, such as @@ -108,91 +102,13 @@ import java.lang.annotation.RetentionPolicy; * may use a background thread to load data. These are implementation specific. * */ -public interface ExoPlayer { +public interface ExoPlayer extends Player { /** - * Listener of changes in player state. + * @deprecated Use {@link Player.EventListener} instead. */ - interface EventListener { - - /** - * Called when the timeline and/or manifest has been refreshed. - *

- * Note that if the timeline has changed then a position discontinuity may also have occurred. - * For example, the current period index may have changed as a result of periods being added or - * removed from the timeline. This will not be reported via a separate call to - * {@link #onPositionDiscontinuity()}. - * - * @param timeline The latest timeline. Never null, but may be empty. - * @param manifest The latest manifest. May be null. - */ - void onTimelineChanged(Timeline timeline, Object manifest); - - /** - * Called when the available or selected tracks change. - * - * @param trackGroups The available tracks. Never null, but may be of length zero. - * @param trackSelections The track selections for each {@link Renderer}. Never null and always - * of length {@link #getRendererCount()}, but may contain null elements. - */ - void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections); - - /** - * Called when the player starts or stops loading the source. - * - * @param isLoading Whether the source is currently being loaded. - */ - void onLoadingChanged(boolean isLoading); - - /** - * Called when the value returned from either {@link #getPlayWhenReady()} or - * {@link #getPlaybackState()} changes. - * - * @param playWhenReady Whether playback will proceed when ready. - * @param playbackState One of the {@code STATE} constants defined in the {@link ExoPlayer} - * interface. - */ - 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. - * - * @param error The error. - */ - void onPlayerError(ExoPlaybackException error); - - /** - * Called when a position discontinuity occurs without a change to the timeline. A position - * discontinuity occurs when the current window or period index changes (as a result of playback - * transitioning from one period in the timeline to the next), or when the playback position - * jumps within the period currently being played (as a result of a seek being performed, or - * when the source introduces a discontinuity internally). - *

- * When a position discontinuity occurs as a result of a change to the timeline this method is - * not called. {@link #onTimelineChanged(Timeline, Object)} is called in this case. - */ - void onPositionDiscontinuity(); - - /** - * Called when the current playback parameters change. The playback parameters may change due to - * a call to {@link ExoPlayer#setPlaybackParameters(PlaybackParameters)}, or the player itself - * may change them (for example, if audio playback switches to passthrough mode, where speed - * adjustment is no longer possible). - * - * @param playbackParameters The playback parameters. - */ - void onPlaybackParametersChanged(PlaybackParameters playbackParameters); - - } + @Deprecated + interface EventListener extends Player.EventListener {} /** * A component of an {@link ExoPlayer} that can receive messages on the playback thread. @@ -245,43 +161,41 @@ public interface ExoPlayer { } /** - * The player does not have a source to play, so it is neither buffering nor ready to play. + * @deprecated Use {@link Player#STATE_IDLE} instead. */ - int STATE_IDLE = 1; + @Deprecated + int STATE_IDLE = Player.STATE_IDLE; /** - * The player not able to immediately play from the current position. The cause is - * {@link Renderer} specific, but this state typically occurs when more data needs to be - * loaded to be ready to play, or more data needs to be buffered for playback to resume. + * @deprecated Use {@link Player#STATE_BUFFERING} instead. */ - int STATE_BUFFERING = 2; + @Deprecated + int STATE_BUFFERING = Player.STATE_BUFFERING; /** - * The player is able to immediately play from the current position. The player will be playing if - * {@link #getPlayWhenReady()} returns true, and paused otherwise. + * @deprecated Use {@link Player#STATE_READY} instead. */ - int STATE_READY = 3; + @Deprecated + int STATE_READY = Player.STATE_READY; /** - * The player has finished playing the media. + * @deprecated Use {@link Player#STATE_ENDED} instead. */ - int STATE_ENDED = 4; + @Deprecated + int STATE_ENDED = Player.STATE_ENDED; /** - * Repeat modes for playback. + * @deprecated Use {@link Player#REPEAT_MODE_OFF} instead. */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({REPEAT_MODE_OFF, REPEAT_MODE_ONE, REPEAT_MODE_ALL}) - public @interface RepeatMode {} + @Deprecated + @RepeatMode int REPEAT_MODE_OFF = Player.REPEAT_MODE_OFF; /** - * Normal playback without repetition. + * @deprecated Use {@link Player#REPEAT_MODE_ONE} instead. */ - int REPEAT_MODE_OFF = 0; + @Deprecated + @RepeatMode int REPEAT_MODE_ONE = Player.REPEAT_MODE_ONE; /** - * "Repeat One" mode to repeat the currently playing window infinitely. + * @deprecated Use {@link Player#REPEAT_MODE_ALL} instead. */ - int REPEAT_MODE_ONE = 1; - /** - * "Repeat All" mode to repeat the entire timeline infinitely. - */ - int REPEAT_MODE_ALL = 2; + @Deprecated + @RepeatMode int REPEAT_MODE_ALL = Player.REPEAT_MODE_ALL; /** * Gets the {@link Looper} associated with the playback thread. @@ -290,29 +204,6 @@ public interface ExoPlayer { */ Looper getPlaybackLooper(); - /** - * Register a listener to receive events from the player. The listener's methods will be called on - * the thread that was used to construct the player. However, if the thread used to construct the - * player does not have a {@link Looper}, then the listener will be called on the main thread. - * - * @param listener The listener to register. - */ - void addListener(EventListener listener); - - /** - * Unregister a listener. The listener will no longer receive events from the player. - * - * @param listener The listener to unregister. - */ - void removeListener(EventListener listener); - - /** - * Returns the current state of the player. - * - * @return One of the {@code STATE} constants defined in this interface. - */ - int getPlaybackState(); - /** * Prepares the player to play the provided {@link MediaSource}. Equivalent to * {@code prepare(mediaSource, true, true)}. @@ -333,118 +224,6 @@ public interface ExoPlayer { */ void prepare(MediaSource mediaSource, boolean resetPosition, boolean resetState); - /** - * Sets whether playback should proceed when {@link #getPlaybackState()} == {@link #STATE_READY}. - *

- * If the player is already in the ready state then this method can be used to pause and resume - * playback. - * - * @param playWhenReady Whether playback should proceed when ready. - */ - void setPlayWhenReady(boolean playWhenReady); - - /** - * Whether playback will proceed when {@link #getPlaybackState()} == {@link #STATE_READY}. - * - * @return Whether playback will proceed when ready. - */ - 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. - */ - boolean isLoading(); - - /** - * Seeks to the default position associated with the current window. The position can depend on - * the type of source passed to {@link #prepare(MediaSource)}. For live streams it will typically - * be the live edge of the window. For other streams it will typically be the start of the window. - */ - void seekToDefaultPosition(); - - /** - * Seeks to the default position associated with the specified window. The position can depend on - * the type of source passed to {@link #prepare(MediaSource)}. For live streams it will typically - * be the live edge of the window. For other streams it will typically be the start of the window. - * - * @param windowIndex The index of the window whose associated default position should be seeked - * to. - */ - void seekToDefaultPosition(int windowIndex); - - /** - * Seeks to a position specified in milliseconds in the current window. - * - * @param positionMs The seek position in the current window, or {@link C#TIME_UNSET} to seek to - * the window's default position. - */ - void seekTo(long positionMs); - - /** - * Seeks to a position specified in milliseconds in the specified window. - * - * @param windowIndex The index of the window. - * @param positionMs The seek position in the specified window, or {@link C#TIME_UNSET} to seek to - * the window's default position. - */ - void seekTo(int windowIndex, long positionMs); - - /** - * Attempts to set the playback parameters. Passing {@code null} sets the parameters to the - * default, {@link PlaybackParameters#DEFAULT}, which means there is no speed or pitch adjustment. - *

- * Playback parameters changes may cause the player to buffer. - * {@link EventListener#onPlaybackParametersChanged(PlaybackParameters)} will be called whenever - * the currently active playback parameters change. When that listener is called, the parameters - * passed to it may not match {@code playbackParameters}. For example, the chosen speed or pitch - * may be out of range, in which case they are constrained to a set of permitted values. If it is - * not possible to change the playback parameters, the listener will not be invoked. - * - * @param playbackParameters The playback parameters, or {@code null} to use the defaults. - */ - void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters); - - /** - * Returns the currently active playback parameters. - * - * @see EventListener#onPlaybackParametersChanged(PlaybackParameters) - */ - PlaybackParameters getPlaybackParameters(); - - /** - * Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention - * is to pause playback. - *

- * Calling this method will cause the playback state to transition to {@link #STATE_IDLE}. The - * player instance can still be used, and {@link #release()} must still be called on the player if - * it's no longer required. - *

- * Calling this method does not reset the playback position. - */ - void stop(); - - /** - * Releases the player. This method must be called when the player is no longer required. The - * player must not be used after calling this method. - */ - void release(); - /** * Sends messages to their target components. The messages are delivered on the playback thread. * If a component throws an {@link ExoPlaybackException} then it is propagated out of the player @@ -462,112 +241,4 @@ public interface ExoPlayer { */ void blockingSendMessages(ExoPlayerMessage... messages); - /** - * Returns the number of renderers. - */ - int getRendererCount(); - - /** - * Returns the track type that the renderer at a given index handles. - * - * @see Renderer#getTrackType() - * @param index The index of the renderer. - * @return One of the {@code TRACK_TYPE_*} constants defined in {@link C}. - */ - int getRendererType(int index); - - /** - * Returns the available track groups. - */ - TrackGroupArray getCurrentTrackGroups(); - - /** - * Returns the current track selections for each renderer. - */ - TrackSelectionArray getCurrentTrackSelections(); - - /** - * Returns the current manifest. The type depends on the {@link MediaSource} passed to - * {@link #prepare}. May be null. - */ - Object getCurrentManifest(); - - /** - * Returns the current {@link Timeline}. Never null, but may be empty. - */ - Timeline getCurrentTimeline(); - - /** - * Returns the index of the period currently being played. - */ - int getCurrentPeriodIndex(); - - /** - * Returns the index of the window currently being played. - */ - int getCurrentWindowIndex(); - - /** - * Returns the duration of the current window in milliseconds, or {@link C#TIME_UNSET} if the - * duration is not known. - */ - long getDuration(); - - /** - * Returns the playback position in the current window, in milliseconds. - */ - long getCurrentPosition(); - - /** - * Returns an estimate of the position in the current window up to which data is buffered, in - * milliseconds. - */ - long getBufferedPosition(); - - /** - * Returns an estimate of the percentage in the current window up to which data is buffered, or 0 - * if no estimate is available. - */ - int getBufferedPercentage(); - - /** - * Returns whether the current window is dynamic, or {@code false} if the {@link Timeline} is - * empty. - * - * @see Timeline.Window#isDynamic - */ - boolean isCurrentWindowDynamic(); - - /** - * Returns whether the current window is seekable, or {@code false} if the {@link Timeline} is - * empty. - * - * @see Timeline.Window#isSeekable - */ - boolean isCurrentWindowSeekable(); - - /** - * Returns whether the player is currently playing an ad. - */ - boolean isPlayingAd(); - - /** - * If {@link #isPlayingAd()} returns true, returns the index of the ad group in the period - * currently being played. Returns {@link C#INDEX_UNSET} otherwise. - */ - int getCurrentAdGroupIndex(); - - /** - * If {@link #isPlayingAd()} returns true, returns the index of the ad in its ad group. Returns - * {@link C#INDEX_UNSET} otherwise. - */ - int getCurrentAdIndexInAdGroup(); - - /** - * If {@link #isPlayingAd()} returns {@code true}, returns the content position that will be - * played once all ads in the ad group have finished playing, in milliseconds. If there is no ad - * playing, the returned position is the same as that returned by {@link #getCurrentPosition()}. - */ - long getContentPosition(); - } 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 20c0b744a4..d81e500349 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 @@ -46,7 +46,7 @@ import java.util.concurrent.CopyOnWriteArraySet; private final TrackSelectionArray emptyTrackSelections; private final Handler eventHandler; private final ExoPlayerImplInternal internalPlayer; - private final CopyOnWriteArraySet listeners; + private final CopyOnWriteArraySet listeners; private final Timeline.Window window; private final Timeline.Period period; @@ -114,12 +114,12 @@ import java.util.concurrent.CopyOnWriteArraySet; } @Override - public void addListener(EventListener listener) { + public void addListener(Player.EventListener listener) { listeners.add(listener); } @Override - public void removeListener(EventListener listener) { + public void removeListener(Player.EventListener listener) { listeners.remove(listener); } @@ -139,7 +139,7 @@ import java.util.concurrent.CopyOnWriteArraySet; if (!timeline.isEmpty() || manifest != null) { timeline = Timeline.EMPTY; manifest = null; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onTimelineChanged(timeline, manifest); } } @@ -148,7 +148,7 @@ import java.util.concurrent.CopyOnWriteArraySet; trackGroups = TrackGroupArray.EMPTY; trackSelections = emptyTrackSelections; trackSelector.onSelectionActivated(null); - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onTracksChanged(trackGroups, trackSelections); } } @@ -162,7 +162,7 @@ import java.util.concurrent.CopyOnWriteArraySet; if (this.playWhenReady != playWhenReady) { this.playWhenReady = playWhenReady; internalPlayer.setPlayWhenReady(playWhenReady); - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPlayerStateChanged(playWhenReady, playbackState); } } @@ -178,7 +178,7 @@ import java.util.concurrent.CopyOnWriteArraySet; if (this.repeatMode != repeatMode) { this.repeatMode = repeatMode; internalPlayer.setRepeatMode(repeatMode); - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onRepeatModeChanged(repeatMode); } } @@ -238,7 +238,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } else { maskingWindowPositionMs = positionMs; internalPlayer.seekTo(timeline, windowIndex, C.msToUs(positionMs)); - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPositionDiscontinuity(); } } @@ -420,14 +420,14 @@ import java.util.concurrent.CopyOnWriteArraySet; } case ExoPlayerImplInternal.MSG_STATE_CHANGED: { playbackState = msg.arg1; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPlayerStateChanged(playWhenReady, playbackState); } break; } case ExoPlayerImplInternal.MSG_LOADING_CHANGED: { isLoading = msg.arg1 != 0; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onLoadingChanged(isLoading); } break; @@ -439,7 +439,7 @@ import java.util.concurrent.CopyOnWriteArraySet; trackGroups = trackSelectorResult.groups; trackSelections = trackSelectorResult.selections; trackSelector.onSelectionActivated(trackSelectorResult.info); - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onTracksChanged(trackGroups, trackSelections); } } @@ -449,7 +449,7 @@ import java.util.concurrent.CopyOnWriteArraySet; if (--pendingSeekAcks == 0) { playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj; if (msg.arg1 != 0) { - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPositionDiscontinuity(); } } @@ -459,7 +459,7 @@ import java.util.concurrent.CopyOnWriteArraySet; case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: { if (pendingSeekAcks == 0) { playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPositionDiscontinuity(); } } @@ -472,7 +472,7 @@ import java.util.concurrent.CopyOnWriteArraySet; timeline = sourceInfo.timeline; manifest = sourceInfo.manifest; playbackInfo = sourceInfo.playbackInfo; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onTimelineChanged(timeline, manifest); } } @@ -482,7 +482,7 @@ import java.util.concurrent.CopyOnWriteArraySet; PlaybackParameters playbackParameters = (PlaybackParameters) msg.obj; if (!this.playbackParameters.equals(playbackParameters)) { this.playbackParameters = playbackParameters; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPlaybackParametersChanged(playbackParameters); } } @@ -490,7 +490,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } case ExoPlayerImplInternal.MSG_ERROR: { ExoPlaybackException exception = (ExoPlaybackException) msg.obj; - for (EventListener listener : listeners) { + for (Player.EventListener listener : listeners) { listener.onPlayerError(exception); } break; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfoSequence.java b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfoSequence.java index d8c82dd498..571f295015 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfoSequence.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/MediaPeriodInfoSequence.java @@ -16,8 +16,8 @@ package com.google.android.exoplayer2; import android.util.Pair; -import com.google.android.exoplayer2.ExoPlayer.RepeatMode; import com.google.android.exoplayer2.ExoPlayerImplInternal.PlaybackInfo; +import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Player.java b/library/core/src/main/java/com/google/android/exoplayer2/Player.java new file mode 100644 index 0000000000..8ca6c20d7a --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/Player.java @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2; + +import android.os.Looper; +import android.support.annotation.IntDef; +import android.support.annotation.Nullable; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * An interface for media players. + */ +public interface Player { + + /** + * Listener of changes in player state. + */ + interface EventListener { + + /** + * Called when the timeline and/or manifest has been refreshed. + *

+ * Note that if the timeline has changed then a position discontinuity may also have occurred. + * For example, the current period index may have changed as a result of periods being added or + * removed from the timeline. This will not be reported via a separate call to + * {@link #onPositionDiscontinuity()}. + * + * @param timeline The latest timeline. Never null, but may be empty. + * @param manifest The latest manifest. May be null. + */ + void onTimelineChanged(Timeline timeline, Object manifest); + + /** + * Called when the available or selected tracks change. + * + * @param trackGroups The available tracks. Never null, but may be of length zero. + * @param trackSelections The track selections for each {@link Renderer}. Never null and always + * of length {@link #getRendererCount()}, but may contain null elements. + */ + void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections); + + /** + * Called when the player starts or stops loading the source. + * + * @param isLoading Whether the source is currently being loaded. + */ + void onLoadingChanged(boolean isLoading); + + /** + * Called when the value returned from either {@link #getPlayWhenReady()} or + * {@link #getPlaybackState()} changes. + * + * @param playWhenReady Whether playback will proceed when ready. + * @param playbackState One of the {@code STATE} constants. + */ + 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. + * + * @param error The error. + */ + void onPlayerError(ExoPlaybackException error); + + /** + * Called when a position discontinuity occurs without a change to the timeline. A position + * discontinuity occurs when the current window or period index changes (as a result of playback + * transitioning from one period in the timeline to the next), or when the playback position + * jumps within the period currently being played (as a result of a seek being performed, or + * when the source introduces a discontinuity internally). + *

+ * When a position discontinuity occurs as a result of a change to the timeline this method is + * not called. {@link #onTimelineChanged(Timeline, Object)} is called in this case. + */ + void onPositionDiscontinuity(); + + /** + * Called when the current playback parameters change. The playback parameters may change due to + * a call to {@link #setPlaybackParameters(PlaybackParameters)}, or the player itself may change + * them (for example, if audio playback switches to passthrough mode, where speed adjustment is + * no longer possible). + * + * @param playbackParameters The playback parameters. + */ + void onPlaybackParametersChanged(PlaybackParameters playbackParameters); + + } + + /** + * The player does not have a source to play, so it is neither buffering nor ready to play. + */ + int STATE_IDLE = 1; + /** + * The player not able to immediately play from the current position. The cause is + * {@link Renderer} specific, but this state typically occurs when more data needs to be + * loaded to be ready to play, or more data needs to be buffered for playback to resume. + */ + int STATE_BUFFERING = 2; + /** + * The player is able to immediately play from the current position. The player will be playing if + * {@link #getPlayWhenReady()} returns true, and paused otherwise. + */ + int STATE_READY = 3; + /** + * The player has finished playing the media. + */ + int STATE_ENDED = 4; + + /** + * Repeat modes for playback. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({REPEAT_MODE_OFF, REPEAT_MODE_ONE, REPEAT_MODE_ALL}) + public @interface RepeatMode {} + /** + * Normal playback without repetition. + */ + int REPEAT_MODE_OFF = 0; + /** + * "Repeat One" mode to repeat the currently playing window infinitely. + */ + int REPEAT_MODE_ONE = 1; + /** + * "Repeat All" mode to repeat the entire timeline infinitely. + */ + int REPEAT_MODE_ALL = 2; + + /** + * Register a listener to receive events from the player. The listener's methods will be called on + * the thread that was used to construct the player. However, if the thread used to construct the + * player does not have a {@link Looper}, then the listener will be called on the main thread. + * + * @param listener The listener to register. + */ + void addListener(EventListener listener); + + /** + * Unregister a listener. The listener will no longer receive events from the player. + * + * @param listener The listener to unregister. + */ + void removeListener(EventListener listener); + + /** + * Returns the current state of the player. + * + * @return One of the {@code STATE} constants defined in this interface. + */ + int getPlaybackState(); + + /** + * Sets whether playback should proceed when {@link #getPlaybackState()} == {@link #STATE_READY}. + *

+ * If the player is already in the ready state then this method can be used to pause and resume + * playback. + * + * @param playWhenReady Whether playback should proceed when ready. + */ + void setPlayWhenReady(boolean playWhenReady); + + /** + * Whether playback will proceed when {@link #getPlaybackState()} == {@link #STATE_READY}. + * + * @return Whether playback will proceed when ready. + */ + 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. + */ + boolean isLoading(); + + /** + * Seeks to the default position associated with the current window. The position can depend on + * the type of media being played. For live streams it will typically be the live edge of the + * window. For other streams it will typically be the start of the window. + */ + void seekToDefaultPosition(); + + /** + * Seeks to the default position associated with the specified window. The position can depend on + * the type of media being played. For live streams it will typically be the live edge of the + * window. For other streams it will typically be the start of the window. + * + * @param windowIndex The index of the window whose associated default position should be seeked + * to. + */ + void seekToDefaultPosition(int windowIndex); + + /** + * Seeks to a position specified in milliseconds in the current window. + * + * @param positionMs The seek position in the current window, or {@link C#TIME_UNSET} to seek to + * the window's default position. + */ + void seekTo(long positionMs); + + /** + * Seeks to a position specified in milliseconds in the specified window. + * + * @param windowIndex The index of the window. + * @param positionMs The seek position in the specified window, or {@link C#TIME_UNSET} to seek to + * the window's default position. + */ + void seekTo(int windowIndex, long positionMs); + + /** + * Attempts to set the playback parameters. Passing {@code null} sets the parameters to the + * default, {@link PlaybackParameters#DEFAULT}, which means there is no speed or pitch adjustment. + *

+ * Playback parameters changes may cause the player to buffer. + * {@link EventListener#onPlaybackParametersChanged(PlaybackParameters)} will be called whenever + * the currently active playback parameters change. When that listener is called, the parameters + * passed to it may not match {@code playbackParameters}. For example, the chosen speed or pitch + * may be out of range, in which case they are constrained to a set of permitted values. If it is + * not possible to change the playback parameters, the listener will not be invoked. + * + * @param playbackParameters The playback parameters, or {@code null} to use the defaults. + */ + void setPlaybackParameters(@Nullable PlaybackParameters playbackParameters); + + /** + * Returns the currently active playback parameters. + * + * @see EventListener#onPlaybackParametersChanged(PlaybackParameters) + */ + PlaybackParameters getPlaybackParameters(); + + /** + * Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention + * is to pause playback. + *

+ * Calling this method will cause the playback state to transition to {@link #STATE_IDLE}. The + * player instance can still be used, and {@link #release()} must still be called on the player if + * it's no longer required. + *

+ * Calling this method does not reset the playback position. + */ + void stop(); + + /** + * Releases the player. This method must be called when the player is no longer required. The + * player must not be used after calling this method. + */ + void release(); + + /** + * Returns the number of renderers. + */ + int getRendererCount(); + + /** + * Returns the track type that the renderer at a given index handles. + * + * @see Renderer#getTrackType() + * @param index The index of the renderer. + * @return One of the {@code TRACK_TYPE_*} constants defined in {@link C}. + */ + int getRendererType(int index); + + /** + * Returns the available track groups. + */ + TrackGroupArray getCurrentTrackGroups(); + + /** + * Returns the current track selections for each renderer. + */ + TrackSelectionArray getCurrentTrackSelections(); + + /** + * Returns the current manifest. The type depends on the type of media being played. May be null. + */ + @Nullable Object getCurrentManifest(); + + /** + * Returns the current {@link Timeline}. Never null, but may be empty. + */ + Timeline getCurrentTimeline(); + + /** + * Returns the index of the period currently being played. + */ + int getCurrentPeriodIndex(); + + /** + * Returns the index of the window currently being played. + */ + int getCurrentWindowIndex(); + + /** + * Returns the duration of the current window in milliseconds, or {@link C#TIME_UNSET} if the + * duration is not known. + */ + long getDuration(); + + /** + * Returns the playback position in the current window, in milliseconds. + */ + long getCurrentPosition(); + + /** + * Returns an estimate of the position in the current window up to which data is buffered, in + * milliseconds. + */ + long getBufferedPosition(); + + /** + * Returns an estimate of the percentage in the current window up to which data is buffered, or 0 + * if no estimate is available. + */ + int getBufferedPercentage(); + + /** + * Returns whether the current window is dynamic, or {@code false} if the {@link Timeline} is + * empty. + * + * @see Timeline.Window#isDynamic + */ + boolean isCurrentWindowDynamic(); + + /** + * Returns whether the current window is seekable, or {@code false} if the {@link Timeline} is + * empty. + * + * @see Timeline.Window#isSeekable + */ + boolean isCurrentWindowSeekable(); + + /** + * Returns whether the player is currently playing an ad. + */ + boolean isPlayingAd(); + + /** + * If {@link #isPlayingAd()} returns true, returns the index of the ad group in the period + * currently being played. Returns {@link C#INDEX_UNSET} otherwise. + */ + int getCurrentAdGroupIndex(); + + /** + * If {@link #isPlayingAd()} returns true, returns the index of the ad in its ad group. Returns + * {@link C#INDEX_UNSET} otherwise. + */ + int getCurrentAdIndexInAdGroup(); + + /** + * If {@link #isPlayingAd()} returns {@code true}, returns the content position that will be + * played once all ads in the ad group have finished playing, in milliseconds. If there is no ad + * playing, the returned position is the same as that returned by {@link #getCurrentPosition()}. + */ + long getContentPosition(); + +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 9d163007fc..ebfe380b6b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -524,12 +524,12 @@ public class SimpleExoPlayer implements ExoPlayer { } @Override - public void addListener(EventListener listener) { + public void addListener(Player.EventListener listener) { player.addListener(listener); } @Override - public void removeListener(EventListener listener) { + public void removeListener(Player.EventListener listener) { player.removeListener(listener); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java index 99a8033589..32c4eb6c73 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java @@ -17,7 +17,7 @@ package com.google.android.exoplayer2.source; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.ExoPlayer.RepeatMode; +import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.util.Assertions; diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java index 6a4f258dd2..7c4afa772a 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java @@ -31,9 +31,10 @@ import android.widget.ImageView; import android.widget.TextView; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.PlaybackParameters; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.Player.RepeatMode; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; @@ -45,7 +46,7 @@ import java.util.Formatter; import java.util.Locale; /** - * A view for controlling {@link ExoPlayer} instances. + * A view for controlling {@link Player} instances. *

* A PlaybackControlView can be customized by setting attributes (or calling corresponding methods), * overriding the view's layout file or by specifying a custom view layout file, as outlined below. @@ -183,7 +184,7 @@ public class PlaybackControlView extends FrameLayout { } /** - * Dispatches operations to the player. + * Dispatches operations to the {@link Player}. *

* Implementations may choose to suppress (e.g. prevent playback from resuming if audio focus is * denied) or modify (e.g. change the seek position to prevent a user from seeking past a @@ -192,33 +193,34 @@ public class PlaybackControlView extends FrameLayout { public interface ControlDispatcher { /** - * Dispatches a {@link ExoPlayer#setPlayWhenReady(boolean)} operation. + * Dispatches a {@link Player#setPlayWhenReady(boolean)} operation. * - * @param player The player to which the operation should be dispatched. + * @param player The {@link Player} to which the operation should be dispatched. * @param playWhenReady Whether playback should proceed when ready. * @return True if the operation was dispatched. False if suppressed. */ - boolean dispatchSetPlayWhenReady(ExoPlayer player, boolean playWhenReady); + boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady); /** - * Dispatches a {@link ExoPlayer#seekTo(int, long)} operation. + * Dispatches a {@link Player#seekTo(int, long)} operation. * - * @param player The player to which the operation should be dispatched. + * @param player The {@link Player} to which the operation should be dispatched. * @param windowIndex The index of the window. * @param positionMs The seek position in the specified window, or {@link C#TIME_UNSET} to seek * to the window's default position. * @return True if the operation was dispatched. False if suppressed. */ - boolean dispatchSeekTo(ExoPlayer player, int windowIndex, long positionMs); + boolean dispatchSeekTo(Player player, int windowIndex, long positionMs); /** - * Dispatches a {@link ExoPlayer#setRepeatMode(int)} operation. + * Dispatches a {@link Player#setRepeatMode(int)} operation. * - * @param player The player to which the operation should be dispatched. + * @param player The {@link Player} to which the operation should be dispatched. * @param repeatMode The repeat mode. * @return True if the operation was dispatched. False if suppressed. */ - boolean dispatchSetRepeatMode(ExoPlayer player, @ExoPlayer.RepeatMode int repeatMode); + boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode); + } /** @@ -228,19 +230,19 @@ public class PlaybackControlView extends FrameLayout { public static final ControlDispatcher DEFAULT_CONTROL_DISPATCHER = new ControlDispatcher() { @Override - public boolean dispatchSetPlayWhenReady(ExoPlayer player, boolean playWhenReady) { + public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) { player.setPlayWhenReady(playWhenReady); return true; } @Override - public boolean dispatchSeekTo(ExoPlayer player, int windowIndex, long positionMs) { + public boolean dispatchSeekTo(Player player, int windowIndex, long positionMs) { player.seekTo(windowIndex, positionMs); return true; } @Override - public boolean dispatchSetRepeatMode(ExoPlayer player, @ExoPlayer.RepeatMode int repeatMode) { + public boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode) { player.setRepeatMode(repeatMode); return true; } @@ -283,7 +285,7 @@ public class PlaybackControlView extends FrameLayout { private final String repeatOneButtonContentDescription; private final String repeatAllButtonContentDescription; - private ExoPlayer player; + private Player player; private ControlDispatcher controlDispatcher; private VisibilityListener visibilityListener; @@ -409,18 +411,19 @@ public class PlaybackControlView extends FrameLayout { } /** - * Returns the player currently being controlled by this view, or null if no player is set. + * Returns the {@link Player} currently being controlled by this view, or null if no player is + * set. */ - public ExoPlayer getPlayer() { + public Player getPlayer() { return player; } /** - * Sets the {@link ExoPlayer} to control. + * Sets the {@link Player} to control. * - * @param player The {@code ExoPlayer} to control. + * @param player The {@link Player} to control. */ - public void setPlayer(ExoPlayer player) { + public void setPlayer(Player player) { if (this.player == player) { return; } @@ -528,16 +531,16 @@ public class PlaybackControlView extends FrameLayout { public void setRepeatToggleModes(@RepeatModeUtil.RepeatToggleModes int repeatToggleModes) { this.repeatToggleModes = repeatToggleModes; if (player != null) { - @ExoPlayer.RepeatMode int currentMode = player.getRepeatMode(); + @Player.RepeatMode int currentMode = player.getRepeatMode(); if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_NONE - && currentMode != ExoPlayer.REPEAT_MODE_OFF) { - controlDispatcher.dispatchSetRepeatMode(player, ExoPlayer.REPEAT_MODE_OFF); + && currentMode != Player.REPEAT_MODE_OFF) { + controlDispatcher.dispatchSetRepeatMode(player, Player.REPEAT_MODE_OFF); } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ONE - && currentMode == ExoPlayer.REPEAT_MODE_ALL) { - controlDispatcher.dispatchSetRepeatMode(player, ExoPlayer.REPEAT_MODE_ONE); + && currentMode == Player.REPEAT_MODE_ALL) { + controlDispatcher.dispatchSetRepeatMode(player, Player.REPEAT_MODE_ONE); } else if (repeatToggleModes == RepeatModeUtil.REPEAT_TOGGLE_MODE_ALL - && currentMode == ExoPlayer.REPEAT_MODE_ONE) { - controlDispatcher.dispatchSetRepeatMode(player, ExoPlayer.REPEAT_MODE_ALL); + && currentMode == Player.REPEAT_MODE_ONE) { + controlDispatcher.dispatchSetRepeatMode(player, Player.REPEAT_MODE_ALL); } } } @@ -658,15 +661,15 @@ public class PlaybackControlView extends FrameLayout { return; } switch (player.getRepeatMode()) { - case ExoPlayer.REPEAT_MODE_OFF: + case Player.REPEAT_MODE_OFF: repeatToggleButton.setImageDrawable(repeatOffButtonDrawable); repeatToggleButton.setContentDescription(repeatOffButtonContentDescription); break; - case ExoPlayer.REPEAT_MODE_ONE: + case Player.REPEAT_MODE_ONE: repeatToggleButton.setImageDrawable(repeatOneButtonDrawable); repeatToggleButton.setContentDescription(repeatOneButtonContentDescription); break; - case ExoPlayer.REPEAT_MODE_ALL: + case Player.REPEAT_MODE_ALL: repeatToggleButton.setImageDrawable(repeatAllButtonDrawable); repeatToggleButton.setContentDescription(repeatAllButtonContentDescription); break; @@ -765,10 +768,10 @@ public class PlaybackControlView extends FrameLayout { // Cancel any pending updates and schedule a new one if necessary. removeCallbacks(updateProgressAction); - int playbackState = player == null ? ExoPlayer.STATE_IDLE : player.getPlaybackState(); - if (playbackState != ExoPlayer.STATE_IDLE && playbackState != ExoPlayer.STATE_ENDED) { + int playbackState = player == null ? Player.STATE_IDLE : player.getPlaybackState(); + if (playbackState != Player.STATE_IDLE && playbackState != Player.STATE_ENDED) { long delayMs; - if (player.getPlayWhenReady() && playbackState == ExoPlayer.STATE_READY) { + if (player.getPlayWhenReady() && playbackState == Player.STATE_READY) { delayMs = 1000 - (position % 1000); if (delayMs < 200) { delayMs += 1000; @@ -995,7 +998,7 @@ public class PlaybackControlView extends FrameLayout { return true; } - private final class ComponentListener implements ExoPlayer.EventListener, TimeBar.OnScrubListener, + private final class ComponentListener implements Player.EventListener, TimeBar.OnScrubListener, OnClickListener { @Override