diff --git a/playback/jellyfin/src/main/kotlin/playsession/PlaySessionService.kt b/playback/jellyfin/src/main/kotlin/playsession/PlaySessionService.kt index 5085d18c7d..a3ed3dd448 100644 --- a/playback/jellyfin/src/main/kotlin/playsession/PlaySessionService.kt +++ b/playback/jellyfin/src/main/kotlin/playsession/PlaySessionService.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.jellyfin.playback.core.mediastream.MediaConversionMethod -import org.jellyfin.playback.core.mediastream.PlayableMediaStream import org.jellyfin.playback.core.mediastream.mediaStream import org.jellyfin.playback.core.model.PlayState import org.jellyfin.playback.core.model.RepeatMode @@ -27,17 +26,13 @@ import org.jellyfin.sdk.model.api.RepeatMode as SdkRepeatMode class PlaySessionService( private val api: ApiClient, ) : PlayerService() { - private var reportedStream: PlayableMediaStream? = null - override suspend fun onInitialize() { - state.queue.entry.onEach { item -> onMediaStreamChange(item?.mediaStream) }.launchIn(coroutineScope) - state.playState.onEach { playState -> when (playState) { - PlayState.PLAYING -> onStart() - PlayState.STOPPED -> onStop() - PlayState.PAUSED -> onPause() - PlayState.ERROR -> onStop() + PlayState.PLAYING -> sendStreamStart() + PlayState.STOPPED -> sendStreamStop() + PlayState.PAUSED -> sendStreamUpdate() + PlayState.ERROR -> sendStreamStop() } }.launchIn(coroutineScope) } @@ -57,32 +52,7 @@ class PlaySessionService( } suspend fun sendUpdateIfActive() { - reportedStream?.let { - coroutineScope.launch { sendStreamUpdate(it) } - } - } - - private fun onMediaStreamChange(stream: PlayableMediaStream?) { - reportedStream = stream - onStart() - } - - private fun onStart() { - reportedStream?.let { - coroutineScope.launch { sendStreamStart(it) } - } - } - - private fun onStop() { - reportedStream?.let { - coroutineScope.launch { sendStreamStop(it) } - } - } - - private fun onPause() { - reportedStream?.let { - coroutineScope.launch { sendStreamUpdate(it) } - } + coroutineScope.launch { sendStreamUpdate() } } private suspend fun getQueue(): List { @@ -94,61 +64,76 @@ class PlaySessionService( .map { QueueItem(id = it.id, playlistItemId = it.playlistItemId) } } - private suspend fun sendStreamStart(stream: PlayableMediaStream) { - val item = stream.queueEntry.baseItem ?: return - api.playStateApi.reportPlaybackStart(PlaybackStartInfo( - itemId = item.id, - playSessionId = stream.identifier, - playlistItemId = item.playlistItemId, - canSeek = true, - isMuted = state.volume.muted, - volumeLevel = (state.volume.volume * 100).roundToInt(), - isPaused = state.playState.value != PlayState.PLAYING, - aspectRatio = state.videoSize.value.aspectRatio.toString(), - positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, - playMethod = stream.conversionMethod.playMethod, - repeatMode = state.repeatMode.value.remoteRepeatMode, - nowPlayingQueue = getQueue(), - playbackOrder = when (state.playbackOrder.value) { - org.jellyfin.playback.core.model.PlaybackOrder.DEFAULT -> PlaybackOrder.DEFAULT - org.jellyfin.playback.core.model.PlaybackOrder.RANDOM -> PlaybackOrder.SHUFFLE - org.jellyfin.playback.core.model.PlaybackOrder.SHUFFLE -> PlaybackOrder.SHUFFLE - } - )) + private suspend fun sendStreamStart() { + val entry = state.queue.entry.value ?: return + val stream = entry.mediaStream ?: return + val item = entry.baseItem ?: return + + api.playStateApi.reportPlaybackStart( + PlaybackStartInfo( + itemId = item.id, + playSessionId = stream.identifier, + playlistItemId = item.playlistItemId, + canSeek = true, + isMuted = state.volume.muted, + volumeLevel = (state.volume.volume * 100).roundToInt(), + isPaused = state.playState.value != PlayState.PLAYING, + aspectRatio = state.videoSize.value.aspectRatio.toString(), + positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, + playMethod = stream.conversionMethod.playMethod, + repeatMode = state.repeatMode.value.remoteRepeatMode, + nowPlayingQueue = getQueue(), + playbackOrder = when (state.playbackOrder.value) { + org.jellyfin.playback.core.model.PlaybackOrder.DEFAULT -> PlaybackOrder.DEFAULT + org.jellyfin.playback.core.model.PlaybackOrder.RANDOM -> PlaybackOrder.SHUFFLE + org.jellyfin.playback.core.model.PlaybackOrder.SHUFFLE -> PlaybackOrder.SHUFFLE + } + ) + ) } - private suspend fun sendStreamUpdate(stream: PlayableMediaStream) { - val item = stream.queueEntry.baseItem ?: return - api.playStateApi.reportPlaybackProgress(PlaybackProgressInfo( - itemId = item.id, - playSessionId = stream.identifier, - playlistItemId = item.playlistItemId, - canSeek = true, - isMuted = state.volume.muted, - volumeLevel = (state.volume.volume * 100).roundToInt(), - isPaused = state.playState.value != PlayState.PLAYING, - aspectRatio = state.videoSize.value.aspectRatio.toString(), - positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, - playMethod = stream.conversionMethod.playMethod, - repeatMode = state.repeatMode.value.remoteRepeatMode, - nowPlayingQueue = getQueue(), - playbackOrder = when (state.playbackOrder.value) { - org.jellyfin.playback.core.model.PlaybackOrder.DEFAULT -> PlaybackOrder.DEFAULT - org.jellyfin.playback.core.model.PlaybackOrder.RANDOM -> PlaybackOrder.SHUFFLE - org.jellyfin.playback.core.model.PlaybackOrder.SHUFFLE -> PlaybackOrder.SHUFFLE - } - )) + private suspend fun sendStreamUpdate() { + val entry = state.queue.entry.value ?: return + val stream = entry.mediaStream ?: return + val item = entry.baseItem ?: return + + api.playStateApi.reportPlaybackProgress( + PlaybackProgressInfo( + itemId = item.id, + playSessionId = stream.identifier, + playlistItemId = item.playlistItemId, + canSeek = true, + isMuted = state.volume.muted, + volumeLevel = (state.volume.volume * 100).roundToInt(), + isPaused = state.playState.value != PlayState.PLAYING, + aspectRatio = state.videoSize.value.aspectRatio.toString(), + positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, + playMethod = stream.conversionMethod.playMethod, + repeatMode = state.repeatMode.value.remoteRepeatMode, + nowPlayingQueue = getQueue(), + playbackOrder = when (state.playbackOrder.value) { + org.jellyfin.playback.core.model.PlaybackOrder.DEFAULT -> PlaybackOrder.DEFAULT + org.jellyfin.playback.core.model.PlaybackOrder.RANDOM -> PlaybackOrder.SHUFFLE + org.jellyfin.playback.core.model.PlaybackOrder.SHUFFLE -> PlaybackOrder.SHUFFLE + } + ) + ) } - private suspend fun sendStreamStop(stream: PlayableMediaStream) { - val item = stream.queueEntry.baseItem ?: return - api.playStateApi.reportPlaybackStopped(PlaybackStopInfo( - itemId = item.id, - playSessionId = stream.identifier, - playlistItemId = item.playlistItemId, - positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, - failed = false, - nowPlayingQueue = getQueue(), - )) + private suspend fun sendStreamStop() { + val entry = state.queue.entry.value ?: return + val stream = entry.mediaStream ?: return + val item = entry.baseItem ?: return + + api.playStateApi.reportPlaybackStopped( + PlaybackStopInfo( + itemId = item.id, + playSessionId = stream.identifier, + playlistItemId = item.playlistItemId, + positionTicks = withContext(Dispatchers.Main) { state.positionInfo.active.inWholeTicks }, + failed = false, + nowPlayingQueue = getQueue(), + ) + ) } }