Play live channel

This commit is contained in:
Damontecres 2025-10-20 15:12:03 -04:00
parent d42f24806a
commit 753acb7b38
No known key found for this signature in database
4 changed files with 28 additions and 3 deletions

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.damontecres.wholphin.ui.detail.series.SeasonEpisode
import com.github.damontecres.wholphin.ui.nav.NavigationManager
import com.github.damontecres.wholphin.util.GetProgramsDtoHandler
import com.github.damontecres.wholphin.util.LoadingExceptionHandler
import com.github.damontecres.wholphin.util.LoadingState
@ -34,6 +35,7 @@ class LiveTvViewModel
@Inject
constructor(
val api: ApiClient,
val navigationManager: NavigationManager,
) : ViewModel() {
val loading = MutableLiveData<LoadingState>(LoadingState.Pending)

View file

@ -35,6 +35,7 @@ import coil3.compose.AsyncImage
import com.github.damontecres.wholphin.ui.components.ErrorMessage
import com.github.damontecres.wholphin.ui.components.LoadingPage
import com.github.damontecres.wholphin.ui.enableMarquee
import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.rememberInt
import com.github.damontecres.wholphin.util.ExceptionHandler
import com.github.damontecres.wholphin.util.LoadingState
@ -73,6 +74,14 @@ fun TvGrid(
programList = programs,
programs = programsByChannel,
start = viewModel.start,
onClick = { program ->
viewModel.navigationManager.navigateTo(
Destination.Playback(
itemId = program.channelId,
positionMs = 0L,
),
)
},
modifier =
Modifier
.fillMaxSize()
@ -88,6 +97,7 @@ fun TvGrid(
programList: List<TvProgram>,
programs: Map<UUID, List<TvProgram>>,
start: LocalDateTime,
onClick: (TvProgram) -> Unit,
modifier: Modifier = Modifier,
) {
val focusManager = LocalFocusManager.current
@ -188,7 +198,9 @@ fun TvGrid(
}
Key.DirectionCenter, Key.Enter, Key.NumPadEnter -> {
Timber.v("Clicked on ${programList[focusedProgramIndex]}")
val program = programList[focusedProgramIndex]
Timber.v("Clicked on %s", program)
onClick.invoke(program)
null
}

View file

@ -32,6 +32,7 @@ import com.github.damontecres.wholphin.preferences.SkipSegmentBehavior
import com.github.damontecres.wholphin.preferences.UserPreferences
import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.nav.NavigationManager
import com.github.damontecres.wholphin.ui.setValueOnMain
import com.github.damontecres.wholphin.ui.showToast
import com.github.damontecres.wholphin.ui.toServerString
import com.github.damontecres.wholphin.util.EqualityMutableLiveData
@ -216,6 +217,7 @@ class PlaybackViewModel
)
return@withContext false
}
val isLiveTv = base.type == BaseItemKind.TV_CHANNEL
dto = base
val title =
@ -316,7 +318,7 @@ class PlaybackViewModel
rowId = -1,
userId = -1,
itemId = base.id,
sourceId = mediaSource.id?.toUUIDOrNull(),
sourceId = if (!isLiveTv) mediaSource.id?.toUUIDOrNull() else null,
audioIndex = audioIndex ?: TrackIndex.UNSPECIFIED,
subtitleIndex = subtitleIndex ?: TrackIndex.UNSPECIFIED,
)
@ -386,12 +388,16 @@ class PlaybackViewModel
subtitleStreamIndex = subtitleIndex,
allowVideoStreamCopy = true,
allowAudioStreamCopy = true,
autoOpenLiveStream = false,
autoOpenLiveStream = true,
mediaSourceId = currentItemPlayback.sourceId?.toServerString(),
alwaysBurnInSubtitleWhenTranscoding = null,
maxStreamingBitrate = maxBitrate.toInt(),
),
)
if (response.errorCode != null) {
loading.setValueOnMain(LoadingState.Error(response.errorCode?.serialName))
return@withContext
}
val source = response.mediaSources.firstOrNull()
source?.let { source ->
val mediaUrl =

View file

@ -21,6 +21,11 @@ val supportItemKinds =
BaseItemKind.COLLECTION_FOLDER,
BaseItemKind.USER_VIEW,
BaseItemKind.TRAILER,
BaseItemKind.TV_CHANNEL,
BaseItemKind.TV_PROGRAM,
BaseItemKind.LIVE_TV_CHANNEL,
BaseItemKind.LIVE_TV_PROGRAM,
BaseItemKind.RECORDING,
)
val supportedCollectionTypes =