react-native-nitro-player 0.5.8 → 0.5.9-alpha.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 (269) 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 +112 -55
  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 +142 -41
  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 +14 -2
  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/nitrogen/generated/android/NitroPlayer+autolinking.cmake +1 -1
  21. package/nitrogen/generated/android/NitroPlayer+autolinking.gradle +1 -1
  22. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +76 -73
  23. package/nitrogen/generated/android/NitroPlayerOnLoad.hpp +14 -5
  24. package/nitrogen/generated/android/c++/JCurrentPlayingType.hpp +5 -6
  25. package/nitrogen/generated/android/c++/JDownloadConfig.hpp +1 -1
  26. package/nitrogen/generated/android/c++/JDownloadError.hpp +1 -1
  27. package/nitrogen/generated/android/c++/JDownloadErrorReason.hpp +8 -9
  28. package/nitrogen/generated/android/c++/JDownloadProgress.hpp +1 -1
  29. package/nitrogen/generated/android/c++/JDownloadQueueStatus.hpp +1 -1
  30. package/nitrogen/generated/android/c++/JDownloadState.hpp +7 -8
  31. package/nitrogen/generated/android/c++/JDownloadStorageInfo.hpp +1 -1
  32. package/nitrogen/generated/android/c++/JDownloadTask.hpp +1 -1
  33. package/nitrogen/generated/android/c++/JDownloadedPlaylist.hpp +1 -1
  34. package/nitrogen/generated/android/c++/JDownloadedTrack.hpp +1 -1
  35. package/nitrogen/generated/android/c++/JEqualizerBand.hpp +1 -1
  36. package/nitrogen/generated/android/c++/JEqualizerPreset.hpp +1 -1
  37. package/nitrogen/generated/android/c++/JEqualizerState.hpp +1 -1
  38. package/nitrogen/generated/android/c++/JFunc_void_DownloadProgress.hpp +1 -1
  39. package/nitrogen/generated/android/c++/JFunc_void_DownloadedTrack.hpp +1 -1
  40. package/nitrogen/generated/android/c++/JFunc_void_TrackItem_std__optional_Reason_.hpp +1 -1
  41. package/nitrogen/generated/android/c++/JFunc_void_TrackPlayerState_std__optional_Reason_.hpp +1 -1
  42. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +1 -1
  43. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +1 -1
  44. package/nitrogen/generated/android/c++/JFunc_void_double_double_std__optional_bool_.hpp +1 -1
  45. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__std__string__.hpp +1 -1
  46. package/nitrogen/generated/android/c++/JFunc_void_std__string_Playlist_std__optional_QueueOperation_.hpp +1 -1
  47. package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string_DownloadState_std__optional_DownloadError_.hpp +1 -1
  48. package/nitrogen/generated/android/c++/JFunc_void_std__vector_EqualizerBand_.hpp +1 -1
  49. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Playlist__std__optional_QueueOperation_.hpp +1 -1
  50. package/nitrogen/generated/android/c++/JFunc_void_std__vector_TrackItem__double.hpp +1 -1
  51. package/nitrogen/generated/android/c++/JGainRange.hpp +1 -1
  52. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.cpp +8 -1
  53. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.hpp +2 -1
  54. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.cpp +8 -1
  55. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.hpp +2 -1
  56. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +9 -1
  57. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +2 -1
  58. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +8 -1
  59. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +2 -1
  60. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +8 -1
  61. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +2 -1
  62. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -1
  63. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +2 -1
  64. package/nitrogen/generated/android/c++/JPlaybackSource.hpp +4 -5
  65. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +1 -1
  66. package/nitrogen/generated/android/c++/JPlayerState.hpp +1 -1
  67. package/nitrogen/generated/android/c++/JPlaylist.hpp +1 -1
  68. package/nitrogen/generated/android/c++/JPresetType.hpp +3 -4
  69. package/nitrogen/generated/android/c++/JQueueOperation.hpp +5 -6
  70. package/nitrogen/generated/android/c++/JReason.hpp +6 -7
  71. package/nitrogen/generated/android/c++/JRepeatMode.hpp +4 -5
  72. package/nitrogen/generated/android/c++/JStorageLocation.hpp +3 -4
  73. package/nitrogen/generated/android/c++/JTAudioDevice.hpp +1 -1
  74. package/nitrogen/generated/android/c++/JTrackItem.hpp +1 -1
  75. package/nitrogen/generated/android/c++/JTrackPlayerState.hpp +4 -5
  76. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +1 -1
  77. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
  78. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.cpp +1 -1
  79. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadError.hpp +3 -3
  80. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.cpp +1 -1
  81. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadTask.hpp +3 -3
  82. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.cpp +1 -1
  83. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedPlaylist.hpp +3 -3
  84. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.cpp +1 -1
  85. package/nitrogen/generated/android/c++/JVariant_NullType_DownloadedTrack.hpp +3 -3
  86. package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.cpp +1 -1
  87. package/nitrogen/generated/android/c++/JVariant_NullType_Playlist.hpp +3 -3
  88. package/nitrogen/generated/android/c++/JVariant_NullType_String.cpp +1 -1
  89. package/nitrogen/generated/android/c++/JVariant_NullType_String.hpp +3 -3
  90. package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.cpp +1 -1
  91. package/nitrogen/generated/android/c++/JVariant_NullType_TrackItem.hpp +3 -3
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/CurrentPlayingType.kt +3 -1
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadConfig.kt +2 -2
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadError.kt +2 -2
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadErrorReason.kt +3 -1
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadProgress.kt +2 -2
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadQueueStatus.kt +2 -2
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadState.kt +3 -1
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadStorageInfo.kt +2 -2
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadTask.kt +2 -2
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedPlaylist.kt +2 -2
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/DownloadedTrack.kt +2 -2
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerBand.kt +2 -2
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerPreset.kt +2 -2
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/EqualizerState.kt +2 -2
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadProgress.kt +1 -1
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_DownloadedTrack.kt +1 -1
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TrackItem_std__optional_Reason_.kt +1 -1
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TrackPlayerState_std__optional_Reason_.kt +1 -1
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_bool.kt +1 -1
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_double_double.kt +1 -1
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_double_double_std__optional_bool_.kt +1 -1
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__optional_std__variant_nitro__NullType__std__string__.kt +1 -1
  114. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_Playlist_std__optional_QueueOperation_.kt +1 -1
  115. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.kt +1 -1
  116. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_EqualizerBand_.kt +1 -1
  117. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_Playlist__std__optional_QueueOperation_.kt +1 -1
  118. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_TrackItem__double.kt +1 -1
  119. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/GainRange.kt +2 -2
  120. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrarySpec.kt +1 -1
  121. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAudioDevicesSpec.kt +1 -1
  122. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +1 -1
  123. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +1 -1
  124. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +1 -1
  125. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +1 -1
  126. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/NitroPlayerOnLoad.kt +1 -1
  127. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlaybackSource.kt +3 -1
  128. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerConfig.kt +2 -2
  129. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerState.kt +2 -2
  130. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Playlist.kt +2 -2
  131. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PresetType.kt +3 -1
  132. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/QueueOperation.kt +3 -1
  133. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Reason.kt +3 -1
  134. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/RepeatMode.kt +3 -1
  135. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/StorageLocation.kt +3 -1
  136. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TAudioDevice.kt +2 -2
  137. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackItem.kt +2 -2
  138. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TrackPlayerState.kt +3 -1
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Double.kt +1 -1
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadError.kt +1 -1
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadTask.kt +1 -1
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedPlaylist.kt +1 -1
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_DownloadedTrack.kt +1 -1
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_Playlist.kt +1 -1
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_String.kt +1 -1
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Variant_NullType_TrackItem.kt +1 -1
  147. package/nitrogen/generated/ios/NitroPlayer+autolinking.rb +2 -2
  148. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +1 -1
  149. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +21 -21
  150. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +1 -1
  151. package/nitrogen/generated/ios/NitroPlayerAutolinking.mm +1 -1
  152. package/nitrogen/generated/ios/NitroPlayerAutolinking.swift +25 -36
  153. package/nitrogen/generated/ios/c++/HybridAudioRoutePickerSpecSwift.cpp +1 -1
  154. package/nitrogen/generated/ios/c++/HybridAudioRoutePickerSpecSwift.hpp +7 -1
  155. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.cpp +1 -1
  156. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +7 -1
  157. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.cpp +1 -1
  158. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +7 -1
  159. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.cpp +1 -1
  160. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +7 -1
  161. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.cpp +1 -1
  162. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +7 -1
  163. package/nitrogen/generated/ios/swift/CurrentPlayingType.swift +1 -1
  164. package/nitrogen/generated/ios/swift/DownloadConfig.swift +78 -168
  165. package/nitrogen/generated/ios/swift/DownloadError.swift +9 -34
  166. package/nitrogen/generated/ios/swift/DownloadErrorReason.swift +1 -1
  167. package/nitrogen/generated/ios/swift/DownloadProgress.swift +13 -50
  168. package/nitrogen/generated/ios/swift/DownloadQueueStatus.swift +15 -58
  169. package/nitrogen/generated/ios/swift/DownloadState.swift +1 -1
  170. package/nitrogen/generated/ios/swift/DownloadStorageInfo.swift +11 -42
  171. package/nitrogen/generated/ios/swift/DownloadTask.swift +97 -210
  172. package/nitrogen/generated/ios/swift/DownloadedPlaylist.swift +13 -56
  173. package/nitrogen/generated/ios/swift/DownloadedTrack.swift +34 -90
  174. package/nitrogen/generated/ios/swift/EqualizerBand.swift +9 -34
  175. package/nitrogen/generated/ios/swift/EqualizerPreset.swift +7 -32
  176. package/nitrogen/generated/ios/swift/EqualizerState.swift +26 -64
  177. package/nitrogen/generated/ios/swift/Func_void.swift +1 -2
  178. package/nitrogen/generated/ios/swift/Func_void_DownloadProgress.swift +1 -2
  179. package/nitrogen/generated/ios/swift/Func_void_DownloadStorageInfo.swift +1 -2
  180. package/nitrogen/generated/ios/swift/Func_void_DownloadedTrack.swift +1 -2
  181. package/nitrogen/generated/ios/swift/Func_void_PlayerState.swift +1 -2
  182. package/nitrogen/generated/ios/swift/Func_void_TrackItem_std__optional_Reason_.swift +1 -2
  183. package/nitrogen/generated/ios/swift/Func_void_TrackPlayerState_std__optional_Reason_.swift +1 -2
  184. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -2
  185. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -2
  186. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +1 -2
  187. package/nitrogen/generated/ios/swift/Func_void_double_double_std__optional_bool_.swift +1 -2
  188. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -2
  189. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__std__string__.swift +1 -2
  190. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -2
  191. package/nitrogen/generated/ios/swift/Func_void_std__string_Playlist_std__optional_QueueOperation_.swift +1 -2
  192. package/nitrogen/generated/ios/swift/Func_void_std__string_std__string_DownloadState_std__optional_DownloadError_.swift +1 -2
  193. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +1 -2
  194. package/nitrogen/generated/ios/swift/Func_void_std__vector_Playlist__std__optional_QueueOperation_.swift +1 -2
  195. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem_.swift +1 -2
  196. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem__double.swift +1 -2
  197. package/nitrogen/generated/ios/swift/Func_void_std__vector_std__string_.swift +1 -2
  198. package/nitrogen/generated/ios/swift/GainRange.swift +5 -18
  199. package/nitrogen/generated/ios/swift/HybridAudioRoutePickerSpec.swift +3 -4
  200. package/nitrogen/generated/ios/swift/HybridAudioRoutePickerSpec_cxx.swift +9 -2
  201. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +3 -4
  202. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +9 -2
  203. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +3 -4
  204. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +9 -2
  205. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +3 -4
  206. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +25 -4
  207. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +3 -4
  208. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +9 -2
  209. package/nitrogen/generated/ios/swift/PlaybackSource.swift +1 -1
  210. package/nitrogen/generated/ios/swift/PlayerConfig.swift +37 -79
  211. package/nitrogen/generated/ios/swift/PlayerState.swift +53 -122
  212. package/nitrogen/generated/ios/swift/Playlist.swift +49 -112
  213. package/nitrogen/generated/ios/swift/PresetType.swift +1 -1
  214. package/nitrogen/generated/ios/swift/QueueOperation.swift +1 -1
  215. package/nitrogen/generated/ios/swift/Reason.swift +1 -1
  216. package/nitrogen/generated/ios/swift/RepeatMode.swift +1 -1
  217. package/nitrogen/generated/ios/swift/StorageLocation.swift +1 -1
  218. package/nitrogen/generated/ios/swift/TrackItem.swift +43 -111
  219. package/nitrogen/generated/ios/swift/TrackPlayerState.swift +1 -1
  220. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +1 -1
  221. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadError.swift +1 -1
  222. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadTask.swift +1 -1
  223. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedPlaylist.swift +1 -1
  224. package/nitrogen/generated/ios/swift/Variant_NullType_DownloadedTrack.swift +1 -1
  225. package/nitrogen/generated/ios/swift/Variant_NullType_Playlist.swift +1 -1
  226. package/nitrogen/generated/ios/swift/Variant_NullType_String.swift +1 -1
  227. package/nitrogen/generated/ios/swift/Variant_NullType_TrackItem.swift +1 -1
  228. package/nitrogen/generated/shared/c++/CurrentPlayingType.hpp +1 -1
  229. package/nitrogen/generated/shared/c++/DownloadConfig.hpp +34 -26
  230. package/nitrogen/generated/shared/c++/DownloadError.hpp +22 -14
  231. package/nitrogen/generated/shared/c++/DownloadErrorReason.hpp +1 -1
  232. package/nitrogen/generated/shared/c++/DownloadProgress.hpp +28 -20
  233. package/nitrogen/generated/shared/c++/DownloadQueueStatus.hpp +31 -23
  234. package/nitrogen/generated/shared/c++/DownloadState.hpp +1 -1
  235. package/nitrogen/generated/shared/c++/DownloadStorageInfo.hpp +25 -17
  236. package/nitrogen/generated/shared/c++/DownloadTask.hpp +40 -32
  237. package/nitrogen/generated/shared/c++/DownloadedPlaylist.hpp +28 -20
  238. package/nitrogen/generated/shared/c++/DownloadedTrack.hpp +31 -23
  239. package/nitrogen/generated/shared/c++/EqualizerBand.hpp +22 -14
  240. package/nitrogen/generated/shared/c++/EqualizerPreset.hpp +19 -11
  241. package/nitrogen/generated/shared/c++/EqualizerState.hpp +19 -11
  242. package/nitrogen/generated/shared/c++/GainRange.hpp +16 -8
  243. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.cpp +1 -1
  244. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.hpp +1 -1
  245. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.cpp +1 -1
  246. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.hpp +1 -1
  247. package/nitrogen/generated/shared/c++/HybridAudioRoutePickerSpec.cpp +1 -1
  248. package/nitrogen/generated/shared/c++/HybridAudioRoutePickerSpec.hpp +1 -1
  249. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.cpp +1 -1
  250. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +1 -1
  251. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.cpp +1 -1
  252. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +1 -1
  253. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.cpp +1 -1
  254. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +1 -1
  255. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -1
  256. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +1 -1
  257. package/nitrogen/generated/shared/c++/PlaybackSource.hpp +1 -1
  258. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +22 -14
  259. package/nitrogen/generated/shared/c++/PlayerState.hpp +31 -23
  260. package/nitrogen/generated/shared/c++/Playlist.hpp +25 -17
  261. package/nitrogen/generated/shared/c++/PresetType.hpp +1 -1
  262. package/nitrogen/generated/shared/c++/QueueOperation.hpp +1 -1
  263. package/nitrogen/generated/shared/c++/Reason.hpp +1 -1
  264. package/nitrogen/generated/shared/c++/RepeatMode.hpp +1 -1
  265. package/nitrogen/generated/shared/c++/StorageLocation.hpp +1 -1
  266. package/nitrogen/generated/shared/c++/TAudioDevice.hpp +22 -14
  267. package/nitrogen/generated/shared/c++/TrackItem.hpp +34 -26
  268. package/nitrogen/generated/shared/c++/TrackPlayerState.hpp +1 -1
  269. package/package.json +3 -3
