-Added seamless shuffling.

-Reenabled full window loading in MediaSourceManager.
This commit is contained in:
John Zhen Mo 2018-03-03 20:58:06 -08:00
parent a88e19a8ed
commit 59558efed1
5 changed files with 50 additions and 25 deletions

View File

@ -384,9 +384,11 @@ public final class BackgroundPlayer extends Service {
@Nullable final StreamInfo info, @Nullable final StreamInfo info,
final int newPlayQueueIndex, final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) { final boolean hasPlayQueueItemChanged) {
resetNotification(); if (shouldUpdateOnProgress || hasPlayQueueItemChanged) {
updateNotification(-1); resetNotification();
updateMetadata(); updateNotification(-1);
updateMetadata();
}
} }
@Override @Override
@ -434,7 +436,8 @@ public final class BackgroundPlayer extends Service {
private void updatePlayback() { private void updatePlayback() {
if (activityListener != null && simpleExoPlayer != null && playQueue != null) { if (activityListener != null && simpleExoPlayer != null && playQueue != null) {
activityListener.onPlaybackUpdate(currentState, getRepeatMode(), playQueue.isShuffled(), getPlaybackParameters()); activityListener.onPlaybackUpdate(currentState, getRepeatMode(),
playQueue.isShuffled(), getPlaybackParameters());
} }
} }

View File

@ -494,14 +494,8 @@ public abstract class BasePlayer implements
public void onShuffleClicked() { public void onShuffleClicked() {
if (DEBUG) Log.d(TAG, "onShuffleClicked() called"); if (DEBUG) Log.d(TAG, "onShuffleClicked() called");
if (playQueue == null) return; if (simpleExoPlayer == null) return;
simpleExoPlayer.setShuffleModeEnabled(!simpleExoPlayer.getShuffleModeEnabled());
setRecovery();
if (playQueue.isShuffled()) {
playQueue.unshuffle();
} else {
playQueue.shuffle();
}
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -765,6 +759,12 @@ public abstract class BasePlayer implements
public void onShuffleModeEnabledChanged(final boolean shuffleModeEnabled) { public void onShuffleModeEnabledChanged(final boolean shuffleModeEnabled) {
if (DEBUG) Log.d(TAG, "ExoPlayer - onShuffleModeEnabledChanged() called with: " + if (DEBUG) Log.d(TAG, "ExoPlayer - onShuffleModeEnabledChanged() called with: " +
"mode = [" + shuffleModeEnabled + "]"); "mode = [" + shuffleModeEnabled + "]");
if (playQueue == null) return;
if (shuffleModeEnabled) {
playQueue.shuffle();
} else {
playQueue.unshuffle();
}
} }
@Override @Override
@ -803,7 +803,7 @@ public abstract class BasePlayer implements
public void onPlaybackSynchronize(@NonNull final PlayQueueItem item, public void onPlaybackSynchronize(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info) { @Nullable final StreamInfo info) {
if (DEBUG) Log.d(TAG, "Playback - onPlaybackSynchronize() called with " + if (DEBUG) Log.d(TAG, "Playback - onPlaybackSynchronize() called with " +
(info == null ? "available" : "null") + " info, " + (info != null ? "available" : "null") + " info, " +
"item=[" + item.getTitle() + "], url=[" + item.getUrl() + "]"); "item=[" + item.getTitle() + "], url=[" + item.getUrl() + "]");
final boolean hasPlayQueueItemChanged = currentItem != item; final boolean hasPlayQueueItemChanged = currentItem != item;

View File

@ -6,6 +6,7 @@ import android.util.Log;
import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource; import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ShuffleOrder;
import org.reactivestreams.Subscriber; import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription; import org.reactivestreams.Subscription;
@ -19,6 +20,7 @@ import org.schabi.newpipe.playlist.PlayQueueItem;
import org.schabi.newpipe.playlist.events.MoveEvent; import org.schabi.newpipe.playlist.events.MoveEvent;
import org.schabi.newpipe.playlist.events.PlayQueueEvent; import org.schabi.newpipe.playlist.events.PlayQueueEvent;
import org.schabi.newpipe.playlist.events.RemoveEvent; import org.schabi.newpipe.playlist.events.RemoveEvent;
import org.schabi.newpipe.playlist.events.ReorderEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -216,7 +218,6 @@ public class MediaSourceManager {
// Event specific action // Event specific action
switch (event.type()) { switch (event.type()) {
case INIT: case INIT:
case REORDER:
case ERROR: case ERROR:
reset(); reset();
break; break;
@ -231,6 +232,12 @@ public class MediaSourceManager {
final MoveEvent moveEvent = (MoveEvent) event; final MoveEvent moveEvent = (MoveEvent) event;
move(moveEvent.getFromIndex(), moveEvent.getToIndex()); move(moveEvent.getFromIndex(), moveEvent.getToIndex());
break; break;
case REORDER:
// Need to move to ensure the playing index from play queue matches that of
// the source timeline, and then window correction can take care of the rest
final ReorderEvent reorderEvent = (ReorderEvent) event;
move(reorderEvent.getFromSelectedIndex(), reorderEvent.getToSelectedIndex());
break;
case SELECT: case SELECT:
case RECOVERY: case RECOVERY:
default: default:
@ -305,7 +312,7 @@ public class MediaSourceManager {
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Metadata Synchronization TODO: maybe this should be a separate manager // Metadata Synchronization
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void maybeSync() { private void maybeSync() {
@ -389,8 +396,8 @@ public class MediaSourceManager {
if (playQueue.indexOf(item) >= sources.getSize()) return; if (playQueue.indexOf(item) >= sources.getSize()) return;
if (!loadingItems.contains(item) && isCorrectionNeeded(item)) { if (!loadingItems.contains(item) && isCorrectionNeeded(item)) {
if (DEBUG) Log.d(TAG, "MediaSource - Loading: [" + item.getTitle() + if (DEBUG) Log.d(TAG, "MediaSource - Loading=[" + item.getTitle() +
"] with url: " + item.getUrl()); "] with url=[" + item.getUrl() + "]");
loadingItems.add(item); loadingItems.add(item);
final Disposable loader = getLoadedMediaSource(item) final Disposable loader = getLoadedMediaSource(item)
@ -423,16 +430,16 @@ public class MediaSourceManager {
private void onMediaSourceReceived(@NonNull final PlayQueueItem item, private void onMediaSourceReceived(@NonNull final PlayQueueItem item,
@NonNull final ManagedMediaSource mediaSource) { @NonNull final ManagedMediaSource mediaSource) {
if (DEBUG) Log.d(TAG, "MediaSource - Loaded: [" + item.getTitle() + if (DEBUG) Log.d(TAG, "MediaSource - Loaded=[" + item.getTitle() +
"] with url: " + item.getUrl()); "] with url=[" + item.getUrl() + "]");
loadingItems.remove(item); loadingItems.remove(item);
final int itemIndex = playQueue.indexOf(item); final int itemIndex = playQueue.indexOf(item);
// Only update the playlist timeline for items at the current index or after. // Only update the playlist timeline for items at the current index or after.
if (itemIndex >= playQueue.getIndex() && isCorrectionNeeded(item)) { if (itemIndex >= playQueue.getIndex() && isCorrectionNeeded(item)) {
if (DEBUG) Log.d(TAG, "MediaSource - Updating: [" + item.getTitle() + if (DEBUG) Log.d(TAG, "MediaSource - Updating index=[" + itemIndex + "] with " +
"] with url: " + item.getUrl()); "title=[" + item.getTitle() + "] at url=[" + item.getUrl() + "]");
update(itemIndex, mediaSource, this::maybeSynchronizePlayer); update(itemIndex, mediaSource, this::maybeSynchronizePlayer);
} }
} }
@ -468,7 +475,8 @@ public class MediaSourceManager {
if (DEBUG) Log.d(TAG, "resetSources() called."); if (DEBUG) Log.d(TAG, "resetSources() called.");
this.sources.releaseSource(); this.sources.releaseSource();
this.sources = new DynamicConcatenatingMediaSource(); this.sources = new DynamicConcatenatingMediaSource(false,
new ShuffleOrder.UnshuffledShuffleOrder(0));
} }
private void populateSources() { private void populateSources() {

View File

@ -351,6 +351,7 @@ public abstract class PlayQueue implements Serializable {
if (backup == null) { if (backup == null) {
backup = new ArrayList<>(streams); backup = new ArrayList<>(streams);
} }
final int originIndex = getIndex();
final PlayQueueItem current = getItem(); final PlayQueueItem current = getItem();
Collections.shuffle(streams); Collections.shuffle(streams);
@ -360,7 +361,7 @@ public abstract class PlayQueue implements Serializable {
} }
queueIndex.set(0); queueIndex.set(0);
broadcast(new ReorderEvent()); broadcast(new ReorderEvent(originIndex, queueIndex.get()));
} }
/** /**
@ -373,6 +374,7 @@ public abstract class PlayQueue implements Serializable {
* */ * */
public synchronized void unshuffle() { public synchronized void unshuffle() {
if (backup == null) return; if (backup == null) return;
final int originIndex = getIndex();
final PlayQueueItem current = getItem(); final PlayQueueItem current = getItem();
streams.clear(); streams.clear();
@ -386,7 +388,7 @@ public abstract class PlayQueue implements Serializable {
queueIndex.set(0); queueIndex.set(0);
} }
broadcast(new ReorderEvent()); broadcast(new ReorderEvent(originIndex, queueIndex.get()));
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////

View File

@ -1,12 +1,24 @@
package org.schabi.newpipe.playlist.events; package org.schabi.newpipe.playlist.events;
public class ReorderEvent implements PlayQueueEvent { public class ReorderEvent implements PlayQueueEvent {
private final int fromSelectedIndex;
private final int toSelectedIndex;
@Override @Override
public PlayQueueEventType type() { public PlayQueueEventType type() {
return PlayQueueEventType.REORDER; return PlayQueueEventType.REORDER;
} }
public ReorderEvent() { public ReorderEvent(final int fromSelectedIndex, final int toSelectedIndex) {
this.fromSelectedIndex = fromSelectedIndex;
this.toSelectedIndex = toSelectedIndex;
}
public int getFromSelectedIndex() {
return fromSelectedIndex;
}
public int getToSelectedIndex() {
return toSelectedIndex;
} }
} }