From 31e2fa8597df3aab1822d994f167517952eb8c85 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 14 Dec 2016 05:33:36 -0800 Subject: [PATCH] Add hook for modifying or cancelling a user invoked seek ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=142007001 --- .../google/android/exoplayer2/ExoPlayer.java | 10 +-- .../exoplayer2/ui/PlaybackControlView.java | 70 +++++++++++++++++-- .../exoplayer2/ui/SimpleExoPlayerView.java | 12 ++++ 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index 06d7af163f..6c64d2c0f3 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -330,17 +330,19 @@ public interface ExoPlayer { /** * Seeks to a position specified in milliseconds in the current window. * - * @param windowPositionMs The seek position 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 windowPositionMs); + void seekTo(long positionMs); /** * Seeks to a position specified in milliseconds in the specified window. * * @param windowIndex The index of the window. - * @param windowPositionMs The seek position in the specified 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 windowPositionMs); + void seekTo(int windowIndex, long positionMs); /** * Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java index 54812185e7..40e814dab3 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java @@ -148,14 +148,45 @@ public class PlaybackControlView extends FrameLayout { * Listener to be notified about changes of the visibility of the UI control. */ public interface VisibilityListener { + /** * Called when the visibility changes. * * @param visibility The new visibility. Either {@link View#VISIBLE} or {@link View#GONE}. */ void onVisibilityChange(int visibility); + } + /** + * Dispatches seek operations to the player. + */ + public interface SeekDispatcher { + + /** + * @param player The player to seek. + * @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 seek was dispatched. False otherwise. + */ + boolean dispatchSeek(ExoPlayer player, int windowIndex, long positionMs); + + } + + /** + * Default {@link SeekDispatcher} that dispatches seeks to the player without modification. + */ + public static final SeekDispatcher DEFAULT_SEEK_DISPATCHER = new SeekDispatcher() { + + @Override + public boolean dispatchSeek(ExoPlayer player, int windowIndex, long positionMs) { + player.seekTo(windowIndex, positionMs); + return true; + } + + }; + public static final int DEFAULT_FAST_FORWARD_MS = 15000; public static final int DEFAULT_REWIND_MS = 5000; public static final int DEFAULT_SHOW_TIMEOUT_MS = 5000; @@ -178,6 +209,7 @@ public class PlaybackControlView extends FrameLayout { private final Timeline.Window currentWindow; private ExoPlayer player; + private SeekDispatcher seekDispatcher; private VisibilityListener visibilityListener; private boolean isAttachedToWindow; @@ -234,6 +266,7 @@ public class PlaybackControlView extends FrameLayout { formatBuilder = new StringBuilder(); formatter = new Formatter(formatBuilder, Locale.getDefault()); componentListener = new ComponentListener(); + seekDispatcher = DEFAULT_SEEK_DISPATCHER; LayoutInflater.from(context).inflate(controllerLayoutId, this); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); @@ -306,6 +339,16 @@ public class PlaybackControlView extends FrameLayout { this.visibilityListener = listener; } + /** + * Sets the {@link SeekDispatcher}. + * + * @param seekDispatcher The {@link SeekDispatcher}, or null to use + * {@link #DEFAULT_SEEK_DISPATCHER}. + */ + public void setSeekDispatcher(SeekDispatcher seekDispatcher) { + this.seekDispatcher = seekDispatcher == null ? DEFAULT_SEEK_DISPATCHER : seekDispatcher; + } + /** * Sets the rewind increment in milliseconds. * @@ -550,9 +593,9 @@ public class PlaybackControlView extends FrameLayout { currentTimeline.getWindow(currentWindowIndex, currentWindow); if (currentWindowIndex > 0 && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS || (currentWindow.isDynamic && !currentWindow.isSeekable))) { - player.seekToDefaultPosition(currentWindowIndex - 1); + seekTo(currentWindowIndex - 1, C.TIME_UNSET); } else { - player.seekTo(0); + seekTo(0); } } @@ -563,9 +606,9 @@ public class PlaybackControlView extends FrameLayout { } int currentWindowIndex = player.getCurrentWindowIndex(); if (currentWindowIndex < currentTimeline.getWindowCount() - 1) { - player.seekToDefaultPosition(currentWindowIndex + 1); + seekTo(currentWindowIndex + 1, C.TIME_UNSET); } else if (currentTimeline.getWindow(currentWindowIndex, currentWindow, false).isDynamic) { - player.seekToDefaultPosition(); + seekTo(currentWindowIndex, C.TIME_UNSET); } } @@ -573,14 +616,27 @@ public class PlaybackControlView extends FrameLayout { if (rewindMs <= 0) { return; } - player.seekTo(Math.max(player.getCurrentPosition() - rewindMs, 0)); + seekTo(Math.max(player.getCurrentPosition() - rewindMs, 0)); } private void fastForward() { if (fastForwardMs <= 0) { return; } - player.seekTo(Math.min(player.getCurrentPosition() + fastForwardMs, player.getDuration())); + seekTo(Math.min(player.getCurrentPosition() + fastForwardMs, player.getDuration())); + } + + private void seekTo(long positionMs) { + seekTo(player.getCurrentWindowIndex(), positionMs); + } + + private void seekTo(int windowIndex, long positionMs) { + boolean dispatched = seekDispatcher.dispatchSeek(player, windowIndex, positionMs); + if (!dispatched) { + // The seek wasn't dispatched. If the progress bar was dragged by the user to perform the + // seek then it'll now be in the wrong position. Trigger a progress update to snap it back. + updateProgress(); + } } @Override @@ -688,7 +744,7 @@ public class PlaybackControlView extends FrameLayout { public void onStopTrackingTouch(SeekBar seekBar) { dragging = false; if (player != null) { - player.seekTo(positionValue(seekBar.getProgress())); + seekTo(positionValue(seekBar.getProgress())); } hideAfterTimeout(); } diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index c7cb5919b7..d094266fcc 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -44,6 +44,7 @@ import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode; +import com.google.android.exoplayer2.ui.PlaybackControlView.SeekDispatcher; import com.google.android.exoplayer2.util.Assertions; import java.util.List; @@ -440,6 +441,17 @@ public final class SimpleExoPlayerView extends FrameLayout { controller.setVisibilityListener(listener); } + /** + * Sets the {@link SeekDispatcher}. + * + * @param seekDispatcher The {@link SeekDispatcher}, or null to use + * {@link PlaybackControlView#DEFAULT_SEEK_DISPATCHER}. + */ + public void setSeekDispatcher(SeekDispatcher seekDispatcher) { + Assertions.checkState(controller != null); + controller.setSeekDispatcher(seekDispatcher); + } + /** * Sets the rewind increment in milliseconds. *