playback: save when service closes

This time, actually wait for the save to complete before stopping the
foreground state. This requires some checks to make sure that we don't
have any "randomly smashing on buttons" errors, but I'm unsure if that
will be enough.

The last case in which this becomes an issue is when the service
is killed outright. I can't do much here to make the state more sane
unless I did some playback position monitoring.
This commit is contained in:
Alexander Capehart 2024-02-17 13:37:02 -07:00
parent 80e08fd74a
commit 23d561cc44
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47

View file

@ -194,6 +194,7 @@ class PlaybackService :
override fun onTaskRemoved(rootIntent: Intent?) { override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent) super.onTaskRemoved(rootIntent)
if (!playbackManager.progression.isPlaying) { if (!playbackManager.progression.isPlaying) {
playbackManager.playing(false)
endSession() endSession()
} }
} }
@ -533,6 +534,7 @@ class PlaybackService :
) { ) {
super.onPositionDiscontinuity(oldPosition, newPosition, reason) super.onPositionDiscontinuity(oldPosition, newPosition, reason)
if (reason == Player.DISCONTINUITY_REASON_SEEK) { if (reason == Player.DISCONTINUITY_REASON_SEEK) {
// TODO: Once position also naturally drifts by some threshold, save
deferSave() deferSave()
} }
} }
@ -638,18 +640,21 @@ class PlaybackService :
// --- OTHER FUNCTIONS --- // --- OTHER FUNCTIONS ---
private fun deferSave() { private fun deferSave() {
saveJob {
logD("Waiting for save buffer")
delay(SAVE_BUFFER)
yield()
logD("Committing saved state")
persistenceRepository.saveState(playbackManager.toSavedState())
}
}
private fun saveJob(block: suspend () -> Unit) {
currentSaveJob?.let { currentSaveJob?.let {
logD("Discarding prior save job") logD("Discarding prior save job")
it.cancel() it.cancel()
} }
currentSaveJob = currentSaveJob = saveScope.launch { block() }
saveScope.launch {
logD("Waiting for save buffer")
delay(SAVE_BUFFER)
yield()
logD("Committing saved state")
persistenceRepository.saveState(playbackManager.toSavedState())
}
} }
private fun broadcastAudioEffectAction(event: String) { private fun broadcastAudioEffectAction(event: String) {
@ -664,8 +669,19 @@ class PlaybackService :
private fun endSession() { private fun endSession() {
// This session has ended, so we need to reset this flag for when the next // This session has ended, so we need to reset this flag for when the next
// session starts. // session starts.
hasPlayed = false saveJob {
foregroundManager.tryStopForeground() logD("Committing saved state")
persistenceRepository.saveState(playbackManager.toSavedState())
withContext(Dispatchers.Main) {
// User could feasibly start playing again if they were fast enough, so
// we need to avoid stopping the foreground state if that's the case.
if (!player.isPlaying) {
hasPlayed = false
playbackManager.playing(false)
foregroundManager.tryStopForeground()
}
}
}
} }
/** /**