Skip to content

Commit

Permalink
Fix PlaySessionService no longer reporting to server
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsvanvelzen committed Jul 2, 2024
1 parent 483cfc8 commit 3bd33cc
Showing 1 changed file with 72 additions and 87 deletions.
159 changes: 72 additions & 87 deletions playback/jellyfin/src/main/kotlin/playsession/PlaySessionService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
Expand All @@ -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<QueueItem> {
Expand All @@ -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(),
)
)
}
}

0 comments on commit 3bd33cc

Please sign in to comment.