@@ -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,7 +82,7 @@ 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
87
 
88
88
  // Temporary tracks for addToUpNext and playNext
@@ -171,7 +171,7 @@ class TrackPlayerCore private constructor(
171
171
  // Notify JavaScript
172
172
  onAndroidAutoConnectionChange?.invoke(connected)
173
173
 
174
- NitroPlayerLogger.log("TrackPlayerCore", "🚗 Android Auto connection changed: connected=$connected, type=$connectionType")
174
+ NitroPlayerLogger.log("TrackPlayerCore") { "🚗 Android Auto connection changed: connected=$connected, type=$connectionType" }
175
175
  }
176
176
  }
177
177
  registerCarConnectionReceiver()
@@ -423,7 +423,7 @@ class TrackPlayerCore private constructor(
423
423
  }
424
424
  }
425
425
  } catch (e: Exception) {
426
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Error playing from playlist track - ${e.message}")
426
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Error playing from playlist track - ${e.message}" }
427
427
  e.printStackTrace()
428
428
  }
429
429
  }
@@ -563,19 +563,19 @@ class TrackPlayerCore private constructor(
563
563
 
564
564
  // Case 1: If fromPlaylist is provided, use that playlist
565
565
  if (fromPlaylist != null) {
566
- NitroPlayerLogger.log("TrackPlayerCore", "🎵 TrackPlayerCore: Looking for song in specified playlist: $fromPlaylist")
566
+ NitroPlayerLogger.log("TrackPlayerCore") { "🎵 TrackPlayerCore: Looking for song in specified playlist: $fromPlaylist" }
567
567
  val playlist = playlistManager.getPlaylist(fromPlaylist)
568
568
  if (playlist != null) {
569
569
  songIndex = playlist.tracks.indexOfFirst { it.id == songId }
570
570
  if (songIndex >= 0) {
571
571
  targetPlaylistId = fromPlaylist
572
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in playlist $fromPlaylist")
572
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in playlist $fromPlaylist" }
573
573
  } else {
574
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Song $songId not found in specified playlist $fromPlaylist")
574
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Song $songId not found in specified playlist $fromPlaylist" }
575
575
  return
576
576
  }
577
577
  } else {
578
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Playlist $fromPlaylist not found")
578
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Playlist $fromPlaylist not found" }
579
579
  return
580
580
  }
581
581
  }
@@ -590,7 +590,7 @@ class TrackPlayerCore private constructor(
590
590
  songIndex = currentPlaylist.tracks.indexOfFirst { it.id == songId }
591
591
  if (songIndex >= 0) {
592
592
  targetPlaylistId = currentPlaylistId
593
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in current playlist $currentPlaylistId")
593
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in current playlist $currentPlaylistId" }
594
594
  }
595
595
  }
596
596
  }
