mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 09:33:33 +00:00
fix shuffle
This commit is contained in:
parent
6698052ba5
commit
5a8a631449
2 changed files with 61 additions and 28 deletions
|
|
@ -19,6 +19,7 @@ import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl
|
import androidx.media3.exoplayer.DefaultLoadControl
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.MediaSource
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
|
import androidx.media3.exoplayer.source.ShuffleOrder.DefaultShuffleOrder
|
||||||
import androidx.media3.session.*
|
import androidx.media3.session.*
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo
|
import androidx.media3.session.MediaSession.ControllerInfo
|
||||||
import com.cappielloantonio.tempo.R
|
import com.cappielloantonio.tempo.R
|
||||||
|
|
@ -39,6 +40,7 @@ import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
class MediaService : MediaLibraryService() {
|
class MediaService : MediaLibraryService() {
|
||||||
|
private val TAG = "MediaService"
|
||||||
private val librarySessionCallback = CustomMediaLibrarySessionCallback()
|
private val librarySessionCallback = CustomMediaLibrarySessionCallback()
|
||||||
|
|
||||||
private lateinit var player: ExoPlayer
|
private lateinit var player: ExoPlayer
|
||||||
|
|
@ -86,7 +88,7 @@ class MediaService : MediaLibraryService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateMediaItems() {
|
fun updateMediaItems() {
|
||||||
Log.d("MediaService", "update items");
|
Log.d(TAG, "update items");
|
||||||
val n = player.mediaItemCount
|
val n = player.mediaItemCount
|
||||||
val k = player.currentMediaItemIndex
|
val k = player.currentMediaItemIndex
|
||||||
val current = player.currentPosition
|
val current = player.currentPosition
|
||||||
|
|
@ -349,14 +351,30 @@ class MediaService : MediaLibraryService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTracksChanged(tracks: Tracks) {
|
override fun onTracksChanged(tracks: Tracks) {
|
||||||
|
Log.d(TAG, "onTracksChanged " + player.currentMediaItemIndex);
|
||||||
ReplayGainUtil.setReplayGain(player, tracks)
|
ReplayGainUtil.setReplayGain(player, tracks)
|
||||||
val currentMediaItem = player.currentMediaItem
|
val currentMediaItem = player.currentMediaItem
|
||||||
if (currentMediaItem != null && currentMediaItem.mediaMetadata.extras != null) {
|
if (currentMediaItem != null) {
|
||||||
MediaManager.scrobble(currentMediaItem, false)
|
val item = MappingUtil.mapMediaItem(currentMediaItem)
|
||||||
|
if (item.mediaMetadata.extras != null)
|
||||||
|
MediaManager.scrobble(item, false)
|
||||||
|
|
||||||
|
if (player.nextMediaItemIndex == C.INDEX_UNSET)
|
||||||
|
MediaManager.continuousPlay(player.currentMediaItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.currentMediaItemIndex + 1 == player.mediaItemCount)
|
// https://stackoverflow.com/questions/56937283/exoplayer-shuffle-doesnt-reproduce-all-the-songs
|
||||||
MediaManager.continuousPlay(player.currentMediaItem)
|
if (MediaManager.justStarted.get()) {
|
||||||
|
Log.d(TAG, "update shuffle order")
|
||||||
|
MediaManager.justStarted.set(false)
|
||||||
|
val shuffledList = IntArray(player.mediaItemCount) { i -> i }
|
||||||
|
shuffledList.shuffle()
|
||||||
|
val index = shuffledList.indexOf(player.currentMediaItemIndex)
|
||||||
|
// swap current media index to the first index
|
||||||
|
if (index > -1 && shuffledList.isNotEmpty())
|
||||||
|
run { val tmp = shuffledList[0]; shuffledList[0] = shuffledList[index]; shuffledList[index] = tmp}
|
||||||
|
player.shuffleOrder = DefaultShuffleOrder(shuffledList, kotlin.random.Random.nextLong())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,12 @@ import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
public class MediaManager {
|
public class MediaManager {
|
||||||
private static final String TAG = "MediaManager";
|
private static final String TAG = "MediaManager";
|
||||||
private static WeakReference<MediaBrowser> attachedBrowserRef = new WeakReference<>(null);
|
private static WeakReference<MediaBrowser> attachedBrowserRef = new WeakReference<>(null);
|
||||||
|
public static AtomicBoolean justStarted = new AtomicBoolean(false);
|
||||||
|
|
||||||
public static void registerPlaybackObserver(
|
public static void registerPlaybackObserver(
|
||||||
ListenableFuture<MediaBrowser> browserFuture,
|
ListenableFuture<MediaBrowser> browserFuture,
|
||||||
|
|
@ -179,8 +181,8 @@ public class MediaManager {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
browser.clearMediaItems();
|
justStarted.set(true);
|
||||||
browser.setMediaItems(MappingUtil.mapMediaItems(media));
|
browser.setMediaItems(MappingUtil.mapMediaItems(media), startIndex, 0);
|
||||||
browser.prepare();
|
browser.prepare();
|
||||||
|
|
||||||
Player.Listener timelineListener = new Player.Listener() {
|
Player.Listener timelineListener = new Player.Listener() {
|
||||||
|
|
@ -210,10 +212,11 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
mediaBrowserListenableFuture.get().clearMediaItems();
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowserListenableFuture.get().setMediaItem(MappingUtil.mapMediaItem(media));
|
justStarted.set(true);
|
||||||
mediaBrowserListenableFuture.get().prepare();
|
browser.setMediaItem(MappingUtil.mapMediaItem(media));
|
||||||
mediaBrowserListenableFuture.get().play();
|
browser.prepare();
|
||||||
|
browser.play();
|
||||||
enqueueDatabase(media, true, 0);
|
enqueueDatabase(media, true, 0);
|
||||||
}
|
}
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
|
@ -229,7 +232,7 @@ public class MediaManager {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
|
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowser.clearMediaItems();
|
justStarted.set(true);
|
||||||
mediaBrowser.setMediaItem(mediaItem);
|
mediaBrowser.setMediaItem(mediaItem);
|
||||||
mediaBrowser.prepare();
|
mediaBrowser.prepare();
|
||||||
mediaBrowser.play();
|
mediaBrowser.play();
|
||||||
|
|
@ -247,10 +250,11 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
mediaBrowserListenableFuture.get().clearMediaItems();
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowserListenableFuture.get().setMediaItem(MappingUtil.mapInternetRadioStation(internetRadioStation));
|
justStarted.set(true);
|
||||||
mediaBrowserListenableFuture.get().prepare();
|
browser.setMediaItem(MappingUtil.mapInternetRadioStation(internetRadioStation));
|
||||||
mediaBrowserListenableFuture.get().play();
|
browser.prepare();
|
||||||
|
browser.play();
|
||||||
}
|
}
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
@ -264,10 +268,11 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
mediaBrowserListenableFuture.get().clearMediaItems();
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowserListenableFuture.get().setMediaItem(MappingUtil.mapMediaItem(podcastEpisode));
|
justStarted.set(true);
|
||||||
mediaBrowserListenableFuture.get().prepare();
|
browser.setMediaItem(MappingUtil.mapMediaItem(podcastEpisode));
|
||||||
mediaBrowserListenableFuture.get().play();
|
browser.prepare();
|
||||||
|
browser.play();
|
||||||
}
|
}
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
@ -281,9 +286,11 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
if (playImmediatelyAfter && mediaBrowserListenableFuture.get().getNextMediaItemIndex() != -1) {
|
Log.e(TAG, "enqueue");
|
||||||
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getNextMediaItemIndex());
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowserListenableFuture.get().addMediaItems(mediaBrowserListenableFuture.get().getNextMediaItemIndex(), MappingUtil.mapMediaItems(media));
|
if (playImmediatelyAfter && browser.getNextMediaItemIndex() != -1) {
|
||||||
|
enqueueDatabase(media, false, browser.getNextMediaItemIndex());
|
||||||
|
browser.addMediaItems(browser.getNextMediaItemIndex(), MappingUtil.mapMediaItems(media));
|
||||||
} else {
|
} else {
|
||||||
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getMediaItemCount());
|
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getMediaItemCount());
|
||||||
mediaBrowserListenableFuture.get().addMediaItems(MappingUtil.mapMediaItems(media));
|
mediaBrowserListenableFuture.get().addMediaItems(MappingUtil.mapMediaItems(media));
|
||||||
|
|
@ -301,9 +308,11 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
if (playImmediatelyAfter && mediaBrowserListenableFuture.get().getNextMediaItemIndex() != -1) {
|
Log.e(TAG, "enqueue");
|
||||||
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getNextMediaItemIndex());
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
mediaBrowserListenableFuture.get().addMediaItem(mediaBrowserListenableFuture.get().getNextMediaItemIndex(), MappingUtil.mapMediaItem(media));
|
if (playImmediatelyAfter && browser.getNextMediaItemIndex() != -1) {
|
||||||
|
enqueueDatabase(media, false, browser.getNextMediaItemIndex());
|
||||||
|
browser.addMediaItem(browser.getNextMediaItemIndex(), MappingUtil.mapMediaItem(media));
|
||||||
} else {
|
} else {
|
||||||
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getMediaItemCount());
|
enqueueDatabase(media, false, mediaBrowserListenableFuture.get().getMediaItemCount());
|
||||||
mediaBrowserListenableFuture.get().addMediaItem(MappingUtil.mapMediaItem(media));
|
mediaBrowserListenableFuture.get().addMediaItem(MappingUtil.mapMediaItem(media));
|
||||||
|
|
@ -321,8 +330,10 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
mediaBrowserListenableFuture.get().removeMediaItems(startIndex, endIndex + 1);
|
Log.e(TAG, "shuffle");
|
||||||
mediaBrowserListenableFuture.get().addMediaItems(MappingUtil.mapMediaItems(media).subList(startIndex, endIndex + 1));
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
|
browser.removeMediaItems(startIndex, endIndex + 1);
|
||||||
|
browser.addMediaItems(MappingUtil.mapMediaItems(media).subList(startIndex, endIndex + 1));
|
||||||
swapDatabase(media);
|
swapDatabase(media);
|
||||||
}
|
}
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
} catch (ExecutionException | InterruptedException e) {
|
||||||
|
|
@ -337,6 +348,7 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
Log.e(TAG, "swap");
|
||||||
mediaBrowserListenableFuture.get().moveMediaItem(from, to);
|
mediaBrowserListenableFuture.get().moveMediaItem(from, to);
|
||||||
swapDatabase(media);
|
swapDatabase(media);
|
||||||
}
|
}
|
||||||
|
|
@ -352,6 +364,7 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
Log.e(TAG, "remove");
|
||||||
if (mediaBrowserListenableFuture.get().getMediaItemCount() > 1 && mediaBrowserListenableFuture.get().getCurrentMediaItemIndex() != toRemove) {
|
if (mediaBrowserListenableFuture.get().getMediaItemCount() > 1 && mediaBrowserListenableFuture.get().getCurrentMediaItemIndex() != toRemove) {
|
||||||
mediaBrowserListenableFuture.get().removeMediaItem(toRemove);
|
mediaBrowserListenableFuture.get().removeMediaItem(toRemove);
|
||||||
removeDatabase(media, toRemove);
|
removeDatabase(media, toRemove);
|
||||||
|
|
@ -371,6 +384,7 @@ public class MediaManager {
|
||||||
mediaBrowserListenableFuture.addListener(() -> {
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
Log.e(TAG, "remove range");
|
||||||
mediaBrowserListenableFuture.get().removeMediaItems(fromItem, toItem);
|
mediaBrowserListenableFuture.get().removeMediaItems(fromItem, toItem);
|
||||||
removeRangeDatabase(media, fromItem, toItem);
|
removeRangeDatabase(media, fromItem, toItem);
|
||||||
}
|
}
|
||||||
|
|
@ -420,6 +434,7 @@ public class MediaManager {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<Child> media) {
|
public void onChanged(List<Child> media) {
|
||||||
if (media != null) {
|
if (media != null) {
|
||||||
|
Log.e(TAG, "continuous play");
|
||||||
ListenableFuture<MediaBrowser> mediaBrowserListenableFuture = new MediaBrowser.Builder(
|
ListenableFuture<MediaBrowser> mediaBrowserListenableFuture = new MediaBrowser.Builder(
|
||||||
App.getContext(),
|
App.getContext(),
|
||||||
new SessionToken(App.getContext(), new ComponentName(App.getContext(), MediaService.class))
|
new SessionToken(App.getContext(), new ComponentName(App.getContext(), MediaService.class))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue