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,475 @@
1
+ package com.margelo.nitro.nitroplayer.download
2
+
3
+ import android.content.Context
4
+ import android.content.SharedPreferences
5
+ import android.util.Log
6
+ import com.margelo.nitro.core.NullType
7
+ import com.margelo.nitro.nitroplayer.*
8
+ import com.margelo.nitro.nitroplayer.playlist.PlaylistManager
9
+ import org.json.JSONArray
10
+ import org.json.JSONObject
11
+ import java.io.File
12
+
13
+ /**
14
+ * Manages persistence of downloaded track metadata using SharedPreferences
15
+ */
16
+ class DownloadDatabase private constructor(
17
+ private val context: Context,
18
+ ) {
19
+ companion object {
20
+ private const val TAG = "DownloadDatabase"
21
+ private const val PREFS_NAME = "NitroPlayerDownloads"
22
+ private const val KEY_DOWNLOADED_TRACKS = "downloaded_tracks"
23
+ private const val KEY_PLAYLIST_TRACKS = "playlist_tracks"
24
+
25
+ @Volatile
26
+ private var instance: DownloadDatabase? = null
27
+
28
+ fun getInstance(context: Context): DownloadDatabase =
29
+ instance ?: synchronized(this) {
30
+ instance ?: DownloadDatabase(context.applicationContext).also { instance = it }
31
+ }
32
+ }
33
+
34
+ private val prefs: SharedPreferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
35
+ private val downloadedTracks = mutableMapOf<String, DownloadedTrackRecord>()
36
+ private val playlistTracks = mutableMapOf<String, MutableSet<String>>()
37
+ private val fileManager = DownloadFileManager.getInstance(context)
38
+
39
+ init {
40
+ loadFromDisk()
41
+ }
42
+
43
+ // Save Operations
44
+ fun saveDownloadedTrack(
45
+ track: DownloadedTrack,
46
+ playlistId: String?,
47
+ ) {
48
+ synchronized(this) {
49
+ val record =
50
+ DownloadedTrackRecord(
51
+ trackId = track.trackId,
52
+ originalTrack = trackItemToRecord(track.originalTrack),
53
+ localPath = track.localPath,
54
+ localArtworkPath = track.localArtworkPath?.asSecondOrNull(),
55
+ downloadedAt = track.downloadedAt,
56
+ fileSize = track.fileSize,
57
+ storageLocation = track.storageLocation.name,
58
+ )
59
+
60
+ downloadedTracks[track.trackId] = record
61
+
62
+ // Associate with playlist if provided
63
+ playlistId?.let {
64
+ if (playlistTracks[it] == null) {
65
+ playlistTracks[it] = mutableSetOf()
66
+ }
67
+ playlistTracks[it]?.add(track.trackId)
68
+ }
69
+
70
+ saveToDisk()
71
+ }
72
+ }
73
+
74
+ // Query Operations
75
+ fun isTrackDownloaded(trackId: String): Boolean {
76
+ synchronized(this) {
77
+ val record = downloadedTracks[trackId] ?: return false
78
+ // Verify file still exists
79
+ return File(record.localPath).exists()
80
+ }
81
+ }
82
+
83
+ fun isPlaylistDownloaded(playlistId: String): Boolean {
84
+ synchronized(this) {
85
+ val trackIds = playlistTracks[playlistId] ?: return false
86
+ if (trackIds.isEmpty()) return false
87
+
88
+ // Get original playlist to check all tracks
89
+ val playlist = PlaylistManager.getInstance(context).getPlaylist(playlistId) ?: return false
90
+
91
+ // Check if all tracks are downloaded
92
+ return playlist.tracks.all { track ->
93
+ isTrackDownloaded(track.id)
94
+ }
95
+ }
96
+ }
97
+
98
+ fun isPlaylistPartiallyDownloaded(playlistId: String): Boolean {
99
+ synchronized(this) {
100
+ val trackIds = playlistTracks[playlistId] ?: return false
101
+ if (trackIds.isEmpty()) return false
102
+
103
+ // Check if at least one track is downloaded
104
+ return trackIds.any { trackId ->
105
+ isTrackDownloaded(trackId)
106
+ }
107
+ }
108
+ }
109
+
110
+ fun getDownloadedTrack(trackId: String): DownloadedTrack? {
111
+ synchronized(this) {
112
+ val record = downloadedTracks[trackId] ?: return null
113
+
114
+ // Verify file still exists
115
+ if (!File(record.localPath).exists()) {
116
+ // File was deleted externally, clean up record
117
+ downloadedTracks.remove(trackId)
118
+ saveToDisk()
119
+ return null
120
+ }
121
+
122
+ return recordToDownloadedTrack(record)
123
+ }
124
+ }
125
+
126
+ fun getAllDownloadedTracks(): List<DownloadedTrack> {
127
+ synchronized(this) {
128
+ val validTracks = mutableListOf<DownloadedTrack>()
129
+ val invalidTrackIds = mutableListOf<String>()
130
+
131
+ for ((trackId, record) in downloadedTracks) {
132
+ if (File(record.localPath).exists()) {
133
+ validTracks.add(recordToDownloadedTrack(record))
134
+ } else {
135
+ invalidTrackIds.add(trackId)
136
+ }
137
+ }
138
+
139
+ // Clean up invalid records
140
+ if (invalidTrackIds.isNotEmpty()) {
141
+ invalidTrackIds.forEach { downloadedTracks.remove(it) }
142
+ saveToDisk()
143
+ }
144
+
145
+ return validTracks
146
+ }
147
+ }
148
+
149
+ fun getDownloadedPlaylist(playlistId: String): DownloadedPlaylist? {
150
+ synchronized(this) {
151
+ val trackIds = playlistTracks[playlistId] ?: return null
152
+ if (trackIds.isEmpty()) return null
153
+
154
+ val playlist = PlaylistManager.getInstance(context).getPlaylist(playlistId) ?: return null
155
+
156
+ val downloadedTracksList = mutableListOf<DownloadedTrack>()
157
+ var totalSize = 0.0
158
+
159
+ for (trackId in trackIds) {
160
+ getDownloadedTrack(trackId)?.let { track ->
161
+ downloadedTracksList.add(track)
162
+ totalSize += track.fileSize
163
+ }
164
+ }
165
+
166
+ if (downloadedTracksList.isEmpty()) return null
167
+
168
+ val isComplete = downloadedTracksList.size == playlist.tracks.size
169
+
170
+ return DownloadedPlaylist(
171
+ playlistId = playlistId,
172
+ originalPlaylist = convertPlaylistManagerToNitro(playlist),
173
+ downloadedTracks = downloadedTracksList.toTypedArray(),
174
+ totalSize = totalSize,
175
+ downloadedAt = downloadedTracksList.minOfOrNull { it.downloadedAt } ?: System.currentTimeMillis().toDouble(),
176
+ isComplete = isComplete,
177
+ )
178
+ }
179
+ }
180
+
181
+ fun getAllDownloadedPlaylists(): List<DownloadedPlaylist> {
182
+ synchronized(this) {
183
+ return playlistTracks.keys.mapNotNull { playlistId ->
184
+ getDownloadedPlaylist(playlistId)
185
+ }
186
+ }
187
+ }
188
+
189
+ // Delete Operations
190
+ fun deleteDownloadedTrack(trackId: String) {
191
+ synchronized(this) {
192
+ downloadedTracks[trackId]?.let { record ->
193
+ // Delete the file
194
+ fileManager.deleteFile(record.localPath)
195
+
196
+ // Delete artwork if exists
197
+ record.localArtworkPath?.let { artworkPath ->
198
+ fileManager.deleteFile(artworkPath)
199
+ }
200
+ }
201
+
202
+ // Remove from records
203
+ downloadedTracks.remove(trackId)
204
+
205
+ // Remove from all playlist associations
206
+ playlistTracks.forEach { (playlistId, trackIds) ->
207
+ trackIds.remove(trackId)
208
+ if (trackIds.isEmpty()) {
209
+ playlistTracks.remove(playlistId)
210
+ }
211
+ }
212
+
213
+ saveToDisk()
214
+ }
215
+ }
216
+
217
+ fun deleteDownloadedPlaylist(playlistId: String) {
218
+ synchronized(this) {
219
+ val trackIds = playlistTracks[playlistId]?.toList() ?: return
220
+
221
+ // Delete all tracks in the playlist
222
+ for (trackId in trackIds) {
223
+ downloadedTracks[trackId]?.let { record ->
224
+ fileManager.deleteFile(record.localPath)
225
+ record.localArtworkPath?.let { fileManager.deleteFile(it) }
226
+ }
227
+ downloadedTracks.remove(trackId)
228
+ }
229
+
230
+ // Remove playlist association
231
+ playlistTracks.remove(playlistId)
232
+
233
+ saveToDisk()
234
+ }
235
+ }
236
+
237
+ fun deleteAllDownloads() {
238
+ synchronized(this) {
239
+ // Delete all files
240
+ for (record in downloadedTracks.values) {
241
+ fileManager.deleteFile(record.localPath)
242
+ record.localArtworkPath?.let { fileManager.deleteFile(it) }
243
+ }
244
+
245
+ // Clear all records
246
+ downloadedTracks.clear()
247
+ playlistTracks.clear()
248
+
249
+ saveToDisk()
250
+ }
251
+ }
252
+
253
+ /** Validates all downloads and removes records for missing files */
254
+ fun syncDownloads(): Int {
255
+ synchronized(this) {
256
+ Log.d(TAG, "syncDownloads called")
257
+
258
+ val trackIdsToRemove = mutableListOf<String>()
259
+
260
+ for ((trackId, record) in downloadedTracks) {
261
+ if (!File(record.localPath).exists()) {
262
+ Log.d(TAG, "Missing file for track $trackId: ${record.localPath}")
263
+ trackIdsToRemove.add(trackId)
264
+ }
265
+ }
266
+
267
+ // Remove invalid records
268
+ for (trackId in trackIdsToRemove) {
269
+ downloadedTracks.remove(trackId)
270
+
271
+ // Also remove from playlist associations
272
+ val playlistsToClean = mutableListOf<String>()
273
+ for ((playlistId, trackIds) in playlistTracks) {
274
+ if (trackIds.remove(trackId)) {
275
+ if (trackIds.isEmpty()) {
276
+ playlistsToClean.add(playlistId)
277
+ }
278
+ }
279
+ }
280
+ playlistsToClean.forEach { playlistTracks.remove(it) }
281
+ }
282
+
283
+ if (trackIdsToRemove.isNotEmpty()) {
284
+ saveToDisk()
285
+ Log.d(TAG, "Cleaned up ${trackIdsToRemove.size} orphaned records")
286
+ } else {
287
+ Log.d(TAG, "All downloads are valid")
288
+ }
289
+
290
+ return trackIdsToRemove.size
291
+ }
292
+ }
293
+
294
+ // Persistence
295
+ private fun saveToDisk() {
296
+ try {
297
+ // Save downloaded tracks
298
+ val tracksJson = JSONObject()
299
+ for ((trackId, record) in downloadedTracks) {
300
+ tracksJson.put(trackId, record.toJson())
301
+ }
302
+ prefs.edit().putString(KEY_DOWNLOADED_TRACKS, tracksJson.toString()).apply()
303
+
304
+ // Save playlist associations
305
+ val playlistJson = JSONObject()
306
+ for ((playlistId, trackIds) in playlistTracks) {
307
+ playlistJson.put(playlistId, JSONArray(trackIds.toList()))
308
+ }
309
+ prefs.edit().putString(KEY_PLAYLIST_TRACKS, playlistJson.toString()).apply()
310
+ } catch (e: Exception) {
311
+ e.printStackTrace()
312
+ }
313
+ }
314
+
315
+ private fun loadFromDisk() {
316
+ try {
317
+ // Load downloaded tracks
318
+ val tracksString = prefs.getString(KEY_DOWNLOADED_TRACKS, null)
319
+ if (tracksString != null) {
320
+ val tracksJson = JSONObject(tracksString)
321
+ for (trackId in tracksJson.keys()) {
322
+ val record = DownloadedTrackRecord.fromJson(tracksJson.getJSONObject(trackId))
323
+ downloadedTracks[trackId] = record
324
+ }
325
+ }
326
+
327
+ // Load playlist associations
328
+ val playlistString = prefs.getString(KEY_PLAYLIST_TRACKS, null)
329
+ if (playlistString != null) {
330
+ val playlistJson = JSONObject(playlistString)
331
+ for (playlistId in playlistJson.keys()) {
332
+ val trackIdsArray = playlistJson.getJSONArray(playlistId)
333
+ val trackIds = mutableSetOf<String>()
334
+ for (i in 0 until trackIdsArray.length()) {
335
+ trackIds.add(trackIdsArray.getString(i))
336
+ }
337
+ playlistTracks[playlistId] = trackIds
338
+ }
339
+ }
340
+ } catch (e: Exception) {
341
+ e.printStackTrace()
342
+ }
343
+ }
344
+
345
+ // Conversion Helpers
346
+ private fun trackItemToRecord(track: TrackItem): TrackItemRecord =
347
+ TrackItemRecord(
348
+ id = track.id,
349
+ title = track.title,
350
+ artist = track.artist,
351
+ album = track.album,
352
+ duration = track.duration,
353
+ url = track.url,
354
+ artwork = track.artwork?.asSecondOrNull(),
355
+ )
356
+
357
+ private fun recordToTrackItem(record: TrackItemRecord): TrackItem {
358
+ val artworkVariant =
359
+ if (record.artwork != null) {
360
+ Variant_NullType_String.create(record.artwork)
361
+ } else {
362
+ null
363
+ }
364
+
365
+ return TrackItem(
366
+ id = record.id,
367
+ title = record.title,
368
+ artist = record.artist,
369
+ album = record.album,
370
+ duration = record.duration,
371
+ url = record.url,
372
+ artwork = artworkVariant,
373
+ extraPayload = null,
374
+ )
375
+ }
376
+
377
+ private fun recordToDownloadedTrack(record: DownloadedTrackRecord): DownloadedTrack {
378
+ val localArtworkVariant =
379
+ if (record.localArtworkPath != null) {
380
+ Variant_NullType_String.create(record.localArtworkPath)
381
+ } else {
382
+ null
383
+ }
384
+
385
+ return DownloadedTrack(
386
+ trackId = record.trackId,
387
+ originalTrack = recordToTrackItem(record.originalTrack),
388
+ localPath = record.localPath,
389
+ localArtworkPath = localArtworkVariant,
390
+ downloadedAt = record.downloadedAt,
391
+ fileSize = record.fileSize,
392
+ storageLocation = StorageLocation.valueOf(record.storageLocation),
393
+ )
394
+ }
395
+
396
+ private fun convertPlaylistManagerToNitro(playlist: com.margelo.nitro.nitroplayer.playlist.Playlist): Playlist {
397
+ // PlaylistManager already uses TrackItem from generated code with proper Variant types
398
+ return Playlist(
399
+ id = playlist.id,
400
+ name = playlist.name,
401
+ description = null, // PlaylistManager doesn't have description in Nitro Playlist
402
+ artwork = null, // PlaylistManager doesn't have artwork in Nitro Playlist
403
+ tracks = playlist.tracks.toTypedArray(),
404
+ )
405
+ }
406
+ }
407
+
408
+ // Internal record classes
409
+ internal data class DownloadedTrackRecord(
410
+ val trackId: String,
411
+ val originalTrack: TrackItemRecord,
412
+ val localPath: String,
413
+ val localArtworkPath: String?,
414
+ val downloadedAt: Double,
415
+ val fileSize: Double,
416
+ val storageLocation: String,
417
+ ) {
418
+ fun toJson(): JSONObject =
419
+ JSONObject().apply {
420
+ put("trackId", trackId)
421
+ put("originalTrack", originalTrack.toJson())
422
+ put("localPath", localPath)
423
+ put("localArtworkPath", localArtworkPath)
424
+ put("downloadedAt", downloadedAt)
425
+ put("fileSize", fileSize)
426
+ put("storageLocation", storageLocation)
427
+ }
428
+
429
+ companion object {
430
+ fun fromJson(json: JSONObject): DownloadedTrackRecord =
431
+ DownloadedTrackRecord(
432
+ trackId = json.getString("trackId"),
433
+ originalTrack = TrackItemRecord.fromJson(json.getJSONObject("originalTrack")),
434
+ localPath = json.getString("localPath"),
435
+ localArtworkPath = json.optString("localArtworkPath", null),
436
+ downloadedAt = json.getDouble("downloadedAt"),
437
+ fileSize = json.getDouble("fileSize"),
438
+ storageLocation = json.getString("storageLocation"),
439
+ )
440
+ }
441
+ }
442
+
443
+ internal data class TrackItemRecord(
444
+ val id: String,
445
+ val title: String,
446
+ val artist: String,
447
+ val album: String,
448
+ val duration: Double,
449
+ val url: String,
450
+ val artwork: String?,
451
+ ) {
452
+ fun toJson(): JSONObject =
453
+ JSONObject().apply {
454
+ put("id", id)
455
+ put("title", title)
456
+ put("artist", artist)
457
+ put("album", album)
458
+ put("duration", duration)
459
+ put("url", url)
460
+ put("artwork", artwork)
461
+ }
462
+
463
+ companion object {
464
+ fun fromJson(json: JSONObject): TrackItemRecord =
465
+ TrackItemRecord(
466
+ id = json.getString("id"),
467
+ title = json.getString("title"),
468
+ artist = json.getString("artist"),
469
+ album = json.getString("album"),
470
+ duration = json.getDouble("duration"),
471
+ url = json.getString("url"),
472
+ artwork = json.optString("artwork", null),
473
+ )
474
+ }
475
+ }
@@ -0,0 +1,159 @@
1
+ package com.margelo.nitro.nitroplayer.download
2
+
3
+ import android.content.Context
4
+ import android.os.Environment
5
+ import android.os.StatFs
6
+ import com.margelo.nitro.nitroplayer.DownloadStorageInfo
7
+ import com.margelo.nitro.nitroplayer.StorageLocation
8
+ import java.io.File
9
+
10
+ /**
11
+ * Manages file operations for downloaded tracks
12
+ */
13
+ class DownloadFileManager private constructor(
14
+ private val context: Context,
15
+ ) {
16
+ companion object {
17
+ private const val PRIVATE_DOWNLOADS_FOLDER = "NitroPlayerDownloads"
18
+ private const val PUBLIC_DOWNLOADS_FOLDER = "NitroPlayerMusic"
19
+
20
+ @Volatile
21
+ private var instance: DownloadFileManager? = null
22
+
23
+ fun getInstance(context: Context): DownloadFileManager =
24
+ instance ?: synchronized(this) {
25
+ instance ?: DownloadFileManager(context.applicationContext).also { instance = it }
26
+ }
27
+ }
28
+
29
+ private val privateDownloadsDir: File by lazy {
30
+ File(context.filesDir, PRIVATE_DOWNLOADS_FOLDER).apply {
31
+ if (!exists()) mkdirs()
32
+ }
33
+ }
34
+
35
+ private val publicDownloadsDir: File by lazy {
36
+ val publicDir =
37
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
38
+ // On Android 10+, use app-specific external storage
39
+ File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC), PUBLIC_DOWNLOADS_FOLDER)
40
+ } else {
41
+ // On older versions, use public Downloads directory
42
+ @Suppress("DEPRECATION")
43
+ File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), PUBLIC_DOWNLOADS_FOLDER)
44
+ }
45
+ publicDir.apply {
46
+ if (!exists()) mkdirs()
47
+ }
48
+ }
49
+
50
+ fun createDownloadFile(
51
+ trackId: String,
52
+ storageLocation: StorageLocation,
53
+ ): File {
54
+ val destinationDir =
55
+ when (storageLocation) {
56
+ StorageLocation.PRIVATE -> privateDownloadsDir
57
+ StorageLocation.PUBLIC -> publicDownloadsDir
58
+ }
59
+
60
+ // Create unique filename based on trackId
61
+ val fileName = "$trackId.mp3"
62
+ return File(destinationDir, fileName)
63
+ }
64
+
65
+ fun deleteFile(path: String) {
66
+ try {
67
+ val file = File(path)
68
+ if (file.exists()) {
69
+ file.delete()
70
+ }
71
+ } catch (e: Exception) {
72
+ e.printStackTrace()
73
+ }
74
+ }
75
+
76
+ fun getFileSize(path: String): Long =
77
+ try {
78
+ File(path).length()
79
+ } catch (e: Exception) {
80
+ 0L
81
+ }
82
+
83
+ fun getStorageInfo(): DownloadStorageInfo {
84
+ var totalDownloadedSize = 0L
85
+ var trackCount = 0
86
+
87
+ // Count files in private directory
88
+ privateDownloadsDir.listFiles()?.forEach { file ->
89
+ if (file.isFile) {
90
+ totalDownloadedSize += file.length()
91
+ trackCount++
92
+ }
93
+ }
94
+
95
+ // Count files in public directory
96
+ publicDownloadsDir.listFiles()?.forEach { file ->
97
+ if (file.isFile) {
98
+ totalDownloadedSize += file.length()
99
+ trackCount++
100
+ }
101
+ }
102
+
103
+ // Get device storage info
104
+ val stat = StatFs(context.filesDir.path)
105
+ val availableSpace = stat.availableBytes
106
+ val totalSpace = stat.totalBytes
107
+
108
+ // Get playlist count from database
109
+ val playlistCount = DownloadDatabase.getInstance(context).getAllDownloadedPlaylists().size
110
+
111
+ return DownloadStorageInfo(
112
+ totalDownloadedSize = totalDownloadedSize.toDouble(),
113
+ trackCount = trackCount.toDouble(),
114
+ playlistCount = playlistCount.toDouble(),
115
+ availableSpace = availableSpace.toDouble(),
116
+ totalSpace = totalSpace.toDouble(),
117
+ )
118
+ }
119
+
120
+ fun getLocalPath(trackId: String): String? {
121
+ // Check private directory first
122
+ val privateFile = File(privateDownloadsDir, "$trackId.mp3")
123
+ if (privateFile.exists()) {
124
+ return privateFile.absolutePath
125
+ }
126
+
127
+ // Check public directory
128
+ val publicFile = File(publicDownloadsDir, "$trackId.mp3")
129
+ if (publicFile.exists()) {
130
+ return publicFile.absolutePath
131
+ }
132
+
133
+ return null
134
+ }
135
+
136
+ fun cleanupOrphanedFiles(validTrackIds: Set<String>): Long {
137
+ var bytesFreed = 0L
138
+
139
+ // Clean private directory
140
+ privateDownloadsDir.listFiles()?.forEach { file ->
141
+ val trackId = file.nameWithoutExtension
142
+ if (trackId !in validTrackIds) {
143
+ bytesFreed += file.length()
144
+ file.delete()
145
+ }
146
+ }
147
+
148
+ // Clean public directory
149
+ publicDownloadsDir.listFiles()?.forEach { file ->
150
+ val trackId = file.nameWithoutExtension
151
+ if (trackId !in validTrackIds) {
152
+ bytesFreed += file.length()
153
+ file.delete()
154
+ }
155
+ }
156
+
157
+ return bytesFreed
158
+ }
159
+ }