@@ -604,7 +604,7 @@ class TrackPlayerCore private constructor(
604
604
  songIndex = playlist.tracks.indexOfFirst { it.id == songId }
605
605
  if (songIndex >= 0) {
606
606
  targetPlaylistId = playlist.id
607
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Found song at index $songIndex in playlist ${playlist.id}")
607
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Found song at index $songIndex in playlist ${playlist.id}" }
608
608
  break
609
609
  }
610
610
  }
@@ -626,7 +626,7 @@ class TrackPlayerCore private constructor(
626
626
 
627
627
  // Load playlist if it's different from current
628
628
  if (currentPlaylistId != targetPlaylistId) {
629
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Loading new playlist: $targetPlaylistId")
629
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Loading new playlist: $targetPlaylistId" }
630
630
  val playlist = playlistManager.getPlaylist(targetPlaylistId)
631
631
  if (playlist != null) {
632
632
  currentPlaylistId = targetPlaylistId
@@ -634,12 +634,12 @@ class TrackPlayerCore private constructor(
634
634
 
635
635
  // Wait a bit for playlist to load, then play from index
636
636
  // Note: Removed postDelayed to avoid race conditions with subsequent queue operations
637
- NitroPlayerLogger.log("TrackPlayerCore", "▶️ Playing from index: $songIndex")
637
+ NitroPlayerLogger.log("TrackPlayerCore") { "▶️ Playing from index: $songIndex" }
638
638
  playFromIndex(songIndex)
639
639
  }
640
640
  } else {
641
641
  // Playlist already loaded, just play from index
642
- NitroPlayerLogger.log("TrackPlayerCore", "▶️ Playing from index: $songIndex")
642
+ NitroPlayerLogger.log("TrackPlayerCore") { "▶️ Playing from index: $songIndex" }
643
643
  playFromIndex(songIndex)
644
644
  }
645
645
  }
@@ -687,7 +687,7 @@ class TrackPlayerCore private constructor(
687
687
  playFromIndexInternal(currentTrackIndex)
688
688
  } else if (currentTrackIndex > 0) {
689
689
  // Go to previous track in original playlist
690
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 TrackPlayerCore: Going to previous track, currentTrackIndex: $currentTrackIndex -> ${currentTrackIndex - 1}")
690
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 TrackPlayerCore: Going to previous track, currentTrackIndex: $currentTrackIndex -> ${currentTrackIndex - 1}" }
691
691
  playFromIndexInternal(currentTrackIndex - 1)
692
692
  } else {
693
693
  // Already at first track, seek to beginning
@@ -718,7 +718,7 @@ class TrackPlayerCore private constructor(
718
718
  }
719
719
  }
720
720
  }
