react-native-nitro-player 0.5.8 → 0.5.9-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/android/src/main/cpp/cpp-adapter.cpp +5 -1
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +2 -2
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +119 -59
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +3 -1
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadManagerCore.kt +19 -8
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadWorker.kt +2 -1
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +14 -2
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +29 -30
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +10 -31
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/queue/Queue.kt +1 -1
  11. package/ios/core/TrackPlayerCore.swift +328 -84
  12. package/ios/download/DownloadDatabase.swift +8 -2
  13. package/ios/download/DownloadFileManager.swift +11 -2
  14. package/ios/download/DownloadManagerCore.swift +84 -25
  15. package/ios/equalizer/EqualizerCore.swift +83 -42
  16. package/ios/media/MediaSessionManager.swift +5 -5
  17. package/ios/playlist/PlaylistModel.swift +1 -1
  18. package/ios/queue/HybridPlayerQueue.swift +2 -0
  19. package/ios/storage/NitroPlayerStorage.swift +4 -2
  20. package/lib/hooks/usePlaylist.js +25 -4
  21. package/nitrogen/generated/android/NitroPlayer+autolinking.cmake +1 -1
  22. package/nitrogen/generated/android/NitroPlayer+autolinking.gradle +1 -1
  23. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +76 -73
  24. package/nitrogen/generated/android/NitroPlayerOnLoad.hpp +14 -5
  25. package/nitrogen/generated/android/c++/JCurrentPlayingType.hpp +5 -6
  26. package/nitrogen/generated/android/c++/JDownloadConfig.hpp +1 -1
  27. package/nitrogen/generated/android/c++/JDownloadError.hpp +1 -1
  28. package/nitrogen/generated/android/c++/JDownloadErrorReason.hpp +8 -9
  29. package/nitrogen/generated/android/c++/JDownloadProgress.hpp +1 -1
  30. package/nitrogen/generated/android/c++/JDownloadQueueStatus.hpp +1 -1
  31. package/nitrogen/generated/android/c++/JDownloadState.hpp +7 -8
  32. package/nitrogen/generated/android/c++/JDownloadStorageInfo.hpp +1 -1
  33. package/nitrogen/generated/android/c++/JDownloadTask.hpp +1 -1
  34. package/nitrogen/generated/android/c++/JDownloadedPlaylist.hpp +1 -1
  35. package/nitrogen/generated/android/c++/JDownloadedTrack.hpp +1 -1
  36. package/nitrogen/generated/android/c++/JEqualizerBand.hpp +1 -1
  37. package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +1 -1
  38. package/nitrogen/generated/android/c++/JEqualizerState.hpp +1 -1
  39. package/nitrogen/generated/android/c++/JFunc_void_DownloadProgress.hpp +1 -1
  40. package/nitrogen/generated/android/c++/JFunc_void_DownloadedTrack.hpp +1 -1
  41. package/nitrogen/generated/android/c++/JFunc_void_TrackItem_std__optional_Reason_.hpp +1 -1
  42. package/nitrogen/generated/android/c++/JFunc_void_TrackPlayerState_std__optional_Reason_.hpp +1 -1
  43. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +1 -1
  44. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +1 -1
  45. package/nitrogen/generated/android/c++/JFunc_void_double_double_std__optional_bool_.hpp +1 -1
  46. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__std__string__.hpp +1 -1
  47. package/nitrogen/generated/android/c++/JFunc_void_std__string_Playlist_std__optional_QueueOperation_.hpp +1 -1
  48. package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string_DownloadState_std__optional_DownloadError_.hpp +1 -1
  49. package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +1 -1
  50. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Playlist__std__optional_QueueOperation_.hpp +1 -1
  51. package/nitrogen/generated/android/c++/JFunc_void_std__vector_TrackItem__double.hpp +1 -1
  52. package/nitrogen/generated/android/c++/JGainRange.hpp +1 -1
  53. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.cpp +8 -1
  54. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.hpp +2 -1
  55. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.cpp +8 -1
  56. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.hpp +2 -1
  57. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +9 -1
  58. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +2 -1
  59. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +8 -1
  60. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +2 -1
  61. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +8 -1
  62. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +2 -1
  63. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -1
  64. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +2 -1
  65. package/nitrogen/generated/android/c++/JPlaybackSource.hpp +4 -5
  66. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +1 -1
  67. package/nitrogen/generated/android/c++/JPlayerState.hpp +1 -1
  68. package/nitrogen/generated/android/c++/JPlaylist.hpp +1 -1
  69. package/nitrogen/generated/android/c++/JPresetType.hpp +3 -4
  70. package/nitrogen/generated/android/c++/JQueueOperation.hpp +5 -6
  71. package/nitrogen/generated/android/c++/JReason.hpp +6 -7
  72. package/nitrogen/generated/android/c++/JRepeatMode.hpp +4 -5
  73. package/nitrogen/generated/android/c++/JStorageLocation.hpp +3 -4
  74. package/nitrogen/generated/android/c++/JTAudioDevice.hpp +1 -1
  75. package/nitrogen/generated/android/c++/JTrackItem.hpp +1 -1
  76. package/nitrogen/generated/android/c++/JTrackPlayerState.hpp +4 -5
  77. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +1 -1
  78. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
  79. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.cpp +1 -1
  80. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.hpp +3 -3
  81. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.cpp +1 -1
  82. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.hpp +3 -3
  83. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.cpp +1 -1
  84. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.hpp +3 -3
  85. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.cpp +1 -1
  86. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.hpp +3 -3
  87. package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.cpp +1 -1
  88. package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.hpp +3 -3
  89. package/nitrogen/generated/android/c++/JVariant_NullType_String.cpp +1 -1
  90. package/nitrogen/generated/android/c++/JVariant_NullType_String.hpp +3 -3
  91. package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.cpp +1 -1
  92. package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.hpp +3 -3
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/CurrentPlayingType.kt +3 -1
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadConfig.kt +2 -2
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadError.kt +2 -2
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadErrorReason.kt +3 -1
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadProgress.kt +2 -2
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadQueueStatus.kt +2 -2
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadState.kt +3 -1
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadStorageInfo.kt +2 -2
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadTask.kt +2 -2
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedPlaylist.kt +2 -2
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedTrack.kt +2 -2
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerBand.kt +2 -2
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerPreset.kt +2 -2
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerState.kt +2 -2
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadProgress.kt +1 -1
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadedTrack.kt +1 -1
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TrackItem_std__optional_Reason_.kt +1 -1
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TrackPlayerState_std__optional_Reason_.kt +1 -1
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_bool.kt +1 -1
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_double_double.kt +1 -1
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_double_double_std__optional_bool_.kt +1 -1
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__optional_std__variant_nitro__NullType__std__string__.kt +1 -1
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_Playlist_std__optional_QueueOperation_.kt +1 -1
  116. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.kt +1 -1
  117. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_EqualizerBand_.kt +1 -1
  118. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_Playlist__std__optional_QueueOperation_.kt +1 -1
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_TrackItem__double.kt +1 -1
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/GainRange.kt +2 -2
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrarySpec.kt +1 -1
  122. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAudioDevicesSpec.kt +1 -1
  123. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +1 -1
  124. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +1 -1
  125. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +1 -1
  126. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +1 -1
  127. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/NitroPlayerOnLoad.kt +1 -1
  128. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlaybackSource.kt +3 -1
  129. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerConfig.kt +2 -2
  130. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerState.kt +2 -2
  131. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Playlist.kt +2 -2
  132. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PresetType.kt +3 -1
  133. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/QueueOperation.kt +3 -1
  134. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Reason.kt +3 -1
  135. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/RepeatMode.kt +3 -1
  136. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/StorageLocation.kt +3 -1
  137. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TAudioDevice.kt +2 -2
  138. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackItem.kt +2 -2
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackPlayerState.kt +3 -1
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Double.kt +1 -1
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadError.kt +1 -1
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadTask.kt +1 -1
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedPlaylist.kt +1 -1
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedTrack.kt +1 -1
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Playlist.kt +1 -1
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_String.kt +1 -1
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_TrackItem.kt +1 -1
  148. package/nitrogen/generated/ios/NitroPlayer+autolinking.rb +2 -2
  149. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +1 -1
  150. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +21 -21
  151. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +1 -1
  152. package/nitrogen/generated/ios/NitroPlayerAutolinking.mm +1 -1
  153. package/nitrogen/generated/ios/NitroPlayerAutolinking.swift +25 -36
  154. package/nitrogen/generated/ios/c++/HybridAudioRoutePickerSpecSwift.cpp +1 -1
  155. package/nitrogen/generated/ios/c++/HybridAudioRoutePickerSpecSwift.hpp +7 -1
  156. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.cpp +1 -1
  157. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +7 -1
  158. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +1 -1
  159. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +7 -1
  160. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.cpp +1 -1
  161. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +7 -1
  162. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.cpp +1 -1
  163. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +7 -1
  164. package/nitrogen/generated/ios/swift/CurrentPlayingType.swift +1 -1
  165. package/nitrogen/generated/ios/swift/DownloadConfig.swift +78 -168
  166. package/nitrogen/generated/ios/swift/DownloadError.swift +9 -34
  167. package/nitrogen/generated/ios/swift/DownloadErrorReason.swift +1 -1
  168. package/nitrogen/generated/ios/swift/DownloadProgress.swift +13 -50
  169. package/nitrogen/generated/ios/swift/DownloadQueueStatus.swift +15 -58
  170. package/nitrogen/generated/ios/swift/DownloadState.swift +1 -1
  171. package/nitrogen/generated/ios/swift/DownloadStorageInfo.swift +11 -42
  172. package/nitrogen/generated/ios/swift/DownloadTask.swift +97 -210
  173. package/nitrogen/generated/ios/swift/DownloadedPlaylist.swift +13 -56
  174. package/nitrogen/generated/ios/swift/DownloadedTrack.swift +34 -90
  175. package/nitrogen/generated/ios/swift/EqualizerBand.swift +9 -34
  176. package/nitrogen/generated/ios/swift/EqualizerPreset.swift +7 -32
  177. package/nitrogen/generated/ios/swift/EqualizerState.swift +26 -64
  178. package/nitrogen/generated/ios/swift/Func_void.swift +1 -2
  179. package/nitrogen/generated/ios/swift/Func_void_DownloadProgress.swift +1 -2
  180. package/nitrogen/generated/ios/swift/Func_void_DownloadStorageInfo.swift +1 -2
  181. package/nitrogen/generated/ios/swift/Func_void_DownloadedTrack.swift +1 -2
  182. package/nitrogen/generated/ios/swift/Func_void_PlayerState.swift +1 -2
  183. package/nitrogen/generated/ios/swift/Func_void_TrackItem_std__optional_Reason_.swift +1 -2
  184. package/nitrogen/generated/ios/swift/Func_void_TrackPlayerState_std__optional_Reason_.swift +1 -2
  185. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -2
  186. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -2
  187. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +1 -2
  188. package/nitrogen/generated/ios/swift/Func_void_double_double_std__optional_bool_.swift +1 -2
  189. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -2
  190. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__std__string__.swift +1 -2
  191. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -2
  192. package/nitrogen/generated/ios/swift/Func_void_std__string_Playlist_std__optional_QueueOperation_.swift +1 -2
  193. package/nitrogen/generated/ios/swift/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.swift +1 -2
  194. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +1 -2
  195. package/nitrogen/generated/ios/swift/Func_void_std__vector_Playlist__std__optional_QueueOperation_.swift +1 -2
  196. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +1 -2
  197. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem__double.swift +1 -2
  198. package/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift +1 -2
  199. package/nitrogen/generated/ios/swift/GainRange.swift +5 -18
  200. package/nitrogen/generated/ios/swift/HybridAudioRoutePickerSpec.swift +3 -4
  201. package/nitrogen/generated/ios/swift/HybridAudioRoutePickerSpec_cxx.swift +9 -2
  202. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +3 -4
  203. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +9 -2
  204. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +3 -4
  205. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +9 -2
  206. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +3 -4
  207. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +25 -4
  208. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +3 -4
  209. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +9 -2
  210. package/nitrogen/generated/ios/swift/PlaybackSource.swift +1 -1
  211. package/nitrogen/generated/ios/swift/PlayerConfig.swift +37 -79
  212. package/nitrogen/generated/ios/swift/PlayerState.swift +53 -122
  213. package/nitrogen/generated/ios/swift/Playlist.swift +49 -112
  214. package/nitrogen/generated/ios/swift/PresetType.swift +1 -1
  215. package/nitrogen/generated/ios/swift/QueueOperation.swift +1 -1
  216. package/nitrogen/generated/ios/swift/Reason.swift +1 -1
  217. package/nitrogen/generated/ios/swift/RepeatMode.swift +1 -1
  218. package/nitrogen/generated/ios/swift/StorageLocation.swift +1 -1
  219. package/nitrogen/generated/ios/swift/TrackItem.swift +43 -111
  220. package/nitrogen/generated/ios/swift/TrackPlayerState.swift +1 -1
  221. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +1 -1
  222. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadError.swift +1 -1
  223. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadTask.swift +1 -1
  224. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedPlaylist.swift +1 -1
  225. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedTrack.swift +1 -1
  226. package/nitrogen/generated/ios/swift/Variant_NullType_Playlist.swift +1 -1
  227. package/nitrogen/generated/ios/swift/Variant_NullType_String.swift +1 -1
  228. package/nitrogen/generated/ios/swift/Variant_NullType_TrackItem.swift +1 -1
  229. package/nitrogen/generated/shared/c++/CurrentPlayingType.hpp +1 -1
  230. package/nitrogen/generated/shared/c++/DownloadConfig.hpp +34 -26
  231. package/nitrogen/generated/shared/c++/DownloadError.hpp +22 -14
  232. package/nitrogen/generated/shared/c++/DownloadErrorReason.hpp +1 -1
  233. package/nitrogen/generated/shared/c++/DownloadProgress.hpp +28 -20
  234. package/nitrogen/generated/shared/c++/DownloadQueueStatus.hpp +31 -23
  235. package/nitrogen/generated/shared/c++/DownloadState.hpp +1 -1
  236. package/nitrogen/generated/shared/c++/DownloadStorageInfo.hpp +25 -17
  237. package/nitrogen/generated/shared/c++/DownloadTask.hpp +40 -32
  238. package/nitrogen/generated/shared/c++/DownloadedPlaylist.hpp +28 -20
  239. package/nitrogen/generated/shared/c++/DownloadedTrack.hpp +31 -23
  240. package/nitrogen/generated/shared/c++/EqualizerBand.hpp +22 -14
  241. package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +19 -11
  242. package/nitrogen/generated/shared/c++/EqualizerState.hpp +19 -11
  243. package/nitrogen/generated/shared/c++/GainRange.hpp +16 -8
  244. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.cpp +1 -1
  245. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.hpp +1 -1
  246. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.cpp +1 -1
  247. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.hpp +1 -1
  248. package/nitrogen/generated/shared/c++/HybridAudioRoutePickerSpec.cpp +1 -1
  249. package/nitrogen/generated/shared/c++/HybridAudioRoutePickerSpec.hpp +1 -1
  250. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.cpp +1 -1
  251. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +1 -1
  252. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +1 -1
  253. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +1 -1
  254. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.cpp +1 -1
  255. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +1 -1
  256. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -1
  257. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +1 -1
  258. package/nitrogen/generated/shared/c++/PlaybackSource.hpp +1 -1
  259. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +22 -14
  260. package/nitrogen/generated/shared/c++/PlayerState.hpp +31 -23
  261. package/nitrogen/generated/shared/c++/Playlist.hpp +25 -17
  262. package/nitrogen/generated/shared/c++/PresetType.hpp +1 -1
  263. package/nitrogen/generated/shared/c++/QueueOperation.hpp +1 -1
  264. package/nitrogen/generated/shared/c++/Reason.hpp +1 -1
  265. package/nitrogen/generated/shared/c++/RepeatMode.hpp +1 -1
  266. package/nitrogen/generated/shared/c++/StorageLocation.hpp +1 -1
  267. package/nitrogen/generated/shared/c++/TAudioDevice.hpp +22 -14
  268. package/nitrogen/generated/shared/c++/TrackItem.hpp +34 -26
  269. package/nitrogen/generated/shared/c++/TrackPlayerState.hpp +1 -1
  270. package/package.json +3 -3
  271. package/src/hooks/usePlaylist.ts +26 -4
