Commit 4828f275 by olly Committed by Oliver Woodman

Make play button behave differently in IDLE and ENDED states

- In IDLE, the button will now call a preparer. This allows
  removal of the separate retry button from the demo app.
- In ENDED, the button will seek back to the default position
  and play.
- Behavior is made consistent with LeanbackPlayerAdapter.

Issue: #3689

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=182506855
parent 7cacbfed
...@@ -19,12 +19,15 @@ ...@@ -19,12 +19,15 @@
periods. periods.
* Replaced `ExoPlayer.sendMessages` with `ExoPlayer.createMessage` to allow * Replaced `ExoPlayer.sendMessages` with `ExoPlayer.createMessage` to allow
more customization of the message. Now supports setting a message delivery more customization of the message. Now supports setting a message delivery
playback position and/or a delivery handler. playback position and/or a delivery handler
([#2189](https://github.com/google/ExoPlayer/issues/2189)). ([#2189](https://github.com/google/ExoPlayer/issues/2189)).
* UI components: * UI components:
* Generalized player and control views to allow them to bind with any * Generalized player and control views to allow them to bind with any
`Player`, and renamed them to `PlayerView` and `PlayerControlView` `Player`, and renamed them to `PlayerView` and `PlayerControlView`
respectively. respectively.
* Made `PlayerView`'s play button behave correctly when the player is ended
([#3689](https://github.com/google/ExoPlayer/issues/3689)), and call a
`PlaybackPreparer` when the player is idle.
* Buffering: * Buffering:
* Allow a back-buffer of media to be retained behind the current playback * Allow a back-buffer of media to be retained behind the current playback
position, for fast backward seeking. The back-buffer can be configured by position, for fast backward seeking. The back-buffer can be configured by
......
...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.C.ContentType; ...@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.C.ContentType;
import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.PlaybackPreparer;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
...@@ -82,7 +83,7 @@ import java.util.UUID; ...@@ -82,7 +83,7 @@ import java.util.UUID;
/** An activity that plays media using {@link SimpleExoPlayer}. */ /** An activity that plays media using {@link SimpleExoPlayer}. */
public class PlayerActivity extends Activity public class PlayerActivity extends Activity
implements OnClickListener, PlayerControlView.VisibilityListener { implements OnClickListener, PlaybackPreparer, PlayerControlView.VisibilityListener {
public static final String DRM_SCHEME_EXTRA = "drm_scheme"; public static final String DRM_SCHEME_EXTRA = "drm_scheme";
public static final String DRM_LICENSE_URL = "drm_license_url"; public static final String DRM_LICENSE_URL = "drm_license_url";
...@@ -114,7 +115,6 @@ public class PlayerActivity extends Activity ...@@ -114,7 +115,6 @@ public class PlayerActivity extends Activity
private PlayerView playerView; private PlayerView playerView;
private LinearLayout debugRootView; private LinearLayout debugRootView;
private TextView debugTextView; private TextView debugTextView;
private Button retryButton;
private DataSource.Factory mediaDataSourceFactory; private DataSource.Factory mediaDataSourceFactory;
private SimpleExoPlayer player; private SimpleExoPlayer player;
...@@ -152,8 +152,6 @@ public class PlayerActivity extends Activity ...@@ -152,8 +152,6 @@ public class PlayerActivity extends Activity
rootView.setOnClickListener(this); rootView.setOnClickListener(this);
debugRootView = findViewById(R.id.controls_root); debugRootView = findViewById(R.id.controls_root);
debugTextView = findViewById(R.id.debug_text_view); debugTextView = findViewById(R.id.debug_text_view);
retryButton = findViewById(R.id.retry_button);
retryButton.setOnClickListener(this);
playerView = findViewById(R.id.player_view); playerView = findViewById(R.id.player_view);
playerView.setControllerVisibilityListener(this); playerView.setControllerVisibilityListener(this);
...@@ -229,9 +227,7 @@ public class PlayerActivity extends Activity ...@@ -229,9 +227,7 @@ public class PlayerActivity extends Activity
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (view == retryButton) { if (view.getParent() == debugRootView) {
initializePlayer();
} else if (view.getParent() == debugRootView) {
MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo();
if (mappedTrackInfo != null) { if (mappedTrackInfo != null) {
trackSelectionHelper.showSelectionDialog( trackSelectionHelper.showSelectionDialog(
...@@ -240,6 +236,13 @@ public class PlayerActivity extends Activity ...@@ -240,6 +236,13 @@ public class PlayerActivity extends Activity
} }
} }
// PlaybackControlView.PlaybackPreparer implementation
@Override
public void preparePlayback() {
initializePlayer();
}
// PlaybackControlView.VisibilityListener implementation // PlaybackControlView.VisibilityListener implementation
@Override @Override
...@@ -301,9 +304,10 @@ public class PlayerActivity extends Activity ...@@ -301,9 +304,10 @@ public class PlayerActivity extends Activity
player.addMetadataOutput(eventLogger); player.addMetadataOutput(eventLogger);
player.addAudioDebugListener(eventLogger); player.addAudioDebugListener(eventLogger);
player.addVideoDebugListener(eventLogger); player.addVideoDebugListener(eventLogger);
player.setPlayWhenReady(shouldAutoPlay);
playerView.setPlayer(player); playerView.setPlayer(player);
player.setPlayWhenReady(shouldAutoPlay); playerView.setPlaybackPreparer(this);
debugViewHelper = new DebugTextViewHelper(player, debugTextView); debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start(); debugViewHelper.start();
} }
...@@ -502,10 +506,6 @@ public class PlayerActivity extends Activity ...@@ -502,10 +506,6 @@ public class PlayerActivity extends Activity
private void updateButtonVisibilities() { private void updateButtonVisibilities() {
debugRootView.removeAllViews(); debugRootView.removeAllViews();
retryButton.setVisibility(inErrorState ? View.VISIBLE : View.GONE);
debugRootView.addView(retryButton);
if (player == null) { if (player == null) {
return; return;
} }
......
...@@ -42,15 +42,7 @@ ...@@ -42,15 +42,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:visibility="gone"> android:visibility="gone"/>
<Button android:id="@+id/retry_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/retry"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
<string name="text">Text</string> <string name="text">Text</string>
<string name="retry">Retry</string>
<string name="selection_disabled">Disabled</string> <string name="selection_disabled">Disabled</string>
<string name="selection_default">Default</string> <string name="selection_default">Default</string>
......
...@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.ControlDispatcher; ...@@ -30,6 +30,7 @@ import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.DefaultControlDispatcher; 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.PlaybackPreparer;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.Player.TimelineChangeReason; import com.google.android.exoplayer2.Player.TimelineChangeReason;
...@@ -50,6 +51,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { ...@@ -50,6 +51,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final Runnable updateProgressRunnable; private final Runnable updateProgressRunnable;
private @Nullable PlaybackPreparer playbackPreparer;
private ControlDispatcher controlDispatcher; private ControlDispatcher controlDispatcher;
private ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider; private ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider;
private SurfaceHolderGlueHost surfaceHolderGlueHost; private SurfaceHolderGlueHost surfaceHolderGlueHost;
...@@ -83,6 +85,15 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { ...@@ -83,6 +85,15 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
} }
/** /**
* Sets the {@link PlaybackPreparer}.
*
* @param playbackPreparer The {@link PlaybackPreparer}.
*/
public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
this.playbackPreparer = playbackPreparer;
}
/**
* 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
...@@ -165,7 +176,11 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { ...@@ -165,7 +176,11 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter {
@Override @Override
public void play() { public void play() {
if (player.getPlaybackState() == Player.STATE_ENDED) { if (player.getPlaybackState() == Player.STATE_IDLE) {
if (playbackPreparer != null) {
playbackPreparer.preparePlayback();
}
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET); controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
} }
if (controlDispatcher.dispatchSetPlayWhenReady(player, true)) { if (controlDispatcher.dispatchSetPlayWhenReady(player, true)) {
......
/*
* Copyright (C) 2018 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;
/** Called to prepare a playback. */
public interface PlaybackPreparer {
/** Called to prepare a playback. */
void preparePlayback();
}
...@@ -31,6 +31,7 @@ import android.widget.ImageView; ...@@ -31,6 +31,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.PlaybackPreparer;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -217,6 +218,7 @@ public class PlayerControlView extends FrameLayout { ...@@ -217,6 +218,7 @@ public class PlayerControlView extends FrameLayout {
private Player player; private Player player;
private com.google.android.exoplayer2.ControlDispatcher controlDispatcher; private com.google.android.exoplayer2.ControlDispatcher controlDispatcher;
private VisibilityListener visibilityListener; private VisibilityListener visibilityListener;
private @Nullable PlaybackPreparer playbackPreparer;
private boolean isAttachedToWindow; private boolean isAttachedToWindow;
private boolean showMultiWindowTimeBar; private boolean showMultiWindowTimeBar;
...@@ -432,6 +434,15 @@ public class PlayerControlView extends FrameLayout { ...@@ -432,6 +434,15 @@ public class PlayerControlView extends FrameLayout {
} }
/** /**
* Sets the {@link PlaybackPreparer}.
*
* @param playbackPreparer The {@link PlaybackPreparer}.
*/
public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
this.playbackPreparer = playbackPreparer;
}
/**
* Sets the {@link com.google.android.exoplayer2.ControlDispatcher}. * Sets the {@link com.google.android.exoplayer2.ControlDispatcher}.
* *
* @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null * @param controlDispatcher The {@link com.google.android.exoplayer2.ControlDispatcher}, or null
...@@ -599,7 +610,7 @@ public class PlayerControlView extends FrameLayout { ...@@ -599,7 +610,7 @@ public class PlayerControlView extends FrameLayout {
return; return;
} }
boolean requestPlayPauseFocus = false; boolean requestPlayPauseFocus = false;
boolean playing = player != null && player.getPlayWhenReady(); boolean playing = isPlaying();
if (playButton != null) { if (playButton != null) {
requestPlayPauseFocus |= playing && playButton.isFocused(); requestPlayPauseFocus |= playing && playButton.isFocused();
playButton.setVisibility(playing ? View.GONE : View.VISIBLE); playButton.setVisibility(playing ? View.GONE : View.VISIBLE);
...@@ -811,7 +822,7 @@ public class PlayerControlView extends FrameLayout { ...@@ -811,7 +822,7 @@ public class PlayerControlView extends FrameLayout {
} }
private void requestPlayPauseFocus() { private void requestPlayPauseFocus() {
boolean playing = player != null && player.getPlayWhenReady(); boolean playing = isPlaying();
if (!playing && playButton != null) { if (!playing && playButton != null) {
playButton.requestFocus(); playButton.requestFocus();
} else if (playing && pauseButton != null) { } else if (playing && pauseButton != null) {
...@@ -985,6 +996,13 @@ public class PlayerControlView extends FrameLayout { ...@@ -985,6 +996,13 @@ public class PlayerControlView extends FrameLayout {
return true; return true;
} }
private boolean isPlaying() {
return player != null
&& player.getPlaybackState() != Player.STATE_ENDED
&& player.getPlaybackState() != Player.STATE_IDLE
&& player.getPlayWhenReady();
}
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
private static boolean isHandledMediaKey(int keyCode) { private static boolean isHandledMediaKey(int keyCode) {
return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
...@@ -1085,6 +1103,13 @@ public class PlayerControlView extends FrameLayout { ...@@ -1085,6 +1103,13 @@ public class PlayerControlView extends FrameLayout {
} else if (rewindButton == view) { } else if (rewindButton == view) {
rewind(); rewind();
} else if (playButton == view) { } else if (playButton == view) {
if (player.getPlaybackState() == Player.STATE_IDLE) {
if (playbackPreparer != null) {
playbackPreparer.preparePlayback();
}
} else if (player.getPlaybackState() == Player.STATE_ENDED) {
controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), C.TIME_UNSET);
}
controlDispatcher.dispatchSetPlayWhenReady(player, true); controlDispatcher.dispatchSetPlayWhenReady(player, true);
} else if (pauseButton == view) { } else if (pauseButton == view) {
controlDispatcher.dispatchSetPlayWhenReady(player, false); controlDispatcher.dispatchSetPlayWhenReady(player, false);
......
...@@ -39,6 +39,7 @@ import android.widget.ImageView; ...@@ -39,6 +39,7 @@ 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.ControlDispatcher;
import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher;
import com.google.android.exoplayer2.PlaybackPreparer;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Player.DiscontinuityReason; import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
...@@ -677,6 +678,16 @@ public class PlayerView extends FrameLayout { ...@@ -677,6 +678,16 @@ public class PlayerView extends FrameLayout {
} }
/** /**
* Sets the {@link PlaybackPreparer}.
*
* @param playbackPreparer The {@link PlaybackPreparer}.
*/
public void setPlaybackPreparer(@Nullable PlaybackPreparer playbackPreparer) {
Assertions.checkState(controller != null);
controller.setPlaybackPreparer(playbackPreparer);
}
/**
* Sets the {@link ControlDispatcher}. * Sets the {@link ControlDispatcher}.
* *
* @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link * @param controlDispatcher The {@link ControlDispatcher}, or null to use {@link
......
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