react-native-nitro-player 0.0.1 → 0.3.0-alpha.10

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 (47) hide show
  1. package/README.md +282 -2
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +37 -29
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +24 -0
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +408 -16
  5. package/ios/HybridAudioRoutePicker.swift +47 -46
  6. package/ios/HybridTrackPlayer.swift +22 -0
  7. package/ios/core/TrackPlayerCore.swift +538 -48
  8. package/lib/hooks/callbackManager.d.ts +28 -0
  9. package/lib/hooks/callbackManager.js +76 -0
  10. package/lib/hooks/index.d.ts +7 -0
  11. package/lib/hooks/index.js +3 -0
  12. package/lib/hooks/useActualQueue.d.ts +48 -0
  13. package/lib/hooks/useActualQueue.js +98 -0
  14. package/lib/hooks/useNowPlaying.d.ts +36 -0
  15. package/lib/hooks/useNowPlaying.js +87 -0
  16. package/lib/hooks/useOnChangeTrack.d.ts +33 -6
  17. package/lib/hooks/useOnChangeTrack.js +65 -9
  18. package/lib/hooks/useOnPlaybackStateChange.d.ts +32 -6
  19. package/lib/hooks/useOnPlaybackStateChange.js +65 -9
  20. package/lib/hooks/usePlaylist.d.ts +48 -0
  21. package/lib/hooks/usePlaylist.js +136 -0
  22. package/lib/index.d.ts +1 -0
  23. package/lib/specs/TrackPlayer.nitro.d.ts +6 -0
  24. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +46 -9
  25. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +5 -0
  26. package/nitrogen/generated/android/c++/JRepeatMode.hpp +62 -0
  27. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +20 -0
  28. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/RepeatMode.kt +22 -0
  29. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +9 -0
  30. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +3 -0
  31. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +44 -4
  32. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +5 -0
  33. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +64 -0
  34. package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
  35. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +5 -0
  36. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +12 -3
  37. package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
  38. package/package.json +13 -12
  39. package/src/hooks/callbackManager.ts +96 -0
  40. package/src/hooks/index.ts +7 -0
  41. package/src/hooks/useActualQueue.ts +116 -0
  42. package/src/hooks/useNowPlaying.ts +97 -0
  43. package/src/hooks/useOnChangeTrack.ts +77 -13
  44. package/src/hooks/useOnPlaybackStateChange.ts +83 -13
  45. package/src/hooks/usePlaylist.ts +161 -0
  46. package/src/index.ts +1 -1
  47. package/src/specs/TrackPlayer.nitro.ts +7 -0
package/README.md CHANGED
@@ -80,8 +80,116 @@ TrackPlayer.pause()
80
80
  TrackPlayer.skipToNext()
81
81
  TrackPlayer.skipToPrevious()
82
82
  TrackPlayer.seek(30) // Seek to 30 seconds
83
+
84
+ // Set repeat mode
85
+ TrackPlayer.setRepeatMode('off') // No repeat
86
+ TrackPlayer.setRepeatMode('Playlist') // Repeat entire playlist
87
+ TrackPlayer.setRepeatMode('track') // Repeat current track
88
+
89
+ // Set volume (0-100)
90
+ TrackPlayer.setVolume(50) // Set volume to 50%
91
+ TrackPlayer.setVolume(0) // Mute
92
+ TrackPlayer.setVolume(100) // Maximum volume
93
+
94
+ // Add temporary tracks to queue
95
+ TrackPlayer.addToUpNext('song-id') // Add to up-next queue (FIFO)
96
+ TrackPlayer.playNext('song-id') // Add to play-next stack (LIFO)
97
+ ```
98
+
99
+ ## Temporary Queue Management
100
+
101
+ The player supports adding temporary tracks to the queue without modifying the original playlist. These tracks are automatically removed after playing.
102
+
103
+ ### `addToUpNext(trackId: string)`
104
+
105
+ Adds a track to the **up-next queue** (FIFO - First In, First Out). Tracks play in the order they were added.
106
+
107
+ **Behavior:**
108
+
109
+ - Track is inserted after the current track and any "play next" tracks
110
+ - Multiple tracks can be added - they play in the order added
111
+ - Track is automatically removed after playing
112
+ - Does not modify the original playlist
113
+
114
+ **Example:**
115
+
116
+ ```typescript
117
+ // Add tracks to up-next queue
118
+ TrackPlayer.addToUpNext('song-1') // Will play 3rd
119
+ TrackPlayer.addToUpNext('song-2') // Will play 4th
120
+ TrackPlayer.addToUpNext('song-3') // Will play 5th
121
+ // Order: [current] → [song-1] → [song-2] → [song-3]
122
+ ```
123
+
124
+ ### `playNext(trackId: string)`
125
+
126
+ Adds a track to the **play-next stack** (LIFO - Last In, First Out). The most recently added track plays first.
127
+
128
+ **Behavior:**
129
+
130
+ - Track is inserted immediately after the current track
131
+ - Multiple tracks can be added - the last added plays first
132
+ - Track is automatically removed after playing
133
+ - Does not modify the original playlist
134
+
135
+ **Example:**
136
+
137
+ ```typescript
138
+ // Add tracks to play-next stack
139
+ TrackPlayer.playNext('song-1') // Will play 3rd
140
+ TrackPlayer.playNext('song-2') // Will play 2nd (most recent)
141
+ TrackPlayer.playNext('song-3') // Will play 1st (most recent)
142
+ // Order: [current] → [song-3] → [song-2] → [song-1]
143
+ ```
144
+
145
+ ### Queue Order
146
+
147
+ The actual playback order is:
148
+
149
+ ```
150
+ [original tracks before current]
151
+ + [CURRENT TRACK]
152
+ + [playNext stack (LIFO)]
153
+ + [upNext queue (FIFO)]
154
+ + [original tracks after current]
83
155
  ```
84
156
 
157
+ ### Clearing Temporary Tracks
158
+
159
+ Temporary tracks are automatically cleared when:
160
+
161
+ - `TrackPlayer.playSong()` is called
162
+ - `PlayerQueue.loadPlaylist()` is called
163
+ - `TrackPlayer.playFromIndex()` is called
164
+
165
+ ### Getting the Actual Queue
166
+
167
+ Use `useActualQueue()` hook to see the complete queue including temporary tracks:
168
+
169
+ ```typescript
170
+ import { useActualQueue } from 'react-native-nitro-player'
171
+
172
+ function QueueView() {
173
+ const { queue, refreshQueue, isLoading } = useActualQueue()
174
+
175
+ return (
176
+ <ScrollView>
177
+ {queue.map((track, index) => (
178
+ <View key={track.id}>
179
+ <Text>{index + 1}. {track.title}</Text>
180
+ </View>
181
+ ))}
182
+ </ScrollView>
183
+ )
184
+ }
185
+ ```
186
+
187
+ **Returns:**
188
+
189
+ - `queue: TrackItem[]` - Complete queue in playback order
190
+ - `refreshQueue: () => void` - Manually refresh the queue
191
+ - `isLoading: boolean` - Whether the queue is currently loading
192
+
85
193
  ## Core Concepts
86
194
 
87
195
  ### PlayerQueue
@@ -99,6 +207,9 @@ Controls playback. Use it to:
99
207
 
100
208
  - Play, pause, and seek
101
209
  - Skip tracks
210
+ - Control repeat mode
211
+ - Control volume
212
+ - Add temporary tracks to queue (`addToUpNext`, `playNext`)
102
213
  - Get current player state
103
214
  - Listen to playback events
104
215
 
@@ -159,6 +270,93 @@ Automatically polls for audio device changes every 2 seconds.
159
270
 
160
271
  - `devices: TAudioDevice[]` - Array of available audio devices
161
272
 
273
+ ### `useNowPlaying()`
274
+
275
+ Returns the complete current player state (same as `TrackPlayer.getState()`). This hook provides all player information in a single object and automatically updates when the player state changes.
276
+
277
+ **Returns:**
278
+
279
+ - `PlayerState` object containing:
280
+ - `currentTrack: TrackItem | null` - The current track being played, or `null` if no track is playing
281
+ - `totalDuration: number` - Total duration of the current track in seconds
282
+ - `currentState: TrackPlayerState` - Current playback state (`'playing'`, `'paused'`, or `'stopped'`)
283
+ - `currentPlaylistId: string | null` - ID of the currently loaded playlist, or `null` if no playlist is loaded
284
+ - `currentIndex: number` - Index of the current track in the playlist (-1 if no track is playing)
285
+
286
+ **Note:** This hook is equivalent to calling `TrackPlayer.getState()` but provides reactive updates. It listens to track changes and playback state changes to update automatically. Also dont rely on progress from this hook
287
+
288
+ ### `useActualQueue()`
289
+
290
+ Returns the actual playback queue including temporary tracks (from `addToUpNext` and `playNext`).
291
+
292
+ **Returns:**
293
+
294
+ - `queue: TrackItem[]` - Complete queue in playback order: `[tracks_before_current] + [current] + [playNext_stack] + [upNext_queue] + [remaining_tracks]`
295
+ - `refreshQueue: () => void` - Manually refresh the queue (useful after adding tracks)
296
+ - `isLoading: boolean` - Whether the queue is currently loading
297
+
298
+ **Auto-updates when:**
299
+
300
+ - Track changes
301
+ - Temporary tracks are added (`playNext`/`addToUpNext`)
302
+ - Playback state changes
303
+
304
+ **Example:**
305
+
306
+ ```typescript
307
+ import { useActualQueue } from 'react-native-nitro-player'
308
+
309
+ function QueueView() {
310
+ const { queue, refreshQueue, isLoading } = useActualQueue()
311
+
312
+ const handleAddToUpNext = (trackId: string) => {
313
+ TrackPlayer.addToUpNext(trackId)
314
+ // Refresh queue after adding track
315
+ setTimeout(refreshQueue, 100)
316
+ }
317
+
318
+ return (
319
+ <ScrollView>
320
+ {queue.map((track, index) => (
321
+ <View key={track.id}>
322
+ <Text>{index + 1}. {track.title}</Text>
323
+ </View>
324
+ ))}
325
+ </ScrollView>
326
+ )
327
+ }
328
+ ```
329
+
330
+ ### `usePlaylist()`
331
+
332
+ Manages playlist-related state and provides access to all playlists and tracks.
333
+
334
+ **Returns:**
335
+
336
+ - `currentPlaylist: Playlist | null` - The currently loaded playlist
337
+ - `currentPlaylistId: string | null` - ID of the currently loaded playlist
338
+ - `allPlaylists: Playlist[]` - Array of all playlists
339
+ - `allTracks: TrackItem[]` - Array of all tracks from all playlists
340
+ - `isLoading: boolean` - Whether playlists are currently loading
341
+ - `refreshPlaylists: () => void` - Manually refresh playlist data
342
+
343
+ **Example:**
344
+
345
+ ```typescript
346
+ import { usePlaylist } from 'react-native-nitro-player'
347
+
348
+ function PlaylistView() {
349
+ const { allPlaylists, allTracks, refreshPlaylists } = usePlaylist()
350
+
351
+ return (
352
+ <View>
353
+ <Text>Playlists: {allPlaylists.length}</Text>
354
+ <Text>Total Tracks: {allTracks.length}</Text>
355
+ </View>
356
+ )
357
+ }
358
+ ```
359
+
162
360
  ## Audio Device APIs
163
361
 
164
362
  ### `AudioDevices` (Android only)
@@ -183,7 +381,7 @@ import { AudioDevices } from 'react-native-nitro-player'
183
381
 
184
382
  if (AudioDevices) {
185
383
  const devices = AudioDevices.getAudioDevices()
186
- devices.forEach((device) => {
384
+ devices.forEach(device => {
187
385
  console.log(`${device.name} - Active: ${device.isActive}`)
188
386
  })
189
387
  }
@@ -228,6 +426,82 @@ if (AudioRoutePicker) {
228
426
  }
229
427
  ```
