new: display current playback position and implement cross-platform position tracking
This commit is contained in:
+4
@@ -7,6 +7,8 @@ import androidx.media3.exoplayer.ExoPlayer
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
class AndroidAudioPlayer(
|
||||
context: Context,
|
||||
@@ -36,6 +38,8 @@ class AndroidAudioPlayer(
|
||||
)
|
||||
}
|
||||
|
||||
override fun currentPosition(): Duration = player.currentPosition.coerceAtLeast(0).milliseconds
|
||||
|
||||
override fun load(uri: String) {
|
||||
val mediaItem = MediaItem.fromUri(uri)
|
||||
player.setMediaItem(mediaItem)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package fr.ajaury.gwenedeg.player
|
||||
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlin.time.Duration
|
||||
|
||||
interface AudioPlayer {
|
||||
val playbackState: StateFlow<PlaybackState>
|
||||
|
||||
fun currentPosition(): Duration
|
||||
|
||||
fun play()
|
||||
|
||||
fun pause()
|
||||
|
||||
@@ -7,13 +7,18 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import platform.AVFoundation.AVPlayer
|
||||
import platform.AVFoundation.AVPlayerItem
|
||||
import platform.AVFoundation.AVPlayerItemDidPlayToEndTimeNotification
|
||||
import platform.AVFoundation.currentTime
|
||||
import platform.AVFoundation.pause
|
||||
import platform.AVFoundation.play
|
||||
import platform.AVFoundation.replaceCurrentItemWithPlayerItem
|
||||
import platform.CoreMedia.CMTimeGetSeconds
|
||||
import platform.Foundation.NSNotificationCenter
|
||||
import platform.Foundation.NSOperationQueue
|
||||
import platform.Foundation.NSURL
|
||||
import platform.darwin.NSObjectProtocol
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class IosAudioPlayer : AudioPlayer {
|
||||
private var player: AVPlayer? = null
|
||||
@@ -22,6 +27,13 @@ class IosAudioPlayer : AudioPlayer {
|
||||
private val _playbackState = MutableStateFlow(PlaybackState.IDLE)
|
||||
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
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalForeignApi::class)
|
||||
override fun load(uri: String) {
|
||||
release()
|
||||
|
||||
@@ -9,6 +9,8 @@ import javax.sound.sampled.AudioFormat
|
||||
import javax.sound.sampled.AudioSystem
|
||||
import javax.sound.sampled.Clip
|
||||
import javax.sound.sampled.LineEvent
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.microseconds
|
||||
|
||||
/**
|
||||
* Desktop [AudioPlayer] backed by [javax.sound.sampled].
|
||||
@@ -25,6 +27,8 @@ 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 fun load(uri: String) {
|
||||
release()
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import org.w3c.dom.HTMLAudioElement
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class WebAudioPlayer : AudioPlayer {
|
||||
private var audio: HTMLAudioElement? = null
|
||||
@@ -12,6 +14,8 @@ 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 fun load(uri: String) {
|
||||
release()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user