expo-libmpv 0.4.6 → 0.5.1

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.
@@ -75,22 +75,29 @@ export const LibmpvView = React.forwardRef<LibmpvViewNativeMethods, LibmpvViewPr
75
75
  }
76
76
  }
77
77
 
78
+ let seekProps: any = {}
79
+ if (typeof props?.seekToSeconds === 'number' && props?.seekToSeconds >= 0) {
80
+ seekProps.seekToSeconds = props.seekToSeconds
81
+ }
82
+
78
83
  // The order props are handled in the native code is non-deterministic
79
84
  // Each native prop setter checks to see if all required props are set
80
85
  // Only then will it try to create an instance of mpv
86
+
81
87
  return <LibmpvViewNative
82
88
  ref={parentRef}
89
+ {...seekProps}
83
90
  style={props.surfaceStyle ? props.surfaceStyle : styles.videoPlayer}
84
91
  videoOutput={props.videoOutput}
85
92
  playUrl={props.playUrl}
86
93
  isPlaying={props.isPlaying}
87
94
  decodingMode={props.decodingMode}
88
95
  acceleratedCodecs={props.acceleratedCodecs}
96
+ videoSync={props.videoSync}
89
97
  surfaceWidth={props.surfaceWidth}
90
98
  surfaceHeight={props.surfaceHeight}
91
99
  selectedAudioTrack={props.selectedAudioTrack}
92
100
  selectedSubtitleTrack={props.selectedSubtitleTrack}
93
- seekToSeconds={props.seekToSeconds}
94
101
  onLibmpvEvent={onLogEvent}
95
102
  onLibmpvLog={onLibmpvLog}
96
103
  />
@@ -6,6 +6,7 @@ export type LibmpvViewProps = {
6
6
  isPlaying: boolean,
7
7
  decodingMode: string,
8
8
  acceleratedCodecs: string,
9
+ videoSync: string,
9
10
  selectedAudioTrack: number,
10
11
  selectedSubtitleTrack: number,
11
12
  seekToSeconds: number,
@@ -1,297 +0,0 @@
1
- package com.libmpv
2
-
3
- import android.os.Handler
4
- import android.os.Looper
5
- import android.content.Context
6
- import android.util.Log
7
- import android.view.SurfaceView
8
- import dev.jdtech.mpv.MPVLib
9
- import java.io.File
10
- import java.io.FileOutputStream
11
- import java.io.InputStream
12
- import java.io.OutputStream
13
-
14
- class LibmpvWrapper(private val applicationContext: Context) {
15
- companion object {
16
- private const val TAG = "expo-libmpv"
17
- private var SWALLOW = true
18
- }
19
-
20
- @Volatile private var created = false
21
- @Volatile private var inited = false
22
- @Volatile private var destroyed = false
23
- @Volatile private var cleaning = false
24
- @Volatile private var isPlaying = false
25
- @Volatile private var hasPlayedOnce = false
26
-
27
- private var mpvDirectory: String? = null
28
- private var surfaceWidth: Int = -1
29
- private var surfaceHeight: Int = -1
30
- private var surfaceView: SurfaceView? = null
31
-
32
- fun isCreated(): Boolean = created
33
- fun isPlaying(): Boolean = isPlaying
34
- fun hasPlayedOnce(): Boolean = hasPlayedOnce
35
- fun getMpvDirectoryPath(): String? = mpvDirectory
36
-
37
- private fun logException(exception: Exception) {
38
- if (destroyed){ return }
39
- try {
40
- val message: String = (exception.message as? String) ?: "Unable to read error message"
41
- MPVLib.logMessage("RNLE", 20, message)
42
- } catch (e: Exception) {
43
- if (!SWALLOW){
44
- throw e
45
- }
46
- }
47
- }
48
-
49
- fun createManagedInstance(): Boolean {
50
- if(created){ return false }
51
- try{
52
- MPVLib.create(applicationContext)
53
- createMpvDirectory()
54
- created = true
55
- return true
56
- } catch(e:Exception){
57
- return false
58
- }
59
- }
60
-
61
- fun initNativeBinding() {
62
- if (destroyed || !created || inited){ return }
63
- try {
64
- MPVLib.init()
65
- inited = true
66
- } catch (e: Exception) {
67
- logException(e)
68
- if (!SWALLOW){
69
- throw e
70
- }
71
- }
72
- }
73
-
74
- private fun createMpvDirectory() {
75
- if (destroyed){ return }
76
- val mpvDir = File(applicationContext.getExternalFilesDir("mpv"), "mpv")
77
- try {
78
- mpvDirectory = mpvDir.absolutePath
79
- if (!mpvDir.exists() && !mpvDir.mkdirs()) {
80
- Log.e(TAG, "exception", IllegalArgumentException("Unable to create $mpvDir"))
81
- return
82
- }
83
-
84
- // Copy font
85
- val mpvFontPath = "${mpvDir}/subfont.ttf"
86
- applicationContext.assets.open("subfont.ttf").use { subfontIn ->
87
- FileOutputStream(mpvFontPath).use { fontOut ->
88
- subfontIn.copyTo(fontOut)
89
- }
90
- }
91
-
92
- // Copy conf
93
- val mpvConfPath = "${mpvDir}/mpv.conf"
94
- applicationContext.assets.open("mpv.conf").use { mpvConfIn ->
95
- FileOutputStream(mpvConfPath).use { confOut ->
96
- mpvConfIn.copyTo(confOut)
97
- }
98
- }
99
- } catch (e: Exception) {
100
- Log.e(TAG, "Unable to create the directory $mpvDir", e)
101
- }
102
- }
103
-
104
- fun addEventObserver(observer: MPVLib.EventObserver) {
105
- if (destroyed || !created){ return }
106
- try {
107
- MPVLib.removeObservers()
108
- MPVLib.addObserver(observer)
109
-
110
- MPVLib.observeProperty("demuxer-cache-time", MPVLib.MpvFormat.MPV_FORMAT_DOUBLE)
111
- MPVLib.observeProperty("duration", MPVLib.MpvFormat.MPV_FORMAT_DOUBLE)
112
- MPVLib.observeProperty("eof-reached", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
113
- MPVLib.observeProperty("paused-for-cache", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
114
- MPVLib.observeProperty("seekable", MPVLib.MpvFormat.MPV_FORMAT_FLAG)
115
- MPVLib.observeProperty("speed", MPVLib.MpvFormat.MPV_FORMAT_DOUBLE)
116
- MPVLib.observeProperty("time-pos", MPVLib.MpvFormat.MPV_FORMAT_DOUBLE)
117
- MPVLib.observeProperty("track-list", MPVLib.MpvFormat.MPV_FORMAT_STRING)
118
-
119
- } catch (e: Exception) {
120
- logException(e)
121
- if (!SWALLOW){
122
- throw e
123
- }
124
- }
125
- }
126
-
127
- fun addLogObserver(observer: MPVLib.LogObserver) {
128
- if (destroyed || !created){ return }
129
- try {
130
- MPVLib.removeLogObservers()
131
- MPVLib.addLogObserver(observer)
132
- } catch (e: Exception) {
133
- logException(e)
134
- if (!SWALLOW) {
135
- throw e
136
- }
137
- }
138
- }
139
-
140
- fun setOptionString(option: String, setting: String) {
141
- if (destroyed || !created){ return }
142
- try {
143
- MPVLib.setOptionString(option, setting)
144
- } catch (e: Exception) {
145
- logException(e)
146
- if (!SWALLOW){
147
- throw e
148
- }
149
- }
150
- }
151
-
152
- fun setPropertyString(property: String, setting: String) {
153
- if (destroyed || !created){ return }
154
- try {
155
- MPVLib.setPropertyString(property, setting)
156
- } catch (e: Exception) {
157
- logException(e)
158
- if (!SWALLOW){
159
- throw e
160
- }
161
- }
162
- }
163
-
164
- fun command(orders: Array<String>) {
165
- if (destroyed || !created){ return }
166
- try {
167
- MPVLib.command(orders)
168
- } catch (e: Exception) {
169
- logException(e)
170
- if (!SWALLOW){
171
- throw e
172
- }
173
- }
174
- }
175
-
176
- fun attachSurface(surfaceView: SurfaceView) {
177
- if (destroyed || !created){ return }
178
- try {
179
- this.surfaceView = surfaceView
180
- applySurfaceDimensions()
181
- MPVLib.attachSurface(surfaceView.holder.surface)
182
- } catch (e: Exception) {
183
- logException(e)
184
- if (!SWALLOW){
185
- throw e
186
- }
187
- }
188
- }
189
-
190
- fun play(url: String, options: String? = null) {
191
- if (destroyed) { return }
192
- if (!isPlaying) {
193
- if (options == null) {
194
- command(arrayOf("loadfile", url))
195
- } else {
196
- command(arrayOf("loadfile", url, "replace", "0", options))
197
- }
198
- command(arrayOf("set", "pause", "no"))
199
- hasPlayedOnce = true
200
- isPlaying = true
201
- }
202
- }
203
-
204
- fun pauseOrUnpause() {
205
- if (destroyed || !hasPlayedOnce){ return }
206
- if (isPlaying){
207
- pause()
208
- } else {
209
- unpause()
210
- }
211
- }
212
-
213
- fun pause() {
214
- if (destroyed || !hasPlayedOnce) { return }
215
- if (isPlaying) {
216
- command(arrayOf("set", "pause", "yes"))
217
- isPlaying = false
218
- }
219
- }
220
-
221
- fun unpause() {
222
- if (destroyed || !hasPlayedOnce) { return }
223
- if (!isPlaying) {
224
- command(arrayOf("set", "pause", "no"))
225
- isPlaying = true
226
- }
227
- }
228
-
229
- fun seekToSeconds(seconds: Int) {
230
- if (destroyed || !created) { return }
231
- command(arrayOf("seek", seconds.toString(), "absolute"))
232
- }
233
-
234
- private fun applySurfaceDimensions() {
235
- if (destroyed) { return }
236
- if (surfaceHeight != -1 && surfaceWidth != -1 && surfaceView != null) {
237
- surfaceView?.holder?.setFixedSize(surfaceWidth, surfaceHeight)
238
- }
239
- }
240
-
241
- fun setSurfaceWidth(width: Int) {
242
- if (destroyed) { return }
243
- surfaceWidth = width
244
- applySurfaceDimensions()
245
- }
246
-
247
- fun setSurfaceHeight(height: Int) {
248
- if (destroyed) { return }
249
- surfaceHeight = height
250
- applySurfaceDimensions()
251
- }
252
-
253
- fun detachSurface(){
254
- if(destroyed) { return }
255
- try{
256
- MPVLib.detachSurface()
257
- }
258
- catch(e:Exception){
259
- logException(e)
260
- if(!SWALLOW){
261
- throw e
262
- }
263
- }
264
- }
265
-
266
-
267
- fun cleanup() {
268
- if (!created || cleaning)
269
- {
270
- return
271
- }
272
-
273
- cleaning = true
274
-
275
- try {
276
- command(arrayOf("stop"))
277
- setPropertyString("pause", "yes")
278
- setPropertyString("vo", "null")
279
- setPropertyString("ao", "null")
280
- detachSurface()
281
- Handler(Looper.getMainLooper()).post {
282
- MPVLib.removeObservers()
283
- MPVLib.removeLogObservers()
284
- MPVLib.destroy()
285
- created = false
286
- cleaning = false
287
- }
288
- } catch (e: Exception) {
289
- logException(e)
290
- cleaning = false
291
- }
292
- }
293
-
294
- fun destroy(){
295
- return cleanup()
296
- }
297
- }