@@ -1,7 +1,11 @@
1
1
  #include "NitroPlayerOnLoad.hpp"
2
2
 
3
3
  #include <jni.h>
4
+ #include <fbjni/fbjni.h>
4
5
 
5
6
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
6
- return margelo::nitro::nitroplayer::initialize(vm);
7
+ return facebook::jni::initialize(vm, []() {
8
+ margelo::nitro::nitroplayer::registerAllNatives();
9
+ });
7
10
  }
11
+
@@ -22,8 +22,8 @@ class HybridPlayerQueue : HybridPlayerQueueSpec() {
22
22
  playlistManager = core.getPlaylistManager()
23
23
  }
24
24
 
25
- private val playlistsChangeListeners = mutableListOf<() -> Unit>()
26
- private val playlistChangeListeners = mutableMapOf<String, () -> Unit>()
25
+ private val playlistsChangeListeners = java.util.concurrent.CopyOnWriteArrayList<() -> Unit>()
26
+ private val playlistChangeListeners = java.util.concurrent.ConcurrentHashMap<String, () -> Unit>()
27
27
 
28
28
  @DoNotStrip
29
29
  @Keep
@@ -44,9 +44,9 @@ class TrackPlayerCore private constructor(
44
44
  private val downloadManager = DownloadManagerCore.getInstance(context)
45
45
  private val mediaLibraryManager = MediaLibraryManager.getInstance(context)
46
46
  private var mediaSessionManager: MediaSessionManager? = null
47
- private var currentPlaylistId: String? = null
47
+ @Volatile private var currentPlaylistId: String? = null
48
48
  private var isManuallySeeked = false
49
- private var isAndroidAutoConnected: Boolean = false
49
+ @Volatile private var isAndroidAutoConnected: Boolean = false
50
50
  private var androidAutoConnectionDetector: AndroidAutoConnectionDetector? = null
51
51
  var onAndroidAutoConnectionChange: ((Boolean) -> Unit)? = null
52
52
  private var previousMediaItem: MediaItem? = null
@@ -82,8 +82,9 @@ class TrackPlayerCore private constructor(
82
82
  private val onPlaybackProgressChangeListeners =
83
83
  Collections.synchronizedList(mutableListOf<WeakCallbackBox<(Double, Double, Boolean?) -> Unit>>())
84
84
 
85
- private var currentRepeatMode: RepeatMode = RepeatMode.OFF
85
+ @Volatile private var currentRepeatMode: RepeatMode = RepeatMode.OFF
86
86
  private var lookaheadCount: Int = 5 // Number of tracks to preload ahead
87
+ private var playerListener: Player.Listener? = null
87
88
 
88
89
  // Temporary tracks for addToUpNext and playNext
89
90
  private var playNextStack: MutableList<TrackItem> = mutableListOf() // LIFO - last added plays first
@@ -171,14 +172,13 @@ class TrackPlayerCore private constructor(
171
172
  // Notify JavaScript
172
173
  onAndroidAutoConnectionChange?.invoke(connected)
173
174
 
174
- NitroPlayerLogger.log("TrackPlayerCore", "🚗 Android Auto connection changed: connected=$connected, type=$connectionType")
175
+ NitroPlayerLogger.log("TrackPlayerCore") { "🚗 Android Auto connection changed: connected=$connected, type=$connectionType" }
175
176
  }
176
177
  }
177
178
  registerCarConnectionReceiver()
178
179
  }
