2018-03-16 07:42:46 +01:00
|
|
|
package org.schabi.newpipe.player.mediasession;
|
|
|
|
|
2022-08-25 16:59:46 +02:00
|
|
|
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
|
|
|
|
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
|
|
|
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM;
|
|
|
|
|
2022-07-21 22:40:21 +02:00
|
|
|
import android.net.Uri;
|
2018-03-16 07:42:46 +01:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.ResultReceiver;
|
2022-07-21 22:40:21 +02:00
|
|
|
import android.support.v4.media.MediaDescriptionCompat;
|
|
|
|
import android.support.v4.media.MediaMetadataCompat;
|
2019-10-07 07:54:31 +02:00
|
|
|
import android.support.v4.media.session.MediaSessionCompat;
|
|
|
|
|
2019-10-04 14:59:08 +02:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
|
|
|
import com.google.android.exoplayer2.util.Util;
|
|
|
|
|
2022-08-25 16:59:46 +02:00
|
|
|
import org.schabi.newpipe.player.Player;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
2023-05-02 12:30:27 +02:00
|
|
|
import org.schabi.newpipe.util.image.ImageStrategy;
|
2022-08-25 16:59:46 +02:00
|
|
|
|
2018-03-16 07:42:46 +01:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
2022-07-21 22:40:21 +02:00
|
|
|
import java.util.Optional;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator {
|
2022-07-21 22:40:21 +02:00
|
|
|
private static final int MAX_QUEUE_SIZE = 10;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
private final MediaSessionCompat mediaSession;
|
2022-07-21 22:40:21 +02:00
|
|
|
private final Player player;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
private long activeQueueItemId;
|
|
|
|
|
|
|
|
public PlayQueueNavigator(@NonNull final MediaSessionCompat mediaSession,
|
2022-07-21 22:40:21 +02:00
|
|
|
@NonNull final Player player) {
|
2018-03-16 07:42:46 +01:00
|
|
|
this.mediaSession = mediaSession;
|
2022-07-21 22:40:21 +02:00
|
|
|
this.player = player;
|
2018-03-16 07:42:46 +01:00
|
|
|
|
|
|
|
this.activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public long getSupportedQueueNavigatorActions(
|
|
|
|
@Nullable final com.google.android.exoplayer2.Player exoPlayer) {
|
2018-03-16 07:42:46 +01:00
|
|
|
return ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS | ACTION_SKIP_TO_QUEUE_ITEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public void onTimelineChanged(@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
|
2018-03-16 07:42:46 +01:00
|
|
|
publishFloatingQueueWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public void onCurrentMediaItemIndexChanged(
|
|
|
|
@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
|
2018-03-16 07:42:46 +01:00
|
|
|
if (activeQueueItemId == MediaSessionCompat.QueueItem.UNKNOWN_ID
|
2022-07-21 22:40:21 +02:00
|
|
|
|| exoPlayer.getCurrentTimeline().getWindowCount() > MAX_QUEUE_SIZE) {
|
2018-03-16 07:42:46 +01:00
|
|
|
publishFloatingQueueWindow();
|
2022-07-21 22:40:21 +02:00
|
|
|
} else if (!exoPlayer.getCurrentTimeline().isEmpty()) {
|
|
|
|
activeQueueItemId = exoPlayer.getCurrentMediaItemIndex();
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public long getActiveQueueItemId(
|
|
|
|
@Nullable final com.google.android.exoplayer2.Player exoPlayer) {
|
|
|
|
return Optional.ofNullable(player.getPlayQueue()).map(PlayQueue::getIndex).orElse(-1);
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public void onSkipToPrevious(@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
|
|
|
|
player.playPrevious();
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public void onSkipToQueueItem(@NonNull final com.google.android.exoplayer2.Player exoPlayer,
|
|
|
|
final long id) {
|
|
|
|
if (player.getPlayQueue() != null) {
|
|
|
|
player.selectQueueItem(player.getPlayQueue().getItem((int) id));
|
|
|
|
}
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public void onSkipToNext(@NonNull final com.google.android.exoplayer2.Player exoPlayer) {
|
|
|
|
player.playNext();
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void publishFloatingQueueWindow() {
|
2022-07-21 22:40:21 +02:00
|
|
|
final int windowCount = Optional.ofNullable(player.getPlayQueue())
|
|
|
|
.map(PlayQueue::size)
|
|
|
|
.orElse(0);
|
|
|
|
if (windowCount == 0) {
|
2018-08-28 19:17:14 +02:00
|
|
|
mediaSession.setQueue(Collections.emptyList());
|
2018-03-16 07:42:46 +01:00
|
|
|
activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Yes this is almost a copypasta, got a problem with that? =\
|
2022-07-21 22:40:21 +02:00
|
|
|
final int currentWindowIndex = player.getPlayQueue().getIndex();
|
|
|
|
final int queueSize = Math.min(MAX_QUEUE_SIZE, windowCount);
|
2020-08-16 10:24:58 +02:00
|
|
|
final int startIndex = Util.constrainValue(currentWindowIndex - ((queueSize - 1) / 2), 0,
|
2018-03-16 07:42:46 +01:00
|
|
|
windowCount - queueSize);
|
|
|
|
|
2020-08-16 10:24:58 +02:00
|
|
|
final List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
|
2018-03-16 07:42:46 +01:00
|
|
|
for (int i = startIndex; i < startIndex + queueSize; i++) {
|
2022-07-21 22:40:21 +02:00
|
|
|
queue.add(new MediaSessionCompat.QueueItem(getQueueMetadata(i), i));
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
mediaSession.setQueue(queue);
|
|
|
|
activeQueueItemId = currentWindowIndex;
|
|
|
|
}
|
|
|
|
|
2022-07-21 22:40:21 +02:00
|
|
|
public MediaDescriptionCompat getQueueMetadata(final int index) {
|
|
|
|
if (player.getPlayQueue() == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
|
|
|
if (item == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
final MediaDescriptionCompat.Builder descBuilder = new MediaDescriptionCompat.Builder()
|
|
|
|
.setMediaId(String.valueOf(index))
|
|
|
|
.setTitle(item.getTitle())
|
|
|
|
.setSubtitle(item.getUploader());
|
|
|
|
|
2022-07-26 16:35:57 +02:00
|
|
|
// set additional metadata for A2DP/AVRCP (Audio/Video Bluetooth profiles)
|
2022-07-21 22:40:21 +02:00
|
|
|
final Bundle additionalMetadata = new Bundle();
|
|
|
|
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_TITLE, item.getTitle());
|
|
|
|
additionalMetadata.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, item.getUploader());
|
|
|
|
additionalMetadata
|
|
|
|
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, item.getDuration() * 1000);
|
2022-08-25 16:59:46 +02:00
|
|
|
additionalMetadata.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, index + 1L);
|
2022-07-21 22:40:21 +02:00
|
|
|
additionalMetadata
|
|
|
|
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, player.getPlayQueue().size());
|
|
|
|
descBuilder.setExtras(additionalMetadata);
|
|
|
|
|
2023-05-02 21:12:32 +02:00
|
|
|
try {
|
|
|
|
descBuilder.setIconUri(Uri.parse(
|
|
|
|
ImageStrategy.choosePreferredImage(item.getThumbnails())));
|
|
|
|
} catch (final Throwable e) {
|
|
|
|
// no thumbnail available at all, or the user disabled image loading,
|
|
|
|
// or the obtained url is not a valid `Uri`
|
2022-07-21 22:40:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return descBuilder.build();
|
|
|
|
}
|
|
|
|
|
2018-03-16 07:42:46 +01:00
|
|
|
@Override
|
2022-07-21 22:40:21 +02:00
|
|
|
public boolean onCommand(@NonNull final com.google.android.exoplayer2.Player exoPlayer,
|
2022-03-13 06:22:47 +01:00
|
|
|
@NonNull final String command,
|
|
|
|
@Nullable final Bundle extras,
|
|
|
|
@Nullable final ResultReceiver cb) {
|
2019-10-07 07:54:31 +02:00
|
|
|
return false;
|
2018-03-16 07:42:46 +01:00
|
|
|
}
|
|
|
|
}
|