230
428
 
429
+ ## Repeat Mode
430
+
431
+ Control how tracks repeat during playback.
432
+
433
+ ### `setRepeatMode(mode: RepeatMode): boolean`
434
+
435
+ Sets the repeat mode for the player.
436
+
437
+ **Parameters:**
438
+
439
+ - `mode: 'off' | 'Playlist' | 'track'` - The repeat mode to set
440
+ - `'off'` - No repeat, playlist stops at the end
441
+ - `'Playlist'` - Repeat the entire playlist
442
+ - `'track'` - Repeat the current track only
443
+
444
+ **Returns:** `true` if successful, `false` otherwise
445
+
446
+ **Example:**
447
+
448
+ ```typescript
449
+ import { TrackPlayer } from 'react-native-nitro-player'
450
+
451
+ // Turn off repeat
452
+ TrackPlayer.setRepeatMode('off')
453
+
454
+ // Repeat entire playlist
455
+ TrackPlayer.setRepeatMode('Playlist')
456
+
457
+ // Repeat current track
458
+ TrackPlayer.setRepeatMode('track')
459
+ ```
460
+
461
+ ## Volume Control
462
+
463
+ Control the playback volume level.
464
+
465
+ ### `setVolume(volume: number): boolean`
466
+
467
+ Sets the playback volume level.
468
+
469
+ **Parameters:**
470
+
471
+ - `volume: number` - Volume level between 0 and 100
472
+ - `0` - Mute (no sound)
473
+ - `50` - Half volume
474
+ - `100` - Maximum volume
475
+
476
+ **Returns:** `true` if successful, `false` otherwise (e.g., if player is not initialized)
477
+
478
+ **Example:**
479
+
480
+ ```typescript
481
+ import { TrackPlayer } from 'react-native-nitro-player'
482
+
483
+ // Set volume to 50%
484
+ const success = TrackPlayer.setVolume(50)
485
+ if (success) {
486
+ console.log('Volume set successfully')
487
+ } else {
488
+ console.warn('Failed to set volume')
489
+ }
490
+
491
+ // Mute the player
492
+ TrackPlayer.setVolume(0)
493
+
494
+ // Set to maximum volume
495
+ TrackPlayer.setVolume(100)
496
+
497
+ // Incremental volume control
498
+ const currentVolume = 50
499
+ TrackPlayer.setVolume(currentVolume + 10) // Increase by 10%
500
+ TrackPlayer.setVolume(currentVolume - 10) // Decrease by 10%
501
+ ```
502
+
503
+ **Note:** The volume value is automatically clamped to the 0-100 range. Values outside this range will be clamped to the nearest valid value.
504
+
231
505
  ## Usage Examples