179
180
 
180
- player.addListener(
181
- object : Player.Listener {
181
+ val listener = object : Player.Listener {
182
182
  override fun onMediaItemTransition(
183
183
  mediaItem: MediaItem?,
184
184
  reason: Int,
@@ -353,8 +353,9 @@ class TrackPlayerCore private constructor(
353
353
  }
354
354
  }
355
355
  }
356
- },
357
- )
356
+ }
357
+ playerListener = listener
358
+ player.addListener(listener)
358
359
 
359
360
  // Start progress updates
360
361
  handler.post(progressUpdateRunnable)
@@ -423,7 +424,7 @@ class TrackPlayerCore private constructor(
423
424
  }
424
425
  }
425
426
  } catch (e: Exception) {
426
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Error playing from playlist track - ${e.message}")
427
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Error playing from playlist track - ${e.message}" }
427
428
  e.printStackTrace()
428
429
  }
429
430
  }
@@ -563,19 +564,19 @@ class TrackPlayerCore private constructor(
563
564
 
564
565
  // Case 1: If fromPlaylist is provided, use that playlist
565
566
  if (fromPlaylist != null) {
566
- NitroPlayerLogger.log("TrackPlayerCore", "🎵 TrackPlayerCore: Looking for song in specified playlist: $fromPlaylist")
567
+ NitroPlayerLogger.log("TrackPlayerCore") { "🎵 TrackPlayerCore: Looking for song in specified playlist: $fromPlaylist" }
567
568
  val playlist = playlistManager.getPlaylist(fromPlaylist)
568
569
  if (playlist != null) {
569
570
  songIndex = playlist.tracks.indexOfFirst { it.id == songId }
570
571
  if (songIndex >= 0) {
571
572
  targetPlaylistId = fromPlaylist
572
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in playlist $fromPlaylist")
573
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in playlist $fromPlaylist" }
573
574
  } else {
574
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Song $songId not found in specified playlist $fromPlaylist")
575
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Song $songId not found in specified playlist $fromPlaylist" }
575
576
  return
576
577
  }
577
578
  } else {
578
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Playlist $fromPlaylist not found")
579
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Playlist $fromPlaylist not found" }
579
580
  return
580
581
  }
581
582
  }
@@ -590,7 +591,7 @@ class TrackPlayerCore private constructor(
590
591
  songIndex = currentPlaylist.tracks.indexOfFirst { it.id == songId }
591
592
  if (songIndex >= 0) {
592
593
  targetPlaylistId = currentPlaylistId
593
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in current playlist $currentPlaylistId")
594
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in current playlist $currentPlaylistId" }
594
595
  }
595
596
  }
596
597
  }
