diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt index 07a9fba7..773bdbee 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderGrid.kt @@ -239,7 +239,7 @@ fun GridTitle( modifier: Modifier = Modifier, ) = Text( text = title, - style = MaterialTheme.typography.displayMedium, + style = MaterialTheme.typography.displaySmall, color = MaterialTheme.colorScheme.onBackground, textAlign = TextAlign.Center, maxLines = 1, diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderView.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderView.kt index 018fc7e4..ffb9cf92 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderView.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/CollectionFolderView.kt @@ -653,6 +653,7 @@ fun CollectionFolderView( }, ) { val state by viewModel.state.collectAsState() + var position by rememberInt(viewModel.position) var showContextMenu by remember { mutableStateOf(null) } var overviewDialog by remember { mutableStateOf(null) } @@ -692,9 +693,15 @@ fun CollectionFolderView( val gridActions = remember(actions) { GridClickActions( - onClickItem = actions.onClickItem, - onLongClickItem = - actions.onLongClickItem ?: { position, item -> + onClickItem = { index, item -> + position = index + actions.onClickItem.invoke(index, item) + }, + onLongClickItem = { index, item -> + position = index + if (actions.onLongClickItem != null) { + actions.onLongClickItem.invoke(index, item) + } else { showContextMenu = ContextMenu.ForBaseItem( fromLongClick = true, @@ -707,7 +714,8 @@ fun CollectionFolderView( canRemoveNextUp = false, actions = contextActions, ) - }, + } + }, onClickPlayAll = actions.onClickPlayAll ?: { shuffle -> itemId.toUUIDOrNull()?.let { @@ -785,7 +793,6 @@ fun CollectionFolderView( var showHeader by rememberSaveable { mutableStateOf(true) } val gridFocusRequester = remember { FocusRequester() } val pager = remember(state.items) { state.items.successValue } - var position by rememberInt(viewModel.position) val focusedItem = pager?.getOrNull(position) if (state.viewOptions.showBackdrop) { diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/components/ItemGrid.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/components/ItemGrid.kt index 8c2b95da..65329026 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/components/ItemGrid.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/components/ItemGrid.kt @@ -2,7 +2,6 @@ package com.github.damontecres.wholphin.ui.components import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState @@ -10,13 +9,10 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.tv.material3.MaterialTheme -import androidx.tv.material3.Text import com.github.damontecres.wholphin.data.model.BaseItem import com.github.damontecres.wholphin.services.NavigationManager import com.github.damontecres.wholphin.ui.cards.GridCard @@ -120,13 +116,8 @@ fun ItemGrid( focusRequester.tryRequestFocus() } Column(modifier = modifier) { - Text( - text = destination.title.getString(), - style = MaterialTheme.typography.displayMedium, - color = MaterialTheme.colorScheme.onBackground, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth(), - ) + GridTitle(destination.title.getString()) + CardGrid( pager = st.data, onClickItem = { index: Int, item: BaseItem -> diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/NowPlayingButtons.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/NowPlayingButtons.kt index 1d976ede..db5bbf4c 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/NowPlayingButtons.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/NowPlayingButtons.kt @@ -44,6 +44,7 @@ import com.github.damontecres.wholphin.ui.playback.ControllerViewState import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackAction import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButton import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButtons +import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackFaButton import com.github.damontecres.wholphin.ui.playback.overlay.buttonSpacing import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource import com.github.damontecres.wholphin.ui.theme.WholphinTheme @@ -74,7 +75,7 @@ fun NowPlayingButtons( modifier = Modifier.align(Alignment.CenterStart), ) { PlaybackButton( - iconRes = R.drawable.baseline_more_vert_96, + iconRes = R.drawable.vector_settings, onClick = { onControllerInteraction.invoke() onClickMore.invoke() diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/SongListDisplay.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/SongListDisplay.kt index 82846282..4e5fa329 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/SongListDisplay.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/detail/music/SongListDisplay.kt @@ -3,6 +3,7 @@ package com.github.damontecres.wholphin.ui.detail.music import androidx.compose.foundation.background import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsFocusedAsState +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column @@ -21,6 +22,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.tv.material3.DenseListItem import androidx.tv.material3.Icon import androidx.tv.material3.ListItem import androidx.tv.material3.ListItemDefaults @@ -118,38 +120,27 @@ fun SongListItem( ) } - if (showArtist) { - // TODO use dense? - ListItem( - selected = isPlaying, - onClick = onClick, - onLongClick = onLongClick, - interactionSource = interactionSource, - leadingContent = leadingContent, - headlineContent = headlineContent, - supportingContent = { - Text( - text = artist ?: "", - ) + DenseListItem( + selected = isPlaying, + onClick = onClick, + onLongClick = onLongClick, + interactionSource = interactionSource, + leadingContent = leadingContent, + headlineContent = headlineContent, + supportingContent = + if (showArtist && artist != null) { + { + Text( + text = artist, + ) + } + } else { + null }, - trailingContent = trailingContent, - scale = ListItemDefaults.scale(1f, 1f, .95f), - modifier = Modifier.weight(1f), - ) - } else { - ListItem( - selected = isPlaying, - onClick = onClick, - onLongClick = onLongClick, - interactionSource = interactionSource, - leadingContent = leadingContent, - headlineContent = headlineContent, - supportingContent = null, - trailingContent = trailingContent, - scale = ListItemDefaults.scale(1f, 1f, .95f), - modifier = Modifier.weight(1f), - ) - } + trailingContent = trailingContent, + scale = ListItemDefaults.scale(1f, 1f, .95f), + modifier = Modifier.weight(1f), + ) if (showMoreButton) { Button( onClick = onClickMore, @@ -198,7 +189,7 @@ fun MusicQueueMarker( @Composable fun SongListItemPreview() { WholphinTheme { - Column { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { SongListItem( title = "Song title", artist = "Artists", @@ -232,6 +223,17 @@ fun SongListItemPreview() { showArtist = true, isPlaying = true, ) + SongListItem( + title = "Song title", + artist = null, + indexNumber = 2, + runtime = 2.minutes + 30.seconds, + onClick = {}, + onLongClick = { }, + modifier = Modifier, + showArtist = true, + isPlaying = true, + ) } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt index 020a1eff..d25375a2 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackPage.kt @@ -48,7 +48,6 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.key.onKeyEvent import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.IntSize @@ -85,7 +84,6 @@ import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackOverlay import com.github.damontecres.wholphin.ui.playback.overlay.SkipIndicator import com.github.damontecres.wholphin.ui.playback.overlay.SkipSegmentButton import com.github.damontecres.wholphin.ui.playback.overlay.rememberSeekBarState -import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.applyToMpv import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.calculateEdgeSize import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.toSubtitleStyle import com.github.damontecres.wholphin.ui.seasonEpisode @@ -95,7 +93,6 @@ import com.github.damontecres.wholphin.util.LoadingState import com.github.damontecres.wholphin.util.Media3SubtitleOverride import com.github.damontecres.wholphin.util.mpv.MpvPlayer import io.github.peerless2012.ass.media.widget.AssSubtitleView -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import timber.log.Timber @@ -163,24 +160,12 @@ fun PlaybackPageContent( val prefs = preferences.appPreferences.playbackPreferences val scope = rememberCoroutineScope() - val configuration = LocalConfiguration.current val density = LocalDensity.current val userDto by viewModel.currentUserDto.collectAsState() var showDebugInfo by remember { mutableStateOf(prefs.showDebugInfo) } var playbackDialog by remember { mutableStateOf(null) } - LaunchedEffect(player) { - if (playerBackend == PlayerBackend.MPV) { - scope.launch(Dispatchers.IO + ExceptionHandler()) { - // MPV can't play HDR, so always use regular settings - preferences.appPreferences.interfacePreferences.subtitlesPreferences.applyToMpv( - configuration, - density, - ) - } - } - } var contentScale by remember(playerBackend) { mutableStateOf( diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt index 3667e03e..631aacc4 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModel.kt @@ -5,6 +5,7 @@ import android.media.MediaCodecList import android.os.Build import android.widget.Toast import androidx.annotation.OptIn +import androidx.compose.ui.unit.Density import androidx.core.net.toUri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -57,6 +58,7 @@ import com.github.damontecres.wholphin.ui.launchDefault import com.github.damontecres.wholphin.ui.launchIO import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.onMain +import com.github.damontecres.wholphin.ui.preferences.subtitle.SubtitleSettings.applyToMpv import com.github.damontecres.wholphin.ui.seekBack import com.github.damontecres.wholphin.ui.seekForward import com.github.damontecres.wholphin.ui.showToast @@ -66,6 +68,7 @@ import com.github.damontecres.wholphin.util.LoadingState import com.github.damontecres.wholphin.util.PlaybackItemState import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener import com.github.damontecres.wholphin.util.checkForSupport +import com.github.damontecres.wholphin.util.mpv.MpvPlayer import com.github.damontecres.wholphin.util.mpv.mpvDeviceProfile import com.github.damontecres.wholphin.util.profile.Codec import com.github.damontecres.wholphin.util.subtitleMimeTypes @@ -1165,10 +1168,10 @@ class PlaybackViewModel private fun listenForTranscodeReason(): Job = viewModelScope.launchIO { state.map { it.currentPlayback }.collectLatest { - if (it != null) { + if (it != null && it.playMethod == PlayMethod.TRANSCODE && it.transcodeInfo == null) { try { var transcodeInfo = it.transcodeInfo - while (isActive && it.playMethod == PlayMethod.TRANSCODE && transcodeInfo == null) { + while (isActive && transcodeInfo == null) { delay(2.seconds) transcodeInfo = api.sessionApi @@ -1526,6 +1529,22 @@ class PlaybackViewModel screensaverService.keepScreenOn(isPlaying) } + override fun onAvailableCommandsChanged(availableCommands: Player.Commands) { + val player = this@PlaybackViewModel.player + if (availableCommands.contains(Player.COMMAND_PREPARE) && player is MpvPlayer) { + // MpvPlayer is initialized, so configure subtitles + Timber.i("Applying subtitle config to MPV") + viewModelScope.launchDefault { + val configuration = context.resources.configuration + val density = Density(context.resources.displayMetrics.density) + preferences.appPreferences.interfacePreferences.subtitlesPreferences.applyToMpv( + configuration, + density, + ) + } + } + } + override fun onBandwidthEstimate( eventTime: AnalyticsListener.EventTime, totalLoadTimeMs: Int, diff --git a/app/src/main/java/com/github/damontecres/wholphin/util/mpv/MpvPlayer.kt b/app/src/main/java/com/github/damontecres/wholphin/util/mpv/MpvPlayer.kt index f0792aa3..1766de82 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/util/mpv/MpvPlayer.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/util/mpv/MpvPlayer.kt @@ -167,6 +167,11 @@ class MpvPlayer( // COMMAND_GET_TEXT, COMMAND_RELEASE, ).build() + notifyListeners(EVENT_AVAILABLE_COMMANDS_CHANGED) { + onAvailableCommandsChanged( + availableCommands, + ) + } trackSelector.init(this, DefaultBandwidthMeter.getSingletonInstance(context)) }