mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-05 13:46:59 +00:00
Format stuff
This commit is contained in:
@@ -10,9 +10,9 @@ import android.os.SystemClock
|
||||
import dev.jdtech.mpv.MPVLib
|
||||
|
||||
class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.EventObserver {
|
||||
val onPrevListeners = mutableSetOf<() -> Unit>()
|
||||
val onNextListeners = mutableSetOf<() -> Unit>()
|
||||
private val onEndListeners = mutableSetOf<() -> Unit>()
|
||||
private val onPrevListeners = mutableSetOf<() -> Unit>()
|
||||
private val onNextListeners = mutableSetOf<() -> Unit>()
|
||||
private val onErrorListeners = mutableSetOf<(type: String, message: String) -> Unit>()
|
||||
private val onAudioFocusChangeListeners = mutableSetOf<(status: String) -> Unit>()
|
||||
private val onVideoTrackChangeListeners = mutableSetOf<(track: Track) -> Unit>()
|
||||
@@ -32,7 +32,7 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
player.observeProperty("aid", MPVLib.MpvFormat.MPV_FORMAT_INT64)
|
||||
player.observeProperty("sid", MPVLib.MpvFormat.MPV_FORMAT_INT64)
|
||||
player.observeProperty("pause", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
player.observeProperty("muted", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
player.observeProperty("mute", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
player.observeProperty("eof-reached", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
player.observeProperty("core-idle", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
player.observeProperty("paused-for-cache", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
|
||||
@@ -65,7 +65,12 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
val label = player.getPropertyString("$base/title")
|
||||
?: player.getPropertyString("$base/codec")
|
||||
val language = player.getPropertyString("$base/lang")
|
||||
return Track(id = trackId.toString(), label = label, language = language, selected = selected)
|
||||
return Track(
|
||||
id = trackId.toString(),
|
||||
label = label,
|
||||
language = language,
|
||||
selected = selected
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -78,8 +83,10 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
isSeeking = false
|
||||
playerStatusListeners.forEach { it(PlayerStatus.LOADING) }
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_FILE_LOADED ->
|
||||
playerStatusListeners.forEach { it(PlayerStatus.READYTOPLAY) }
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_SEEK -> isSeeking = true
|
||||
MPVLib.MpvEvent.MPV_EVENT_PLAYBACK_RESTART -> isSeeking = false
|
||||
MPVLib.MpvEvent.MPV_EVENT_END_FILE -> {
|
||||
@@ -93,6 +100,7 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
}
|
||||
playerStatusListeners.forEach { it(PlayerStatus.IDLE) }
|
||||
}
|
||||
|
||||
MPVLib.MpvEvent.MPV_EVENT_QUEUE_OVERFLOW -> onErrorListeners.forEach {
|
||||
it("queue_overflow", "mpv event queue overflow")
|
||||
}
|
||||
@@ -107,10 +115,12 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
val track = getTrackById("video", value)
|
||||
if (track != null) onVideoTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
|
||||
"aid" -> {
|
||||
val track = getTrackById("audio", value)
|
||||
if (track != null) onAudioTrackChangeListeners.forEach { it(track) }
|
||||
}
|
||||
|
||||
"sid" -> {
|
||||
val track = getTrackById("sub", value)
|
||||
onSubtitleChangeListeners.forEach { it(track) }
|
||||
@@ -124,12 +134,16 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
lastTimePosDispatchMs = SystemClock.elapsedRealtime()
|
||||
stateListeners[NumberProperty.CURRENTTIME]?.forEach { it(value.coerceAtLeast(0.0)) }
|
||||
}
|
||||
|
||||
"demuxer-cache-time" -> stateListeners[NumberProperty.BUFFERED]
|
||||
?.forEach { it(value.coerceAtLeast(0.0)) }
|
||||
|
||||
"duration" -> stateListeners[NumberProperty.DURATION]
|
||||
?.forEach { it(value.coerceAtLeast(0.0)) }
|
||||
|
||||
"speed" -> stateListeners[NumberProperty.PLAYBACKRATE]
|
||||
?.forEach { it(value) }
|
||||
|
||||
"volume" -> stateListeners[NumberProperty.VOLUME]
|
||||
?.forEach { it((value / 100.0).coerceIn(0.0, 1.0)) }
|
||||
}
|
||||
@@ -142,8 +156,10 @@ class EventMap(private val player: MPVLib) : HybridOmniEventMapSpec(), MPVLib.Ev
|
||||
onAudioFocusChangeListeners.forEach { it(if (isPlaying) "playing" else "paused") }
|
||||
stateBoolListeners[BoolProperty.ISPLAYING]?.forEach { it(isPlaying) }
|
||||
}
|
||||
"muted" ->
|
||||
|
||||
"mute" ->
|
||||
stateBoolListeners[BoolProperty.MUTED]?.forEach { it(value) }
|
||||
|
||||
"eof-reached" -> eofReached = value
|
||||
"core-idle", "paused-for-cache" ->
|
||||
playerStatusListeners.forEach { it(computePlayerStatus()) }
|
||||
|
||||
@@ -12,8 +12,9 @@ import com.margelo.nitro.omni.views.*;
|
||||
public class OmniPackage : BaseReactPackage() {
|
||||
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
|
||||
|
||||
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider { emptyMap() }
|
||||
|
||||
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
|
||||
ReactModuleInfoProvider { emptyMap() }
|
||||
|
||||
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
||||
val viewManagers = ArrayList<ViewManager<*, *>>()
|
||||
viewManagers.add(HybridOmniViewManager())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.zoriya.omni
|
||||
|
||||
import android.util.Log
|
||||
import com.margelo.nitro.NitroModules
|
||||
import com.margelo.nitro.omni.Source
|
||||
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
||||
@@ -15,7 +16,7 @@ class OmniPlayer : HybridOmniPlayerSpec() {
|
||||
override val eventMap = EventMap(player)
|
||||
|
||||
init {
|
||||
player.setOptionString("vo", "gpu")
|
||||
player.setOptionString("vo", "null")
|
||||
player.setOptionString("gpu-context", "android")
|
||||
player.setOptionString("opengl-es", "yes")
|
||||
player.setOptionString("hwdec", "mediacodec-copy")
|
||||
@@ -65,43 +66,48 @@ class OmniPlayer : HybridOmniPlayerSpec() {
|
||||
|
||||
fun setSurface(surface: android.view.Surface?) {
|
||||
if (surface == null) {
|
||||
player.setOptionString("vo", "null")
|
||||
player.setOptionString("force-window", "no")
|
||||
player.detachSurface()
|
||||
} else {
|
||||
player.attachSurface(surface)
|
||||
player.setOptionString("force-window", "yes")
|
||||
player.setOptionString("vo", "gpu-next")
|
||||
}
|
||||
}
|
||||
|
||||
override val hasPrev get() = source.metadata?.hasPrev ?: false
|
||||
override val hasNext get() = source.metadata?.hasNext ?: false
|
||||
override val status: PlayerStatus
|
||||
get() {
|
||||
val idle = player.getPropertyBoolean("core-idle") ?: false
|
||||
val loading = player.getPropertyBoolean("paused-for-cache") ?: false
|
||||
return when {
|
||||
idle -> PlayerStatus.IDLE
|
||||
loading -> PlayerStatus.LOADING
|
||||
else -> PlayerStatus.READYTOPLAY
|
||||
}
|
||||
}
|
||||
override val status: PlayerStatus
|
||||
get() {
|
||||
val idle = player.getPropertyBoolean("core-idle") ?: false
|
||||
val loading = player.getPropertyBoolean("paused-for-cache") ?: false
|
||||
return when {
|
||||
idle -> PlayerStatus.IDLE
|
||||
loading -> PlayerStatus.LOADING
|
||||
else -> PlayerStatus.READYTOPLAY
|
||||
}
|
||||
}
|
||||
override val isPlaying get() = !(player.getPropertyBoolean("pause") ?: true)
|
||||
override var currentTime
|
||||
get() = (player.getPropertyDouble("time-pos") ?: 0.0).coerceAtLeast(0.0)
|
||||
set(value) {
|
||||
player.command(arrayOf("seek", value.coerceAtLeast(0.0).toString(), "absolute"))
|
||||
}
|
||||
override val buffered get() = (player.getPropertyDouble("demuxer-cache-time") ?: 0.0).coerceAtLeast(0.0)
|
||||
get() = (player.getPropertyDouble("time-pos") ?: 0.0).coerceAtLeast(0.0)
|
||||
set(value) {
|
||||
player.command(arrayOf("seek", value.coerceAtLeast(0.0).toString(), "absolute"))
|
||||
}
|
||||
override val buffered
|
||||
get() = (player.getPropertyDouble("demuxer-cache-time") ?: 0.0).coerceAtLeast(0.0)
|
||||
override val duration get() = (player.getPropertyDouble("duration") ?: 0.0).coerceAtLeast(0.0)
|
||||
|
||||
override var playbackRate
|
||||
get() = player.getPropertyDouble("speed") ?: 1.0
|
||||
set(value) {
|
||||
player.setPropertyDouble("speed", value.coerceAtLeast(0.0))
|
||||
}
|
||||
}
|
||||
|
||||
override var muted
|
||||
get() = player.getPropertyBoolean("muted") ?: false
|
||||
get() = player.getPropertyBoolean("mute") ?: false
|
||||
set(value) {
|
||||
player.setPropertyBoolean("muted", value)
|
||||
player.setPropertyBoolean("mute", value)
|
||||
}
|
||||
override var volume
|
||||
get() = (player.getPropertyDouble("volume") ?: 100.0).coerceIn(0.0, 100.0) / 100.0
|
||||
@@ -128,32 +134,32 @@ class OmniPlayer : HybridOmniPlayerSpec() {
|
||||
}
|
||||
|
||||
override fun playPrev() {
|
||||
// App-level action; no default implementation in VLC player.
|
||||
eventMap.onPrevListeners.forEach { it() }
|
||||
}
|
||||
|
||||
override fun playNext() {
|
||||
// App-level action; no default implementation in VLC player.
|
||||
eventMap.onNextListeners.forEach { it() }
|
||||
}
|
||||
|
||||
override fun selectVideo(video: Track) {
|
||||
val id = video.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("vid", id)
|
||||
}
|
||||
override fun selectVideo(video: Track) {
|
||||
val id = video.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("vid", id)
|
||||
}
|
||||
|
||||
override fun selectAudio(audio: Track) {
|
||||
val id = audio.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("aid", id)
|
||||
}
|
||||
override fun selectAudio(audio: Track) {
|
||||
val id = audio.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("aid", id)
|
||||
}
|
||||
|
||||
override fun selectSubtitle(subtitle: Track?) {
|
||||
when (subtitle) {
|
||||
null -> player.setPropertyString("sid", "no")
|
||||
else -> {
|
||||
val id = subtitle.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("sid", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun selectSubtitle(subtitle: Track?) {
|
||||
when (subtitle) {
|
||||
null -> player.setPropertyString("sid", "no")
|
||||
else -> {
|
||||
val id = subtitle.id.toIntOrNull() ?: return
|
||||
player.setPropertyInt("sid", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun selectRendition(rendition: Rendition?) {
|
||||
// Not supported by libVLC MediaPlayer track APIs.
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.margelo.nitro.omni.HybridOmniPlayerFactorySpec
|
||||
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
||||
import com.margelo.nitro.omni.Source
|
||||
|
||||
class OmniPlayerFactory(val context: ThemedReactContext): HybridOmniPlayerFactorySpec() {
|
||||
class OmniPlayerFactory(val context: ThemedReactContext) : HybridOmniPlayerFactorySpec() {
|
||||
override fun createPlayer(props: Source): HybridOmniPlayerSpec {
|
||||
return OmniPlayer().apply {
|
||||
source = props
|
||||
|
||||
@@ -26,7 +26,12 @@ class OmniView(val context: ThemedReactContext) : HybridOmniViewSpec() {
|
||||
boundPlayer?.setSurface(holder.surface)
|
||||
}
|
||||
|
||||
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
||||
override fun surfaceChanged(
|
||||
holder: SurfaceHolder,
|
||||
format: Int,
|
||||
width: Int,
|
||||
height: Int
|
||||
) {
|
||||
surfaceReady = true
|
||||
boundPlayer?.setSurface(holder.surface)
|
||||
}
|
||||
|
||||
+1
-2
@@ -5,8 +5,7 @@ import type { OmniEvents } from "./types/events";
|
||||
import type { OmniPlayerState } from "./types/player";
|
||||
|
||||
function capitalize<T extends string>(str: T): Capitalize<T> {
|
||||
return (str.charAt(0).toUpperCase() +
|
||||
str.slice(1).toLowerCase()) as Capitalize<T>;
|
||||
return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>;
|
||||
}
|
||||
|
||||
export const useEvent = <Event extends keyof OmniEvents>(
|
||||
|
||||
Reference in New Issue
Block a user