@@ -604,7 +605,7 @@ class TrackPlayerCore private constructor(
604
605
  songIndex = playlist.tracks.indexOfFirst { it.id == songId }
605
606
  if (songIndex >= 0) {
606
607
  targetPlaylistId = playlist.id
607
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in playlist ${playlist.id}")
608
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in playlist ${playlist.id}" }
608
609
  break
609
610
  }
610
611
  }
@@ -626,7 +627,7 @@ class TrackPlayerCore private constructor(
626
627
 
627
628
  // Load playlist if it's different from current
628
629
  if (currentPlaylistId != targetPlaylistId) {
629
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Loading new playlist: $targetPlaylistId")
630
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Loading new playlist: $targetPlaylistId" }
630
631
  val playlist = playlistManager.getPlaylist(targetPlaylistId)
631
632
  if (playlist != null) {
632
633
  currentPlaylistId = targetPlaylistId
@@ -634,12 +635,12 @@ class TrackPlayerCore private constructor(
634
635
 
635
636
  // Wait a bit for playlist to load, then play from index
636
637
  // Note: Removed postDelayed to avoid race conditions with subsequent queue operations
637
- NitroPlayerLogger.log("TrackPlayerCore", "▶️ Playing from index: $songIndex")
638
+ NitroPlayerLogger.log("TrackPlayerCore") { "▶️ Playing from index: $songIndex" }
638
639
  playFromIndex(songIndex)
639
640
  }
640
641
  } else {
641
642
  // Playlist already loaded, just play from index
642
- NitroPlayerLogger.log("TrackPlayerCore", "▶️ Playing from index: $songIndex")
643
+ NitroPlayerLogger.log("TrackPlayerCore") { "▶️ Playing from index: $songIndex" }
643
644
  playFromIndex(songIndex)
644
645
  }
645
646
  }
@@ -687,7 +688,7 @@ class TrackPlayerCore private constructor(
687
688
  playFromIndexInternal(currentTrackIndex)
688
689
  } else if (currentTrackIndex > 0) {
689
690
  // Go to previous track in original playlist
690
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 TrackPlayerCore: Going to previous track, currentTrackIndex: $currentTrackIndex -> ${currentTrackIndex - 1}")
691
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 TrackPlayerCore: Going to previous track, currentTrackIndex: $currentTrackIndex -> ${currentTrackIndex - 1}" }
691
692
  playFromIndexInternal(currentTrackIndex - 1)
692
693
  } else {
693
694
  // Already at first track, seek to beginning
@@ -718,7 +719,7 @@ class TrackPlayerCore private constructor(
718
719
  }
719
720
  }
720
721
  }
721
- NitroPlayerLogger.log("TrackPlayerCore", "🔁 setRepeatMode: $mode")
722
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔁 setRepeatMode: $mode" }
722
723
  return true
723
724
  }
724
725
 
@@ -750,7 +751,15 @@ class TrackPlayerCore private constructor(
750
751
  Thread.currentThread().interrupt()
751
752
  }
752
753
 
753
- return result ?: getStateInternal()
754
+ return result ?: PlayerState(
755
+ currentTrack = null,
756
+ currentPosition = 0.0,
757
+ totalDuration = 0.0,
758
+ currentState = TrackPlayerState.STOPPED,
759
+ currentPlaylistId = null,
760
+ currentIndex = -1.0,
761
+ currentPlayingType = CurrentPlayingType.NOT_PLAYING
762
+ )
754
763
  }
755
764
 
756
765
  private fun getStateInternal(): PlayerState =
@@ -832,7 +841,7 @@ class TrackPlayerCore private constructor(
832
841
  }
833
842
  lookaheadCount?.let {
834
843
  this.lookaheadCount = it
835
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Lookahead count set to: $it")
844
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Lookahead count set to: $it" }
836
845
  }
837
846
  mediaSessionManager?.configure(
838
847
  androidAutoEnabled,
@@ -985,7 +994,7 @@ class TrackPlayerCore private constructor(
985
994
 
986
995
  // Remove tracks before the target from playNext (they're being skipped)
987
996
  if (actualListIndex > 0) {
988
- repeat(actualListIndex) { playNextStack.removeAt(0) }
997
+ playNextStack.subList(0, actualListIndex).clear()
989
998
  }
990
999
 
991
1000
  // Rebuild queue and advance
@@ -1010,7 +1019,7 @@ class TrackPlayerCore private constructor(
1010
1019
 
1011
1020
  // Remove tracks before target from upNext
1012
1021
  if (actualListIndex > 0) {
1013
- repeat(actualListIndex) { upNextQueue.removeAt(0) }
1022
+ upNextQueue.subList(0, actualListIndex).clear()
1014
1023
  }
1015
1024
 
1016
1025
  // Rebuild queue and advance
@@ -1066,7 +1075,7 @@ class TrackPlayerCore private constructor(
1066
1075
  }
1067
1076
 
1068
1077
  if (index < 0 || index >= currentTracks.size) {
1069
- NitroPlayerLogger.log("TrackPlayerCore", " ❌ Invalid index $index for currentTracks size ${currentTracks.size}")
1078
+ NitroPlayerLogger.log("TrackPlayerCore") { " ❌ Invalid index $index for currentTracks size ${currentTracks.size}" }
1070
1079
  return
1071
1080
  }
1072
1081
 
@@ -1112,18 +1121,18 @@ class TrackPlayerCore private constructor(
1112
1121
  }
1113
1122
 
1114
1123
  private fun addToUpNextInternal(trackId: String) {
1115
- NitroPlayerLogger.log("TrackPlayerCore", "📋 TrackPlayerCore: addToUpNext($trackId)")
1124
+ NitroPlayerLogger.log("TrackPlayerCore") { "📋 TrackPlayerCore: addToUpNext($trackId)" }
1116
1125
 
1117
1126
  // Find the track from current playlist or all playlists
1118
1127
  val track = findTrackById(trackId)
1119
1128
  if (track == null) {
1120
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Track $trackId not found")
1129
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Track $trackId not found" }
1121
1130
  return
1122
1131
  }
1123
1132
 
1124
1133
  // Add to end of upNext queue (FIFO)
1125
1134
  upNextQueue.add(track)
1126
- NitroPlayerLogger.log("TrackPlayerCore", " ✅ Added '${track.title}' to upNext queue (position: ${upNextQueue.size})")
1135
+ NitroPlayerLogger.log("TrackPlayerCore") { " ✅ Added '${track.title}' to upNext queue (position: ${upNextQueue.size})" }
1127
1136
 
1128
1137
  // Rebuild the player queue if actively playing
1129
1138
  if (::player.isInitialized && player.currentMediaItem != null) {
@@ -1142,18 +1151,18 @@ class TrackPlayerCore private constructor(
1142
1151
  }
1143
1152
 
1144
1153
  private fun playNextInternal(trackId: String) {
1145
- NitroPlayerLogger.log("TrackPlayerCore", "⏭️ TrackPlayerCore: playNext($trackId)")
1154
+ NitroPlayerLogger.log("TrackPlayerCore") { "⏭️ TrackPlayerCore: playNext($trackId)" }
1146
1155
 
1147
1156
  // Find the track from current playlist or all playlists
1148
1157
  val track = findTrackById(trackId)
1149
1158
  if (track == null) {
1150
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Track $trackId not found")
1159
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Track $trackId not found" }
1151
1160
  return
1152
1161
  }
1153
1162
 
1154
1163
  // Insert at beginning of playNext stack (LIFO)
1155
1164
  playNextStack.add(0, track)
1156
- NitroPlayerLogger.log("TrackPlayerCore", " ✅ Added '${track.title}' to playNext stack (position: 1)")
1165
+ NitroPlayerLogger.log("TrackPlayerCore") { " ✅ Added '${track.title}' to playNext stack (position: 1)" }
1157
1166
 
1158
1167
  // Rebuild the player queue if actively playing
1159
1168
  if (::player.isInitialized && player.currentMediaItem != null) {
@@ -1258,6 +1267,8 @@ class TrackPlayerCore private constructor(
1258
1267
  handler.post {
1259
1268
  androidAutoConnectionDetector?.unregisterCarConnectionReceiver()
1260
1269
  handler.removeCallbacks(progressUpdateRunnable)
1270
+ playerListener?.let { player.removeListener(it) }
1271
+ playerListener = null
1261
1272
  }
1262
1273
  }
1263
1274
 
@@ -1274,7 +1285,7 @@ class TrackPlayerCore private constructor(
1274
1285
  NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
1275
1286
  NitroPlayerLogger.log("TrackPlayerCore", "✅ TrackPlayerCore: Android Auto media library set successfully")
1276
1287
  } catch (e: Exception) {
1277
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Error setting media library - ${e.message}")
1288
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Error setting media library - ${e.message}" }
1278
1289
  e.printStackTrace()
1279
1290
  }
1280
1291
  }
@@ -1297,7 +1308,7 @@ class TrackPlayerCore private constructor(
1297
1308
  // Convert to 0.0-1.0 range for ExoPlayer
1298
1309
  val normalizedVolume = (clampedVolume / 100.0).toFloat()
1299
1310
  player.volume = normalizedVolume
1300
- NitroPlayerLogger.log("TrackPlayerCore", "🔊 TrackPlayerCore: Volume set to $clampedVolume% (normalized: $normalizedVolume)")
1311
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔊 TrackPlayerCore: Volume set to $clampedVolume% (normalized: $normalizedVolume)" }
1301
1312
  }
1302
1313
  true
1303
1314
  } else {
@@ -1342,7 +1353,7 @@ class TrackPlayerCore private constructor(
1342
1353
  try {
1343
1354
  callback(track, reason)
1344
1355
  } catch (e: Exception) {
1345
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in track change listener: ${e.message}")
1356
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in track change listener: ${e.message}" }
1346
1357
  }
1347
1358
  }
1348
1359
  }
@@ -1363,7 +1374,7 @@ class TrackPlayerCore private constructor(
1363
1374
  try {
1364
1375
  callback(state, reason)
1365
1376
  } catch (e: Exception) {
1366
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in playback state listener: ${e.message}")
1377
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in playback state listener: ${e.message}" }
1367
1378
  }
1368
1379
  }
1369
1380
  }
@@ -1384,29 +1395,38 @@ class TrackPlayerCore private constructor(
1384
1395
  try {
1385
1396
  callback(position, duration)
1386
1397
  } catch (e: Exception) {
1387
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in seek listener: ${e.message}")
1398
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in seek listener: ${e.message}" }
1388
1399
  }
1389
1400
  }
1390
1401
  }
1391
1402
  }
1392
1403
 
1404
+ private var progressNotifyCounter = 0
1405
+ private val progressCallbackScratch = ArrayList<(Double, Double, Boolean?) -> Unit>(4)
1406
+
1393
1407
  private fun notifyPlaybackProgress(
1394
1408
  position: Double,
1395
1409
  duration: Double,
1396
1410
  isPlaying: Boolean?,
1397
1411
  ) {
1398
- val liveCallbacks =
1399
- synchronized(onPlaybackProgressChangeListeners) {
1412
+ progressCallbackScratch.clear()
1413
+ synchronized(onPlaybackProgressChangeListeners) {
1414
+ if (++progressNotifyCounter % 10 == 0) {
1400
1415
  onPlaybackProgressChangeListeners.removeAll { !it.isAlive }
1401
- onPlaybackProgressChangeListeners.map { it.callback }
1402
1416
  }
1417
+ for (box in onPlaybackProgressChangeListeners) {
1418
+ if (box.isAlive) progressCallbackScratch.add(box.callback)
1419
+ }
1420
+ }
1421
+
1422
+ if (progressCallbackScratch.isEmpty()) return
1403
1423
 
1404
1424
  handler.post {
1405
- for (callback in liveCallbacks) {
1425
+ for (callback in progressCallbackScratch) {
1406
1426
  try {
1407
1427
  callback(position, duration, isPlaying)
1408
1428
  } catch (e: Exception) {
1409
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in playback progress listener: ${e.message}")
1429
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in playback progress listener: ${e.message}" }
1410
1430
  }
1411
1431
  }
1412
1432
  }
@@ -1502,22 +1522,34 @@ class TrackPlayerCore private constructor(
1502
1522
  */
1503
1523
  fun updateTracks(tracks: List<TrackItem>) {
1504
1524
  handler.post {
1505
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 updateTracks: ${tracks.size} updates")
1525
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 updateTracks: ${tracks.size} updates" }
1506
1526
 
1507
- // Get current track ID to avoid updating it (preserves gapless playback)
1508
- val currentTrackId = getCurrentTrack()?.id
1527
+ // Get current track to decide how to handle it
1528
+ val currentTrack = getCurrentTrack()
1529
+ val currentTrackId = currentTrack?.id
1530
+
1531
+ // Separate the current-track update (if any) from the rest
1532
+ val currentTrackUpdate = if (currentTrackId != null) tracks.find { it.id == currentTrackId } else null
1533
+ val currentTrackIsEmpty = currentTrack?.url.isNullOrEmpty()
1509
1534
 
1510
1535
  // Filter out current track and validate
1511
1536
  val safeTracks =
1512
1537
  tracks.filter { track ->
1513
1538
  when {
1514
- track.id == currentTrackId -> {
1515
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Skipping update for currently playing track: ${track.id} (preserves gapless)")
1539
+ track.id == currentTrackId && !currentTrackIsEmpty -> {
1540
+ // Has a real URL already skip to preserve gapless playback
1541
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Skipping update for currently playing track: ${track.id} (preserves gapless)" }
1516
1542
  false
1517
1543
  }
1518
1544
 
1545
+ track.id == currentTrackId && currentTrackIsEmpty -> {
1546
+ // Empty URL — must not be playing, allow the update
1547
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Updating current track with no URL: ${track.id}" }
1548
+ track.url.isNotEmpty() // only include if the update actually provides a URL
1549
+ }
1550
+
1519
1551
  track.url.isEmpty() -> {
1520
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Skipping track with empty URL: ${track.id}")
1552
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Skipping track with empty URL: ${track.id}" }
1521
1553
  false
1522
1554
  }
1523
1555
 
@@ -1535,9 +1567,26 @@ class TrackPlayerCore private constructor(
1535
1567
  // Update in PlaylistManager
1536
1568
  val affectedPlaylists = playlistManager.updateTracks(safeTracks)
1537
1569
 
1538
- // Rebuild queue if current playlist was affected
1570
+ // If the current track was one of the updates (had no URL before), replace its
1571
+ // MediaItem in ExoPlayer directly — rebuildQueueFromCurrentPosition skips index 0.
1572
+ if (currentTrackUpdate != null && currentTrackIsEmpty && currentTrackUpdate.url.isNotEmpty()) {
1573
+ val exoIndex = player.currentMediaItemIndex
1574
+ if (exoIndex >= 0) {
1575
+ val playlistId = currentPlaylistId ?: ""
1576
+ val mediaId = if (playlistId.isNotEmpty()) "$playlistId:${currentTrackUpdate.id}" else currentTrackUpdate.id
1577
+ val newMediaItem = currentTrackUpdate.toMediaItem(mediaId)
1578
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Replacing MediaItem at index $exoIndex for current track with resolved URL" }
1579
+ player.replaceMediaItem(exoIndex, newMediaItem)
1580
+ // If ExoPlayer was in an error/idle state waiting for a URI, re-prepare
1581
+ if (player.playbackState == Player.STATE_IDLE) {
1582
+ player.prepare()
1583
+ }
1584
+ }
1585
+ }
1586
+
1587
+ // Rebuild queue for other updated tracks if current playlist was affected
1539
1588
  if (currentPlaylistId != null && affectedPlaylists.containsKey(currentPlaylistId)) {
1540
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Rebuilding queue - ${affectedPlaylists[currentPlaylistId]} tracks updated in current playlist")
1589
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Rebuilding queue - ${affectedPlaylists[currentPlaylistId]} tracks updated in current playlist" }
1541
1590
 
1542
1591
  // This method preserves current item and gapless buffering
1543
1592
  rebuildQueueFromCurrentPosition()
@@ -1545,7 +1594,7 @@ class TrackPlayerCore private constructor(
1545
1594
  NitroPlayerLogger.log("TrackPlayerCore", "✅ Queue rebuilt, gapless playback preserved")
1546
1595
  }
1547
1596
 
1548
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Track updates complete - ${affectedPlaylists.size} playlists affected")
1597
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Track updates complete - ${affectedPlaylists.size} playlists affected" }
1549
1598
  }
1550
1599
  }
1551
1600
 
@@ -1696,14 +1745,14 @@ class TrackPlayerCore private constructor(
1696
1745
  }
1697
1746
 
1698
1747
  // Add to class properties
1699
- private val onTracksNeedUpdateListeners = mutableListOf<WeakReference<OnTracksNeedUpdateListener>>()
1748
+ private val onTracksNeedUpdateListeners = mutableListOf<OnTracksNeedUpdateListener>()
1700
1749
 
1701
1750
  /**
1702
1751
  * Register listener for when tracks need update
1703
1752
  */
1704
1753
  fun addOnTracksNeedUpdateListener(listener: OnTracksNeedUpdateListener) {
1705
1754
  handler.post {
1706
- onTracksNeedUpdateListeners.add(WeakReference(listener))
1755
+ onTracksNeedUpdateListeners.add(listener)
1707
1756
  }
1708
1757
  }
1709
1758
 
@@ -1712,7 +1761,7 @@ class TrackPlayerCore private constructor(
1712
1761
  */
1713
1762
  fun removeOnTracksNeedUpdateListener(listener: OnTracksNeedUpdateListener) {
1714
1763
  handler.post {
1715
- onTracksNeedUpdateListeners.removeAll { it.get() == listener || it.get() == null }
1764
+ onTracksNeedUpdateListeners.removeAll { it == listener }
1716
1765
  }
1717
1766
  }
1718
1767
 
@@ -1726,8 +1775,7 @@ class TrackPlayerCore private constructor(
1726
1775
  ) {
1727
1776
  val liveCallbacks =
1728
1777
  synchronized(onTracksNeedUpdateListeners) {
1729
- onTracksNeedUpdateListeners.removeAll { it.get() == null }
1730
- onTracksNeedUpdateListeners.mapNotNull { it.get() }
1778
+ onTracksNeedUpdateListeners.toList()
1731
1779
  }
1732
1780
 
1733
1781
  handler.post {
@@ -1735,7 +1783,7 @@ class TrackPlayerCore private constructor(
1735
1783
  try {
1736
1784
  callback.onTracksNeedUpdate(tracks, lookahead)
1737
1785
  } catch (e: Exception) {
1738
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in onTracksNeedUpdate listener: ${e.message}")
1786
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in onTracksNeedUpdate listener: ${e.message}" }
1739
1787
  }
1740
1788
  }
1741
1789
  }
@@ -1746,11 +1794,23 @@ class TrackPlayerCore private constructor(
1746
1794
  * Call this in onMediaItemTransition or after skipTo operations
1747
1795
  */
1748
1796
  private fun checkUpcomingTracksForUrls(lookahead: Int = 5) {
1749
- val nextTracks = getNextTracksInternal(lookahead)
1750
- val tracksNeedingUrls = nextTracks.filter { it.url.isEmpty() }
1797
+ val upcomingTracks = if (currentTrackIndex < 0) {
1798
+ // Playback hasn't started yet - check first N tracks from the loaded playlist
1799
+ currentTracks.take(lookahead)
1800
+ } else {
1801
+ // Playback is active - check upcoming tracks
1802
+ getNextTracksInternal(lookahead)
1803
+ }
1804
+
1805
+ // Always include the current track if it has no URL — it can't play without one
1806
+ val currentTrack = getCurrentTrack()
1807
+ val currentNeedsUrl = currentTrack != null && currentTrack.url.isEmpty()
1808
+ val candidateTracks = if (currentNeedsUrl) listOf(currentTrack!!) + upcomingTracks else upcomingTracks
1809
+
1810
+ val tracksNeedingUrls = candidateTracks.filter { it.url.isEmpty() }
1751
1811
 
1752
1812
  if (tracksNeedingUrls.isNotEmpty()) {
1753
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ ${tracksNeedingUrls.size} upcoming tracks need URLs")
1813
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ ${tracksNeedingUrls.size} upcoming tracks need URLs" }
1754
1814
  notifyTracksNeedUpdate(tracksNeedingUrls, lookahead)
1755
1815
  }
1756
1816
  }
@@ -205,12 +205,14 @@ class DownloadDatabase private constructor(
205
205
  downloadedTracks.remove(trackId)
206
206
 
207
207
  // Remove from all playlist associations
208
+ val emptyPlaylists = mutableListOf<String>()
208
209
  playlistTracks.forEach { (playlistId, trackIds) ->
209
210
  trackIds.remove(trackId)
210
211
  if (trackIds.isEmpty()) {
211
- playlistTracks.remove(playlistId)
212
+ emptyPlaylists.add(playlistId)
212
213
  }
213
214
  }
215
+ emptyPlaylists.forEach { playlistTracks.remove(it) }
214
216
 
215
217
  saveToDisk()
216
218
  }
@@ -28,6 +28,8 @@ class DownloadManagerCore private constructor(
28
28
  instance ?: synchronized(this) {
29
29
  instance ?: DownloadManagerCore(context.applicationContext).also { instance = it }
30
30
  }
31
+
32
+ private val ACTIVE_STATES = setOf(DownloadState.DOWNLOADING, DownloadState.PENDING, DownloadState.PAUSED)
31
33
  }
32
34
 
33
35
  // Configuration
@@ -221,20 +223,29 @@ class DownloadManagerCore private constructor(
221
223
 
222
224
  fun getActiveDownloads(): Array<DownloadTask> =
223
225
  activeTasks.values
224
- .filter { it.state in listOf(DownloadState.DOWNLOADING, DownloadState.PENDING, DownloadState.PAUSED) }
226
+ .filter { it.state in ACTIVE_STATES }
225
227
  .map { it.toDownloadTask() }
226
228
  .toTypedArray()
227
229
 
228
230
  fun getQueueStatus(): DownloadQueueStatus {
229
- val metadata = activeTasks.values.toList()
231
+ var pendingCount = 0
232
+ var activeCount = 0
233
+ var failedCount = 0
234
+ var totalBytes = 0.0
235
+ var downloadedBytes = 0.0
236
+
237
+ for (m in activeTasks.values) {
238
+ when (m.state) {
239
+ DownloadState.PENDING -> pendingCount++
240
+ DownloadState.DOWNLOADING -> activeCount++
241
+ DownloadState.FAILED -> failedCount++
242
+ else -> {}
243
+ }
244
+ totalBytes += m.totalBytes ?: 0.0
245
+ downloadedBytes += m.bytesDownloaded
246
+ }
230
247
 
231
- val pendingCount = metadata.count { it.state == DownloadState.PENDING }
232
- val activeCount = metadata.count { it.state == DownloadState.DOWNLOADING }
233
248
  val completedCount = database.getAllDownloadedTracks().size
234
- val failedCount = metadata.count { it.state == DownloadState.FAILED }
235
-
236
- val totalBytes = metadata.sumOf { it.totalBytes ?: 0.0 }
237
- val downloadedBytes = metadata.sumOf { it.bytesDownloaded }
238
249
 
239
250
  return DownloadQueueStatus(
240
251
  pendingCount = pendingCount.toDouble(),
@@ -35,6 +35,7 @@ class DownloadWorker(
35
35
  private const val NOTIFICATION_CHANNEL_ID = "nitro_player_downloads"
36
36
  private const val NOTIFICATION_ID = 2001
37
37
  private const val BUFFER_SIZE = 8192
38
+ private val CONTENT_DISPOSITION_REGEX = Regex("filename=\"?([^\";]+)\"?")
38
39
  }
39
40
 
40
41
  private val downloadManager = DownloadManagerCore.getInstance(context)
@@ -130,7 +131,7 @@ class DownloadWorker(
130
131
  if (extension.isNullOrEmpty()) {
131
132
  val contentDisposition = connection.getHeaderField("Content-Disposition")
132
133
  if (contentDisposition != null) {
133
- val match = Regex("filename=\"?([^\";]+)\"?").find(contentDisposition)
134
+ val match = CONTENT_DISPOSITION_REGEX.find(contentDisposition)
134
135
  if (match != null) {
135
136
  val filename = match.groupValues[1]
136
137
  extension = MimeTypeMap.getFileExtensionFromUrl(filename)
@@ -190,8 +190,7 @@ class EqualizerCore private constructor(
190
190
  currentPresetName = null // Custom settings
191
191
  notifyBandChange(getBands())
192
192
  notifyPresetChange(null)
193
- saveBandGains(getAllGains())
194
- saveCurrentPreset(null)
193
+ saveBandGainsAndPreset(getAllGains(), null)
195
194
  true
196
195
  } catch (e: Exception) {
197
196
  false
@@ -389,6 +388,19 @@ class EqualizerCore private constructor(
389
388
  }
390
389
  }
391
390
 
391
+ private fun saveBandGainsAndPreset(gains: List<Double>, presetName: String?) {
392
+ val json = JSONArray()
393
+ gains.forEach { json.put(it) }
394
+ prefs.edit().apply {
395
+ putString("eq_band_gains", json.toString())
396
+ if (presetName != null) {
397
+ putString("eq_current_preset", presetName)
398
+ } else {
399
+ remove("eq_current_preset")
400
+ }
401
+ }.apply()
402
+ }
403
+
392
404
  private fun restoreSettings() {
393
405
  val enabled = prefs.getBoolean("eq_enabled", false)
394
406
  val gainsJson = prefs.getString("eq_band_gains", null)