new: display playback progress with a progress bar

This commit is contained in:
2026-06-19 13:38:32 +02:00
parent 090305dbde
commit 511e3b5b9a
8 changed files with 61 additions and 20 deletions
@@ -1,6 +1,7 @@
package fr.ajaury.gwenedeg.player
import android.content.Context
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
@@ -38,7 +39,15 @@ class AndroidAudioPlayer(
)
}
override fun currentPosition(): Duration = player.currentPosition.coerceAtLeast(0).milliseconds
override val currentPosition: Duration
get() = player.currentPosition.coerceAtLeast(0).milliseconds
override val duration: Duration
get() = player.duration
.takeIf { it != C.TIME_UNSET }
?.coerceAtLeast(0)
?.milliseconds
?: 0.milliseconds
override fun load(uri: String) {
val mediaItem = MediaItem.fromUri(uri)
@@ -6,7 +6,9 @@ import kotlin.time.Duration
interface AudioPlayer {
val playbackState: StateFlow<PlaybackState>
fun currentPosition(): Duration
val currentPosition: Duration
val duration: Duration
fun play()
@@ -7,7 +7,9 @@ import kotlinx.coroutines.flow.asStateFlow
import platform.AVFoundation.AVPlayer
import platform.AVFoundation.AVPlayerItem
import platform.AVFoundation.AVPlayerItemDidPlayToEndTimeNotification
import platform.AVFoundation.currentItem
import platform.AVFoundation.currentTime
import platform.AVFoundation.duration
import platform.AVFoundation.pause
import platform.AVFoundation.play
import platform.AVFoundation.replaceCurrentItemWithPlayerItem
@@ -28,11 +30,20 @@ class IosAudioPlayer : AudioPlayer {
override val playbackState: StateFlow<PlaybackState> = _playbackState.asStateFlow()
@OptIn(ExperimentalForeignApi::class)
override fun currentPosition(): Duration {
val player = player ?: return 0.milliseconds
val seconds = CMTimeGetSeconds(player.currentTime()).takeIf { !it.isNaN() }
return seconds?.seconds ?: 0.milliseconds
}
override val currentPosition: Duration
get() {
val player = player ?: return 0.milliseconds
val seconds = CMTimeGetSeconds(player.currentTime()).takeIf { !it.isNaN() }
return seconds?.seconds ?: 0.milliseconds
}
@OptIn(ExperimentalForeignApi::class)
override val duration: Duration
get() {
val item = player?.currentItem ?: return 0.milliseconds
val seconds = CMTimeGetSeconds(item.duration).takeIf { it.isFinite() }
return seconds?.seconds ?: 0.milliseconds
}
@OptIn(ExperimentalForeignApi::class)
override fun load(uri: String) {
@@ -27,7 +27,11 @@ class JvmAudioPlayer : AudioPlayer {
private val _playbackState = MutableStateFlow(PlaybackState.IDLE)
override val playbackState: StateFlow<PlaybackState> = _playbackState.asStateFlow()
override fun currentPosition(): Duration = (clip?.microsecondPosition ?: 0L).microseconds
override val currentPosition: Duration
get() = (clip?.microsecondPosition ?: 0L).microseconds
override val duration: Duration
get() = (clip?.microsecondLength ?: 0L).microseconds
override fun load(uri: String) {
release()
@@ -14,7 +14,11 @@ class WebAudioPlayer : AudioPlayer {
private val _playbackState = MutableStateFlow(PlaybackState.IDLE)
override val playbackState: StateFlow<PlaybackState> = _playbackState.asStateFlow()
override fun currentPosition(): Duration = (audio?.currentTime ?: 0.0).seconds
override val currentPosition: Duration
get() = (audio?.currentTime ?: 0.0).seconds
override val duration: Duration
get() = (audio?.duration?.takeIf { it.isFinite() } ?: 0.0).seconds
override fun load(uri: String) {
release()