232
506
 
233
507
  ### Using React Hooks
@@ -259,6 +533,9 @@ function PlayerComponent() {
259
533
  // Check Android Auto connection
260
534
  const { isConnected } = useAndroidAutoConnection()
261
535
 
536
+ // Get complete player state (alternative to individual hooks)
537
+ const nowPlaying = useNowPlaying()
538
+
262
539
  return (
263
540
  <View>
264
541
  {track && (
@@ -266,6 +543,8 @@ function PlayerComponent() {
266
543
  )}
267
544
  <Text>State: {state}</Text>
268
545
  <Text>Progress: {position} / {totalDuration}</Text>
546
+ {/* Or use useNowPlaying for all state at once */}
547
+ <Text>Now Playing State: {nowPlaying.currentState}</Text>
269
548
  </View>
270
549
  )
271
550
  }
@@ -349,7 +628,7 @@ TrackPlayer.onPlaybackProgressChange(
349
628
  )
350
629
 
351
630
  // Listen to Android Auto connection changes
352
- TrackPlayer.onAndroidAutoConnectionChange((connected) => {
631
+ TrackPlayer.onAndroidAutoConnectionChange(connected => {
353
632
  console.log('Android Auto:', connected ? 'Connected' : 'Disconnected')
354
633
  })
355
634
  ```
@@ -572,6 +851,7 @@ AndroidAutoMediaLibraryHelper.set({
572
851
 
573
852
  - ✅ **Playlist Management**: Create, update, and manage multiple playlists
574
853
  - ✅ **Playback Controls**: Play, pause, seek, skip tracks
854
+ - ✅ **Volume Control**: Adjust playback volume (0-100)
575
855
  - ✅ **React Hooks**: Built-in hooks for reactive state management
576
856
  - ✅ **Event Listeners**: Listen to track changes, state changes, and more
577
857
  - ✅ **Android Auto Support**: Control playback from Android Auto with customizable UI
@@ -7,21 +7,21 @@ import android.os.Build
7
7
  import com.margelo.nitro.NitroModules
8
8
 
9
9
  class HybridAudioDevices : HybridAudioDevicesSpec() {
10
-
11
- val applicationContext = NitroModules.applicationContext;
10
+ val applicationContext = NitroModules.applicationContext
12
11
  private val audioManager = applicationContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
13
-
12
+
14
13
  // Device types that can be set as communication devices
15
14
  private val validCommunicationDeviceTypes: Set<Int> by lazy {
16
- val types = mutableSetOf(
17
- AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
18
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
19
- AudioDeviceInfo.TYPE_WIRED_HEADSET,
20
- AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
21
- AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
22
- AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
23
- AudioDeviceInfo.TYPE_USB_HEADSET
24
- )
15
+ val types =
16
+ mutableSetOf(
17
+ AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
18
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
19
+ AudioDeviceInfo.TYPE_WIRED_HEADSET,
20
+ AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
21
+ AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
22
+ AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
23
+ AudioDeviceInfo.TYPE_USB_HEADSET,
24
+ )
25
25
  // BLE types are only available on Android S (API 31) and above
26
26
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
27
27
  types.add(AudioDeviceInfo.TYPE_BLE_HEADSET)
@@ -29,7 +29,7 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
29
29
  }
30
30
  types
31
31
  }
32
-
32
+
33
33
  override fun getAudioDevices(): Array<TAudioDevice> {
34
34
  val devices = audioManager.getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
35
35
  var activeDevice: AudioDeviceInfo? = null
@@ -37,20 +37,23 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
37
37
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
38
38
  activeDevice = audioManager.communicationDevice
39
39
  }
40
-
40
+
41
41
  // Filter to only include valid communication devices
42
- return devices.filter { device ->
43
- validCommunicationDeviceTypes.contains(device.type)
44
- }.map { device -> TAudioDevice(
45
- id = device.id.toDouble(),
46
- name = device.productName?.toString() ?: getDeviceTypeName(device.type),
47
- type = device.type.toDouble(),
48
- isActive = device == activeDevice
49
- ) }.toTypedArray()
42
+ return devices
43
+ .filter { device ->
44
+ validCommunicationDeviceTypes.contains(device.type)
45
+ }.map { device ->
46
+ TAudioDevice(
47
+ id = device.id.toDouble(),
48
+ name = device.productName?.toString() ?: getDeviceTypeName(device.type),
49
+ type = device.type.toDouble(),
50
+ isActive = device == activeDevice,
51
+ )
52
+ }.toTypedArray()
50
53
  }
51
-
52
- private fun getDeviceTypeName(type: Int): String {
53
- return when (type) {
54
+
55
+ private fun getDeviceTypeName(type: Int): String =
56
+ when (type) {
54
57
  AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> "Built-in Earpiece"
55
58
  AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> "Built-in Speaker"
56
59
  AudioDeviceInfo.TYPE_WIRED_HEADSET -> "Wired Headset"
@@ -62,11 +65,11 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
62
65
  27 -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) "BLE Speaker" else "Type 27"
63
66
  else -> "Type $type"
64
67
  }
65
- }
66
68
 
67
69
  override fun setAudioDevice(deviceId: Double): Boolean {
68
70
  val device =
69
- audioManager.getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
71
+ audioManager
72
+ .getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
70
73
  .firstOrNull { it.id == deviceId.toInt() }
71
74
  ?: return false
72
75
 
@@ -83,21 +86,26 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
83
86
  // Pre-Android 12 fallback (best-effort)
84
87
  when (device.type) {
85
88
  android.media.AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
86
- android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP -> {
89
+ android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
90
+ -> {
87
91
  audioManager.startBluetoothSco()
88
92
  audioManager.isBluetoothScoOn = true
89
93
  true
90
94
  }
95
+
91
96
  android.media.AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> {
92
97
  audioManager.isSpeakerphoneOn = true
93
98
  true
94
99
  }
100
+
95
101
  android.media.AudioDeviceInfo.TYPE_WIRED_HEADSET,
96
- android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES -> {
102
+ android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
103
+ -> {
97
104
  audioManager.isSpeakerphoneOn = false
98
105
  audioManager.isBluetoothScoOn = false
99
106
  true
100
107
  }
108
+
101
109
  else -> {
102
110
  android.util.Log.w(TAG, "Unsupported device type for pre-Android 12: ${device.type}")
103
111
  false
@@ -53,10 +53,30 @@ class HybridTrackPlayer : HybridTrackPlayerSpec() {
53
53
  core.seek(position)
54
54
  }
55
55
 
56
+ @DoNotStrip
57
+ @Keep
58
+ override fun addToUpNext(trackId: String) {
59
+ core.addToUpNext(trackId)
60
+ }
61
+
62
+ @DoNotStrip
63
+ @Keep
64
+ override fun playNext(trackId: String) {
65
+ core.playNext(trackId)
66
+ }
67
+
68
+ @DoNotStrip
69
+ @Keep
70
+ override fun getActualQueue(): Array<TrackItem> = core.getActualQueue().toTypedArray()
71
+
56
72
  @DoNotStrip
57
73
  @Keep
58
74
  override fun getState(): PlayerState = core.getState()
59
75
 
76
+ @DoNotStrip
77
+ @Keep
78
+ override fun setRepeatMode(mode: RepeatMode): Boolean = core.setRepeatMode(mode)
79
+
60
80
  override fun onChangeTrack(callback: (track: TrackItem, reason: Reason?) -> Unit) {
61
81
  core.onChangeTrack = callback
62
82
  }
@@ -90,4 +110,8 @@ class HybridTrackPlayer : HybridTrackPlayerSpec() {
90
110
 
91
111
  @Keep
92
112
  override fun isAndroidAutoConnected(): Boolean = core.isAndroidAutoConnected()
113
+
114
+ @DoNotStrip
115
+ @Keep
116
+ override fun setVolume(volume: Double): Boolean = core.setVolume(volume)
93
117
  }