react-native-nitro-player 0.3.0-alpha.9 → 0.4.0
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 +444 -4
- package/android/build.gradle +4 -1
- package/android/src/main/AndroidManifest.xml +16 -1
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrary.kt +2 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +8 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridDownloadManager.kt +225 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridEqualizer.kt +105 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +6 -6
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +37 -12
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +970 -213
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +475 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadFileManager.kt +159 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadManagerCore.kt +489 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadWorker.kt +209 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +486 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaBrowserService.kt +3 -1
- package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +14 -6
- package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +27 -0
- package/ios/HybridDownloadManager.swift +226 -0
- package/ios/HybridEqualizer.swift +111 -0
- package/ios/HybridTrackPlayer.swift +36 -8
- package/ios/core/TrackPlayerCore.swift +998 -276
- package/ios/download/DownloadDatabase.swift +493 -0
- package/ios/download/DownloadFileManager.swift +241 -0
- package/ios/download/DownloadManagerCore.swift +923 -0
- package/ios/equalizer/EqualizerCore.swift +685 -0
- package/ios/media/MediaSessionManager.swift +40 -28
- package/ios/playlist/PlaylistManager.swift +40 -9
- package/ios/queue/HybridPlayerQueue.swift +33 -13
- package/lib/hooks/downloadCallbackManager.d.ts +36 -0
- package/lib/hooks/downloadCallbackManager.js +108 -0
- package/lib/hooks/equalizerCallbackManager.d.ts +37 -0
- package/lib/hooks/equalizerCallbackManager.js +109 -0
- package/lib/hooks/index.d.ts +16 -0
- package/lib/hooks/index.js +10 -0
- package/lib/hooks/useActualQueue.d.ts +48 -0
- package/lib/hooks/useActualQueue.js +98 -0
- package/lib/hooks/useDownloadActions.d.ts +26 -0
- package/lib/hooks/useDownloadActions.js +117 -0
- package/lib/hooks/useDownloadProgress.d.ts +25 -0
- package/lib/hooks/useDownloadProgress.js +79 -0
- package/lib/hooks/useDownloadStorage.d.ts +19 -0
- package/lib/hooks/useDownloadStorage.js +60 -0
- package/lib/hooks/useDownloadedTracks.d.ts +25 -0
- package/lib/hooks/useDownloadedTracks.js +69 -0
- package/lib/hooks/useEqualizer.d.ts +25 -0
- package/lib/hooks/useEqualizer.js +124 -0
- package/lib/hooks/useEqualizerPresets.d.ts +22 -0
- package/lib/hooks/useEqualizerPresets.js +96 -0
- package/lib/hooks/useNowPlaying.js +3 -2
- package/lib/hooks/useOnChangeTrack.js +15 -12
- package/lib/hooks/useOnPlaybackStateChange.js +16 -13
- package/lib/hooks/usePlaylist.d.ts +48 -0
- package/lib/hooks/usePlaylist.js +136 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +6 -0
- package/lib/specs/DownloadManager.nitro.d.ts +152 -0
- package/lib/specs/DownloadManager.nitro.js +1 -0
- package/lib/specs/Equalizer.nitro.d.ts +43 -0
- package/lib/specs/Equalizer.nitro.js +1 -0
- package/lib/specs/TrackPlayer.nitro.d.ts +6 -2
- package/lib/types/DownloadTypes.d.ts +110 -0
- package/lib/types/DownloadTypes.js +1 -0
- package/lib/types/EqualizerTypes.d.ts +52 -0
- package/lib/types/EqualizerTypes.js +1 -0
- package/lib/types/PlayerQueue.d.ts +4 -0
- package/nitro.json +8 -0
- package/nitrogen/generated/android/NitroPlayer+autolinking.cmake +10 -1
- package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +32 -2
- package/nitrogen/generated/android/c++/JCurrentPlayingType.hpp +65 -0
- package/nitrogen/generated/android/c++/JDownloadConfig.hpp +92 -0
- package/nitrogen/generated/android/c++/JDownloadError.hpp +71 -0
- package/nitrogen/generated/android/c++/JDownloadErrorReason.hpp +74 -0
- package/nitrogen/generated/android/c++/JDownloadProgress.hpp +79 -0
- package/nitrogen/generated/android/c++/JDownloadQueueStatus.hpp +81 -0
- package/nitrogen/generated/android/c++/JDownloadState.hpp +71 -0
- package/nitrogen/generated/android/c++/JDownloadStorageInfo.hpp +73 -0
- package/nitrogen/generated/android/c++/JDownloadTask.hpp +108 -0
- package/nitrogen/generated/android/c++/JDownloadedPlaylist.hpp +111 -0
- package/nitrogen/generated/android/c++/JDownloadedTrack.hpp +92 -0
- package/nitrogen/generated/android/c++/JEqualizerBand.hpp +69 -0
- package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +78 -0
- package/nitrogen/generated/android/c++/JEqualizerState.hpp +91 -0
- package/nitrogen/generated/android/c++/JFunc_void_DownloadProgress.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_DownloadedTrack.hpp +89 -0
- package/nitrogen/generated/android/c++/JFunc_void_TrackItem_std__optional_Reason_.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__std__string__.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_Playlist_std__optional_QueueOperation_.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string_DownloadState_std__optional_DownloadError_.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +97 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Playlist__std__optional_QueueOperation_.hpp +2 -0
- package/nitrogen/generated/android/c++/JGainRange.hpp +61 -0
- package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +470 -0
- package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +99 -0
- package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +204 -0
- package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +82 -0
- package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +2 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +117 -15
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +6 -2
- package/nitrogen/generated/android/c++/JPlaybackSource.hpp +62 -0
- package/nitrogen/generated/android/c++/JPlayerState.hpp +11 -3
- package/nitrogen/generated/android/c++/JPlaylist.hpp +2 -0
- package/nitrogen/generated/android/c++/JPresetType.hpp +59 -0
- package/nitrogen/generated/android/c++/JStorageLocation.hpp +59 -0
- package/nitrogen/generated/android/c++/JTrackItem.hpp +9 -3
- package/nitrogen/generated/android/c++/JTrackPlayerState.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.hpp +74 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.hpp +84 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.hpp +85 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.hpp +80 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.hpp +2 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.hpp +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/CurrentPlayingType.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadConfig.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadError.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadErrorReason.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadProgress.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadQueueStatus.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadState.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadStorageInfo.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadTask.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedPlaylist.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedTrack.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerBand.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerPreset.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerState.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadProgress.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadedTrack.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__optional_std__variant_nitro__NullType__std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_EqualizerBand_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/GainRange.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +210 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +141 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +19 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlaybackSource.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerState.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PresetType.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/StorageLocation.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackItem.kt +7 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackPlayerState.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Double.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadError.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadTask.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedPlaylist.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedTrack.kt +59 -0
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +138 -8
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +1046 -121
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +66 -0
- package/nitrogen/generated/ios/NitroPlayerAutolinking.mm +16 -0
- package/nitrogen/generated/ios/NitroPlayerAutolinking.swift +30 -0
- package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +386 -0
- package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +223 -0
- package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +1 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +46 -6
- package/nitrogen/generated/ios/swift/CurrentPlayingType.swift +48 -0
- package/nitrogen/generated/ios/swift/DownloadConfig.swift +270 -0
- package/nitrogen/generated/ios/swift/DownloadError.swift +69 -0
- package/nitrogen/generated/ios/swift/DownloadErrorReason.swift +60 -0
- package/nitrogen/generated/ios/swift/DownloadProgress.swift +91 -0
- package/nitrogen/generated/ios/swift/DownloadQueueStatus.swift +102 -0
- package/nitrogen/generated/ios/swift/DownloadState.swift +56 -0
- package/nitrogen/generated/ios/swift/DownloadStorageInfo.swift +80 -0
- package/nitrogen/generated/ios/swift/DownloadTask.swift +315 -0
- package/nitrogen/generated/ios/swift/DownloadedPlaylist.swift +103 -0
- package/nitrogen/generated/ios/swift/DownloadedTrack.swift +147 -0
- package/nitrogen/generated/ios/swift/EqualizerBand.swift +69 -0
- package/nitrogen/generated/ios/swift/EqualizerPreset.swift +70 -0
- package/nitrogen/generated/ios/swift/EqualizerState.swift +115 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_DownloadProgress.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_DownloadStorageInfo.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_DownloadedTrack.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlayerState.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__std__string__.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift +47 -0
- package/nitrogen/generated/ios/swift/GainRange.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +90 -0
- package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +705 -0
- package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +73 -0
- package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +396 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +6 -2
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +105 -8
- package/nitrogen/generated/ios/swift/PlaybackSource.swift +44 -0
- package/nitrogen/generated/ios/swift/PlayerState.swift +13 -2
- package/nitrogen/generated/ios/swift/PresetType.swift +40 -0
- package/nitrogen/generated/ios/swift/StorageLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/TrackItem.swift +31 -1
- package/nitrogen/generated/ios/swift/TrackPlayerState.swift +4 -4
- package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_DownloadError.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_DownloadTask.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedPlaylist.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedTrack.swift +18 -0
- package/nitrogen/generated/shared/c++/CurrentPlayingType.hpp +84 -0
- package/nitrogen/generated/shared/c++/DownloadConfig.hpp +108 -0
- package/nitrogen/generated/shared/c++/DownloadError.hpp +89 -0
- package/nitrogen/generated/shared/c++/DownloadErrorReason.hpp +96 -0
- package/nitrogen/generated/shared/c++/DownloadProgress.hpp +97 -0
- package/nitrogen/generated/shared/c++/DownloadQueueStatus.hpp +99 -0
- package/nitrogen/generated/shared/c++/DownloadState.hpp +92 -0
- package/nitrogen/generated/shared/c++/DownloadStorageInfo.hpp +91 -0
- package/nitrogen/generated/shared/c++/DownloadTask.hpp +122 -0
- package/nitrogen/generated/shared/c++/DownloadedPlaylist.hpp +101 -0
- package/nitrogen/generated/shared/c++/DownloadedTrack.hpp +107 -0
- package/nitrogen/generated/shared/c++/EqualizerBand.hpp +87 -0
- package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +86 -0
- package/nitrogen/generated/shared/c++/EqualizerState.hpp +89 -0
- package/nitrogen/generated/shared/c++/GainRange.hpp +79 -0
- package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.cpp +55 -0
- package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +134 -0
- package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +38 -0
- package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +95 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +11 -5
- package/nitrogen/generated/shared/c++/PlaybackSource.hpp +80 -0
- package/nitrogen/generated/shared/c++/PlayerState.hpp +9 -2
- package/nitrogen/generated/shared/c++/PresetType.hpp +76 -0
- package/nitrogen/generated/shared/c++/StorageLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/TrackItem.hpp +7 -2
- package/nitrogen/generated/shared/c++/TrackPlayerState.hpp +5 -5
- package/package.json +1 -1
- package/src/hooks/downloadCallbackManager.ts +149 -0
- package/src/hooks/equalizerCallbackManager.ts +138 -0
- package/src/hooks/index.ts +23 -0
- package/src/hooks/useActualQueue.ts +116 -0
- package/src/hooks/useDownloadActions.ts +179 -0
- package/src/hooks/useDownloadProgress.ts +126 -0
- package/src/hooks/useDownloadStorage.ts +84 -0
- package/src/hooks/useDownloadedTracks.ts +138 -0
- package/src/hooks/useEqualizer.ts +173 -0
- package/src/hooks/useEqualizerPresets.ts +140 -0
- package/src/hooks/useNowPlaying.ts +3 -2
- package/src/hooks/useOnChangeTrack.ts +15 -11
- package/src/hooks/useOnPlaybackStateChange.ts +19 -15
- package/src/hooks/usePlaylist.ts +161 -0
- package/src/index.ts +12 -0
- package/src/specs/DownloadManager.nitro.ts +203 -0
- package/src/specs/Equalizer.nitro.ts +69 -0
- package/src/specs/TrackPlayer.nitro.ts +6 -2
- package/src/types/DownloadTypes.ts +135 -0
- package/src/types/EqualizerTypes.ts +72 -0
- package/src/types/PlayerQueue.ts +9 -0
|
@@ -106,36 +106,29 @@ class MediaSessionManager {
|
|
|
106
106
|
return .success
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
commandCenter.seekForwardCommand.
|
|
112
|
-
|
|
113
|
-
let state = core.getState()
|
|
114
|
-
let newPosition = min(state.currentPosition + Constants.seekInterval, state.totalDuration)
|
|
115
|
-
core.seek(position: newPosition)
|
|
116
|
-
return .success
|
|
117
|
-
}
|
|
109
|
+
// Disable continuous seek commands - they replace the interactive scrubber
|
|
110
|
+
// with non-interactive forward/backward buttons on the lock screen
|
|
111
|
+
commandCenter.seekForwardCommand.isEnabled = false
|
|
112
|
+
commandCenter.seekBackwardCommand.isEnabled = false
|
|
118
113
|
|
|
119
|
-
//
|
|
120
|
-
commandCenter.seekBackwardCommand.isEnabled = true
|
|
121
|
-
commandCenter.seekBackwardCommand.addTarget { [weak self] event in
|
|
122
|
-
guard let self = self, let core = self.trackPlayerCore else { return .commandFailed }
|
|
123
|
-
let state = core.getState()
|
|
124
|
-
let newPosition = max(state.currentPosition - Constants.seekInterval, 0.0)
|
|
125
|
-
core.seek(position: newPosition)
|
|
126
|
-
return .success
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Change playback position
|
|
114
|
+
// Change playback position (interactive scrubber)
|
|
130
115
|
commandCenter.changePlaybackPositionCommand.isEnabled = true
|
|
131
116
|
commandCenter.changePlaybackPositionCommand.addTarget { [weak self] event in
|
|
132
117
|
guard let self = self,
|
|
133
118
|
let core = self.trackPlayerCore,
|
|
134
|
-
let
|
|
119
|
+
let positionEvent = event as? MPChangePlaybackPositionCommandEvent
|
|
135
120
|
else {
|
|
136
121
|
return .commandFailed
|
|
137
122
|
}
|
|
138
|
-
|
|
123
|
+
// Immediately update elapsed time AND set playback rate to 0 during seek
|
|
124
|
+
// This prevents the scrubber from freezing/desyncing during the async seek operation
|
|
125
|
+
if var info = MPNowPlayingInfoCenter.default().nowPlayingInfo {
|
|
126
|
+
info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = positionEvent.positionTime
|
|
127
|
+
// Set rate to 0 to pause scrubber animation during seek
|
|
128
|
+
info[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
|
|
129
|
+
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
|
|
130
|
+
}
|
|
131
|
+
core.seek(position: positionEvent.positionTime)
|
|
139
132
|
return .success
|
|
140
133
|
}
|
|
141
134
|
}
|
|
@@ -156,20 +149,39 @@ class MediaSessionManager {
|
|
|
156
149
|
|
|
157
150
|
let state = core.getState()
|
|
158
151
|
|
|
159
|
-
|
|
152
|
+
// Use player duration if valid, otherwise fall back to track metadata duration.
|
|
153
|
+
// Duration must always be present for the lock screen scrubber to be interactive.
|
|
154
|
+
let playerDuration = state.totalDuration
|
|
155
|
+
let effectiveDuration: Double
|
|
156
|
+
if playerDuration > 0 && !playerDuration.isNaN && !playerDuration.isInfinite {
|
|
157
|
+
effectiveDuration = playerDuration
|
|
158
|
+
} else {
|
|
159
|
+
effectiveDuration = track.duration
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
var nowPlayingInfo: [String: Any] = [
|
|
160
163
|
MPMediaItemPropertyTitle: track.title,
|
|
161
164
|
MPMediaItemPropertyArtist: track.artist,
|
|
162
165
|
MPMediaItemPropertyAlbumTitle: track.album,
|
|
163
166
|
MPNowPlayingInfoPropertyElapsedPlaybackTime: state.currentPosition,
|
|
164
|
-
MPMediaItemPropertyPlaybackDuration:
|
|
167
|
+
MPMediaItemPropertyPlaybackDuration: effectiveDuration,
|
|
165
168
|
MPNowPlayingInfoPropertyPlaybackRate: state.currentState == .playing ? 1.0 : 0.0,
|
|
166
169
|
]
|
|
167
170
|
|
|
168
|
-
//
|
|
171
|
+
// Add artwork synchronously if cached, otherwise load async
|
|
169
172
|
if let artwork = track.artwork, case .second(let artworkUrl) = artwork {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
if let cachedImage = artworkCache[artworkUrl] {
|
|
174
|
+
// Artwork is cached - include it directly to avoid overwrite race condition
|
|
175
|
+
nowPlayingInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(
|
|
176
|
+
boundsSize: CGSize(width: Constants.artworkSize, height: Constants.artworkSize),
|
|
177
|
+
requestHandler: { _ in cachedImage }
|
|
178
|
+
)
|
|
179
|
+
} else {
|
|
180
|
+
// Artwork not cached - load asynchronously and update later
|
|
181
|
+
loadArtwork(url: artworkUrl) { [weak self] image in
|
|
182
|
+
guard let self = self, let image = image else { return }
|
|
183
|
+
// Re-read current nowPlayingInfo to avoid overwriting other updates
|
|
184
|
+
var updatedInfo = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? [:]
|
|
173
185
|
updatedInfo[MPMediaItemPropertyArtwork] = MPMediaItemArtwork(
|
|
174
186
|
boundsSize: CGSize(width: Constants.artworkSize, height: Constants.artworkSize),
|
|
175
187
|
requestHandler: { _ in image }
|
|
@@ -260,7 +260,8 @@ class PlaylistManager {
|
|
|
260
260
|
* Load a playlist for playback (sets it as current)
|
|
261
261
|
*/
|
|
262
262
|
func loadPlaylist(playlistId: String) -> Bool {
|
|
263
|
-
|
|
263
|
+
let exists = queue.sync { playlists[playlistId] != nil }
|
|
264
|
+
guard exists else {
|
|
264
265
|
return false
|
|
265
266
|
}
|
|
266
267
|
|
|
@@ -326,18 +327,26 @@ class PlaylistManager {
|
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
private func notifyPlaylistsChanged(_ operation: QueueOperation?) {
|
|
329
|
-
let allPlaylists = queue.sync {
|
|
330
|
-
|
|
330
|
+
let (allPlaylists, currentListeners) = queue.sync {
|
|
331
|
+
(Array(playlists.values), listeners)
|
|
332
|
+
}
|
|
333
|
+
DispatchQueue.main.async {
|
|
334
|
+
currentListeners.forEach { $0.1(allPlaylists, operation) }
|
|
331
335
|
}
|
|
332
|
-
listeners.forEach { $0.1(allPlaylists, operation) }
|
|
333
336
|
}
|
|
334
337
|
|
|
335
338
|
private func notifyPlaylistChanged(_ playlistId: String, _ operation: QueueOperation?) {
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
let result: (PlaylistModel, [(String, (PlaylistModel, QueueOperation?) -> Void)])? = queue.sync
|
|
340
|
+
{
|
|
341
|
+
guard let p = playlists[playlistId] else { return nil }
|
|
342
|
+
return (p, playlistListeners[playlistId] ?? [])
|
|
338
343
|
}
|
|
339
344
|
|
|
340
|
-
|
|
345
|
+
guard let (playlist, currentListeners) = result else { return }
|
|
346
|
+
|
|
347
|
+
DispatchQueue.main.async {
|
|
348
|
+
currentListeners.forEach { $0.1(playlist, operation) }
|
|
349
|
+
}
|
|
341
350
|
}
|
|
342
351
|
|
|
343
352
|
private func savePlaylistsToUserDefaults() {
|
|
@@ -368,6 +377,10 @@ class PlaylistManager {
|
|
|
368
377
|
} else {
|
|
369
378
|
trackDict["artwork"] = ""
|
|
370
379
|
}
|
|
380
|
+
// Serialize extraPayload to dictionary for persistence
|
|
381
|
+
if let extraPayload = track.extraPayload {
|
|
382
|
+
trackDict["extraPayload"] = extraPayload.toDictionary()
|
|
383
|
+
}
|
|
371
384
|
return trackDict
|
|
372
385
|
},
|
|
373
386
|
]
|
|
@@ -386,7 +399,6 @@ class PlaylistManager {
|
|
|
386
399
|
}
|
|
387
400
|
|
|
388
401
|
do {
|
|
389
|
-
let decoder = JSONDecoder()
|
|
390
402
|
let playlistsDict = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] ?? []
|
|
391
403
|
|
|
392
404
|
queue.sync {
|
|
@@ -417,6 +429,24 @@ class PlaylistManager {
|
|
|
417
429
|
let artwork = artworkString.flatMap {
|
|
418
430
|
!$0.isEmpty ? Variant_NullType_String.second($0) : nil
|
|
419
431
|
}
|
|
432
|
+
|
|
433
|
+
// Deserialize extraPayload from dictionary
|
|
434
|
+
var extraPayload: AnyMap? = nil
|
|
435
|
+
if let extraPayloadDict = trackDict["extraPayload"] as? [String: Any] {
|
|
436
|
+
extraPayload = AnyMap()
|
|
437
|
+
for (key, value) in extraPayloadDict {
|
|
438
|
+
if let stringValue = value as? String {
|
|
439
|
+
extraPayload?.setString(key: key, value: stringValue)
|
|
440
|
+
} else if let doubleValue = value as? Double {
|
|
441
|
+
extraPayload?.setDouble(key: key, value: doubleValue)
|
|
442
|
+
} else if let intValue = value as? Int {
|
|
443
|
+
extraPayload?.setDouble(key: key, value: Double(intValue))
|
|
444
|
+
} else if let boolValue = value as? Bool {
|
|
445
|
+
extraPayload?.setBoolean(key: key, value: boolValue)
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
420
450
|
return TrackItem(
|
|
421
451
|
id: id,
|
|
422
452
|
title: title,
|
|
@@ -424,7 +454,8 @@ class PlaylistManager {
|
|
|
424
454
|
album: album,
|
|
425
455
|
duration: duration,
|
|
426
456
|
url: url,
|
|
427
|
-
artwork: artwork
|
|
457
|
+
artwork: artwork,
|
|
458
|
+
extraPayload: extraPayload
|
|
428
459
|
)
|
|
429
460
|
}
|
|
430
461
|
|
|
@@ -9,8 +9,12 @@ import NitroModules
|
|
|
9
9
|
|
|
10
10
|
final class HybridPlayerQueue: HybridPlayerQueueSpec {
|
|
11
11
|
private let playlistManager = PlaylistManager.shared
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
|
|
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
18
|
|
|
15
19
|
func createPlaylist(name: String, description: String?, artwork: String?) throws -> String {
|
|
16
20
|
return playlistManager.createPlaylist(name: name, description: description, artwork: artwork)
|
|
@@ -72,24 +76,40 @@ final class HybridPlayerQueue: HybridPlayerQueueSpec {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
func onPlaylistsChanged(callback: @escaping ([Playlist], QueueOperation?) -> Void) throws {
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
// Store callback in static storage so it persists across HybridPlayerQueue instances
|
|
80
|
+
HybridPlayerQueue.playlistsChangeCallbacks.append(callback)
|
|
81
|
+
|
|
82
|
+
// Register a single listener with PlaylistManager that dispatches to all callbacks
|
|
83
|
+
if !HybridPlayerQueue.isPlaylistsListenerRegistered {
|
|
84
|
+
HybridPlayerQueue.isPlaylistsListenerRegistered = true
|
|
85
|
+
_ = playlistManager.addPlaylistsChangeListener { playlists, operation in
|
|
86
|
+
let generatedPlaylists = playlists.map { $0.toGeneratedPlaylist() }
|
|
87
|
+
// Call all registered callbacks
|
|
88
|
+
for cb in HybridPlayerQueue.playlistsChangeCallbacks {
|
|
89
|
+
cb(generatedPlaylists, operation)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
func onPlaylistChanged(callback: @escaping (String, Playlist, QueueOperation?) -> Void) throws {
|
|
85
|
-
//
|
|
96
|
+
// Store callback in static storage so it persists across HybridPlayerQueue instances
|
|
97
|
+
HybridPlayerQueue.playlistChangeCallbacks.append(callback)
|
|
98
|
+
|
|
99
|
+
// Register listeners for all existing playlists (only once per playlist)
|
|
86
100
|
let allPlaylists = playlistManager.getAllPlaylists()
|
|
87
101
|
for playlist in allPlaylists {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
if !HybridPlayerQueue.playlistListenerIds.contains(playlist.id) {
|
|
103
|
+
HybridPlayerQueue.playlistListenerIds.insert(playlist.id)
|
|
104
|
+
_ = playlistManager.addPlaylistChangeListener(playlistId: playlist.id) {
|
|
105
|
+
updatedPlaylist, operation in
|
|
106
|
+
let generatedPlaylist = updatedPlaylist.toGeneratedPlaylist()
|
|
107
|
+
// Call all registered callbacks
|
|
108
|
+
for cb in HybridPlayerQueue.playlistChangeCallbacks {
|
|
109
|
+
cb(updatedPlaylist.id, generatedPlaylist, operation)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
91
112
|
}
|
|
92
|
-
playlistChangeListeners[playlist.id] = removeListener
|
|
93
113
|
}
|
|
94
114
|
}
|
|
95
115
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DownloadProgress, DownloadState, DownloadedTrack, DownloadError } from '../types/DownloadTypes';
|
|
2
|
+
type ProgressCallback = (progress: DownloadProgress) => void;
|
|
3
|
+
type StateChangeCallback = (downloadId: string, trackId: string, state: DownloadState, error?: DownloadError) => void;
|
|
4
|
+
type CompleteCallback = (downloadedTrack: DownloadedTrack) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Internal subscription manager for download callbacks.
|
|
7
|
+
* Allows multiple hooks to subscribe to a single native callback.
|
|
8
|
+
*/
|
|
9
|
+
declare class DownloadCallbackSubscriptionManager {
|
|
10
|
+
private progressSubscribers;
|
|
11
|
+
private stateChangeSubscribers;
|
|
12
|
+
private completeSubscribers;
|
|
13
|
+
private isProgressRegistered;
|
|
14
|
+
private isStateChangeRegistered;
|
|
15
|
+
private isCompleteRegistered;
|
|
16
|
+
/**
|
|
17
|
+
* Subscribe to download progress updates
|
|
18
|
+
* @returns Unsubscribe function
|
|
19
|
+
*/
|
|
20
|
+
subscribeToProgress(callback: ProgressCallback): () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe to download state changes
|
|
23
|
+
* @returns Unsubscribe function
|
|
24
|
+
*/
|
|
25
|
+
subscribeToStateChange(callback: StateChangeCallback): () => void;
|
|
26
|
+
/**
|
|
27
|
+
* Subscribe to download completions
|
|
28
|
+
* @returns Unsubscribe function
|
|
29
|
+
*/
|
|
30
|
+
subscribeToComplete(callback: CompleteCallback): () => void;
|
|
31
|
+
private ensureProgressRegistered;
|
|
32
|
+
private ensureStateChangeRegistered;
|
|
33
|
+
private ensureCompleteRegistered;
|
|
34
|
+
}
|
|
35
|
+
export declare const downloadCallbackManager: DownloadCallbackSubscriptionManager;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { DownloadManager } from '../index';
|
|
2
|
+
/**
|
|
3
|
+
* Internal subscription manager for download callbacks.
|
|
4
|
+
* Allows multiple hooks to subscribe to a single native callback.
|
|
5
|
+
*/
|
|
6
|
+
class DownloadCallbackSubscriptionManager {
|
|
7
|
+
progressSubscribers = new Set();
|
|
8
|
+
stateChangeSubscribers = new Set();
|
|
9
|
+
completeSubscribers = new Set();
|
|
10
|
+
isProgressRegistered = false;
|
|
11
|
+
isStateChangeRegistered = false;
|
|
12
|
+
isCompleteRegistered = false;
|
|
13
|
+
/**
|
|
14
|
+
* Subscribe to download progress updates
|
|
15
|
+
* @returns Unsubscribe function
|
|
16
|
+
*/
|
|
17
|
+
subscribeToProgress(callback) {
|
|
18
|
+
this.progressSubscribers.add(callback);
|
|
19
|
+
this.ensureProgressRegistered();
|
|
20
|
+
return () => {
|
|
21
|
+
this.progressSubscribers.delete(callback);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to download state changes
|
|
26
|
+
* @returns Unsubscribe function
|
|
27
|
+
*/
|
|
28
|
+
subscribeToStateChange(callback) {
|
|
29
|
+
this.stateChangeSubscribers.add(callback);
|
|
30
|
+
this.ensureStateChangeRegistered();
|
|
31
|
+
return () => {
|
|
32
|
+
this.stateChangeSubscribers.delete(callback);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to download completions
|
|
37
|
+
* @returns Unsubscribe function
|
|
38
|
+
*/
|
|
39
|
+
subscribeToComplete(callback) {
|
|
40
|
+
this.completeSubscribers.add(callback);
|
|
41
|
+
this.ensureCompleteRegistered();
|
|
42
|
+
return () => {
|
|
43
|
+
this.completeSubscribers.delete(callback);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
ensureProgressRegistered() {
|
|
47
|
+
if (this.isProgressRegistered)
|
|
48
|
+
return;
|
|
49
|
+
try {
|
|
50
|
+
DownloadManager.onDownloadProgress((progress) => {
|
|
51
|
+
this.progressSubscribers.forEach((subscriber) => {
|
|
52
|
+
try {
|
|
53
|
+
subscriber(progress);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error('[DownloadCallbackManager] Error in progress subscriber:', error);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
this.isProgressRegistered = true;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
console.error('[DownloadCallbackManager] Failed to register progress callback:', error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
ensureStateChangeRegistered() {
|
|
67
|
+
if (this.isStateChangeRegistered)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
DownloadManager.onDownloadStateChange((downloadId, trackId, state, error) => {
|
|
71
|
+
this.stateChangeSubscribers.forEach((subscriber) => {
|
|
72
|
+
try {
|
|
73
|
+
subscriber(downloadId, trackId, state, error);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error('[DownloadCallbackManager] Error in state change subscriber:', err);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
this.isStateChangeRegistered = true;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error('[DownloadCallbackManager] Failed to register state change callback:', error);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
ensureCompleteRegistered() {
|
|
87
|
+
if (this.isCompleteRegistered)
|
|
88
|
+
return;
|
|
89
|
+
try {
|
|
90
|
+
DownloadManager.onDownloadComplete((downloadedTrack) => {
|
|
91
|
+
this.completeSubscribers.forEach((subscriber) => {
|
|
92
|
+
try {
|
|
93
|
+
subscriber(downloadedTrack);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error('[DownloadCallbackManager] Error in complete subscriber:', error);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
this.isCompleteRegistered = true;
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('[DownloadCallbackManager] Failed to register complete callback:', error);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Export singleton instance
|
|
108
|
+
export const downloadCallbackManager = new DownloadCallbackSubscriptionManager();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { EqualizerBand } from '../types/EqualizerTypes';
|
|
2
|
+
type EnabledChangeCallback = (enabled: boolean) => void;
|
|
3
|
+
type BandChangeCallback = (bands: EqualizerBand[]) => void;
|
|
4
|
+
type PresetChangeCallback = (presetName: string | null) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Internal subscription manager that allows multiple hooks to subscribe
|
|
7
|
+
* to equalizer callbacks. This solves the problem where registering
|
|
8
|
+
* a new callback overwrites the previous one.
|
|
9
|
+
*/
|
|
10
|
+
declare class EqualizerCallbackSubscriptionManager {
|
|
11
|
+
private enabledChangeSubscribers;
|
|
12
|
+
private bandChangeSubscribers;
|
|
13
|
+
private presetChangeSubscribers;
|
|
14
|
+
private isEnabledChangeRegistered;
|
|
15
|
+
private isBandChangeRegistered;
|
|
16
|
+
private isPresetChangeRegistered;
|
|
17
|
+
/**
|
|
18
|
+
* Subscribe to enabled state changes
|
|
19
|
+
* @returns Unsubscribe function
|
|
20
|
+
*/
|
|
21
|
+
subscribeToEnabledChange(callback: EnabledChangeCallback): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Subscribe to band changes
|
|
24
|
+
* @returns Unsubscribe function
|
|
25
|
+
*/
|
|
26
|
+
subscribeToBandChange(callback: BandChangeCallback): () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to preset changes
|
|
29
|
+
* @returns Unsubscribe function
|
|
30
|
+
*/
|
|
31
|
+
subscribeToPresetChange(callback: PresetChangeCallback): () => void;
|
|
32
|
+
private ensureEnabledChangeRegistered;
|
|
33
|
+
private ensureBandChangeRegistered;
|
|
34
|
+
private ensurePresetChangeRegistered;
|
|
35
|
+
}
|
|
36
|
+
export declare const equalizerCallbackManager: EqualizerCallbackSubscriptionManager;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Equalizer } from '../index';
|
|
2
|
+
/**
|
|
3
|
+
* Internal subscription manager that allows multiple hooks to subscribe
|
|
4
|
+
* to equalizer callbacks. This solves the problem where registering
|
|
5
|
+
* a new callback overwrites the previous one.
|
|
6
|
+
*/
|
|
7
|
+
class EqualizerCallbackSubscriptionManager {
|
|
8
|
+
enabledChangeSubscribers = new Set();
|
|
9
|
+
bandChangeSubscribers = new Set();
|
|
10
|
+
presetChangeSubscribers = new Set();
|
|
11
|
+
isEnabledChangeRegistered = false;
|
|
12
|
+
isBandChangeRegistered = false;
|
|
13
|
+
isPresetChangeRegistered = false;
|
|
14
|
+
/**
|
|
15
|
+
* Subscribe to enabled state changes
|
|
16
|
+
* @returns Unsubscribe function
|
|
17
|
+
*/
|
|
18
|
+
subscribeToEnabledChange(callback) {
|
|
19
|
+
this.enabledChangeSubscribers.add(callback);
|
|
20
|
+
this.ensureEnabledChangeRegistered();
|
|
21
|
+
return () => {
|
|
22
|
+
this.enabledChangeSubscribers.delete(callback);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Subscribe to band changes
|
|
27
|
+
* @returns Unsubscribe function
|
|
28
|
+
*/
|
|
29
|
+
subscribeToBandChange(callback) {
|
|
30
|
+
this.bandChangeSubscribers.add(callback);
|
|
31
|
+
this.ensureBandChangeRegistered();
|
|
32
|
+
return () => {
|
|
33
|
+
this.bandChangeSubscribers.delete(callback);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Subscribe to preset changes
|
|
38
|
+
* @returns Unsubscribe function
|
|
39
|
+
*/
|
|
40
|
+
subscribeToPresetChange(callback) {
|
|
41
|
+
this.presetChangeSubscribers.add(callback);
|
|
42
|
+
this.ensurePresetChangeRegistered();
|
|
43
|
+
return () => {
|
|
44
|
+
this.presetChangeSubscribers.delete(callback);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
ensureEnabledChangeRegistered() {
|
|
48
|
+
if (this.isEnabledChangeRegistered)
|
|
49
|
+
return;
|
|
50
|
+
try {
|
|
51
|
+
Equalizer.onEnabledChange((enabled) => {
|
|
52
|
+
this.enabledChangeSubscribers.forEach((subscriber) => {
|
|
53
|
+
try {
|
|
54
|
+
subscriber(enabled);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.error('[EqualizerCallbackManager] Error in enabled change subscriber:', error);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
this.isEnabledChangeRegistered = true;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.error('[EqualizerCallbackManager] Failed to register enabled change callback:', error);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
ensureBandChangeRegistered() {
|
|
68
|
+
if (this.isBandChangeRegistered)
|
|
69
|
+
return;
|
|
70
|
+
try {
|
|
71
|
+
Equalizer.onBandChange((bands) => {
|
|
72
|
+
this.bandChangeSubscribers.forEach((subscriber) => {
|
|
73
|
+
try {
|
|
74
|
+
subscriber(bands);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('[EqualizerCallbackManager] Error in band change subscriber:', error);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
this.isBandChangeRegistered = true;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('[EqualizerCallbackManager] Failed to register band change callback:', error);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
ensurePresetChangeRegistered() {
|
|
88
|
+
if (this.isPresetChangeRegistered)
|
|
89
|
+
return;
|
|
90
|
+
try {
|
|
91
|
+
Equalizer.onPresetChange((presetName) => {
|
|
92
|
+
this.presetChangeSubscribers.forEach((subscriber) => {
|
|
93
|
+
try {
|
|
94
|
+
subscriber(presetName);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error('[EqualizerCallbackManager] Error in preset change subscriber:', error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
this.isPresetChangeRegistered = true;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.error('[EqualizerCallbackManager] Failed to register preset change callback:', error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Export singleton instance
|
|
109
|
+
export const equalizerCallbackManager = new EqualizerCallbackSubscriptionManager();
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -7,3 +7,19 @@ export { useOnPlaybackProgressChange } from './useOnPlaybackProgressChange';
|
|
|
7
7
|
export { useAndroidAutoConnection } from './useAndroidAutoConnection';
|
|
8
8
|
export { useAudioDevices } from './useAudioDevices';
|
|
9
9
|
export { useNowPlaying } from './useNowPlaying';
|
|
10
|
+
export { usePlaylist } from './usePlaylist';
|
|
11
|
+
export type { UsePlaylistResult } from './usePlaylist';
|
|
12
|
+
export { useActualQueue } from './useActualQueue';
|
|
13
|
+
export type { UseActualQueueResult } from './useActualQueue';
|
|
14
|
+
export { useDownloadProgress } from './useDownloadProgress';
|
|
15
|
+
export type { UseDownloadProgressOptions, UseDownloadProgressResult, } from './useDownloadProgress';
|
|
16
|
+
export { useDownloadedTracks } from './useDownloadedTracks';
|
|
17
|
+
export type { UseDownloadedTracksResult } from './useDownloadedTracks';
|
|
18
|
+
export { useDownloadActions } from './useDownloadActions';
|
|
19
|
+
export type { UseDownloadActionsResult } from './useDownloadActions';
|
|
20
|
+
export { useDownloadStorage } from './useDownloadStorage';
|
|
21
|
+
export type { UseDownloadStorageResult } from './useDownloadStorage';
|
|
22
|
+
export { useEqualizer } from './useEqualizer';
|
|
23
|
+
export type { UseEqualizerResult } from './useEqualizer';
|
|
24
|
+
export { useEqualizerPresets } from './useEqualizerPresets';
|
|
25
|
+
export type { UseEqualizerPresetsResult } from './useEqualizerPresets';
|
package/lib/hooks/index.js
CHANGED
|
@@ -5,3 +5,13 @@ export { useOnPlaybackProgressChange } from './useOnPlaybackProgressChange';
|
|
|
5
5
|
export { useAndroidAutoConnection } from './useAndroidAutoConnection';
|
|
6
6
|
export { useAudioDevices } from './useAudioDevices';
|
|
7
7
|
export { useNowPlaying } from './useNowPlaying';
|
|
8
|
+
export { usePlaylist } from './usePlaylist';
|
|
9
|
+
export { useActualQueue } from './useActualQueue';
|
|
10
|
+
// Download hooks
|
|
11
|
+
export { useDownloadProgress } from './useDownloadProgress';
|
|
12
|
+
export { useDownloadedTracks } from './useDownloadedTracks';
|
|
13
|
+
export { useDownloadActions } from './useDownloadActions';
|
|
14
|
+
export { useDownloadStorage } from './useDownloadStorage';
|
|
15
|
+
// Equalizer hooks
|
|
16
|
+
export { useEqualizer } from './useEqualizer';
|
|
17
|
+
export { useEqualizerPresets } from './useEqualizerPresets';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { TrackItem } from '../types/PlayerQueue';
|
|
2
|
+
export interface UseActualQueueResult {
|
|
3
|
+
/** The current queue in playback order */
|
|
4
|
+
queue: TrackItem[];
|
|
5
|
+
/** Manually refresh the queue */
|
|
6
|
+
refreshQueue: () => void;
|
|
7
|
+
/** Whether the queue is currently loading */
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Hook to get the actual playback queue including temporary tracks
|
|
12
|
+
*
|
|
13
|
+
* Returns the complete queue in playback order:
|
|
14
|
+
* [tracks_before_current] + [current] + [playNext_stack] + [upNext_queue] + [remaining_tracks]
|
|
15
|
+
*
|
|
16
|
+
* Auto-updates when:
|
|
17
|
+
* - Track changes
|
|
18
|
+
* - Playback state changes
|
|
19
|
+
*
|
|
20
|
+
* Call `refreshQueue()` after adding tracks via `playNext()` or `addToUpNext()`
|
|
21
|
+
* to immediately see the updated queue.
|
|
22
|
+
*
|
|
23
|
+
* @returns Object containing queue array, refresh function, and loading state
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* function QueueView() {
|
|
28
|
+
* const { queue, refreshQueue, isLoading } = useActualQueue();
|
|
29
|
+
*
|
|
30
|
+
* const handleAddToUpNext = (trackId: string) => {
|
|
31
|
+
* TrackPlayer.addToUpNext(trackId);
|
|
32
|
+
* // Refresh queue after adding track
|
|
33
|
+
* setTimeout(refreshQueue, 100);
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* return (
|
|
37
|
+
* <ScrollView>
|
|
38
|
+
* {queue.map((track, index) => (
|
|
39
|
+
* <Text key={track.id}>
|
|
40
|
+
* {index + 1}. {track.title}
|
|
41
|
+
* </Text>
|
|
42
|
+
* ))}
|
|
43
|
+
* </ScrollView>
|
|
44
|
+
* );
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function useActualQueue(): UseActualQueueResult;
|