expo-libmpv 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/libmpv/LibmpvModule.kt +15 -0
  3. package/android/src/main/java/com/libmpv/{LibmpvVideoView.kt → LibmpvView.kt} +95 -125
  4. package/android/src/main/java/com/libmpv/{LibmpvVideoModule.kt → LibmpvViewModule.kt} +18 -15
  5. package/android/src/main/java/com/libmpv/LibmpvWrapper.kt +148 -193
  6. package/build/Libmpv.d.ts +5 -0
  7. package/build/Libmpv.d.ts.map +1 -0
  8. package/build/Libmpv.js +4 -0
  9. package/build/Libmpv.js.map +1 -0
  10. package/build/LibmpvView.d.ts +5 -0
  11. package/build/LibmpvView.d.ts.map +1 -0
  12. package/build/{LibmpvVideoView.js → LibmpvView.js} +5 -5
  13. package/build/LibmpvView.js.map +1 -0
  14. package/build/{LibmpvVideo.types.d.ts → LibmpvViewTypes.d.ts} +3 -3
  15. package/build/LibmpvViewTypes.d.ts.map +1 -0
  16. package/build/LibmpvViewTypes.js +2 -0
  17. package/build/LibmpvViewTypes.js.map +1 -0
  18. package/build/index.d.ts +12 -2
  19. package/build/index.d.ts.map +1 -1
  20. package/build/index.js +11 -2
  21. package/build/index.js.map +1 -1
  22. package/expo-module.config.json +2 -1
  23. package/package.json +1 -1
  24. package/src/Libmpv.tsx +7 -0
  25. package/src/{LibmpvVideoView.tsx → LibmpvView.tsx} +5 -7
  26. package/src/{LibmpvVideo.types.ts → LibmpvViewTypes.ts} +2 -2
  27. package/src/index.ts +14 -2
  28. package/build/LibmpvVideo.types.d.ts.map +0 -1
  29. package/build/LibmpvVideo.types.js +0 -2
  30. package/build/LibmpvVideo.types.js.map +0 -1
  31. package/build/LibmpvVideoView.d.ts +0 -5
  32. package/build/LibmpvVideoView.d.ts.map +0 -1
  33. package/build/LibmpvVideoView.js.map +0 -1
@@ -36,7 +36,7 @@ if (useManagedAndroidSdkVersions) {
36
36
  }
37
37
 
38
38
  dependencies {
39
- implementation "com.libmpv:android-libmpv:0.5.10"
39
+ implementation "com.libmpv:android-libmpv:0.6.2"
40
40
  }
41
41
 
42
42
  android {
@@ -0,0 +1,15 @@
1
+ package com.libmpv
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class LibmpvModule : Module() {
7
+ override fun definition() = ModuleDefinition {
8
+ Name("Libmpv")
9
+
10
+ AsyncFunction("getProperty") { viewTag: Int, name: String ->
11
+ val view = appContext.findView<LibmpvView>(viewTag)
12
+ view?.getProperty(name)
13
+ }
14
+ }
15
+ }
@@ -12,9 +12,10 @@ import dev.jdtech.mpv.MPVLib
12
12
  import expo.modules.kotlin.AppContext
13
13
  import expo.modules.kotlin.views.ExpoView
14
14
  import expo.modules.kotlin.viewevent.EventDispatcher
15
+ import kotlinx.coroutines.runBlocking
15
16
 
16
- class LibmpvVideoView(context: Context, appContext: AppContext) :
17
- ExpoView(context,appContext),
17
+ class LibmpvView(context: Context, appContext: AppContext) :
18
+ ExpoView(context, appContext),
18
19
  SurfaceHolder.Callback,
19
20
  MPVLib.LogObserver,
20
21
  MPVLib.EventObserver {
@@ -27,7 +28,10 @@ class LibmpvVideoView(context: Context, appContext: AppContext) :
27
28
  private val onLibmpvLog by EventDispatcher()
28
29
  private val onLibmpvEvent by EventDispatcher()
29
30
 
30
- private var isSurfaceCreated: Boolean = false
31
+ @Volatile private var isSurfaceCreated = false
32
+ @Volatile private var cleaning = false
33
+ private val mainHandler = Handler(Looper.getMainLooper())
34
+
31
35
  val mpv: LibmpvWrapper = LibmpvWrapper(context)
32
36
  private val surfaceView: SurfaceView = SurfaceView(context)
33
37
 
@@ -38,77 +42,82 @@ class LibmpvVideoView(context: Context, appContext: AppContext) :
38
42
  var audioIndex: Int? = null
39
43
  var subtitleIndex: Int? = null
40
44
  var useHardwareDecoder: Boolean? = null
45
+ var seekToSeconds: Int? = null
41
46
 
42
47
  init {
43
48
  surfaceView.holder.addCallback(this)
44
49
  val layoutParams = FrameLayout.LayoutParams(
45
- FrameLayout.LayoutParams.MATCH_PARENT,
46
- FrameLayout.LayoutParams.MATCH_PARENT
50
+ FrameLayout.LayoutParams.MATCH_PARENT,
51
+ FrameLayout.LayoutParams.MATCH_PARENT
47
52
  )
48
- appContext.activityProvider?.currentActivity?.let { activity ->
49
- if (activity is androidx.lifecycle.LifecycleOwner) {
50
- activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
51
- override fun onDestroy(owner: LifecycleOwner) {
52
- log("LibmpvVideoView", "Lifecycle onDestroy -> cleanup()")
53
- cleanup()
54
- }
55
- })
53
+
54
+ appContext.activityProvider?.currentActivity?.let { activity ->
55
+ if (activity is androidx.lifecycle.LifecycleOwner) {
56
+ activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
57
+ override fun onDestroy(owner: LifecycleOwner) {
58
+ log("LibmpvView", "Lifecycle onDestroy -> cleanup()")
59
+ cleanup()
60
+ }
61
+ })
62
+ }
56
63
  }
57
- }
58
64
 
59
65
  addView(surfaceView, layoutParams)
60
66
  }
61
67
 
62
68
  fun isSurfaceReady(): Boolean = isSurfaceCreated
63
69
 
64
- fun attemptCreation(){
65
- val allPropsReady = playUrl != null &&
66
- surfaceWidth != null &&
67
- surfaceHeight != null &&
68
- audioIndex != null &&
69
- subtitleIndex != null &&
70
- useHardwareDecoder != null
71
-
72
- if (allPropsReady) {
73
- log("LibmpvVideoView.attemptCreation", "Initializing MPV instance")
74
- createNativePlayer()
75
- } else {
76
- log("LibmpvVideoView.attemptCreation", "attemptCreation wasn't ready")
77
- }
70
+ fun attemptCreation() {
71
+ val allPropsReady = playUrl != null &&
72
+ surfaceWidth != null &&
73
+ surfaceHeight != null &&
74
+ audioIndex != null &&
75
+ subtitleIndex != null &&
76
+ useHardwareDecoder != null
77
+
78
+ if (allPropsReady) {
79
+ log("LibmpvView.attemptCreation", "Initializing MPV instance")
80
+ createNativePlayer()
81
+ } else {
82
+ log("LibmpvView.attemptCreation", "attemptCreation wasn't ready")
83
+ }
78
84
  }
79
85
 
80
86
  fun createNativePlayer() {
81
87
  mpv.create()
82
88
  prepareMpvSettings()
83
- log("LibmpvVideoView.createNativePlayer", "mpv settings prepared. Waiting on surface creation.")
89
+ log("LibmpvView.createNativePlayer", "mpv settings prepared. Waiting on surface creation.")
84
90
  }
85
91
 
86
- fun runCommand(orders: String){
92
+ fun runCommand(orders: String) {
87
93
  mpv.command(orders.split("|").toTypedArray())
88
94
  }
89
95
 
90
- fun setOptionString(options: String){
96
+ fun setOptionString(options: String) {
91
97
  val parts = options.split("|").toTypedArray()
92
- mpv.setOptionString(parts[0],parts[1])
98
+ if (parts.size == 2) mpv.setOptionString(parts[0], parts[1])
99
+ }
100
+
101
+ fun getProperty(name: String): String? {
102
+ return runBlocking { mpv.getProperty(name) }
93
103
  }
94
104
 
95
105
  private fun prepareMpvSettings() {
96
106
  mpv.addLogObserver(this)
97
107
  mpv.addEventObserver(this)
98
- mpv.setOptionString("force-window", "no")
99
108
 
109
+ mpv.setOptionString("force-window", "no")
100
110
  mpv.setOptionString("config", "yes")
101
- val mpvDir = mpv.getMpvDirectoryPath()
102
- mpvDir?.let{
103
- mpv.setOptionString("config-dir", mpvDir)
104
- mpv.setOptionString("sub-font-dir", mpvDir)
111
+
112
+ mpv.getMpvDirectoryPath()?.let { dir ->
113
+ mpv.setOptionString("config-dir", dir)
114
+ mpv.setOptionString("sub-font-dir", dir)
105
115
  }
106
116
 
107
117
  mpv.setOptionString("keep-open", "always")
108
118
  mpv.setOptionString("save-position-on-quit", "no")
109
119
  mpv.setOptionString("ytdl", "no")
110
120
  mpv.setOptionString("msg-level", "all=no")
111
-
112
121
  mpv.setOptionString("profile", "fast")
113
122
  mpv.setOptionString("vo", "gpu-next")
114
123
 
@@ -122,19 +131,15 @@ class LibmpvVideoView(context: Context, appContext: AppContext) :
122
131
  mpv.setOptionString("gpu-context", "android")
123
132
  mpv.setOptionString("opengl-es", "yes")
124
133
  mpv.setOptionString("video-sync", "audio")
125
-
126
- mpv.setOptionString("audio-samplerate","48000")
127
- mpv.setOptionString("audio-format","float")
128
- mpv.setOptionString("audio-buffer","2.0")
129
-
134
+ mpv.setOptionString("audio-samplerate", "48000")
135
+ mpv.setOptionString("audio-format", "float")
136
+ mpv.setOptionString("audio-buffer", "2.0")
130
137
  mpv.setOptionString("ao", "audiotrack")
131
138
  mpv.setOptionString("alang", "")
132
-
133
139
  mpv.setOptionString("sub-font-provider", "none")
134
140
  mpv.setOptionString("slang", "")
135
141
  mpv.setOptionString("sub-scale-with-window", "yes")
136
142
  mpv.setOptionString("sub-use-margins", "no")
137
-
138
143
  mpv.setOptionString("cache", "yes")
139
144
  mpv.setOptionString("cache-pause-initial", "yes")
140
145
  mpv.setOptionString("cache-secs", "5")
@@ -142,45 +147,34 @@ class LibmpvVideoView(context: Context, appContext: AppContext) :
142
147
  }
143
148
 
144
149
  fun log(method: String, argument: String) {
145
- onLibmpvLog(mapOf(
146
- "method" to method,
147
- "argument" to argument
148
- ))
150
+ onLibmpvLog(mapOf("method" to method, "argument" to argument))
149
151
  }
150
152
 
151
153
  override fun surfaceCreated(holder: SurfaceHolder) {
152
- val width = surfaceWidth ?: 0
153
- val height = surfaceHeight ?: 0
154
- // In the new Fabric version, this is stretching the content
155
- //holder.setFixedSize(width, height)
156
- //mpv.setPropertyString("android-surface-size", "${width}x${height}")
157
154
  mpv.attachSurface(surfaceView)
158
155
  prepareMpvPlayback()
159
156
  isSurfaceCreated = true
160
- log("LibmpvVideoView.surfaceCreated", "Surface created and MPV should be playing")
157
+ log("LibmpvView.surfaceCreated", "Surface created and MPV attached")
161
158
  }
162
159
 
163
160
  private fun prepareMpvPlayback() {
164
161
  mpv.init()
165
162
  mpv.setOptionString("force-window", "yes")
166
- var options = "vid=1"
167
- options += if (audioIndex == -1) {
168
- ",aid=no"
169
- } else {
170
- ",aid=${(audioIndex ?: 0) + 1}"
171
- }
172
- options += if (subtitleIndex == -1) {
173
- ",sid=no"
174
- } else {
175
- ",sid=${(subtitleIndex ?: 0) + 1}"
163
+
164
+ val aid = if (audioIndex == -1) "aid=no" else "aid=${(audioIndex ?: 0) + 1}"
165
+ val sid = if (subtitleIndex == -1) "sid=no" else "sid=${(subtitleIndex ?: 0) + 1}"
166
+ val opts = "vid=1,$aid,$sid"
167
+ val url = playUrl ?: ""
168
+ mpv.play(url, opts)
169
+ if (seekToSeconds != null && seekToSeconds!! > 0) {
170
+ mpv.seekToSeconds(seekToSeconds!!)
171
+ log("LibmpvView.prepareMpvPlayback", "Applied initial seek to $seekToSeconds")
176
172
  }
177
- val url: String = (playUrl as? String) ?: ""
178
- mpv.play(url, options)
179
173
  }
180
174
 
181
175
  fun setHardwareDecoder(useHardware: Boolean) {
182
176
  useHardwareDecoder = useHardware
183
- if (useHardwareDecoder == true) {
177
+ if (useHardware) {
184
178
  mpv.setOptionString("hwdec", HARDWARE_OPTIONS)
185
179
  mpv.setOptionString("hwdec-codecs", ACCELERATED_CODECS)
186
180
  } else {
@@ -190,90 +184,66 @@ class LibmpvVideoView(context: Context, appContext: AppContext) :
190
184
 
191
185
  override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
192
186
 
193
- fun cleanup() {
194
- // Launch on background executor so UI returns immediately
195
- Thread {
196
- try {
197
- try { mpv.setPropertyString("pause", "yes") } catch (_: Throwable) {}
198
- try { mpv.setPropertyString("ao", "null") } catch (_: Throwable) {}
199
- Handler(Looper.getMainLooper()).post {
200
- try {
201
- surfaceView.holder.removeCallback(this@LibmpvVideoView)
202
- mpv.cleanup()
203
- } catch (e: Exception) {
187
+ fun cleanup() {
188
+ if (cleaning) return
189
+ cleaning = true
190
+ Thread {
191
+ try {
192
+ runCatching { mpv.setPropertyString("pause", "yes") }
193
+ runCatching { mpv.setPropertyString("ao", "null") }
194
+
195
+ mainHandler.post {
196
+ try {
197
+ surfaceView.holder.removeCallback(this@LibmpvView)
198
+ mpv.cleanup()
199
+ } catch (_: Exception) {}
200
+ cleaning = false
204
201
  }
205
- }
206
- } catch (_: Throwable) {}
207
- }.start()
208
- }
202
+ } catch (_: Throwable) {}
203
+ }.start()
204
+ }
209
205
 
210
206
  override fun surfaceDestroyed(holder: SurfaceHolder) {
211
- try {
212
- mpv.setPropertyString("pause", "yes")
213
- mpv.setPropertyString("vo", "null")
214
- mpv.setPropertyString("force-window", "no")
215
- } catch (_: Throwable) {}
216
- try { mpv.detachSurface() } catch (_: Throwable) {}
207
+ runCatching { mpv.setPropertyString("pause", "yes") }
208
+ runCatching { mpv.setPropertyString("vo", "null") }
209
+ runCatching { mpv.setPropertyString("force-window", "no") }
210
+ runCatching { mpv.detachSurface() }
211
+ isSurfaceCreated = false
217
212
  }
218
213
 
219
- // MPVLib.LogObserver
220
214
  override fun logMessage(prefix: String, level: Int, text: String) {
221
- onLibmpvLog(mapOf(
222
- "prefix" to prefix,
223
- "level" to "$level",
224
- "text" to text
225
- ))
215
+ onLibmpvLog(mapOf("prefix" to prefix, "level" to "$level", "text" to text))
226
216
  }
227
217
 
228
- // MPVLib.EventObserver
229
218
  override fun eventProperty(property: String) {
230
- onLibmpvEvent(mapOf(
231
- "property" to property,
232
- "kind" to "none"
233
- ))
219
+ onLibmpvEvent(mapOf("property" to property, "kind" to "none"))
234
220
  }
235
221
 
236
222
  override fun eventProperty(property: String, value: Long) {
237
- onLibmpvEvent(mapOf(
238
- "property" to property,
239
- "kind" to "long",
240
- "value" to "$value"
241
- ))
223
+ onLibmpvEvent(mapOf("property" to property, "kind" to "long", "value" to "$value"))
242
224
  }
243
225
 
244
226
  override fun eventProperty(property: String, value: Double) {
245
- onLibmpvEvent(mapOf(
246
- "property" to property,
247
- "kind" to "double",
248
- "value" to "$value"
249
- ))
227
+ onLibmpvEvent(mapOf("property" to property, "kind" to "double", "value" to "$value"))
250
228
  }
251
229
 
252
230
  override fun eventProperty(property: String, value: Boolean) {
253
- onLibmpvEvent(mapOf(
254
- "property" to property,
255
- "kind" to "boolean",
256
- "value" to if (value) "true" else "false"
257
- ))
231
+ onLibmpvEvent(mapOf("property" to property, "kind" to "boolean", "value" to if (value) "true" else "false"))
258
232
  }
259
233
 
260
234
  override fun eventProperty(property: String, value: String) {
261
- onLibmpvEvent(mapOf(
262
- "property" to property,
263
- "kind" to "string",
264
- "value" to value
265
- ))
235
+ onLibmpvEvent(mapOf("property" to property, "kind" to "string", "value" to value))
266
236
  }
267
237
 
268
238
  override fun event(eventId: Int) {
269
- onLibmpvEvent(mapOf(
270
- "eventId" to "$eventId",
271
- "kind" to "eventId"
272
- ))
239
+ onLibmpvEvent(mapOf("eventId" to "$eventId", "kind" to "eventId"))
273
240
  }
274
241
 
275
242
  override fun onDetachedFromWindow() {
276
243
  super.onDetachedFromWindow()
277
- cleanup()
244
+ if (!cleaning) {
245
+ cleaning = true
246
+ cleanup()
247
+ }
278
248
  }
279
249
  }
@@ -3,25 +3,26 @@ package com.libmpv
3
3
  import expo.modules.kotlin.modules.Module
4
4
  import expo.modules.kotlin.modules.ModuleDefinition
5
5
 
6
- class LibmpvVideoModule : Module() {
6
+ class LibmpvViewModule : Module() {
7
7
  override fun definition() = ModuleDefinition {
8
- Name("LibmpvVideo")
9
- View(LibmpvVideoView::class) {
8
+ Name("LibmpvView")
9
+
10
+ View(LibmpvView::class) {
10
11
  Events("onLibmpvLog", "onLibmpvEvent")
11
12
 
12
- AsyncFunction("runCommand") { view: LibmpvVideoView, orders: String ->
13
+ AsyncFunction("runCommand") { view: LibmpvView, orders: String ->
13
14
  view.runCommand(orders)
14
15
  }
15
16
 
16
- AsyncFunction("setOptionString") { view: LibmpvVideoView, options: String ->
17
+ AsyncFunction("setOptionString") { view: LibmpvView, options: String ->
17
18
  view.setOptionString(options)
18
19
  }
19
20
 
20
- AsyncFunction("cleanup") { view: LibmpvVideoView ->
21
+ AsyncFunction("cleanup") { view: LibmpvView ->
21
22
  view.cleanup()
22
23
  }
23
24
 
24
- Prop("playUrl") { view: LibmpvVideoView, playUrl: String ->
25
+ Prop("playUrl") { view: LibmpvView, playUrl: String ->
25
26
  view.playUrl = playUrl
26
27
  if (view.isSurfaceReady()) {
27
28
  view.mpv.play(playUrl)
@@ -31,7 +32,7 @@ class LibmpvVideoModule : Module() {
31
32
  view.log("setPlayUrl", playUrl)
32
33
  }
33
34
 
34
- Prop("useHardwareDecoder") { view: LibmpvVideoView, useHardwareDecoder: Boolean ->
35
+ Prop("useHardwareDecoder") { view: LibmpvView, useHardwareDecoder: Boolean ->
35
36
  view.useHardwareDecoder = useHardwareDecoder
36
37
  if (view.isSurfaceReady()) {
37
38
  view.setHardwareDecoder(useHardwareDecoder)
@@ -41,7 +42,7 @@ class LibmpvVideoModule : Module() {
41
42
  view.log("setUseHardwareDecoder", "$useHardwareDecoder")
42
43
  }
43
44
 
44
- Prop("surfaceWidth") { view: LibmpvVideoView, surfaceWidth: Int ->
45
+ Prop("surfaceWidth") { view: LibmpvView, surfaceWidth: Int ->
45
46
  view.surfaceWidth = surfaceWidth
46
47
  if (view.isSurfaceReady()) {
47
48
  view.mpv.setSurfaceWidth(surfaceWidth)
@@ -51,7 +52,7 @@ class LibmpvVideoModule : Module() {
51
52
  view.log("setSurfaceWidth", "$surfaceWidth")
52
53
  }
53
54
 
54
- Prop("surfaceHeight") { view: LibmpvVideoView, surfaceHeight: Int ->
55
+ Prop("surfaceHeight") { view: LibmpvView, surfaceHeight: Int ->
55
56
  view.surfaceHeight = surfaceHeight
56
57
  if (view.isSurfaceReady()) {
57
58
  view.mpv.setSurfaceHeight(surfaceHeight)
@@ -61,7 +62,7 @@ class LibmpvVideoModule : Module() {
61
62
  view.log("setSurfaceHeight", "$surfaceHeight")
62
63
  }
63
64
 
64
- Prop("selectedAudioTrack") { view: LibmpvVideoView, audioTrackIndex: Int ->
65
+ Prop("selectedAudioTrack") { view: LibmpvView, audioTrackIndex: Int ->
65
66
  view.audioIndex = audioTrackIndex
66
67
  if (view.isSurfaceReady()) {
67
68
  val mpvIndex = if (audioTrackIndex != -1) (audioTrackIndex + 1).toString() else "no"
@@ -72,7 +73,7 @@ class LibmpvVideoModule : Module() {
72
73
  view.log("selectAudioTrack", "$audioTrackIndex")
73
74
  }
74
75
 
75
- Prop("selectedSubtitleTrack") { view: LibmpvVideoView, subtitleTrackIndex: Int ->
76
+ Prop("selectedSubtitleTrack") { view: LibmpvView, subtitleTrackIndex: Int ->
76
77
  view.subtitleIndex = subtitleTrackIndex
77
78
  if (view.isSurfaceReady()) {
78
79
  val mpvIndex = if (subtitleTrackIndex != -1) (subtitleTrackIndex + 1).toString() else "no"
@@ -83,14 +84,16 @@ class LibmpvVideoModule : Module() {
83
84
  view.log("selectSubtitleTrack", "$subtitleTrackIndex")
84
85
  }
85
86
 
86
- Prop("seekToSeconds") { view: LibmpvVideoView, seconds: Int ->
87
+ Prop("seekToSeconds") { view: LibmpvView, seconds: Int ->
87
88
  if (view.isSurfaceReady()) {
88
89
  view.mpv.seekToSeconds(seconds)
90
+ } else {
91
+ view.seekToSeconds = seconds
89
92
  }
90
93
  view.log("seekToSeconds", "$seconds")
91
94
  }
92
95
 
93
- Prop("isPlaying") { view: LibmpvVideoView, isPlaying: Boolean ->
96
+ Prop("isPlaying") { view: LibmpvView, isPlaying: Boolean ->
94
97
  if (view.isSurfaceReady() && view.mpv.hasPlayedOnce()) {
95
98
  when {
96
99
  isPlaying && !view.mpv.isPlaying() -> {
@@ -105,7 +108,7 @@ class LibmpvVideoModule : Module() {
105
108
  }
106
109
  }
107
110
 
108
- OnViewDestroys { view: LibmpvVideoView ->
111
+ OnViewDestroys { view: LibmpvView ->
109
112
  view.cleanup()
110
113
  }
111
114
  }
@@ -1,274 +1,229 @@
1
1
  package com.libmpv
2
2
 
3
+ import android.content.Context
3
4
  import android.os.Handler
4
5
  import android.os.Looper
5
- import android.content.Context
6
6
  import android.util.Log
7
7
  import android.view.SurfaceView
8
8
  import dev.jdtech.mpv.MPVLib
9
9
  import java.io.File
10
10
  import java.io.FileOutputStream
11
- import java.io.InputStream
12
- import java.io.OutputStream
11
+ import kotlinx.coroutines.suspendCancellableCoroutine
12
+ import kotlin.coroutines.resume
13
13
 
14
14
  class LibmpvWrapper(private val applicationContext: Context) {
15
15
  companion object {
16
16
  private const val TAG = "react-native-libmpv"
17
- private var swallow = true
18
17
  }
19
18
 
19
+ private enum class State { NEW, CREATED, INIT, RUNNING, CLEANUP, DESTROYED }
20
+
21
+ private val mainHandler = Handler(Looper.getMainLooper())
22
+ private val mpv = MPVLib()
23
+
20
24
  @Volatile private var created = false
21
- @Volatile private var destroying = false
22
- @Volatile private var isDestroyed = false
23
25
  @Volatile private var cleaning = false
26
+ @Volatile private var isDestroyed = false
27
+ @Volatile private var state = State.NEW
28
+
24
29
  private var isPlaying = false
25
30
  private var hasPlayedOnce = false
31
+ private var mpvDirectory: String? = null
26
32
  private var eventObserver: MPVLib.EventObserver? = null
27
33
  private var logObserver: MPVLib.LogObserver? = null
28
- private var mpvDirectory: String? = null
34
+ private var surfaceView: SurfaceView? = null
29
35
  private var surfaceWidth: Int = -1
30
36
  private var surfaceHeight: Int = -1
31
- private var surfaceView: SurfaceView? = null
32
- private val mpv: MPVLib = MPVLib()
33
37
 
34
- fun create(): Boolean {
35
- mpv.create(applicationContext)
36
- createMpvDirectory()
37
- created = true
38
- return true
38
+ private inline fun safe(block: () -> Unit) {
39
+ try { block() } catch (e: Exception) { logException(e) }
39
40
  }
40
41
 
41
- fun isCreated(): Boolean = created
42
- fun isPlaying(): Boolean = isPlaying
43
- fun hasPlayedOnce(): Boolean = hasPlayedOnce
44
- fun getMpvDirectoryPath(): String? = mpvDirectory
45
-
46
- private fun createMpvDirectory() {
47
- if (isDestroyed) return
48
- val mpvDir = File(applicationContext.getExternalFilesDir("mpv"), "mpv")
42
+ private fun logException(e: Exception) {
49
43
  try {
50
- mpvDirectory = mpvDir.absolutePath
51
- if (!mpvDir.exists() && !mpvDir.mkdirs()) {
52
- Log.e(TAG, "exception", IllegalArgumentException("Unable to create $mpvDir"))
53
- return
54
- }
44
+ Log.e(TAG, "mpv exception", e)
45
+ logObserver?.logMessage("RNLE", 20, e.message ?: "unknown native error")
46
+ } catch (_: Throwable) {}
47
+ }
55
48
 
56
- // Copy font
57
- val mpvFontPath = "${mpvDir}/subfont.ttf"
58
- applicationContext.assets.open("subfont.ttf").use { subfontIn ->
59
- FileOutputStream(mpvFontPath).use { fontOut ->
60
- subfontIn.copyTo(fontOut)
61
- }
49
+ private fun ensureUi(block: () -> Unit) {
50
+ if (Looper.myLooper() == Looper.getMainLooper()) block()
51
+ else mainHandler.post(block)
52
+ }
53
+
54
+ fun create(): Boolean {
55
+ ensureUi {
56
+ safe {
57
+ mpv.create(applicationContext)
58
+ createMpvDirectory()
59
+ created = true
60
+ state = State.CREATED
62
61
  }
62
+ }
63
+ return true
64
+ }
63
65
 
64
- // Copy conf
65
- val mpvConfPath = "${mpvDir}/mpv.conf"
66
- applicationContext.assets.open("mpv.conf").use { mpvConfIn ->
67
- FileOutputStream(mpvConfPath).use { confOut ->
68
- mpvConfIn.copyTo(confOut)
66
+ fun init() {
67
+ ensureUi {
68
+ safe {
69
+ if (state == State.CREATED) {
70
+ mpv.init()
71
+ state = State.RUNNING
69
72
  }
70
73
  }
71
- } catch (e: Exception) {
72
- Log.e(TAG, "Unable to create the directory $mpvDir", e)
73
74
  }
74
75
  }
75
76
 
76
- private fun logException(exception: Exception) {
77
- if (isDestroyed) return
78
- try {
79
- val message: String = (exception.message as? String) ?: "Unable to read error message"
80
- logObserver?.logMessage("RNLE", 20, message)
81
- } catch (e: Exception) {
82
- if (!swallow) throw e
77
+ fun destroy() = cleanup()
78
+
79
+ fun cleanup() {
80
+ if (!created || cleaning || state >= State.CLEANUP) return
81
+ cleaning = true
82
+ state = State.CLEANUP
83
+ ensureUi {
84
+ safe { mpv.command(arrayOf("stop")) }
85
+ safe { mpv.setPropertyString("pause", "yes") }
86
+ safe { mpv.detachSurface() }
87
+ safe { mpv.removeObservers() }
88
+ safe { mpv.removeLogObservers() }
89
+ safe { mpv.destroy() }
90
+ created = false
91
+ isDestroyed = true
92
+ cleaning = false
93
+ state = State.DESTROYED
83
94
  }
84
95
  }
85
96
 
97
+ fun isCreated() = created
98
+ fun isAlive() = !isDestroyed
99
+ fun isPlaying() = isPlaying
100
+ fun hasPlayedOnce() = hasPlayedOnce
101
+ fun getMpvDirectoryPath() = mpvDirectory
102
+
86
103
  fun addEventObserver(observer: MPVLib.EventObserver) {
87
- if (isDestroyed) return
88
- try {
89
- if (!created) return
90
- mpv.removeObservers()
91
- eventObserver = observer
92
- mpv.addObserver(eventObserver)
93
- mpv.observeProperty("demuxer-cache-time", MPVLib.MPV_FORMAT_INT64)
94
- mpv.observeProperty("duration", MPVLib.MPV_FORMAT_INT64)
95
- mpv.observeProperty("eof-reached", MPVLib.MPV_FORMAT_FLAG)
96
- mpv.observeProperty("paused-for-cache", MPVLib.MPV_FORMAT_FLAG)
97
- mpv.observeProperty("seekable", MPVLib.MPV_FORMAT_FLAG)
98
- mpv.observeProperty("speed", MPVLib.MPV_FORMAT_DOUBLE)
99
- mpv.observeProperty("time-pos", MPVLib.MPV_FORMAT_INT64)
100
- mpv.observeProperty("track-list", MPVLib.MPV_FORMAT_STRING)
101
- } catch (e: Exception) {
102
- logException(e)
103
- if (!swallow) throw e
104
+ ensureUi {
105
+ safe {
106
+ mpv.removeObservers()
107
+ eventObserver = observer
108
+ mpv.addObserver(observer)
109
+ }
104
110
  }
105
111
  }
106
112
 
107
113
  fun addLogObserver(observer: MPVLib.LogObserver) {
108
- if (isDestroyed) return
109
- try {
110
- if (!created) return
111
- mpv.removeLogObservers()
112
- logObserver = observer
113
- mpv.addLogObserver(logObserver)
114
- } catch (e: Exception) {
115
- logException(e)
116
- if (!swallow) throw e
114
+ ensureUi {
115
+ safe {
116
+ mpv.removeLogObservers()
117
+ logObserver = observer
118
+ mpv.addLogObserver(observer)
119
+ }
117
120
  }
118
121
  }
119
122
 
120
- fun setOptionString(option: String, setting: String) {
121
- if (isDestroyed) return
122
- try {
123
- if (created) mpv.setOptionString(option, setting)
124
- } catch (e: Exception) {
125
- logException(e)
126
- if (!swallow) throw e
127
- }
123
+ fun setOptionString(option: String, value: String) {
124
+ ensureUi { safe { mpv.setOptionString(option, value) } }
128
125
  }
129
126
 
130
- fun setPropertyString(property: String, setting: String) {
131
- if (isDestroyed) return
132
- try {
133
- if (created) mpv.setPropertyString(property, setting)
134
- } catch (e: Exception) {
135
- logException(e)
136
- if (!swallow) throw e
137
- }
127
+ fun setPropertyString(property: String, value: String) {
128
+ ensureUi { safe { mpv.setPropertyString(property, value) } }
138
129
  }
139
130
 
140
- fun init() {
141
- if (isDestroyed) return
142
- try {
143
- if (created) mpv.init()
144
- } catch (e: Exception) {
145
- logException(e)
146
- if (!swallow) throw e
131
+ suspend fun getProperty(name: String): String? =
132
+ suspendCancellableCoroutine { cont ->
133
+ ensureUi {
134
+ try { cont.resume(mpv.getPropertyString(name)) }
135
+ catch (e: Exception) { logException(e); cont.resume(null) }
136
+ }
147
137
  }
148
- }
149
138
 
150
139
  fun command(orders: Array<String>) {
151
- if (isDestroyed) return
152
- try {
153
- if (created) mpv.command(orders)
154
- } catch (e: Exception) {
155
- logException(e)
156
- if (!swallow) throw e
157
- }
140
+ ensureUi { safe { mpv.command(orders) } }
158
141
  }
159
142
 
160
143
  fun attachSurface(surfaceView: SurfaceView) {
161
- if (isDestroyed) return
162
- try {
163
- if (created) {
164
- this.surfaceView = surfaceView
165
- applySurfaceDimensions()
166
- mpv.attachSurface(surfaceView.holder.surface)
144
+ this.surfaceView = surfaceView
145
+ applySurfaceDimensions()
146
+ ensureUi {
147
+ safe {
148
+ if (state >= State.CREATED && state < State.CLEANUP) {
149
+ mpv.attachSurface(surfaceView.holder.surface)
150
+ }
167
151
  }
168
- } catch (e: Exception) {
169
- logException(e)
170
- if (!swallow) throw e
171
152
  }
172
153
  }
173
154
 
174
- fun play(url: String, options: String? = null) {
175
- if (isDestroyed) return
176
- if (!isPlaying) {
177
- if (options == null) {
178
- command(arrayOf("loadfile", url))
179
- } else {
180
- command(arrayOf("loadfile", url, "replace", "0", options))
181
- }
182
- command(arrayOf("set", "pause", "no"))
183
- hasPlayedOnce = true
184
- isPlaying = true
185
- }
155
+ fun detachSurface() {
156
+ ensureUi { safe { mpv.detachSurface() } }
186
157
  }
187
158
 
188
- fun pauseOrUnpause() {
189
- if (isDestroyed) return
190
- if (!hasPlayedOnce) return
191
- if (isPlaying) pause() else unpause()
159
+ fun setSurfaceWidth(width: Int) {
160
+ surfaceWidth = width
161
+ applySurfaceDimensions()
192
162
  }
193
163
 
194
- fun pause() {
195
- if (isDestroyed) return
196
- if (!hasPlayedOnce) return
197
- if (isPlaying) {
198
- command(arrayOf("set", "pause", "yes"))
199
- isPlaying = false
200
- }
164
+ fun setSurfaceHeight(height: Int) {
165
+ surfaceHeight = height
166
+ applySurfaceDimensions()
201
167
  }
202
168
 
203
- fun unpause() {
204
- if (isDestroyed) return
205
- if (!hasPlayedOnce) return
206
- if (!isPlaying) {
207
- command(arrayOf("set", "pause", "no"))
208
- isPlaying = true
169
+ private fun applySurfaceDimensions() {
170
+ ensureUi {
171
+ try {
172
+ if (surfaceWidth > 0 && surfaceHeight > 0 && surfaceView != null) {
173
+ surfaceView?.holder?.setFixedSize(surfaceWidth, surfaceHeight)
174
+ }
175
+ } catch (e: Exception) { logException(e) }
209
176
  }
210
177
  }
211
178
 
212
- fun seekToSeconds(seconds: Int) {
213
- if (isDestroyed) return
214
- if (created) {
215
- command(arrayOf("seek", seconds.toString(), "absolute"))
179
+ fun play(url: String, options: String? = null) {
180
+ ensureUi {
181
+ safe {
182
+ if (!isPlaying) {
183
+ if (options == null)
184
+ mpv.command(arrayOf("loadfile", url))
185
+ else
186
+ mpv.command(arrayOf("loadfile", url, "replace", "0", options))
187
+ mpv.command(arrayOf("set", "pause", "no"))
188
+ hasPlayedOnce = true
189
+ isPlaying = true
190
+ }
191
+ }
216
192
  }
217
193
  }
218
194
 
219
- private fun applySurfaceDimensions() {
220
- if (isDestroyed) return
221
- if (surfaceHeight != -1 && surfaceWidth != -1 && surfaceView != null) {
222
- surfaceView?.holder?.setFixedSize(surfaceWidth, surfaceHeight)
223
- }
195
+ fun pause() {
196
+ ensureUi { safe { mpv.command(arrayOf("set", "pause", "yes")); isPlaying = false } }
224
197
  }
225
198
 
226
- fun setSurfaceWidth(width: Int) {
227
- surfaceWidth = width
228
- applySurfaceDimensions()
199
+ fun unpause() {
200
+ ensureUi { safe { mpv.command(arrayOf("set", "pause", "no")); isPlaying = true } }
229
201
  }
230
202
 
231
- fun setSurfaceHeight(height: Int) {
232
- surfaceHeight = height
233
- applySurfaceDimensions()
203
+ fun pauseOrUnpause() {
204
+ ensureUi { if (isPlaying) pause() else unpause() }
234
205
  }
235
206
 
236
- fun detachSurface(){
237
- if(isDestroyed) return
238
- try{
239
-
240
- }catch(swallow:Exception){}
241
- }
242
-
243
-
244
- fun cleanup() {
245
- if (!created || cleaning) return
246
- cleaning = true
247
-
248
- Thread {
249
- try {
250
- safe { command(arrayOf("stop")) }
251
- safe { setPropertyString("pause", "yes") }
252
- safe { setPropertyString("vo", "null") }
253
- safe { setPropertyString("ao", "null") }
254
- safe { detachSurface() }
255
- Handler(Looper.getMainLooper()).post {
256
- safe { mpv.removeObservers() }
257
- safe { mpv.removeLogObservers() }
258
- safe { mpv.destroy() }
259
- created = false
260
- cleaning = false
261
- }
262
- } catch (e: Exception) {
263
- logException(e)
264
- cleaning = false
207
+ fun seekToSeconds(seconds: Int) {
208
+ ensureUi { safe { mpv.command(arrayOf("seek", seconds.toString(), "absolute")) } }
265
209
  }
266
- }.start()
267
- }
268
210
 
269
- private inline fun safe(block: () -> Unit) {
270
- try { if (created) block() } catch (e: Exception) { logException(e) }
271
- }
272
-
273
- fun destroy() = cleanup()
211
+ private fun createMpvDirectory() {
212
+ val dir = File(applicationContext.getExternalFilesDir("mpv"), "mpv")
213
+ try {
214
+ mpvDirectory = dir.absolutePath
215
+ if (!dir.exists() && !dir.mkdirs()) {
216
+ Log.e(TAG, "Unable to create $dir")
217
+ return
218
+ }
219
+ applicationContext.assets.open("subfont.ttf").use { inp ->
220
+ FileOutputStream("${dir}/subfont.ttf").use { out -> inp.copyTo(out) }
221
+ }
222
+ applicationContext.assets.open("mpv.conf").use { inp ->
223
+ FileOutputStream("${dir}/mpv.conf").use { out -> inp.copyTo(out) }
224
+ }
225
+ } catch (e: Exception) {
226
+ logException(e)
227
+ }
228
+ }
274
229
  }
@@ -0,0 +1,5 @@
1
+ export declare const Libmpv: {
2
+ getProperty(viewTag: number, name: string): Promise<string | null>;
3
+ };
4
+ export default Libmpv;
5
+ //# sourceMappingURL=Libmpv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Libmpv.d.ts","sourceRoot":"","sources":["../src/Libmpv.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;yBACM,MAAM,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAC1D,CAAC;AAEb,eAAe,MAAM,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export const Libmpv = requireNativeModule('Libmpv');
3
+ export default Libmpv;
4
+ //# sourceMappingURL=Libmpv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Libmpv.js","sourceRoot":"","sources":["../src/Libmpv.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,MAAM,MAAM,GAAG,mBAAmB,CAEtC,QAAQ,CAAC,CAAC;AAEb,eAAe,MAAM,CAAA","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\nexport const Libmpv = requireNativeModule<'getProperty' extends never ? any : {\n getProperty(viewTag: number, name: string): Promise<string | null>;\n}>('Libmpv');\n\nexport default Libmpv"]}
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import { LibmpvViewProps, LibmpvViewNativeMethods } from './LibmpvViewTypes';
3
+ export declare const LibmpvView: React.ForwardRefExoticComponent<Omit<LibmpvViewProps, "ref"> & React.RefAttributes<LibmpvViewNativeMethods>>;
4
+ export default LibmpvView;
5
+ //# sourceMappingURL=LibmpvView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibmpvView.d.ts","sourceRoot":"","sources":["../src/LibmpvView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAkC7E,eAAO,MAAM,UAAU,8GAsDrB,CAAA;AAEF,eAAe,UAAU,CAAA"}
@@ -28,8 +28,8 @@ const EVENT_LOOKUP = {
28
28
  24: 'QUEUE_OVERFLOW',
29
29
  25: 'HOOK'
30
30
  };
31
- const LibmpvVideoView = requireNativeView('LibmpvVideo');
32
- export const LibmpvVideo = React.forwardRef((props, parentRef) => {
31
+ const LibmpvViewNative = requireNativeView('LibmpvView');
32
+ export const LibmpvView = React.forwardRef((props, parentRef) => {
33
33
  React.useEffect(() => {
34
34
  return () => {
35
35
  if (parentRef?.current?.cleanup) {
@@ -67,7 +67,7 @@ export const LibmpvVideo = React.forwardRef((props, parentRef) => {
67
67
  // The order props are handled in the native code is non-deterministic
68
68
  // Each native prop setter checks to see if all required props are set
69
69
  // Only then will it try to create an instance of mpv
70
- return <LibmpvVideoView ref={parentRef} style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer} playUrl={props.playUrl} isPlaying={props.isPlaying} useHardwareDecoder={props.useHardwareDecoder} surfaceWidth={props.surfaceWidth} surfaceHeight={props.surfaceHeight} selectedAudioTrack={props.selectedAudioTrack} selectedSubtitleTrack={props.selectedSubtitleTrack} seekToSeconds={props.seekToSeconds} onLibmpvEvent={onLogEvent} onLibmpvLog={onLibmpvLog}/>;
70
+ return <LibmpvViewNative ref={parentRef} style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer} playUrl={props.playUrl} isPlaying={props.isPlaying} useHardwareDecoder={props.useHardwareDecoder} surfaceWidth={props.surfaceWidth} surfaceHeight={props.surfaceHeight} selectedAudioTrack={props.selectedAudioTrack} selectedSubtitleTrack={props.selectedSubtitleTrack} seekToSeconds={props.seekToSeconds} onLibmpvEvent={onLogEvent} onLibmpvLog={onLibmpvLog}/>;
71
71
  });
72
- export default LibmpvVideo;
73
- //# sourceMappingURL=LibmpvVideoView.js.map
72
+ export default LibmpvView;
73
+ //# sourceMappingURL=LibmpvView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibmpvView.js","sourceRoot":"","sources":["../src/LibmpvView.tsx"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeView } from 'expo';\nimport * as React from 'react';\nimport { LibmpvViewProps, LibmpvViewNativeMethods } from './LibmpvViewTypes';\n\nconst styles: any = {\n videoPlayer: {\n position: \"absolute\",\n left: 0,\n bottom: 0,\n right: 0,\n top: 0\n }\n};\n\nconst EVENT_LOOKUP: any = {\n 0: 'NONE',\n 1: 'SHUTDOWN',\n 2: 'LOG_MESSAGE',\n 3: 'GET_PROPERTY_REPLY',\n 4: 'SET_PROPERTY_REPLY',\n 5: 'COMMAND_REPLY',\n 6: 'START_FILE',\n 7: 'END_FILE',\n 8: 'FILE_LOADED',\n 16: 'CLIENT_MESSAGE',\n 17: 'VIDEO_RECONFIG',\n 18: 'AUDIO_RECONFIG',\n 20: 'SEEK',\n 21: 'PLAYBACK_RESTART',\n 22: 'PROPERTY_CHANGE',\n 24: 'QUEUE_OVERFLOW',\n 25: 'HOOK'\n}\n\nconst LibmpvViewNative: React.ComponentType<LibmpvViewProps> = requireNativeView('LibmpvView');\n\nexport const LibmpvView = React.forwardRef<LibmpvViewNativeMethods, LibmpvViewProps>((props: any, parentRef: any) => {\n React.useEffect(() => {\n return () => {\n if (parentRef?.current?.cleanup) {\n parentRef.current.cleanup();\n }\n };\n }, []);\n\n // Pass mpv events and logs back up to the parent\n const onLogEvent = (libmpvEvent: any) => {\n if (props.onLibmpvEvent) {\n if (libmpvEvent && libmpvEvent.nativeEvent) {\n libmpvEvent = libmpvEvent.nativeEvent\n }\n if (libmpvEvent.eventId) {\n libmpvEvent.value = parseInt(libmpvEvent.eventId, 10)\n libmpvEvent.eventKind = EVENT_LOOKUP[libmpvEvent.eventId]\n }\n else if (libmpvEvent.kind === 'long' || libmpvEvent.kind === 'double') {\n libmpvEvent.value = Number(libmpvEvent.value)\n }\n else if (libmpvEvent.kind === 'boolean') {\n libmpvEvent.value = libmpvEvent.value === 'true'\n }\n return props.onLibmpvEvent(libmpvEvent)\n }\n }\n const onLibmpvLog = (libmpvLog: any) => {\n if (props.onLibmpvLog) {\n if (libmpvLog && libmpvLog.nativeEvent) {\n libmpvLog = libmpvLog.nativeEvent\n }\n return props.onLibmpvLog(libmpvLog);\n }\n }\n\n // The order props are handled in the native code is non-deterministic\n // Each native prop setter checks to see if all required props are set\n // Only then will it try to create an instance of mpv\n return <LibmpvViewNative\n ref={parentRef}\n style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer}\n playUrl={props.playUrl}\n isPlaying={props.isPlaying}\n useHardwareDecoder={props.useHardwareDecoder}\n surfaceWidth={props.surfaceWidth}\n surfaceHeight={props.surfaceHeight}\n selectedAudioTrack={props.selectedAudioTrack}\n selectedSubtitleTrack={props.selectedSubtitleTrack}\n seekToSeconds={props.seekToSeconds}\n onLibmpvEvent={onLogEvent}\n onLibmpvLog={onLibmpvLog}\n />\n})\n\nexport default LibmpvView"]}
@@ -1,4 +1,4 @@
1
- export type LibmpvVideoViewProps = {
1
+ export type LibmpvViewProps = {
2
2
  ref: any;
3
3
  style: any;
4
4
  playUrl: string;
@@ -12,8 +12,8 @@ export type LibmpvVideoViewProps = {
12
12
  onLibmpvEvent: (libmpvEvent: any) => void;
13
13
  onLibmpvLog: (libmpvLog: any) => void;
14
14
  };
15
- export type LibmpvNativeMethods = {
15
+ export type LibmpvViewNativeMethods = {
16
16
  runCommand: (pipeDelimitedArguments: string) => void | Promise<void>;
17
17
  setOptionString: (pipeDelimitedArguments: string) => void | Promise<void>;
18
18
  };
19
- //# sourceMappingURL=LibmpvVideo.types.d.ts.map
19
+ //# sourceMappingURL=LibmpvViewTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibmpvViewTypes.d.ts","sourceRoot":"","sources":["../src/LibmpvViewTypes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,WAAW,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,eAAe,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=LibmpvViewTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibmpvViewTypes.js","sourceRoot":"","sources":["../src/LibmpvViewTypes.ts"],"names":[],"mappings":"","sourcesContent":["export type LibmpvViewProps = {\n ref: any,\n style: any,\n playUrl: string,\n isPlaying: boolean,\n useHardwareDecoder: boolean,\n selectedAudioTrack: number,\n selectedSubtitleTrack: number,\n seekToSeconds: number,\n surfaceWidth: number,\n surfaceHeight: number,\n onLibmpvEvent: (libmpvEvent: any) => void,\n onLibmpvLog: (libmpvLog: any) => void,\n};\n\nexport type LibmpvViewNativeMethods = {\n runCommand: (pipeDelimitedArguments: string) => void | Promise<void>;\n setOptionString: (pipeDelimitedArguments: string) => void | Promise<void>;\n};"]}
package/build/index.d.ts CHANGED
@@ -1,3 +1,13 @@
1
- export { default as LibmpvVideo } from './LibmpvVideoView';
2
- export * from './LibmpvVideo.types';
1
+ export { default as Libmpv } from './Libmpv';
2
+ export { default as LibmpvView } from './LibmpvView';
3
+ import * as LibmpvViewTypes from './LibmpvViewTypes';
4
+ export * as LibmpvViewTypes from './LibmpvViewTypes';
5
+ declare const _default: {
6
+ Module: {
7
+ getProperty(viewTag: number, name: string): Promise<string | null>;
8
+ };
9
+ View: import("react").ForwardRefExoticComponent<Omit<LibmpvViewTypes.LibmpvViewProps, "ref"> & import("react").RefAttributes<LibmpvViewTypes.LibmpvViewNativeMethods>>;
10
+ Types: typeof LibmpvViewTypes;
11
+ };
12
+ export default _default;
3
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3D,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAA;AAG5C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;;;;;;;;AAErD,wBAIC"}
package/build/index.js CHANGED
@@ -1,3 +1,12 @@
1
- export { default as LibmpvVideo } from './LibmpvVideoView';
2
- export * from './LibmpvVideo.types';
1
+ import { default as Libmpv } from './Libmpv';
2
+ export { default as Libmpv } from './Libmpv';
3
+ import { default as LibmpvView } from './LibmpvView';
4
+ export { default as LibmpvView } from './LibmpvView';
5
+ import * as LibmpvViewTypes from './LibmpvViewTypes';
6
+ export * as LibmpvViewTypes from './LibmpvViewTypes';
7
+ export default {
8
+ Module: Libmpv,
9
+ View: LibmpvView,
10
+ Types: LibmpvViewTypes
11
+ };
3
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC3D,cAAc,qBAAqB,CAAC","sourcesContent":["export { default as LibmpvVideo } from './LibmpvVideoView';\nexport * from './LibmpvVideo.types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAA;AAE5C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,mBAAmB,CAAC;AAErD,eAAe;IACX,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,eAAe;CACzB,CAAA","sourcesContent":["import { default as Libmpv } from './Libmpv'\nexport { default as Libmpv } from './Libmpv'\n\nimport { default as LibmpvView } from './LibmpvView';\nexport { default as LibmpvView } from './LibmpvView';\n\nimport * as LibmpvViewTypes from './LibmpvViewTypes';\nexport * as LibmpvViewTypes from './LibmpvViewTypes';\n\nexport default {\n Module: Libmpv,\n View: LibmpvView,\n Types: LibmpvViewTypes\n}\n"]}
@@ -4,7 +4,8 @@
4
4
  ],
5
5
  "android": {
6
6
  "modules": [
7
- "com.libmpv.LibmpvVideoModule"
7
+ "com.libmpv.LibmpvModule",
8
+ "com.libmpv.LibmpvViewModule"
8
9
  ]
9
10
  }
10
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-libmpv",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "A libmpv Fabric component for Android",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
package/src/Libmpv.tsx ADDED
@@ -0,0 +1,7 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+
3
+ export const Libmpv = requireNativeModule<'getProperty' extends never ? any : {
4
+ getProperty(viewTag: number, name: string): Promise<string | null>;
5
+ }>('Libmpv');
6
+
7
+ export default Libmpv
@@ -1,7 +1,6 @@
1
1
  import { requireNativeView } from 'expo';
2
2
  import * as React from 'react';
3
-
4
- import { LibmpvVideoViewProps, LibmpvNativeMethods } from './LibmpvVideo.types';
3
+ import { LibmpvViewProps, LibmpvViewNativeMethods } from './LibmpvViewTypes';
5
4
 
6
5
  const styles: any = {
7
6
  videoPlayer: {
@@ -33,10 +32,9 @@ const EVENT_LOOKUP: any = {
33
32
  25: 'HOOK'
34
33
  }
35
34
 
36
- const LibmpvVideoView: React.ComponentType<LibmpvVideoViewProps> =
37
- requireNativeView('LibmpvVideo');
35
+ const LibmpvViewNative: React.ComponentType<LibmpvViewProps> = requireNativeView('LibmpvView');
38
36
 
39
- export const LibmpvVideo = React.forwardRef<LibmpvNativeMethods, LibmpvVideoViewProps>((props: any, parentRef: any) => {
37
+ export const LibmpvView = React.forwardRef<LibmpvViewNativeMethods, LibmpvViewProps>((props: any, parentRef: any) => {
40
38
  React.useEffect(() => {
41
39
  return () => {
42
40
  if (parentRef?.current?.cleanup) {
@@ -76,7 +74,7 @@ export const LibmpvVideo = React.forwardRef<LibmpvNativeMethods, LibmpvVideoView
76
74
  // The order props are handled in the native code is non-deterministic
77
75
  // Each native prop setter checks to see if all required props are set
78
76
  // Only then will it try to create an instance of mpv
79
- return <LibmpvVideoView
77
+ return <LibmpvViewNative
80
78
  ref={parentRef}
81
79
  style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer}
82
80
  playUrl={props.playUrl}
@@ -92,4 +90,4 @@ export const LibmpvVideo = React.forwardRef<LibmpvNativeMethods, LibmpvVideoView
92
90
  />
93
91
  })
94
92
 
95
- export default LibmpvVideo
93
+ export default LibmpvView
@@ -1,4 +1,4 @@
1
- export type LibmpvVideoViewProps = {
1
+ export type LibmpvViewProps = {
2
2
  ref: any,
3
3
  style: any,
4
4
  playUrl: string,
@@ -13,7 +13,7 @@ export type LibmpvVideoViewProps = {
13
13
  onLibmpvLog: (libmpvLog: any) => void,
14
14
  };
15
15
 
16
- export type LibmpvNativeMethods = {
16
+ export type LibmpvViewNativeMethods = {
17
17
  runCommand: (pipeDelimitedArguments: string) => void | Promise<void>;
18
18
  setOptionString: (pipeDelimitedArguments: string) => void | Promise<void>;
19
19
  };
package/src/index.ts CHANGED
@@ -1,2 +1,14 @@
1
- export { default as LibmpvVideo } from './LibmpvVideoView';
2
- export * from './LibmpvVideo.types';
1
+ import { default as Libmpv } from './Libmpv'
2
+ export { default as Libmpv } from './Libmpv'
3
+
4
+ import { default as LibmpvView } from './LibmpvView';
5
+ export { default as LibmpvView } from './LibmpvView';
6
+
7
+ import * as LibmpvViewTypes from './LibmpvViewTypes';
8
+ export * as LibmpvViewTypes from './LibmpvViewTypes';
9
+
10
+ export default {
11
+ Module: Libmpv,
12
+ View: LibmpvView,
13
+ Types: LibmpvViewTypes
14
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"LibmpvVideo.types.d.ts","sourceRoot":"","sources":["../src/LibmpvVideo.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,CAAC,WAAW,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,WAAW,EAAE,CAAC,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,eAAe,EAAE,CAAC,sBAAsB,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=LibmpvVideo.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LibmpvVideo.types.js","sourceRoot":"","sources":["../src/LibmpvVideo.types.ts"],"names":[],"mappings":"","sourcesContent":["export type LibmpvVideoViewProps = {\n ref: any,\n style: any,\n playUrl: string,\n isPlaying: boolean,\n useHardwareDecoder: boolean,\n selectedAudioTrack: number,\n selectedSubtitleTrack: number,\n seekToSeconds: number,\n surfaceWidth: number,\n surfaceHeight: number,\n onLibmpvEvent: (libmpvEvent: any) => void,\n onLibmpvLog: (libmpvLog: any) => void,\n};\n\nexport type LibmpvNativeMethods = {\n runCommand: (pipeDelimitedArguments: string) => void | Promise<void>;\n setOptionString: (pipeDelimitedArguments: string) => void | Promise<void>;\n};"]}
@@ -1,5 +0,0 @@
1
- import * as React from 'react';
2
- import { LibmpvVideoViewProps, LibmpvNativeMethods } from './LibmpvVideo.types';
3
- export declare const LibmpvVideo: React.ForwardRefExoticComponent<Omit<LibmpvVideoViewProps, "ref"> & React.RefAttributes<LibmpvNativeMethods>>;
4
- export default LibmpvVideo;
5
- //# sourceMappingURL=LibmpvVideoView.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LibmpvVideoView.d.ts","sourceRoot":"","sources":["../src/LibmpvVideoView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAmChF,eAAO,MAAM,WAAW,+GAsDtB,CAAA;AAEF,eAAe,WAAW,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"LibmpvVideoView.js","sourceRoot":"","sources":["../src/LibmpvVideoView.tsx"],"names":[],"mappings":"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","sourcesContent":["import { requireNativeView } from 'expo';\nimport * as React from 'react';\n\nimport { LibmpvVideoViewProps, LibmpvNativeMethods } from './LibmpvVideo.types';\n\nconst styles: any = {\n videoPlayer: {\n position: \"absolute\",\n left: 0,\n bottom: 0,\n right: 0,\n top: 0\n }\n};\n\nconst EVENT_LOOKUP: any = {\n 0: 'NONE',\n 1: 'SHUTDOWN',\n 2: 'LOG_MESSAGE',\n 3: 'GET_PROPERTY_REPLY',\n 4: 'SET_PROPERTY_REPLY',\n 5: 'COMMAND_REPLY',\n 6: 'START_FILE',\n 7: 'END_FILE',\n 8: 'FILE_LOADED',\n 16: 'CLIENT_MESSAGE',\n 17: 'VIDEO_RECONFIG',\n 18: 'AUDIO_RECONFIG',\n 20: 'SEEK',\n 21: 'PLAYBACK_RESTART',\n 22: 'PROPERTY_CHANGE',\n 24: 'QUEUE_OVERFLOW',\n 25: 'HOOK'\n}\n\nconst LibmpvVideoView: React.ComponentType<LibmpvVideoViewProps> =\n requireNativeView('LibmpvVideo');\n\nexport const LibmpvVideo = React.forwardRef<LibmpvNativeMethods, LibmpvVideoViewProps>((props: any, parentRef: any) => {\n React.useEffect(() => {\n return () => {\n if (parentRef?.current?.cleanup) {\n parentRef.current.cleanup();\n }\n };\n }, []);\n\n // Pass mpv events and logs back up to the parent\n const onLogEvent = (libmpvEvent: any) => {\n if (props.onLibmpvEvent) {\n if (libmpvEvent && libmpvEvent.nativeEvent) {\n libmpvEvent = libmpvEvent.nativeEvent\n }\n if (libmpvEvent.eventId) {\n libmpvEvent.value = parseInt(libmpvEvent.eventId, 10)\n libmpvEvent.eventKind = EVENT_LOOKUP[libmpvEvent.eventId]\n }\n else if (libmpvEvent.kind === 'long' || libmpvEvent.kind === 'double') {\n libmpvEvent.value = Number(libmpvEvent.value)\n }\n else if (libmpvEvent.kind === 'boolean') {\n libmpvEvent.value = libmpvEvent.value === 'true'\n }\n return props.onLibmpvEvent(libmpvEvent)\n }\n }\n const onLibmpvLog = (libmpvLog: any) => {\n if (props.onLibmpvLog) {\n if (libmpvLog && libmpvLog.nativeEvent) {\n libmpvLog = libmpvLog.nativeEvent\n }\n return props.onLibmpvLog(libmpvLog);\n }\n }\n\n // The order props are handled in the native code is non-deterministic\n // Each native prop setter checks to see if all required props are set\n // Only then will it try to create an instance of mpv\n return <LibmpvVideoView\n ref={parentRef}\n style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer}\n playUrl={props.playUrl}\n isPlaying={props.isPlaying}\n useHardwareDecoder={props.useHardwareDecoder}\n surfaceWidth={props.surfaceWidth}\n surfaceHeight={props.surfaceHeight}\n selectedAudioTrack={props.selectedAudioTrack}\n selectedSubtitleTrack={props.selectedSubtitleTrack}\n seekToSeconds={props.seekToSeconds}\n onLibmpvEvent={onLogEvent}\n onLibmpvLog={onLibmpvLog}\n />\n})\n\nexport default LibmpvVideo\n"]}