diff --git a/app/src/main/java/com/happyseal/zenplayer/features/player/data/AudioFocusManager.kt b/app/src/main/java/com/happyseal/zenplayer/features/player/data/AudioFocusManager.kt index cfa91350..72db6672 100644 --- a/app/src/main/java/com/happyseal/zenplayer/features/player/data/AudioFocusManager.kt +++ b/app/src/main/java/com/happyseal/zenplayer/features/player/data/AudioFocusManager.kt @@ -39,8 +39,13 @@ class AudioFocusManager( ) { private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager + @Volatile private var currentFocusState = FocusState.NO_FOCUS + + @Volatile private var wasPlayingBeforeTransientLoss = false + + @Volatile private var wasDucked = false private val audioFocusChangeListener = diff --git a/app/src/main/java/com/happyseal/zenplayer/features/player/data/PlayQueueManager.kt b/app/src/main/java/com/happyseal/zenplayer/features/player/data/PlayQueueManager.kt index d21ddd51..6f18942b 100644 --- a/app/src/main/java/com/happyseal/zenplayer/features/player/data/PlayQueueManager.kt +++ b/app/src/main/java/com/happyseal/zenplayer/features/player/data/PlayQueueManager.kt @@ -84,8 +84,11 @@ class PlayQueueManager( * 다음 곡 재생 */ override suspend fun playNext() { - check(_playQueue.value != null) { "재생 큐가 설정되지 않은 상태에서 playNext() 호출" } - playlistMutex.withLock { playNextInternal() } + val action = playlistMutex.withLock { + check(_playQueue.value != null) { "재생 큐가 설정되지 않은 상태에서 playNext() 호출" } + computeNextAction() + } + action() } /** @@ -132,30 +135,33 @@ class PlayQueueManager( } } - private suspend fun playNextInternal() { - val current = _playQueue.value ?: return + // 락 안에서 상태를 변경하고, 락 밖에서 실행할 side effect(emit/play)를 반환한다. + private fun computeNextAction(): suspend () -> Unit { + val current = _playQueue.value ?: return {} - when (_repeatMode.value) { - RepeatMode.ONE -> { - current.currentTrack?.let { audioController.prepareTrack(it) } + if (_repeatMode.value == RepeatMode.ONE) { + val track = current.currentTrack + return { + track?.let { audioController.prepareTrack(it) } audioController.play() - return } - // NONE/ALL은 공통 로직(다음 인덱스 계산)으로 fall-through - RepeatMode.NONE, - RepeatMode.ALL, - -> Unit } val nextIndex = getNextIndex(current) - if (nextIndex != null) { + return if (nextIndex != null) { val updated = current.copy(currentIndex = nextIndex) _playQueue.value = updated - updated.currentTrack?.let { audioController.prepareTrack(it) } - audioController.play() + val track = updated.currentTrack + { + track?.let { audioController.prepareTrack(it) } + audioController.play() + } } else { - _events.emit(PlaylistEvent.PlaylistEnded) - current.currentTrack?.let { audioController.prepareTrack(it) } + val track = current.currentTrack + { + _events.emit(PlaylistEvent.PlaylistEnded) + track?.let { audioController.prepareTrack(it) } + } } }