mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Show playback debug info
This commit is contained in:
parent
9cc2fc40d3
commit
64e881f51c
9 changed files with 177 additions and 28 deletions
|
|
@ -187,18 +187,17 @@ sealed interface AppPreference<T> {
|
||||||
summaryOff = R.string.disabled,
|
summaryOff = R.string.disabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
// val PlaybackDebugInfo =
|
val PlaybackDebugInfo =
|
||||||
// AppSwitchPreference(
|
AppSwitchPreference(
|
||||||
// title = R.string.playback_debug_info,
|
title = R.string.playback_debug_info,
|
||||||
// prefKey = R.string.pref_key_show_playback_debug_info,
|
defaultValue = false,
|
||||||
// defaultValue = false,
|
getter = { it.playbackPreferences.showDebugInfo },
|
||||||
// getter = { it.playbackPreferences.showDebugInfo },
|
setter = { prefs, value ->
|
||||||
// setter = { prefs, value ->
|
prefs.updatePlaybackPreferences { showDebugInfo = value }
|
||||||
// prefs.updatePlaybackPreferences { showDebugInfo = value }
|
},
|
||||||
// },
|
summaryOn = R.string.show,
|
||||||
// summaryOn = R.string.show,
|
summaryOff = R.string.hide,
|
||||||
// summaryOff = R.string.hide,
|
)
|
||||||
// )
|
|
||||||
|
|
||||||
// val AutoCheckForUpdates =
|
// val AutoCheckForUpdates =
|
||||||
// AppSwitchPreference(
|
// AppSwitchPreference(
|
||||||
|
|
@ -246,6 +245,7 @@ val basicPreferences =
|
||||||
AppPreference.RewatchNextUp,
|
AppPreference.RewatchNextUp,
|
||||||
AppPreference.PlayThemeMusic,
|
AppPreference.PlayThemeMusic,
|
||||||
AppPreference.OssLicenseInfo,
|
AppPreference.OssLicenseInfo,
|
||||||
|
AppPreference.PlaybackDebugInfo,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class AppPreferencesSerializer
|
||||||
AppPreference.SkipBack.defaultValue.seconds.inWholeMilliseconds
|
AppPreference.SkipBack.defaultValue.seconds.inWholeMilliseconds
|
||||||
controllerTimeoutMs = AppPreference.ControllerTimeout.defaultValue
|
controllerTimeoutMs = AppPreference.ControllerTimeout.defaultValue
|
||||||
seekBarSteps = AppPreference.SeekBarSteps.defaultValue.toInt()
|
seekBarSteps = AppPreference.SeekBarSteps.defaultValue.toInt()
|
||||||
|
showDebugInfo = AppPreference.PlaybackDebugInfo.defaultValue
|
||||||
}.build()
|
}.build()
|
||||||
homePagePreferences =
|
homePagePreferences =
|
||||||
HomePagePreferences
|
HomePagePreferences
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ fun PlaybackContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
viewModel: PlaybackViewModel = hiltViewModel(),
|
viewModel: PlaybackViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
|
val prefs = preferences.appPreferences.playbackPreferences
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
LaunchedEffect(destination.itemId) {
|
LaunchedEffect(destination.itemId) {
|
||||||
|
|
@ -88,6 +89,7 @@ fun PlaybackContent(
|
||||||
val currentPlayback by viewModel.currentPlayback.observeAsState(null)
|
val currentPlayback by viewModel.currentPlayback.observeAsState(null)
|
||||||
|
|
||||||
var cues by remember { mutableStateOf<List<Cue>>(listOf()) }
|
var cues by remember { mutableStateOf<List<Cue>>(listOf()) }
|
||||||
|
var showDebugInfo by remember { mutableStateOf(prefs.showDebugInfo) }
|
||||||
|
|
||||||
// TODO move to viewmodel?
|
// TODO move to viewmodel?
|
||||||
val cueListener =
|
val cueListener =
|
||||||
|
|
@ -246,7 +248,9 @@ fun PlaybackContent(
|
||||||
contentScale = it.scale
|
contentScale = it.scale
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaybackAction.ShowDebug -> TODO()
|
PlaybackAction.ShowDebug -> {
|
||||||
|
showDebugInfo = !showDebugInfo
|
||||||
|
}
|
||||||
PlaybackAction.ShowPlaylist -> TODO()
|
PlaybackAction.ShowPlaylist -> TODO()
|
||||||
PlaybackAction.ShowVideoFilterDialog -> TODO()
|
PlaybackAction.ShowVideoFilterDialog -> TODO()
|
||||||
is PlaybackAction.ToggleAudio -> {
|
is PlaybackAction.ToggleAudio -> {
|
||||||
|
|
@ -259,12 +263,11 @@ fun PlaybackContent(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSeekBarChange = seekBarState::onValueChange,
|
onSeekBarChange = seekBarState::onValueChange,
|
||||||
showDebugInfo = false,
|
showDebugInfo = showDebugInfo,
|
||||||
scale = contentScale,
|
scale = contentScale,
|
||||||
playbackSpeed = playbackSpeed,
|
playbackSpeed = playbackSpeed,
|
||||||
moreButtonOptions = MoreButtonOptions(mapOf()),
|
moreButtonOptions = MoreButtonOptions(mapOf()),
|
||||||
subtitleIndex = currentPlayback?.subtitleIndex,
|
currentPlayback = currentPlayback,
|
||||||
audioIndex = currentPlayback?.audioIndex,
|
|
||||||
audioStreams = audioStreams,
|
audioStreams = audioStreams,
|
||||||
trickplayInfo = trickplay,
|
trickplayInfo = trickplay,
|
||||||
trickplayUrlFor = viewModel::getTrickplayUrl,
|
trickplayUrlFor = viewModel::getTrickplayUrl,
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,7 @@ fun LeftPlaybackButtons(
|
||||||
val options =
|
val options =
|
||||||
buildList {
|
buildList {
|
||||||
addAll(moreButtonOptions.options.keys)
|
addAll(moreButtonOptions.options.keys)
|
||||||
add(if (showDebugInfo) "Hide transcode info" else "Show transcode info")
|
add(if (showDebugInfo) "Hide debug info" else "Show debug info")
|
||||||
}
|
}
|
||||||
BottomDialog(
|
BottomDialog(
|
||||||
choices = options,
|
choices = options,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package com.github.damontecres.dolphin.ui.playback
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.animateDpAsState
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
|
@ -35,9 +36,11 @@ import androidx.media3.common.Player
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.dolphin.data.model.Chapter
|
import com.github.damontecres.dolphin.data.model.Chapter
|
||||||
|
import com.github.damontecres.dolphin.ui.AppColors
|
||||||
import com.github.damontecres.dolphin.ui.cards.ChapterCard
|
import com.github.damontecres.dolphin.ui.cards.ChapterCard
|
||||||
import com.github.damontecres.dolphin.ui.ifElse
|
import com.github.damontecres.dolphin.ui.ifElse
|
||||||
import com.github.damontecres.dolphin.ui.isNotNullOrBlank
|
import com.github.damontecres.dolphin.ui.isNotNullOrBlank
|
||||||
|
import com.github.damontecres.dolphin.ui.letNotEmpty
|
||||||
import org.jellyfin.sdk.model.api.TrickplayInfo
|
import org.jellyfin.sdk.model.api.TrickplayInfo
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
|
|
@ -60,8 +63,7 @@ fun PlaybackOverlay(
|
||||||
scale: ContentScale,
|
scale: ContentScale,
|
||||||
playbackSpeed: Float,
|
playbackSpeed: Float,
|
||||||
moreButtonOptions: MoreButtonOptions,
|
moreButtonOptions: MoreButtonOptions,
|
||||||
subtitleIndex: Int?,
|
currentPlayback: CurrentPlayback?,
|
||||||
audioIndex: Int?,
|
|
||||||
audioStreams: List<AudioStream>,
|
audioStreams: List<AudioStream>,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
subtitle: String? = null,
|
subtitle: String? = null,
|
||||||
|
|
@ -168,8 +170,8 @@ fun PlaybackOverlay(
|
||||||
seekEnabled = seekEnabled,
|
seekEnabled = seekEnabled,
|
||||||
seekBarInteractionSource = seekBarInteractionSource,
|
seekBarInteractionSource = seekBarInteractionSource,
|
||||||
moreButtonOptions = moreButtonOptions,
|
moreButtonOptions = moreButtonOptions,
|
||||||
subtitleIndex = subtitleIndex,
|
subtitleIndex = currentPlayback?.subtitleIndex,
|
||||||
audioIndex = audioIndex,
|
audioIndex = currentPlayback?.audioIndex,
|
||||||
audioStreams = audioStreams,
|
audioStreams = audioStreams,
|
||||||
playbackSpeed = playbackSpeed,
|
playbackSpeed = playbackSpeed,
|
||||||
scale = scale,
|
scale = scale,
|
||||||
|
|
@ -276,5 +278,22 @@ fun PlaybackOverlay(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AnimatedVisibility(
|
||||||
|
showDebugInfo && controllerViewState.controlsVisible,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.align(Alignment.TopStart),
|
||||||
|
) {
|
||||||
|
currentPlayback?.tracks?.letNotEmpty {
|
||||||
|
PlaybackTrackInfo(
|
||||||
|
trackSupport = it,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.align(Alignment.TopStart)
|
||||||
|
.padding(16.dp)
|
||||||
|
.background(AppColors.TransparentBlack50),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
package com.github.damontecres.dolphin.ui.playback
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.tv.material3.Icon
|
||||||
|
import androidx.tv.material3.MaterialTheme
|
||||||
|
import androidx.tv.material3.Text
|
||||||
|
import com.github.damontecres.dolphin.util.TrackSupport
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PlaybackTrackInfo(
|
||||||
|
trackSupport: List<TrackSupport>,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val selectedWeight = .5f
|
||||||
|
val weights = listOf(.25f, .4f, .5f, 1f, 1f)
|
||||||
|
val textStyle =
|
||||||
|
MaterialTheme.typography.bodySmall.copy(color = MaterialTheme.colorScheme.onBackground)
|
||||||
|
|
||||||
|
LazyColumn(
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
|
modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val texts =
|
||||||
|
listOf(
|
||||||
|
"ID",
|
||||||
|
"Type",
|
||||||
|
"Codec",
|
||||||
|
"Supported",
|
||||||
|
"Labels",
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = Modifier.weight(selectedWeight),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Selected",
|
||||||
|
style = textStyle,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
texts.forEachIndexed { index, text ->
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.CenterStart,
|
||||||
|
modifier = Modifier.weight(weights[index]),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = textStyle,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
items(trackSupport) { track ->
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
|
modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val texts =
|
||||||
|
listOf(
|
||||||
|
track.id ?: "",
|
||||||
|
track.type.name,
|
||||||
|
track.codecs ?: "",
|
||||||
|
track.supported.name,
|
||||||
|
track.labels.joinToString(", "),
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = Modifier.weight(selectedWeight),
|
||||||
|
) {
|
||||||
|
if (track.selected) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier.size(12.dp),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = "-",
|
||||||
|
style = textStyle,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
texts.forEachIndexed { index, text ->
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.CenterStart,
|
||||||
|
modifier = Modifier.weight(weights[index]),
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
style = textStyle,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,8 @@ import com.github.damontecres.dolphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.dolphin.ui.nav.Destination
|
import com.github.damontecres.dolphin.ui.nav.Destination
|
||||||
import com.github.damontecres.dolphin.util.ExceptionHandler
|
import com.github.damontecres.dolphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.dolphin.util.TrackActivityPlaybackListener
|
import com.github.damontecres.dolphin.util.TrackActivityPlaybackListener
|
||||||
|
import com.github.damontecres.dolphin.util.TrackSupport
|
||||||
|
import com.github.damontecres.dolphin.util.checkForSupport
|
||||||
import com.github.damontecres.dolphin.util.profile.PlaybackListener
|
import com.github.damontecres.dolphin.util.profile.PlaybackListener
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
|
@ -224,6 +226,7 @@ class PlaybackViewModel
|
||||||
allowAudioStreamCopy = true,
|
allowAudioStreamCopy = true,
|
||||||
autoOpenLiveStream = true,
|
autoOpenLiveStream = true,
|
||||||
mediaSourceId = null,
|
mediaSourceId = null,
|
||||||
|
alwaysBurnInSubtitleWhenTranscoding = false,
|
||||||
),
|
),
|
||||||
).content
|
).content
|
||||||
val source = response.mediaSources.firstOrNull()
|
val source = response.mediaSources.firstOrNull()
|
||||||
|
|
@ -251,16 +254,19 @@ class PlaybackViewModel
|
||||||
val decision = StreamDecision(itemId, transcodeType, mediaUrl)
|
val decision = StreamDecision(itemId, transcodeType, mediaUrl)
|
||||||
Timber.v("Playback decision: $decision")
|
Timber.v("Playback decision: $decision")
|
||||||
|
|
||||||
|
val playback =
|
||||||
|
CurrentPlayback(
|
||||||
|
itemId,
|
||||||
|
audioIndex,
|
||||||
|
subtitleIndex,
|
||||||
|
source.id?.toUUIDOrNull(),
|
||||||
|
listOf(),
|
||||||
|
)
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
duration.value = source.runTimeTicks?.ticks
|
duration.value = source.runTimeTicks?.ticks
|
||||||
stream.value = decision
|
stream.value = decision
|
||||||
currentPlayback.value =
|
currentPlayback.value = playback
|
||||||
CurrentPlayback(
|
|
||||||
itemId,
|
|
||||||
audioIndex,
|
|
||||||
subtitleIndex,
|
|
||||||
source.id?.toUUIDOrNull(),
|
|
||||||
)
|
|
||||||
player.setMediaItem(
|
player.setMediaItem(
|
||||||
decision.mediaItem,
|
decision.mediaItem,
|
||||||
positionMs,
|
positionMs,
|
||||||
|
|
@ -277,6 +283,10 @@ class PlaybackViewModel
|
||||||
audioIndex,
|
audioIndex,
|
||||||
subtitleIndex,
|
subtitleIndex,
|
||||||
)
|
)
|
||||||
|
currentPlayback.value =
|
||||||
|
currentPlayback.value?.copy(
|
||||||
|
tracks = checkForSupport(tracks),
|
||||||
|
)
|
||||||
player.removeListener(this)
|
player.removeListener(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,6 +348,7 @@ data class CurrentPlayback(
|
||||||
val audioIndex: Int?,
|
val audioIndex: Int?,
|
||||||
val subtitleIndex: Int?,
|
val subtitleIndex: Int?,
|
||||||
val mediaSourceId: UUID?,
|
val mediaSourceId: UUID?,
|
||||||
|
val tracks: List<TrackSupport>,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val Format.idAsInt: Int?
|
private val Format.idAsInt: Int?
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ message PlaybackPreferences {
|
||||||
int64 skip_back_ms = 2;
|
int64 skip_back_ms = 2;
|
||||||
int64 controller_timeout_ms = 3;
|
int64 controller_timeout_ms = 3;
|
||||||
int32 seek_bar_steps = 4;
|
int32 seek_bar_steps = 4;
|
||||||
|
bool show_debug_info = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message HomePagePreferences{
|
message HomePagePreferences{
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,5 @@
|
||||||
<string name="genres">Genres</string>
|
<string name="genres">Genres</string>
|
||||||
<string name="play_theme_music">Play theme music</string>
|
<string name="play_theme_music">Play theme music</string>
|
||||||
<string name="license_info">License information</string>
|
<string name="license_info">License information</string>
|
||||||
|
<string name="playback_debug_info">Show playback debug info</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue