Update eventmap

This commit is contained in:
2026-04-22 00:17:34 +02:00
parent eee49c5e6b
commit e4d70467c6
4 changed files with 94 additions and 79 deletions
@@ -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
View File
@@ -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>
) : (