-Made playback manager load circular.
-Improved play previous button to reset before 5 seconds.
This commit is contained in:
parent
6b816a11f7
commit
a0ba3ce2e4
7 changed files with 63 additions and 20 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue