expo-libvlc-player 7.0.11 → 7.0.13

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.
package/README.md CHANGED
@@ -120,19 +120,19 @@ See the [Example App](example/App.tsx) for additional usage.
120
120
 
121
121
  ### View methods
122
122
 
123
- | Method | Description | Returns |
124
- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
125
- | `play()` | Starts playback of the current player | `Promise<void>` |
126
- | `pause()` | Pauses playback of the current player | `Promise<void>` |
127
- | `stop()` | Stops playback of the current player | `Promise<void>` |
128
- | `seek(value: number, type?: "time" \| "position")` | Sets the time or position of the current player. Value must be a double equal or greater than `0` and type defaults to `"time"` | `Promise<void>` |
129
- | `record(path?: string)` | Starts or stops recording the current media. Path must be a valid directory or `undefined` to stop recording | `Promise<void>` |
130
- | `snapshot(path: string)` | Takes a snapshot of the current media. Path must be a valid directory | `Promise<void>` |
131
- | `postAction(action: 1 \| 2)` | Posts an answer to a [`Dialog`](#dialog). Action must be either `1` or `2` | `Promise<void>` |
132
- | `postLogin(username: string, password: string, store?: boolean)` | Posts a username and password to a login [`Dialog`](#dialog). Username can't be empty, password can be empty and if `true`, store the credentials | `Promise<void>` |
133
- | `dismiss()` | Dismisses a [`Dialog`](#dialog) | `Promise<void>` |
134
- | `startPictureInPicture()` | Enters Picture-in-Picture (PiP) mode. Config plugin has to be configured for Picture-in-Picture (PiP) to work | `Promise<void>` |
135
- | `stopPictureInPicture()` | Exits Picture-in-Picture (PiP) mode on iOS | `Promise<void>` |
123
+ | Method | Description | Returns |
124
+ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------- |
125
+ | `play()` | Starts playback of the current player | `Promise<void>` |
126
+ | `pause()` | Pauses playback of the current player | `Promise<void>` |
127
+ | `stop()` | Stops playback of the current player | `Promise<void>` |
128
+ | `seek(value: number, type?: "time" \| "position")` | Sets the time or position of the current player. Value must be a number equal or greater than `0` and type defaults to `"time"` | `Promise<void>` |
129
+ | `record(path?: string)` | Starts or stops recording the current media. Path must be a valid directory or `undefined` to stop recording | `Promise<void>` |
130
+ | `snapshot(path: string)` | Takes a snapshot of the current media. Path must be a valid directory | `Promise<void>` |
131
+ | `postAction(action: 1 \| 2)` | Posts an answer to a dialog. Action must be either `1` or `2` | `Promise<void>` |
132
+ | `postLogin(username: string, password: string, store?: boolean)` | Posts a username and password to a login dialog. Username can't be empty, password can be empty and if `true`, store the credentials | `Promise<void>` |
133
+ | `dismiss()` | Dismisses a dialog | `Promise<void>` |
134
+ | `startPictureInPicture()` | Enters Picture-in-Picture (PiP) mode. Config plugin has to be configured for Picture-in-Picture (PiP) to work | `Promise<void>` |
135
+ | `stopPictureInPicture()` | Exits Picture-in-Picture (PiP) mode on iOS | `Promise<void>` |
136
136
 
137
137
  ### View props
138
138
 
@@ -144,12 +144,12 @@ The `LibVlcPlayerView` extends React Native `ViewProps` and implements the follo
144
144
  | `options` | Sets the options to initialize the media with. See the [VideoLAN Wiki](https://wiki.videolan.org/VLC_command-line_help/) for more | `[]` |
145
145
  | `tracks` | Sets the player audio, video and subtitle tracks. See [`Tracks`](#tracks) for more | `undefined` |
146
146
  | `slaves` | Sets the player audio and subtitle slaves. See [`Slave`](#slave) for more | `[]` |
147
- | `scale` | Sets the player scaling factor. Must be a float equal or greater than `0` | `0` |
148
- | `aspectRatio` | Sets the container aspect ratio. Must be a valid ratio, float, or `"auto"` | `undefined` |
147
+ | `scale` | Sets the player scaling factor. Must be a number equal or greater than `0` | `0` |
148
+ | `aspectRatio` | Sets the container aspect ratio. Must be a valid ratio, number, or `"auto"` | `undefined` |
149
149
  | `contentFit` | Sets how the video should be scaled to fit in the container | `"contain"` |
150
- | `rate` | Sets the player rate. Must be a float equal or greater than `1` | `1` |
151
- | `time` | Sets the initial player time. Must be an integer (ms) greater than `0` | `0` |
152
- | `volume` | Sets the player volume. Must be an integer between `0` and `100` | `100` |
150
+ | `rate` | Sets the player rate. Must be a number equal or greater than `1` | `1` |
151
+ | `time` | Sets the initial player time. Must be a number equal or greater than `0` | `0` |
152
+ | `volume` | Sets the player volume. Must be a number between `0` and `100` | `100` |
153
153
  | `mute` | Sets the player volume to `0` when `true` and previous value is restored when `false` | `false` |
154
154
  | `audioMixingMode` | Determines how the player will interact with other audio in the system | `"auto"` |
155
155
  | `repeat` | Determines whether the media should repeat once ended | `false` |
@@ -165,7 +165,7 @@ The `LibVlcPlayerView` extends React Native `ViewProps` and implements the follo
165
165
  | `onPaused` | Called after the `Paused` player event | |
166
166
  | `onStopped` | Called after the `Stopped` player event | |
167
167
  | `onEncounteredError` | Called after the `EncounteredError` player event | [`Error`](#error) |
168
- | `onDialogDisplay` | Called after a `Dialog` needs to be displayed | [`Dialog`](#dialog) |
168
+ | `onDialogDisplay` | Called after a dialog needs to be displayed | [`Dialog`](#dialog) |
169
169
  | `onTimeChanged` | Called after the `TimeChanged` player event | [`Time`](#time) |
170
170
  | `onPositionChanged` | Called after the `PositionChanged` player event | [`Position`](#position) |
171
171
  | `onESAdded` | Called after the `ESAdded` player event | [`MediaTracks`](#mediatracks) |
@@ -179,38 +179,6 @@ The `LibVlcPlayerView` extends React Native `ViewProps` and implements the follo
179
179
 
180
180
  ### Module types
181
181
 
182
- #### `Error`
183
-
184
- ```ts
185
- interface Error {
186
- message: string;
187
- }
188
- ```
189
-
190
- #### `Time`
191
-
192
- ```ts
193
- interface Time {
194
- value: number;
195
- }
196
- ```
197
-
198
- #### `Position`
199
-
200
- ```ts
201
- interface Position {
202
- value: number;
203
- }
204
- ```
205
-
206
- #### `Snapshot`
207
-
208
- ```ts
209
- interface Snapshot {
210
- path: string;
211
- }
212
- ```
213
-
214
182
  #### `Tracks`
215
183
 
216
184
  ```ts
@@ -231,6 +199,14 @@ interface Slave {
231
199
  }
232
200
  ```
233
201
 
202
+ #### `Error`
203
+
204
+ ```ts
205
+ interface Error {
206
+ message: string;
207
+ }
208
+ ```
209
+
234
210
  #### `Dialog`
235
211
 
236
212
  ```ts
@@ -244,12 +220,19 @@ interface Dialog {
244
220
  }
245
221
  ```
246
222
 
247
- #### `Recording`
223
+ #### `Time`
248
224
 
249
225
  ```ts
250
- interface Recording {
251
- path: string | null;
252
- isRecording: boolean;
226
+ interface Time {
227
+ value: number;
228
+ }
229
+ ```
230
+
231
+ #### `Position`
232
+
233
+ ```ts
234
+ interface Position {
235
+ value: number;
253
236
  }
254
237
  ```
255
238
 
@@ -272,6 +255,23 @@ interface MediaTracks {
272
255
  }
273
256
  ```
274
257
 
258
+ #### `Recording`
259
+
260
+ ```ts
261
+ interface Recording {
262
+ path: string | null;
263
+ isRecording: boolean;
264
+ }
265
+ ```
266
+
267
+ #### `Snapshot`
268
+
269
+ ```ts
270
+ interface Snapshot {
271
+ path: string;
272
+ }
273
+ ```
274
+
275
275
  #### `MediaInfo`
276
276
 
277
277
  ```ts
@@ -317,7 +317,7 @@ https://developer.apple.com/documentation/technotes/tn3179-understanding-local-n
317
317
 
318
318
  ## Disclaimer
319
319
 
320
- This project is not affiliated with, endorsed by, or officially supported by VideoLAN. The VLC icon is trademark of VideoLAN and is used here solely to indicate compatibility with the following **LibVLC** bindings:
320
+ This project is not affiliated with, endorsed by, or officially supported by VideoLAN. The VLC icon is trademark of VideoLAN and is used here solely to indicate compatibility with the following LibVLC bindings:
321
321
 
322
322
  - `libvlcjni` for Android / Android TV
323
323
  - `VLCKit` for iOS / Apple TV
@@ -326,11 +326,11 @@ For official VLC products and support, please visit [videolan.org](https://www.v
326
326
 
327
327
  ## Credits
328
328
 
329
- This library is inspired by existing projects such as [expo-video](https://github.com/expo/expo/tree/main/packages/expo-video) and [react-native-vlc-media-player](https://github.com/razorRun/react-native-vlc-media-player).
329
+ This library is inspired by existing projects such as [react-native-vlc-media-player](https://github.com/razorRun/react-native-vlc-media-player) and [expo-video](https://github.com/expo/expo/tree/main/packages/expo-video).
330
330
 
331
331
  ## Contributing
332
332
 
333
- Contributions are always welcome. Please raise any issues and/or fix them by creating a pull request.
333
+ Contributions are always welcome. Please raise any issues or fix them by creating a pull request.
334
334
 
335
335
  ## License
336
336
 
@@ -722,18 +722,19 @@ class LibVlcPlayerView(
722
722
  fun retryUntil(
723
723
  maxRetries: Int = MediaPlayerConstants.MAX_RETRY_COUNT,
724
724
  retry: Int = 0,
725
- delay: Long = MediaPlayerConstants.RETRY_DELAY_MS,
725
+ delay: Double = MediaPlayerConstants.RETRY_DELAY_MS,
726
726
  block: (isLastAttempt: Boolean) -> Boolean,
727
727
  ) {
728
728
  val isLastAttempt = retry >= maxRetries
729
729
 
730
730
  if (block(isLastAttempt) || isLastAttempt) return
731
731
 
732
- val expDelay = (delay.toDouble() * 1.5).toLong()
732
+ val expDelay = delay * MediaPlayerConstants.EXP_DELAY_MULTIPLIER
733
+ val postDelay = delay.toLong()
733
734
 
734
735
  postDelayed({
735
736
  retryUntil(maxRetries, retry + 1, expDelay, block)
736
- }, delay)
737
+ }, postDelay)
737
738
  }
738
739
  }
739
740
 
@@ -766,7 +767,7 @@ fun LibVlcPlayerView.setPlayerListener(mediaPlayer: MediaPlayer?) {
766
767
  return@retryUntil hasVideoOut
767
768
  }
768
769
 
769
- retryUntil { isLastAttempt ->
770
+ retryUntil {
770
771
  if (hasVideoSize) {
771
772
  setContentFit(layout = playerLayout)
772
773
  setContentFit(layout = pictureLayout)
@@ -775,7 +776,7 @@ fun LibVlcPlayerView.setPlayerListener(mediaPlayer: MediaPlayer?) {
775
776
  return@retryUntil hasVideoSize
776
777
  }
777
778
 
778
- retryUntil { isLastAttempt ->
779
+ retryUntil {
779
780
  if (hasAudioOut) {
780
781
  MediaPlayerManager.audioFocusManager.updateAudioFocus()
781
782
  }
@@ -16,6 +16,7 @@ object MediaPlayerConstants {
16
16
  const val SEEK_STEP_MS: Long = 10_000L
17
17
 
18
18
  const val COROUTINE_DELAY_MS: Long = 1_000L
19
- const val RETRY_DELAY_MS: Long = 200L
19
+ const val EXP_DELAY_MULTIPLIER: Double = 1.5
20
+ const val RETRY_DELAY_MS: Double = 200.0
20
21
  const val MAX_RETRY_COUNT: Int = 5
21
22
  }
@@ -22,7 +22,7 @@ export interface LibVlcPlayerViewRef {
22
22
  /**
23
23
  * Sets the time or position of the current player
24
24
  *
25
- * @param value - Must be a double equal or greater than `0`
25
+ * @param value - Must be a number equal or greater than `0`
26
26
  * @param type - Defaults to `"time"`
27
27
  *
28
28
  * @returns A promise which resolves to `void`
@@ -333,13 +333,13 @@ export interface LibVlcPlayerViewProps extends ViewProps {
333
333
  */
334
334
  slaves?: Slave[];
335
335
  /**
336
- * Sets the player scaling factor. Must be a float equal or greater than `0`
336
+ * Sets the player scaling factor. Must be a number equal or greater than `0`
337
337
  *
338
338
  * @default 0
339
339
  */
340
340
  scale?: number;
341
341
  /**
342
- * Sets the container aspect ratio. Must be a valid ratio, float, or `"auto"`
342
+ * Sets the container aspect ratio. Must be a valid ratio, number, or `"auto"`
343
343
  *
344
344
  * @example "16:9"
345
345
  *
@@ -355,19 +355,19 @@ export interface LibVlcPlayerViewProps extends ViewProps {
355
355
  */
356
356
  contentFit?: VideoContentFit;
357
357
  /**
358
- * Sets the player rate. Must be a float equal or greater than `1`
358
+ * Sets the player rate. Must be a number equal or greater than `1`
359
359
  *
360
360
  * @default 1
361
361
  */
362
362
  rate?: number;
363
363
  /**
364
- * Sets the initial player time. Must be an integer (ms) greater than `0`
364
+ * Sets the initial player time. Must be a number equal or greater than `0`
365
365
  *
366
366
  * @default 0
367
367
  */
368
368
  time?: number;
369
369
  /**
370
- * Sets the player volume. Must be an integer between `0` and `100`
370
+ * Sets the player volume. Must be a number between `0` and `100`
371
371
  *
372
372
  * @default 100
373
373
  */
@@ -1 +1 @@
1
- {"version":3,"file":"LibVlcPlayer.types.js","sourceRoot":"","sources":["../src/LibVlcPlayer.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ViewProps } from \"react-native\";\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/consistent-type-definitions\nexport type LibVlcPlayerModuleEvents = {};\n\nexport interface LibVlcPlayerViewRef {\n /**\n * Starts playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly play: () => Promise<void>;\n /**\n * Pauses playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly pause: () => Promise<void>;\n /**\n * Stops playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly stop: () => Promise<void>;\n /**\n * Sets the time or position of the current player\n *\n * @param value - Must be a double equal or greater than `0`\n * @param type - Defaults to `\"time\"`\n *\n * @returns A promise which resolves to `void`\n */\n readonly seek: (value: number, type?: \"time\" | \"position\") => Promise<void>;\n /**\n * Starts or stops recording the current media\n *\n * @param path - Must be a valid directory or `undefined` to stop recording\n *\n * @returns A promise which resolves to `void`\n */\n readonly record: (path?: string) => Promise<void>;\n /**\n * Takes a snapshot of the current media\n *\n * @param path - Must be a valid directory\n *\n * @returns A promise which resolves to `void`\n */\n readonly snapshot: (path: string) => Promise<void>;\n /**\n * Posts an answer to a `Dialog`\n *\n * @param action - Must be either `1` or `2`\n *\n * @returns A promise which resolves to `void`\n */\n readonly postAction: (action: 1 | 2) => Promise<void>;\n /**\n * Posts a username and password to a login `Dialog`\n *\n * @param username - Must be a valid username, can't be empty\n * @param password - Must be a valid password, can be empty\n * @param store - If `true`, store the credentials\n *\n * @returns A promise which resolves to `void`\n */\n readonly postLogin: (username: string, password: string, store?: boolean) => Promise<void>;\n /**\n * Dismisses a `Dialog`\n *\n * @returns A promise which resolves to `void`\n */\n readonly dismiss: () => Promise<void>;\n /**\n * Enters Picture-in-Picture (PiP) mode\n *\n * @note Config plugin has to be configured for Picture-in-Picture (PiP) to work\n *\n * @returns A promise which resolves to `void`\n */\n readonly startPictureInPicture: () => Promise<void>;\n /**\n * Exits Picture-in-Picture (PiP) mode\n *\n * @platform ios\n *\n * @returns A promise which resolves to `void`\n */\n readonly stopPictureInPicture: () => Promise<void>;\n}\n\nexport type LibVlcSource = string | number | null;\n\nexport type LibVlcSlaveSource = string | number;\n\nexport interface Tracks {\n audio?: number;\n video?: number;\n subtitle?: number;\n}\n\nexport interface Slave {\n source: LibVlcSlaveSource;\n type: \"audio\" | \"subtitle\";\n selected?: boolean;\n}\n\nexport type VideoAspectRatio = \"auto\" | (string & {}) | number;\n\nexport type VideoContentFit = \"contain\" | \"cover\" | \"fill\";\n\nexport type AudioMixingMode = \"mixWithOthers\" | \"duckOthers\" | \"auto\" | \"doNotMix\";\n\nexport interface NativeEventProps {\n target: number;\n}\n\nexport interface NativeEvent<T> {\n nativeEvent: T & NativeEventProps;\n}\n\nexport type LibVlcEvent<T> = Omit<T & NativeEventProps, \"target\">;\n\nexport interface Error {\n message: string;\n}\n\nexport interface Time {\n value: number;\n}\n\nexport interface Position {\n value: number;\n}\n\nexport interface Snapshot {\n path: string;\n}\n\nexport interface Dialog {\n title: string;\n text: string;\n type: \"error\" | \"login\" | \"question\";\n cancelText?: string;\n action1Text?: string;\n action2Text?: string;\n}\n\nexport interface Recording {\n path: string | null;\n isRecording: boolean;\n}\n\nexport interface Track {\n id: number;\n name: string;\n}\n\nexport interface MediaTracks {\n audio: Track[];\n video: Track[];\n subtitle: Track[];\n}\n\nexport interface MediaInfo {\n width: number;\n height: number;\n length: number;\n seekable: boolean;\n}\n\n/**\n * @hidden\n */\ntype BufferingListener = () => void;\n\n/**\n * @hidden\n */\ntype PlayingListener = () => void;\n\n/**\n * @hidden\n */\ntype PausedListener = () => void;\n\n/**\n * @hidden\n */\ntype StoppedListener = () => void;\n\n/**\n * @hidden\n */\ntype EncounteredErrorListener = (event: NativeEvent<Error>) => void;\n\n/**\n * @hidden\n */\ntype TimeChangedListener = (event: NativeEvent<Time>) => void;\n\n/**\n * @hidden\n */\ntype PositionChangedListener = (event: NativeEvent<Position>) => void;\n\n/**\n * @hidden\n */\ntype ESAddedListener = (event: NativeEvent<MediaTracks>) => void;\n\n/**\n * @hidden\n */\ntype RecordChangedListener = (event: NativeEvent<Recording>) => void;\n\n/**\n * @hidden\n */\ntype SnapshotTakenListener = (event: NativeEvent<Snapshot>) => void;\n\n/**\n * @hidden\n */\ntype DialogDisplayListener = (event: NativeEvent<Dialog>) => void;\n\n/**\n * @hidden\n */\ntype FirstPlayListener = (event: NativeEvent<MediaInfo>) => void;\n\n/**\n * @hidden\n */\ntype ForegroundListener = () => void;\n\n/**\n * @hidden\n */\ntype BackgroundListener = () => void;\n\n/**\n * @hidden\n */\ntype PictureInPictureStartListener = () => void;\n\n/**\n * @hidden\n */\ntype PictureInPictureStopListener = () => void;\n\n/**\n * @hidden\n */\nexport interface LibVlcPlayerViewNativeProps extends ViewProps {\n ref?: React.Ref<LibVlcPlayerViewRef>;\n source?: LibVlcSource;\n options?: string[];\n tracks?: Tracks;\n slaves?: Slave[];\n scale?: number;\n aspectRatio?: VideoAspectRatio;\n contentFit?: VideoContentFit;\n rate?: number;\n time?: number;\n volume?: number;\n mute?: boolean;\n audioMixingMode?: AudioMixingMode;\n repeat?: boolean;\n autoplay?: boolean;\n pictureInPicture?: boolean;\n onBuffering?: BufferingListener;\n onPlaying?: PlayingListener;\n onPaused?: PausedListener;\n onStopped?: StoppedListener;\n onEncounteredError?: EncounteredErrorListener;\n onDialogDisplay?: DialogDisplayListener;\n onTimeChanged?: TimeChangedListener;\n onPositionChanged?: PositionChangedListener;\n onESAdded?: ESAddedListener;\n onRecordChanged?: RecordChangedListener;\n onSnapshotTaken?: SnapshotTakenListener;\n onFirstPlay?: FirstPlayListener;\n onForeground?: ForegroundListener;\n onBackground?: BackgroundListener;\n onPictureInPictureStart?: PictureInPictureStartListener;\n onPictureInPictureStop?: PictureInPictureStopListener;\n}\n\nexport interface LibVlcPlayerViewProps extends ViewProps {\n /**\n * Allows getting a ref to the component instance.\n *\n * Once the component unmounts, React will set `ref.current` to `null`\n *\n * @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}\n */\n ref: React.RefObject<LibVlcPlayerViewRef | null>;\n /**\n * Sets the source of the media to be played. Set to `null` to release the player\n *\n * @example\n *\n * ```tsx\n * const BIG_BUCK_BUNNY =\n * \"https://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_h264.mov\";\n *\n * <LibVlcPlayerView source={BIG_BUCK_BUNNY} />\n * ```\n */\n source: LibVlcSource;\n /**\n * Sets the options to initialize the media with\n *\n * @see {@link https://wiki.videolan.org/VLC_command-line_help/ VideoLAN Wiki}\n *\n * @example\n *\n * ```tsx\n * const options = [\"--network-caching=1000\"];\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * options={options}\n * />\n * ```\n *\n * @default []\n */\n options?: string[];\n /**\n * Sets the player audio, video and subtitle tracks\n *\n * @example\n *\n * ```tsx\n * const tracks = {\n * audio: -1,\n * video: 1,\n * subtitle: 1,\n * };\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * tracks={tracks}\n * />\n * ```\n *\n * @default undefined\n */\n tracks?: Tracks;\n /**\n * Sets the player audio and subtitle slaves\n *\n * @example\n *\n * ```tsx\n * const slaves = [\n * {\n * source: \"file://path/to/subtitle.srt\",\n * type: \"subtitle\",\n * selected: true,\n * },\n * ];\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * slaves={slaves}\n * />\n * ```\n *\n * @default []\n */\n slaves?: Slave[];\n /**\n * Sets the player scaling factor. Must be a float equal or greater than `0`\n *\n * @default 0\n */\n scale?: number;\n /**\n * Sets the container aspect ratio. Must be a valid ratio, float, or `\"auto\"`\n *\n * @example \"16:9\"\n *\n * @default undefined\n */\n aspectRatio?: VideoAspectRatio;\n /**\n * Sets how the video should be scaled to fit in the container\n *\n * @example \"cover\"\n *\n * @default \"contain\"\n */\n contentFit?: VideoContentFit;\n /**\n * Sets the player rate. Must be a float equal or greater than `1`\n *\n * @default 1\n */\n rate?: number;\n /**\n * Sets the initial player time. Must be an integer (ms) greater than `0`\n *\n * @default 0\n */\n time?: number;\n /**\n * Sets the player volume. Must be an integer between `0` and `100`\n *\n * @default 100\n */\n volume?: number;\n /**\n * Sets the player volume to `0` when `true` and previous value is restored when `false`\n *\n * @default false\n */\n mute?: boolean;\n /**\n * Determines how the player will interact with other audio playing in the system\n *\n * @example \"doNotMix\"\n *\n * @default \"auto\"\n */\n audioMixingMode?: AudioMixingMode;\n /**\n * Determines whether the media should repeat once ended\n *\n * @default false\n */\n repeat?: boolean;\n /**\n * Determines whether the media should autoplay once created\n *\n * @default true\n */\n autoplay?: boolean;\n /**\n * Determines whether the player should allow Picture-in-Picture (PiP) mode\n *\n * @default false\n */\n pictureInPicture?: boolean;\n /**\n * Called after the `Buffering` player event\n */\n onBuffering?: () => void;\n /**\n * Called after the `Playing` player event\n */\n onPlaying?: () => void;\n /**\n * Called after the `Paused` player event\n */\n onPaused?: () => void;\n /**\n * Called after the `Stopped` player event\n */\n onStopped?: () => void;\n /**\n * Called after the `EncounteredError` player event\n */\n onEncounteredError?: (event: Error) => void;\n /**\n * Called after a `Dialog` needs to be displayed\n */\n onDialogDisplay?: (event: Dialog) => void;\n /**\n * Called after the `TimeChanged` player event\n */\n onTimeChanged?: (event: Time) => void;\n /**\n * Called after the `PositionChanged` player event\n */\n onPositionChanged?: (event: Position) => void;\n /**\n * Called after the `ESAdded` player event\n */\n onESAdded?: (event: MediaTracks) => void;\n /**\n * Called after the `RecordChanged` player event\n */\n onRecordChanged?: (event: Recording) => void;\n /**\n * Called after a media snapshot is taken\n */\n onSnapshotTaken?: (event: Snapshot) => void;\n /**\n * Called after the player first playing event\n */\n onFirstPlay?: (event: MediaInfo) => void;\n /**\n * Called after the player enters the foreground\n */\n onForeground?: () => void;\n /**\n * Called after the player enters the background\n */\n onBackground?: () => void;\n /**\n * Called after the player enters Picture-in-Picture (PiP) mode\n */\n onPictureInPictureStart?: () => void;\n /**\n * Called after the player exits Picture-in-Picture (PiP) mode\n */\n onPictureInPictureStop?: () => void;\n}\n"]}
1
+ {"version":3,"file":"LibVlcPlayer.types.js","sourceRoot":"","sources":["../src/LibVlcPlayer.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ViewProps } from \"react-native\";\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/consistent-type-definitions\nexport type LibVlcPlayerModuleEvents = {};\n\nexport interface LibVlcPlayerViewRef {\n /**\n * Starts playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly play: () => Promise<void>;\n /**\n * Pauses playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly pause: () => Promise<void>;\n /**\n * Stops playback of the current player\n *\n * @returns A promise which resolves to `void`\n */\n readonly stop: () => Promise<void>;\n /**\n * Sets the time or position of the current player\n *\n * @param value - Must be a number equal or greater than `0`\n * @param type - Defaults to `\"time\"`\n *\n * @returns A promise which resolves to `void`\n */\n readonly seek: (value: number, type?: \"time\" | \"position\") => Promise<void>;\n /**\n * Starts or stops recording the current media\n *\n * @param path - Must be a valid directory or `undefined` to stop recording\n *\n * @returns A promise which resolves to `void`\n */\n readonly record: (path?: string) => Promise<void>;\n /**\n * Takes a snapshot of the current media\n *\n * @param path - Must be a valid directory\n *\n * @returns A promise which resolves to `void`\n */\n readonly snapshot: (path: string) => Promise<void>;\n /**\n * Posts an answer to a `Dialog`\n *\n * @param action - Must be either `1` or `2`\n *\n * @returns A promise which resolves to `void`\n */\n readonly postAction: (action: 1 | 2) => Promise<void>;\n /**\n * Posts a username and password to a login `Dialog`\n *\n * @param username - Must be a valid username, can't be empty\n * @param password - Must be a valid password, can be empty\n * @param store - If `true`, store the credentials\n *\n * @returns A promise which resolves to `void`\n */\n readonly postLogin: (username: string, password: string, store?: boolean) => Promise<void>;\n /**\n * Dismisses a `Dialog`\n *\n * @returns A promise which resolves to `void`\n */\n readonly dismiss: () => Promise<void>;\n /**\n * Enters Picture-in-Picture (PiP) mode\n *\n * @note Config plugin has to be configured for Picture-in-Picture (PiP) to work\n *\n * @returns A promise which resolves to `void`\n */\n readonly startPictureInPicture: () => Promise<void>;\n /**\n * Exits Picture-in-Picture (PiP) mode\n *\n * @platform ios\n *\n * @returns A promise which resolves to `void`\n */\n readonly stopPictureInPicture: () => Promise<void>;\n}\n\nexport type LibVlcSource = string | number | null;\n\nexport type LibVlcSlaveSource = string | number;\n\nexport interface Tracks {\n audio?: number;\n video?: number;\n subtitle?: number;\n}\n\nexport interface Slave {\n source: LibVlcSlaveSource;\n type: \"audio\" | \"subtitle\";\n selected?: boolean;\n}\n\nexport type VideoAspectRatio = \"auto\" | (string & {}) | number;\n\nexport type VideoContentFit = \"contain\" | \"cover\" | \"fill\";\n\nexport type AudioMixingMode = \"mixWithOthers\" | \"duckOthers\" | \"auto\" | \"doNotMix\";\n\nexport interface NativeEventProps {\n target: number;\n}\n\nexport interface NativeEvent<T> {\n nativeEvent: T & NativeEventProps;\n}\n\nexport type LibVlcEvent<T> = Omit<T & NativeEventProps, \"target\">;\n\nexport interface Error {\n message: string;\n}\n\nexport interface Time {\n value: number;\n}\n\nexport interface Position {\n value: number;\n}\n\nexport interface Snapshot {\n path: string;\n}\n\nexport interface Dialog {\n title: string;\n text: string;\n type: \"error\" | \"login\" | \"question\";\n cancelText?: string;\n action1Text?: string;\n action2Text?: string;\n}\n\nexport interface Recording {\n path: string | null;\n isRecording: boolean;\n}\n\nexport interface Track {\n id: number;\n name: string;\n}\n\nexport interface MediaTracks {\n audio: Track[];\n video: Track[];\n subtitle: Track[];\n}\n\nexport interface MediaInfo {\n width: number;\n height: number;\n length: number;\n seekable: boolean;\n}\n\n/**\n * @hidden\n */\ntype BufferingListener = () => void;\n\n/**\n * @hidden\n */\ntype PlayingListener = () => void;\n\n/**\n * @hidden\n */\ntype PausedListener = () => void;\n\n/**\n * @hidden\n */\ntype StoppedListener = () => void;\n\n/**\n * @hidden\n */\ntype EncounteredErrorListener = (event: NativeEvent<Error>) => void;\n\n/**\n * @hidden\n */\ntype TimeChangedListener = (event: NativeEvent<Time>) => void;\n\n/**\n * @hidden\n */\ntype PositionChangedListener = (event: NativeEvent<Position>) => void;\n\n/**\n * @hidden\n */\ntype ESAddedListener = (event: NativeEvent<MediaTracks>) => void;\n\n/**\n * @hidden\n */\ntype RecordChangedListener = (event: NativeEvent<Recording>) => void;\n\n/**\n * @hidden\n */\ntype SnapshotTakenListener = (event: NativeEvent<Snapshot>) => void;\n\n/**\n * @hidden\n */\ntype DialogDisplayListener = (event: NativeEvent<Dialog>) => void;\n\n/**\n * @hidden\n */\ntype FirstPlayListener = (event: NativeEvent<MediaInfo>) => void;\n\n/**\n * @hidden\n */\ntype ForegroundListener = () => void;\n\n/**\n * @hidden\n */\ntype BackgroundListener = () => void;\n\n/**\n * @hidden\n */\ntype PictureInPictureStartListener = () => void;\n\n/**\n * @hidden\n */\ntype PictureInPictureStopListener = () => void;\n\n/**\n * @hidden\n */\nexport interface LibVlcPlayerViewNativeProps extends ViewProps {\n ref?: React.Ref<LibVlcPlayerViewRef>;\n source?: LibVlcSource;\n options?: string[];\n tracks?: Tracks;\n slaves?: Slave[];\n scale?: number;\n aspectRatio?: VideoAspectRatio;\n contentFit?: VideoContentFit;\n rate?: number;\n time?: number;\n volume?: number;\n mute?: boolean;\n audioMixingMode?: AudioMixingMode;\n repeat?: boolean;\n autoplay?: boolean;\n pictureInPicture?: boolean;\n onBuffering?: BufferingListener;\n onPlaying?: PlayingListener;\n onPaused?: PausedListener;\n onStopped?: StoppedListener;\n onEncounteredError?: EncounteredErrorListener;\n onDialogDisplay?: DialogDisplayListener;\n onTimeChanged?: TimeChangedListener;\n onPositionChanged?: PositionChangedListener;\n onESAdded?: ESAddedListener;\n onRecordChanged?: RecordChangedListener;\n onSnapshotTaken?: SnapshotTakenListener;\n onFirstPlay?: FirstPlayListener;\n onForeground?: ForegroundListener;\n onBackground?: BackgroundListener;\n onPictureInPictureStart?: PictureInPictureStartListener;\n onPictureInPictureStop?: PictureInPictureStopListener;\n}\n\nexport interface LibVlcPlayerViewProps extends ViewProps {\n /**\n * Allows getting a ref to the component instance.\n *\n * Once the component unmounts, React will set `ref.current` to `null`\n *\n * @see {@link https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom React Docs}\n */\n ref: React.RefObject<LibVlcPlayerViewRef | null>;\n /**\n * Sets the source of the media to be played. Set to `null` to release the player\n *\n * @example\n *\n * ```tsx\n * const BIG_BUCK_BUNNY =\n * \"https://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_h264.mov\";\n *\n * <LibVlcPlayerView source={BIG_BUCK_BUNNY} />\n * ```\n */\n source: LibVlcSource;\n /**\n * Sets the options to initialize the media with\n *\n * @see {@link https://wiki.videolan.org/VLC_command-line_help/ VideoLAN Wiki}\n *\n * @example\n *\n * ```tsx\n * const options = [\"--network-caching=1000\"];\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * options={options}\n * />\n * ```\n *\n * @default []\n */\n options?: string[];\n /**\n * Sets the player audio, video and subtitle tracks\n *\n * @example\n *\n * ```tsx\n * const tracks = {\n * audio: -1,\n * video: 1,\n * subtitle: 1,\n * };\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * tracks={tracks}\n * />\n * ```\n *\n * @default undefined\n */\n tracks?: Tracks;\n /**\n * Sets the player audio and subtitle slaves\n *\n * @example\n *\n * ```tsx\n * const slaves = [\n * {\n * source: \"file://path/to/subtitle.srt\",\n * type: \"subtitle\",\n * selected: true,\n * },\n * ];\n *\n * <LibVlcPlayerView\n * source={BIG_BUCK_BUNNY}\n * slaves={slaves}\n * />\n * ```\n *\n * @default []\n */\n slaves?: Slave[];\n /**\n * Sets the player scaling factor. Must be a number equal or greater than `0`\n *\n * @default 0\n */\n scale?: number;\n /**\n * Sets the container aspect ratio. Must be a valid ratio, number, or `\"auto\"`\n *\n * @example \"16:9\"\n *\n * @default undefined\n */\n aspectRatio?: VideoAspectRatio;\n /**\n * Sets how the video should be scaled to fit in the container\n *\n * @example \"cover\"\n *\n * @default \"contain\"\n */\n contentFit?: VideoContentFit;\n /**\n * Sets the player rate. Must be a number equal or greater than `1`\n *\n * @default 1\n */\n rate?: number;\n /**\n * Sets the initial player time. Must be a number equal or greater than `0`\n *\n * @default 0\n */\n time?: number;\n /**\n * Sets the player volume. Must be a number between `0` and `100`\n *\n * @default 100\n */\n volume?: number;\n /**\n * Sets the player volume to `0` when `true` and previous value is restored when `false`\n *\n * @default false\n */\n mute?: boolean;\n /**\n * Determines how the player will interact with other audio playing in the system\n *\n * @example \"doNotMix\"\n *\n * @default \"auto\"\n */\n audioMixingMode?: AudioMixingMode;\n /**\n * Determines whether the media should repeat once ended\n *\n * @default false\n */\n repeat?: boolean;\n /**\n * Determines whether the media should autoplay once created\n *\n * @default true\n */\n autoplay?: boolean;\n /**\n * Determines whether the player should allow Picture-in-Picture (PiP) mode\n *\n * @default false\n */\n pictureInPicture?: boolean;\n /**\n * Called after the `Buffering` player event\n */\n onBuffering?: () => void;\n /**\n * Called after the `Playing` player event\n */\n onPlaying?: () => void;\n /**\n * Called after the `Paused` player event\n */\n onPaused?: () => void;\n /**\n * Called after the `Stopped` player event\n */\n onStopped?: () => void;\n /**\n * Called after the `EncounteredError` player event\n */\n onEncounteredError?: (event: Error) => void;\n /**\n * Called after a `Dialog` needs to be displayed\n */\n onDialogDisplay?: (event: Dialog) => void;\n /**\n * Called after the `TimeChanged` player event\n */\n onTimeChanged?: (event: Time) => void;\n /**\n * Called after the `PositionChanged` player event\n */\n onPositionChanged?: (event: Position) => void;\n /**\n * Called after the `ESAdded` player event\n */\n onESAdded?: (event: MediaTracks) => void;\n /**\n * Called after the `RecordChanged` player event\n */\n onRecordChanged?: (event: Recording) => void;\n /**\n * Called after a media snapshot is taken\n */\n onSnapshotTaken?: (event: Snapshot) => void;\n /**\n * Called after the player first playing event\n */\n onFirstPlay?: (event: MediaInfo) => void;\n /**\n * Called after the player enters the foreground\n */\n onForeground?: () => void;\n /**\n * Called after the player enters the background\n */\n onBackground?: () => void;\n /**\n * Called after the player enters Picture-in-Picture (PiP) mode\n */\n onPictureInPictureStart?: () => void;\n /**\n * Called after the player exits Picture-in-Picture (PiP) mode\n */\n onPictureInPictureStop?: () => void;\n}\n"]}
@@ -5,6 +5,7 @@ enum MediaPlayerConstants {
5
5
  static let minPlayerVolume: Int = 0
6
6
  static let maxPlayerVolume: Int = 100
7
7
 
8
- static let retryDelayMs: Int = 200
8
+ static let expDelayMultiplier: Double = 1.5
9
+ static let retryDelayMs: Double = 200.0
9
10
  static let maxRetryCount: Int = 5
10
11
  }
@@ -224,7 +224,7 @@ class LibVlcPlayerView: ExpoView {
224
224
 
225
225
  if volume != MediaPlayerConstants.maxPlayerVolume || mute {
226
226
  // Audio instance not ready, try again
227
- retryUntil { [weak self] isLastAttempt in
227
+ retryUntil { [weak self] _ in
228
228
  guard let self else { return true }
229
229
 
230
230
  let newVolume = mute ?
@@ -233,7 +233,7 @@ class LibVlcPlayerView: ExpoView {
233
233
 
234
234
  player.audio?.volume = Int32(newVolume)
235
235
 
236
- return isLastAttempt
236
+ return false
237
237
  }
238
238
  }
239
239
 
@@ -480,10 +480,6 @@ class LibVlcPlayerView: ExpoView {
480
480
  }
481
481
  }
482
482
 
483
- private func snapshotExists(_ path: String) -> Bool {
484
- FileManager.default.fileExists(atPath: path)
485
- }
486
-
487
483
  func snapshot(_ path: String) {
488
484
  if hasVideoSize {
489
485
  let dateFormatter = DateFormatter()
@@ -491,24 +487,16 @@ class LibVlcPlayerView: ExpoView {
491
487
  let timestamp = dateFormatter.string(from: Date())
492
488
 
493
489
  let snapshotPath = path + "/vlc-snapshot-\(timestamp).jpg"
494
- let video = getVideoSize()
490
+ let video = CGSize(width: 0, height: 0) // Use original window size
495
491
 
496
492
  mediaPlayer?.saveVideoSnapshot(at: snapshotPath, withWidth: Int32(video.width), andHeight: Int32(video.height))
497
493
 
498
- retryUntil { [weak self] isLastAttempt in
499
- guard let self else { return true }
500
-
501
- let hasSnapshot = snapshotExists(snapshotPath)
494
+ let fileExists = FileManager.default.fileExists(atPath: snapshotPath)
502
495
 
503
- if hasSnapshot {
504
- onSnapshotTaken(["path": snapshotPath])
505
- } else if !isLastAttempt {
506
- mediaPlayer?.saveVideoSnapshot(at: snapshotPath, withWidth: Int32(0), andHeight: Int32(0))
507
- } else {
508
- onEncounteredError(["message": "Snapshot could not be taken"])
509
- }
510
-
511
- return hasSnapshot
496
+ if fileExists {
497
+ onSnapshotTaken(["path": snapshotPath])
498
+ } else {
499
+ onEncounteredError(["message": "Snapshot could not be taken"])
512
500
  }
513
501
  } else {
514
502
  onEncounteredError(["message": "Snapshot could not be taken"])
@@ -566,16 +554,17 @@ class LibVlcPlayerView: ExpoView {
566
554
  func retryUntil(
567
555
  maxRetries: Int = MediaPlayerConstants.maxRetryCount,
568
556
  retry: Int = 0,
569
- delay: Int = MediaPlayerConstants.retryDelayMs,
557
+ delay: Double = MediaPlayerConstants.retryDelayMs,
570
558
  block: @escaping (_ isLastAttempt: Bool) -> Bool
571
559
  ) {
572
560
  let isLastAttempt = retry >= maxRetries
573
561
 
574
562
  if block(isLastAttempt) || isLastAttempt { return }
575
563
 
576
- let expDelay = Int(Double(delay) * 1.5)
564
+ let deadline = DispatchTime.now() + .milliseconds(Int(delay))
565
+ let expDelay = delay * MediaPlayerConstants.expDelayMultiplier
577
566
 
578
- DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(delay)) { [weak self] in
567
+ DispatchQueue.main.asyncAfter(deadline: deadline) { [weak self] in
579
568
  self?.retryUntil(maxRetries: maxRetries, retry: retry + 1, delay: expDelay, block: block)
580
569
  }
581
570
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-libvlc-player",
3
- "version": "7.0.11",
3
+ "version": "7.0.13",
4
4
  "description": "LibVLC Player for Expo",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -25,7 +25,7 @@ export interface LibVlcPlayerViewRef {
25
25
  /**
26
26
  * Sets the time or position of the current player
27
27
  *
28
- * @param value - Must be a double equal or greater than `0`
28
+ * @param value - Must be a number equal or greater than `0`
29
29
  * @param type - Defaults to `"time"`
30
30
  *
31
31
  * @returns A promise which resolves to `void`
@@ -373,13 +373,13 @@ export interface LibVlcPlayerViewProps extends ViewProps {
373
373
  */
374
374
  slaves?: Slave[];
375
375
  /**
376
- * Sets the player scaling factor. Must be a float equal or greater than `0`
376
+ * Sets the player scaling factor. Must be a number equal or greater than `0`
377
377
  *
378
378
  * @default 0
379
379
  */
380
380
  scale?: number;
381
381
  /**
382
- * Sets the container aspect ratio. Must be a valid ratio, float, or `"auto"`
382
+ * Sets the container aspect ratio. Must be a valid ratio, number, or `"auto"`
383
383
  *
384
384
  * @example "16:9"
385
385
  *
@@ -395,19 +395,19 @@ export interface LibVlcPlayerViewProps extends ViewProps {
395
395
  */
396
396
  contentFit?: VideoContentFit;
397
397
  /**
398
- * Sets the player rate. Must be a float equal or greater than `1`
398
+ * Sets the player rate. Must be a number equal or greater than `1`
399
399
  *
400
400
  * @default 1
401
401
  */
402
402
  rate?: number;
403
403
  /**
404
- * Sets the initial player time. Must be an integer (ms) greater than `0`
404
+ * Sets the initial player time. Must be a number equal or greater than `0`
405
405
  *
406
406
  * @default 0
407
407
  */
408
408
  time?: number;
409
409
  /**
410
- * Sets the player volume. Must be an integer between `0` and `100`
410
+ * Sets the player volume. Must be a number between `0` and `100`
411
411
  *
412
412
  * @default 100
413
413
  */