mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-05 05:36:17 +00:00
Update eventmap
This commit is contained in:
@@ -2,7 +2,17 @@ package dev.zoriya.omni
|
||||
|
||||
import android.os.SystemClock
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.C.TRACK_TYPE_AUDIO
|
||||
import androidx.media3.common.C.TRACK_TYPE_TEXT
|
||||
import androidx.media3.common.C.TRACK_TYPE_VIDEO
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.PlaybackParameters
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Player.STATE_BUFFERING
|
||||
import androidx.media3.common.Player.STATE_ENDED
|
||||
import androidx.media3.common.Player.STATE_IDLE
|
||||
import androidx.media3.common.Player.STATE_READY
|
||||
import androidx.media3.common.Tracks
|
||||
import com.margelo.nitro.omni.BoolProperty
|
||||
import com.margelo.nitro.omni.HybridOmniEventMapSpec
|
||||
import com.margelo.nitro.omni.NumberProperty
|
||||
@@ -11,8 +21,8 @@ import com.margelo.nitro.omni.Rendition
|
||||
import com.margelo.nitro.omni.Track
|
||||
|
||||
class EventMap(private val player: Player) : HybridOmniEventMapSpec(), Player.Listener {
|
||||
val onPrevListeners = mutableSetOf<() -> Unit>()
|
||||
val onNextListeners = mutableSetOf<() -> Unit>()
|
||||
private val onPrevListeners = mutableSetOf<() -> Unit>()
|
||||
private val onNextListeners = mutableSetOf<() -> Unit>()
|
||||
private val onEndListeners = mutableSetOf<() -> Unit>()
|
||||
private val onErrorListeners = mutableSetOf<(type: String, message: String) -> Unit>()
|
||||
private val onAudioFocusChangeListeners = mutableSetOf<(status: String) -> Unit>()
|
||||
@@ -27,17 +37,6 @@ class EventMap(private val player: Player) : HybridOmniEventMapSpec(), Player.Li
|
||||
|
||||
init {
|
||||
player.addListener(this)
|
||||
emitCoreState(forceCurrentTime = true)
|
||||
}
|
||||
|
||||
private fun computePlayerStatus(): PlayerStatus {
|
||||
val loading = player.isLoading
|
||||
val idle = player.playbackState == Player.STATE_IDLE || player.playbackState == Player.STATE_ENDED
|
||||
return when {
|
||||
loading -> PlayerStatus.LOADING
|
||||
idle -> PlayerStatus.IDLE
|
||||
else -> PlayerStatus.READYTOPLAY
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectedTrack(trackType: Int): Track? {
|
||||
@@ -58,61 +57,56 @@ class EventMap(private val player: Player) : HybridOmniEventMapSpec(), Player.Li
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onEvents(player: Player, events: Player.Events) {
|
||||
if (
|
||||
events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) ||
|
||||
events.contains(Player.EVENT_IS_LOADING_CHANGED)
|
||||
) {
|
||||
val status = computePlayerStatus()
|
||||
playerStatusListeners.forEach { it(status) }
|
||||
if (player.playbackState == Player.STATE_ENDED) {
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
val state = when (player.playbackState) {
|
||||
STATE_IDLE -> PlayerStatus.IDLE
|
||||
STATE_BUFFERING -> PlayerStatus.LOADING
|
||||
STATE_READY -> PlayerStatus.READYTOPLAY
|
||||
STATE_ENDED -> {
|
||||
onEndListeners.forEach { it() }
|
||||
PlayerStatus.IDLE
|
||||
}
|
||||
else -> PlayerStatus.IDLE
|
||||
}
|
||||
playerStatusListeners.forEach { it(state) }
|
||||
}
|
||||
|
||||
if (
|
||||
events.contains(Player.EVENT_PLAY_WHEN_READY_CHANGED) ||
|
||||
events.contains(Player.EVENT_IS_PLAYING_CHANGED)
|
||||
) {
|
||||
val isPlaying = player.isPlaying
|
||||
onAudioFocusChangeListeners.forEach { it(if (isPlaying) "playing" else "paused") }
|
||||
stateBoolListeners[BoolProperty.ISPLAYING]?.forEach { it(isPlaying) }
|
||||
}
|
||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||
onIsPlayingChanged(playWhenReady)
|
||||
}
|
||||
|
||||
if (events.contains(Player.EVENT_VOLUME_CHANGED)) {
|
||||
val volume = player.volume.toDouble().coerceIn(0.0, 1.0)
|
||||
stateListeners[NumberProperty.VOLUME]?.forEach { it(volume) }
|
||||
stateBoolListeners[BoolProperty.MUTED]?.forEach { it(volume <= 0.0) }
|
||||
}
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
stateBoolListeners[BoolProperty.ISPLAYING]?.forEach { it(isPlaying) }
|
||||
}
|
||||
|
||||
if (events.contains(Player.EVENT_PLAYBACK_PARAMETERS_CHANGED)) {
|
||||
stateListeners[NumberProperty.PLAYBACKRATE]?.forEach {
|
||||
it(player.playbackParameters.speed.toDouble())
|
||||
}
|
||||
}
|
||||
override fun onVolumeChanged(volume: Float) {
|
||||
stateListeners[NumberProperty.VOLUME]?.forEach { it(volume.toDouble()) }
|
||||
stateBoolListeners[BoolProperty.MUTED]?.forEach { it(volume <= 0.0) }
|
||||
}
|
||||
|
||||
if (
|
||||
events.contains(Player.EVENT_POSITION_DISCONTINUITY) ||
|
||||
events.contains(Player.EVENT_PLAYBACK_STATE_CHANGED) ||
|
||||
events.contains(Player.EVENT_IS_LOADING_CHANGED)
|
||||
) {
|
||||
emitCoreState(forceCurrentTime = true)
|
||||
} else {
|
||||
emitCoreState(forceCurrentTime = false)
|
||||
}
|
||||
|
||||
if (events.contains(Player.EVENT_TRACKS_CHANGED)) {
|
||||
selectedTrack(C.TRACK_TYPE_VIDEO)?.let { track ->
|
||||
onVideoTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
selectedTrack(C.TRACK_TYPE_AUDIO)?.let { track ->
|
||||
onAudioTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
onSubtitleChangeListeners.forEach { it(selectedTrack(C.TRACK_TYPE_TEXT)) }
|
||||
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {
|
||||
stateListeners[NumberProperty.PLAYBACKRATE]?.forEach {
|
||||
it(playbackParameters.speed.toDouble())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPlayerError(error: androidx.media3.common.PlaybackException) {
|
||||
override fun onTracksChanged(tracks: Tracks) {
|
||||
selectedTrack(TRACK_TYPE_VIDEO)?.let { track ->
|
||||
onVideoTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
selectedTrack(TRACK_TYPE_AUDIO)?.let { track ->
|
||||
onAudioTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
onSubtitleChangeListeners.forEach {
|
||||
it(
|
||||
selectedTrack(
|
||||
TRACK_TYPE_TEXT
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
onErrorListeners.forEach {
|
||||
it(error.errorCodeName, error.message ?: "unknown message")
|
||||
}
|
||||
@@ -123,7 +117,7 @@ class EventMap(private val player: Player) : HybridOmniEventMapSpec(), Player.Li
|
||||
newPosition: Player.PositionInfo,
|
||||
reason: Int
|
||||
) {
|
||||
emitCurrentTime(force = true)
|
||||
emitCoreState(forceCurrentTime = true)
|
||||
}
|
||||
|
||||
private fun emitCoreState(forceCurrentTime: Boolean) {
|
||||
|
||||
@@ -146,7 +146,7 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
|
||||
override fun addMediaItems(
|
||||
p0: Int,
|
||||
p1: List<MediaItem?>?
|
||||
p1: List<MediaItem>
|
||||
) = Unit
|
||||
|
||||
override fun moveMediaItems(fromIndex: Int, toIndex: Int, newIndex: Int) = Unit
|
||||
@@ -165,18 +165,15 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
|
||||
override fun prepare() = Unit
|
||||
|
||||
override fun getPlaybackState(): Int {
|
||||
val ended = mpv.getPropertyBoolean("eof-reached") ?: false
|
||||
if (ended) return Player.STATE_ENDED
|
||||
override fun getPlaybackState(): Int =
|
||||
when (true) {
|
||||
mpv.getPropertyBoolean("paused-for-cache") -> STATE_BUFFERING
|
||||
mpv.getPropertyBoolean("eof-reached") -> STATE_ENDED
|
||||
mpv.getPropertyBoolean("core-idle") -> STATE_IDLE
|
||||
else -> STATE_READY
|
||||
}
|
||||
|
||||
val idle = mpv.getPropertyBoolean("core-idle") ?: false
|
||||
if (idle) return Player.STATE_IDLE
|
||||
|
||||
val loading = mpv.getPropertyBoolean("paused-for-cache") ?: false
|
||||
return if (loading) Player.STATE_BUFFERING else Player.STATE_READY
|
||||
}
|
||||
|
||||
override fun getPlaybackSuppressionReason(): Int = Player.PLAYBACK_SUPPRESSION_REASON_NONE
|
||||
override fun getPlaybackSuppressionReason(): Int = PLAYBACK_SUPPRESSION_REASON_NONE
|
||||
|
||||
override fun getPlayerError(): PlaybackException? = playerError
|
||||
|
||||
@@ -188,7 +185,7 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
|
||||
override fun setRepeatMode(repeatMode: Int) = Unit
|
||||
|
||||
override fun getRepeatMode(): Int = Player.REPEAT_MODE_OFF
|
||||
override fun getRepeatMode(): Int = REPEAT_MODE_OFF
|
||||
|
||||
override fun setShuffleModeEnabled(shuffleModeEnabled: Boolean) = Unit
|
||||
|
||||
@@ -481,6 +478,16 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
|
||||
override fun event(eventId: Int) {
|
||||
when (eventId) {
|
||||
MPVLib.MpvEvent.MPV_EVENT_START_FILE -> listeners.forEach {
|
||||
it.onPlaybackStateChanged(STATE_BUFFERING)
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_FILE_LOADED ->
|
||||
listeners.forEach {
|
||||
it.onPlaybackStateChanged(STATE_READY)
|
||||
it.onIsPlayingChanged(playWhenReady)
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_SEEK,
|
||||
MPVLib.MpvEvent.MPV_EVENT_PLAYBACK_RESTART -> {
|
||||
val positionMs = getCurrentPosition()
|
||||
@@ -500,6 +507,12 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
}
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_END_FILE -> listeners.forEach {
|
||||
it.onPlaybackStateChanged(
|
||||
STATE_ENDED
|
||||
)
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_QUEUE_OVERFLOW -> {
|
||||
playerError = PlaybackException(
|
||||
"mpv event queue overflow",
|
||||
@@ -508,7 +521,13 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
)
|
||||
listeners.forEach {
|
||||
it.onPlayerErrorChanged(playerError)
|
||||
it.onPlayerError(playerError)
|
||||
it.onPlayerError(
|
||||
playerError ?: PlaybackException(
|
||||
"unknown",
|
||||
null,
|
||||
PlaybackException.ERROR_CODE_UNSPECIFIED
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -555,8 +574,9 @@ class MpvPlayer(ctx: Context) : BasePlayer(), MPVLib.EventObserver {
|
||||
}
|
||||
|
||||
"core-idle", "eof-reached" ->
|
||||
listeners.forEach { it.onPlaybackStateChanged(getPlaybackState())
|
||||
it.onIsPlayingChanged(false) }
|
||||
listeners.forEach {
|
||||
it.onPlaybackStateChanged(getPlaybackState())
|
||||
}
|
||||
|
||||
"paused-for-cache" -> {
|
||||
listeners.forEach {
|
||||
|
||||
@@ -112,11 +112,11 @@ class OmniPlayer : HybridOmniPlayerSpec() {
|
||||
}
|
||||
|
||||
override fun playPrev() {
|
||||
eventMap.onPrevListeners.forEach { it() }
|
||||
player.seekToPreviousMediaItem()
|
||||
}
|
||||
|
||||
override fun playNext() {
|
||||
eventMap.onNextListeners.forEach { it() }
|
||||
player.seekToNextMediaItem()
|
||||
}
|
||||
|
||||
override fun selectVideo(video: Track) {
|
||||
|
||||
+3
-2
@@ -200,7 +200,6 @@ function PlayerExample({
|
||||
refreshTracks();
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container}>
|
||||
<Text style={styles.heading}>react-native-omni</Text>
|
||||
@@ -393,7 +392,8 @@ function PlayerExample({
|
||||
rendition.selected && styles.selectedTrackButtonText,
|
||||
]}
|
||||
>
|
||||
{rendition.width}x{rendition.height} ({Math.round(rendition.bitrate / 1000)} kbps)
|
||||
{rendition.width}x{rendition.height} (
|
||||
{Math.round(rendition.bitrate / 1000)} kbps)
|
||||
</Text>
|
||||
</Pressable>
|
||||
))
|
||||
@@ -405,6 +405,7 @@ function PlayerExample({
|
||||
style={styles.logCard}
|
||||
contentContainerStyle={styles.logContent}
|
||||
>
|
||||
<Text style={styles.selectorTitle}>Logs</Text>
|
||||
{logs.length === 0 ? (
|
||||
<Text style={styles.logText}>Event log will appear here.</Text>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user