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.
Files changed (257) hide show
  1. package/README.md +444 -4
  2. package/android/build.gradle +4 -1
  3. package/android/src/main/AndroidManifest.xml +16 -1
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrary.kt +2 -0
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +8 -0
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridDownloadManager.kt +225 -0
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridEqualizer.kt +105 -0
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +6 -6
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +37 -12
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +970 -213
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +475 -0
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadFileManager.kt +159 -0
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadManagerCore.kt +489 -0
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadWorker.kt +209 -0
  15. package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +486 -0
  16. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaBrowserService.kt +3 -1
  17. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +14 -6
  18. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +27 -0
  19. package/ios/HybridDownloadManager.swift +226 -0
  20. package/ios/HybridEqualizer.swift +111 -0
  21. package/ios/HybridTrackPlayer.swift +36 -8
  22. package/ios/core/TrackPlayerCore.swift +998 -276
  23. package/ios/download/DownloadDatabase.swift +493 -0
  24. package/ios/download/DownloadFileManager.swift +241 -0
  25. package/ios/download/DownloadManagerCore.swift +923 -0
  26. package/ios/equalizer/EqualizerCore.swift +685 -0
  27. package/ios/media/MediaSessionManager.swift +40 -28
  28. package/ios/playlist/PlaylistManager.swift +40 -9
  29. package/ios/queue/HybridPlayerQueue.swift +33 -13
  30. package/lib/hooks/downloadCallbackManager.d.ts +36 -0
  31. package/lib/hooks/downloadCallbackManager.js +108 -0
  32. package/lib/hooks/equalizerCallbackManager.d.ts +37 -0
  33. package/lib/hooks/equalizerCallbackManager.js +109 -0
  34. package/lib/hooks/index.d.ts +16 -0
  35. package/lib/hooks/index.js +10 -0
  36. package/lib/hooks/useActualQueue.d.ts +48 -0
  37. package/lib/hooks/useActualQueue.js +98 -0
  38. package/lib/hooks/useDownloadActions.d.ts +26 -0
  39. package/lib/hooks/useDownloadActions.js +117 -0
  40. package/lib/hooks/useDownloadProgress.d.ts +25 -0
  41. package/lib/hooks/useDownloadProgress.js +79 -0
  42. package/lib/hooks/useDownloadStorage.d.ts +19 -0
  43. package/lib/hooks/useDownloadStorage.js +60 -0
  44. package/lib/hooks/useDownloadedTracks.d.ts +25 -0
  45. package/lib/hooks/useDownloadedTracks.js +69 -0
  46. package/lib/hooks/useEqualizer.d.ts +25 -0
  47. package/lib/hooks/useEqualizer.js +124 -0
  48. package/lib/hooks/useEqualizerPresets.d.ts +22 -0
  49. package/lib/hooks/useEqualizerPresets.js +96 -0
  50. package/lib/hooks/useNowPlaying.js +3 -2
  51. package/lib/hooks/useOnChangeTrack.js +15 -12
  52. package/lib/hooks/useOnPlaybackStateChange.js +16 -13
  53. package/lib/hooks/usePlaylist.d.ts +48 -0
  54. package/lib/hooks/usePlaylist.js +136 -0
  55. package/lib/index.d.ts +6 -0
  56. package/lib/index.js +6 -0
  57. package/lib/specs/DownloadManager.nitro.d.ts +152 -0
  58. package/lib/specs/DownloadManager.nitro.js +1 -0
  59. package/lib/specs/Equalizer.nitro.d.ts +43 -0
  60. package/lib/specs/Equalizer.nitro.js +1 -0
  61. package/lib/specs/TrackPlayer.nitro.d.ts +6 -2
  62. package/lib/types/DownloadTypes.d.ts +110 -0
  63. package/lib/types/DownloadTypes.js +1 -0
  64. package/lib/types/EqualizerTypes.d.ts +52 -0
  65. package/lib/types/EqualizerTypes.js +1 -0
  66. package/lib/types/PlayerQueue.d.ts +4 -0
  67. package/nitro.json +8 -0
  68. package/nitrogen/generated/android/NitroPlayer+autolinking.cmake +10 -1
  69. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +32 -2
  70. package/nitrogen/generated/android/c++/JCurrentPlayingType.hpp +65 -0
  71. package/nitrogen/generated/android/c++/JDownloadConfig.hpp +92 -0
  72. package/nitrogen/generated/android/c++/JDownloadError.hpp +71 -0
  73. package/nitrogen/generated/android/c++/JDownloadErrorReason.hpp +74 -0
  74. package/nitrogen/generated/android/c++/JDownloadProgress.hpp +79 -0
  75. package/nitrogen/generated/android/c++/JDownloadQueueStatus.hpp +81 -0
  76. package/nitrogen/generated/android/c++/JDownloadState.hpp +71 -0
  77. package/nitrogen/generated/android/c++/JDownloadStorageInfo.hpp +73 -0
  78. package/nitrogen/generated/android/c++/JDownloadTask.hpp +108 -0
  79. package/nitrogen/generated/android/c++/JDownloadedPlaylist.hpp +111 -0
  80. package/nitrogen/generated/android/c++/JDownloadedTrack.hpp +92 -0
  81. package/nitrogen/generated/android/c++/JEqualizerBand.hpp +69 -0
  82. package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +78 -0
  83. package/nitrogen/generated/android/c++/JEqualizerState.hpp +91 -0
  84. package/nitrogen/generated/android/c++/JFunc_void_DownloadProgress.hpp +80 -0
  85. package/nitrogen/generated/android/c++/JFunc_void_DownloadedTrack.hpp +89 -0
  86. package/nitrogen/generated/android/c++/JFunc_void_TrackItem_std__optional_Reason_.hpp +2 -0
  87. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__std__string__.hpp +81 -0
  88. package/nitrogen/generated/android/c++/JFunc_void_std__string_Playlist_std__optional_QueueOperation_.hpp +2 -0
  89. package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string_DownloadState_std__optional_DownloadError_.hpp +83 -0
  90. package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +97 -0
  91. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Playlist__std__optional_QueueOperation_.hpp +2 -0
  92. package/nitrogen/generated/android/c++/JGainRange.hpp +61 -0
  93. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +470 -0
  94. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +99 -0
  95. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +204 -0
  96. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +82 -0
  97. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +2 -0
  98. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +117 -15
  99. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +6 -2
  100. package/nitrogen/generated/android/c++/JPlaybackSource.hpp +62 -0
  101. package/nitrogen/generated/android/c++/JPlayerState.hpp +11 -3
  102. package/nitrogen/generated/android/c++/JPlaylist.hpp +2 -0
  103. package/nitrogen/generated/android/c++/JPresetType.hpp +59 -0
  104. package/nitrogen/generated/android/c++/JStorageLocation.hpp +59 -0
  105. package/nitrogen/generated/android/c++/JTrackItem.hpp +9 -3
  106. package/nitrogen/generated/android/c++/JTrackPlayerState.hpp +3 -3
  107. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
  108. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
  109. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.cpp +26 -0
  110. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.hpp +74 -0
  111. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.cpp +26 -0
  112. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.hpp +84 -0
  113. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.cpp +26 -0
  114. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.hpp +85 -0
  115. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.cpp +26 -0
  116. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.hpp +80 -0
  117. package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.hpp +2 -0
  118. package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.hpp +2 -0
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/CurrentPlayingType.kt +23 -0
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadConfig.kt +59 -0
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadError.kt +47 -0
  122. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadErrorReason.kt +26 -0
  123. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadProgress.kt +53 -0
  124. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadQueueStatus.kt +56 -0
  125. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadState.kt +25 -0
  126. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadStorageInfo.kt +50 -0
  127. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadTask.kt +65 -0
  128. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedPlaylist.kt +53 -0
  129. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedTrack.kt +56 -0
  130. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerBand.kt +47 -0
  131. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerPreset.kt +44 -0
  132. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerState.kt +44 -0
  133. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadProgress.kt +80 -0
  134. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadedTrack.kt +80 -0
  135. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__optional_std__variant_nitro__NullType__std__string__.kt +80 -0
  136. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.kt +80 -0
  137. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_EqualizerBand_.kt +80 -0
  138. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/GainRange.kt +41 -0
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +210 -0
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +141 -0
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +19 -2
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlaybackSource.kt +22 -0
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerState.kt +6 -3
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PresetType.kt +21 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/StorageLocation.kt +21 -0
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackItem.kt +7 -3
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackPlayerState.kt +2 -2
  148. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Double.kt +59 -0
  149. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadError.kt +59 -0
  150. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadTask.kt +59 -0
  151. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedPlaylist.kt +59 -0
  152. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedTrack.kt +59 -0
  153. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +138 -8
  154. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +1046 -121
  155. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +66 -0
  156. package/nitrogen/generated/ios/NitroPlayerAutolinking.mm +16 -0
  157. package/nitrogen/generated/ios/NitroPlayerAutolinking.swift +30 -0
  158. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.cpp +11 -0
  159. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +386 -0
  160. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +11 -0
  161. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +223 -0
  162. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +1 -0
  163. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +46 -6
  164. package/nitrogen/generated/ios/swift/CurrentPlayingType.swift +48 -0
  165. package/nitrogen/generated/ios/swift/DownloadConfig.swift +270 -0
  166. package/nitrogen/generated/ios/swift/DownloadError.swift +69 -0
  167. package/nitrogen/generated/ios/swift/DownloadErrorReason.swift +60 -0
  168. package/nitrogen/generated/ios/swift/DownloadProgress.swift +91 -0
  169. package/nitrogen/generated/ios/swift/DownloadQueueStatus.swift +102 -0
  170. package/nitrogen/generated/ios/swift/DownloadState.swift +56 -0
  171. package/nitrogen/generated/ios/swift/DownloadStorageInfo.swift +80 -0
  172. package/nitrogen/generated/ios/swift/DownloadTask.swift +315 -0
  173. package/nitrogen/generated/ios/swift/DownloadedPlaylist.swift +103 -0
  174. package/nitrogen/generated/ios/swift/DownloadedTrack.swift +147 -0
  175. package/nitrogen/generated/ios/swift/EqualizerBand.swift +69 -0
  176. package/nitrogen/generated/ios/swift/EqualizerPreset.swift +70 -0
  177. package/nitrogen/generated/ios/swift/EqualizerState.swift +115 -0
  178. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  179. package/nitrogen/generated/ios/swift/Func_void_DownloadProgress.swift +47 -0
  180. package/nitrogen/generated/ios/swift/Func_void_DownloadStorageInfo.swift +47 -0
  181. package/nitrogen/generated/ios/swift/Func_void_DownloadedTrack.swift +47 -0
  182. package/nitrogen/generated/ios/swift/Func_void_PlayerState.swift +47 -0
  183. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  184. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  185. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__std__string__.swift +66 -0
  186. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
  187. package/nitrogen/generated/ios/swift/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.swift +47 -0
  188. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +47 -0
  189. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +47 -0
  190. package/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift +47 -0
  191. package/nitrogen/generated/ios/swift/GainRange.swift +47 -0
  192. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +90 -0
  193. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +705 -0
  194. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +73 -0
  195. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +396 -0
  196. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +6 -2
  197. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +105 -8
  198. package/nitrogen/generated/ios/swift/PlaybackSource.swift +44 -0
  199. package/nitrogen/generated/ios/swift/PlayerState.swift +13 -2
  200. package/nitrogen/generated/ios/swift/PresetType.swift +40 -0
  201. package/nitrogen/generated/ios/swift/StorageLocation.swift +40 -0
  202. package/nitrogen/generated/ios/swift/TrackItem.swift +31 -1
  203. package/nitrogen/generated/ios/swift/TrackPlayerState.swift +4 -4
  204. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +18 -0
  205. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadError.swift +18 -0
  206. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadTask.swift +18 -0
  207. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedPlaylist.swift +18 -0
  208. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedTrack.swift +18 -0
  209. package/nitrogen/generated/shared/c++/CurrentPlayingType.hpp +84 -0
  210. package/nitrogen/generated/shared/c++/DownloadConfig.hpp +108 -0
  211. package/nitrogen/generated/shared/c++/DownloadError.hpp +89 -0
  212. package/nitrogen/generated/shared/c++/DownloadErrorReason.hpp +96 -0
  213. package/nitrogen/generated/shared/c++/DownloadProgress.hpp +97 -0
  214. package/nitrogen/generated/shared/c++/DownloadQueueStatus.hpp +99 -0
  215. package/nitrogen/generated/shared/c++/DownloadState.hpp +92 -0
  216. package/nitrogen/generated/shared/c++/DownloadStorageInfo.hpp +91 -0
  217. package/nitrogen/generated/shared/c++/DownloadTask.hpp +122 -0
  218. package/nitrogen/generated/shared/c++/DownloadedPlaylist.hpp +101 -0
  219. package/nitrogen/generated/shared/c++/DownloadedTrack.hpp +107 -0
  220. package/nitrogen/generated/shared/c++/EqualizerBand.hpp +87 -0
  221. package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +86 -0
  222. package/nitrogen/generated/shared/c++/EqualizerState.hpp +89 -0
  223. package/nitrogen/generated/shared/c++/GainRange.hpp +79 -0
  224. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.cpp +55 -0
  225. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +134 -0
  226. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +38 -0
  227. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +95 -0
  228. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +4 -0
  229. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +11 -5
  230. package/nitrogen/generated/shared/c++/PlaybackSource.hpp +80 -0
  231. package/nitrogen/generated/shared/c++/PlayerState.hpp +9 -2
  232. package/nitrogen/generated/shared/c++/PresetType.hpp +76 -0
  233. package/nitrogen/generated/shared/c++/StorageLocation.hpp +76 -0
  234. package/nitrogen/generated/shared/c++/TrackItem.hpp +7 -2
  235. package/nitrogen/generated/shared/c++/TrackPlayerState.hpp +5 -5
  236. package/package.json +1 -1
  237. package/src/hooks/downloadCallbackManager.ts +149 -0
  238. package/src/hooks/equalizerCallbackManager.ts +138 -0
  239. package/src/hooks/index.ts +23 -0
  240. package/src/hooks/useActualQueue.ts +116 -0
  241. package/src/hooks/useDownloadActions.ts +179 -0
  242. package/src/hooks/useDownloadProgress.ts +126 -0
  243. package/src/hooks/useDownloadStorage.ts +84 -0
  244. package/src/hooks/useDownloadedTracks.ts +138 -0
  245. package/src/hooks/useEqualizer.ts +173 -0
  246. package/src/hooks/useEqualizerPresets.ts +140 -0
  247. package/src/hooks/useNowPlaying.ts +3 -2
  248. package/src/hooks/useOnChangeTrack.ts +15 -11
  249. package/src/hooks/useOnPlaybackStateChange.ts +19 -15
  250. package/src/hooks/usePlaylist.ts +161 -0
  251. package/src/index.ts +12 -0
  252. package/src/specs/DownloadManager.nitro.ts +203 -0
  253. package/src/specs/Equalizer.nitro.ts +69 -0
  254. package/src/specs/TrackPlayer.nitro.ts +6 -2
  255. package/src/types/DownloadTypes.ts +135 -0
  256. package/src/types/EqualizerTypes.ts +72 -0
  257. package/src/types/PlayerQueue.ts +9 -0
