Merge branch 'save-shuffle' into 'develop'

Save shuffle

See merge request ultrasonic/ultrasonic!777
This commit is contained in:
tzugen 2022-07-09 12:30:51 +00:00
commit 8ecf7f468e
6 changed files with 79 additions and 58 deletions

View File

@ -0,0 +1,19 @@
package org.moire.ultrasonic.service
import java.io.Serializable
import org.moire.ultrasonic.domain.Track
/**
* Represents the state of the Media Player implementation
*/
data class PlaybackState(
val songs: List<Track> = listOf(),
val currentPlayingIndex: Int = 0,
val currentPlayingPosition: Int = 0,
var shufflePlay: Boolean = false,
var repeatMode: Int = 0
) : Serializable {
companion object {
const val serialVersionUID = -293487987L
}
}

View File

@ -1,19 +0,0 @@
package org.moire.ultrasonic.service;
import org.moire.ultrasonic.domain.Track;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the state of the Media Player implementation
*/
public class State implements Serializable
{
public static final long serialVersionUID = -6346438781062572270L;
public List<Track> songs = new ArrayList<>();
public int currentPlayingIndex;
public int currentPlayingPosition;
}

View File

@ -17,6 +17,7 @@ import org.moire.ultrasonic.adapters.BaseAdapter
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.domain.Track import org.moire.ultrasonic.domain.Track
import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle import org.moire.ultrasonic.fragment.FragmentTitle.Companion.setTitle
import org.moire.ultrasonic.service.PlaybackState
/** /**
* Lists the Bookmarks available on the server * Lists the Bookmarks available on the server
@ -65,12 +66,14 @@ class BookmarksFragment : TrackCollectionFragment() {
private fun playNow(songs: List<Track>) { private fun playNow(songs: List<Track>) {
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
val position = songs[0].bookmarkPosition val state = PlaybackState(
mediaPlayerController.restore(
songs = songs, songs = songs,
currentPlayingIndex = 0, currentPlayingIndex = 0,
currentPlayingPosition = position, currentPlayingPosition = songs[0].bookmarkPosition
)
mediaPlayerController.restore(
state = state,
autoPlay = true, autoPlay = true,
newPlaylist = true newPlaylist = true
) )

View File

@ -256,9 +256,7 @@ class MediaPlayerController(
@Synchronized @Synchronized
fun restore( fun restore(
songs: List<Track>, state: PlaybackState,
currentPlayingIndex: Int,
currentPlayingPosition: Int,
autoPlay: Boolean, autoPlay: Boolean,
newPlaylist: Boolean newPlaylist: Boolean
) { ) {
@ -266,21 +264,24 @@ class MediaPlayerController(
else InsertionMode.APPEND else InsertionMode.APPEND
addToPlaylist( addToPlaylist(
songs, state.songs,
cachePermanently = false, cachePermanently = false,
autoPlay = false, autoPlay = false,
shuffle = false, shuffle = false,
insertionMode = insertionMode insertionMode = insertionMode
) )
if (currentPlayingIndex != -1) { repeatMode = state.repeatMode
isShufflePlayEnabled = state.shufflePlay
if (state.currentPlayingIndex != -1) {
if (jukeboxMediaPlayer.isEnabled) { if (jukeboxMediaPlayer.isEnabled) {
jukeboxMediaPlayer.skip( jukeboxMediaPlayer.skip(
currentPlayingIndex, state.currentPlayingIndex,
currentPlayingPosition / 1000 state.currentPlayingPosition / 1000
) )
} else { } else {
seekTo(currentPlayingIndex, currentPlayingPosition) seekTo(state.currentPlayingIndex, state.currentPlayingPosition)
} }
prepare() prepare()
@ -445,8 +446,8 @@ class MediaPlayerController(
controller?.clearMediaItems() controller?.clearMediaItems()
if (controller != null && serialize) { if (controller != null && serialize) {
playbackStateSerializer.serialize( playbackStateSerializer.serializeAsync(
listOf(), -1, 0 listOf(), -1, 0, isShufflePlayEnabled, repeatMode
) )
} }
@ -481,10 +482,12 @@ class MediaPlayerController(
// Don't serialize invalid sessions // Don't serialize invalid sessions
if (currentMediaItemIndex == -1) return if (currentMediaItemIndex == -1) return
playbackStateSerializer.serialize( playbackStateSerializer.serializeAsync(
legacyPlaylistManager.playlist, songs = legacyPlaylistManager.playlist,
currentMediaItemIndex, currentPlayingIndex = currentMediaItemIndex,
playerPosition currentPlayingPosition = playerPosition,
isShufflePlayEnabled,
repeatMode
) )
} }

View File

@ -60,9 +60,7 @@ class MediaPlayerLifecycleSupport : KoinComponent {
Timber.i("Restoring %s songs", it!!.songs.size) Timber.i("Restoring %s songs", it!!.songs.size)
mediaPlayerController.restore( mediaPlayerController.restore(
it.songs, it,
it.currentPlayingIndex,
it.currentPlayingPosition,
autoPlay, autoPlay,
false false
) )
@ -78,7 +76,9 @@ class MediaPlayerLifecycleSupport : KoinComponent {
playbackStateSerializer.serializeNow( playbackStateSerializer.serializeNow(
mediaPlayerController.playList, mediaPlayerController.playList,
mediaPlayerController.currentMediaItemIndex, mediaPlayerController.currentMediaItemIndex,
mediaPlayerController.playerPosition mediaPlayerController.playerPosition,
mediaPlayerController.isShufflePlayEnabled,
mediaPlayerController.repeatMode
) )
mediaPlayerController.clear(false) mediaPlayerController.clear(false)

View File

@ -31,17 +31,25 @@ class PlaybackStateSerializer : KoinComponent {
private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val ioScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) private val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
fun serialize( fun serializeAsync(
songs: Iterable<DownloadFile>, songs: Iterable<DownloadFile>,
currentPlayingIndex: Int, currentPlayingIndex: Int,
currentPlayingPosition: Int currentPlayingPosition: Int,
shufflePlay: Boolean,
repeatMode: Int
) { ) {
if (isSerializing.get() || !isSetup.get()) return if (isSerializing.get() || !isSetup.get()) return
isSerializing.set(true) isSerializing.set(true)
ioScope.launch { ioScope.launch {
serializeNow(songs, currentPlayingIndex, currentPlayingPosition) serializeNow(
songs,
currentPlayingIndex,
currentPlayingPosition,
shufflePlay,
repeatMode
)
}.invokeOnCompletion { }.invokeOnCompletion {
isSerializing.set(false) isSerializing.set(false)
} }
@ -50,28 +58,34 @@ class PlaybackStateSerializer : KoinComponent {
fun serializeNow( fun serializeNow(
referencedList: Iterable<DownloadFile>, referencedList: Iterable<DownloadFile>,
currentPlayingIndex: Int, currentPlayingIndex: Int,
currentPlayingPosition: Int currentPlayingPosition: Int,
shufflePlay: Boolean,
repeatMode: Int
) { ) {
val state = State()
val songs = referencedList.toList()
for (downloadFile in songs) { val tracks = referencedList.toList().map {
state.songs.add(downloadFile.track) it.track
} }
state.currentPlayingIndex = currentPlayingIndex val state = PlaybackState(
state.currentPlayingPosition = currentPlayingPosition tracks,
currentPlayingIndex,
currentPlayingPosition,
shufflePlay,
repeatMode
)
Timber.i( Timber.i(
"Serialized currentPlayingIndex: %d, currentPlayingPosition: %d", "Serialized currentPlayingIndex: %d, currentPlayingPosition: %d, shuffle: %b",
state.currentPlayingIndex, state.currentPlayingIndex,
state.currentPlayingPosition state.currentPlayingPosition,
state.shufflePlay
) )
FileUtil.serialize(context, state, Constants.FILENAME_PLAYLIST_SER) FileUtil.serialize(context, state, Constants.FILENAME_PLAYLIST_SER)
} }
fun deserialize(afterDeserialized: (State?) -> Unit?) { fun deserialize(afterDeserialized: (PlaybackState?) -> Unit?) {
if (isDeserializing.get()) return if (isDeserializing.get()) return
ioScope.launch { ioScope.launch {
try { try {
@ -85,16 +99,17 @@ class PlaybackStateSerializer : KoinComponent {
} }
} }
private fun deserializeNow(afterDeserialized: (State?) -> Unit?) { private fun deserializeNow(afterDeserialized: (PlaybackState?) -> Unit?) {
val state = FileUtil.deserialize<State>( val state = FileUtil.deserialize<PlaybackState>(
context, Constants.FILENAME_PLAYLIST_SER context, Constants.FILENAME_PLAYLIST_SER
) ?: return ) ?: return
Timber.i( Timber.i(
"Deserialized currentPlayingIndex: %d, currentPlayingPosition: %d ", "Deserialized currentPlayingIndex: %d, currentPlayingPosition: %d, shuffle: %b",
state.currentPlayingIndex, state.currentPlayingIndex,
state.currentPlayingPosition state.currentPlayingPosition,
state.shufflePlay
) )
mainScope.launch { mainScope.launch {