-Made playback manager load circular.

-Improved play previous button to reset before 5 seconds.
This commit is contained in:
John Zhen M 2017-09-17 20:14:02 -07:00 committed by John Zhen Mo
parent 6b816a11f7
commit a0ba3ce2e4
7 changed files with 63 additions and 20 deletions

View file

@ -340,7 +340,7 @@ public final class BackgroundPlayer extends Service {
public void onFastRewind() { public void onFastRewind() {
if (!isPlayerReady()) return; if (!isPlayerReady()) return;
playQueue.offsetIndex(-1); onPlayPrevious();
triggerProgressUpdate(); triggerProgressUpdate();
} }
@ -348,7 +348,7 @@ public final class BackgroundPlayer extends Service {
public void onFastForward() { public void onFastForward() {
if (!isPlayerReady()) return; if (!isPlayerReady()) return;
playQueue.offsetIndex(+1); onPlayNext();
triggerProgressUpdate(); triggerProgressUpdate();
} }

View file

@ -153,6 +153,7 @@ public abstract class BasePlayer implements Player.EventListener,
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public int FAST_FORWARD_REWIND_AMOUNT = 10000; // 10 Seconds public int FAST_FORWARD_REWIND_AMOUNT = 10000; // 10 Seconds
public int PLAY_PREV_ACTIVATION_LIMIT = 5000; // 5 seconds
public static final String CACHE_FOLDER_NAME = "exoplayer"; public static final String CACHE_FOLDER_NAME = "exoplayer";
protected SimpleExoPlayer simpleExoPlayer; protected SimpleExoPlayer simpleExoPlayer;
@ -659,11 +660,15 @@ public abstract class BasePlayer implements Player.EventListener,
@Override @Override
public void onPositionDiscontinuity() { public void onPositionDiscontinuity() {
// Refresh the playback if there is a transition to the next video // Refresh the playback if there is a transition to the next video
int newIndex = simpleExoPlayer.getCurrentWindowIndex(); final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with: index = [" + newIndex + "]"); final int newQueueIndex = playbackManager.getQueueIndexOf(newWindowIndex);
if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with: " +
"window index = [" + newWindowIndex + "], queue index = [" + newQueueIndex + "]");
if (newIndex == playbackManager.getCurrentSourceIndex() + 1) { if (newQueueIndex == -1) {
playQueue.offsetIndex(+1); playQueue.offsetIndex(+1);
} else {
playQueue.setIndex(newQueueIndex);
} }
} }
@ -765,6 +770,24 @@ public abstract class BasePlayer implements Player.EventListener,
seekBy(FAST_FORWARD_REWIND_AMOUNT); seekBy(FAST_FORWARD_REWIND_AMOUNT);
} }
public void onPlayPrevious() {
if (simpleExoPlayer == null || playQueue == null || currentInfo == null) return;
if (DEBUG) Log.d(TAG, "onPlayPrevious() called");
if (simpleExoPlayer.getCurrentPosition() <= PLAY_PREV_ACTIVATION_LIMIT) {
playQueue.offsetIndex(-1);
} else {
simpleExoPlayer.seekTo(currentInfo.start_position);
}
}
public void onPlayNext() {
if (playQueue == null) return;
if (DEBUG) Log.d(TAG, "onPlayNext() called");
playQueue.offsetIndex(+1);
}
public void seekBy(int milliSeconds) { public void seekBy(int milliSeconds) {
if (DEBUG) Log.d(TAG, "seekBy() called with: milliSeconds = [" + milliSeconds + "]"); if (DEBUG) Log.d(TAG, "seekBy() called with: milliSeconds = [" + milliSeconds + "]");
if (simpleExoPlayer == null || (isCompleted() && milliSeconds > 0) || ((milliSeconds < 0 && simpleExoPlayer.getCurrentPosition() == 0))) if (simpleExoPlayer == null || (isCompleted() && milliSeconds > 0) || ((milliSeconds < 0 && simpleExoPlayer.getCurrentPosition() == 0)))

View file

@ -468,10 +468,10 @@ public final class MainVideoPlayer extends Activity {
if (!playerImpl.isPlayerReady()) return false; if (!playerImpl.isPlayerReady()) return false;
if (e.getX() > playerImpl.getRootView().getWidth() / 2) if (e.getX() > playerImpl.getRootView().getWidth() / 2)
playerImpl.playQueue.offsetIndex(+1); playerImpl.onPlayNext();
//playerImpl.onFastForward(); //playerImpl.onFastForward();
else else
playerImpl.playQueue.offsetIndex(-1); playerImpl.onPlayPrevious();
//playerImpl.onFastRewind(); //playerImpl.onFastRewind();
return true; return true;

View file

@ -575,10 +575,10 @@ public final class PopupVideoPlayer extends Service {
if (e.getX() > popupWidth / 2) { if (e.getX() > popupWidth / 2) {
//playerImpl.onFastForward(); //playerImpl.onFastForward();
playerImpl.playQueue.offsetIndex(+1); playerImpl.onPlayNext();
} else { } else {
//playerImpl.onFastRewind(); //playerImpl.onFastRewind();
playerImpl.playQueue.offsetIndex(-1); playerImpl.onPlayPrevious();
} }
return true; return true;

View file

@ -28,7 +28,8 @@ import io.reactivex.functions.Consumer;
public class PlaybackManager { public class PlaybackManager {
private final String TAG = "PlaybackManager@" + Integer.toHexString(hashCode()); private final String TAG = "PlaybackManager@" + Integer.toHexString(hashCode());
// One-side rolling window size for default loading // One-side rolling window size for default loading
// Effectively loads WINDOW_SIZE * 2 streams // Effectively loads WINDOW_SIZE * 2 + 1 streams, should be at least 1
// todo: inject this parameter, allow user settings perhaps
private static final int WINDOW_SIZE = 3; private static final int WINDOW_SIZE = 3;
private final PlaybackListener playbackListener; private final PlaybackListener playbackListener;
@ -73,6 +74,11 @@ public class PlaybackManager {
return sourceToQueueIndex.indexOf(playQueue.getIndex()); return sourceToQueueIndex.indexOf(playQueue.getIndex());
} }
public int getQueueIndexOf(final int sourceIndex) {
if (sourceIndex < 0 || sourceIndex >= sourceToQueueIndex.size()) return -1;
return sourceToQueueIndex.get(sourceIndex);
}
public int expectedTimelineSize() { public int expectedTimelineSize() {
return sources.getSize(); return sources.getSize();
} }
@ -210,11 +216,14 @@ public class PlaybackManager {
// The rest are just for seamless playback // The rest are just for seamless playback
final int leftBound = Math.max(0, currentIndex - WINDOW_SIZE); final int leftBound = Math.max(0, currentIndex - WINDOW_SIZE);
final int rightBound = Math.min(playQueue.size(), currentIndex + WINDOW_SIZE); final int rightLimit = currentIndex + WINDOW_SIZE + 1;
final List<PlayQueueItem> items = playQueue.getStreams().subList(leftBound, rightBound); final int rightBound = Math.min(playQueue.size(), rightLimit);
for (final PlayQueueItem item: items) { final List<PlayQueueItem> items = new ArrayList<>(playQueue.getStreams().subList(leftBound, rightBound));
load(item);
} final int excess = rightLimit - playQueue.size();
if (excess >= 0) items.addAll(playQueue.getStreams().subList(0, excess));
for (final PlayQueueItem item: items) load(item);
} }
private void load(@Nullable final PlayQueueItem item) { private void load(@Nullable final PlayQueueItem item) {
@ -234,7 +243,9 @@ public class PlaybackManager {
@Override @Override
public void onSuccess(@NonNull StreamInfo streamInfo) { public void onSuccess(@NonNull StreamInfo streamInfo) {
final MediaSource source = playbackListener.sourceOf(streamInfo, item.getSortedQualityIndex()); final MediaSource source = playbackListener.sourceOf(streamInfo, item.getSortedQualityIndex());
insert(playQueue.indexOf(item), source); final int itemIndex = playQueue.indexOf(item);
// replace all except the currently playing
insert(itemIndex, source, false);
if (tryUnblock()) sync(); if (tryUnblock()) sync();
} }
@ -261,7 +272,7 @@ public class PlaybackManager {
// Insert source into playlist with position in respect to the play queue // Insert source into playlist with position in respect to the play queue
// If the play queue index already exists, then the insert is ignored // If the play queue index already exists, then the insert is ignored
private void insert(final int queueIndex, final MediaSource source) { private void insert(final int queueIndex, final MediaSource source, final boolean replace) {
if (queueIndex < 0) return; if (queueIndex < 0) return;
int pos = Collections.binarySearch(sourceToQueueIndex, queueIndex); int pos = Collections.binarySearch(sourceToQueueIndex, queueIndex);
@ -269,6 +280,9 @@ public class PlaybackManager {
final int sourceIndex = -pos-1; final int sourceIndex = -pos-1;
sourceToQueueIndex.add(sourceIndex, queueIndex); sourceToQueueIndex.add(sourceIndex, queueIndex);
sources.addMediaSource(sourceIndex, source); sources.addMediaSource(sourceIndex, source);
} else if (replace) {
sources.addMediaSource(pos + 1, source);
sources.removeMediaSource(pos);
} }
} }

View file

@ -126,10 +126,14 @@ public abstract class PlayQueue implements Serializable {
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public synchronized void setIndex(final int index) { public synchronized void setIndex(final int index) {
if (index < 0 || index >= streams.size()) return; if (index == getIndex()) return;
queueIndex.set(Math.min(Math.max(0, index), streams.size() - 1)); int newIndex = index;
indexEventBroadcast.onNext(new SelectEvent(index)); if (index < 0) newIndex = 0;
if (index >= streams.size()) newIndex = isComplete() ? index % streams.size() : streams.size() - 1;
queueIndex.set(newIndex);
indexEventBroadcast.onNext(new SelectEvent(newIndex));
} }
public synchronized void offsetIndex(final int offset) { public synchronized void offsetIndex(final int offset) {

View file

@ -37,6 +37,8 @@ public class PlayQueueItem implements Serializable {
this.duration = streamInfo.duration; this.duration = streamInfo.duration;
this.sortedQualityIndex = sortedQualityIndex; this.sortedQualityIndex = sortedQualityIndex;
this.stream = Single.just(streamInfo);
} }
PlayQueueItem(final StreamInfoItem streamInfoItem) { PlayQueueItem(final StreamInfoItem streamInfoItem) {