@@ -0,0 +1,493 @@
1
+ //
2
+ // DownloadDatabase.swift
3
+ // NitroPlayer
4
+ //
5
+ // Created by Ritesh Shukla on 2026-01-23..
6
+ //
7
+
8
+ import Foundation
9
+ import NitroModules
10
+
11
+ /// Manages persistence of downloaded track metadata using UserDefaults
12
+ final class DownloadDatabase {
13
+
14
+ // MARK: - Singleton
15
+
16
+ static let shared = DownloadDatabase()
17
+
18
+ // MARK: - Constants
19
+
20
+ private static let downloadedTracksKey = "NitroPlayerDownloadedTracks"
21
+ private static let playlistTracksKey = "NitroPlayerPlaylistTracks"
22
+
23
+ // MARK: - Properties
24
+
25
+ private var downloadedTracks: [String: DownloadedTrackRecord] = [:]
26
+ private var playlistTracks: [String: Set<String>] = [:] // playlistId -> Set of trackIds
27
+
28
+ private let queue = DispatchQueue(
29
+ label: "com.nitroplayer.downloadDatabase", attributes: .concurrent)
30
+
31
+ // MARK: - Initialization
32
+
33
+ private init() {
34
+ loadFromDisk()
35
+ }
36
+
37
+ // MARK: - Save Operations
38
+
39
+ func saveDownloadedTrack(_ track: DownloadedTrack, playlistId: String?) {
40
+ queue.async(flags: .barrier) {
41
+ let record = DownloadedTrackRecord(
42
+ trackId: track.trackId,
43
+ originalTrack: self.trackItemToRecord(track.originalTrack),
44
+ localPath: track.localPath,
45
+ localArtworkPath: self.variantToString(track.localArtworkPath),
46
+ downloadedAt: track.downloadedAt,
47
+ fileSize: track.fileSize,
48
+ storageLocation: track.storageLocation == .private ? "private" : "public"
49
+ )
50
+
51
+ self.downloadedTracks[track.trackId] = record
52
+
53
+ // Associate with playlist if provided
54
+ if let playlistId = playlistId {
55
+ if self.playlistTracks[playlistId] == nil {
56
+ self.playlistTracks[playlistId] = Set()
57
+ }
58
+ self.playlistTracks[playlistId]?.insert(track.trackId)
59
+ }
60
+
61
+ self.saveToDisk()
62
+ }
63
+ }
64
+
65
+ // MARK: - Query Operations
66
+
67
+ func isTrackDownloaded(trackId: String) -> Bool {
68
+ return queue.sync {
69
+ guard let record = downloadedTracks[trackId] else {
70
+ print("🔍 DownloadDatabase: Track \(trackId) NOT found in database")
71
+ return false
72
+ }
73
+ // Verify file still exists
74
+ let exists = FileManager.default.fileExists(atPath: record.localPath)
75
+ if exists {
76
+ print("✅ DownloadDatabase: Track \(trackId) IS downloaded at \(record.localPath)")
77
+ } else {
78
+ print(
79
+ "❌ DownloadDatabase: Track \(trackId) record exists but file NOT found at \(record.localPath)"
80
+ )
81
+ }
82
+ return exists
83
+ }
84
+ }
85
+
86
+ func isPlaylistDownloaded(playlistId: String) -> Bool {
87
+ return queue.sync {
88
+ guard let trackIds = playlistTracks[playlistId], !trackIds.isEmpty else { return false }
89
+
90
+ // Get original playlist to check all tracks
91
+ guard let playlistModel = PlaylistManager.shared.getPlaylist(playlistId: playlistId) else {
92
+ return false
93
+ }
94
+
95
+ // Check if all tracks are downloaded
96
+ for track in playlistModel.tracks {
97
+ if !isTrackDownloaded(trackId: track.id) {
98
+ return false
99
+ }
100
+ }
101
+
102
+ return true
103
+ }
104
+ }
105
+
106
+ func isPlaylistPartiallyDownloaded(playlistId: String) -> Bool {
107
+ return queue.sync {
108
+ guard let trackIds = playlistTracks[playlistId], !trackIds.isEmpty else { return false }
109
+
110
+ // Check if at least one track is downloaded
111
+ for trackId in trackIds {
112
+ if isTrackDownloaded(trackId: trackId) {
113
+ return true
114
+ }
115
+ }
116
+
117
+ return false
118
+ }
119
+ }
120
+
121
+ func getDownloadedTrack(trackId: String) -> DownloadedTrack? {
122
+ return queue.sync {
123
+ print("🔍 DownloadDatabase.getDownloadedTrack() for trackId: \(trackId)")
124
+ print(" Total records in memory: \(downloadedTracks.count)")
125
+ print(" Available trackIds: \(Array(downloadedTracks.keys))")
126
+
127
+ guard let record = downloadedTracks[trackId] else {
128
+ print(" ❌ No record found for trackId: \(trackId)")
129
+ return nil
130
+ }
131
+
132
+ print(" Found record, checking file at: \(record.localPath)")
133
+
134
+ // Verify file still exists
135
+ guard FileManager.default.fileExists(atPath: record.localPath) else {
136
+ print(" ❌ File does NOT exist, cleaning up record")
137
+ // File was deleted externally, clean up record
138
+ queue.async(flags: .barrier) {
139
+ self.downloadedTracks.removeValue(forKey: trackId)
140
+ self.saveToDisk()
141
+ }
142
+ return nil
143
+ }
144
+
145
+ print(" ✅ File exists, returning track")
146
+ return recordToDownloadedTrack(record)
147
+ }
148
+ }
149
+
150
+ func getAllDownloadedTracks() -> [DownloadedTrack] {
151
+ return queue.sync {
152
+ print(
153
+ "🎯 DownloadDatabase: getAllDownloadedTracks called, have \(downloadedTracks.count) records")
154
+
155
+ var validTracks: [DownloadedTrack] = []
156
+ var invalidTrackIds: [String] = []
157
+
158
+ for (trackId, record) in downloadedTracks {
159
+ print(" Checking track \(trackId) at path: \(record.localPath)")
160
+ if FileManager.default.fileExists(atPath: record.localPath) {
161
+ print(" ✅ File exists")
162
+ validTracks.append(recordToDownloadedTrack(record))
163
+ } else {
164
+ print(" ❌ File NOT found")
165
+ invalidTrackIds.append(trackId)
166
+ }
167
+ }
168
+
169
+ // Clean up invalid records
170
+ if !invalidTrackIds.isEmpty {
171
+ print(" Cleaning up \(invalidTrackIds.count) invalid records")
172
+ queue.async(flags: .barrier) {
173
+ for trackId in invalidTrackIds {
174
+ self.downloadedTracks.removeValue(forKey: trackId)
175
+ }
176
+ self.saveToDisk()
177
+ }
178
+ }
179
+
180
+ print("🎯 DownloadDatabase: Returning \(validTracks.count) valid tracks")
181
+ return validTracks
182
+ }
183
+ }
184
+
185
+ func getDownloadedPlaylist(playlistId: String) -> DownloadedPlaylist? {
186
+ return queue.sync { () -> DownloadedPlaylist? in
187
+ guard let trackIds = playlistTracks[playlistId], !trackIds.isEmpty else { return nil }
188
+ guard let playlistModel = PlaylistManager.shared.getPlaylist(playlistId: playlistId) else {
189
+ return nil
190
+ }
191
+
192
+ var downloadedTracks: [DownloadedTrack] = []
193
+ var totalSize: Double = 0
194
+
195
+ for trackId in trackIds {
196
+ if let track = getDownloadedTrack(trackId: trackId) {
197
+ downloadedTracks.append(track)
198
+ totalSize += track.fileSize
199
+ }
200
+ }
201
+
202
+ guard !downloadedTracks.isEmpty else { return nil }
203
+
204
+ let isComplete = downloadedTracks.count == playlistModel.tracks.count
205
+
206
+ return DownloadedPlaylist(
207
+ playlistId: playlistId,
208
+ originalPlaylist: playlistModel.toGeneratedPlaylist(),
209
+ downloadedTracks: downloadedTracks,
210
+ totalSize: totalSize,
211
+ downloadedAt: downloadedTracks.map { $0.downloadedAt }.min()
212
+ ?? Date().timeIntervalSince1970,
213
+ isComplete: isComplete
214
+ )
215
+ }
216
+ }
217
+
218
+ func getAllDownloadedPlaylists() -> [DownloadedPlaylist] {
219
+ return queue.sync {
220
+ var playlists: [DownloadedPlaylist] = []
221
+
222
+ for playlistId in playlistTracks.keys {
223
+ if let playlist = getDownloadedPlaylist(playlistId: playlistId) {
224
+ playlists.append(playlist)
225
+ }
226
+ }
227
+
228
+ return playlists
229
+ }
230
+ }
231
+
232
+ // MARK: - Sync Operations
233
+
234
+ /// Validates all downloads and removes records for missing files
235
+ /// Returns the number of orphaned records that were cleaned up
236
+ func syncDownloads() -> Int {
237
+ return queue.sync(flags: .barrier) {
238
+ print("🔄 DownloadDatabase: syncDownloads called")
239
+
240
+ var removedCount = 0
241
+ var trackIdsToRemove: [String] = []
242
+
243
+ for (trackId, record) in downloadedTracks {
244
+ if !FileManager.default.fileExists(atPath: record.localPath) {
245
+ print(" ❌ Missing file for track \(trackId): \(record.localPath)")
246
+ trackIdsToRemove.append(trackId)
247
+ }
248
+ }
249
+
250
+ // Remove invalid records
251
+ for trackId in trackIdsToRemove {
252
+ downloadedTracks.removeValue(forKey: trackId)
253
+
254
+ // Also remove from playlist associations
255
+ for (playlistId, var trackIds) in playlistTracks {
256
+ if trackIds.remove(trackId) != nil {
257
+ if trackIds.isEmpty {
258
+ playlistTracks.removeValue(forKey: playlistId)
259
+ } else {
260
+ playlistTracks[playlistId] = trackIds
261
+ }
262
+ }
263
+ }
264
+
265
+ removedCount += 1
266
+ }
267
+
268
+ if removedCount > 0 {
269
+ saveToDisk()
270
+ print(" ✅ Cleaned up \(removedCount) orphaned records")
271
+ } else {
272
+ print(" ✅ All downloads are valid")
273
+ }
274
+
275
+ return removedCount
276
+ }
277
+ }
278
+
279
+ // MARK: - Delete Operations
280
+
281
+ func deleteDownloadedTrack(trackId: String) {
282
+ queue.async(flags: .barrier) {
283
+ guard let record = self.downloadedTracks[trackId] else { return }
284
+
285
+ // Delete the file
286
+ DownloadFileManager.shared.deleteFile(at: record.localPath)
287
+
288
+ // Delete artwork if exists
289
+ if let artworkPath = record.localArtworkPath {
290
+ DownloadFileManager.shared.deleteFile(at: artworkPath)
291
+ }
292
+
293
+ // Remove from records
294
+ self.downloadedTracks.removeValue(forKey: trackId)
295
+
296
+ // Remove from all playlist associations
297
+ for (playlistId, var trackIds) in self.playlistTracks {
298
+ trackIds.remove(trackId)
299
+ if trackIds.isEmpty {
300
+ self.playlistTracks.removeValue(forKey: playlistId)
301
+ } else {
302
+ self.playlistTracks[playlistId] = trackIds
303
+ }
304
+ }
305
+
306
+ self.saveToDisk()
307
+ }
308
+ }
309
+
310
+ func deleteDownloadedPlaylist(playlistId: String) {
311
+ queue.async(flags: .barrier) {
312
+ guard let trackIds = self.playlistTracks[playlistId] else { return }
313
+
314
+ // Delete all tracks in the playlist
315
+ for trackId in trackIds {
316
+ if let record = self.downloadedTracks[trackId] {
317
+ DownloadFileManager.shared.deleteFile(at: record.localPath)
318
+ if let artworkPath = record.localArtworkPath {
319
+ DownloadFileManager.shared.deleteFile(at: artworkPath)
320
+ }
321
+ self.downloadedTracks.removeValue(forKey: trackId)
322
+ }
323
+ }
324
+
325
+ // Remove playlist association
326
+ self.playlistTracks.removeValue(forKey: playlistId)
327
+
328
+ self.saveToDisk()
329
+ }
330
+ }
331
+
332
+ func deleteAllDownloads() {
333
+ queue.async(flags: .barrier) {
334
+ // Delete all files
335
+ for record in self.downloadedTracks.values {
336
+ DownloadFileManager.shared.deleteFile(at: record.localPath)
337
+ if let artworkPath = record.localArtworkPath {
338
+ DownloadFileManager.shared.deleteFile(at: artworkPath)
339
+ }
340
+ }
341
+
342
+ // Clear all records
343
+ self.downloadedTracks.removeAll()
344
+ self.playlistTracks.removeAll()
345
+
346
+ self.saveToDisk()
347
+ }
348
+ }
349
+
350
+ // MARK: - Persistence
351
+
352
+ private func saveToDisk() {
353
+ do {
354
+ let tracksData = try JSONEncoder().encode(downloadedTracks)
355
+ UserDefaults.standard.set(tracksData, forKey: Self.downloadedTracksKey)
356
+
357
+ // Convert Set to Array for encoding
358
+ let playlistTracksDict = playlistTracks.mapValues { Array($0) }
359
+ let playlistData = try JSONEncoder().encode(playlistTracksDict)
360
+ UserDefaults.standard.set(playlistData, forKey: Self.playlistTracksKey)
361
+ } catch {
362
+ print("[DownloadDatabase] Failed to save to disk: \(error)")
363
+ }
364
+ }
365
+
366
+ private func loadFromDisk() {
367
+ print("\n" + String(repeating: "📀", count: 40))
368
+ print("📀 DownloadDatabase: LOADING FROM DISK")
369
+ print(String(repeating: "📀", count: 40))
370
+
371
+ // Load synchronously to ensure data is available immediately
372
+ // Load downloaded tracks
373
+ if let tracksData = UserDefaults.standard.data(forKey: Self.downloadedTracksKey) {
374
+ do {
375
+ self.downloadedTracks = try JSONDecoder().decode(
376
+ [String: DownloadedTrackRecord].self, from: tracksData)
377
+ print("✅ DownloadDatabase: Loaded \(self.downloadedTracks.count) tracks from disk")
378
+
379
+ // Log each downloaded track
380
+ for (trackId, record) in self.downloadedTracks {
381
+ print(" 📥 \(trackId)")
382
+ print(" Title: \(record.originalTrack.title)")
383
+ print(" Path: \(record.localPath)")
384
+ print(" Exists: \(FileManager.default.fileExists(atPath: record.localPath))")
385
+ }
386
+ } catch {
387
+ print("❌ DownloadDatabase: Failed to load tracks from disk: \(error)")
388
+ }
389
+ } else {
390
+ print("⚠️ DownloadDatabase: No saved tracks found in UserDefaults")
391
+ }
392
+
393
+ // Load playlist associations
394
+ if let playlistData = UserDefaults.standard.data(forKey: Self.playlistTracksKey) {
395
+ do {
396
+ let playlistTracksDict = try JSONDecoder().decode(
397
+ [String: [String]].self, from: playlistData)
398
+ self.playlistTracks = playlistTracksDict.mapValues { Set($0) }
399
+ print(
400
+ "✅ DownloadDatabase: Loaded \(self.playlistTracks.count) playlist associations from disk")
401
+
402
+ // Log playlist associations
403
+ for (playlistId, trackIds) in self.playlistTracks {
404
+ print(" 📋 Playlist \(playlistId): \(trackIds.count) tracks")
405
+ }
406
+ } catch {
407
+ print("❌ DownloadDatabase: Failed to load playlist tracks from disk: \(error)")
408
+ }
409
+ } else {
410
+ print("⚠️ DownloadDatabase: No playlist associations found")
411
+ }
412
+
413
+ print(String(repeating: "📀", count: 40) + "\n")
414
+ }
415
+
416
+ // MARK: - Conversion Helpers
417
+
418
+ /// Convert Variant_NullType_String? to String?
419
+ private func variantToString(_ variant: Variant_NullType_String?) -> String? {
420
+ guard let variant = variant else { return nil }
421
+ switch variant {
422
+ case .first(_):
423
+ return nil
424
+ case .second(let value):
425
+ return value
426
+ }
427
+ }
428
+
429
+ /// Convert String? to Variant_NullType_String?
430
+ private func stringToVariant(_ string: String?) -> Variant_NullType_String? {
431
+ guard let string = string else { return nil }
432
+ return .second(string)
433
+ }
434
+
435
+ private func trackItemToRecord(_ track: TrackItem) -> TrackItemRecord {
436
+ return TrackItemRecord(
437
+ id: track.id,
438
+ title: track.title,
439
+ artist: track.artist,
440
+ album: track.album,
441
+ duration: track.duration,
442
+ url: track.url,
443
+ artwork: variantToString(track.artwork)
444
+ )
445
+ }
446
+
447
+ private func recordToTrackItem(_ record: TrackItemRecord) -> TrackItem {
448
+ return TrackItem(
449
+ id: record.id,
450
+ title: record.title,
451
+ artist: record.artist,
452
+ album: record.album,
453
+ duration: record.duration,
454
+ url: record.url,
455
+ artwork: stringToVariant(record.artwork),
456
+ extraPayload: nil
457
+ )
458
+ }
459
+
460
+ private func recordToDownloadedTrack(_ record: DownloadedTrackRecord) -> DownloadedTrack {
461
+ return DownloadedTrack(
462
+ trackId: record.trackId,
463
+ originalTrack: recordToTrackItem(record.originalTrack),
464
+ localPath: record.localPath,
465
+ localArtworkPath: stringToVariant(record.localArtworkPath),
466
+ downloadedAt: record.downloadedAt,
467
+ fileSize: record.fileSize,
468
+ storageLocation: record.storageLocation == "private" ? .private : .public
469
+ )
470
+ }
471
+ }
472
+
473
+ // MARK: - Codable Records
474
+
475
+ private struct DownloadedTrackRecord: Codable {
476
+ let trackId: String
477
+ let originalTrack: TrackItemRecord
478
+ let localPath: String
479
+ let localArtworkPath: String?
480
+ let downloadedAt: Double
481
+ let fileSize: Double
482
+ let storageLocation: String
483
+ }
484
+
485
+ private struct TrackItemRecord: Codable {
486
+ let id: String
487
+ let title: String
488
+ let artist: String
489
+ let album: String
490
+ let duration: Double
491
+ let url: String
492
+ let artwork: String?
493
+ }