honour shuffle order when publishing queue to media session

Issue #5360

PiperOrigin-RevId: 235196177
This commit is contained in:
bachinger 2019-02-22 16:29:36 +00:00 committed by Oliver Woodman
parent eea1ce3e0a
commit e8077fb3f4
3 changed files with 44 additions and 12 deletions

View File

@ -60,6 +60,8 @@
`TrackSelectionDialogBuilder` and add option to select multiple overrides.
* MediaSessionConnector: Let apps intercept media button events
([#5179](https://github.com/google/ExoPlayer/issues/5179)).
* Fix issue with `TimelineQueueNavigator` not publishing the queue in shuffled
order when in shuffle mode.
### 2.9.6 ###

View File

@ -971,6 +971,7 @@ public final class MediaSessionConnector {
? PlaybackStateCompat.SHUFFLE_MODE_ALL
: PlaybackStateCompat.SHUFFLE_MODE_NONE);
invalidateMediaSessionPlaybackState();
invalidateMediaSessionQueue();
}
@Override

View File

@ -25,10 +25,10 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ControlDispatcher;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.Assertions;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* An abstract implementation of the {@link MediaSessionConnector.QueueNavigator} that maps the
@ -67,6 +67,7 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
* @param maxQueueSize The maximum queue size.
*/
public TimelineQueueNavigator(MediaSessionCompat mediaSession, int maxQueueSize) {
Assertions.checkState(maxQueueSize > 0);
this.mediaSession = mediaSession;
this.maxQueueSize = maxQueueSize;
activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
@ -193,22 +194,50 @@ public abstract class TimelineQueueNavigator implements MediaSessionConnector.Qu
// Helper methods.
private void publishFloatingQueueWindow(Player player) {
if (player.getCurrentTimeline().isEmpty()) {
Timeline timeline = player.getCurrentTimeline();
if (timeline.isEmpty()) {
mediaSession.setQueue(Collections.emptyList());
activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
return;
}
int windowCount = player.getCurrentTimeline().getWindowCount();
ArrayDeque<MediaSessionCompat.QueueItem> queue = new ArrayDeque<>();
int queueSize = Math.min(maxQueueSize, timeline.getWindowCount());
// Add the active queue item.
int currentWindowIndex = player.getCurrentWindowIndex();
int queueSize = Math.min(maxQueueSize, windowCount);
int startIndex = Util.constrainValue(currentWindowIndex - ((queueSize - 1) / 2), 0,
windowCount - queueSize);
List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
for (int i = startIndex; i < startIndex + queueSize; i++) {
queue.add(new MediaSessionCompat.QueueItem(getMediaDescription(player, i), i));
queue.add(
new MediaSessionCompat.QueueItem(
getMediaDescription(player, currentWindowIndex), currentWindowIndex));
// Fill queue alternating with next and/or previous queue items.
int firstWindowIndex = currentWindowIndex;
int lastWindowIndex = currentWindowIndex;
boolean shuffleModeEnabled = player.getShuffleModeEnabled();
while ((firstWindowIndex != C.INDEX_UNSET || lastWindowIndex != C.INDEX_UNSET)
&& queue.size() < queueSize) {
// Begin with next to have a longer tail than head if an even sized queue needs to be trimmed.
if (lastWindowIndex != C.INDEX_UNSET) {
lastWindowIndex =
timeline.getNextWindowIndex(
lastWindowIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
if (lastWindowIndex != C.INDEX_UNSET) {
queue.add(
new MediaSessionCompat.QueueItem(
getMediaDescription(player, lastWindowIndex), lastWindowIndex));
}
}
if (firstWindowIndex != C.INDEX_UNSET && queue.size() < queueSize) {
firstWindowIndex =
timeline.getPreviousWindowIndex(
firstWindowIndex, Player.REPEAT_MODE_OFF, shuffleModeEnabled);
if (firstWindowIndex != C.INDEX_UNSET) {
queue.addFirst(
new MediaSessionCompat.QueueItem(
getMediaDescription(player, firstWindowIndex), firstWindowIndex));
}
}
}
mediaSession.setQueue(queue);
mediaSession.setQueue(new ArrayList<>(queue));
activeQueueItemId = currentWindowIndex;
}
}