revert playback: save state when sanitizing

Edge case I thought existed did not. PlaybackService must have saved
before dying, and thus if it did not foreground after a sanitization,
the saved state would still sanitize in a similar manner.
This commit is contained in:
OxygenCobalt 2022-07-07 16:14:47 -06:00
parent a217bde713
commit 29cc680c34
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 42 additions and 58 deletions

View file

@ -28,7 +28,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.oxycblt.auxio.IntegerTable
import org.oxycblt.auxio.R
import org.oxycblt.auxio.playback.state.PlaybackStateDatabase
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.settings.Settings
import org.oxycblt.auxio.util.logD
@ -119,8 +118,7 @@ class IndexerService : Service(), Indexer.Controller, Settings.Callback {
imageLoader.memoryCache?.clear()
// Clear invalid models from PlaybackStateManager.
playbackManager.sanitize(
PlaybackStateDatabase.getInstance(this@IndexerService), newLibrary)
playbackManager.sanitize(newLibrary)
}
musicStore.updateLibrary(newLibrary)

View file

@ -70,7 +70,7 @@ class PlaybackStateManager private constructor() {
notifyPlayingChanged()
}
/** The current playback progress */
private var positionMs = 0L
var positionMs = 0L
/** The current [RepeatMode] */
var repeatMode = RepeatMode.NONE
set(value) {
@ -81,7 +81,7 @@ class PlaybackStateManager private constructor() {
var isShuffled = false
private set
/** Whether this instance has been initialized */
/** Whether this instance has played something or restored a state. */
var isInitialized = false
private set
@ -141,10 +141,7 @@ class PlaybackStateManager private constructor() {
// --- PLAYING FUNCTIONS ---
/**
* Play a [song].
* @param playbackMode The [PlaybackMode] to construct the queue off of.
*/
/** Play a [song]. */
@Synchronized
fun play(song: Song, playbackMode: PlaybackMode, settings: Settings) {
val library = musicStore.library ?: return
@ -165,10 +162,7 @@ class PlaybackStateManager private constructor() {
isInitialized = true
}
/**
* Play a [parent], such as an artist or album.
* @param shuffled Whether the queue is shuffled or not
*/
/** Play a [parent], such as an artist or album. */
@Synchronized
fun play(parent: MusicParent, shuffled: Boolean, settings: Settings) {
val library = musicStore.library ?: return
@ -321,11 +315,7 @@ class PlaybackStateManager private constructor() {
// --- STATE FUNCTIONS ---
/**
* Update the current [positionMs]. Will not notify listeners of a seek event.
* @param positionMs The new position in millis.
* @see seekTo
*/
/** Update the current [positionMs]. Only meant for use by [Controller] */
@Synchronized
fun synchronizePosition(controller: Controller, positionMs: Long) {
if (BuildConfig.DEBUG && this.controller !== controller) {
@ -400,47 +390,41 @@ class PlaybackStateManager private constructor() {
withContext(Dispatchers.IO) { database.write(state) }
}
/** Sanitize the state with [newLibrary]. Writes the state to [database] */
suspend fun sanitize(database: PlaybackStateDatabase, newLibrary: MusicStore.Library) {
val state =
synchronized(this) {
if (!isInitialized) {
logD("Not initialized, no need to sanitize")
return
/** Sanitize the state with [newLibrary]. */
@Synchronized
fun sanitize(newLibrary: MusicStore.Library) {
if (!isInitialized) {
logD("Not initialized, no need to sanitize")
return
}
logD("Sanitizing state")
val oldSongId = song?.id
val oldPosition = positionMs
parent =
parent?.let {
when (it) {
is Album -> newLibrary.sanitize(it)
is Artist -> newLibrary.sanitize(it)
is Genre -> newLibrary.sanitize(it)
}
logD("Sanitizing state")
val oldSongId = song?.id
val oldPosition = positionMs
parent =
parent?.let {
when (it) {
is Album -> newLibrary.sanitize(it)
is Artist -> newLibrary.sanitize(it)
is Genre -> newLibrary.sanitize(it)
}
}
_queue = newLibrary.sanitize(_queue).toMutableList()
while (song?.id != oldSongId && index > -1) {
index--
}
// Continuing playback while also possibly doing drastic state updates is
// a bad idea, so pause.
isPlaying = false
notifyNewPlayback()
// Controller may have reloaded the media item, re-seek to the previous position
seekTo(oldPosition)
makeStateImpl()
}
withContext(Dispatchers.IO) { database.write(state) }
_queue = newLibrary.sanitize(_queue).toMutableList()
while (song?.id != oldSongId && index > -1) {
index--
}
// Continuing playback while also possibly doing drastic state updates is
// a bad idea, so pause.
isPlaying = false
notifyNewPlayback()
// Controller may have reloaded the media item, re-seek to the previous position
seekTo(oldPosition)
}
private fun makeStateImpl() =

View file

@ -221,6 +221,10 @@ class MediaSessionComponent(
playbackManager.seekTo(position)
}
override fun onFastForward() {
playbackManager.next()
}
override fun onRewind() {
playbackManager.rewind()
playbackManager.isPlaying = true

View file

@ -69,8 +69,6 @@ import org.oxycblt.auxio.widgets.WidgetProvider
*
* TODO: Android Auto
*
* TODO: Attempt to re-unify delayed actions again
*
* @author OxygenCobalt
*/
class PlaybackService :