From 533f60748061414efc571da303c099a0886674dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Muller?= Date: Mon, 11 Nov 2024 14:33:45 +0100 Subject: [PATCH] Update documentation in `pillarbox-ui` (#787) --- ...PillarboxAndroidLibraryPublishingPlugin.kt | 5 + pillarbox-ui/Module.md | 13 -- pillarbox-ui/docs/README.md | 180 ++++++++++-------- .../pillarbox/ui/ProgressTrackerState.kt | 9 +- .../java/ch/srgssr/pillarbox/ui/ScaleMode.kt | 14 +- .../ui/SimpleProgressTrackerState.kt | 6 +- .../ui/SmoothProgressTrackerState.kt | 6 +- .../ui/exoplayer/ExoPlayerControlView.kt | 6 +- .../pillarbox/ui/exoplayer/ExoPlayerView.kt | 38 ++-- .../ui/exoplayer/ExoplayerSubtitleView.kt | 24 ++- .../ui/exoplayer/SubtitleTextSize.kt | 21 +- .../ui/extension/ComposablePlayer.kt | 95 ++++++--- .../ui/widget/DelayedVisibilityState.kt | 81 ++++---- .../pillarbox/ui/widget/KeepScreenOn.kt | 2 +- .../pillarbox/ui/widget/ToggleableBox.kt | 20 +- .../ui/widget/player/PlayerSurface.kt | 36 ++-- 16 files changed, 328 insertions(+), 228 deletions(-) delete mode 100644 pillarbox-ui/Module.md diff --git a/build-logic/plugins/src/main/java/ch/srgssr/pillarbox/gradle/PillarboxAndroidLibraryPublishingPlugin.kt b/build-logic/plugins/src/main/java/ch/srgssr/pillarbox/gradle/PillarboxAndroidLibraryPublishingPlugin.kt index 72d7c627f..ed530ee91 100644 --- a/build-logic/plugins/src/main/java/ch/srgssr/pillarbox/gradle/PillarboxAndroidLibraryPublishingPlugin.kt +++ b/build-logic/plugins/src/main/java/ch/srgssr/pillarbox/gradle/PillarboxAndroidLibraryPublishingPlugin.kt @@ -94,6 +94,11 @@ class PillarboxAndroidLibraryPublishingPlugin : Plugin { includes.from("docs/README.md") } + externalDocumentationLinks.register("kotlinx.coroutines") { + url.set(URI("https://kotlinlang.org/api/kotlinx.coroutines")) + packageListUrl.set(URI("https://kotlinlang.org/api/kotlinx.coroutines/package-list")) + } + externalDocumentationLinks.register("kotlinx.serialization") { url.set(URI("https://kotlinlang.org/api/kotlinx.serialization")) packageListUrl.set(URI("https://kotlinlang.org/api/kotlinx.serialization/package-list")) diff --git a/pillarbox-ui/Module.md b/pillarbox-ui/Module.md deleted file mode 100644 index befd9fb82..000000000 --- a/pillarbox-ui/Module.md +++ /dev/null @@ -1,13 +0,0 @@ -# Module pillarbox-ui - -Provides UI Compose components: - -- [`PlayerSurface`](ch.srgssr.pillarbox.ui.widget.player.PlayerSurface). -- Compose wrapper for ExoPlayer views. -- [`ProgressTracker`](ch.srgssr.pillarbox.ui.ProgressTrackerState) to connect the player to a progress bar or slider. - -To use this module, add the following dependency to your project's `build.gradle`/`build.gradle.kts` file: - -```kotlin -implementation("ch.srgssr.pillarbox:pillarbox-ui:") -``` diff --git a/pillarbox-ui/docs/README.md b/pillarbox-ui/docs/README.md index e427d908b..68117d7e9 100644 --- a/pillarbox-ui/docs/README.md +++ b/pillarbox-ui/docs/README.md @@ -1,126 +1,146 @@ -[![Pillarbox logo](https://github.com/SRGSSR/pillarbox-apple/blob/main/docs/README-images/logo.jpg)](https://github.com/SRGSSR/pillarbox-android) -[![Last release](https://img.shields.io/github/v/release/SRGSSR/pillarbox-android?label=Release)](https://github.com/SRGSSR/pillarbox-android/releases) -[![Android min SDK](https://img.shields.io/badge/Android-21%2B-34A853)](https://github.com/SRGSSR/pillarbox-android) -[![License](https://img.shields.io/github/license/SRGSSR/pillarbox-android?label=License)](https://github.com/SRGSSR/pillarbox-android/blob/main/LICENSE) +# Module pillarbox-ui -# Pillarbox UI module +Provides UI Compose components and helpers. -Provides UI Compose components: +This includes: -- PlayerSurface -- Exoplayer views compose wrappers -- ProgressTrackers to connect the player to a progress bar or slider. +- [PlayerSurface][ch.srgssr.pillarbox.ui.widget.player.PlayerSurface], to display a player on a surface, texture, or spherical surface. +- Compose wrapper for ExoPlayer `View`s. +- [ProgressTracker][ch.srgssr.pillarbox.ui.ProgressTrackerState] to connect the player to a progress bar or slider. ## Integration -```gradle -implementation("ch.srgssr.pillarbox:pillarbox-ui:$LATEST_RELEASE_VERSION") -``` +To use this module, add the following dependency to your project's `build.gradle`/`build.gradle.kts` file: -More information can be found on the [top level README](../docs/README.md) +```kotlin +implementation("ch.srgssr.pillarbox:pillarbox-ui:") +``` ## Getting started -### Drawing a simple video surface +### Display a `Player` ```kotlin @Composable -fun SimplePlayer(player: Player) { - Box(modifier = Modifier) { - PlayerSurface(player = player) - } +fun SimplePlayer( + player: Player, + modifier: Modifier = Modifier, +) { + PlayerSurface( + player = player, + modifier = modifier, + ) } ``` -### Create a simple player with controls and subtitles +### Create a `Player` with controls and subtitles -In this example, we are drawing controls and subtitles on top of the player surface. To add subtitles use `ExoPlayerSubtitleView` and for controls -you can use the Exoplayer version, `ExoPlayerControlView`. +In this example, we are drawing controls and subtitles on top of the [Player][androidx.media3.common.Player]. To add controls, you can use +[ExoPlayerControlView][ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerControlView]. And for subtitles, you can use +[ExoPlayerSubtitleView][ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerSubtitleView]. ```kotlin @Composable -fun MyPlayer(player: Player) { - val defaultAspectRatio = 1.0f +fun MyPlayer( + player: Player, + modifier: Modifier = Modifier, +) { Box( - modifier = Modifier + modifier = modifier .fillMaxWidth() .wrapContentHeight() .background(color = Color.Black), - contentAlignment = Alignment.Center + contentAlignment = Alignment.Center, ) { PlayerSurface( - modifier = Modifier, player = player, - scaleMode = ScaleMode.Fit, - defaultAspectRatio = defaultAspectRatio, - surfaceType = SurfaceType.Surface, // By default + defaultAspectRatio = 1f, + ) + + ExoPlayerControlView( + player = player, + modifier = Modifier.matchParentSize(), + ) + + ExoPlayerSubtitleView( + player = player, + modifier = Modifier.matchParentSize(), ) - ExoPlayerControlView(modifier = Modifier.matchParentSize(), player = player) - ExoPlayerSubtitleView(modifier = Modifier.matchParentSize(), player = player) } } ``` -The `defaultAspectRatio` is used while the video is loading or if the player doesn't play a video. - -In this example we use `ScaleMode.Fit` to fit the content to the parent container but there are more scales modes : - -- `ScaleMode.Fit` : Fit player content to the parent container and keep aspect ratio. -- `ScaleMode.Fill` : Fill player content to the parent container. -- `ScaleMode.Crop` : Crop player content inside the parent container and keep aspect ratio. Content outside the parent container will be clipped. +The `defaultAspectRatio` is used while the video is loading or if the [Player][androidx.media3.common.Player] doesn't play a video. -### Surface types +### Scale mode -`PlayerSurface` allows choosing between multiple types of surface: +You can customize how the [Player][androidx.media3.common.Player] scales in the [PlayerSurface][ch.srgssr.pillarbox.ui.widget.player.PlayerSurface], +by setting the `scaleMode` argument. -- `SurfaceType.Surface` (default): the player is linked to a `SurfaceView`. This option is the most optimized version, and supports playing any - content including DRM protected content. -- `SurfaceType.Texture`: the player is linked to a `TextureView`. This option may be interesting when dealing with animation, and the `Surface` - option doesn't work as expected. -- `SurfaceType.Spherical`: the player is linked to a `SphericalGLSurfaceView`. This surface type is suited when playing 360° video content. +```kotlin +PlayerSurface( + player = player, + scaleMode = ScaleMode.Fit, +) +``` -> [!NOTE] -> The last two surface types are not suited when playing DRM protected content. +- [ScaleMode.Fit][ch.srgssr.pillarbox.ui.ScaleMode.Fit] (default): resizes the [Player][androidx.media3.common.Player] to fit within its parent while + maintaining its aspect ratio. +- [ScaleMode.Fill][ch.srgssr.pillarbox.ui.ScaleMode.Fill]: stretches the [Player][androidx.media3.common.Player] to fill its parent, ignoring the + defined aspect ratio. +- [ScaleMode.Crop][ch.srgssr.pillarbox.ui.ScaleMode.Crop]: trims the [Player][androidx.media3.common.Player] to fill its parent while maintaining its + aspect ratio. -### Listen to player states +### Surface type -To listen to player states _Pillarbox_ provides some extensions `PlayerCallbackFlow.kt` and some Compose extensions `ComposablePlayer.kt`. +[PlayerSurface][ch.srgssr.pillarbox.ui.widget.player.PlayerSurface] lets you set the type of surface used to render its content, using its +`surfaceType` argument. ```kotlin +PlayerSurface( + player = player, + surfaceType = SurfaceType.Surface, +) +``` -@Composable -fun MyPlayerView(player: Player) { - val defaultAspectRatio = 1.0f - Box( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .background(color = Color.Black), - contentAlignment = Alignment.Center - ) { - PlayerSurface( - modifier = Modifier, - player = player, - scaleMode = ScaleMode.Fit, - defaultAspectRatio = defaultAspectRatio - ) - // Displays current position periodically - val currentPosition = player.currentPositionAsState() - Text(text = "Position = $currentPosition ms", modifier = Modifier.align(Alignment.TopStart)) +- [SurfaceType.Surface][ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Surface] (default): the [Player][androidx.media3.common.Player] is attached + to a [SurfaceView][android.view.SurfaceView]. This is the most optimized option, and supports playing any content including DRM protected content. +- [SurfaceType.Texture][ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Texture]: the [Player][androidx.media3.common.Player] is attached to + a [TextureView][android.view.TextureView]. This option may be interesting when dealing with animation, and + the [SurfaceType.Surface][ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Surface] option doesn't work as expected. This does not work with DRM + content. +- [SurfaceType.Spherical][ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Spherical]: the [Player][androidx.media3.common.Player] is attached to + a [SphericalGLSurfaceView][androidx.media3.exoplayer.video.spherical.SphericalGLSurfaceView]. This option is suited when playing 360° video + content. This does not work with DRM content. - val duration = player.durationAsState() - Text(text = "Duration = $duration ms", modifier = Modifier.align(Alignment.TopEnd)) +### Observe `Player` states - val isPlaying = player.isPlayingAsState() - Button(modifier = Modififer.align(Alignement.Center), onClick = { togglePlayingBack() }) { - Text(text = if (isPlaying) "Pause" else "Play") - } - } +The [ch.srgssr.pillarbox.ui.extension][ch.srgssr.pillarbox.ui.extension] package provides a collection of extensions to observe a +[Player][androidx.media3.common.Player]'s state through Compose's [State][androidx.compose.runtime.State] instances. + +```kotlin +@Composable +fun MyPlayer(player: Player) { + val currentPosition: Long by player.currentPositionAsState() + val duration: Long by player.durationAsState() + val isPlaying: Boolean by player.isPlayingAsState() } ``` -## Compose - -To learn more about compose, you can read the [Official documentation](https://developer.android.com/jetpack/compose) - - +[android.view.SurfaceView]: https://developer.android.com/reference/android/view/SurfaceView +[android.view.TextureView]: https://developer.android.com/reference/android/view/TextureView +[androidx.compose.runtime.State]: https://developer.android.com/reference/kotlin/androidx/compose/runtime/State.html +[androidx.media3.common.Player]: https://developer.android.com/reference/androidx/media3/common/Player +[androidx.media3.exoplayer.video.spherical.SphericalGLSurfaceView]: https://developer.android.com/reference/androidx/media3/exoplayer/video/spherical/SphericalGLSurfaceView +[ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerControlView]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.exoplayer/-exo-player-control-view.html +[ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerSubtitleView]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.exoplayer/-exo-player-subtitle-view.html +[ch.srgssr.pillarbox.ui.extension]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.extension/index.html +[ch.srgssr.pillarbox.ui.widget.player.PlayerSurface]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.widget.player/-player-surface.html +[ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Spherical]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.widget.player/-surface-type/-spherical/index.html +[ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Surface]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.widget.player/-surface-type/-surface/index.html +[ch.srgssr.pillarbox.ui.widget.player.SurfaceType.Texture]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui.widget.player/-surface-type/-texture/index.html +[ch.srgssr.pillarbox.ui.ProgressTrackerState]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui/-progress-tracker-state/index.html +[ch.srgssr.pillarbox.ui.ScaleMode]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui/-scale-mode/index.html +[ch.srgssr.pillarbox.ui.ScaleMode.Crop]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui/-scale-mode/-crop/index.html +[ch.srgssr.pillarbox.ui.ScaleMode.Fill]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui/-scale-mode/-fill/index.html +[ch.srgssr.pillarbox.ui.ScaleMode.Fit]: https://android.pillarbox.ch/api/pillarbox-ui/ch.srgssr.pillarbox.ui/-scale-mode/-fit/index.html diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ProgressTrackerState.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ProgressTrackerState.kt index a4373b44a..1c28d9a8c 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ProgressTrackerState.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ProgressTrackerState.kt @@ -9,23 +9,24 @@ import kotlinx.coroutines.flow.StateFlow import kotlin.time.Duration /** - * Interface used to subscribe to and update the [Player] progression. + * This interface allows subscribing to the current [Player] progress and provides callbacks for manual progress adjustments. */ interface ProgressTrackerState { /** - * Emits the current progress, which can be either the value being manually set, or the actual [Player] progress. + * A [StateFlow] emitting the current progress, which can either be the progress manually set, or the actual progress of the underlying [Player]. */ val progress: StateFlow /** * Callback to invoke when the progress is being manually changed. * - * @param progress The new progress of the media being played. It must be between 0ms and [Player.getDuration]. + * @param progress The new progress of the media being played. It must be between 0ms and the total duration of the media, as returned by + * [Player.getDuration]. */ fun onChanged(progress: Duration) /** - * Callback to invoke when the progress is no longer being changed. + * Callback to invoke when the progress operation has finished. */ fun onFinished() } diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ScaleMode.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ScaleMode.kt index a2f99480c..87258097f 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ScaleMode.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/ScaleMode.kt @@ -4,22 +4,28 @@ */ package ch.srgssr.pillarbox.ui +import androidx.media3.common.Player + /** - * Scale mode + * Represents the scaling mode for the [Player] content within its parent container. */ enum class ScaleMode { /** - * Fit player content to the parent container and keep aspect ratio. + * Resizes the [Player][androidx.media3.common.Player] content to fit within the parent while maintaining its aspect ratio. This ensures the + * entire content is visible, but may result in black bars (letterboxing or pillarboxing) on the sides or top/bottom if the aspect ratios of the + * media and container do not match. */ Fit, /** - * Fill player content to the parent container. + * Stretches the [Player][androidx.media3.common.Player] to fill its parent, ignoring the defined aspect ratio. This may cause the content to be + * distorted horizontally or vertically to match the parent's dimensions. */ Fill, /** - * Crop player content inside the parent container and keep aspect ratio. + * Trims the [Player][androidx.media3.common.Player] to fill its parent while maintaining its aspect ratio. Any content that extends beyond the + * bounds of the container will be clipped. */ Crop, } diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SimpleProgressTrackerState.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SimpleProgressTrackerState.kt index d91fd2637..e08351cc3 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SimpleProgressTrackerState.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SimpleProgressTrackerState.kt @@ -18,10 +18,10 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds /** - * [Player] progress tracker that only updated the player's actual progress when [onFinished] is called. + * A [ProgressTrackerState] implementation that updates the [Player] progress only when [onFinished] is called. * - * @param player The [Player] whose current position must be tracked. - * @param coroutineScope + * @param player The [Player] whose progress needs to be tracked. + * @param coroutineScope The [CoroutineScope] used for managing [StateFlow]s. */ class SimpleProgressTrackerState( private val player: Player, diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SmoothProgressTrackerState.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SmoothProgressTrackerState.kt index c0bcbf467..c30c031cb 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SmoothProgressTrackerState.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/SmoothProgressTrackerState.kt @@ -13,10 +13,10 @@ import kotlinx.coroutines.flow.StateFlow import kotlin.time.Duration /** - * [Player] progress tracker that updates the player's actual progress everytime that [onChanged] is called. + * A [ProgressTrackerState] implementation that updates the [Player] progress every time [onChanged] is called. * - * @param player The [Player] whose current position must be tracked. - * @param coroutineScope + * @param player The [Player] whose progress needs to be tracked. + * @param coroutineScope The [CoroutineScope] used for managing [StateFlow]s. */ class SmoothProgressTrackerState( private val player: PillarboxExoPlayer, diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerControlView.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerControlView.kt index ba2d6227f..89967e300 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerControlView.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerControlView.kt @@ -12,10 +12,10 @@ import androidx.media3.common.Player import androidx.media3.ui.PlayerControlView /** - * Composable basic version of [PlayerControlView] from Media3 (Exoplayer) + * A Composable function that displays an ExoPlayer [PlayerControlView]. * - * @param player The player to bind to the controls. - * @param modifier The modifier to be applied to the layout. + * @param player The [Player] instance to be controlled. + * @param modifier The [Modifier] to apply to this layout. */ @Composable fun ExoPlayerControlView( diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerView.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerView.kt index c083f786d..96aa3bb10 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerView.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoPlayerView.kt @@ -20,20 +20,32 @@ import androidx.media3.ui.PlayerView import androidx.media3.ui.PlayerView.ShowBuffering /** - * Composable PlayerView provided by Media3 library + * A Composable function that displays an ExoPlayer [PlayerView]. * - * @param player The player to attach to the [PlayerView] - * @param modifier The modifier to be applied to the layout. - * @param useController true to display controls - * @param controllerAutoShow [PlayerView.setControllerAutoShow] - * @param showNextButton [PlayerView.setShowNextButton] - * @param showPreviousButton [PlayerView.setShowPreviousButton] - * @param showBuffering [PlayerView.setShowBuffering] - * @param resizeMode The resize mode for [PlayerView] - * @param errorMessageProvider The errorMessageProvider - * @param fullScreenListener [PlayerView.setFullscreenButtonClickListener] - * @param controllerVisibilityListener [PlayerView.setControllerVisibilityListener] - * @param shutterBackgroundColor [PlayerView.setShutterBackgroundColor] + * @param player The [Player] instance to be attached to the [PlayerView]. + * @param modifier The [Modifier] to apply to this layout. + * @param useController Whether to display playback controls. + * @param controllerAutoShow Whether the controls should be shown automatically when the playback starts, pauses, ends or fails. + * @param showNextButton Whether to display the "next" button in the controller. + * @param showPreviousButton Whether to display the "previous" button in the controller. + * @param showBuffering Specifies when to display the buffering indicator. + * @param resizeMode Specifies how the video content should be resized to fit the [PlayerView]. + * @param errorMessageProvider An optional [ErrorMessageProvider] to customize error messages displayed during playback failures. + * @param fullScreenListener An optional [PlayerView.FullscreenButtonClickListener] to handle clicks on the fullscreen button. + * @param controllerVisibilityListener An optional [PlayerView.ControllerVisibilityListener] to receive callbacks when the controller's visibility + * changes. + * @param shutterBackgroundColor The color of the shutter (background) when the video is not playing. + * + * @see PlayerView.setUseController + * @see PlayerView.setControllerAutoShow + * @see PlayerView.setShowNextButton + * @see PlayerView.setShowPreviousButton + * @see PlayerView.setShowBuffering + * @see PlayerView.setResizeMode + * @see PlayerView.setErrorMessageProvider + * @see PlayerView.setFullscreenButtonClickListener + * @see PlayerView.setControllerVisibilityListener + * @see PlayerView.setShutterBackgroundColor */ @Suppress("DEPRECATION") @Composable diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoplayerSubtitleView.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoplayerSubtitleView.kt index 734c35199..1b7fb1637 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoplayerSubtitleView.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/ExoplayerSubtitleView.kt @@ -25,12 +25,13 @@ import androidx.media3.ui.SubtitleView import com.google.common.collect.ImmutableList /** - * Composable basic version of [ExoPlayerSubtitleView] from Media3 (Exoplayer) that listen to Player Cues + * A Composable function that displays an ExoPlayer [SubtitleView]. + * It observes the active cues from the provided [player] and displays them in a [SubtitleView]. * - * @param player The Player to get Cues - * @param modifier The modifier to be applied to the layout. - * @param captionStyle Caption style of the subtitle texts. It will override any user-preferred style. - * @param subtitleTextSize Text size of the subtitle texts. It will override any user-preferred size. + * @param player The [Player] instance to retrieve subtitle cues from. + * @param modifier The [Modifier] to apply to this layout. + * @param captionStyle Optional [CaptionStyleCompat] to override the user's preferred caption style. + * @param subtitleTextSize Optional [SubtitleTextSize] to override the user's preferred subtitle text size. */ @Composable fun ExoPlayerSubtitleView( @@ -44,11 +45,14 @@ fun ExoPlayerSubtitleView( } /** - * Composable basic version of [ExoPlayerSubtitleView] from Media3 (Exoplayer) - * @param modifier The modifier to be applied to the layout. - * @param cues The cues to displays [Player.getCurrentCues] - * @param captionStyle Caption style of the subtitle texts. It will override any user-preferred style. - * @param subtitleTextSize Text size of the subtitle texts. It will override any user-preferred size. + * A Composable function that displays an ExoPlayer [SubtitleView]. + * + * @param modifier The [Modifier] to apply to this layout. + * @param cues The list of cues to be displayed. + * @param captionStyle Optional [CaptionStyleCompat] to override the user's preferred caption style. + * @param subtitleTextSize Optional [SubtitleTextSize] to override the user's preferred subtitle text size. + * + * @see Player.getCurrentCues To get the current cues from the [Player]. */ @Composable fun ExoPlayerSubtitleView( diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/SubtitleTextSize.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/SubtitleTextSize.kt index c8d1dbf05..587edc0da 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/SubtitleTextSize.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/exoplayer/SubtitleTextSize.kt @@ -4,19 +4,24 @@ */ package ch.srgssr.pillarbox.ui.exoplayer +import android.view.View +import android.view.accessibility.CaptioningManager import androidx.annotation.Dimension /** - * Subtitle text size + * Represents the text size for subtitles. * - * It will override the caption font scale defined by the user in the CaptionManager. + * This interface provides options for defining the subtitle text size, allowing for either a fractional size relative to the [View]'s height or a + * fixed size with a specific unit. + * + * It overrides the caption font scale set by the user in the [CaptioningManager]. */ sealed interface SubtitleTextSize { /** - * Sets the text size to be a fraction of the view's remaining height after its top and bottom padding have been subtracted or not. + * Represents a text size calculated as a fraction of the [View]'s height, optionally ignoring the [View]'s vertical padding. * - * @property fractionOfHeight A fraction between 0 and 1. - * @property ignorePadding ignore padding during height computations. + * @property fractionOfHeight The fraction of the [View]'s height that should be used to calculate the text size, between 0 and 1. + * @property ignorePadding Whether to subtract the [View]'s vertical padding from its height before calculating the text size. */ data class Fractional( val fractionOfHeight: Float, @@ -24,10 +29,10 @@ sealed interface SubtitleTextSize { ) : SubtitleTextSize /** - * Specify a fixed size caption text. + * Represents a fixed size for caption text. * - * @property unit Unit of the size [Dimension] - * @property size The size of the text in the unit dimension. + * @property unit The unit of the text size. This should be one of the [Dimension] constants. + * @property size The size of the text in the specified unit. */ data class Fixed(@Dimension val unit: Int, val size: Float) : SubtitleTextSize } diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/extension/ComposablePlayer.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/extension/ComposablePlayer.kt index 5e36f2687..4eb0370c6 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/extension/ComposablePlayer.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/extension/ComposablePlayer.kt @@ -52,14 +52,11 @@ import ch.srgssr.pillarbox.player.shuffleModeEnabledAsFlow import ch.srgssr.pillarbox.player.videoSizeAsFlow import kotlinx.coroutines.flow.map import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds /** - * Composable helper function to facilitate compose integration - */ - -/** - * Is playing [Player.isPlaying] + * Observe the [Player.isPlaying] property as a [State]. + * + * @return A [State] that represents whether the [Player] is currently playing. */ @Composable fun Player.isPlayingAsState(): State { @@ -70,7 +67,9 @@ fun Player.isPlayingAsState(): State { } /** - * Play when ready as state [Player.getPlayWhenReady] + * Observe the [Player.getPlayWhenReady] property as a [State]. + * + * @return A [State] that represents the current 'play when ready' value of the [Player]. */ @Composable fun Player.playWhenReadyAsState(): State { @@ -81,7 +80,9 @@ fun Player.playWhenReadyAsState(): State { } /** - * Playback state [Player.getPlaybackState] + * Observe the [Player.getPlaybackState] property as a [State]. + * + * @return A [State] that presents the current playback state of the [Player]. */ @Composable fun Player.playbackStateAsState(): IntState { @@ -92,7 +93,9 @@ fun Player.playbackStateAsState(): IntState { } /** - * Current position [Player.getCurrentPosition] + * Observe the [Player.getCurrentPosition] property as a [State]. + * + * @return A [State] that represents the current position of the [Player]. */ @Composable fun Player.currentPositionAsState(): LongState { @@ -103,7 +106,11 @@ fun Player.currentPositionAsState(): LongState { } /** - * Current buffered percentage [Player.getBufferedPercentage] + * Observe the [Player.getBufferedPercentage] property, adjusted between 0 and 1, as a [State]. + * + * @param updateInterval The interval at which this value is updated. + * + * @return A [State] that represents the buffer percentage (between 0 and 1) of the [Player]. */ @Composable fun Player.currentBufferedPercentageAsState(updateInterval: Duration = DefaultUpdateInterval): FloatState { @@ -114,7 +121,9 @@ fun Player.currentBufferedPercentageAsState(updateInterval: Duration = DefaultUp } /** - * Duration [Player.getDuration] + * Observe the [Player.getDuration] property as a [State]. + * + * @return A [State] that represents the duration of the current [MediaItem]. */ @Composable fun Player.durationAsState(): LongState { @@ -125,7 +134,9 @@ fun Player.durationAsState(): LongState { } /** - * Available commands [Player.getAvailableCommands] + * Observe the [Player.getAvailableCommands] property as a [State]. + * + * @return A [State] that represents the currently available commands of the [Player]. */ @Composable fun Player.availableCommandsAsState(): State { @@ -136,7 +147,9 @@ fun Player.availableCommandsAsState(): State { } /** - * Player error [Player.getPlayerError] + * Observe the [Player.getPlayerError] property as a [State]. + * + * @return A [State] that represents the current error of the [Player], or `null` if none. */ @Composable fun Player.playerErrorAsState(): State { @@ -147,7 +160,9 @@ fun Player.playerErrorAsState(): State { } /** - * Shuffle mode enabled [Player.getShuffleModeEnabled] + * Observe the [Player.getShuffleModeEnabled] property as a [State]. + * + * @return A [State] that represents whether shuffle mode is currently enabled. */ @Composable fun Player.shuffleModeEnabledAsState(): State { @@ -158,7 +173,9 @@ fun Player.shuffleModeEnabledAsState(): State { } /** - * Media item count [Player.getMediaItemCount] + * Observe the [Player.getMediaItemCount] property as a [State]. + * + * @return A [State] that represents the current [MediaItem] count of the [Player]. */ @Composable fun Player.mediaItemCountAsState(): IntState { @@ -169,7 +186,9 @@ fun Player.mediaItemCountAsState(): IntState { } /** - * @return true if [Player.getMediaItemCount] > 0 + * Observe whether the [Player] has any media items. + * + * @return A [State] that represents whether the [Player] currently has any media items. */ @Composable fun Player.hasMediaItemsAsState(): State { @@ -181,7 +200,9 @@ fun Player.hasMediaItemsAsState(): State { } /** - * Playback speed [Player.getPlaybackParameters] + * Observe the [Player.getPlaybackSpeed] property as a [State]. + * + * @return A [State] that represents the current playback speed of the [Player]. */ @Composable fun Player.playbackSpeedAsState(): FloatState { @@ -192,7 +213,9 @@ fun Player.playbackSpeedAsState(): FloatState { } /** - * Current media metadata [Player.getMediaMetadata] + * Observe the [Player.getMediaMetadata] property as a [State]. + * + * @return A [State] that represents the metadata of the current [MediaItem] of the [Player]. */ @Composable fun Player.currentMediaMetadataAsState(): State { @@ -203,7 +226,9 @@ fun Player.currentMediaMetadataAsState(): State { } /** - * Current media item index as state [Player.getCurrentMediaItem] + * Observe the [Player.getCurrentMediaItemIndex] property as a [State]. + * + * @return A [State] that represents the current [MediaItem] index. */ @Composable fun Player.currentMediaItemIndexAsState(): IntState { @@ -214,7 +239,9 @@ fun Player.currentMediaItemIndexAsState(): IntState { } /** - * Get current media items as state [Player.getCurrentMediaItems] + * Observe the [Player.getCurrentMediaItems] property as a [State]. + * + * @return A [State] that represents the current [MediaItem]s of the [Player]. */ @Composable fun Player.getCurrentMediaItemsAsState(): State> { @@ -225,7 +252,9 @@ fun Player.getCurrentMediaItemsAsState(): State> { } /** - * Video size as state [Player.getVideoSize] + * Observe the [Player.getVideoSize] property as a [State]. + * + * @return A [State] that represents the video size of the current [MediaItem]. */ @Composable fun Player.videoSizeAsState(): State { @@ -236,9 +265,11 @@ fun Player.videoSizeAsState(): State { } /** - * Get aspect ratio of the current video as [State]. + * Observe the aspect ratio of the current [MediaItem] as a [State]. * * @param defaultAspectRatio The aspect ratio when the video size is unknown, or for audio content. + * + * @return A [State] that represents the current aspect ratio of the [Player]. */ @Composable fun Player.getAspectRatioAsState(defaultAspectRatio: Float): FloatState { @@ -249,7 +280,9 @@ fun Player.getAspectRatioAsState(defaultAspectRatio: Float): FloatState { } /** - * @return `true` if current media item is a live stream. + * Observe the [Player.isCurrentMediaItemLive] property as a [State]. + * + * @return A [State] that represents whether the current [MediaItem] is a live stream. */ @Composable fun Player.isCurrentMediaItemLiveAsState(): State { @@ -260,7 +293,9 @@ fun Player.isCurrentMediaItemLiveAsState(): State { } /** - * @return Get the current chapter as state, when the current chapter changes. + * Observe the [Player.getChapterAtPosition] property as a [State]. + * + * @return A [State] that represents the current [Chapter], or `null` if none. */ @Composable fun Player.getCurrentChapterAsState(): State { @@ -271,7 +306,9 @@ fun Player.getCurrentChapterAsState(): State { } /** - * @return Get the current credit as state, when the current credit changes. + * Observe the [Player.getCreditAtPosition] property as a [State]. + * + * @return A [State] that represents the current [Credit], or `null` if none. */ @Composable fun Player.getCurrentCreditAsState(): State { @@ -282,10 +319,14 @@ fun Player.getCurrentCreditAsState(): State { } /** - * @return Get the current [PlaybackMetrics] as [State]. + * Observe the [PillarboxExoPlayer.getCurrentMetrics] property as a [State]. + * + * @param updateInterval The interval at which this value is updated. + * + * @return A [State] that represents the current metrics of the [PillarboxExoPlayer], or `null` if none. */ @Composable -fun PillarboxExoPlayer.getPeriodicallyCurrentMetricsAsState(updateInterval: Duration = 1.seconds): State { +fun PillarboxExoPlayer.getPeriodicallyCurrentMetricsAsState(updateInterval: Duration = DefaultUpdateInterval): State { return remember(this) { currentPositionAsFlow(updateInterval).map { getCurrentMetrics() } }.collectAsState(initial = getCurrentMetrics()) diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/DelayedVisibilityState.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/DelayedVisibilityState.kt index daf319f41..aec4cce17 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/DelayedVisibilityState.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/DelayedVisibilityState.kt @@ -9,6 +9,7 @@ import android.os.Build import android.view.accessibility.AccessibilityManager import androidx.compose.foundation.Indication import androidx.compose.foundation.focusable +import androidx.compose.foundation.interaction.Interaction import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.selection.toggleable import androidx.compose.runtime.Composable @@ -39,10 +40,10 @@ import kotlin.time.Duration.Companion.ZERO import kotlin.time.Duration.Companion.seconds /** - * Delayed visibility state + * Represents a state that manages visibility, with an optional delayed auto-hiding functionality. * - * @param initialVisible Initial visible - * @param initialDuration Initial duration + * @param initialVisible The initial visibility state of the component. + * @param initialDuration The initial duration before auto-hiding. */ @Stable class DelayedVisibilityState internal constructor( @@ -53,52 +54,58 @@ class DelayedVisibilityState internal constructor( private set /** - * Visible + * Represents the visibility state of the component. + * + * This property is observable and changes to this property will trigger recomposition. */ var isVisible by mutableStateOf(initialVisible) /** - * Duration + * Represents the delay until auto-hide is performed. + * + * This property is observable and changes to this property will trigger recomposition. */ var duration by mutableStateOf(initialDuration) /** - * Toggle + * Toggles the visibility of the component. */ fun toggle() { this.isVisible = !isVisible } /** - * Show + * Makes the component visible. */ fun show() { this.isVisible = true } /** - * Hide + * Makes the component invisible. */ fun hide() { this.isVisible = false } /** - * Disable auto hide + * Disables the auto-hide behavior of the component. */ fun disableAutoHide() { duration = DisabledDuration } /** - * Reset the auto hide countdown + * Resets the auto-hide countdown. */ fun resetAutoHide() { autoHideResetTrigger = !autoHideResetTrigger } /** - * Is auto hide enabled + * Checks if the auto-hide feature is enabled. + * + * @return `true` if auto-hide is enabled, `false` otherwise. */ fun isAutoHideEnabled(): Boolean { return duration < INFINITE && duration > ZERO @@ -107,23 +114,23 @@ class DelayedVisibilityState internal constructor( @Suppress("UndocumentedPublicClass") companion object { /** - * Default duration + * Default auto-hide duration. */ val DefaultDuration = 3.seconds /** - * Disabled duration + * Disabled auto-hide duration. */ val DisabledDuration = ZERO } } /** - * Toggleable + * Makes a Composable toggleable, controlling the visibility state of a [DelayedVisibilityState]. * - * @param enabled whether this toggleable will handle input events and appear enabled for semantics purposes - * @param role the type of user interface element. Accessibility services might use this to describe the element or do customizations - * @param delayedVisibilityState the delayed visibility state to link + * @param enabled Whether to handle input events and appear enabled for semantics purposes. + * @param role The type of UI element. Accessibility services might use this to describe the element. + * @param delayedVisibilityState The [DelayedVisibilityState] instance to control the visibility of the component. */ fun Modifier.toggleable( enabled: Boolean = true, @@ -137,14 +144,14 @@ fun Modifier.toggleable( ) /** - * Toggleable + * Makes a Composable toggleable, controlling the visibility state of a [DelayedVisibilityState]. * - * @param enabled whether this toggleable will handle input events and appear enabled for semantics purposes - * @param role the type of user interface element. Accessibility services might use this to describe the element or do customizations - * @param indication indication to be shown when the modified element is pressed. By default, indication from LocalIndication will be used. - * Pass null to show no indication, or current value from LocalIndication to show theme default - * @param interactionSource MutableInteractionSource that will be used to emit PressInteraction.Press when this toggleable is being pressed. - * @param delayedVisibilityState the delayed visibility state to link + * @param enabled Whether to handle input events and appear enabled for semantics purposes. + * @param role The type of UI element. Accessibility services might use this to describe the element. + * @param indication Indication to be shown when the Composable is pressed. If `null`, no indication will be shown. + * @param interactionSource The [MutableInteractionSource] that will be used to dispatch [Interaction]s when this toggleable component is being + * interacted with. + * @param delayedVisibilityState The [DelayedVisibilityState] instance to control the visibility of the component. */ fun Modifier.toggleable( enabled: Boolean = true, @@ -169,9 +176,9 @@ fun Modifier.toggleable( ) /** - * Maintain visibility on focus + * Maintains a Composable visible when it gains focus. * - * @param delayedVisibilityState the delayed visibility state to link + * @param delayedVisibilityState The [DelayedVisibilityState] instance to control the visibility of the component. */ fun Modifier.maintainVisibleOnFocus(delayedVisibilityState: DelayedVisibilityState): Modifier { return onFocusChanged { @@ -182,12 +189,14 @@ fun Modifier.maintainVisibleOnFocus(delayedVisibilityState: DelayedVisibilitySta } /** - * Remember delayed visibility state + * Remembers a [DelayedVisibilityState] for the provided [Player] * - * @param player The player to listen if it is playing or not - * @param visible visibility state of the content - * @param autoHideEnabled true to enable hide after [duration] - * @param duration the duration to wait after hiding the content. + * @param player The [Player] to associate with the [DelayedVisibilityState]. + * @param visible Whether the component is initially visible. + * @param autoHideEnabled Whether auto-hiding is enabled. Auto-hiding is always disabled when accessibility is on. + * @param duration The duration to wait before hiding the component. + * + * @return A [DelayedVisibilityState] instance. */ @Composable fun rememberDelayedVisibilityState( @@ -206,11 +215,13 @@ fun rememberDelayedVisibilityState( } /** - * Remember delayed visibility state + * Remembers a [DelayedVisibilityState]. + * + * @param visible Whether the component is initially visible. + * @param autoHideEnabled Whether auto-hiding is enabled. Auto-hiding is always disabled when accessibility is on. + * @param duration The duration to wait before hiding the component. * - * @param visible visibility state of the content. - * @param autoHideEnabled true to enable hide after [duration]. Auto hide is always disabled when accessibility is on. - * @param duration the duration to wait after hiding the content. + * @return A [DelayedVisibilityState] instance. */ @Composable fun rememberDelayedVisibilityState( diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/KeepScreenOn.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/KeepScreenOn.kt index a51120aea..7666d2cf3 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/KeepScreenOn.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/KeepScreenOn.kt @@ -12,7 +12,7 @@ import androidx.media3.common.Player import ch.srgssr.pillarbox.ui.extension.isPlayingAsState /** - * Keep screen on when [Player.isPlaying] + * Keeps the screen on while the [Player] is playing. */ @Composable @SuppressLint("ComposableNaming") diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/ToggleableBox.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/ToggleableBox.kt index f8f7689fe..3a56a1e4d 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/ToggleableBox.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/ToggleableBox.kt @@ -35,17 +35,17 @@ import kotlinx.coroutines.launch import kotlin.time.Duration /** - * Toggle view + * A Composable function that provides a container with toggleable content. * - * @param visibilityState A state that holds the current visibility and auto hide delay mode. - * @param toggleableContent Content to show or hide based on the value of [DelayedVisibilityState.isVisible]. - * @param modifier modifier for the Layout created to contain the content. - * @param toggleable content is toggleable. - * @param contentAlignment - The default alignment inside the Box. - * @param propagateMinConstraints - Whether the incoming min constraints should be passed to content. - * @param enter EnterTransition(s) used for the appearing animation, fading in while expanding by default. - * @param exit ExitTransition(s) used for the disappearing animation, fading out while shrinking by default. - * @param content Content displayed under toggleableContent. + * @param visibilityState The [DelayedVisibilityState] managing the visibility of the toggleable content. + * @param toggleableContent The content to show or hidde based on [DelayedVisibilityState.isVisible]. + * @param modifier The [Modifier] to apply to the layout. + * @param toggleable Whether the content is toggleable or not. + * @param contentAlignment The alignment of the content within the layout. + * @param propagateMinConstraints Whether the incoming minimum constraints should be passed to the content. + * @param enter The `enter` transition to be used when [toggleableContent] becomes visible. + * @param exit The `exit` transition to be used when [toggleableContent] becomes hidden. + * @param content The content to be displayed underneath [toggleableContent]. */ @Composable fun ToggleableBox( diff --git a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/player/PlayerSurface.kt b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/player/PlayerSurface.kt index 92f057d34..56571d03c 100644 --- a/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/player/PlayerSurface.kt +++ b/pillarbox-ui/src/main/java/ch/srgssr/pillarbox/ui/widget/player/PlayerSurface.kt @@ -33,17 +33,18 @@ import ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerSubtitleView import ch.srgssr.pillarbox.ui.extension.getAspectRatioAsState /** - * Pillarbox player surface + * A Composable function that displays a [Player]. * - * @param player The player to render in this [SurfaceView]. - * @param modifier The [Modifier] to be applied to the layout. - * @param scaleMode The scale mode to use. Only used for video content. Only used when the aspect ratio is strictly positive. - * @param contentAlignment The "letterboxing" content alignment inside the parent. Only used when the aspect ratio is strictly positive. - * @param defaultAspectRatio The aspect ratio to use while video is loading or for audio content. - * @param displayDebugView When `true`, displays debug information on top of the surface. Only used when the aspect ratio is strictly positive. - * @param surfaceType Surface type to use. When playing DRM content, only [SurfaceType.Surface] is supported. - * @param surfaceContent The Composable content to display on top of the [SurfaceView]. By default, render the subtitles. Only used when the aspect - * ratio is strictly positive. + * It supports different surface type, scaling modes, and allows for custom content to be laid on top of the [Player]. + * + * @param player The [Player] instance to use for playback. + * @param modifier The [Modifier] to apply to the layout. + * @param scaleMode The scaling mode to use. + * @param contentAlignment The "letterboxing" content alignment inside the parent. + * @param defaultAspectRatio The default aspect ratio to use while the video is loading, or for audio content. + * @param displayDebugView Whether to display a debug view showing video size and aspect ratio information. Defaults to false. + * @param surfaceType The type of surface to use for rendering the video. + * @param surfaceContent The content to display on top of the [Player]. */ @Suppress("CyclomaticComplexMethod") @Composable @@ -129,21 +130,28 @@ fun PlayerSurface( } /** - * Surface type + * Represents the type of surface used for video rendering. */ enum class SurfaceType { /** - * Render into a [SurfaceView]. + * Renders the video into a [SurfaceView]. + * + * This is the most optimized option, and it supports DRM content. */ Surface, /** - * Render into a [TextureView], not compatible with DRM content. + * Renders the video into a [TextureView]. + * + * This option may be interesting when dealing with animation, and the [SurfaceType.Surface] option doesn't work as expected. However, it does + * not support DRM content. */ Texture, /** - * Render into a [SphericalGLSurfaceView] useful for 360° content. + * Renders the video into a [SphericalGLSurfaceView]. + * + * This is suited for 360° video content. However, it does not support DRM content. */ Spherical, }