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.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.github.damontecres.wholphin.ui.detail.series.SeasonEpisode 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.GetProgramsDtoHandler
import com.github.damontecres.wholphin.util.LoadingExceptionHandler import com.github.damontecres.wholphin.util.LoadingExceptionHandler
import com.github.damontecres.wholphin.util.LoadingState import com.github.damontecres.wholphin.util.LoadingState
@ -34,6 +35,7 @@ class LiveTvViewModel
@Inject @Inject
constructor( constructor(
val api: ApiClient, val api: ApiClient,
val navigationManager: NavigationManager,
) : ViewModel() { ) : ViewModel() {
val loading = MutableLiveData<LoadingState>(LoadingState.Pending) 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.ErrorMessage
import com.github.damontecres.wholphin.ui.components.LoadingPage import com.github.damontecres.wholphin.ui.components.LoadingPage
import com.github.damontecres.wholphin.ui.enableMarquee 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.ui.rememberInt
import com.github.damontecres.wholphin.util.ExceptionHandler import com.github.damontecres.wholphin.util.ExceptionHandler
import com.github.damontecres.wholphin.util.LoadingState import com.github.damontecres.wholphin.util.LoadingState
@ -73,6 +74,14 @@ fun TvGrid(
programList = programs, programList = programs,
programs = programsByChannel, programs = programsByChannel,
start = viewModel.start, start = viewModel.start,
onClick = { program ->
viewModel.navigationManager.navigateTo(
Destination.Playback(
itemId = program.channelId,
positionMs = 0L,
),
)
},
modifier = modifier =
Modifier Modifier
.fillMaxSize() .fillMaxSize()
@ -88,6 +97,7 @@ fun TvGrid(
programList: List<TvProgram>, programList: List<TvProgram>,
programs: Map<UUID, List<TvProgram>>, programs: Map<UUID, List<TvProgram>>,
start: LocalDateTime, start: LocalDateTime,
onClick: (TvProgram) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val focusManager = LocalFocusManager.current val focusManager = LocalFocusManager.current
@ -188,7 +198,9 @@ fun TvGrid(
} }
Key.DirectionCenter, Key.Enter, Key.NumPadEnter -> { 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 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.preferences.UserPreferences
import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.nav.NavigationManager 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.showToast
import com.github.damontecres.wholphin.ui.toServerString import com.github.damontecres.wholphin.ui.toServerString
import com.github.damontecres.wholphin.util.EqualityMutableLiveData import com.github.damontecres.wholphin.util.EqualityMutableLiveData
@ -216,6 +217,7 @@ class PlaybackViewModel
) )
return@withContext false return@withContext false
} }
val isLiveTv = base.type == BaseItemKind.TV_CHANNEL
dto = base dto = base
val title = val title =
@ -316,7 +318,7 @@ class PlaybackViewModel
rowId = -1, rowId = -1,
userId = -1, userId = -1,
itemId = base.id, itemId = base.id,
sourceId = mediaSource.id?.toUUIDOrNull(), sourceId = if (!isLiveTv) mediaSource.id?.toUUIDOrNull() else null,
audioIndex = audioIndex ?: TrackIndex.UNSPECIFIED, audioIndex = audioIndex ?: TrackIndex.UNSPECIFIED,
subtitleIndex = subtitleIndex ?: TrackIndex.UNSPECIFIED, subtitleIndex = subtitleIndex ?: TrackIndex.UNSPECIFIED,
) )
@ -386,12 +388,16 @@ class PlaybackViewModel
subtitleStreamIndex = subtitleIndex, subtitleStreamIndex = subtitleIndex,
allowVideoStreamCopy = true, allowVideoStreamCopy = true,
allowAudioStreamCopy = true, allowAudioStreamCopy = true,
autoOpenLiveStream = false, autoOpenLiveStream = true,
mediaSourceId = currentItemPlayback.sourceId?.toServerString(), mediaSourceId = currentItemPlayback.sourceId?.toServerString(),
alwaysBurnInSubtitleWhenTranscoding = null, alwaysBurnInSubtitleWhenTranscoding = null,
maxStreamingBitrate = maxBitrate.toInt(), maxStreamingBitrate = maxBitrate.toInt(),
), ),
) )
if (response.errorCode != null) {
loading.setValueOnMain(LoadingState.Error(response.errorCode?.serialName))
return@withContext
}
val source = response.mediaSources.firstOrNull() val source = response.mediaSources.firstOrNull()
source?.let { source -> source?.let { source ->
val mediaUrl = val mediaUrl =

View file

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