-Made playback manager load circular.
-Improved play previous button to reset before 5 seconds.
This commit is contained in:
parent
6b816a11f7
commit
a0ba3ce2e4
|
@ -340,7 +340,7 @@ public final class BackgroundPlayer extends Service {
|
|||
public void onFastRewind() {
|
||||
if (!isPlayerReady()) return;
|
||||
|
||||
playQueue.offsetIndex(-1);
|
||||
onPlayPrevious();
|
||||
triggerProgressUpdate();
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ public final class BackgroundPlayer extends Service {
|
|||
public void onFastForward() {
|
||||
if (!isPlayerReady()) return;
|
||||
|
||||
playQueue.offsetIndex(+1);
|
||||
onPlayNext();
|
||||
triggerProgressUpdate();
|
||||
}
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
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";
|
||||
|
||||
protected SimpleExoPlayer simpleExoPlayer;
|
||||
|
@ -659,11 +660,15 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
@Override
|
||||
public void onPositionDiscontinuity() {
|
||||
// Refresh the playback if there is a transition to the next video
|
||||
int newIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||
if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with: index = [" + newIndex + "]");
|
||||
final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||
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);
|
||||
} else {
|
||||
playQueue.setIndex(newQueueIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,6 +770,24 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
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) {
|
||||
if (DEBUG) Log.d(TAG, "seekBy() called with: milliSeconds = [" + milliSeconds + "]");
|
||||
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 (e.getX() > playerImpl.getRootView().getWidth() / 2)
|
||||
playerImpl.playQueue.offsetIndex(+1);
|
||||
playerImpl.onPlayNext();
|
||||
//playerImpl.onFastForward();
|
||||
else
|
||||
playerImpl.playQueue.offsetIndex(-1);
|
||||
playerImpl.onPlayPrevious();
|
||||
//playerImpl.onFastRewind();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -575,10 +575,10 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
if (e.getX() > popupWidth / 2) {
|
||||
//playerImpl.onFastForward();
|
||||
playerImpl.playQueue.offsetIndex(+1);
|
||||
playerImpl.onPlayNext();
|
||||
} else {
|
||||
//playerImpl.onFastRewind();
|
||||
playerImpl.playQueue.offsetIndex(-1);
|
||||
playerImpl.onPlayPrevious();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -28,7 +28,8 @@ import io.reactivex.functions.Consumer;
|
|||
public class PlaybackManager {
|
||||
private final String TAG = "PlaybackManager@" + Integer.toHexString(hashCode());
|
||||
// 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 final PlaybackListener playbackListener;
|
||||
|
@ -73,6 +74,11 @@ public class PlaybackManager {
|
|||
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() {
|
||||
return sources.getSize();
|
||||
}
|
||||
|
@ -210,11 +216,14 @@ public class PlaybackManager {
|
|||
|
||||
// The rest are just for seamless playback
|
||||
final int leftBound = Math.max(0, currentIndex - WINDOW_SIZE);
|
||||
final int rightBound = Math.min(playQueue.size(), currentIndex + WINDOW_SIZE);
|
||||
final List<PlayQueueItem> items = playQueue.getStreams().subList(leftBound, rightBound);
|
||||
for (final PlayQueueItem item: items) {
|
||||
load(item);
|
||||
}
|
||||
final int rightLimit = currentIndex + WINDOW_SIZE + 1;
|
||||
final int rightBound = Math.min(playQueue.size(), rightLimit);
|
||||
final List<PlayQueueItem> items = new ArrayList<>(playQueue.getStreams().subList(leftBound, rightBound));
|
||||
|
||||
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) {
|
||||
|
@ -234,7 +243,9 @@ public class PlaybackManager {
|
|||
@Override
|
||||
public void onSuccess(@NonNull StreamInfo streamInfo) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -261,7 +272,7 @@ public class PlaybackManager {
|
|||
|
||||
// Insert source into playlist with position in respect to the play queue
|
||||
// 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;
|
||||
|
||||
int pos = Collections.binarySearch(sourceToQueueIndex, queueIndex);
|
||||
|
@ -269,6 +280,9 @@ public class PlaybackManager {
|
|||
final int sourceIndex = -pos-1;
|
||||
sourceToQueueIndex.add(sourceIndex, queueIndex);
|
||||
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) {
|
||||
if (index < 0 || index >= streams.size()) return;
|
||||
if (index == getIndex()) return;
|
||||
|
||||
queueIndex.set(Math.min(Math.max(0, index), streams.size() - 1));
|
||||
indexEventBroadcast.onNext(new SelectEvent(index));
|
||||
int newIndex = 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) {
|
||||
|
|
|
@ -37,6 +37,8 @@ public class PlayQueueItem implements Serializable {
|
|||
this.duration = streamInfo.duration;
|
||||
|
||||
this.sortedQualityIndex = sortedQualityIndex;
|
||||
|
||||
this.stream = Single.just(streamInfo);
|
||||
}
|
||||
|
||||
PlayQueueItem(final StreamInfoItem streamInfoItem) {
|
||||
|
|
Loading…
Reference in New Issue