playback: fix brief pause when adding songs to playlists

This commit is contained in:
Alexander Capehart 2024-07-05 12:11:50 -06:00
parent ebdf3e153b
commit 294c558b93
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 44 additions and 12 deletions

View file

@ -10,6 +10,7 @@
- Sorting songs by date now uses songs date first, before the earliest album date - Sorting songs by date now uses songs date first, before the earliest album date
#### What's Fixed #### What's Fixed
- Playback no longer briefly pauses when adding songs to playlists
- Music loader no longer spawns thousands of threads when scanning - Music loader no longer spawns thousands of threads when scanning
- Excessive CPU no longer spent showing music loading process - Excessive CPU no longer spent showing music loading process
- Fixed playback sheet flickering on warm start - Fixed playback sheet flickering on warm start

View file

@ -49,6 +49,7 @@ import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.service.toMediaItem import org.oxycblt.auxio.music.service.toMediaItem
import org.oxycblt.auxio.music.service.toSong import org.oxycblt.auxio.music.service.toSong
import org.oxycblt.auxio.playback.PlaybackSettings import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.playback.msToSecs
import org.oxycblt.auxio.playback.persist.PersistenceRepository import org.oxycblt.auxio.playback.persist.PersistenceRepository
import org.oxycblt.auxio.playback.replaygain.ReplayGainAudioProcessor import org.oxycblt.auxio.playback.replaygain.ReplayGainAudioProcessor
import org.oxycblt.auxio.playback.state.DeferredPlayback import org.oxycblt.auxio.playback.state.DeferredPlayback
@ -365,13 +366,21 @@ class ExoPlaybackStateHolder(
override fun applySavedState( override fun applySavedState(
parent: MusicParent?, parent: MusicParent?,
rawQueue: RawQueue, rawQueue: RawQueue,
positionMs: Long,
repeatMode: RepeatMode,
ack: StateAck.NewPlayback? ack: StateAck.NewPlayback?
) { ) {
logD("Applying saved state") val resolve = resolveQueue()
var sendEvent = false logD("${rawQueue.heap == resolve.heap}")
logD("${rawQueue.shuffledMapping == resolve.shuffledMapping}")
logD("${rawQueue.heapIndex == resolve.heapIndex}")
logD("${rawQueue.isShuffled == resolve.isShuffled}")
logD("${rawQueue == resolve}")
var sendNewPlaybackEvent = false
var shouldSeek = false
if (this.parent != parent) { if (this.parent != parent) {
this.parent = parent this.parent = parent
sendEvent = true sendNewPlaybackEvent = true
} }
if (rawQueue != resolveQueue()) { if (rawQueue != resolveQueue()) {
player.setMediaItems(rawQueue.heap.map { it.toMediaItem(context, null) }) player.setMediaItems(rawQueue.heap.map { it.toMediaItem(context, null) })
@ -384,9 +393,18 @@ class ExoPlaybackStateHolder(
player.seekTo(rawQueue.heapIndex, C.TIME_UNSET) player.seekTo(rawQueue.heapIndex, C.TIME_UNSET)
player.prepare() player.prepare()
player.pause() player.pause()
sendEvent = true sendNewPlaybackEvent = true
shouldSeek = true
} }
if (sendEvent) {
repeatMode(repeatMode)
// Positions in milliseconds will drift during tight restores (i.e what the music loader
// does to sanitize the state), compare by seconds instead.
if (positionMs.msToSecs() != player.currentPosition.msToSecs() || shouldSeek) {
player.seekTo(positionMs)
}
if (sendNewPlaybackEvent) {
ack?.let { playbackManager.ack(this, it) } ack?.let { playbackManager.ack(this, it) }
} }
} }

View file

@ -145,7 +145,13 @@ interface PlaybackStateHolder {
* @param ack The [StateAck] to return to [PlaybackStateManager]. If null, do not return any * @param ack The [StateAck] to return to [PlaybackStateManager]. If null, do not return any
* ack. * ack.
*/ */
fun applySavedState(parent: MusicParent?, rawQueue: RawQueue, ack: StateAck.NewPlayback?) fun applySavedState(
parent: MusicParent?,
rawQueue: RawQueue,
positionMs: Long,
repeatMode: RepeatMode,
ack: StateAck.NewPlayback?
)
/** End whatever ongoing playback session may be going on */ /** End whatever ongoing playback session may be going on */
fun endSession() fun endSession()

View file

@ -24,6 +24,7 @@ import org.oxycblt.auxio.list.adapter.UpdateInstructions
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.PlaybackStateManager.Listener
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logW import org.oxycblt.auxio.util.logW
@ -416,9 +417,12 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
this.stateHolder = stateHolder this.stateHolder = stateHolder
if (isInitialized && currentSong != null) { if (isInitialized && currentSong != null) {
stateHolder.applySavedState(stateMirror.parent, stateMirror.rawQueue, null) stateHolder.applySavedState(
stateHolder.seekTo(stateMirror.progression.calculateElapsedPositionMs()) stateMirror.parent,
stateHolder.playing(false) stateMirror.rawQueue,
stateMirror.progression.calculateElapsedPositionMs(),
stateMirror.repeatMode,
null)
} }
pendingDeferredPlayback?.let(stateHolder::handleDeferred) pendingDeferredPlayback?.let(stateHolder::handleDeferred)
} }
@ -795,9 +799,12 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
index index
}) })
stateHolder.applySavedState(savedState.parent, rawQueue, StateAck.NewPlayback) stateHolder.applySavedState(
stateHolder.seekTo(savedState.positionMs) savedState.parent,
stateHolder.repeatMode(savedState.repeatMode) rawQueue,
savedState.positionMs,
savedState.repeatMode,
StateAck.NewPlayback)
isInitialized = true isInitialized = true
} }