playback: simplify the context start paths

This commit is contained in:
austinried
2026-11-12 05:02:49 +00:00
parent 29335f7ddf
commit d62bff5ace
@@ -104,7 +104,7 @@ private data class ReloadUndo(
} }
private data class PendingPlay( private data class PendingPlay(
val entries: List<QueueEntry>, val entry: QueueEntry,
val position: Long, val position: Long,
) )
@@ -127,7 +127,7 @@ class PlaybackController(
private var player: PlayerHandle? = null private var player: PlayerHandle? = null
private var connecting = false private var connecting = false
private var pendingPlay: PendingPlay? = null private var pendingPlay: PendingPlay? = null
private var pendingShuffle: List<QueueEntry>? = null private var pendingShuffle: QueueEntry? = null
private var positionJob: Job? = null private var positionJob: Job? = null
private var windowJob: Job? = null private var windowJob: Job? = null
private var bufferingJob: Job? = null private var bufferingJob: Job? = null
@@ -190,7 +190,7 @@ class PlaybackController(
val shuffle = pendingShuffle val shuffle = pendingShuffle
pendingShuffle = null pendingShuffle = null
when { when {
pending != null -> start(pending.entries, pending.position) pending != null -> start(pending.entry, pending.position)
shuffle != null -> startShuffled(shuffle) shuffle != null -> startShuffled(shuffle)
else -> restore() else -> restore()
} }
@@ -210,89 +210,75 @@ class PlaybackController(
sourceId: Long, sourceId: Long,
albumId: String, albumId: String,
startOrdinal: Long, startOrdinal: Long,
) = playContext(queueRepository.albumEntry(sourceId, albumId), startOrdinal) ) = play(queueRepository.albumEntry(sourceId, albumId), startOrdinal)
fun playSong( fun playSong(
sourceId: Long, sourceId: Long,
songId: String, songId: String,
) = playContext(queueRepository.songEntry(sourceId, songId), 0) ) = play(queueRepository.songEntry(sourceId, songId), 0)
fun playPlaylist( fun playPlaylist(
sourceId: Long, sourceId: Long,
playlistId: String, playlistId: String,
startPosition: Long, startPosition: Long,
) = playContext(queueRepository.playlistEntry(sourceId, playlistId), startPosition) ) = play(queueRepository.playlistEntry(sourceId, playlistId), startPosition)
fun playGenre( fun playGenre(
sourceId: Long, sourceId: Long,
genre: String, genre: String,
startOrdinal: Long, startOrdinal: Long,
) = playContext(queueRepository.genreEntry(sourceId, genre), startOrdinal) ) = play(queueRepository.genreEntry(sourceId, genre), startOrdinal)
fun playDownloaded( fun playDownloaded(
sourceId: Long, sourceId: Long,
startOrdinal: Long, startOrdinal: Long,
) = playContext(queueRepository.downloadedEntry(sourceId), startOrdinal) ) = play(queueRepository.downloadedEntry(sourceId), startOrdinal)
fun playStarred( fun playStarred(
sourceId: Long, sourceId: Long,
startOrdinal: Long, startOrdinal: Long,
) = playContext(queueRepository.starredEntry(sourceId), startOrdinal) ) = play(queueRepository.starredEntry(sourceId), startOrdinal)
fun shuffleAlbum( fun shuffleAlbum(
sourceId: Long, sourceId: Long,
albumId: String, albumId: String,
) = shuffleContext(queueRepository.albumEntry(sourceId, albumId)) ) = shufflePlay(queueRepository.albumEntry(sourceId, albumId))
fun shufflePlaylist( fun shufflePlaylist(
sourceId: Long, sourceId: Long,
playlistId: String, playlistId: String,
) = shuffleContext(queueRepository.playlistEntry(sourceId, playlistId)) ) = shufflePlay(queueRepository.playlistEntry(sourceId, playlistId))
fun shuffleArtist( fun shuffleArtist(
sourceId: Long, sourceId: Long,
artistId: String, artistId: String,
) = shuffleContext(queueRepository.artistEntry(sourceId, artistId)) ) = shufflePlay(queueRepository.artistEntry(sourceId, artistId))
fun shuffleGenre( fun shuffleGenre(
sourceId: Long, sourceId: Long,
genre: String, genre: String,
) = shuffleContext(queueRepository.genreEntry(sourceId, genre)) ) = shufflePlay(queueRepository.genreEntry(sourceId, genre))
fun shuffleStarred(sourceId: Long) = shuffleContext(queueRepository.starredEntry(sourceId)) fun shuffleStarred(sourceId: Long) = shufflePlay(queueRepository.starredEntry(sourceId))
fun shuffleDownloaded(sourceId: Long) = shuffleContext(queueRepository.downloadedEntry(sourceId)) fun shuffleDownloaded(sourceId: Long) = shufflePlay(queueRepository.downloadedEntry(sourceId))
private fun playContext( private fun shufflePlay(entry: QueueEntry) {
entry: QueueEntry,
start: Long,
) = play(listOf(entry), start)
private fun shuffleContext(entry: QueueEntry) = shufflePlay(listOf(entry))
private fun shufflePlay(entries: List<QueueEntry>) {
if (player == null) { if (player == null) {
pendingShuffle = entries pendingShuffle = entry
connect() connect()
return return
} }
scope.launch { startShuffled(entries) } scope.launch { startShuffled(entry) }
} }
private suspend fun startShuffled(entries: List<QueueEntry>) = private suspend fun startShuffled(entry: QueueEntry) =
startLock.withLock { startLock.withLock {
val entry = entries.first()
windowJob?.cancel()
windowStart = 0
windowEnd = -1
lastEdit = null
endedHandled = false
val previous = snapshot val previous = snapshot
val previousEntry = previous?.entries?.firstOrNull()?.entry val previousEntry = previous?.entries?.firstOrNull()?.entry
val same = previousEntry != null && previousEntry.kind == entry.kind && previousEntry.refId == entry.refId val same = previousEntry != null && previousEntry.kind == entry.kind && previousEntry.refId == entry.refId
val avoid = if (same) currentPosition()?.let { previous.flatContext(previous.anchorContextPlay(it)) } else null val avoid = if (same) currentPosition()?.let { previous.flatContext(previous.anchorContextPlay(it)) } else null
queueRepository.replace(entries) var snap = resetQueue(entry)
var snap = queueRepository.snapshot()
if (snap.contextSize == 0L) { if (snap.contextSize == 0L) {
stopLocked() stopLocked()
return@withLock return@withLock
@@ -307,6 +293,18 @@ class PlaybackController(
loadWindow(0, autoplay = true) loadWindow(0, autoplay = true)
} }
private suspend fun resetQueue(entry: QueueEntry): QueueSnapshot {
windowJob?.cancel()
windowStart = 0
windowEnd = -1
lastEdit = null
endedHandled = false
queueRepository.replace(listOf(entry))
val snapshot = queueRepository.snapshot()
this.snapshot = snapshot
return snapshot
}
private fun randomIndex( private fun randomIndex(
size: Long, size: Long,
avoid: Long?, avoid: Long?,
@@ -968,34 +966,27 @@ class PlaybackController(
} }
private fun play( private fun play(
entries: List<QueueEntry>, entry: QueueEntry,
startPosition: Long, startPosition: Long,
) { ) {
if (player == null) { if (player == null) {
pendingPlay = PendingPlay(entries, startPosition) pendingPlay = PendingPlay(entry, startPosition)
connect() connect()
return return
} }
scope.launch { start(entries, startPosition) } scope.launch { start(entry, startPosition) }
} }
private suspend fun start( private suspend fun start(
entries: List<QueueEntry>, entry: QueueEntry,
startPosition: Long, startPosition: Long,
) = startLock.withLock { ) = startLock.withLock {
windowJob?.cancel() val snapshot = resetQueue(entry)
windowStart = 0
windowEnd = -1
lastEdit = null
endedHandled = false
val modes = queueRepository.modes() val modes = queueRepository.modes()
shuffleEnabled = false shuffleEnabled = false
repeatMode = modes.repeat.toRepeatMode() repeatMode = modes.repeat.toRepeatMode()
player?.setRepeatOne(repeatMode == RepeatMode.One) player?.setRepeatOne(repeatMode == RepeatMode.One)
queueRepository.replace(entries) queueSourceId = entry.sourceId
val snapshot = queueRepository.snapshot()
this.snapshot = snapshot
queueSourceId = entries.firstOrNull()?.sourceId
if (snapshot.size == 0L) { if (snapshot.size == 0L) {
stopLocked() stopLocked()
return@withLock return@withLock