721
- NitroPlayerLogger.log("TrackPlayerCore", "🔁 setRepeatMode: $mode")
721
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔁 setRepeatMode: $mode" }
722
722
  return true
723
723
  }
724
724
 
@@ -750,7 +750,15 @@ class TrackPlayerCore private constructor(
750
750
  Thread.currentThread().interrupt()
751
751
  }
752
752
 
753
- return result ?: getStateInternal()
753
+ return result ?: PlayerState(
754
+ currentTrack = null,
755
+ currentPosition = 0.0,
756
+ totalDuration = 0.0,
757
+ currentState = TrackPlayerState.STOPPED,
758
+ currentPlaylistId = null,
759
+ currentIndex = -1.0,
760
+ currentPlayingType = CurrentPlayingType.NOT_PLAYING
761
+ )
754
762
  }
755
763
 
756
764
  private fun getStateInternal(): PlayerState =
@@ -832,7 +840,7 @@ class TrackPlayerCore private constructor(
832
840
  }
833
841
  lookaheadCount?.let {
834
842
  this.lookaheadCount = it
835
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Lookahead count set to: $it")
843
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Lookahead count set to: $it" }
836
844
  }
837
845
  mediaSessionManager?.configure(
838
846
  androidAutoEnabled,
@@ -985,7 +993,7 @@ class TrackPlayerCore private constructor(
985
993
 
986
994
  // Remove tracks before the target from playNext (they're being skipped)
987
995
  if (actualListIndex > 0) {
988
- repeat(actualListIndex) { playNextStack.removeAt(0) }
996
+ playNextStack.subList(0, actualListIndex).clear()
989
997
  }
990
998
 
991
999
  // Rebuild queue and advance
@@ -1010,7 +1018,7 @@ class TrackPlayerCore private constructor(
1010
1018
 
1011
1019
  // Remove tracks before target from upNext
1012
1020
  if (actualListIndex > 0) {
1013
- repeat(actualListIndex) { upNextQueue.removeAt(0) }
1021
+ upNextQueue.subList(0, actualListIndex).clear()
1014
1022
  }
1015
1023
 
1016
1024
  // Rebuild queue and advance
@@ -1066,7 +1074,7 @@ class TrackPlayerCore private constructor(
1066
1074
  }
1067
1075
 
1068
1076
  if (index < 0 || index >= currentTracks.size) {
1069
- NitroPlayerLogger.log("TrackPlayerCore", " ❌ Invalid index $index for currentTracks size ${currentTracks.size}")
1077
+ NitroPlayerLogger.log("TrackPlayerCore") { " ❌ Invalid index $index for currentTracks size ${currentTracks.size}" }
1070
1078
  return
1071
1079
  }
1072
1080
 
@@ -1112,18 +1120,18 @@ class TrackPlayerCore private constructor(
1112
1120
  }
1113
1121
 
1114
1122
  private fun addToUpNextInternal(trackId: String) {
1115
- NitroPlayerLogger.log("TrackPlayerCore", "📋 TrackPlayerCore: addToUpNext($trackId)")
1123
+ NitroPlayerLogger.log("TrackPlayerCore") { "📋 TrackPlayerCore: addToUpNext($trackId)" }
1116
1124
 
1117
1125
  // Find the track from current playlist or all playlists
1118
1126
  val track = findTrackById(trackId)
1119
1127
  if (track == null) {
1120
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Track $trackId not found")
1128
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Track $trackId not found" }
1121
1129
  return
1122
1130
  }
1123
1131
 
1124
1132
  // Add to end of upNext queue (FIFO)
1125
1133
  upNextQueue.add(track)
1126
- NitroPlayerLogger.log("TrackPlayerCore", " ✅ Added '${track.title}' to upNext queue (position: ${upNextQueue.size})")
1134
+ NitroPlayerLogger.log("TrackPlayerCore") { " ✅ Added '${track.title}' to upNext queue (position: ${upNextQueue.size})" }
1127
1135
 
1128
1136
  // Rebuild the player queue if actively playing
1129
1137
  if (::player.isInitialized && player.currentMediaItem != null) {
@@ -1142,18 +1150,18 @@ class TrackPlayerCore private constructor(
1142
1150
  }
1143
1151
 
1144
1152
  private fun playNextInternal(trackId: String) {
1145
- NitroPlayerLogger.log("TrackPlayerCore", "⏭️ TrackPlayerCore: playNext($trackId)")
1153
+ NitroPlayerLogger.log("TrackPlayerCore") { "⏭️ TrackPlayerCore: playNext($trackId)" }
1146
1154
 
1147
1155
  // Find the track from current playlist or all playlists
1148
1156
  val track = findTrackById(trackId)
1149
1157
  if (track == null) {
1150
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Track $trackId not found")
1158
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Track $trackId not found" }
1151
1159
  return
1152
1160
  }
1153
1161
 
1154
1162
  // Insert at beginning of playNext stack (LIFO)
1155
1163
  playNextStack.add(0, track)
1156
- NitroPlayerLogger.log("TrackPlayerCore", " ✅ Added '${track.title}' to playNext stack (position: 1)")
1164
+ NitroPlayerLogger.log("TrackPlayerCore") { " ✅ Added '${track.title}' to playNext stack (position: 1)" }
1157
1165
 
1158
1166
  // Rebuild the player queue if actively playing
1159
1167
  if (::player.isInitialized && player.currentMediaItem != null) {
@@ -1274,7 +1282,7 @@ class TrackPlayerCore private constructor(
1274
1282
  NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
1275
1283
  NitroPlayerLogger.log("TrackPlayerCore", "✅ TrackPlayerCore: Android Auto media library set successfully")
1276
1284
  } catch (e: Exception) {
1277
- NitroPlayerLogger.log("TrackPlayerCore", "❌ TrackPlayerCore: Error setting media library - ${e.message}")
1285
+ NitroPlayerLogger.log("TrackPlayerCore") { "❌ TrackPlayerCore: Error setting media library - ${e.message}" }
1278
1286
  e.printStackTrace()
1279
1287
  }
1280
1288
  }
@@ -1297,7 +1305,7 @@ class TrackPlayerCore private constructor(
1297
1305
  // Convert to 0.0-1.0 range for ExoPlayer
1298
1306
  val normalizedVolume = (clampedVolume / 100.0).toFloat()
1299
1307
  player.volume = normalizedVolume
1300
- NitroPlayerLogger.log("TrackPlayerCore", "🔊 TrackPlayerCore: Volume set to $clampedVolume% (normalized: $normalizedVolume)")
1308
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔊 TrackPlayerCore: Volume set to $clampedVolume% (normalized: $normalizedVolume)" }
1301
1309
  }
1302
1310
  true
1303
1311
  } else {
@@ -1342,7 +1350,7 @@ class TrackPlayerCore private constructor(
1342
1350
  try {
1343
1351
  callback(track, reason)
1344
1352
  } catch (e: Exception) {
1345
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in track change listener: ${e.message}")
1353
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in track change listener: ${e.message}" }
1346
1354
  }
1347
1355
  }
1348
1356
  }
@@ -1363,7 +1371,7 @@ class TrackPlayerCore private constructor(
1363
1371
  try {
1364
1372
  callback(state, reason)
1365
1373
  } catch (e: Exception) {
1366
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in playback state listener: ${e.message}")
1374
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in playback state listener: ${e.message}" }
1367
1375
  }
1368
1376
  }
1369
1377
  }
@@ -1384,29 +1392,38 @@ class TrackPlayerCore private constructor(
1384
1392
  try {
1385
1393
  callback(position, duration)
1386
1394
  } catch (e: Exception) {
1387
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in seek listener: ${e.message}")
1395
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in seek listener: ${e.message}" }
1388
1396
  }
1389
1397
  }
1390
1398
  }
1391
1399
  }
1392
1400
 
1401
+ private var progressNotifyCounter = 0
1402
+ private val progressCallbackScratch = ArrayList<(Double, Double, Boolean?) -> Unit>(4)
1403
+
1393
1404
  private fun notifyPlaybackProgress(
1394
1405
  position: Double,
1395
1406
  duration: Double,
1396
1407
  isPlaying: Boolean?,
1397
1408
  ) {
1398
- val liveCallbacks =
1399
- synchronized(onPlaybackProgressChangeListeners) {
1409
+ progressCallbackScratch.clear()
1410
+ synchronized(onPlaybackProgressChangeListeners) {
1411
+ if (++progressNotifyCounter % 10 == 0) {
1400
1412
  onPlaybackProgressChangeListeners.removeAll { !it.isAlive }
1401
- onPlaybackProgressChangeListeners.map { it.callback }
1402
1413
  }
1414
+ for (box in onPlaybackProgressChangeListeners) {
1415
+ if (box.isAlive) progressCallbackScratch.add(box.callback)
1416
+ }
1417
+ }
1418
+
1419
+ if (progressCallbackScratch.isEmpty()) return
1403
1420
 
1404
1421
  handler.post {
1405
- for (callback in liveCallbacks) {
1422
+ for (callback in progressCallbackScratch) {
1406
1423
  try {
1407
1424
  callback(position, duration, isPlaying)
1408
1425
  } catch (e: Exception) {
1409
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in playback progress listener: ${e.message}")
1426
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in playback progress listener: ${e.message}" }
1410
1427
  }
1411
1428
  }
1412
1429
  }
@@ -1502,22 +1519,34 @@ class TrackPlayerCore private constructor(
1502
1519
  */
1503
1520
  fun updateTracks(tracks: List<TrackItem>) {
1504
1521
  handler.post {
1505
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 updateTracks: ${tracks.size} updates")
1522
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 updateTracks: ${tracks.size} updates" }
1506
1523
 
1507
- // Get current track ID to avoid updating it (preserves gapless playback)
1508
- val currentTrackId = getCurrentTrack()?.id
1524
+ // Get current track to decide how to handle it
1525
+ val currentTrack = getCurrentTrack()
1526
+ val currentTrackId = currentTrack?.id
1527
+
1528
+ // Separate the current-track update (if any) from the rest
1529
+ val currentTrackUpdate = if (currentTrackId != null) tracks.find { it.id == currentTrackId } else null
1530
+ val currentTrackIsEmpty = currentTrack?.url.isNullOrEmpty()
1509
1531
 
1510
1532
  // Filter out current track and validate
1511
1533
  val safeTracks =
1512
1534
  tracks.filter { track ->
1513
1535
  when {
1514
- track.id == currentTrackId -> {
1515
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Skipping update for currently playing track: ${track.id} (preserves gapless)")
1536
+ track.id == currentTrackId && !currentTrackIsEmpty -> {
1537
+ // Has a real URL already skip to preserve gapless playback
1538
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Skipping update for currently playing track: ${track.id} (preserves gapless)" }
1516
1539
  false
1517
1540
  }
1518
1541
 
1542
+ track.id == currentTrackId && currentTrackIsEmpty -> {
1543
+ // Empty URL — must not be playing, allow the update
1544
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Updating current track with no URL: ${track.id}" }
1545
+ track.url.isNotEmpty() // only include if the update actually provides a URL
1546
+ }
1547
+
1519
1548
  track.url.isEmpty() -> {
1520
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Skipping track with empty URL: ${track.id}")
1549
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Skipping track with empty URL: ${track.id}" }
1521
1550
  false
1522
1551
  }
1523
1552
 
@@ -1535,9 +1564,26 @@ class TrackPlayerCore private constructor(
1535
1564
  // Update in PlaylistManager
1536
1565
  val affectedPlaylists = playlistManager.updateTracks(safeTracks)
1537
1566
 
1538
- // Rebuild queue if current playlist was affected
1567
+ // If the current track was one of the updates (had no URL before), replace its
1568
+ // MediaItem in ExoPlayer directly — rebuildQueueFromCurrentPosition skips index 0.
1569
+ if (currentTrackUpdate != null && currentTrackIsEmpty && currentTrackUpdate.url.isNotEmpty()) {
1570
+ val exoIndex = player.currentMediaItemIndex
1571
+ if (exoIndex >= 0) {
1572
+ val playlistId = currentPlaylistId ?: ""
1573
+ val mediaId = if (playlistId.isNotEmpty()) "$playlistId:${currentTrackUpdate.id}" else currentTrackUpdate.id
1574
+ val newMediaItem = currentTrackUpdate.toMediaItem(mediaId)
1575
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Replacing MediaItem at index $exoIndex for current track with resolved URL" }
1576
+ player.replaceMediaItem(exoIndex, newMediaItem)
1577
+ // If ExoPlayer was in an error/idle state waiting for a URI, re-prepare
1578
+ if (player.playbackState == Player.STATE_IDLE) {
1579
+ player.prepare()
1580
+ }
1581
+ }
1582
+ }
1583
+
1584
+ // Rebuild queue for other updated tracks if current playlist was affected
1539
1585
  if (currentPlaylistId != null && affectedPlaylists.containsKey(currentPlaylistId)) {
1540
- NitroPlayerLogger.log("TrackPlayerCore", "🔄 Rebuilding queue - ${affectedPlaylists[currentPlaylistId]} tracks updated in current playlist")
1586
+ NitroPlayerLogger.log("TrackPlayerCore") { "🔄 Rebuilding queue - ${affectedPlaylists[currentPlaylistId]} tracks updated in current playlist" }
1541
1587
 
1542
1588
  // This method preserves current item and gapless buffering
1543
1589
  rebuildQueueFromCurrentPosition()
@@ -1545,7 +1591,7 @@ class TrackPlayerCore private constructor(
1545
1591
  NitroPlayerLogger.log("TrackPlayerCore", "✅ Queue rebuilt, gapless playback preserved")
1546
1592
  }
1547
1593
 
1548
- NitroPlayerLogger.log("TrackPlayerCore", "✅ Track updates complete - ${affectedPlaylists.size} playlists affected")
1594
+ NitroPlayerLogger.log("TrackPlayerCore") { "✅ Track updates complete - ${affectedPlaylists.size} playlists affected" }
1549
1595
  }
1550
1596
  }
1551
1597
 
@@ -1696,14 +1742,14 @@ class TrackPlayerCore private constructor(
1696
1742
  }
1697
1743
 
1698
1744
  // Add to class properties
1699
- private val onTracksNeedUpdateListeners = mutableListOf<WeakReference<OnTracksNeedUpdateListener>>()
1745
+ private val onTracksNeedUpdateListeners = mutableListOf<OnTracksNeedUpdateListener>()
1700
1746
 
1701
1747
  /**
1702
1748
  * Register listener for when tracks need update
1703
1749
  */
1704
1750
  fun addOnTracksNeedUpdateListener(listener: OnTracksNeedUpdateListener) {
1705
1751
  handler.post {
1706
- onTracksNeedUpdateListeners.add(WeakReference(listener))
1752
+ onTracksNeedUpdateListeners.add(listener)
1707
1753
  }
1708
1754
  }
1709
1755
 
@@ -1712,7 +1758,7 @@ class TrackPlayerCore private constructor(
1712
1758
  */
1713
1759
  fun removeOnTracksNeedUpdateListener(listener: OnTracksNeedUpdateListener) {
1714
1760
  handler.post {
1715
- onTracksNeedUpdateListeners.removeAll { it.get() == listener || it.get() == null }
1761
+ onTracksNeedUpdateListeners.removeAll { it == listener }
1716
1762
  }
1717
1763
  }
1718
1764
 
@@ -1726,8 +1772,7 @@ class TrackPlayerCore private constructor(
1726
1772
  ) {
1727
1773
  val liveCallbacks =
1728
1774
  synchronized(onTracksNeedUpdateListeners) {
1729
- onTracksNeedUpdateListeners.removeAll { it.get() == null }
1730
- onTracksNeedUpdateListeners.mapNotNull { it.get() }
1775
+ onTracksNeedUpdateListeners.toList()
1731
1776
  }
1732
1777
 
1733
1778
  handler.post {
@@ -1735,7 +1780,7 @@ class TrackPlayerCore private constructor(
1735
1780
  try {
1736
1781
  callback.onTracksNeedUpdate(tracks, lookahead)
1737
1782
  } catch (e: Exception) {
1738
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ Error in onTracksNeedUpdate listener: ${e.message}")
1783
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ Error in onTracksNeedUpdate listener: ${e.message}" }
1739
1784
  }
1740
1785
  }
1741
1786
  }
@@ -1746,11 +1791,23 @@ class TrackPlayerCore private constructor(
1746
1791
  * Call this in onMediaItemTransition or after skipTo operations
1747
1792
  */
1748
1793
  private fun checkUpcomingTracksForUrls(lookahead: Int = 5) {
1749
- val nextTracks = getNextTracksInternal(lookahead)
1750
- val tracksNeedingUrls = nextTracks.filter { it.url.isEmpty() }
1794
+ val upcomingTracks = if (currentTrackIndex < 0) {
1795
+ // Playback hasn't started yet - check first N tracks from the loaded playlist
1796
+ currentTracks.take(lookahead)
1797
+ } else {
1798
+ // Playback is active - check upcoming tracks
1799
+ getNextTracksInternal(lookahead)
1800
+ }
1801
+
1802
+ // Always include the current track if it has no URL — it can't play without one
1803
+ val currentTrack = getCurrentTrack()
1804
+ val currentNeedsUrl = currentTrack != null && currentTrack.url.isEmpty()
1805
+ val candidateTracks = if (currentNeedsUrl) listOf(currentTrack!!) + upcomingTracks else upcomingTracks
1806
+
1807
+ val tracksNeedingUrls = candidateTracks.filter { it.url.isEmpty() }
1751
1808
 
1752
1809
  if (tracksNeedingUrls.isNotEmpty()) {
1753
- NitroPlayerLogger.log("TrackPlayerCore", "⚠️ ${tracksNeedingUrls.size} upcoming tracks need URLs")
1810
+ NitroPlayerLogger.log("TrackPlayerCore") { "⚠️ ${tracksNeedingUrls.size} upcoming tracks need URLs" }
1754
1811
  notifyTracksNeedUpdate(tracksNeedingUrls, lookahead)
1755
1812
  }
1756
1813
  }
@@ -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)