react-native-nitro-player 0.7.0 → 0.7.1-alpha.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.
Files changed (110) hide show
  1. package/README.md +47 -46
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrary.kt +9 -13
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +45 -90
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridDownloadManager.kt +48 -182
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridEqualizer.kt +21 -77
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +55 -104
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +113 -123
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/ExoPlayerCore.kt +82 -0
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/ListenerRegistry.kt +48 -0
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerAndroidAuto.kt +62 -0
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +153 -1887
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +122 -0
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerNotify.kt +44 -0
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerPlayback.kt +162 -0
  15. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueue.kt +179 -0
  16. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueueBuild.kt +170 -0
  17. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerSetup.kt +28 -0
  18. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerTempQueue.kt +121 -0
  19. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerUrlLoader.kt +98 -0
  20. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +27 -18
  21. package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +150 -135
  22. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +13 -30
  23. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +102 -162
  24. package/ios/HybridDownloadManager.swift +32 -26
  25. package/ios/HybridEqualizer.swift +48 -35
  26. package/ios/HybridTrackPlayer.swift +127 -102
  27. package/ios/core/ListenerRegistry.swift +60 -0
  28. package/ios/core/TrackPlayerCore.swift +130 -2356
  29. package/ios/core/TrackPlayerListener.swift +395 -0
  30. package/ios/core/TrackPlayerNotify.swift +52 -0
  31. package/ios/core/TrackPlayerPlayback.swift +274 -0
  32. package/ios/core/TrackPlayerQueue.swift +221 -0
  33. package/ios/core/TrackPlayerQueueBuild.swift +493 -0
  34. package/ios/core/TrackPlayerTempQueue.swift +167 -0
  35. package/ios/core/TrackPlayerUrlLoader.swift +169 -0
  36. package/ios/equalizer/EqualizerCore.swift +63 -123
  37. package/ios/media/MediaSessionManager.swift +32 -49
  38. package/ios/playlist/PlaylistManager.swift +2 -9
  39. package/ios/queue/HybridPlayerQueue.swift +69 -66
  40. package/lib/hooks/useDownloadedTracks.js +16 -13
  41. package/lib/hooks/useEqualizer.d.ts +4 -4
  42. package/lib/hooks/useEqualizer.js +22 -17
  43. package/lib/hooks/useEqualizerPresets.d.ts +3 -3
  44. package/lib/hooks/useEqualizerPresets.js +12 -18
  45. package/lib/specs/AndroidAutoMediaLibrary.nitro.d.ts +2 -2
  46. package/lib/specs/AudioDevices.nitro.d.ts +2 -2
  47. package/lib/specs/DownloadManager.nitro.d.ts +10 -10
  48. package/lib/specs/Equalizer.nitro.d.ts +10 -10
  49. package/lib/specs/TrackPlayer.nitro.d.ts +38 -16
  50. package/lib/types/EqualizerTypes.d.ts +3 -3
  51. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +2 -0
  52. package/nitrogen/generated/android/c++/JFunc_void_std__vector_TrackItem__std__vector_TrackItem_.hpp +122 -0
  53. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.cpp +31 -6
  54. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.hpp +2 -2
  55. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.cpp +16 -3
  56. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.hpp +1 -1
  57. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +154 -44
  58. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +10 -10
  59. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +130 -34
  60. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +9 -9
  61. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +115 -24
  62. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +8 -8
  63. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +243 -24
  64. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +16 -8
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_TrackItem__std__vector_TrackItem_.kt +80 -0
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrarySpec.kt +3 -2
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAudioDevicesSpec.kt +2 -1
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +10 -10
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +10 -9
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +9 -8
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +45 -8
  72. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +74 -18
  73. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +380 -151
  74. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +10 -10
  75. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +12 -9
  76. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +23 -8
  77. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +82 -8
  78. package/nitrogen/generated/ios/swift/Func_void_EqualizerState.swift +46 -0
  79. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__DownloadedPlaylist_.swift +58 -0
  80. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__DownloadedTrack_.swift +58 -0
  81. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__std__string_.swift +58 -0
  82. package/nitrogen/generated/ios/swift/Func_void_std__vector_DownloadedPlaylist_.swift +46 -0
  83. package/nitrogen/generated/ios/swift/Func_void_std__vector_DownloadedTrack_.swift +46 -0
  84. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +5 -5
  85. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem__std__vector_TrackItem_.swift +46 -0
  86. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +10 -10
  87. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +141 -71
  88. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +9 -9
  89. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +105 -41
  90. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +8 -8
  91. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +95 -32
  92. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +16 -8
  93. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +267 -32
  94. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.hpp +3 -2
  95. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.hpp +2 -1
  96. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +10 -10
  97. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +10 -9
  98. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +9 -8
  99. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +8 -0
  100. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +16 -8
  101. package/package.json +5 -5
  102. package/src/hooks/useDownloadedTracks.ts +17 -13
  103. package/src/hooks/useEqualizer.ts +26 -21
  104. package/src/hooks/useEqualizerPresets.ts +15 -21
  105. package/src/specs/AndroidAutoMediaLibrary.nitro.ts +2 -2
  106. package/src/specs/AudioDevices.nitro.ts +2 -2
  107. package/src/specs/DownloadManager.nitro.ts +10 -10
  108. package/src/specs/Equalizer.nitro.ts +10 -10
  109. package/src/specs/TrackPlayer.nitro.ts +52 -16
  110. package/src/types/EqualizerTypes.ts +17 -13
