mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
-Refactored Playback manager to expose only readonly methods.
-Removed swap and move operations. -Code clean up.
This commit is contained in:
parent
9413856463
commit
f8abf92a66
@ -382,9 +382,6 @@ public class BackgroundPlayer extends Service {
|
||||
public void sync(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
super.sync(info, sortedStreamsIndex);
|
||||
|
||||
setVideoTitle(info.name);
|
||||
setUploaderName(info.uploader_name);
|
||||
|
||||
notRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
||||
notRemoteView.setTextViewText(R.id.notificationArtist, getUploaderName());
|
||||
bigNotRemoteView.setTextViewText(R.id.notificationSongName, getVideoTitle());
|
||||
|
@ -93,7 +93,6 @@ import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.annotations.NonNull;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.disposables.SerialDisposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Predicate;
|
||||
|
||||
@ -136,11 +135,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
public static final String RESTORE_QUEUE_INDEX = "restore_queue_index";
|
||||
public static final String RESTORE_WINDOW_POS = "restore_window_pos";
|
||||
|
||||
protected String videoUrl = "";
|
||||
protected String videoTitle = "";
|
||||
protected String videoThumbnailUrl = "";
|
||||
protected String uploaderName = "";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playlist
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -148,8 +142,11 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
protected PlaybackManager playbackManager;
|
||||
protected PlayQueue playQueue;
|
||||
|
||||
protected int queueStartPos = 0;
|
||||
protected long videoStartPos = -1;
|
||||
private boolean isRecovery = false;
|
||||
private int queuePos = 0;
|
||||
private long videoPos = -1;
|
||||
|
||||
protected StreamInfo currentInfo;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Player
|
||||
@ -246,8 +243,10 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||
if (intent == null) return;
|
||||
|
||||
queueStartPos = intent.getIntExtra(RESTORE_QUEUE_INDEX, 0);
|
||||
videoStartPos = intent.getLongExtra(START_POSITION, 0);
|
||||
setRecovery(
|
||||
intent.getIntExtra(RESTORE_QUEUE_INDEX, 0),
|
||||
intent.getLongExtra(START_POSITION, 0)
|
||||
);
|
||||
setPlaybackSpeed(intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed()));
|
||||
|
||||
switch (intent.getStringExtra(INTENT_TYPE)) {
|
||||
@ -535,21 +534,37 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
public void onTimelineChanged(Timeline timeline, Object manifest) {
|
||||
if (DEBUG) Log.d(TAG, "onTimelineChanged(), timeline size = " + timeline.getWindowCount());
|
||||
|
||||
if (simpleExoPlayer.getCurrentWindowIndex() != playbackManager.getCurrentSourceIndex()) {
|
||||
if (timeline.getWindowCount() > playbackManager.getCurrentSourceIndex()) {
|
||||
if (DEBUG) Log.d(TAG, "Rewinding to correct window");
|
||||
simpleExoPlayer.seekToDefaultPosition(playbackManager.getCurrentSourceIndex());
|
||||
}
|
||||
final int currentSourceIndex = playbackManager.getCurrentSourceIndex();
|
||||
|
||||
// Check timeline has window
|
||||
if (simpleExoPlayer.getCurrentTimeline().getWindowCount() <= currentSourceIndex) return;
|
||||
|
||||
// Check if window is ready
|
||||
Timeline.Window window = new Timeline.Window();
|
||||
simpleExoPlayer.getCurrentTimeline().getWindow(currentSourceIndex, window);
|
||||
if (window.isDynamic) return;
|
||||
|
||||
// Check if already playing correct window
|
||||
final boolean isCurrentWindowCorrect = simpleExoPlayer.getCurrentWindowIndex() == currentSourceIndex;
|
||||
if (isCurrentWindowCorrect && getCurrentState() == STATE_PLAYING) return;
|
||||
|
||||
// Check if recovering on correct item
|
||||
if (isRecovery && queuePos == playQueue.getIndex() && isCurrentWindowCorrect) {
|
||||
if (DEBUG) Log.d(TAG, "Rewinding to recovery window: " + currentSourceIndex + " at: " + getTimeString((int)videoPos));
|
||||
simpleExoPlayer.seekTo(currentSourceIndex, videoPos);
|
||||
isRecovery = false;
|
||||
} else if (!isCurrentWindowCorrect) { // Or if on wrong window
|
||||
final long startPos = currentInfo != null ? currentInfo.start_position : 0;
|
||||
if (DEBUG) Log.d(TAG, "Rewinding to correct window: " + currentSourceIndex + " at: " + getTimeString((int)startPos));
|
||||
simpleExoPlayer.seekTo(currentSourceIndex, startPos);
|
||||
}
|
||||
|
||||
if (!simpleExoPlayer.isCurrentWindowDynamic() && simpleExoPlayer.isCurrentWindowSeekable()) {
|
||||
simpleExoPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
// Good to go...
|
||||
simpleExoPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
||||
Log.w(TAG, "onTracksChanged() called, unsupported operation. Is this expected?");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -604,8 +619,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
@Override
|
||||
public void onPlayerError(ExoPlaybackException error) {
|
||||
if (DEBUG) Log.d(TAG, "onPlayerError() called with: error = [" + error + "]");
|
||||
playbackManager.report(error);
|
||||
|
||||
playQueue.remove(playQueue.getIndex());
|
||||
onError(error);
|
||||
}
|
||||
|
||||
@ -615,7 +629,9 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
int newIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||
if (DEBUG) Log.d(TAG, "onPositionDiscontinuity() called with: index = [" + newIndex + "]");
|
||||
|
||||
playbackManager.refresh(newIndex);
|
||||
if (newIndex == playbackManager.getCurrentSourceIndex() + 1) {
|
||||
playQueue.offsetIndex(+1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -633,6 +649,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
if (DEBUG) Log.d(TAG, "Blocking...");
|
||||
|
||||
simpleExoPlayer.stop();
|
||||
isPrepared = false;
|
||||
|
||||
changeState(STATE_BUFFERING);
|
||||
}
|
||||
@ -642,13 +659,8 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
if (simpleExoPlayer == null) return;
|
||||
if (DEBUG) Log.d(TAG, "Unblocking...");
|
||||
|
||||
if (queueStartPos != playQueue.getIndex()) {
|
||||
queueStartPos = playQueue.getIndex();
|
||||
videoStartPos = 0;
|
||||
}
|
||||
|
||||
simpleExoPlayer.prepare(playbackManager.getMediaSource());
|
||||
simpleExoPlayer.seekTo(playbackManager.getCurrentSourceIndex(), videoStartPos);
|
||||
simpleExoPlayer.prepare(playbackManager.getMediaSource(), true, true);
|
||||
isPrepared = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -656,13 +668,10 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
if (simpleExoPlayer == null) return;
|
||||
if (DEBUG) Log.d(TAG, "Syncing...");
|
||||
|
||||
videoUrl = info.url;
|
||||
videoThumbnailUrl = info.thumbnail_url;
|
||||
videoTitle = info.name;
|
||||
|
||||
currentInfo = info;
|
||||
onTimelineChanged(simpleExoPlayer.getCurrentTimeline(), null);
|
||||
|
||||
initThumbnail(videoThumbnailUrl);
|
||||
initThumbnail(info.thumbnail_url);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -774,7 +783,11 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
}
|
||||
|
||||
public void triggerProgressUpdate() {
|
||||
onUpdateProgress((int) simpleExoPlayer.getCurrentPosition(), (int) simpleExoPlayer.getDuration(), simpleExoPlayer.getBufferedPercentage());
|
||||
onUpdateProgress(
|
||||
(int) simpleExoPlayer.getCurrentPosition(),
|
||||
(int) simpleExoPlayer.getDuration(),
|
||||
simpleExoPlayer.getBufferedPercentage()
|
||||
);
|
||||
}
|
||||
|
||||
public void animateAudio(final float from, final float to, int duration) {
|
||||
@ -823,35 +836,19 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
}
|
||||
|
||||
public String getVideoUrl() {
|
||||
return videoUrl;
|
||||
return currentInfo.url;
|
||||
}
|
||||
|
||||
public void setVideoUrl(String videoUrl) {
|
||||
this.videoUrl = videoUrl;
|
||||
}
|
||||
|
||||
public long getVideoStartPos() {
|
||||
return videoStartPos;
|
||||
}
|
||||
|
||||
public void setVideoStartPos(long videoStartPos) {
|
||||
this.videoStartPos = videoStartPos;
|
||||
public long getVideoPos() {
|
||||
return videoPos;
|
||||
}
|
||||
|
||||
public String getVideoTitle() {
|
||||
return videoTitle;
|
||||
}
|
||||
|
||||
public void setVideoTitle(String videoTitle) {
|
||||
this.videoTitle = videoTitle;
|
||||
return currentInfo.name;
|
||||
}
|
||||
|
||||
public String getUploaderName() {
|
||||
return uploaderName;
|
||||
}
|
||||
|
||||
public void setUploaderName(String uploaderName) {
|
||||
this.uploaderName = uploaderName;
|
||||
return currentInfo.uploader_name;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
@ -866,14 +863,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
isPrepared = prepared;
|
||||
}
|
||||
|
||||
public String getVideoThumbnailUrl() {
|
||||
return videoThumbnailUrl;
|
||||
}
|
||||
|
||||
public void setVideoThumbnailUrl(String videoThumbnailUrl) {
|
||||
this.videoThumbnailUrl = videoThumbnailUrl;
|
||||
}
|
||||
|
||||
public float getPlaybackSpeed() {
|
||||
return simpleExoPlayer.getPlaybackParameters().speed;
|
||||
}
|
||||
@ -897,4 +886,15 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||
public boolean isProgressLoopRunning() {
|
||||
return progressUpdateReactor != null && !progressUpdateReactor.isDisposed();
|
||||
}
|
||||
|
||||
public boolean getRecovery() {
|
||||
return isRecovery;
|
||||
}
|
||||
|
||||
public void setRecovery(final int queuePos, final long windowPos) {
|
||||
if (DEBUG) Log.d(TAG, "Setting recovery, queue: " + queuePos + ", pos: " + windowPos);
|
||||
this.isRecovery = true;
|
||||
this.queuePos = queuePos;
|
||||
this.videoPos = windowPos;
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,10 @@ public class MainVideoPlayer extends Activity {
|
||||
if (DEBUG) Log.d(TAG, "onStop() called");
|
||||
activityPaused = true;
|
||||
if (playerImpl.getPlayer() != null) {
|
||||
playerImpl.setVideoStartPos((int) playerImpl.getPlayer().getCurrentPosition());
|
||||
playerImpl.setRecovery(
|
||||
playerImpl.getCurrentQueueIndex(),
|
||||
(int) playerImpl.getPlayer().getCurrentPosition()
|
||||
);
|
||||
playerImpl.destroyPlayer();
|
||||
}
|
||||
}
|
||||
@ -224,13 +227,6 @@ public class MainVideoPlayer extends Activity {
|
||||
screenRotationButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIntent(Intent intent) {
|
||||
super.handleIntent(intent);
|
||||
titleTextView.setText(getVideoTitle());
|
||||
channelTextView.setText(getUploaderName());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -263,7 +259,8 @@ public class MainVideoPlayer extends Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
context.startService(NavigationHelper.getOpenVideoPlayerIntent(context, PopupVideoPlayer.class, this));
|
||||
final Intent intent = NavigationHelper.getOpenVideoPlayerIntent(context, PopupVideoPlayer.class, this);
|
||||
context.startService(intent);
|
||||
destroyPlayer();
|
||||
|
||||
((View) getControlAnimationView().getParent()).setVisibility(View.GONE);
|
||||
|
@ -50,15 +50,11 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.BuildConfig;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
|
||||
@ -68,19 +64,16 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.playback.PlaybackManager;
|
||||
import org.schabi.newpipe.playlist.PlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
@ -745,9 +738,6 @@ public class PopupVideoPlayer extends Service {
|
||||
}
|
||||
|
||||
public void onReceive(final StreamInfo info) {
|
||||
if (info.start_position > 0) playerImpl.setVideoStartPos(info.start_position * 1000);
|
||||
else playerImpl.setVideoStartPos(-1);
|
||||
|
||||
mainHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -234,8 +234,6 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||
final Serializable serializable = intent.getSerializableExtra(PLAY_QUEUE);
|
||||
if (!(serializable instanceof PlayQueue)) return;
|
||||
|
||||
selectedIndexStream = intent.getIntExtra(INDEX_SEL_VIDEO_STREAM, -1);
|
||||
|
||||
playQueue = (PlayQueue) serializable;
|
||||
playQueue.init();
|
||||
|
||||
@ -406,12 +404,6 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||
public void onPrepared(boolean playWhenReady) {
|
||||
if (DEBUG) Log.d(TAG, "onPrepared() called with: playWhenReady = [" + playWhenReady + "]");
|
||||
|
||||
if (videoStartPos > 0) {
|
||||
playbackSeekBar.setProgress((int) videoStartPos);
|
||||
playbackCurrentTime.setText(getTimeString((int) videoStartPos));
|
||||
videoStartPos = -1;
|
||||
}
|
||||
|
||||
playbackSeekBar.setMax((int) simpleExoPlayer.getDuration());
|
||||
playbackEndTime.setText(getTimeString((int) simpleExoPlayer.getDuration()));
|
||||
playbackSpeed.setText(formatSpeed(getPlaybackSpeed()));
|
||||
@ -453,6 +445,8 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||
|
||||
protected void onFullScreenButtonClicked() {
|
||||
if (!isPlayerReady()) return;
|
||||
|
||||
changeState(STATE_BUFFERING);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -492,11 +486,11 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||
Log.d(TAG, "onMenuItemClick() called with: menuItem = [" + menuItem + "], menuItem.getItemId = [" + menuItem.getItemId() + "]");
|
||||
|
||||
if (qualityPopupMenuGroupId == menuItem.getGroupId()) {
|
||||
if (selectedIndexStream == menuItem.getItemId()) return true;
|
||||
if (selectedIndexStream == menuItem.getItemId() || getRecovery()) return true;
|
||||
|
||||
queueStartPos = playQueue.getIndex();
|
||||
videoStartPos = simpleExoPlayer.getCurrentPosition();
|
||||
playbackManager.updateCurrent(menuItem.getItemId());
|
||||
final int index = playQueue.getIndex();
|
||||
setRecovery(index, simpleExoPlayer.getCurrentPosition());
|
||||
playQueue.updateIndex(index, menuItem.getItemId());
|
||||
|
||||
qualityTextView.setText(menuItem.getTitle());
|
||||
return true;
|
||||
|
@ -12,7 +12,6 @@ import org.schabi.newpipe.playlist.PlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.events.PlayQueueMessage;
|
||||
import org.schabi.newpipe.playlist.events.RemoveEvent;
|
||||
import org.schabi.newpipe.playlist.events.MoveEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -29,7 +28,7 @@ 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
|
||||
private static final int WINDOW_SIZE = 2;
|
||||
private static final int WINDOW_SIZE = 3;
|
||||
|
||||
private final PlaybackListener playbackListener;
|
||||
private final PlayQueue playQueue;
|
||||
@ -77,37 +76,6 @@ public class PlaybackManager {
|
||||
return sources;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the player has transitioned to another stream.
|
||||
* */
|
||||
public void refresh(final int newSourceIndex) {
|
||||
if (sourceToQueueIndex.indexOf(newSourceIndex) != -1 && newSourceIndex == getCurrentSourceIndex() + 1) {
|
||||
playQueue.offsetIndex(+1);
|
||||
}
|
||||
}
|
||||
|
||||
public void report(final Exception error) {
|
||||
// ignore error checking for now, just remove the current index
|
||||
if (error == null) return;
|
||||
|
||||
tryBlock();
|
||||
|
||||
final int index = playQueue.getIndex();
|
||||
playQueue.remove(index);
|
||||
|
||||
resetSources();
|
||||
load();
|
||||
}
|
||||
|
||||
public void updateCurrent(final int newSortedStreamsIndex) {
|
||||
tryBlock();
|
||||
|
||||
PlayQueueItem item = playQueue.getCurrent();
|
||||
item.setSortedQualityIndex(newSortedStreamsIndex);
|
||||
|
||||
resetSources();
|
||||
load();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (playQueueReactor != null) playQueueReactor.cancel();
|
||||
@ -146,14 +114,19 @@ public class PlaybackManager {
|
||||
case APPEND:
|
||||
break;
|
||||
case SELECT:
|
||||
onSelect();
|
||||
if (isBlocked) break;
|
||||
if (isCurrentIndexLoaded()) sync(); else tryBlock();
|
||||
break;
|
||||
case REMOVE:
|
||||
final RemoveEvent removeEvent = (RemoveEvent) event;
|
||||
if (removeEvent.isCurrent()) tryBlock();
|
||||
remove(removeEvent.index());
|
||||
break;
|
||||
case MOVE:
|
||||
throw new UnsupportedOperationException("Move not yet supported");
|
||||
case UPDATE:
|
||||
case SHUFFLE:
|
||||
tryBlock();
|
||||
resetSources();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -208,30 +181,6 @@ public class PlaybackManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Responds to a SELECT event.
|
||||
*
|
||||
* If the player is being blocked, then nothing should happen.
|
||||
*
|
||||
* Otherwise:
|
||||
*
|
||||
* When the selected item is already loaded, then we simply synchronize and
|
||||
* start loading some more items.
|
||||
*
|
||||
* When the current item has not been fully loaded, then the player will be
|
||||
* blocked. The sources will be reset and reloaded, to conserve memory.
|
||||
* */
|
||||
private void onSelect() {
|
||||
if (isBlocked) return;
|
||||
|
||||
if (isCurrentIndexLoaded()) {
|
||||
sync();
|
||||
} else {
|
||||
tryBlock();
|
||||
resetSources();
|
||||
}
|
||||
}
|
||||
|
||||
private void sync() {
|
||||
final PlayQueueItem currentItem = playQueue.getCurrent();
|
||||
|
||||
@ -319,13 +268,14 @@ public class PlaybackManager {
|
||||
if (queueIndex < 0) return;
|
||||
|
||||
final int sourceIndex = sourceToQueueIndex.indexOf(queueIndex);
|
||||
if (sourceIndex != -1) {
|
||||
sourceToQueueIndex.remove(sourceIndex);
|
||||
sources.removeMediaSource(sourceIndex);
|
||||
// Will be slow on really large arrays, fast enough for typical use case
|
||||
for (int i = sourceIndex; i < sourceToQueueIndex.size(); i++) {
|
||||
sourceToQueueIndex.set(i, sourceToQueueIndex.get(i) - 1);
|
||||
}
|
||||
if (sourceIndex == -1) return;
|
||||
|
||||
sourceToQueueIndex.remove(sourceIndex);
|
||||
sources.removeMediaSource(sourceIndex);
|
||||
|
||||
// Will be slow on really large arrays, fast enough for typical use case
|
||||
for (int i = sourceIndex; i < sourceToQueueIndex.size(); i++) {
|
||||
sourceToQueueIndex.set(i, sourceToQueueIndex.get(i) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,14 +10,13 @@ import org.schabi.newpipe.playlist.events.InitEvent;
|
||||
import org.schabi.newpipe.playlist.events.PlayQueueMessage;
|
||||
import org.schabi.newpipe.playlist.events.RemoveEvent;
|
||||
import org.schabi.newpipe.playlist.events.SelectEvent;
|
||||
import org.schabi.newpipe.playlist.events.MoveEvent;
|
||||
import org.schabi.newpipe.playlist.events.UpdateEvent;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import io.reactivex.BackpressureStrategy;
|
||||
@ -96,7 +95,7 @@ public abstract class PlayQueue implements Serializable {
|
||||
}
|
||||
|
||||
public int indexOf(final PlayQueueItem item) {
|
||||
// reference equality, can't think of a better way to do this
|
||||
// referential equality, can't think of a better way to do this
|
||||
// todo: better than this
|
||||
return streams.indexOf(item);
|
||||
}
|
||||
@ -134,6 +133,13 @@ public abstract class PlayQueue implements Serializable {
|
||||
setIndex(getIndex() + offset);
|
||||
}
|
||||
|
||||
public synchronized void updateIndex(final int index, final int selectedQuality) {
|
||||
if (index < 0 || index >= streams.size()) return;
|
||||
|
||||
get(index).setSortedQualityIndex(selectedQuality);
|
||||
broadcast(new UpdateEvent(index));
|
||||
}
|
||||
|
||||
protected synchronized void append(final PlayQueueItem item) {
|
||||
streams.add(item);
|
||||
broadcast(new AppendEvent(1));
|
||||
@ -158,29 +164,6 @@ public abstract class PlayQueue implements Serializable {
|
||||
broadcast(new RemoveEvent(index, isCurrent));
|
||||
}
|
||||
|
||||
protected synchronized void swap(final int source, final int target) {
|
||||
if (source < 0 || target < 0) return;
|
||||
|
||||
final List<PlayQueueItem> items = streams;
|
||||
if (source < items.size() && target < items.size()) {
|
||||
// Swap two items
|
||||
final PlayQueueItem sourceItem = items.get(source);
|
||||
final PlayQueueItem targetItem = items.get(target);
|
||||
|
||||
items.set(target, sourceItem);
|
||||
items.set(source, targetItem);
|
||||
|
||||
// If the current playing index is one of the swapped indices, change that as well
|
||||
final int index = queueIndex.get();
|
||||
if (index == source || index == target) {
|
||||
final int newIndex = index == source ? target : source;
|
||||
queueIndex.set(newIndex);
|
||||
}
|
||||
|
||||
broadcast(new MoveEvent(source, target));
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Rx Broadcast
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -82,10 +82,6 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
||||
playQueue.remove(index);
|
||||
}
|
||||
|
||||
public void swap(final int source, final int target) {
|
||||
playQueue.swap(source, target);
|
||||
}
|
||||
|
||||
private void startReactor() {
|
||||
final Observer<PlayQueueMessage> observer = new Observer<PlayQueueMessage>() {
|
||||
@Override
|
||||
|
@ -1,25 +0,0 @@
|
||||
package org.schabi.newpipe.playlist.events;
|
||||
|
||||
|
||||
public class MoveEvent implements PlayQueueMessage {
|
||||
final private int from;
|
||||
final private int to;
|
||||
|
||||
@Override
|
||||
public PlayQueueEvent type() {
|
||||
return PlayQueueEvent.MOVE;
|
||||
}
|
||||
|
||||
public MoveEvent(final int from, final int to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public int getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public int getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
@ -3,10 +3,7 @@ package org.schabi.newpipe.playlist.events;
|
||||
public enum PlayQueueEvent {
|
||||
INIT,
|
||||
|
||||
// sent when the user is seamlessly transitioned by exoplayer to the next stream
|
||||
NEXT,
|
||||
|
||||
// sent when the user transitions to an unbuffered period
|
||||
// sent when the index is changed
|
||||
SELECT,
|
||||
|
||||
// sent when more streams are added to the play queue
|
||||
@ -16,6 +13,12 @@ public enum PlayQueueEvent {
|
||||
REMOVE,
|
||||
|
||||
// sent when two streams swap place in the play queue
|
||||
MOVE
|
||||
MOVE,
|
||||
|
||||
// sent when a stream is updated
|
||||
UPDATE,
|
||||
|
||||
// send when queue is shuffled
|
||||
SHUFFLE
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,18 @@
|
||||
package org.schabi.newpipe.playlist.events;
|
||||
|
||||
public class UpdateEvent implements PlayQueueMessage {
|
||||
final private int updatedIndex;
|
||||
|
||||
@Override
|
||||
public PlayQueueEvent type() {
|
||||
return PlayQueueEvent.UPDATE;
|
||||
}
|
||||
|
||||
public UpdateEvent(final int updatedIndex) {
|
||||
this.updatedIndex = updatedIndex;
|
||||
}
|
||||
|
||||
public int index() {
|
||||
return updatedIndex;
|
||||
}
|
||||
}
|
@ -71,7 +71,6 @@ public class NavigationHelper {
|
||||
return new Intent(context, targetClazz)
|
||||
.putExtra(BasePlayer.INTENT_TYPE, VideoPlayer.PLAYER_INTENT)
|
||||
.putExtra(VideoPlayer.PLAY_QUEUE, instance.getPlayQueue())
|
||||
.putExtra(VideoPlayer.INDEX_SEL_VIDEO_STREAM, instance.getSelectedStreamIndex())
|
||||
.putExtra(VideoPlayer.RESTORE_QUEUE_INDEX, instance.getCurrentQueueIndex())
|
||||
.putExtra(BasePlayer.START_POSITION, instance.getPlayer().getCurrentPosition())
|
||||
.putExtra(BasePlayer.PLAYBACK_SPEED, instance.getPlaybackSpeed());
|
||||
|
Loading…
Reference in New Issue
Block a user