diff --git a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/PlayerView.kt b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/PlayerView.kt index d42440e81..3f446b8cb 100644 --- a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/PlayerView.kt +++ b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/PlayerView.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.zIndex +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.media3.common.Player import ch.srgssr.pillarbox.demo.shared.ui.settings.MetricsOverlayOptions import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerControls @@ -27,9 +28,10 @@ import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerError import ch.srgssr.pillarbox.demo.ui.player.controls.PlayerNoContent import ch.srgssr.pillarbox.demo.ui.player.controls.SkipButton import ch.srgssr.pillarbox.demo.ui.player.controls.rememberProgressTrackerState -import ch.srgssr.pillarbox.demo.ui.player.metrics.MetricsDebugView +import ch.srgssr.pillarbox.demo.ui.player.metrics.MetricsOverlay import ch.srgssr.pillarbox.demo.ui.theme.paddings import ch.srgssr.pillarbox.player.PillarboxExoPlayer +import ch.srgssr.pillarbox.player.currentPositionAsFlow import ch.srgssr.pillarbox.ui.ProgressTrackerState import ch.srgssr.pillarbox.ui.ScaleMode import ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerSubtitleView @@ -41,6 +43,8 @@ import ch.srgssr.pillarbox.ui.widget.ToggleableBox import ch.srgssr.pillarbox.ui.widget.keepScreenOn import ch.srgssr.pillarbox.ui.widget.player.PlayerSurface import ch.srgssr.pillarbox.ui.widget.rememberDelayedVisibilityState +import kotlinx.coroutines.flow.map +import kotlin.time.Duration.Companion.milliseconds /** * Simple player view @@ -124,13 +128,20 @@ fun PlayerView( } ExoPlayerSubtitleView(player = player) if (overlayEnabled && player is PillarboxExoPlayer) { - MetricsDebugView( - modifier = Modifier - .fillMaxSize() - .align(Alignment.TopStart), - overlayOptions = overlayOptions, - player = player, - ) + val currentMetricsFlow = remember(player) { + player.currentPositionAsFlow(updateInterval = 500.milliseconds).map { + player.getCurrentMetrics() + } + } + val currentMetrics by currentMetricsFlow.collectAsStateWithLifecycle(player.getCurrentMetrics()) + currentMetrics?.let { + MetricsOverlay( + modifier = Modifier + .fillMaxSize() + .align(Alignment.TopStart), + playbackMetrics = it, overlayOptions = overlayOptions + ) + } } } diff --git a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsDebugView.kt b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsOverlay.kt similarity index 85% rename from pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsDebugView.kt rename to pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsOverlay.kt index 6842336a6..857ed2d17 100644 --- a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsDebugView.kt +++ b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsOverlay.kt @@ -7,41 +7,25 @@ package ch.srgssr.pillarbox.demo.ui.player.metrics import androidx.compose.foundation.layout.Column import androidx.compose.foundation.text.BasicText import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.sp -import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.media3.common.Format import ch.srgssr.pillarbox.demo.shared.ui.settings.MetricsOverlayOptions -import ch.srgssr.pillarbox.player.PillarboxExoPlayer import ch.srgssr.pillarbox.player.analytics.metrics.PlaybackMetrics import ch.srgssr.pillarbox.player.utils.BitrateUtil.toByteRate /** - * Metrics debug view + * Display [playbackMetrics] as overlay. * - * @param player the [PillarboxExoPlayer] to debug. - * @param modifier The Modifier. - * @param overlayOptions [MetricsOverlayOptions]. + * @param playbackMetrics The [PlaybackMetrics] to display. + * @param overlayOptions The [MetricsOverlayOptions] the options. + * @param modifier The modifier to be applied to the layout. */ @Composable -fun MetricsDebugView( - player: PillarboxExoPlayer, - modifier: Modifier = Modifier, - overlayOptions: MetricsOverlayOptions = MetricsOverlayOptions() -) { - val viewmodel = rememberMetricsViewModel(player) - val currentMetrics by viewmodel.metricsFlow.collectAsStateWithLifecycle() - currentMetrics?.let { - OverlayMetrics(modifier = Modifier, playbackMetrics = it, overlayOptions = overlayOptions) - } -} - -@Composable -internal fun OverlayMetrics( +fun MetricsOverlay( playbackMetrics: PlaybackMetrics, overlayOptions: MetricsOverlayOptions, modifier: Modifier = Modifier, diff --git a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsViewModel.kt b/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsViewModel.kt deleted file mode 100644 index e1ad9f36c..000000000 --- a/pillarbox-demo/src/main/java/ch/srgssr/pillarbox/demo/ui/player/metrics/MetricsViewModel.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) SRG SSR. All rights reserved. - * License information is available from the LICENSE file. - */ -package ch.srgssr.pillarbox.demo.ui.player.metrics - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.Stable -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.media3.common.Player -import androidx.media3.exoplayer.analytics.AnalyticsListener -import ch.srgssr.pillarbox.player.PillarboxExoPlayer -import ch.srgssr.pillarbox.player.analytics.PillarboxAnalyticsListener -import ch.srgssr.pillarbox.player.currentPositionAsFlow -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch - -/** - * Remember metrics view model - * - * @param player The [PillarboxExoPlayer] to get metrics from. - * @param coroutineScope The [CoroutineScope] to listen current [player] position. - */ -@Composable -fun rememberMetricsViewModel( - player: PillarboxExoPlayer, - coroutineScope: CoroutineScope = rememberCoroutineScope() -): MetricsViewModel { - val metricsViewModel = remember(player) { - MetricsViewModel(coroutineScope = coroutineScope, player = player) - } - DisposableEffect(metricsViewModel) { - onDispose { - metricsViewModel.clear() - } - } - return metricsViewModel -} - -/** - * Metrics view model - * @param coroutineScope The [CoroutineScope] to listen current [player] position. - * @param player The [PillarboxExoPlayer] to get metrics from. - */ -@Stable -class MetricsViewModel internal constructor( - coroutineScope: CoroutineScope, - private val player: PillarboxExoPlayer -) { - private val playerComponent = PlayerComponent() - - /** - * Metrics flow - */ - val metricsFlow = MutableStateFlow(player.getCurrentMetrics()) - - init { - player.addAnalyticsListener(playerComponent) - coroutineScope.launch { - player.currentPositionAsFlow().collectLatest { - metricsFlow.value = player.getCurrentMetrics() - } - } - } - - /** - * Clear - */ - internal fun clear() { - player.removeAnalyticsListener(playerComponent) - } - - private inner class PlayerComponent : PillarboxAnalyticsListener { - - override fun onEvents(p: Player, events: AnalyticsListener.Events) { - metricsFlow.value = player.getCurrentMetrics() - } - } -}