@@ -268,9 +268,6 @@ class PlaylistManager {
268
268
 
269
269
  currentPlaylistId = playlistId
270
270
 
271
- // Update TrackPlayerCore
272
- TrackPlayerCore.shared.loadPlaylist(playlistId: playlistId)
273
-
274
271
  return true
275
272
  }
276
273
 
@@ -399,9 +396,7 @@ class PlaylistManager {
399
396
  let (allPlaylists, currentListeners) = queue.sync {
400
397
  (Array(playlists.values), listeners)
401
398
  }
402
- DispatchQueue.main.async {
403
- currentListeners.forEach { $0.1(allPlaylists, operation) }
404
- }
399
+ currentListeners.forEach { $0.1(allPlaylists, operation) }
405
400
  }
406
401
 
407
402
  private func notifyPlaylistChanged(_ playlistId: String, _ operation: QueueOperation?) {
@@ -413,9 +408,7 @@ class PlaylistManager {
413
408
 
414
409
  guard let (playlist, currentListeners) = result else { return }
415
410
 
416
- DispatchQueue.main.async {
417
- currentListeners.forEach { $0.1(playlist, operation) }
418
- }
411
+ currentListeners.forEach { $0.1(playlist, operation) }
419
412
  }
420
413
 
421
414
  private func scheduleSave() {
@@ -9,109 +9,112 @@ import NitroModules
9
9
 
10
10
  final class HybridPlayerQueue: HybridPlayerQueueSpec {
11
11
  private let playlistManager = PlaylistManager.shared
12
+ private let core = TrackPlayerCore.shared
12
13
 
13
- // Static storage for callbacks to ensure they persist across HybridPlayerQueue instances
14
- private static var playlistsChangeCallbacks: [([Playlist], QueueOperation?) -> Void] = []
15
- private static var playlistChangeCallbacks: [(String, Playlist, QueueOperation?) -> Void] = []
16
- private static var isPlaylistsListenerRegistered = false
17
- private static var playlistListenerIds: Set<String> = []
14
+ // Per-instance listener removers (no static storage)
15
+ private var playlistsChangeRemover: (() -> Void)?
16
+ private var playlistChangeRemovers: [() -> Void] = []
18
17
 
19
- func createPlaylist(name: String, description: String?, artwork: String?) throws -> String {
20
- return playlistManager.createPlaylist(name: name, description: description, artwork: artwork)
18
+ // MARK: - Playlist CRUD
19
+
20
+ func createPlaylist(name: String, description: String?, artwork: String?) throws -> Promise<String> {
21
+ Promise.async { self.playlistManager.createPlaylist(name: name, description: description, artwork: artwork) }
21
22
  }
22
23
 
23
- func deletePlaylist(playlistId: String) throws {
24
- _ = playlistManager.deletePlaylist(playlistId: playlistId)
24
+ func deletePlaylist(playlistId: String) throws -> Promise<Void> {
25
+ Promise.async { _ = self.playlistManager.deletePlaylist(playlistId: playlistId) }
25
26
  }
26
27
 
27
- func updatePlaylist(playlistId: String, name: String?, description: String?, artwork: String?)
28
- throws
29
- {
30
- _ = playlistManager.updatePlaylist(
31
- playlistId: playlistId, name: name, description: description, artwork: artwork)
28
+ func updatePlaylist(playlistId: String, name: String?, description: String?, artwork: String?) throws -> Promise<Void> {
29
+ Promise.async {
30
+ _ = self.playlistManager.updatePlaylist(
31
+ playlistId: playlistId, name: name, description: description, artwork: artwork)
32
+ self.core.updatePlaylist(playlistId: playlistId)
33
+ }
32
34
  }
33
35
 
34
36
  func getPlaylist(playlistId: String) throws -> Variant_NullType_Playlist {
35
37
  if let playlist = playlistManager.getPlaylist(playlistId: playlistId) {
36
38
  return Variant_NullType_Playlist.second(playlist.toGeneratedPlaylist())
37
- } else {
38
- return Variant_NullType_Playlist.first(NullType.null)
39
39
  }
40
+ return Variant_NullType_Playlist.first(NullType.null)
40
41
  }
41
42
 
42
43
  func getAllPlaylists() throws -> [Playlist] {
43
- return playlistManager.getAllPlaylists().map { $0.toGeneratedPlaylist() }
44
+ playlistManager.getAllPlaylists().map { $0.toGeneratedPlaylist() }
44
45
  }
45
46
 
46
- func addTrackToPlaylist(playlistId: String, track: TrackItem, index: Double?) throws {
47
- let insertIndex = index.map { Int($0) }
48
- _ = playlistManager.addTrackToPlaylist(playlistId: playlistId, track: track, index: insertIndex)
47
+ // MARK: - Track mutations
48
+
49
+ func addTrackToPlaylist(playlistId: String, track: TrackItem, index: Double?) throws -> Promise<Void> {
50
+ Promise.async {
51
+ _ = self.playlistManager.addTrackToPlaylist(playlistId: playlistId, track: track, index: index.map { Int($0) })
52
+ self.core.updatePlaylist(playlistId: playlistId)
53
+ }
49
54
  }
50
55
 
51
- func addTracksToPlaylist(playlistId: String, tracks: [TrackItem], index: Double?) throws {
52
- let insertIndex = index.map { Int($0) }
53
- _ = playlistManager.addTracksToPlaylist(
54
- playlistId: playlistId, tracks: tracks, index: insertIndex)
56
+ func addTracksToPlaylist(playlistId: String, tracks: [TrackItem], index: Double?) throws -> Promise<Void> {
57
+ Promise.async {
58
+ _ = self.playlistManager.addTracksToPlaylist(playlistId: playlistId, tracks: tracks, index: index.map { Int($0) })
59
+ self.core.updatePlaylist(playlistId: playlistId)
60
+ }
55
61
  }
56
62
 
57
- func removeTrackFromPlaylist(playlistId: String, trackId: String) throws {
58
- _ = playlistManager.removeTrackFromPlaylist(playlistId: playlistId, trackId: trackId)
63
+ func removeTrackFromPlaylist(playlistId: String, trackId: String) throws -> Promise<Void> {
64
+ Promise.async {
65
+ _ = self.playlistManager.removeTrackFromPlaylist(playlistId: playlistId, trackId: trackId)
66
+ self.core.updatePlaylist(playlistId: playlistId)
67
+ }
59
68
  }
60
69
 
61
- func reorderTrackInPlaylist(playlistId: String, trackId: String, newIndex: Double) throws {
62
- _ = playlistManager.reorderTrackInPlaylist(
63
- playlistId: playlistId, trackId: trackId, newIndex: Int(newIndex))
70
+ func reorderTrackInPlaylist(playlistId: String, trackId: String, newIndex: Double) throws -> Promise<Void> {
71
+ Promise.async {
72
+ _ = self.playlistManager.reorderTrackInPlaylist(
73
+ playlistId: playlistId, trackId: trackId, newIndex: Int(newIndex))
74
+ self.core.updatePlaylist(playlistId: playlistId)
75
+ }
64
76
  }
65
77
 
66
- func loadPlaylist(playlistId: String) throws {
67
- _ = playlistManager.loadPlaylist(playlistId: playlistId)
78
+ // MARK: - Playback control
79
+
80
+ func loadPlaylist(playlistId: String) throws -> Promise<Void> {
81
+ Promise.async {
82
+ // Update PlaylistManager.currentPlaylistId so getCurrentPlaylistId() returns correctly
83
+ _ = self.playlistManager.loadPlaylist(playlistId: playlistId)
84
+ await self.core.loadPlaylist(playlistId: playlistId)
85
+ }
68
86
  }
69
87
 
70
88
  func getCurrentPlaylistId() throws -> Variant_NullType_String {
71
- if let playlistId = playlistManager.getCurrentPlaylistId() {
72
- return Variant_NullType_String.second(playlistId)
73
- } else {
74
- return Variant_NullType_String.first(NullType.null)
89
+ if let id = playlistManager.getCurrentPlaylistId() {
90
+ return Variant_NullType_String.second(id)
75
91
  }
92
+ return Variant_NullType_String.first(NullType.null)
76
93
  }
77
94
 
78
- func onPlaylistsChanged(callback: @escaping ([Playlist], QueueOperation?) -> Void) throws {
79
- // Store callback in static storage so it persists across HybridPlayerQueue instances
80
- HybridPlayerQueue.playlistsChangeCallbacks.removeAll()
81
- HybridPlayerQueue.playlistsChangeCallbacks.append(callback)
82
-
83
- // Register a single listener with PlaylistManager that dispatches to all callbacks
84
- if !HybridPlayerQueue.isPlaylistsListenerRegistered {
85
- HybridPlayerQueue.isPlaylistsListenerRegistered = true
86
- _ = playlistManager.addPlaylistsChangeListener { playlists, operation in
87
- let generatedPlaylists = playlists.map { $0.toGeneratedPlaylist() }
88
- // Call all registered callbacks
89
- for cb in HybridPlayerQueue.playlistsChangeCallbacks {
90
- cb(generatedPlaylists, operation)
91
- }
92
- }
95
+ // MARK: - Events (per-instance listener storage)
96
+
97
+ func onPlaylistsChanged(callback: @escaping (_ playlists: [Playlist], _ operation: QueueOperation?) -> Void) throws {
98
+ let remover = playlistManager.addPlaylistsChangeListener { playlists, operation in
99
+ callback(playlists.map { $0.toGeneratedPlaylist() }, operation)
93
100
  }
101
+ playlistsChangeRemover = remover
94
102
  }
95
103
 
96
- func onPlaylistChanged(callback: @escaping (String, Playlist, QueueOperation?) -> Void) throws {
97
- // Store callback in static storage so it persists across HybridPlayerQueue instances
98
- HybridPlayerQueue.playlistChangeCallbacks.removeAll()
99
- HybridPlayerQueue.playlistChangeCallbacks.append(callback)
100
-
101
- // Register listeners for all existing playlists (only once per playlist)
104
+ func onPlaylistChanged(callback: @escaping (_ playlistId: String, _ playlist: Playlist, _ operation: QueueOperation?) -> Void) throws {
102
105
  let allPlaylists = playlistManager.getAllPlaylists()
103
106
  for playlist in allPlaylists {
104
- if !HybridPlayerQueue.playlistListenerIds.contains(playlist.id) {
105
- HybridPlayerQueue.playlistListenerIds.insert(playlist.id)
106
- _ = playlistManager.addPlaylistChangeListener(playlistId: playlist.id) {
107
- updatedPlaylist, operation in
108
- let generatedPlaylist = updatedPlaylist.toGeneratedPlaylist()
109
- // Call all registered callbacks
110
- for cb in HybridPlayerQueue.playlistChangeCallbacks {
111
- cb(updatedPlaylist.id, generatedPlaylist, operation)
112
- }
113
- }
107
+ let remover = playlistManager.addPlaylistChangeListener(playlistId: playlist.id) { updated, operation in
108
+ callback(updated.id, updated.toGeneratedPlaylist(), operation)
114
109
  }
110
+ playlistChangeRemovers.append(remover)
115
111
  }
116
112
  }
113
+
114
+ // MARK: - Cleanup
115
+
116
+ deinit {
117
+ playlistsChangeRemover?()
118
+ playlistChangeRemovers.forEach { $0() }
119
+ }
117
120
  }
@@ -12,21 +12,24 @@ export function useDownloadedTracks() {
12
12
  const refresh = useCallback(() => {
13
13
  if (!isMounted.current)
14
14
  return;
15
- try {
16
- const tracks = DownloadManager.getAllDownloadedTracks();
17
- const playlists = DownloadManager.getAllDownloadedPlaylists();
18
- if (isMounted.current) {
19
- setDownloadedTracks(tracks);
20
- setDownloadedPlaylists(playlists);
21
- setIsLoading(false);
15
+ const run = async () => {
16
+ try {
17
+ const tracks = await DownloadManager.getAllDownloadedTracks();
18
+ const playlists = await DownloadManager.getAllDownloadedPlaylists();
19
+ if (isMounted.current) {
20
+ setDownloadedTracks(tracks);
21
+ setDownloadedPlaylists(playlists);
22
+ setIsLoading(false);
23
+ }
22
24
  }
23
- }
24
- catch (error) {
25
- console.error('[useDownloadedTracks] Error refreshing:', error);
26
- if (isMounted.current) {
27
- setIsLoading(false);
25
+ catch (error) {
26
+ console.error('[useDownloadedTracks] Error refreshing:', error);
27
+ if (isMounted.current) {
28
+ setIsLoading(false);
29
+ }
28
30
  }
29
- }
31
+ };
32
+ void run();
30
33
  }, []);
31
34
  useEffect(() => {
32
35
  isMounted.current = true;
@@ -7,13 +7,13 @@ export interface UseEqualizerResult {
7
7
  /** Currently applied preset name */
8
8
  currentPreset: string | null;
9
9
  /** Toggle equalizer on/off */
10
- setEnabled: (enabled: boolean) => boolean;
10
+ setEnabled: (enabled: boolean) => Promise<boolean>;
11
11
  /** Set gain for a specific band */
12
- setBandGain: (bandIndex: number, gainDb: number) => boolean;
12
+ setBandGain: (bandIndex: number, gainDb: number) => Promise<boolean>;
13
13
  /** Set all band gains at once */
14
- setAllBandGains: (gains: number[]) => boolean;
14
+ setAllBandGains: (gains: number[]) => Promise<boolean>;
15
15
  /** Reset to flat response */
16
- reset: () => void;
16
+ reset: () => Promise<void>;
17
17
  /** Whether equalizer is loading */
18
18
  isLoading: boolean;
19
19
  /** Gain range (min/max in dB) */
@@ -2,11 +2,16 @@ import { useEffect, useState, useCallback, useRef } from 'react';
2
2
  import { Equalizer } from '../index';
3
3
  import { equalizerCallbackManager } from './equalizerCallbackManager';
4
4
  const DEFAULT_BANDS = [
5
- { index: 0, centerFrequency: 60, gainDb: 0, frequencyLabel: '60 Hz' },
6
- { index: 1, centerFrequency: 230, gainDb: 0, frequencyLabel: '230 Hz' },
7
- { index: 2, centerFrequency: 910, gainDb: 0, frequencyLabel: '910 Hz' },
8
- { index: 3, centerFrequency: 3600, gainDb: 0, frequencyLabel: '3.6 kHz' },
9
- { index: 4, centerFrequency: 14000, gainDb: 0, frequencyLabel: '14 kHz' },
5
+ { index: 0, centerFrequency: 31, gainDb: 0, frequencyLabel: '31 Hz' },
6
+ { index: 1, centerFrequency: 63, gainDb: 0, frequencyLabel: '63 Hz' },
7
+ { index: 2, centerFrequency: 125, gainDb: 0, frequencyLabel: '125 Hz' },
8
+ { index: 3, centerFrequency: 250, gainDb: 0, frequencyLabel: '250 Hz' },
9
+ { index: 4, centerFrequency: 500, gainDb: 0, frequencyLabel: '500 Hz' },
10
+ { index: 5, centerFrequency: 1000, gainDb: 0, frequencyLabel: '1 kHz' },
11
+ { index: 6, centerFrequency: 2000, gainDb: 0, frequencyLabel: '2 kHz' },
12
+ { index: 7, centerFrequency: 4000, gainDb: 0, frequencyLabel: '4 kHz' },
13
+ { index: 8, centerFrequency: 8000, gainDb: 0, frequencyLabel: '8 kHz' },
14
+ { index: 9, centerFrequency: 16000, gainDb: 0, frequencyLabel: '16 kHz' },
10
15
  ];
11
16
  export function useEqualizer() {
12
17
  const [isEnabled, setIsEnabledState] = useState(false);
@@ -20,7 +25,7 @@ export function useEqualizer() {
20
25
  isMounted.current = true;
21
26
  const loadState = async () => {
22
27
  try {
23
- const state = Equalizer.getState();
28
+ const state = await Equalizer.getState();
24
29
  if (isMounted.current) {
25
30
  setIsEnabledState(state.enabled);
26
31
  setBands(state.bands);
@@ -69,42 +74,42 @@ export function useEqualizer() {
69
74
  });
70
75
  return unsubscribe;
71
76
  }, []);
72
- const setEnabled = useCallback((enabled) => {
77
+ const setEnabled = useCallback(async (enabled) => {
73
78
  try {
74
- return Equalizer.setEnabled(enabled);
79
+ await Equalizer.setEnabled(enabled);
80
+ return true;
75
81
  }
76
82
  catch (error) {
77
83
  console.error('[useEqualizer] Error setting enabled:', error);
78
84
  return false;
79
85
  }
80
86
  }, []);
81
- const setBandGain = useCallback((bandIndex, gainDb) => {
82
- // Optimistic update
87
+ const setBandGain = useCallback(async (bandIndex, gainDb) => {
83
88
  setBands((prevBands) => prevBands.map((b) => (b.index === bandIndex ? { ...b, gainDb } : b)));
84
89
  try {
85
- return Equalizer.setBandGain(bandIndex, gainDb);
90
+ await Equalizer.setBandGain(bandIndex, gainDb);
91
+ return true;
86
92
  }
87
93
  catch (error) {
88
94
  console.error('[useEqualizer] Error setting band gain:', error);
89
95
  return false;
90
96
  }
91
97
  }, []);
92
- const setAllBandGains = useCallback((gains) => {
93
- // Optimistic update
98
+ const setAllBandGains = useCallback(async (gains) => {
94
99
  setBands((prevBands) => prevBands.map((b, i) => ({ ...b, gainDb: gains[i] ?? b.gainDb })));
95
100
  try {
96
- return Equalizer.setAllBandGains(gains);
101
+ await Equalizer.setAllBandGains(gains);
102
+ return true;
97
103
  }
98
104
  catch (error) {
99
105
  console.error('[useEqualizer] Error setting all band gains:', error);
100
106
  return false;
101
107
  }
102
108
  }, []);
103
- const reset = useCallback(() => {
104
- // Optimistic update
109
+ const reset = useCallback(async () => {
105
110
  setBands((prevBands) => prevBands.map((b) => ({ ...b, gainDb: 0 })));
106
111
  try {
107
- Equalizer.reset();
112
+ await Equalizer.reset();
108
113
  }
109
114
  catch (error) {
110
115
  console.error('[useEqualizer] Error resetting equalizer:', error);
@@ -7,11 +7,11 @@ export interface UseEqualizerPresetsResult {
7
7
  /** Custom user presets */
8
8
  customPresets: EqualizerPreset[];
9
9
  /** Apply a preset by name */
10
- applyPreset: (name: string) => boolean;
10
+ applyPreset: (name: string) => Promise<boolean>;
11
11
  /** Save current settings as custom preset */
12
- saveCustomPreset: (name: string) => boolean;
12
+ saveCustomPreset: (name: string) => Promise<boolean>;
13
13
  /** Delete a custom preset */
14
- deleteCustomPreset: (name: string) => boolean;
14
+ deleteCustomPreset: (name: string) => Promise<boolean>;
15
15
  /** Currently applied preset name */
16
16
  currentPreset: string | null;
17
17
  /** Whether presets are loading */
@@ -43,39 +43,33 @@ export function useEqualizerPresets() {
43
43
  });
44
44
  return unsubscribe;
45
45
  }, []);
46
- const applyPreset = useCallback((name) => {
46
+ const applyPreset = useCallback(async (name) => {
47
47
  try {
48
- const success = Equalizer.applyPreset(name);
49
- if (success) {
50
- setCurrentPreset(name);
51
- }
52
- return success;
48
+ await Equalizer.applyPreset(name);
49
+ setCurrentPreset(name);
50
+ return true;
53
51
  }
54
52
  catch (error) {
55
53
  console.error('[useEqualizerPresets] Error applying preset:', error);
56
54
  return false;
57
55
  }
58
56
  }, []);
59
- const saveCustomPreset = useCallback((name) => {
57
+ const saveCustomPreset = useCallback(async (name) => {
60
58
  try {
61
- const success = Equalizer.saveCustomPreset(name);
62
- if (success) {
63
- refreshPresets();
64
- }
65
- return success;
59
+ await Equalizer.saveCustomPreset(name);
60
+ refreshPresets();
61
+ return true;
66
62
  }
67
63
  catch (error) {
68
64
  console.error('[useEqualizerPresets] Error saving custom preset:', error);
69
65
  return false;
70
66
  }
71
67
  }, [refreshPresets]);
72
- const deleteCustomPreset = useCallback((name) => {
68
+ const deleteCustomPreset = useCallback(async (name) => {
73
69
  try {
74
- const success = Equalizer.deleteCustomPreset(name);
75
- if (success) {
76
- refreshPresets();
77
- }
78
- return success;
70
+ await Equalizer.deleteCustomPreset(name);
71
+ refreshPresets();
72
+ return true;
79
73
  }
80
74
  catch (error) {
81
75
  console.error('[useEqualizerPresets] Error deleting custom preset:', error);
@@ -12,10 +12,10 @@ export interface AndroidAutoMediaLibrary extends HybridObject<{
12
12
  *
13
13
  * @param libraryJson - JSON string of the MediaLibrary structure
14
14
  */
15
- setMediaLibrary(libraryJson: string): void;
15
+ setMediaLibrary(libraryJson: string): Promise<void>;
16
16
  /**
17
17
  * Clear the Android Auto media library
18
18
  * Falls back to showing all playlists
19
19
  */
20
- clearMediaLibrary(): void;
20
+ clearMediaLibrary(): Promise<void>;
21
21
  }
@@ -18,7 +18,7 @@ export interface AudioDevices extends HybridObject<{
18
18
  * Set the audio device
19
19
  *
20
20
  * @param deviceId - The ID of the audio device
21
- * @returns True if the audio device was set successfully, false otherwise
21
+ * @returns Promise that resolves when the device has been set
22
22
  */
23
- setAudioDevice(deviceId: number): boolean;
23
+ setAudioDevice(deviceId: number): Promise<void>;
24
24
  }
@@ -74,35 +74,35 @@ export interface DownloadManager extends HybridObject<{
74
74
  /**
75
75
  * Check if a track is downloaded
76
76
  */
77
- isTrackDownloaded(trackId: string): boolean;
77
+ isTrackDownloaded(trackId: string): Promise<boolean>;
78
78
  /**
79
79
  * Check if a playlist is fully downloaded
80
80
  */
81
- isPlaylistDownloaded(playlistId: string): boolean;
81
+ isPlaylistDownloaded(playlistId: string): Promise<boolean>;
82
82
  /**
83
83
  * Check if a playlist is partially downloaded
84
84
  */
85
- isPlaylistPartiallyDownloaded(playlistId: string): boolean;
85
+ isPlaylistPartiallyDownloaded(playlistId: string): Promise<boolean>;
86
86
  /**
87
87
  * Get downloaded track by track ID
88
88
  */
89
- getDownloadedTrack(trackId: string): DownloadedTrack | null;
89
+ getDownloadedTrack(trackId: string): Promise<DownloadedTrack | null>;
90
90
  /**
91
91
  * Get all downloaded tracks
92
92
  */
93
- getAllDownloadedTracks(): DownloadedTrack[];
93
+ getAllDownloadedTracks(): Promise<DownloadedTrack[]>;
94
94
  /**
95
95
  * Get downloaded playlist by playlist ID
96
96
  */
97
- getDownloadedPlaylist(playlistId: string): DownloadedPlaylist | null;
97
+ getDownloadedPlaylist(playlistId: string): Promise<DownloadedPlaylist | null>;
98
98
  /**
99
99
  * Get all downloaded playlists
100
100
  */
101
- getAllDownloadedPlaylists(): DownloadedPlaylist[];
101
+ getAllDownloadedPlaylists(): Promise<DownloadedPlaylist[]>;
102
102
  /**
103
103
  * Get local file path for a downloaded track
104
104
  */
105
- getLocalPath(trackId: string): string | null;
105
+ getLocalPath(trackId: string): Promise<string | null>;
106
106
  /**
107
107
  * Delete a downloaded track
108
108
  */
@@ -124,7 +124,7 @@ export interface DownloadManager extends HybridObject<{
124
124
  * Call this to clean up after manual file deletion
125
125
  * @returns number of orphaned records that were cleaned up
126
126
  */
127
- syncDownloads(): number;
127
+ syncDownloads(): Promise<number>;
128
128
  /**
129
129
  * Set playback source preference
130
130
  */
@@ -136,7 +136,7 @@ export interface DownloadManager extends HybridObject<{
136
136
  /**
137
137
  * Get the effective URL for a track (local or network based on preference)
138
138
  */
139
- getEffectiveUrl(track: TrackItem): string;
139
+ getEffectiveUrl(track: TrackItem): Promise<string>;
140
140
  /**
141
141
  * Called when download progress updates
142
142
  */
@@ -5,15 +5,15 @@ export interface Equalizer extends HybridObject<{
5
5
  ios: 'swift';
6
6
  }> {
7
7
  /** Enable or disable the equalizer */
8
- setEnabled(enabled: boolean): boolean;
8
+ setEnabled(enabled: boolean): Promise<void>;
9
9
  /** Check if equalizer is currently enabled */
10
10
  isEnabled(): boolean;
11
11
  /** Get all equalizer bands with current gain values */
12
- getBands(): EqualizerBand[];
12
+ getBands(): Promise<EqualizerBand[]>;
13
13
  /** Set gain for a specific band index (-12 to +12 dB) */
14
- setBandGain(bandIndex: number, gainDb: number): boolean;
15
- /** Set gains for all bands at once (array of 5 values) */
16
- setAllBandGains(gains: number[]): boolean;
14
+ setBandGain(bandIndex: number, gainDb: number): Promise<void>;
15
+ /** Set gains for all bands at once (array of 10 values) */
16
+ setAllBandGains(gains: number[]): Promise<void>;
17
17
  /** Get the valid gain range for bands */
18
18
  getBandRange(): GainRange;
19
19
  /** Get all available presets (built-in + custom) */
@@ -23,17 +23,17 @@ export interface Equalizer extends HybridObject<{
23
23
  /** Get custom user presets only */
24
24
  getCustomPresets(): EqualizerPreset[];
25
25
  /** Apply a preset by name */
26
- applyPreset(presetName: string): boolean;
26
+ applyPreset(presetName: string): Promise<void>;
27
27
  /** Get currently applied preset name (null if custom values) */
28
28
  getCurrentPresetName(): string | null;
29
29
  /** Save current settings as a custom preset */
30
- saveCustomPreset(name: string): boolean;
30
+ saveCustomPreset(name: string): Promise<void>;
31
31
  /** Delete a custom preset by name */
32
- deleteCustomPreset(name: string): boolean;
32
+ deleteCustomPreset(name: string): Promise<void>;
33
33
  /** Get complete equalizer state */
34
- getState(): EqualizerState;
34
+ getState(): Promise<EqualizerState>;
35
35
  /** Reset to flat response (all bands at 0 dB) */
36
- reset(): void;
36
+ reset(): Promise<void>;
37
37
  /** Called when equalizer enabled state changes */
38
38
  onEnabledChange(callback: (enabled: boolean) => void): void;
39
39
  /** Called when any band gain changes */
@@ -4,16 +4,16 @@ export interface PlayerQueue extends HybridObject<{
4
4
  android: 'kotlin';
5
5
  ios: 'swift';
6
6
  }> {
7
- createPlaylist(name: string, description?: string, artwork?: string): string;
8
- deletePlaylist(playlistId: string): void;
9
- updatePlaylist(playlistId: string, name?: string, description?: string, artwork?: string): void;
7
+ createPlaylist(name: string, description?: string, artwork?: string): Promise<string>;
8
+ deletePlaylist(playlistId: string): Promise<void>;
9
+ updatePlaylist(playlistId: string, name?: string, description?: string, artwork?: string): Promise<void>;
10
10
  getPlaylist(playlistId: string): Playlist | null;
11
11
  getAllPlaylists(): Playlist[];
12
- addTrackToPlaylist(playlistId: string, track: TrackItem, index?: number): void;
13
- addTracksToPlaylist(playlistId: string, tracks: TrackItem[], index?: number): void;
14
- removeTrackFromPlaylist(playlistId: string, trackId: string): void;
15
- reorderTrackInPlaylist(playlistId: string, trackId: string, newIndex: number): void;
16
- loadPlaylist(playlistId: string): void;
12
+ addTrackToPlaylist(playlistId: string, track: TrackItem, index?: number): Promise<void>;
13
+ addTracksToPlaylist(playlistId: string, tracks: TrackItem[], index?: number): Promise<void>;
14
+ removeTrackFromPlaylist(playlistId: string, trackId: string): Promise<void>;
15
+ reorderTrackInPlaylist(playlistId: string, trackId: string, newIndex: number): Promise<void>;
16
+ loadPlaylist(playlistId: string): Promise<void>;
17
17
  getCurrentPlaylistId(): string | null;
18
18
  onPlaylistsChanged(callback: (playlists: Playlist[], operation?: QueueOperation) => void): void;
19
19
  onPlaylistChanged(callback: (playlistId: string, playlist: Playlist, operation?: QueueOperation) => void): void;
@@ -23,27 +23,27 @@ export interface TrackPlayer extends HybridObject<{
23
23
  android: 'kotlin';
24
24
  ios: 'swift';
25
25
  }> {
26
- play(): void;
27
- pause(): void;
26
+ play(): Promise<void>;
27
+ pause(): Promise<void>;
28
28
  playSong(songId: string, fromPlaylist?: string): Promise<void>;
29
- skipToNext(): void;
29
+ skipToNext(): Promise<void>;
30
30
  skipToIndex(index: number): Promise<boolean>;
31
- skipToPrevious(): void;
32
- seek(position: number): void;
31
+ skipToPrevious(): Promise<void>;
32
+ seek(position: number): Promise<void>;
33
33
  addToUpNext(trackId: string): Promise<void>;
34
34
  playNext(trackId: string): Promise<void>;
35
35
  getActualQueue(): Promise<TrackItem[]>;
36
36
  getState(): Promise<PlayerState>;
37
- setRepeatMode(mode: RepeatMode): boolean;
37
+ setRepeatMode(mode: RepeatMode): Promise<void>;
38
38
  getRepeatMode(): RepeatMode;
39
- configure(config: PlayerConfig): void;
39
+ configure(config: PlayerConfig): Promise<void>;
40
40
  onChangeTrack(callback: (track: TrackItem, reason?: Reason) => void): void;
41
41
  onPlaybackStateChange(callback: (state: TrackPlayerState, reason?: Reason) => void): void;
42
42
  onSeek(callback: (position: number, totalDuration: number) => void): void;
43
43
  onPlaybackProgressChange(callback: (position: number, totalDuration: number, isManuallySeeked?: boolean) => void): void;
44
44
  onAndroidAutoConnectionChange(callback: (connected: boolean) => void): void;
45
45
  isAndroidAutoConnected(): boolean;
46
- setVolume(volume: number): boolean;
46
+ setVolume(volume: number): Promise<void>;
47
47
  /**
48
48
  * Update entire track objects across all playlists
49
49
  * Matches by track.id and updates all properties (url, artwork, title, etc.)
@@ -91,4 +91,26 @@ export interface TrackPlayer extends HybridObject<{
91
91
  * @returns Promise resolving to playback speed
92
92
  */
93
93
  getPlaybackSpeed(): Promise<number>;
94
+ /** Remove a track from the playNext stack by ID. Returns true if found and removed. */
95
+ removeFromPlayNext(trackId: string): Promise<boolean>;
96
+ /** Remove a track from the upNext queue by ID. Returns true if found and removed. */
97
+ removeFromUpNext(trackId: string): Promise<boolean>;
98
+ /** Clear the entire playNext stack */
99
+ clearPlayNext(): Promise<void>;
100
+ /** Clear the entire upNext queue */
101
+ clearUpNext(): Promise<void>;
102
+ /**
103
+ * Reorder a temporary track within the combined virtual queue
104
+ * (playNextStack + upNextQueue). newIndex is 0-based within that combined list.
105
+ * Returns true if the track was found and moved.
106
+ */
107
+ reorderTemporaryTrack(trackId: string, newIndex: number): Promise<boolean>;
108
+ /** Get the current playNext stack (LIFO order, index 0 plays first) */
109
+ getPlayNextQueue(): Promise<TrackItem[]>;
110
+ /** Get the current upNext queue (FIFO order, index 0 plays first) */
111
+ getUpNextQueue(): Promise<TrackItem[]>;
112
+ /**
113
+ * Register callback that fires whenever the temporary queue (playNext or upNext) changes.
114
+ */
115
+ onTemporaryQueueChange(callback: (playNextQueue: TrackItem[], upNextQueue: TrackItem[]) => void): void;
94
116
  }