mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-16 02:44:51 +00:00
Migrate to mpv
This commit is contained in:
@@ -138,7 +138,7 @@ dependencies {
|
|||||||
// Add a dependency on NitroModules
|
// Add a dependency on NitroModules
|
||||||
implementation project(":react-native-nitro-modules")
|
implementation project(":react-native-nitro-modules")
|
||||||
|
|
||||||
implementation("org.videolan.android:libvlc-all:4.0.0-eap24")
|
implementation("dev.jdtech.mpv:libmpv:1.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNewArchitectureEnabled()) {
|
if (isNewArchitectureEnabled()) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Omni_kotlinVersion=2.1.20
|
Omni_kotlinVersion=2.1.20
|
||||||
Omni_minSdkVersion=23
|
Omni_minSdkVersion=26
|
||||||
Omni_targetSdkVersion=35
|
Omni_targetSdkVersion=35
|
||||||
Omni_compileSdkVersion=34
|
Omni_compileSdkVersion=34
|
||||||
Omni_ndkVersion=27.1.12297006
|
Omni_ndkVersion=27.1.12297006
|
||||||
|
|||||||
@@ -1,100 +1,127 @@
|
|||||||
package dev.zoriya.omni
|
package dev.zoriya.omni
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import com.margelo.nitro.NitroModules
|
import com.margelo.nitro.NitroModules
|
||||||
import com.margelo.nitro.omni.HybridOmniEventMapSpec
|
|
||||||
import com.margelo.nitro.omni.Source
|
import com.margelo.nitro.omni.Source
|
||||||
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
||||||
import com.margelo.nitro.omni.PlayerStatus
|
import com.margelo.nitro.omni.PlayerStatus
|
||||||
import com.margelo.nitro.omni.Rendition
|
import com.margelo.nitro.omni.Rendition
|
||||||
import com.margelo.nitro.omni.Track
|
import com.margelo.nitro.omni.Track
|
||||||
|
import dev.jdtech.mpv.MPVLib
|
||||||
import dev.zoriya.omni.utils.deferredObservable
|
import dev.zoriya.omni.utils.deferredObservable
|
||||||
import org.videolan.libvlc.LibVLC
|
|
||||||
import org.videolan.libvlc.Media
|
|
||||||
import org.videolan.libvlc.MediaPlayer
|
|
||||||
import org.videolan.libvlc.interfaces.IMedia
|
|
||||||
|
|
||||||
object VlcConst {
|
class OmniPlayer : HybridOmniPlayerSpec() {
|
||||||
val vlc = LibVLC(NitroModules.applicationContext ?: throw Error("No Context available!"))
|
val ctx = NitroModules.applicationContext ?: throw Error("No Context available!")
|
||||||
}
|
val player = MPVLib.create(ctx) ?: throw Error("Failed to initialize MPVLib")
|
||||||
|
override val eventMap = EventMap(player)
|
||||||
|
|
||||||
class OmniPlayer() : HybridOmniPlayerSpec() {
|
init {
|
||||||
val player = MediaPlayer(VlcConst.vlc)
|
player.setOptionString("vo", "gpu")
|
||||||
override val eventMap = EventMap(player);
|
player.setOptionString("gpu-context", "android")
|
||||||
|
player.setOptionString("opengl-es", "yes")
|
||||||
|
player.setOptionString("hwdec", "mediacodec-copy")
|
||||||
|
player.setOptionString("profile", "fast")
|
||||||
|
|
||||||
|
player.setOptionString("cache", "yes")
|
||||||
|
player.setOptionString("cache-pause-initial", "yes")
|
||||||
|
player.setOptionString("demuxer-max-bytes", "150MiB")
|
||||||
|
player.setOptionString("demuxer-max-back-bytes", "75MiB")
|
||||||
|
player.setOptionString("demuxer-readahead-secs", "20")
|
||||||
|
|
||||||
|
// seek to keyframes
|
||||||
|
player.setOptionString("hr-seek", "no")
|
||||||
|
|
||||||
|
player.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
super.dispose()
|
||||||
|
|
||||||
|
player.detachSurface()
|
||||||
|
eventMap.dispose()
|
||||||
|
player.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
override var source: Source by deferredObservable { _, _, new ->
|
override var source: Source by deferredObservable { _, _, new ->
|
||||||
val src = new.src.firstOrNull()?.uri ?: return@deferredObservable
|
player.command(arrayOf("stop"))
|
||||||
player.media = Media(VlcConst.vlc, Uri.parse(src))
|
|
||||||
|
val src = new.src.firstOrNull() ?: return@deferredObservable
|
||||||
|
|
||||||
|
player.setPropertyString(
|
||||||
|
"http-header-fields",
|
||||||
|
src.headers.entries.joinToString("\r\n") { "${it.key}: ${it.value}" }
|
||||||
|
)
|
||||||
new.startTime?.let { start ->
|
new.startTime?.let { start ->
|
||||||
player.time = (start * 1000.0).toLong().coerceAtLeast(0L)
|
player.setPropertyDouble("start", start.coerceAtLeast(0.0))
|
||||||
|
}
|
||||||
|
// TODO: set video/audio/sub specified
|
||||||
|
player.command(arrayOf("loadfile", src.uri, "replace"))
|
||||||
|
for (subtitle in new.subtitles) {
|
||||||
|
player.command(arrayOf("sub-add", subtitle.link, "cached"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSurface(surface: android.view.Surface?) {
|
||||||
|
if (surface == null) {
|
||||||
|
player.detachSurface()
|
||||||
|
} else {
|
||||||
|
player.attachSurface(surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val hasPrev get() = source.metadata?.hasPrev ?: false
|
override val hasPrev get() = source.metadata?.hasPrev ?: false
|
||||||
override val hasNext get() = source.metadata?.hasNext ?: false
|
override val hasNext get() = source.metadata?.hasNext ?: false
|
||||||
override val status
|
override val status: PlayerStatus
|
||||||
get() = when (player.playerState) {
|
get() {
|
||||||
IMedia.State.NothingSpecial -> PlayerStatus.IDLE
|
val idle = player.getPropertyBoolean("core-idle") ?: false
|
||||||
IMedia.State.Opening -> PlayerStatus.LOADING
|
val loading = player.getPropertyBoolean("paused-for-cache") ?: false
|
||||||
IMedia.State.Playing -> PlayerStatus.READYTOPLAY
|
return when {
|
||||||
IMedia.State.Paused -> PlayerStatus.READYTOPLAY
|
idle -> PlayerStatus.IDLE
|
||||||
IMedia.State.Stopped -> PlayerStatus.IDLE
|
loading -> PlayerStatus.LOADING
|
||||||
IMedia.State.Ended -> PlayerStatus.IDLE
|
else -> PlayerStatus.READYTOPLAY
|
||||||
IMedia.State.Error -> PlayerStatus.ERROR
|
}
|
||||||
else -> PlayerStatus.ERROR
|
}
|
||||||
}
|
override val isPlaying get() = !(player.getPropertyBoolean("pause") ?: true)
|
||||||
override val isPlaying: Boolean get() = player.isPlaying
|
override var currentTime
|
||||||
override var currentTime: Double
|
get() = (player.getPropertyDouble("time-pos") ?: 0.0).coerceAtLeast(0.0)
|
||||||
get() = player.time.coerceAtLeast(0L) / 1000.0
|
set(value) {
|
||||||
set(value) {
|
player.command(arrayOf("seek", value.coerceAtLeast(0.0).toString(), "absolute"))
|
||||||
player.time = (value * 1000.0).toLong().coerceAtLeast(0L)
|
}
|
||||||
}
|
override val buffered get() = (player.getPropertyDouble("demuxer-cache-time") ?: 0.0).coerceAtLeast(0.0)
|
||||||
override val buffered: Double
|
override val duration get() = (player.getPropertyDouble("duration") ?: 0.0).coerceAtLeast(0.0)
|
||||||
get() {
|
|
||||||
val total = duration
|
|
||||||
if (total <= 0.0) return 0.0
|
|
||||||
return (total * player.position.toDouble()).coerceIn(0.0, total)
|
|
||||||
}
|
|
||||||
override val duration: Double get() = player.length.coerceAtLeast(0L) / 1000.0
|
|
||||||
override var playbackRate: Double
|
|
||||||
get() = player.rate.toDouble()
|
|
||||||
set(value) {
|
|
||||||
if (value > 0.0) player.rate = value.toFloat()
|
|
||||||
}
|
|
||||||
override var volume: Double
|
|
||||||
get() = (player.volume.coerceIn(0, 100) / 100.0)
|
|
||||||
set(value) {
|
|
||||||
player.volume = (value.coerceIn(0.0, 1.0) * 100.0).toInt()
|
|
||||||
}
|
|
||||||
override val videos get() = getTracks(IMedia.Track.Type.Video)
|
|
||||||
override val audios get() = getTracks(IMedia.Track.Type.Audio)
|
|
||||||
override val subtitles get() = getTracks(IMedia.Track.Type.Text)
|
|
||||||
|
|
||||||
fun getTracks(type: Int): Array<Track> {
|
override var playbackRate
|
||||||
val tracks = player.getTracks(type)
|
get() = player.getPropertyDouble("speed") ?: 1.0
|
||||||
val selected = player.getSelectedTrack(type)
|
set(value) {
|
||||||
return tracks.map {
|
player.setPropertyDouble("speed", value.coerceAtLeast(0.0))
|
||||||
Track(
|
}
|
||||||
id = it.id,
|
|
||||||
label = it.name,
|
|
||||||
language = it.language,
|
|
||||||
selected = it.id == selected.id
|
|
||||||
)
|
|
||||||
}.toTypedArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
override var muted
|
||||||
|
get() = player.getPropertyBoolean("muted") ?: false
|
||||||
|
set(value) {
|
||||||
|
player.setPropertyBoolean("muted", value)
|
||||||
|
}
|
||||||
|
override var volume
|
||||||
|
get() = (player.getPropertyDouble("volume") ?: 100.0).coerceIn(0.0, 100.0) / 100.0
|
||||||
|
set(value) {
|
||||||
|
player.setPropertyDouble("volume", value.coerceIn(0.0, 1.0) * 100.0)
|
||||||
|
}
|
||||||
|
override val videos get() = getTracks("video")
|
||||||
|
override val audios get() = getTracks("audio")
|
||||||
|
override val subtitles get() = getTracks("sub")
|
||||||
|
|
||||||
|
// TODO: use `edition-list`
|
||||||
override val rendition: Array<Rendition> get() = emptyArray()
|
override val rendition: Array<Rendition> get() = emptyArray()
|
||||||
|
|
||||||
override fun play() {
|
override fun play() {
|
||||||
player.play()
|
player.setPropertyBoolean("pause", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pause() {
|
override fun pause() {
|
||||||
player.pause()
|
player.setPropertyBoolean("pause", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun seekBy(offset: Double) {
|
override fun seekBy(offset: Double) {
|
||||||
currentTime += offset
|
player.command(arrayOf("seek", offset.toString(), "relative"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun playPrev() {
|
override fun playPrev() {
|
||||||
@@ -105,22 +132,56 @@ class OmniPlayer() : HybridOmniPlayerSpec() {
|
|||||||
// App-level action; no default implementation in VLC player.
|
// App-level action; no default implementation in VLC player.
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun selectVideo(video: Track) {
|
override fun selectVideo(video: Track) {
|
||||||
player.selectTrack(video.id)
|
val id = video.id.toIntOrNull() ?: return
|
||||||
}
|
player.setPropertyInt("vid", id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun selectAudio(audio: Track) {
|
override fun selectAudio(audio: Track) {
|
||||||
player.selectTrack(audio.id)
|
val id = audio.id.toIntOrNull() ?: return
|
||||||
}
|
player.setPropertyInt("aid", id)
|
||||||
|
}
|
||||||
|
|
||||||
override fun selectSubtitle(subtitle: Track?) {
|
override fun selectSubtitle(subtitle: Track?) {
|
||||||
when (subtitle) {
|
when (subtitle) {
|
||||||
null -> player.unselectTrackType(IMedia.Track.Type.Text)
|
null -> player.setPropertyString("sid", "no")
|
||||||
else -> player.selectTrack(subtitle.id)
|
else -> {
|
||||||
}
|
val id = subtitle.id.toIntOrNull() ?: return
|
||||||
}
|
player.setPropertyInt("sid", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun selectRendition(rendition: Rendition?) {
|
override fun selectRendition(rendition: Rendition?) {
|
||||||
// Not supported by libVLC MediaPlayer track APIs.
|
// Not supported by libVLC MediaPlayer track APIs.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getTracks(type: String): Array<Track> {
|
||||||
|
val count = player.getPropertyInt("track-list/count") ?: 0
|
||||||
|
if (count <= 0) return emptyArray()
|
||||||
|
|
||||||
|
val tracks = ArrayList<Track>(count)
|
||||||
|
for (i in 0 until count) {
|
||||||
|
val base = "track-list/$i"
|
||||||
|
val trackType = player.getPropertyString("$base/type") ?: continue
|
||||||
|
if (trackType != type) continue
|
||||||
|
|
||||||
|
val id = player.getPropertyInt("$base/id") ?: continue
|
||||||
|
val selected = player.getPropertyBoolean("$base/selected") ?: false
|
||||||
|
val label = player.getPropertyString("$base/title")
|
||||||
|
?: player.getPropertyString("$base/codec")
|
||||||
|
val language = player.getPropertyString("$base/lang")
|
||||||
|
|
||||||
|
tracks.add(
|
||||||
|
Track(
|
||||||
|
id = id.toString(),
|
||||||
|
label = label,
|
||||||
|
language = language,
|
||||||
|
selected = selected
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tracks.toTypedArray()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package dev.zoriya.omni
|
|||||||
|
|
||||||
import com.facebook.react.uimanager.ThemedReactContext
|
import com.facebook.react.uimanager.ThemedReactContext
|
||||||
import com.margelo.nitro.omni.HybridOmniPlayerFactorySpec
|
import com.margelo.nitro.omni.HybridOmniPlayerFactorySpec
|
||||||
import com.margelo.nitro.omni.HybridOmniPlayerPropsSpec
|
|
||||||
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
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: HybridOmniPlayerPropsSpec): HybridOmniPlayerSpec {
|
override fun createPlayer(props: Source): HybridOmniPlayerSpec {
|
||||||
return OmniPlayer().apply {
|
return OmniPlayer().apply {
|
||||||
source = props
|
source = props
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,43 @@
|
|||||||
package dev.zoriya.omni
|
package dev.zoriya.omni
|
||||||
|
|
||||||
|
import android.view.SurfaceHolder
|
||||||
|
import android.view.SurfaceView
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.facebook.react.uimanager.ThemedReactContext
|
import com.facebook.react.uimanager.ThemedReactContext
|
||||||
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
import com.margelo.nitro.omni.HybridOmniPlayerSpec
|
||||||
import com.margelo.nitro.omni.HybridOmniViewSpec
|
import com.margelo.nitro.omni.HybridOmniViewSpec
|
||||||
import org.videolan.libvlc.util.VLCVideoLayout
|
|
||||||
|
|
||||||
class OmniView(val context: ThemedReactContext) : HybridOmniViewSpec() {
|
class OmniView(val context: ThemedReactContext) : HybridOmniViewSpec() {
|
||||||
private val videoLayout = VLCVideoLayout(context)
|
private val surfaceView = SurfaceView(context)
|
||||||
private var viewsAttached = false
|
private var surfaceReady = false
|
||||||
private var boundPlayer: OmniPlayer? = null
|
private var boundPlayer: OmniPlayer? = null
|
||||||
|
|
||||||
override val view: View = videoLayout
|
override val view: View = surfaceView
|
||||||
|
|
||||||
override lateinit var player: HybridOmniPlayerSpec
|
override lateinit var player: HybridOmniPlayerSpec
|
||||||
override var autoplay: Boolean? = true
|
override var autoplay: Boolean? = true
|
||||||
override var showNotification: Boolean? = true
|
override var showNotification: Boolean? = true
|
||||||
override var autoPip: Boolean? = true
|
override var autoPip: Boolean? = true
|
||||||
|
|
||||||
|
init {
|
||||||
|
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
|
||||||
|
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||||
|
surfaceReady = true
|
||||||
|
boundPlayer?.setSurface(holder.surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
|
||||||
|
surfaceReady = true
|
||||||
|
boundPlayer?.setSurface(holder.surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||||
|
surfaceReady = false
|
||||||
|
boundPlayer?.setSurface(null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
override fun afterUpdate() {
|
override fun afterUpdate() {
|
||||||
if (!::player.isInitialized) {
|
if (!::player.isInitialized) {
|
||||||
throw IllegalStateException("Player is null in OmniView")
|
throw IllegalStateException("Player is null in OmniView")
|
||||||
@@ -25,17 +45,14 @@ class OmniView(val context: ThemedReactContext) : HybridOmniViewSpec() {
|
|||||||
|
|
||||||
val omniPlayer = player as? OmniPlayer
|
val omniPlayer = player as? OmniPlayer
|
||||||
?: throw IllegalStateException("Player is not an OmniPlayer in OmniView")
|
?: throw IllegalStateException("Player is not an OmniPlayer in OmniView")
|
||||||
val vout = omniPlayer.player.vlcVout
|
|
||||||
|
|
||||||
if (boundPlayer !== omniPlayer) {
|
if (boundPlayer !== omniPlayer) {
|
||||||
boundPlayer?.player?.detachViews()
|
boundPlayer?.setSurface(null)
|
||||||
viewsAttached = false
|
|
||||||
boundPlayer = omniPlayer
|
boundPlayer = omniPlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!viewsAttached || !vout.areViewsAttached()) {
|
if (surfaceReady) {
|
||||||
omniPlayer.player.attachViews(videoLayout, null, false, false)
|
omniPlayer.setSurface(surfaceView.holder.surface)
|
||||||
viewsAttached = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoplay == true && !omniPlayer.isPlaying) {
|
if (autoplay == true && !omniPlayer.isPlaying) {
|
||||||
@@ -47,11 +64,7 @@ class OmniView(val context: ThemedReactContext) : HybridOmniViewSpec() {
|
|||||||
if (!::player.isInitialized) return
|
if (!::player.isInitialized) return
|
||||||
|
|
||||||
val omniPlayer = player as? OmniPlayer ?: return
|
val omniPlayer = player as? OmniPlayer ?: return
|
||||||
val vout = omniPlayer.player.vlcVout
|
omniPlayer.setSurface(null)
|
||||||
if (vout.areViewsAttached()) {
|
|
||||||
omniPlayer.player.detachViews()
|
|
||||||
}
|
|
||||||
viewsAttached = false
|
|
||||||
boundPlayer = null
|
boundPlayer = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ inline fun <T : Any> deferredObservable(
|
|||||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||||
val old = this.value
|
val old = this.value
|
||||||
this.value = value
|
this.value = value
|
||||||
onChange(old, value)
|
onChange(thisRef, old, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
buildToolsVersion = "36.0.0"
|
buildToolsVersion = "36.0.0"
|
||||||
minSdkVersion = 24
|
minSdkVersion = 26
|
||||||
compileSdkVersion = 36
|
compileSdkVersion = 36
|
||||||
targetSdkVersion = 36
|
targetSdkVersion = 36
|
||||||
ndkVersion = "27.1.12297006"
|
ndkVersion = "27.1.12297006"
|
||||||
|
|||||||
@@ -207,6 +207,15 @@ namespace margelo::nitro::omni {
|
|||||||
static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* volume */)>("setVolume");
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* volume */)>("setVolume");
|
||||||
method(_javaPart, volume);
|
method(_javaPart, volume);
|
||||||
}
|
}
|
||||||
|
bool JHybridOmniPlayerSpec::getMuted() {
|
||||||
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>("getMuted");
|
||||||
|
auto __result = method(_javaPart);
|
||||||
|
return static_cast<bool>(__result);
|
||||||
|
}
|
||||||
|
void JHybridOmniPlayerSpec::setMuted(bool muted) {
|
||||||
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jboolean /* muted */)>("setMuted");
|
||||||
|
method(_javaPart, muted);
|
||||||
|
}
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
void JHybridOmniPlayerSpec::play() {
|
void JHybridOmniPlayerSpec::play() {
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ namespace margelo::nitro::omni {
|
|||||||
void setPlaybackRate(double playbackRate) override;
|
void setPlaybackRate(double playbackRate) override;
|
||||||
double getVolume() override;
|
double getVolume() override;
|
||||||
void setVolume(double volume) override;
|
void setVolume(double volume) override;
|
||||||
|
bool getMuted() override;
|
||||||
|
void setMuted(bool muted) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Methods
|
// Methods
|
||||||
|
|||||||
+6
@@ -92,6 +92,12 @@ abstract class HybridOmniPlayerSpec: HybridObject() {
|
|||||||
@set:DoNotStrip
|
@set:DoNotStrip
|
||||||
@set:Keep
|
@set:Keep
|
||||||
abstract var volume: Double
|
abstract var volume: Double
|
||||||
|
|
||||||
|
@get:DoNotStrip
|
||||||
|
@get:Keep
|
||||||
|
@set:DoNotStrip
|
||||||
|
@set:Keep
|
||||||
|
abstract var muted: Boolean
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
@DoNotStrip
|
@DoNotStrip
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ namespace margelo::nitro::omni {
|
|||||||
prototype.registerHybridSetter("playbackRate", &HybridOmniPlayerSpec::setPlaybackRate);
|
prototype.registerHybridSetter("playbackRate", &HybridOmniPlayerSpec::setPlaybackRate);
|
||||||
prototype.registerHybridGetter("volume", &HybridOmniPlayerSpec::getVolume);
|
prototype.registerHybridGetter("volume", &HybridOmniPlayerSpec::getVolume);
|
||||||
prototype.registerHybridSetter("volume", &HybridOmniPlayerSpec::setVolume);
|
prototype.registerHybridSetter("volume", &HybridOmniPlayerSpec::setVolume);
|
||||||
|
prototype.registerHybridGetter("muted", &HybridOmniPlayerSpec::getMuted);
|
||||||
|
prototype.registerHybridSetter("muted", &HybridOmniPlayerSpec::setMuted);
|
||||||
prototype.registerHybridMethod("play", &HybridOmniPlayerSpec::play);
|
prototype.registerHybridMethod("play", &HybridOmniPlayerSpec::play);
|
||||||
prototype.registerHybridMethod("pause", &HybridOmniPlayerSpec::pause);
|
prototype.registerHybridMethod("pause", &HybridOmniPlayerSpec::pause);
|
||||||
prototype.registerHybridMethod("seekBy", &HybridOmniPlayerSpec::seekBy);
|
prototype.registerHybridMethod("seekBy", &HybridOmniPlayerSpec::seekBy);
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ namespace margelo::nitro::omni {
|
|||||||
virtual void setPlaybackRate(double playbackRate) = 0;
|
virtual void setPlaybackRate(double playbackRate) = 0;
|
||||||
virtual double getVolume() = 0;
|
virtual double getVolume() = 0;
|
||||||
virtual void setVolume(double volume) = 0;
|
virtual void setVolume(double volume) = 0;
|
||||||
|
virtual bool getMuted() = 0;
|
||||||
|
virtual void setMuted(bool muted) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Methods
|
// Methods
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ in
|
|||||||
nodejs
|
nodejs
|
||||||
biome
|
biome
|
||||||
jdk
|
jdk
|
||||||
((android-studio.withSdk android.androidsdk).overrideAttrs {forceWayland = true;})
|
((android-studio.override {forceWayland = true;}).withSdk android.androidsdk)
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import type { HybridObject } from "react-native-nitro-modules";
|
import type { HybridObject } from "react-native-nitro-modules";
|
||||||
import type { OmniEvents } from "../types/events";
|
import type { OmniEvents } from "../types/events";
|
||||||
import type {
|
import type {
|
||||||
OmniPlayerState,
|
// OmniPlayerState,
|
||||||
OmniPlayer as OmniPlayerT,
|
OmniPlayer as OmniPlayerT,
|
||||||
} from "../types/player";
|
} from "../types/player";
|
||||||
import type { Source } from "../types/source";
|
import type { Source } from "../types/source";
|
||||||
|
|
||||||
export interface OmniEventMap extends HybridObject<{ android: "kotlin" }> {
|
export interface OmniEventMap extends HybridObject<{ android: "kotlin" }> {
|
||||||
addStateListener(
|
// addStateListener(
|
||||||
key: keyof OmniPlayerState,
|
// key: keyof OmniPlayerState,
|
||||||
cb: (value: number) => void,
|
// cb: (value: number) => void,
|
||||||
): void;
|
// ): void;
|
||||||
removeStateListener(cb: OmniEvents["end"]): void;
|
// removeStateListener(cb: OmniEvents["end"]): void;
|
||||||
|
|
||||||
addOnEndListener(cb: OmniEvents["end"]): void;
|
addOnEndListener(cb: OmniEvents["end"]): void;
|
||||||
removeOnEndListener(cb: OmniEvents["end"]): void;
|
removeOnEndListener(cb: OmniEvents["end"]): void;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export interface OmniPlayerState {
|
|||||||
playbackRate: number;
|
playbackRate: number;
|
||||||
// between 0 and 1
|
// between 0 and 1
|
||||||
volume: number;
|
volume: number;
|
||||||
|
muted: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlayerStatus = "idle" | "loading" | "readyToPlay" | "error";
|
export type PlayerStatus = "idle" | "loading" | "readyToPlay" | "error";
|
||||||
|
|||||||
Reference in New Issue
Block a user