Fix network on main exception trying to play theme songs (#111)

Fetch the theme song info on the IO thread

This would throw an exception on some devices, but it would be caught
without affecting the app, other than just not playing theme music.
This commit is contained in:
damontecres 2025-10-29 20:07:00 -04:00 committed by GitHub
parent 84ee57225b
commit f76556f90e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 18 deletions

View file

@ -146,7 +146,7 @@ class SeriesViewModel
seriesId: UUID,
playThemeSongs: ThemeSongVolume,
) {
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
val themeSongs = api.libraryApi.getThemeSongs(seriesId).content
themeSongs.items.firstOrNull()?.let { theme ->
theme.mediaSources?.firstOrNull()?.let { source ->
@ -161,7 +161,7 @@ class SeriesViewModel
Codec.Audio.FLAC,
),
)
Timber.Forest.v("Found theme song for series $seriesId")
Timber.v("Found theme song for series $seriesId")
withContext(Dispatchers.Main) {
themeSongPlayer.play(playThemeSongs, url)
addCloseable {

View file

@ -173,10 +173,11 @@ class PlaybackViewModel
this.itemId = itemId
val item = destination.item
viewModelScope.launch(
Dispatchers.IO +
LoadingExceptionHandler(
loading,
"Error preparing for playback for ${destination.itemId}",
) + Dispatchers.IO,
),
) {
val queriedItem = item?.data ?: api.userLibraryApi.getItem(itemId).content
val base =
@ -493,7 +494,7 @@ class PlaybackViewModel
subtitleIndex = subtitleIndex ?: TrackIndex.DISABLED,
)
if (userInitiated) {
viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
viewModelScope.launchIO {
Timber.v("Saving user initiated item playback: %s", itemPlayback)
val updated = itemPlaybackRepository.saveItemPlayback(itemPlayback)
withContext(Dispatchers.Main) {
@ -560,7 +561,7 @@ class PlaybackViewModel
}
fun changeAudioStream(index: Int) {
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
changeStreams(
dto,
currentItemPlayback.value!!,
@ -573,7 +574,7 @@ class PlaybackViewModel
}
fun changeSubtitleStream(index: Int?): Job =
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
changeStreams(
dto,
currentItemPlayback.value!!,
@ -604,7 +605,7 @@ class PlaybackViewModel
object : Player.Listener {
override fun onPlaybackStateChanged(playbackState: Int) {
if (playbackState == Player.STATE_ENDED) {
viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
viewModelScope.launchIO {
val nextItem = playlist.peek()
Timber.v("Setting next up to ${nextItem?.id}")
withContext(Dispatchers.Main) {
@ -625,7 +626,7 @@ class PlaybackViewModel
private fun listenForSegments() {
segmentJob?.cancel()
segmentJob =
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
viewModelScope.launchIO {
val prefs = preferences.appPreferences.playbackPreferences
val segments by api.mediaSegmentsApi.getItemSegments(itemId)
if (segments.items.isNotEmpty()) {
@ -700,7 +701,7 @@ class PlaybackViewModel
fun playUpNextUp() {
playlist.value?.let {
if (it.hasNext()) {
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
cancelUpNextEpisode()
val item = it.getAndAdvance()
val played = play(item.data, 0)
@ -715,7 +716,7 @@ class PlaybackViewModel
fun playPrevious() {
playlist.value?.let {
if (it.hasPrevious()) {
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
cancelUpNextEpisode()
val item = it.getPreviousAndReverse()
val played = play(item.data, 0)
@ -727,13 +728,13 @@ class PlaybackViewModel
}
}
fun cancelUpNextEpisode() {
nextUp.value = null
suspend fun cancelUpNextEpisode() {
nextUp.setValueOnMain(null)
}
fun playItemInPlaylist(item: BaseItem) {
playlist.value?.let { playlist ->
viewModelScope.launch(ExceptionHandler()) {
viewModelScope.launchIO {
val toPlay = playlist.advanceTo(item.id)
if (toPlay != null) {
val played = play(toPlay.data, 0)

View file

@ -3,12 +3,12 @@ package com.github.damontecres.wholphin.util
import android.content.Context
import android.widget.Toast
import com.github.damontecres.wholphin.hilt.IoCoroutineScope
import com.github.damontecres.wholphin.ui.launchIO
import com.github.damontecres.wholphin.ui.showToast
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.sessionApi
import org.jellyfin.sdk.api.sockets.subscribe
@ -32,7 +32,7 @@ class ServerEventListener
}
fun init() {
scope.launch(ExceptionHandler()) {
scope.launchIO {
api.sessionApi.postCapabilities(
playableMediaTypes = listOf(MediaType.VIDEO),
supportedCommands =