mirror of
https://github.com/androidx/media.git
synced 2025-05-17 12:39:52 +08:00
Make LeanbackPlayerAdapter use a ControlDispatcher + Misc cleanup
1. Make LeanbackPlayerAdapter use a ControlDispatcher. This allows apps to suppress control events in some circumstances, and is in-line with our mobile controls. 2. Misc simplifications and cleanup to LeanbackPlayerAdapter. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=166852816
This commit is contained in:
parent
44dc3c3ab3
commit
55e928f75a
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.leanback;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v17.leanback.R;
|
import android.support.v17.leanback.R;
|
||||||
import android.support.v17.leanback.media.PlaybackGlueHost;
|
import android.support.v17.leanback.media.PlaybackGlueHost;
|
||||||
import android.support.v17.leanback.media.PlayerAdapter;
|
import android.support.v17.leanback.media.PlayerAdapter;
|
||||||
@ -25,6 +26,8 @@ import android.util.Pair;
|
|||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ControlDispatcher;
|
||||||
|
import com.google.android.exoplayer2.DefaultControlDispatcher;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
@ -48,13 +51,13 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
private final SimpleExoPlayer player;
|
private final SimpleExoPlayer player;
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
private final ComponentListener componentListener;
|
private final ComponentListener componentListener;
|
||||||
private final Runnable updatePlayerRunnable;
|
private final Runnable updateProgressRunnable;
|
||||||
|
|
||||||
|
private ControlDispatcher controlDispatcher;
|
||||||
private ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider;
|
private ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider;
|
||||||
private SurfaceHolderGlueHost surfaceHolderGlueHost;
|
private SurfaceHolderGlueHost surfaceHolderGlueHost;
|
||||||
private boolean initialized;
|
|
||||||
private boolean hasSurface;
|
private boolean hasSurface;
|
||||||
private boolean isBuffering;
|
private boolean lastNotifiedPreparedState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds an instance. Note that the {@code PlayerAdapter} does not manage the lifecycle of the
|
* Builds an instance. Note that the {@code PlayerAdapter} does not manage the lifecycle of the
|
||||||
@ -70,7 +73,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
this.player = player;
|
this.player = player;
|
||||||
handler = new Handler();
|
handler = new Handler();
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
updatePlayerRunnable = new Runnable() {
|
controlDispatcher = new DefaultControlDispatcher();
|
||||||
|
updateProgressRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Callback callback = getCallback();
|
Callback callback = getCallback();
|
||||||
@ -81,34 +85,15 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void onAttachedToHost(PlaybackGlueHost host) {
|
* Sets the {@link ControlDispatcher}.
|
||||||
if (host instanceof SurfaceHolderGlueHost) {
|
*
|
||||||
surfaceHolderGlueHost = ((SurfaceHolderGlueHost) host);
|
* @param controlDispatcher The {@link ControlDispatcher}, or null to use
|
||||||
surfaceHolderGlueHost.setSurfaceHolderCallback(componentListener);
|
* {@link DefaultControlDispatcher}.
|
||||||
}
|
*/
|
||||||
notifyListeners();
|
public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) {
|
||||||
player.addListener(componentListener);
|
this.controlDispatcher = controlDispatcher == null ? new DefaultControlDispatcher()
|
||||||
player.addVideoListener(componentListener);
|
: controlDispatcher;
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyListeners() {
|
|
||||||
boolean oldIsPrepared = isPrepared();
|
|
||||||
int playbackState = player.getPlaybackState();
|
|
||||||
boolean isInitialized = playbackState != Player.STATE_IDLE;
|
|
||||||
isBuffering = playbackState == Player.STATE_BUFFERING;
|
|
||||||
boolean hasEnded = playbackState == Player.STATE_ENDED;
|
|
||||||
|
|
||||||
initialized = isInitialized;
|
|
||||||
Callback callback = getCallback();
|
|
||||||
if (oldIsPrepared != isPrepared()) {
|
|
||||||
callback.onPreparedStateChanged(this);
|
|
||||||
}
|
|
||||||
callback.onPlayStateChanged(this);
|
|
||||||
callback.onBufferingStateChanged(this, isBuffering || !initialized);
|
|
||||||
if (hasEnded) {
|
|
||||||
callback.onPlayCompleted(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,6 +106,19 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
this.errorMessageProvider = errorMessageProvider;
|
this.errorMessageProvider = errorMessageProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayerAdapter implementation.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToHost(PlaybackGlueHost host) {
|
||||||
|
if (host instanceof SurfaceHolderGlueHost) {
|
||||||
|
surfaceHolderGlueHost = ((SurfaceHolderGlueHost) host);
|
||||||
|
surfaceHolderGlueHost.setSurfaceHolderCallback(componentListener);
|
||||||
|
}
|
||||||
|
notifyStateChanged();
|
||||||
|
player.addListener(componentListener);
|
||||||
|
player.addVideoListener(componentListener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDetachedFromHost() {
|
public void onDetachedFromHost() {
|
||||||
player.removeListener(componentListener);
|
player.removeListener(componentListener);
|
||||||
@ -129,56 +127,59 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
surfaceHolderGlueHost.setSurfaceHolderCallback(null);
|
surfaceHolderGlueHost.setSurfaceHolderCallback(null);
|
||||||
surfaceHolderGlueHost = null;
|
surfaceHolderGlueHost = null;
|
||||||
}
|
}
|
||||||
initialized = false;
|
|
||||||
hasSurface = false;
|
hasSurface = false;
|
||||||
Callback callback = getCallback();
|
Callback callback = getCallback();
|
||||||
callback.onBufferingStateChanged(this, false);
|
callback.onBufferingStateChanged(this, false);
|
||||||
callback.onPlayStateChanged(this);
|
callback.onPlayStateChanged(this);
|
||||||
callback.onPreparedStateChanged(this);
|
maybeNotifyPreparedStateChanged(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgressUpdatingEnabled(final boolean enabled) {
|
public void setProgressUpdatingEnabled(boolean enabled) {
|
||||||
handler.removeCallbacks(updatePlayerRunnable);
|
handler.removeCallbacks(updateProgressRunnable);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
handler.post(updatePlayerRunnable);
|
handler.post(updateProgressRunnable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return initialized && player.getPlayWhenReady();
|
int playbackState = player.getPlaybackState();
|
||||||
|
return playbackState != Player.STATE_IDLE && playbackState != Player.STATE_ENDED
|
||||||
|
&& player.getPlayWhenReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDuration() {
|
public long getDuration() {
|
||||||
long durationMs = player.getDuration();
|
long durationMs = player.getDuration();
|
||||||
return durationMs != C.TIME_UNSET ? durationMs : -1;
|
return durationMs == C.TIME_UNSET ? -1 : durationMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentPosition() {
|
public long getCurrentPosition() {
|
||||||
return initialized ? player.getCurrentPosition() : -1;
|
return player.getPlaybackState() == Player.STATE_IDLE ? -1 : player.getCurrentPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
if (player.getPlaybackState() == Player.STATE_ENDED) {
|
if (player.getPlaybackState() == Player.STATE_ENDED) {
|
||||||
player.seekToDefaultPosition();
|
controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
|
||||||
|
}
|
||||||
|
if (controlDispatcher.dispatchSetPlayWhenReady(player, true)) {
|
||||||
|
getCallback().onPlayStateChanged(this);
|
||||||
}
|
}
|
||||||
player.setPlayWhenReady(true);
|
|
||||||
getCallback().onPlayStateChanged(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
player.setPlayWhenReady(false);
|
if (controlDispatcher.dispatchSetPlayWhenReady(player, false)) {
|
||||||
getCallback().onPlayStateChanged(this);
|
getCallback().onPlayStateChanged(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seekTo(long positionMs) {
|
public void seekTo(long positionMs) {
|
||||||
player.seekTo(positionMs);
|
controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), positionMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -188,13 +189,35 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPrepared() {
|
public boolean isPrepared() {
|
||||||
return initialized && (surfaceHolderGlueHost == null || hasSurface);
|
return player.getPlaybackState() != Player.STATE_IDLE
|
||||||
|
&& (surfaceHolderGlueHost == null || hasSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setVideoSurface(Surface surface) {
|
// Internal methods.
|
||||||
|
|
||||||
|
/* package */ void setVideoSurface(Surface surface) {
|
||||||
hasSurface = surface != null;
|
hasSurface = surface != null;
|
||||||
player.setVideoSurface(surface);
|
player.setVideoSurface(surface);
|
||||||
getCallback().onPreparedStateChanged(this);
|
maybeNotifyPreparedStateChanged(getCallback());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void notifyStateChanged() {
|
||||||
|
int playbackState = player.getPlaybackState();
|
||||||
|
Callback callback = getCallback();
|
||||||
|
maybeNotifyPreparedStateChanged(callback);
|
||||||
|
callback.onPlayStateChanged(this);
|
||||||
|
callback.onBufferingStateChanged(this, playbackState == Player.STATE_BUFFERING);
|
||||||
|
if (playbackState == Player.STATE_ENDED) {
|
||||||
|
callback.onPlayCompleted(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maybeNotifyPreparedStateChanged(Callback callback) {
|
||||||
|
boolean isPrepared = isPrepared();
|
||||||
|
if (lastNotifiedPreparedState != isPrepared) {
|
||||||
|
lastNotifiedPreparedState = isPrepared;
|
||||||
|
callback.onPreparedStateChanged(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ComponentListener implements Player.EventListener,
|
private final class ComponentListener implements Player.EventListener,
|
||||||
@ -208,7 +231,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
|
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +244,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||||
notifyListeners();
|
notifyStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -292,4 +315,3 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.android.exoplayer2.Player.RepeatMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches operations to the {@link Player}.
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
* non-skippable advert) operations.
|
||||||
|
*/
|
||||||
|
public interface ControlDispatcher {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a {@link Player#setPlayWhenReady(boolean)} operation.
|
||||||
|
*
|
||||||
|
* @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(Player player, boolean playWhenReady);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a {@link Player#seekTo(int, long)} operation.
|
||||||
|
*
|
||||||
|
* @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(Player player, int windowIndex, long positionMs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a {@link Player#setRepeatMode(int)} operation.
|
||||||
|
*
|
||||||
|
* @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(Player player, @RepeatMode int repeatMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatches a {@link Player#setShuffleModeEnabled(boolean)} operation.
|
||||||
|
*
|
||||||
|
* @param player The {@link Player} to which the operation should be dispatched.
|
||||||
|
* @param shuffleModeEnabled Whether shuffling is enabled.
|
||||||
|
* @return True if the operation was dispatched. False if suppressed.
|
||||||
|
*/
|
||||||
|
boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.google.android.exoplayer2.Player.RepeatMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default {@link ControlDispatcher} that dispatches all operations to the player without
|
||||||
|
* modification.
|
||||||
|
*/
|
||||||
|
public class DefaultControlDispatcher implements ControlDispatcher {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
|
||||||
|
player.setPlayWhenReady(playWhenReady);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchSeekTo(Player player, int windowIndex, long positionMs) {
|
||||||
|
player.seekTo(windowIndex, positionMs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode) {
|
||||||
|
player.setRepeatMode(repeatMode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled) {
|
||||||
|
player.setShuffleModeEnabled(shuffleModeEnabled);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -34,7 +34,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Player.RepeatMode;
|
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
@ -180,6 +179,12 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
ExoPlayerLibraryInfo.registerModule("goog.exo.ui");
|
ExoPlayerLibraryInfo.registerModule("goog.exo.ui");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link com.google.android.exoplayer2.ControlDispatcher}.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public interface ControlDispatcher extends com.google.android.exoplayer2.ControlDispatcher {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener to be notified about changes of the visibility of the UI control.
|
* Listener to be notified about changes of the visibility of the UI control.
|
||||||
*/
|
*/
|
||||||
@ -194,86 +199,13 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class DefaultControlDispatcher
|
||||||
|
extends com.google.android.exoplayer2.DefaultControlDispatcher implements ControlDispatcher {}
|
||||||
/**
|
/**
|
||||||
* Dispatches operations to the {@link Player}.
|
* @deprecated Use {@link com.google.android.exoplayer2.DefaultControlDispatcher}.
|
||||||
* <p>
|
|
||||||
* 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
|
|
||||||
* non-skippable advert) operations.
|
|
||||||
*/
|
*/
|
||||||
public interface ControlDispatcher {
|
@Deprecated
|
||||||
|
public static final ControlDispatcher DEFAULT_CONTROL_DISPATCHER = new DefaultControlDispatcher();
|
||||||
/**
|
|
||||||
* Dispatches a {@link Player#setPlayWhenReady(boolean)} operation.
|
|
||||||
*
|
|
||||||
* @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(Player player, boolean playWhenReady);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a {@link Player#seekTo(int, long)} operation.
|
|
||||||
*
|
|
||||||
* @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(Player player, int windowIndex, long positionMs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a {@link Player#setRepeatMode(int)} operation.
|
|
||||||
*
|
|
||||||
* @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(Player player, @RepeatMode int repeatMode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a {@link Player#setShuffleModeEnabled(boolean)} operation.
|
|
||||||
*
|
|
||||||
* @param player The {@link Player} to which the operation should be dispatched.
|
|
||||||
* @param shuffleModeEnabled Whether shuffling is enabled.
|
|
||||||
* @return True if the operation was dispatched. False if suppressed.
|
|
||||||
*/
|
|
||||||
boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default {@link ControlDispatcher} that dispatches operations to the player without
|
|
||||||
* modification.
|
|
||||||
*/
|
|
||||||
public static final ControlDispatcher DEFAULT_CONTROL_DISPATCHER = new ControlDispatcher() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchSetPlayWhenReady(Player player, boolean playWhenReady) {
|
|
||||||
player.setPlayWhenReady(playWhenReady);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchSeekTo(Player player, int windowIndex, long positionMs) {
|
|
||||||
player.seekTo(windowIndex, positionMs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode) {
|
|
||||||
player.setRepeatMode(repeatMode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled) {
|
|
||||||
player.setShuffleModeEnabled(shuffleModeEnabled);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default fast forward increment, in milliseconds.
|
* The default fast forward increment, in milliseconds.
|
||||||
@ -325,7 +257,7 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
private final String repeatAllButtonContentDescription;
|
private final String repeatAllButtonContentDescription;
|
||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
private ControlDispatcher controlDispatcher;
|
private com.google.android.exoplayer2.ControlDispatcher controlDispatcher;
|
||||||
private VisibilityListener visibilityListener;
|
private VisibilityListener visibilityListener;
|
||||||
|
|
||||||
private boolean isAttachedToWindow;
|
private boolean isAttachedToWindow;
|
||||||
@ -400,7 +332,7 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
extraAdGroupTimesMs = new long[0];
|
extraAdGroupTimesMs = new long[0];
|
||||||
extraPlayedAdGroups = new boolean[0];
|
extraPlayedAdGroups = new boolean[0];
|
||||||
componentListener = new ComponentListener();
|
componentListener = new ComponentListener();
|
||||||
controlDispatcher = DEFAULT_CONTROL_DISPATCHER;
|
controlDispatcher = new com.google.android.exoplayer2.DefaultControlDispatcher();
|
||||||
|
|
||||||
LayoutInflater.from(context).inflate(controllerLayoutId, this);
|
LayoutInflater.from(context).inflate(controllerLayoutId, this);
|
||||||
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
|
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
|
||||||
@ -534,14 +466,15 @@ public class PlaybackControlView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link ControlDispatcher}.
|
* Sets the {@link com.google.android.exoplayer2.ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link ControlDispatcher}, or null to use
|
* @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null
|
||||||
* {@link #DEFAULT_CONTROL_DISPATCHER}.
|
* to use {@link com.google.android.exoplayer2.DefaultControlDispatcher}.
|
||||||
*/
|
*/
|
||||||
public void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
public void setControlDispatcher(
|
||||||
this.controlDispatcher = controlDispatcher == null ? DEFAULT_CONTROL_DISPATCHER
|
@Nullable com.google.android.exoplayer2.ControlDispatcher controlDispatcher) {
|
||||||
: controlDispatcher;
|
this.controlDispatcher = controlDispatcher == null
|
||||||
|
? new com.google.android.exoplayer2.DefaultControlDispatcher() : controlDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,6 +34,8 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ControlDispatcher;
|
||||||
|
import com.google.android.exoplayer2.DefaultControlDispatcher;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
@ -47,7 +49,6 @@ import com.google.android.exoplayer2.text.TextOutput;
|
|||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
|
||||||
import com.google.android.exoplayer2.ui.PlaybackControlView.ControlDispatcher;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.RepeatModeUtil;
|
import com.google.android.exoplayer2.util.RepeatModeUtil;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -616,9 +617,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
|||||||
* Sets the {@link ControlDispatcher}.
|
* Sets the {@link ControlDispatcher}.
|
||||||
*
|
*
|
||||||
* @param controlDispatcher The {@link ControlDispatcher}, or null to use
|
* @param controlDispatcher The {@link ControlDispatcher}, or null to use
|
||||||
* {@link PlaybackControlView#DEFAULT_CONTROL_DISPATCHER}.
|
* {@link DefaultControlDispatcher}.
|
||||||
*/
|
*/
|
||||||
public void setControlDispatcher(ControlDispatcher controlDispatcher) {
|
public void setControlDispatcher(@Nullable ControlDispatcher controlDispatcher) {
|
||||||
Assertions.checkState(controller != null);
|
Assertions.checkState(controller != null);
|
||||||
controller.setControlDispatcher(controlDispatcher);
|
controller.setControlDispatcher(controlDispatcher);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user