@5stones/react-native-audio-browser 0.1.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 (1065) hide show
  1. package/AudioBrowser.podspec +43 -0
  2. package/LICENSE +21 -0
  3. package/README.md +5 -0
  4. package/android/CMakeLists.txt +32 -0
  5. package/android/build.gradle +210 -0
  6. package/android/fix-prefab.gradle +51 -0
  7. package/android/gradle.properties +5 -0
  8. package/android/src/main/AndroidManifest.xml +36 -0
  9. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  10. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +1191 -0
  11. package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +21 -0
  12. package/android/src/main/java/com/audiobrowser/Callbacks.kt +92 -0
  13. package/android/src/main/java/com/audiobrowser/HeadlessTaskService.kt +59 -0
  14. package/android/src/main/java/com/audiobrowser/Service.kt +336 -0
  15. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +1169 -0
  16. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +103 -0
  17. package/android/src/main/java/com/audiobrowser/browser/RouteMatch.kt +9 -0
  18. package/android/src/main/java/com/audiobrowser/browser/SimpleRouter.kt +150 -0
  19. package/android/src/main/java/com/audiobrowser/extension/EnumExtensions.kt +5 -0
  20. package/android/src/main/java/com/audiobrowser/extension/NumberExt.kt +13 -0
  21. package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +171 -0
  22. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +251 -0
  23. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +80 -0
  24. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +101 -0
  25. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +125 -0
  26. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +256 -0
  27. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +163 -0
  28. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +177 -0
  29. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +580 -0
  30. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +578 -0
  31. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +58 -0
  32. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +245 -0
  33. package/android/src/main/java/com/audiobrowser/player/Player.kt +1509 -0
  34. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +230 -0
  35. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +191 -0
  36. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +80 -0
  37. package/android/src/main/java/com/audiobrowser/util/AndroidAudioContentTypeFactory.kt +17 -0
  38. package/android/src/main/java/com/audiobrowser/util/BatteryOptimizationHelper.kt +95 -0
  39. package/android/src/main/java/com/audiobrowser/util/BatteryWarningStore.kt +38 -0
  40. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +155 -0
  41. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +390 -0
  42. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +197 -0
  43. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +75 -0
  44. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +97 -0
  45. package/android/src/main/java/com/audiobrowser/util/NetworkConnectivityMonitor.kt +121 -0
  46. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +25 -0
  47. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +72 -0
  48. package/android/src/main/java/com/audiobrowser/util/RepeatModeFactory.kt +22 -0
  49. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +36 -0
  50. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +130 -0
  51. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +50 -0
  52. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +125 -0
  53. package/android/src/main/res/values/strings.xml +6 -0
  54. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +273 -0
  55. package/android/src/test/java/com/audiobrowser/browser/SimpleBrowserTest.kt +33 -0
  56. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +156 -0
  57. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +240 -0
  58. package/ios/Bridge.h +8 -0
  59. package/ios/Browser/BrowserConfig.swift +85 -0
  60. package/ios/Browser/BrowserManager.swift +985 -0
  61. package/ios/Browser/BrowserPathHelper.swift +156 -0
  62. package/ios/Browser/JsonModels.swift +165 -0
  63. package/ios/Browser/SimpleRouter.swift +184 -0
  64. package/ios/CarPlay/CarPlayController.swift +1342 -0
  65. package/ios/CarPlay/RNABCarPlaySceneDelegate.h +15 -0
  66. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +59 -0
  67. package/ios/CarPlay/Track+CarPlay.swift +49 -0
  68. package/ios/Extension/Capability+RemoteCommand.swift +76 -0
  69. package/ios/Extension/ChapterMetadata+AVFoundation.swift +37 -0
  70. package/ios/Extension/TimedMetadata+AVFoundation.swift +126 -0
  71. package/ios/Extension/Track+AVPlayer.swift +68 -0
  72. package/ios/Extension/TrackMetadata+AVFoundation.swift +128 -0
  73. package/ios/Http/HttpClient.swift +237 -0
  74. package/ios/HybridAudioBrowser.swift +1309 -0
  75. package/ios/Model/MediaURL.swift +66 -0
  76. package/ios/Model/PlayerUpdateOptions.swift +116 -0
  77. package/ios/Model/RemoteCommand.swift +71 -0
  78. package/ios/Model/SourceType.swift +6 -0
  79. package/ios/Model/TrackPlayerError.swift +69 -0
  80. package/ios/NowPlayingInfo/MediaItemProperty.swift +78 -0
  81. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +9 -0
  82. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +283 -0
  83. package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +6 -0
  84. package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +220 -0
  85. package/ios/Observer/PlayerItemNotificationObserver.swift +83 -0
  86. package/ios/Observer/PlayerItemPropertyObserver.swift +110 -0
  87. package/ios/Observer/PlayerStateObserver.swift +52 -0
  88. package/ios/Observer/PlayerTimeObserver.swift +109 -0
  89. package/ios/Option/PitchAlgorithms.swift +17 -0
  90. package/ios/Option/SessionCategories.swift +100 -0
  91. package/ios/Option/TimeEventFrequency.swift +18 -0
  92. package/ios/Player/PlaybackProgressUpdateManager.swift +60 -0
  93. package/ios/Player/PlayingStateManager.swift +29 -0
  94. package/ios/Player/RetryManager.swift +281 -0
  95. package/ios/Player/ShuffleOrder.swift +191 -0
  96. package/ios/Player/SleepTimerManager.swift +137 -0
  97. package/ios/RemoteCommand/RemoteCommandController.swift +400 -0
  98. package/ios/Support/RNTrackPlayer-Bridging-Header.h +7 -0
  99. package/ios/TrackPlayer.swift +1590 -0
  100. package/ios/TrackPlayerCallbacks.swift +121 -0
  101. package/ios/Util/Emitter.swift +46 -0
  102. package/ios/Util/LRUCache.swift +182 -0
  103. package/ios/Util/MetadataAdapter.swift +131 -0
  104. package/ios/Util/NetworkMonitor.swift +68 -0
  105. package/ios/Util/OnceValue.swift +70 -0
  106. package/ios/Util/SVGProcessor.swift +56 -0
  107. package/lib/commonjs/AudioBrowser.js +50 -0
  108. package/lib/commonjs/AudioBrowser.js.map +1 -0
  109. package/lib/commonjs/features/battery.js +154 -0
  110. package/lib/commonjs/features/battery.js.map +1 -0
  111. package/lib/commonjs/features/browser.js +271 -0
  112. package/lib/commonjs/features/browser.js.map +1 -0
  113. package/lib/commonjs/features/equalizer.js +69 -0
  114. package/lib/commonjs/features/equalizer.js.map +1 -0
  115. package/lib/commonjs/features/errors.js +165 -0
  116. package/lib/commonjs/features/errors.js.map +1 -0
  117. package/lib/commonjs/features/favorites.js +101 -0
  118. package/lib/commonjs/features/favorites.js.map +1 -0
  119. package/lib/commonjs/features/index.js +160 -0
  120. package/lib/commonjs/features/index.js.map +1 -0
  121. package/lib/commonjs/features/metadata.js +54 -0
  122. package/lib/commonjs/features/metadata.js.map +1 -0
  123. package/lib/commonjs/features/network.js +40 -0
  124. package/lib/commonjs/features/network.js.map +1 -0
  125. package/lib/commonjs/features/nowPlaying.js +61 -0
  126. package/lib/commonjs/features/nowPlaying.js.map +1 -0
  127. package/lib/commonjs/features/output.js +54 -0
  128. package/lib/commonjs/features/output.js.map +1 -0
  129. package/lib/commonjs/features/playback/controls.js +79 -0
  130. package/lib/commonjs/features/playback/controls.js.map +1 -0
  131. package/lib/commonjs/features/playback/index.js +83 -0
  132. package/lib/commonjs/features/playback/index.js.map +1 -0
  133. package/lib/commonjs/features/playback/playWhenReady.js +55 -0
  134. package/lib/commonjs/features/playback/playWhenReady.js.map +1 -0
  135. package/lib/commonjs/features/playback/playing.js +41 -0
  136. package/lib/commonjs/features/playback/playing.js.map +1 -0
  137. package/lib/commonjs/features/playback/progress.js +104 -0
  138. package/lib/commonjs/features/playback/progress.js.map +1 -0
  139. package/lib/commonjs/features/playback/rate.js +29 -0
  140. package/lib/commonjs/features/playback/rate.js.map +1 -0
  141. package/lib/commonjs/features/playback/state.js +62 -0
  142. package/lib/commonjs/features/playback/state.js.map +1 -0
  143. package/lib/commonjs/features/playback/volume.js +68 -0
  144. package/lib/commonjs/features/playback/volume.js.map +1 -0
  145. package/lib/commonjs/features/player/index.js +28 -0
  146. package/lib/commonjs/features/player/index.js.map +1 -0
  147. package/lib/commonjs/features/player/options.js +182 -0
  148. package/lib/commonjs/features/player/options.js.map +1 -0
  149. package/lib/commonjs/features/player/setup.js +143 -0
  150. package/lib/commonjs/features/player/setup.js.map +1 -0
  151. package/lib/commonjs/features/queue/activeTrack.js +52 -0
  152. package/lib/commonjs/features/queue/activeTrack.js.map +1 -0
  153. package/lib/commonjs/features/queue/index.js +50 -0
  154. package/lib/commonjs/features/queue/index.js.map +1 -0
  155. package/lib/commonjs/features/queue/queue.js +177 -0
  156. package/lib/commonjs/features/queue/queue.js.map +1 -0
  157. package/lib/commonjs/features/queue/repeatMode.js +58 -0
  158. package/lib/commonjs/features/queue/repeatMode.js.map +1 -0
  159. package/lib/commonjs/features/queue/shuffle.js +57 -0
  160. package/lib/commonjs/features/queue/shuffle.js.map +1 -0
  161. package/lib/commonjs/features/rating.js +2 -0
  162. package/lib/commonjs/features/rating.js.map +1 -0
  163. package/lib/commonjs/features/remoteControls.js +286 -0
  164. package/lib/commonjs/features/remoteControls.js.map +1 -0
  165. package/lib/commonjs/features/sleepTimer.js +164 -0
  166. package/lib/commonjs/features/sleepTimer.js.map +1 -0
  167. package/lib/commonjs/index.js +22 -0
  168. package/lib/commonjs/index.js.map +1 -0
  169. package/lib/commonjs/native.js +9 -0
  170. package/lib/commonjs/native.js.map +1 -0
  171. package/lib/commonjs/native.web.js +10 -0
  172. package/lib/commonjs/native.web.js.map +1 -0
  173. package/lib/commonjs/package.json +1 -0
  174. package/lib/commonjs/specs/audio-browser.nitro.js +6 -0
  175. package/lib/commonjs/specs/audio-browser.nitro.js.map +1 -0
  176. package/lib/commonjs/types/browser-native.js +6 -0
  177. package/lib/commonjs/types/browser-native.js.map +1 -0
  178. package/lib/commonjs/types/browser-nodes.js +6 -0
  179. package/lib/commonjs/types/browser-nodes.js.map +1 -0
  180. package/lib/commonjs/types/browser.js +6 -0
  181. package/lib/commonjs/types/browser.js.map +1 -0
  182. package/lib/commonjs/types/index.js +28 -0
  183. package/lib/commonjs/types/index.js.map +1 -0
  184. package/lib/commonjs/types/player.js +2 -0
  185. package/lib/commonjs/types/player.js.map +1 -0
  186. package/lib/commonjs/utils/LazyNativeEmitter.js +58 -0
  187. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -0
  188. package/lib/commonjs/utils/NativeUpdatedValue.js +59 -0
  189. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -0
  190. package/lib/commonjs/utils/resolveAssetSource.js +11 -0
  191. package/lib/commonjs/utils/resolveAssetSource.js.map +1 -0
  192. package/lib/commonjs/utils/useDebug.js +221 -0
  193. package/lib/commonjs/utils/useDebug.js.map +1 -0
  194. package/lib/commonjs/utils/useNativeUpdatedValue.js +44 -0
  195. package/lib/commonjs/utils/useNativeUpdatedValue.js.map +1 -0
  196. package/lib/commonjs/web/NativeAudioBrowser.js +668 -0
  197. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -0
  198. package/lib/commonjs/web/SimpleRouter.js +144 -0
  199. package/lib/commonjs/web/SimpleRouter.js.map +1 -0
  200. package/lib/commonjs/web/TrackPlayer/Event.js +19 -0
  201. package/lib/commonjs/web/TrackPlayer/Event.js.map +1 -0
  202. package/lib/commonjs/web/TrackPlayer/Player.js +276 -0
  203. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -0
  204. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +284 -0
  205. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  206. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +12 -0
  207. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -0
  208. package/lib/commonjs/web/TrackPlayer/SetupNotCalledError.js +13 -0
  209. package/lib/commonjs/web/TrackPlayer/SetupNotCalledError.js.map +1 -0
  210. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +75 -0
  211. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -0
  212. package/lib/commonjs/web/TrackPlayer/State.js +18 -0
  213. package/lib/commonjs/web/TrackPlayer/State.js.map +1 -0
  214. package/lib/commonjs/web/TrackPlayer/index.js +52 -0
  215. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -0
  216. package/lib/commonjs/web/browser/BrowserManager.js +594 -0
  217. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -0
  218. package/lib/commonjs/web/browser/FavoriteManager.js +80 -0
  219. package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -0
  220. package/lib/commonjs/web/browser/NavigationErrorManager.js +106 -0
  221. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -0
  222. package/lib/commonjs/web/browser/SearchManager.js +80 -0
  223. package/lib/commonjs/web/browser/SearchManager.js.map +1 -0
  224. package/lib/commonjs/web/http/HttpClient.js +81 -0
  225. package/lib/commonjs/web/http/HttpClient.js.map +1 -0
  226. package/lib/commonjs/web/http/RequestConfigBuilder.js +294 -0
  227. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -0
  228. package/lib/commonjs/web/player/NowPlayingManager.js +70 -0
  229. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -0
  230. package/lib/commonjs/web/player/OptionsManager.js +88 -0
  231. package/lib/commonjs/web/player/OptionsManager.js.map +1 -0
  232. package/lib/commonjs/web/util/BrowserPathHelper.js +138 -0
  233. package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -0
  234. package/lib/commonjs/web/util/shuffle.js +21 -0
  235. package/lib/commonjs/web/util/shuffle.js.map +1 -0
  236. package/lib/module/AudioBrowser.js +7 -0
  237. package/lib/module/AudioBrowser.js.map +1 -0
  238. package/lib/module/features/battery.js +144 -0
  239. package/lib/module/features/battery.js.map +1 -0
  240. package/lib/module/features/browser.js +257 -0
  241. package/lib/module/features/browser.js.map +1 -0
  242. package/lib/module/features/equalizer.js +60 -0
  243. package/lib/module/features/equalizer.js.map +1 -0
  244. package/lib/module/features/errors.js +156 -0
  245. package/lib/module/features/errors.js.map +1 -0
  246. package/lib/module/features/favorites.js +95 -0
  247. package/lib/module/features/favorites.js.map +1 -0
  248. package/lib/module/features/index.js +26 -0
  249. package/lib/module/features/index.js.map +1 -0
  250. package/lib/module/features/metadata.js +51 -0
  251. package/lib/module/features/metadata.js.map +1 -0
  252. package/lib/module/features/network.js +35 -0
  253. package/lib/module/features/network.js.map +1 -0
  254. package/lib/module/features/nowPlaying.js +54 -0
  255. package/lib/module/features/nowPlaying.js.map +1 -0
  256. package/lib/module/features/output.js +47 -0
  257. package/lib/module/features/output.js.map +1 -0
  258. package/lib/module/features/playback/controls.js +69 -0
  259. package/lib/module/features/playback/controls.js.map +1 -0
  260. package/lib/module/features/playback/index.js +10 -0
  261. package/lib/module/features/playback/index.js.map +1 -0
  262. package/lib/module/features/playback/playWhenReady.js +49 -0
  263. package/lib/module/features/playback/playWhenReady.js.map +1 -0
  264. package/lib/module/features/playback/playing.js +36 -0
  265. package/lib/module/features/playback/playing.js.map +1 -0
  266. package/lib/module/features/playback/progress.js +98 -0
  267. package/lib/module/features/playback/progress.js.map +1 -0
  268. package/lib/module/features/playback/rate.js +25 -0
  269. package/lib/module/features/playback/rate.js.map +1 -0
  270. package/lib/module/features/playback/state.js +57 -0
  271. package/lib/module/features/playback/state.js.map +1 -0
  272. package/lib/module/features/playback/volume.js +60 -0
  273. package/lib/module/features/playback/volume.js.map +1 -0
  274. package/lib/module/features/player/index.js +5 -0
  275. package/lib/module/features/player/index.js.map +1 -0
  276. package/lib/module/features/player/options.js +176 -0
  277. package/lib/module/features/player/options.js.map +1 -0
  278. package/lib/module/features/player/setup.js +140 -0
  279. package/lib/module/features/player/setup.js.map +1 -0
  280. package/lib/module/features/queue/activeTrack.js +46 -0
  281. package/lib/module/features/queue/activeTrack.js.map +1 -0
  282. package/lib/module/features/queue/index.js +7 -0
  283. package/lib/module/features/queue/index.js.map +1 -0
  284. package/lib/module/features/queue/queue.js +162 -0
  285. package/lib/module/features/queue/queue.js.map +1 -0
  286. package/lib/module/features/queue/repeatMode.js +52 -0
  287. package/lib/module/features/queue/repeatMode.js.map +1 -0
  288. package/lib/module/features/queue/shuffle.js +50 -0
  289. package/lib/module/features/queue/shuffle.js.map +1 -0
  290. package/lib/module/features/rating.js +2 -0
  291. package/lib/module/features/rating.js.map +1 -0
  292. package/lib/module/features/remoteControls.js +275 -0
  293. package/lib/module/features/remoteControls.js.map +1 -0
  294. package/lib/module/features/sleepTimer.js +155 -0
  295. package/lib/module/features/sleepTimer.js.map +1 -0
  296. package/lib/module/index.js +6 -0
  297. package/lib/module/index.js.map +1 -0
  298. package/lib/module/native.js +5 -0
  299. package/lib/module/native.js.map +1 -0
  300. package/lib/module/native.web.js +7 -0
  301. package/lib/module/native.web.js.map +1 -0
  302. package/lib/module/package.json +1 -0
  303. package/lib/module/specs/audio-browser.nitro.js +4 -0
  304. package/lib/module/specs/audio-browser.nitro.js.map +1 -0
  305. package/lib/module/types/browser-native.js +4 -0
  306. package/lib/module/types/browser-native.js.map +1 -0
  307. package/lib/module/types/browser-nodes.js +4 -0
  308. package/lib/module/types/browser-nodes.js.map +1 -0
  309. package/lib/module/types/browser.js +4 -0
  310. package/lib/module/types/browser.js.map +1 -0
  311. package/lib/module/types/index.js +5 -0
  312. package/lib/module/types/index.js.map +1 -0
  313. package/lib/module/types/player.js +2 -0
  314. package/lib/module/types/player.js.map +1 -0
  315. package/lib/module/utils/LazyNativeEmitter.js +53 -0
  316. package/lib/module/utils/LazyNativeEmitter.js.map +1 -0
  317. package/lib/module/utils/NativeUpdatedValue.js +54 -0
  318. package/lib/module/utils/NativeUpdatedValue.js.map +1 -0
  319. package/lib/module/utils/resolveAssetSource.js +7 -0
  320. package/lib/module/utils/resolveAssetSource.js.map +1 -0
  321. package/lib/module/utils/useDebug.js +218 -0
  322. package/lib/module/utils/useDebug.js.map +1 -0
  323. package/lib/module/utils/useNativeUpdatedValue.js +40 -0
  324. package/lib/module/utils/useNativeUpdatedValue.js.map +1 -0
  325. package/lib/module/web/NativeAudioBrowser.js +664 -0
  326. package/lib/module/web/NativeAudioBrowser.js.map +1 -0
  327. package/lib/module/web/SimpleRouter.js +139 -0
  328. package/lib/module/web/SimpleRouter.js.map +1 -0
  329. package/lib/module/web/TrackPlayer/Event.js +15 -0
  330. package/lib/module/web/TrackPlayer/Event.js.map +1 -0
  331. package/lib/module/web/TrackPlayer/Player.js +271 -0
  332. package/lib/module/web/TrackPlayer/Player.js.map +1 -0
  333. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +279 -0
  334. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  335. package/lib/module/web/TrackPlayer/RepeatMode.js +8 -0
  336. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -0
  337. package/lib/module/web/TrackPlayer/SetupNotCalledError.js +8 -0
  338. package/lib/module/web/TrackPlayer/SetupNotCalledError.js.map +1 -0
  339. package/lib/module/web/TrackPlayer/SleepTimer.js +70 -0
  340. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -0
  341. package/lib/module/web/TrackPlayer/State.js +14 -0
  342. package/lib/module/web/TrackPlayer/State.js.map +1 -0
  343. package/lib/module/web/TrackPlayer/index.js +7 -0
  344. package/lib/module/web/TrackPlayer/index.js.map +1 -0
  345. package/lib/module/web/browser/BrowserManager.js +590 -0
  346. package/lib/module/web/browser/BrowserManager.js.map +1 -0
  347. package/lib/module/web/browser/FavoriteManager.js +75 -0
  348. package/lib/module/web/browser/FavoriteManager.js.map +1 -0
  349. package/lib/module/web/browser/NavigationErrorManager.js +101 -0
  350. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -0
  351. package/lib/module/web/browser/SearchManager.js +76 -0
  352. package/lib/module/web/browser/SearchManager.js.map +1 -0
  353. package/lib/module/web/http/HttpClient.js +76 -0
  354. package/lib/module/web/http/HttpClient.js.map +1 -0
  355. package/lib/module/web/http/RequestConfigBuilder.js +291 -0
  356. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -0
  357. package/lib/module/web/player/NowPlayingManager.js +65 -0
  358. package/lib/module/web/player/NowPlayingManager.js.map +1 -0
  359. package/lib/module/web/player/OptionsManager.js +83 -0
  360. package/lib/module/web/player/OptionsManager.js.map +1 -0
  361. package/lib/module/web/util/BrowserPathHelper.js +134 -0
  362. package/lib/module/web/util/BrowserPathHelper.js.map +1 -0
  363. package/lib/module/web/util/shuffle.js +17 -0
  364. package/lib/module/web/util/shuffle.js.map +1 -0
  365. package/lib/typescript/src/AudioBrowser.d.ts +5 -0
  366. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -0
  367. package/lib/typescript/src/features/battery.d.ts +112 -0
  368. package/lib/typescript/src/features/battery.d.ts.map +1 -0
  369. package/lib/typescript/src/features/browser.d.ts +68 -0
  370. package/lib/typescript/src/features/browser.d.ts.map +1 -0
  371. package/lib/typescript/src/features/equalizer.d.ts +35 -0
  372. package/lib/typescript/src/features/equalizer.d.ts.map +1 -0
  373. package/lib/typescript/src/features/errors.d.ts +136 -0
  374. package/lib/typescript/src/features/errors.d.ts.map +1 -0
  375. package/lib/typescript/src/features/favorites.d.ts +84 -0
  376. package/lib/typescript/src/features/favorites.d.ts.map +1 -0
  377. package/lib/typescript/src/features/index.d.ts +23 -0
  378. package/lib/typescript/src/features/index.d.ts.map +1 -0
  379. package/lib/typescript/src/features/metadata.d.ts +103 -0
  380. package/lib/typescript/src/features/metadata.d.ts.map +1 -0
  381. package/lib/typescript/src/features/network.d.ts +18 -0
  382. package/lib/typescript/src/features/network.d.ts.map +1 -0
  383. package/lib/typescript/src/features/nowPlaying.d.ts +36 -0
  384. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -0
  385. package/lib/typescript/src/features/output.d.ts +28 -0
  386. package/lib/typescript/src/features/output.d.ts.map +1 -0
  387. package/lib/typescript/src/features/playback/controls.d.ts +40 -0
  388. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -0
  389. package/lib/typescript/src/features/playback/index.d.ts +8 -0
  390. package/lib/typescript/src/features/playback/index.d.ts.map +1 -0
  391. package/lib/typescript/src/features/playback/playWhenReady.d.ts +30 -0
  392. package/lib/typescript/src/features/playback/playWhenReady.d.ts.map +1 -0
  393. package/lib/typescript/src/features/playback/playing.d.ts +21 -0
  394. package/lib/typescript/src/features/playback/playing.d.ts.map +1 -0
  395. package/lib/typescript/src/features/playback/progress.d.ts +51 -0
  396. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -0
  397. package/lib/typescript/src/features/playback/rate.d.ts +12 -0
  398. package/lib/typescript/src/features/playback/rate.d.ts.map +1 -0
  399. package/lib/typescript/src/features/playback/state.d.ts +43 -0
  400. package/lib/typescript/src/features/playback/state.d.ts.map +1 -0
  401. package/lib/typescript/src/features/playback/volume.d.ts +32 -0
  402. package/lib/typescript/src/features/playback/volume.d.ts.map +1 -0
  403. package/lib/typescript/src/features/player/index.d.ts +3 -0
  404. package/lib/typescript/src/features/player/index.d.ts.map +1 -0
  405. package/lib/typescript/src/features/player/options.d.ts +413 -0
  406. package/lib/typescript/src/features/player/options.d.ts.map +1 -0
  407. package/lib/typescript/src/features/player/setup.d.ts +471 -0
  408. package/lib/typescript/src/features/player/setup.d.ts.map +1 -0
  409. package/lib/typescript/src/features/queue/activeTrack.d.ts +38 -0
  410. package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -0
  411. package/lib/typescript/src/features/queue/index.d.ts +5 -0
  412. package/lib/typescript/src/features/queue/index.d.ts.map +1 -0
  413. package/lib/typescript/src/features/queue/queue.d.ts +111 -0
  414. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -0
  415. package/lib/typescript/src/features/queue/repeatMode.d.ts +34 -0
  416. package/lib/typescript/src/features/queue/repeatMode.d.ts.map +1 -0
  417. package/lib/typescript/src/features/queue/shuffle.d.ts +27 -0
  418. package/lib/typescript/src/features/queue/shuffle.d.ts.map +1 -0
  419. package/lib/typescript/src/features/rating.d.ts +14 -0
  420. package/lib/typescript/src/features/rating.d.ts.map +1 -0
  421. package/lib/typescript/src/features/remoteControls.d.ts +164 -0
  422. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -0
  423. package/lib/typescript/src/features/sleepTimer.d.ts +80 -0
  424. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -0
  425. package/lib/typescript/src/index.d.ts +4 -0
  426. package/lib/typescript/src/index.d.ts.map +1 -0
  427. package/lib/typescript/src/native.d.ts +3 -0
  428. package/lib/typescript/src/native.d.ts.map +1 -0
  429. package/lib/typescript/src/native.web.d.ts +3 -0
  430. package/lib/typescript/src/native.web.d.ts.map +1 -0
  431. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +242 -0
  432. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -0
  433. package/lib/typescript/src/types/browser-native.d.ts +39 -0
  434. package/lib/typescript/src/types/browser-native.d.ts.map +1 -0
  435. package/lib/typescript/src/types/browser-nodes.d.ts +153 -0
  436. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -0
  437. package/lib/typescript/src/types/browser.d.ts +710 -0
  438. package/lib/typescript/src/types/browser.d.ts.map +1 -0
  439. package/lib/typescript/src/types/index.d.ts +3 -0
  440. package/lib/typescript/src/types/index.d.ts.map +1 -0
  441. package/lib/typescript/src/types/player.d.ts +64 -0
  442. package/lib/typescript/src/types/player.d.ts.map +1 -0
  443. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +35 -0
  444. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -0
  445. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +39 -0
  446. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -0
  447. package/lib/typescript/src/utils/resolveAssetSource.d.ts +4 -0
  448. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -0
  449. package/lib/typescript/src/utils/useDebug.d.ts +65 -0
  450. package/lib/typescript/src/utils/useDebug.d.ts.map +1 -0
  451. package/lib/typescript/src/utils/useNativeUpdatedValue.d.ts +14 -0
  452. package/lib/typescript/src/utils/useNativeUpdatedValue.d.ts.map +1 -0
  453. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +176 -0
  454. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -0
  455. package/lib/typescript/src/web/SimpleRouter.d.ts +40 -0
  456. package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -0
  457. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +11 -0
  458. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +1 -0
  459. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +71 -0
  460. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +1 -0
  461. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +39 -0
  462. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +1 -0
  463. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +6 -0
  464. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +1 -0
  465. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +4 -0
  466. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +1 -0
  467. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +34 -0
  468. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +1 -0
  469. package/lib/typescript/src/web/TrackPlayer/State.d.ts +13 -0
  470. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +1 -0
  471. package/lib/typescript/src/web/TrackPlayer/index.d.ts +5 -0
  472. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +1 -0
  473. package/lib/typescript/src/web/browser/BrowserManager.d.ts +154 -0
  474. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +1 -0
  475. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +42 -0
  476. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +1 -0
  477. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +40 -0
  478. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +1 -0
  479. package/lib/typescript/src/web/browser/SearchManager.d.ts +22 -0
  480. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +1 -0
  481. package/lib/typescript/src/web/http/HttpClient.d.ts +25 -0
  482. package/lib/typescript/src/web/http/HttpClient.d.ts.map +1 -0
  483. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +98 -0
  484. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +1 -0
  485. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +34 -0
  486. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +1 -0
  487. package/lib/typescript/src/web/player/OptionsManager.d.ts +32 -0
  488. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +1 -0
  489. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +69 -0
  490. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +1 -0
  491. package/lib/typescript/src/web/util/shuffle.d.ts +8 -0
  492. package/lib/typescript/src/web/util/shuffle.d.ts.map +1 -0
  493. package/nitro.json +24 -0
  494. package/nitrogen/generated/.gitattributes +1 -0
  495. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +88 -0
  496. package/nitrogen/generated/android/AudioBrowser+autolinking.gradle +27 -0
  497. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +124 -0
  498. package/nitrogen/generated/android/AudioBrowserOnLoad.hpp +25 -0
  499. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +68 -0
  500. package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +61 -0
  501. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +86 -0
  502. package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +62 -0
  503. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +86 -0
  504. package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +62 -0
  505. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +163 -0
  506. package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +62 -0
  507. package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +58 -0
  508. package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +57 -0
  509. package/nitrogen/generated/android/c++/JBrowseError.hpp +57 -0
  510. package/nitrogen/generated/android/c++/JBrowseResult.cpp +26 -0
  511. package/nitrogen/generated/android/c++/JBrowseResult.hpp +83 -0
  512. package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +76 -0
  513. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +65 -0
  514. package/nitrogen/generated/android/c++/JChapterMetadata.hpp +70 -0
  515. package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +125 -0
  516. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +71 -0
  517. package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +72 -0
  518. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +61 -0
  519. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +111 -0
  520. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +134 -0
  521. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +143 -0
  522. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +136 -0
  523. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +143 -0
  524. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +157 -0
  525. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  526. package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +79 -0
  527. package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +77 -0
  528. package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +80 -0
  529. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +88 -0
  530. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +80 -0
  531. package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +83 -0
  532. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +89 -0
  533. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +98 -0
  534. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +83 -0
  535. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +88 -0
  536. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +81 -0
  537. package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +77 -0
  538. package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +77 -0
  539. package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +77 -0
  540. package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +77 -0
  541. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +77 -0
  542. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +77 -0
  543. package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +79 -0
  544. package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +78 -0
  545. package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +77 -0
  546. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +87 -0
  547. package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +77 -0
  548. package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +79 -0
  549. package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +79 -0
  550. package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +79 -0
  551. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
  552. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +75 -0
  553. package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +79 -0
  554. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +89 -0
  555. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +84 -0
  556. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
  557. package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +98 -0
  558. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +105 -0
  559. package/nitrogen/generated/android/c++/JHeartRating.hpp +57 -0
  560. package/nitrogen/generated/android/c++/JHttpMethod.hpp +74 -0
  561. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +1811 -0
  562. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +250 -0
  563. package/nitrogen/generated/android/c++/JIOSCategory.hpp +71 -0
  564. package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +80 -0
  565. package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +74 -0
  566. package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +62 -0
  567. package/nitrogen/generated/android/c++/JImageContext.hpp +61 -0
  568. package/nitrogen/generated/android/c++/JImageQueryParams.hpp +62 -0
  569. package/nitrogen/generated/android/c++/JImageSource.hpp +86 -0
  570. package/nitrogen/generated/android/c++/JIosOutput.hpp +67 -0
  571. package/nitrogen/generated/android/c++/JIosOutputType.hpp +86 -0
  572. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +153 -0
  573. package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +69 -0
  574. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +196 -0
  575. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +147 -0
  576. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +105 -0
  577. package/nitrogen/generated/android/c++/JNavigationError.hpp +72 -0
  578. package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +62 -0
  579. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +68 -0
  580. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +86 -0
  581. package/nitrogen/generated/android/c++/JNotificationButton.hpp +68 -0
  582. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +94 -0
  583. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +104 -0
  584. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +62 -0
  585. package/nitrogen/generated/android/c++/JOptions.hpp +97 -0
  586. package/nitrogen/generated/android/c++/JPartialAndroidSetupPlayerOptions.hpp +104 -0
  587. package/nitrogen/generated/android/c++/JPartialIOSSetupPlayerOptions.hpp +100 -0
  588. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +96 -0
  589. package/nitrogen/generated/android/c++/JPercentageRating.hpp +57 -0
  590. package/nitrogen/generated/android/c++/JPlayback.hpp +66 -0
  591. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +83 -0
  592. package/nitrogen/generated/android/c++/JPlaybackError.hpp +61 -0
  593. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +60 -0
  594. package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +57 -0
  595. package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +69 -0
  596. package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +61 -0
  597. package/nitrogen/generated/android/c++/JPlaybackState.hpp +80 -0
  598. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +101 -0
  599. package/nitrogen/generated/android/c++/JPlayingState.hpp +61 -0
  600. package/nitrogen/generated/android/c++/JProgress.hpp +65 -0
  601. package/nitrogen/generated/android/c++/JRatingType.hpp +74 -0
  602. package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +57 -0
  603. package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +57 -0
  604. package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +62 -0
  605. package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +57 -0
  606. package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +57 -0
  607. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +66 -0
  608. package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +57 -0
  609. package/nitrogen/generated/android/c++/JRepeatMode.hpp +62 -0
  610. package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +58 -0
  611. package/nitrogen/generated/android/c++/JRequestConfig.hpp +115 -0
  612. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +154 -0
  613. package/nitrogen/generated/android/c++/JRetryConfig.hpp +61 -0
  614. package/nitrogen/generated/android/c++/JSearchMode.hpp +71 -0
  615. package/nitrogen/generated/android/c++/JSearchParams.hpp +84 -0
  616. package/nitrogen/generated/android/c++/JSleepTimer.cpp +30 -0
  617. package/nitrogen/generated/android/c++/JSleepTimer.hpp +88 -0
  618. package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +57 -0
  619. package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +57 -0
  620. package/nitrogen/generated/android/c++/JStarRating.hpp +57 -0
  621. package/nitrogen/generated/android/c++/JThumbsRating.hpp +57 -0
  622. package/nitrogen/generated/android/c++/JTimedMetadata.hpp +74 -0
  623. package/nitrogen/generated/android/c++/JTrack.hpp +129 -0
  624. package/nitrogen/generated/android/c++/JTrackMetadata.hpp +118 -0
  625. package/nitrogen/generated/android/c++/JTrackStyle.hpp +59 -0
  626. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +134 -0
  627. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +105 -0
  628. package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.cpp +26 -0
  629. package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +70 -0
  630. package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.cpp +26 -0
  631. package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +70 -0
  632. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +34 -0
  633. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +105 -0
  634. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
  635. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
  636. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +26 -0
  637. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +75 -0
  638. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +24 -0
  639. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +41 -0
  640. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +50 -0
  641. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidPlayerWakeMode.kt +22 -0
  642. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +50 -0
  643. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AppKilledPlaybackBehavior.kt +22 -0
  644. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +72 -0
  645. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AudioBrowserOnLoad.kt +35 -0
  646. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatus.kt +22 -0
  647. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +38 -0
  648. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +38 -0
  649. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +38 -0
  650. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +59 -0
  651. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +41 -0
  652. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +23 -0
  653. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ChapterMetadata.kt +47 -0
  654. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +59 -0
  655. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +41 -0
  656. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +44 -0
  657. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +41 -0
  658. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +80 -0
  659. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +80 -0
  660. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +80 -0
  661. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.kt +80 -0
  662. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt +80 -0
  663. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +80 -0
  664. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +80 -0
  665. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +80 -0
  666. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +80 -0
  667. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +80 -0
  668. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +80 -0
  669. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_IosOutput.kt +80 -0
  670. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +80 -0
  671. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +80 -0
  672. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +80 -0
  673. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +80 -0
  674. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +80 -0
  675. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +80 -0
  676. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +80 -0
  677. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +80 -0
  678. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +80 -0
  679. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +80 -0
  680. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +80 -0
  681. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +80 -0
  682. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +80 -0
  683. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +80 -0
  684. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +80 -0
  685. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSetRatingEvent.kt +80 -0
  686. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +80 -0
  687. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +80 -0
  688. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +80 -0
  689. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +80 -0
  690. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +80 -0
  691. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +80 -0
  692. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +80 -0
  693. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +80 -0
  694. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +80 -0
  695. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +80 -0
  696. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +80 -0
  697. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +80 -0
  698. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HeartRating.kt +38 -0
  699. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HttpMethod.kt +26 -0
  700. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1137 -0
  701. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategory.kt +25 -0
  702. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryMode.kt +28 -0
  703. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryOptions.kt +26 -0
  704. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryPolicy.kt +22 -0
  705. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +41 -0
  706. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +41 -0
  707. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +47 -0
  708. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutput.kt +44 -0
  709. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +30 -0
  710. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +69 -0
  711. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +41 -0
  712. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +69 -0
  713. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +63 -0
  714. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +53 -0
  715. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +47 -0
  716. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +38 -0
  717. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +24 -0
  718. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +50 -0
  719. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +24 -0
  720. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +50 -0
  721. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +65 -0
  722. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +41 -0
  723. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +53 -0
  724. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialAndroidSetupPlayerOptions.kt +65 -0
  725. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialIOSSetupPlayerOptions.kt +50 -0
  726. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +47 -0
  727. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PercentageRating.kt +38 -0
  728. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +41 -0
  729. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +50 -0
  730. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +41 -0
  731. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +38 -0
  732. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +38 -0
  733. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +47 -0
  734. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +41 -0
  735. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +28 -0
  736. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +71 -0
  737. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +41 -0
  738. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +44 -0
  739. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RatingType.kt +26 -0
  740. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +38 -0
  741. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +38 -0
  742. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +41 -0
  743. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +38 -0
  744. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +38 -0
  745. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSetRatingEvent.kt +38 -0
  746. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +38 -0
  747. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatMode.kt +22 -0
  748. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +38 -0
  749. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +59 -0
  750. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +89 -0
  751. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +41 -0
  752. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +25 -0
  753. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +56 -0
  754. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +72 -0
  755. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +38 -0
  756. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +38 -0
  757. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StarRating.kt +38 -0
  758. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ThumbsRating.kt +38 -0
  759. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +50 -0
  760. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +86 -0
  761. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +83 -0
  762. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +21 -0
  763. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +66 -0
  764. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +53 -0
  765. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +59 -0
  766. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +59 -0
  767. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +85 -0
  768. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +59 -0
  769. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout.kt +59 -0
  770. package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +60 -0
  771. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +407 -0
  772. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +2822 -0
  773. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +300 -0
  774. package/nitrogen/generated/ios/AudioBrowserAutolinking.mm +33 -0
  775. package/nitrogen/generated/ios/AudioBrowserAutolinking.swift +25 -0
  776. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.cpp +11 -0
  777. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +1190 -0
  778. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +52 -0
  779. package/nitrogen/generated/ios/swift/AndroidAudioOffloadSettings.swift +85 -0
  780. package/nitrogen/generated/ios/swift/AndroidOptions.swift +125 -0
  781. package/nitrogen/generated/ios/swift/AndroidPlayerWakeMode.swift +44 -0
  782. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +187 -0
  783. package/nitrogen/generated/ios/swift/AppKilledPlaybackBehavior.swift +44 -0
  784. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +445 -0
  785. package/nitrogen/generated/ios/swift/BatteryOptimizationStatus.swift +44 -0
  786. package/nitrogen/generated/ios/swift/BatteryOptimizationStatusChangedEvent.swift +36 -0
  787. package/nitrogen/generated/ios/swift/BatteryWarningPendingChangedEvent.swift +36 -0
  788. package/nitrogen/generated/ios/swift/BrowseError.swift +36 -0
  789. package/nitrogen/generated/ios/swift/BrowseResult.swift +18 -0
  790. package/nitrogen/generated/ios/swift/BrowserSourceCallbackParam.swift +86 -0
  791. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +48 -0
  792. package/nitrogen/generated/ios/swift/ChapterMetadata.swift +107 -0
  793. package/nitrogen/generated/ios/swift/EqualizerSettings.swift +168 -0
  794. package/nitrogen/generated/ios/swift/FavoriteChangedEvent.swift +47 -0
  795. package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +58 -0
  796. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +47 -0
  797. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.swift +61 -0
  798. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.swift +62 -0
  799. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +77 -0
  800. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.swift +62 -0
  801. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +69 -0
  802. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.swift +68 -0
  803. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  804. package/nitrogen/generated/ios/swift/Func_void_BatteryOptimizationStatusChangedEvent.swift +47 -0
  805. package/nitrogen/generated/ios/swift/Func_void_BatteryWarningPendingChangedEvent.swift +47 -0
  806. package/nitrogen/generated/ios/swift/Func_void_EqualizerSettings.swift +47 -0
  807. package/nitrogen/generated/ios/swift/Func_void_FavoriteChangedEvent.swift +47 -0
  808. package/nitrogen/generated/ios/swift/Func_void_IosOutput.swift +47 -0
  809. package/nitrogen/generated/ios/swift/Func_void_NavigationErrorEvent.swift +47 -0
  810. package/nitrogen/generated/ios/swift/Func_void_NowPlayingMetadata.swift +47 -0
  811. package/nitrogen/generated/ios/swift/Func_void_Options.swift +47 -0
  812. package/nitrogen/generated/ios/swift/Func_void_Playback.swift +47 -0
  813. package/nitrogen/generated/ios/swift/Func_void_PlaybackActiveTrackChangedEvent.swift +47 -0
  814. package/nitrogen/generated/ios/swift/Func_void_PlaybackErrorEvent.swift +47 -0
  815. package/nitrogen/generated/ios/swift/Func_void_PlaybackPlayWhenReadyChangedEvent.swift +47 -0
  816. package/nitrogen/generated/ios/swift/Func_void_PlaybackProgressUpdatedEvent.swift +47 -0
  817. package/nitrogen/generated/ios/swift/Func_void_PlaybackQueueEndedEvent.swift +47 -0
  818. package/nitrogen/generated/ios/swift/Func_void_PlayingState.swift +47 -0
  819. package/nitrogen/generated/ios/swift/Func_void_RemoteJumpBackwardEvent.swift +47 -0
  820. package/nitrogen/generated/ios/swift/Func_void_RemoteJumpForwardEvent.swift +47 -0
  821. package/nitrogen/generated/ios/swift/Func_void_RemotePlayIdEvent.swift +47 -0
  822. package/nitrogen/generated/ios/swift/Func_void_RemotePlaySearchEvent.swift +47 -0
  823. package/nitrogen/generated/ios/swift/Func_void_RemoteSeekEvent.swift +47 -0
  824. package/nitrogen/generated/ios/swift/Func_void_RemoteSetRatingEvent.swift +47 -0
  825. package/nitrogen/generated/ios/swift/Func_void_RemoteSkipEvent.swift +47 -0
  826. package/nitrogen/generated/ios/swift/Func_void_RepeatModeChangedEvent.swift +47 -0
  827. package/nitrogen/generated/ios/swift/Func_void_RequestConfig.swift +47 -0
  828. package/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift +47 -0
  829. package/nitrogen/generated/ios/swift/Func_void_TrackMetadata.swift +47 -0
  830. package/nitrogen/generated/ios/swift/Func_void_bool.swift +47 -0
  831. package/nitrogen/generated/ios/swift/Func_void_double.swift +47 -0
  832. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  833. package/nitrogen/generated/ios/swift/Func_void_std__optional_FormattedNavigationError_.swift +47 -0
  834. package/nitrogen/generated/ios/swift/Func_void_std__optional_ResolvedTrack_.swift +47 -0
  835. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.swift +69 -0
  836. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_RequestConfig__.swift +67 -0
  837. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift +67 -0
  838. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_Track___.swift +67 -0
  839. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
  840. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError_.swift +59 -0
  841. package/nitrogen/generated/ios/swift/Func_void_std__vector_ChapterMetadata_.swift +47 -0
  842. package/nitrogen/generated/ios/swift/Func_void_std__vector_Track_.swift +47 -0
  843. package/nitrogen/generated/ios/swift/HeartRating.swift +36 -0
  844. package/nitrogen/generated/ios/swift/HttpMethod.swift +60 -0
  845. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +181 -0
  846. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2352 -0
  847. package/nitrogen/generated/ios/swift/IOSCategory.swift +56 -0
  848. package/nitrogen/generated/ios/swift/IOSCategoryMode.swift +68 -0
  849. package/nitrogen/generated/ios/swift/IOSCategoryOptions.swift +60 -0
  850. package/nitrogen/generated/ios/swift/IOSCategoryPolicy.swift +44 -0
  851. package/nitrogen/generated/ios/swift/ImageContext.swift +71 -0
  852. package/nitrogen/generated/ios/swift/ImageQueryParams.swift +85 -0
  853. package/nitrogen/generated/ios/swift/ImageSource.swift +139 -0
  854. package/nitrogen/generated/ios/swift/IosOutput.swift +58 -0
  855. package/nitrogen/generated/ios/swift/IosOutputType.swift +76 -0
  856. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +434 -0
  857. package/nitrogen/generated/ios/swift/MediaTransformParams.swift +59 -0
  858. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +360 -0
  859. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +275 -0
  860. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +215 -0
  861. package/nitrogen/generated/ios/swift/NavigationError.swift +100 -0
  862. package/nitrogen/generated/ios/swift/NavigationErrorEvent.swift +48 -0
  863. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +52 -0
  864. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +187 -0
  865. package/nitrogen/generated/ios/swift/NotificationButton.swift +52 -0
  866. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +159 -0
  867. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +351 -0
  868. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +85 -0
  869. package/nitrogen/generated/ios/swift/Options.swift +148 -0
  870. package/nitrogen/generated/ios/swift/PartialAndroidSetupPlayerOptions.swift +328 -0
  871. package/nitrogen/generated/ios/swift/PartialIOSSetupPlayerOptions.swift +159 -0
  872. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +157 -0
  873. package/nitrogen/generated/ios/swift/PercentageRating.swift +36 -0
  874. package/nitrogen/generated/ios/swift/Playback.swift +59 -0
  875. package/nitrogen/generated/ios/swift/PlaybackActiveTrackChangedEvent.swift +128 -0
  876. package/nitrogen/generated/ios/swift/PlaybackError.swift +47 -0
  877. package/nitrogen/generated/ios/swift/PlaybackErrorEvent.swift +48 -0
  878. package/nitrogen/generated/ios/swift/PlaybackPlayWhenReadyChangedEvent.swift +36 -0
  879. package/nitrogen/generated/ios/swift/PlaybackProgressUpdatedEvent.swift +69 -0
  880. package/nitrogen/generated/ios/swift/PlaybackQueueEndedEvent.swift +47 -0
  881. package/nitrogen/generated/ios/swift/PlaybackState.swift +68 -0
  882. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +385 -0
  883. package/nitrogen/generated/ios/swift/PlayingState.swift +47 -0
  884. package/nitrogen/generated/ios/swift/Progress.swift +58 -0
  885. package/nitrogen/generated/ios/swift/RatingType.swift +60 -0
  886. package/nitrogen/generated/ios/swift/RemoteJumpBackwardEvent.swift +36 -0
  887. package/nitrogen/generated/ios/swift/RemoteJumpForwardEvent.swift +36 -0
  888. package/nitrogen/generated/ios/swift/RemotePlayIdEvent.swift +59 -0
  889. package/nitrogen/generated/ios/swift/RemotePlaySearchEvent.swift +36 -0
  890. package/nitrogen/generated/ios/swift/RemoteSeekEvent.swift +36 -0
  891. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +76 -0
  892. package/nitrogen/generated/ios/swift/RemoteSkipEvent.swift +36 -0
  893. package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
  894. package/nitrogen/generated/ios/swift/RepeatModeChangedEvent.swift +36 -0
  895. package/nitrogen/generated/ios/swift/RequestConfig.swift +298 -0
  896. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +511 -0
  897. package/nitrogen/generated/ios/swift/RetryConfig.swift +59 -0
  898. package/nitrogen/generated/ios/swift/SearchMode.swift +56 -0
  899. package/nitrogen/generated/ios/swift/SearchParams.swift +209 -0
  900. package/nitrogen/generated/ios/swift/SleepTimer.swift +19 -0
  901. package/nitrogen/generated/ios/swift/SleepTimerEndOfTrack.swift +36 -0
  902. package/nitrogen/generated/ios/swift/SleepTimerTime.swift +36 -0
  903. package/nitrogen/generated/ios/swift/StarRating.swift +36 -0
  904. package/nitrogen/generated/ios/swift/ThumbsRating.swift +36 -0
  905. package/nitrogen/generated/ios/swift/TimedMetadata.swift +175 -0
  906. package/nitrogen/generated/ios/swift/Track.swift +488 -0
  907. package/nitrogen/generated/ios/swift/TrackMetadata.swift +505 -0
  908. package/nitrogen/generated/ios/swift/TrackStyle.swift +40 -0
  909. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +372 -0
  910. package/nitrogen/generated/ios/swift/UpdateOptions.swift +215 -0
  911. package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +18 -0
  912. package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +18 -0
  913. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +20 -0
  914. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +18 -0
  915. package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +18 -0
  916. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +88 -0
  917. package/nitrogen/generated/shared/c++/AndroidAudioOffloadSettings.hpp +79 -0
  918. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +101 -0
  919. package/nitrogen/generated/shared/c++/AndroidPlayerWakeMode.hpp +80 -0
  920. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +101 -0
  921. package/nitrogen/generated/shared/c++/AppKilledPlaybackBehavior.hpp +80 -0
  922. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +133 -0
  923. package/nitrogen/generated/shared/c++/BatteryOptimizationStatus.hpp +80 -0
  924. package/nitrogen/generated/shared/c++/BatteryOptimizationStatusChangedEvent.hpp +76 -0
  925. package/nitrogen/generated/shared/c++/BatteryWarningPendingChangedEvent.hpp +75 -0
  926. package/nitrogen/generated/shared/c++/BrowseError.hpp +75 -0
  927. package/nitrogen/generated/shared/c++/BrowserSourceCallbackParam.hpp +81 -0
  928. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +84 -0
  929. package/nitrogen/generated/shared/c++/ChapterMetadata.hpp +88 -0
  930. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +105 -0
  931. package/nitrogen/generated/shared/c++/FavoriteChangedEvent.hpp +80 -0
  932. package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +88 -0
  933. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +79 -0
  934. package/nitrogen/generated/shared/c++/HeartRating.hpp +75 -0
  935. package/nitrogen/generated/shared/c++/HttpMethod.hpp +96 -0
  936. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +207 -0
  937. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +375 -0
  938. package/nitrogen/generated/shared/c++/IOSCategory.hpp +92 -0
  939. package/nitrogen/generated/shared/c++/IOSCategoryMode.hpp +104 -0
  940. package/nitrogen/generated/shared/c++/IOSCategoryOptions.hpp +96 -0
  941. package/nitrogen/generated/shared/c++/IOSCategoryPolicy.hpp +80 -0
  942. package/nitrogen/generated/shared/c++/ImageContext.hpp +79 -0
  943. package/nitrogen/generated/shared/c++/ImageQueryParams.hpp +80 -0
  944. package/nitrogen/generated/shared/c++/ImageSource.hpp +91 -0
  945. package/nitrogen/generated/shared/c++/IosOutput.hpp +85 -0
  946. package/nitrogen/generated/shared/c++/IosOutputType.hpp +112 -0
  947. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +123 -0
  948. package/nitrogen/generated/shared/c++/MediaTransformParams.hpp +84 -0
  949. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +135 -0
  950. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +131 -0
  951. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +103 -0
  952. package/nitrogen/generated/shared/c++/NavigationError.hpp +90 -0
  953. package/nitrogen/generated/shared/c++/NavigationErrorEvent.hpp +77 -0
  954. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +88 -0
  955. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +101 -0
  956. package/nitrogen/generated/shared/c++/NotificationButton.hpp +88 -0
  957. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +94 -0
  958. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +124 -0
  959. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +80 -0
  960. package/nitrogen/generated/shared/c++/Options.hpp +105 -0
  961. package/nitrogen/generated/shared/c++/PartialAndroidSetupPlayerOptions.hpp +121 -0
  962. package/nitrogen/generated/shared/c++/PartialIOSSetupPlayerOptions.hpp +103 -0
  963. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +96 -0
  964. package/nitrogen/generated/shared/c++/PercentageRating.hpp +75 -0
  965. package/nitrogen/generated/shared/c++/Playback.hpp +84 -0
  966. package/nitrogen/generated/shared/c++/PlaybackActiveTrackChangedEvent.hpp +93 -0
  967. package/nitrogen/generated/shared/c++/PlaybackError.hpp +79 -0
  968. package/nitrogen/generated/shared/c++/PlaybackErrorEvent.hpp +77 -0
  969. package/nitrogen/generated/shared/c++/PlaybackPlayWhenReadyChangedEvent.hpp +75 -0
  970. package/nitrogen/generated/shared/c++/PlaybackProgressUpdatedEvent.hpp +87 -0
  971. package/nitrogen/generated/shared/c++/PlaybackQueueEndedEvent.hpp +79 -0
  972. package/nitrogen/generated/shared/c++/PlaybackState.hpp +104 -0
  973. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +119 -0
  974. package/nitrogen/generated/shared/c++/PlayingState.hpp +79 -0
  975. package/nitrogen/generated/shared/c++/Progress.hpp +83 -0
  976. package/nitrogen/generated/shared/c++/RatingType.hpp +96 -0
  977. package/nitrogen/generated/shared/c++/RemoteJumpBackwardEvent.hpp +75 -0
  978. package/nitrogen/generated/shared/c++/RemoteJumpForwardEvent.hpp +75 -0
  979. package/nitrogen/generated/shared/c++/RemotePlayIdEvent.hpp +80 -0
  980. package/nitrogen/generated/shared/c++/RemotePlaySearchEvent.hpp +75 -0
  981. package/nitrogen/generated/shared/c++/RemoteSeekEvent.hpp +75 -0
  982. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +86 -0
  983. package/nitrogen/generated/shared/c++/RemoteSkipEvent.hpp +75 -0
  984. package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
  985. package/nitrogen/generated/shared/c++/RepeatModeChangedEvent.hpp +76 -0
  986. package/nitrogen/generated/shared/c++/RequestConfig.hpp +107 -0
  987. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +153 -0
  988. package/nitrogen/generated/shared/c++/RetryConfig.hpp +79 -0
  989. package/nitrogen/generated/shared/c++/SearchMode.hpp +92 -0
  990. package/nitrogen/generated/shared/c++/SearchParams.hpp +102 -0
  991. package/nitrogen/generated/shared/c++/SleepTimerEndOfTrack.hpp +75 -0
  992. package/nitrogen/generated/shared/c++/SleepTimerTime.hpp +75 -0
  993. package/nitrogen/generated/shared/c++/StarRating.hpp +75 -0
  994. package/nitrogen/generated/shared/c++/ThumbsRating.hpp +75 -0
  995. package/nitrogen/generated/shared/c++/TimedMetadata.hpp +92 -0
  996. package/nitrogen/generated/shared/c++/Track.hpp +145 -0
  997. package/nitrogen/generated/shared/c++/TrackMetadata.hpp +136 -0
  998. package/nitrogen/generated/shared/c++/TrackStyle.hpp +76 -0
  999. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +116 -0
  1000. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +103 -0
  1001. package/package.json +120 -0
  1002. package/src/AudioBrowser.ts +4 -0
  1003. package/src/features/battery.ts +176 -0
  1004. package/src/features/browser.ts +315 -0
  1005. package/src/features/equalizer.ts +64 -0
  1006. package/src/features/errors.ts +196 -0
  1007. package/src/features/favorites.ts +102 -0
  1008. package/src/features/index.ts +23 -0
  1009. package/src/features/metadata.ts +130 -0
  1010. package/src/features/network.ts +34 -0
  1011. package/src/features/nowPlaying.ts +56 -0
  1012. package/src/features/output.ts +50 -0
  1013. package/src/features/playback/controls.ts +66 -0
  1014. package/src/features/playback/index.ts +7 -0
  1015. package/src/features/playback/playWhenReady.ts +57 -0
  1016. package/src/features/playback/playing.ts +40 -0
  1017. package/src/features/playback/progress.ts +122 -0
  1018. package/src/features/playback/rate.ts +22 -0
  1019. package/src/features/playback/state.ts +72 -0
  1020. package/src/features/playback/volume.ts +59 -0
  1021. package/src/features/player/index.ts +2 -0
  1022. package/src/features/player/options.ts +479 -0
  1023. package/src/features/player/setup.ts +551 -0
  1024. package/src/features/queue/activeTrack.ts +59 -0
  1025. package/src/features/queue/index.ts +4 -0
  1026. package/src/features/queue/queue.ts +173 -0
  1027. package/src/features/queue/repeatMode.ts +58 -0
  1028. package/src/features/queue/shuffle.ts +49 -0
  1029. package/src/features/rating.ts +17 -0
  1030. package/src/features/remoteControls.ts +341 -0
  1031. package/src/features/sleepTimer.ts +186 -0
  1032. package/src/index.ts +5 -0
  1033. package/src/native.ts +5 -0
  1034. package/src/native.web.ts +4 -0
  1035. package/src/specs/audio-browser.nitro.ts +326 -0
  1036. package/src/types/browser-native.ts +66 -0
  1037. package/src/types/browser-nodes.ts +174 -0
  1038. package/src/types/browser.ts +792 -0
  1039. package/src/types/index.ts +2 -0
  1040. package/src/types/player.ts +69 -0
  1041. package/src/utils/LazyNativeEmitter.ts +58 -0
  1042. package/src/utils/NativeUpdatedValue.ts +56 -0
  1043. package/src/utils/resolveAssetSource.ts +4 -0
  1044. package/src/utils/useDebug.ts +283 -0
  1045. package/src/utils/useNativeUpdatedValue.ts +41 -0
  1046. package/src/web/NativeAudioBrowser.ts +781 -0
  1047. package/src/web/SimpleRouter.ts +177 -0
  1048. package/src/web/TrackPlayer/Event.ts +11 -0
  1049. package/src/web/TrackPlayer/Player.ts +323 -0
  1050. package/src/web/TrackPlayer/PlaylistPlayer.ts +337 -0
  1051. package/src/web/TrackPlayer/RepeatMode.ts +7 -0
  1052. package/src/web/TrackPlayer/SetupNotCalledError.ts +5 -0
  1053. package/src/web/TrackPlayer/SleepTimer.ts +71 -0
  1054. package/src/web/TrackPlayer/State.ts +15 -0
  1055. package/src/web/TrackPlayer/index.ts +4 -0
  1056. package/src/web/browser/BrowserManager.ts +642 -0
  1057. package/src/web/browser/FavoriteManager.ts +77 -0
  1058. package/src/web/browser/NavigationErrorManager.ts +112 -0
  1059. package/src/web/browser/SearchManager.ts +82 -0
  1060. package/src/web/http/HttpClient.ts +107 -0
  1061. package/src/web/http/RequestConfigBuilder.ts +347 -0
  1062. package/src/web/player/NowPlayingManager.ts +83 -0
  1063. package/src/web/player/OptionsManager.ts +101 -0
  1064. package/src/web/util/BrowserPathHelper.ts +147 -0
  1065. package/src/web/util/shuffle.ts +14 -0
@@ -0,0 +1,1590 @@
1
+ @preconcurrency import AVFoundation
2
+ import Foundation
3
+ import Kingfisher
4
+ import MediaPlayer
5
+ import NitroModules
6
+ import os.log
7
+
8
+ /// Result of media URL resolution
9
+ struct MediaResolvedUrl {
10
+ let url: String
11
+ let headers: [String: String]?
12
+ let userAgent: String?
13
+ }
14
+
15
+ @MainActor
16
+ class TrackPlayer {
17
+ private let logger = Logger(subsystem: "com.audiobrowser", category: "TrackPlayer")
18
+
19
+ let nowPlayingInfoController: NowPlayingInfoController
20
+ let remoteCommandController: RemoteCommandController
21
+ let sleepTimerManager = SleepTimerManager()
22
+ private let retryManager = RetryManager()
23
+ private var pendingRetryTask: Task<Void, Never>?
24
+ private weak var callbacks: TrackPlayerCallbacks?
25
+ private var lastIndex: Int = -1
26
+ private var lastTrack: Track?
27
+
28
+ /// Retry configuration for load errors (network failures, timeouts, etc.)
29
+ var retryConfig: Variant_Bool_RetryConfig? {
30
+ didSet {
31
+ retryManager.updatePolicy(from: retryConfig)
32
+ }
33
+ }
34
+
35
+ /// Network monitor for accelerating retries when connectivity is restored.
36
+ /// When set, retries will trigger immediately when network comes back online
37
+ /// instead of waiting for the full exponential backoff delay.
38
+ weak var networkMonitor: NetworkMonitor? {
39
+ didSet {
40
+ retryManager.networkMonitor = networkMonitor
41
+ }
42
+ }
43
+
44
+ /// Callback to resolve media URLs with optional transform
45
+ var mediaUrlResolver: ((String) async -> MediaResolvedUrl)?
46
+
47
+ /// Callback to resolve artwork URLs with size context for Now Playing.
48
+ /// Returns an ImageSource with potentially size-optimized URL.
49
+ var artworkUrlResolver: ((Track, ImageContext?) async -> ImageSource?)?
50
+
51
+ /// The repeat mode for the queue player.
52
+ var repeatMode: RepeatMode = .off {
53
+ didSet {
54
+ guard oldValue != repeatMode else { return }
55
+
56
+ // Sync state with MPRemoteCommandCenter for CarPlay/lock screen button display
57
+ remoteCommandController.updateRepeatMode(repeatMode)
58
+
59
+ callbacks?.playerDidChangeRepeatMode(
60
+ RepeatModeChangedEvent(repeatMode: repeatMode),
61
+ )
62
+ }
63
+ }
64
+
65
+ /// Whether shuffle mode is enabled.
66
+ /// When enabled, next/previous traverse the shuffle order instead of sequential order.
67
+ /// Like Media3, the shuffle order is pre-generated when tracks are added to the queue,
68
+ /// so toggling shuffle just changes how navigation works without reshuffling.
69
+ var shuffleEnabled: Bool = false {
70
+ didSet {
71
+ guard oldValue != shuffleEnabled else { return }
72
+
73
+ // Sync state with MPRemoteCommandCenter for CarPlay/lock screen button display
74
+ remoteCommandController.updateShuffleMode(shuffleEnabled)
75
+
76
+ logger.debug("Shuffle \(self.shuffleEnabled ? "enabled" : "disabled"), order: \(self.shuffleOrder.shuffled)")
77
+ callbacks?.playerDidChangeShuffleEnabled(shuffleEnabled)
78
+ }
79
+ }
80
+
81
+ /// The shuffle order for randomized playback
82
+ private var shuffleOrder = ShuffleOrder()
83
+
84
+ // MARK: - Queue Properties
85
+
86
+ /**
87
+ The index of the current track. `-1` when there is no current track
88
+ */
89
+ private(set) var currentIndex: Int = -1
90
+
91
+ /**
92
+ The source path from which the current queue was expanded (e.g., from a contextual URL).
93
+ Used to avoid re-expanding the queue when selecting tracks from the same source.
94
+ */
95
+ private(set) var queueSourcePath: String?
96
+
97
+ /**
98
+ All tracks held by the queue.
99
+ */
100
+ private(set) var tracks: [Track] = [] {
101
+ didSet {
102
+ callbacks?.playerDidChangeQueue(tracks)
103
+ }
104
+ }
105
+
106
+ var currentTrack: Track? {
107
+ guard currentIndex >= 0, currentIndex < tracks.count else { return nil }
108
+ return tracks[currentIndex]
109
+ }
110
+
111
+ /**
112
+ The upcoming tracks in playback order.
113
+ When shuffle is enabled, returns tracks in shuffled order.
114
+ */
115
+ var nextTracks: [Track] {
116
+ guard currentIndex >= 0, currentIndex < tracks.count else { return [] }
117
+
118
+ if shuffleEnabled {
119
+ // Return tracks in shuffled order after current position
120
+ var result: [Track] = []
121
+ var index = currentIndex
122
+ while let nextIndex = shuffleOrder.getNextIndex(after: index) {
123
+ result.append(tracks[nextIndex])
124
+ index = nextIndex
125
+ }
126
+ return result
127
+ }
128
+
129
+ guard currentIndex < tracks.count - 1 else { return [] }
130
+ return Array(tracks[currentIndex + 1 ..< tracks.count])
131
+ }
132
+
133
+ /**
134
+ The previous tracks in playback order.
135
+ When shuffle is enabled, returns tracks in shuffled order.
136
+ */
137
+ var previousTracks: [Track] {
138
+ guard currentIndex >= 0, currentIndex < tracks.count else { return [] }
139
+
140
+ if shuffleEnabled {
141
+ // Return tracks in shuffled order before current position
142
+ var result: [Track] = []
143
+ var index = currentIndex
144
+ while let prevIndex = shuffleOrder.getPreviousIndex(before: index) {
145
+ result.insert(tracks[prevIndex], at: 0)
146
+ index = prevIndex
147
+ }
148
+ return result
149
+ }
150
+
151
+ guard currentIndex > 0 else { return [] }
152
+ return Array(tracks[0 ..< currentIndex])
153
+ }
154
+
155
+ /**
156
+ Whether the current track is the last track in playback order.
157
+ When shuffle is enabled, this checks the shuffle order; otherwise, queue order.
158
+ */
159
+ private var isLastInPlaybackOrder: Bool {
160
+ if shuffleEnabled {
161
+ return shuffleOrder.isLast(currentIndex)
162
+ }
163
+ return currentIndex == tracks.count - 1
164
+ }
165
+
166
+ // MARK: - AVPlayer Properties (from AVPlayerWrapper)
167
+
168
+ /// Represents a seek operation that's pending while a track loads
169
+ private struct PendingSeek: Sendable {
170
+ let time: TimeInterval
171
+ let completion: (@Sendable (Bool) -> Void)?
172
+
173
+ func execute(on player: AVPlayer, delegate: TrackPlayer?) {
174
+ let cmTime = CMTime(seconds: time, preferredTimescale: 1000)
175
+ let seekTime = time
176
+ player
177
+ .seek(to: cmTime, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero) { finished in
178
+ Task { @MainActor in
179
+ delegate?.handleSeekCompleted(to: Double(seekTime), didFinish: finished)
180
+ }
181
+ completion?(finished)
182
+ }
183
+ }
184
+
185
+ func cancel() {
186
+ completion?(false)
187
+ }
188
+ }
189
+
190
+ private var avPlayer = AVPlayer()
191
+
192
+ private lazy var playerObserver: PlayerStateObserver = .init(
193
+ onStatusChange: { [weak self] status in
194
+ Task { @MainActor in self?.avPlayerStatusDidChange(status) }
195
+ },
196
+ onTimeControlStatusChange: { [weak self] status in
197
+ Task { @MainActor in self?.avPlayerDidChangeTimeControlStatus(status) }
198
+ },
199
+ )
200
+
201
+ private lazy var playerTimeObserver: PlayerTimeObserver = .init(
202
+ periodicObserverTimeInterval: CMTime(seconds: 1, preferredTimescale: 1000),
203
+ onAudioDidStart: { [weak self] in
204
+ Task { @MainActor in self?.audioDidStart() }
205
+ },
206
+ onSecondElapsed: { [weak self] seconds in
207
+ Task { @MainActor in self?.setNowPlayingCurrentTime(seconds: seconds) }
208
+ },
209
+ )
210
+
211
+ private lazy var playerItemNotificationObserver: PlayerItemNotificationObserver = .init(
212
+ onDidPlayToEndTime: { [weak self] in
213
+ Task { @MainActor in self?.handleTrackDidPlayToEndTime() }
214
+ },
215
+ onFailedToPlayToEndTime: { [weak self] error in
216
+ Task { @MainActor in self?.handleItemFailedToPlayToEndTime(error: error) }
217
+ },
218
+ )
219
+
220
+ private lazy var playerItemObserver: PlayerItemPropertyObserver = .init(
221
+ onDurationUpdate: { [weak self] duration in
222
+ Task { @MainActor in self?.callbacks?.playerDidUpdateDuration(duration) }
223
+ },
224
+ onPlaybackLikelyToKeepUpUpdate: { [weak self] isLikely in
225
+ Task { @MainActor in self?.avItemDidUpdatePlaybackLikelyToKeepUp(isLikely) }
226
+ },
227
+ onStatusChange: { [weak self] status, error in
228
+ Task { @MainActor in self?.avItemStatusDidChange(status, error: error) }
229
+ },
230
+ onTimedMetadataReceived: { [weak self] groups in
231
+ self?.callbacks?.playerDidReceiveTimedMetadata(groups)
232
+ },
233
+ )
234
+
235
+ private lazy var progressUpdateManager: PlaybackProgressUpdateManager =
236
+ PlaybackProgressUpdateManager { [weak self] in
237
+ guard let self, currentIndex >= 0 else { return }
238
+ let progressEvent = PlaybackProgressUpdatedEvent(
239
+ track: Double(currentIndex),
240
+ position: currentTime,
241
+ duration: duration,
242
+ buffered: bufferedPosition,
243
+ )
244
+ callbacks?.playerDidUpdateProgress(progressEvent)
245
+ }
246
+
247
+ lazy var playingStateManager: PlayingStateManager = PlayingStateManager { [weak self] state in
248
+ self?.callbacks?.playerDidChangePlayingState(state)
249
+ }
250
+
251
+ private var pendingSeek: PendingSeek?
252
+ private var metadataLoadTask: Task<Void, Never>?
253
+ private var playableLoadTask: Task<Void, Never>?
254
+ private var asset: AVAsset?
255
+ private var url: URL?
256
+ private var urlOptions: [String: Any]?
257
+ private(set) var playbackError: TrackPlayerError.PlaybackError? {
258
+ didSet {
259
+ guard oldValue != playbackError else { return }
260
+
261
+ // Setting an error should set state to .error
262
+ if let _ = playbackError, state != .error {
263
+ state = .error
264
+ }
265
+
266
+ callbacks?.playerDidError(PlaybackErrorEvent(error: playbackError?.toNitroError()))
267
+ }
268
+ }
269
+
270
+ private(set) var lastPlayerTimeControlStatus: AVPlayer.TimeControlStatus = .paused
271
+
272
+ func getPlayback() -> Playback {
273
+ Playback(state: state, error: playbackError?.toNitroError())
274
+ }
275
+
276
+ func getRepeatMode() -> RepeatMode {
277
+ repeatMode
278
+ }
279
+
280
+ func setRepeatMode(_ mode: RepeatMode) {
281
+ repeatMode = mode
282
+ }
283
+
284
+ /**
285
+ Controls the time pitch algorithm applied to each track loaded into the player.
286
+ If the loaded `AudioItem` conforms to `TimePitcher`-protocol this will be overriden.
287
+ */
288
+ var audioTimePitchAlgorithm: AVAudioTimePitchAlgorithm = .timeDomain
289
+
290
+ /**
291
+ Default remote commands to use for each playing track
292
+ */
293
+ var remoteCommands: [RemoteCommand] = [] {
294
+ didSet {
295
+ enableRemoteCommands(remoteCommands)
296
+ }
297
+ }
298
+
299
+ /**
300
+ Handles the `playWhenReady` setting while executing a given action.
301
+
302
+ This method takes an optional `Bool` value and a closure representing an action to execute.
303
+ If the `Bool` value is not `nil`, `self.playWhenReady` is set accordingly either before or
304
+ after executing the action.
305
+
306
+ - Parameters:
307
+ - playWhenReady: Optional `Bool` to set `self.playWhenReady`.
308
+ - If `true`, `self.playWhenReady` will be set after executing the action.
309
+ - If `false`, `self.playWhenReady` will be set before executing the action.
310
+ - If `nil`, `self.playWhenReady` will not be changed.
311
+ - action: A closure representing the action to execute. This closure can throw an error.
312
+
313
+ - Throws: This function will propagate any errors thrown by the `action` closure.
314
+ */
315
+ func handlePlayWhenReady(_ playWhenReady: Bool?, action: () throws -> Void) rethrows {
316
+ if playWhenReady == false {
317
+ self.playWhenReady = false
318
+ }
319
+
320
+ try action()
321
+
322
+ if playWhenReady == true {
323
+ self.playWhenReady = true
324
+ }
325
+ }
326
+
327
+ // MARK: - AVPlayer State and Computed Properties
328
+
329
+ private(set) var state: PlaybackState = .none {
330
+ didSet {
331
+ guard oldValue != state else { return }
332
+
333
+ // Clear error when transitioning away from error state
334
+ if oldValue == .error, state != .error {
335
+ playbackError = nil
336
+ }
337
+
338
+ switch state {
339
+ case .ready:
340
+ setTimePitchingAlgorithmForCurrentItem()
341
+ // When item becomes ready and playWhenReady is true, start playback
342
+ if playWhenReady {
343
+ startPlayback()
344
+ }
345
+ case .loading:
346
+ setTimePitchingAlgorithmForCurrentItem()
347
+ default: break
348
+ }
349
+
350
+ switch state {
351
+ case .ready, .loading, .playing, .paused:
352
+ updateNowPlayingPlaybackValues()
353
+ // Update playback state for CarPlay Now Playing
354
+ updateNowPlayingPlaybackState()
355
+ default: break
356
+ }
357
+
358
+ let playback = Playback(state: state, error: playbackError?.toNitroError())
359
+ callbacks?.playerDidChangePlayback(playback)
360
+
361
+ // Emit queue ended event when playback ends on the last track
362
+ // This matches Android's behavior (TrackPlayer.kt:642-646)
363
+ if state == .ended, isLastInPlaybackOrder {
364
+ let event = PlaybackQueueEndedEvent(
365
+ track: Double(currentIndex),
366
+ position: currentTime,
367
+ )
368
+ callbacks?.playerDidEndQueue(event)
369
+ }
370
+
371
+ progressUpdateManager.onPlaybackStateChanged(state)
372
+ playingStateManager.update(playWhenReady: playWhenReady, state: state)
373
+ }
374
+ }
375
+
376
+ var playbackActive: Bool {
377
+ switch state {
378
+ case .none, .stopped, .ended, .error:
379
+ false
380
+ default: true
381
+ }
382
+ }
383
+
384
+ var reasonForWaitingToPlay: AVPlayer.WaitingReason? {
385
+ avPlayer.reasonForWaitingToPlay
386
+ }
387
+
388
+ // MARK: - Getters from AVPlayerWrapper
389
+
390
+ /**
391
+ The elapsed playback time of the current track.
392
+ */
393
+ var currentTime: Double {
394
+ let seconds = avPlayer.currentTime().seconds
395
+ return seconds.isNaN ? 0 : seconds
396
+ }
397
+
398
+ /**
399
+ The duration of the current track.
400
+ */
401
+ var duration: Double {
402
+ guard let item = avPlayer.currentItem else { return 0.0 }
403
+
404
+ if !item.asset.duration.seconds.isNaN {
405
+ return item.asset.duration.seconds
406
+ }
407
+ if !item.duration.seconds.isNaN {
408
+ return item.duration.seconds
409
+ }
410
+ if let seekable = item.seekableTimeRanges.last?.timeRangeValue.duration.seconds,
411
+ !seekable.isNaN
412
+ {
413
+ return seekable
414
+ }
415
+ return 0.0
416
+ }
417
+
418
+ /**
419
+ The bufferedPosition of the active track
420
+ */
421
+ var bufferedPosition: Double {
422
+ avPlayer.currentItem?.loadedTimeRanges.last?.timeRangeValue.end.seconds ?? 0
423
+ }
424
+
425
+ /**
426
+ The current state of the underlying `TrackPlayer`.
427
+ */
428
+ var playerState: PlaybackState {
429
+ state
430
+ }
431
+
432
+ // MARK: - Setters for AVPlayerWrapper
433
+
434
+ /**
435
+ Whether the player should start playing automatically when the track is ready.
436
+ */
437
+ var playWhenReady: Bool = false {
438
+ didSet {
439
+ if playWhenReady == true, state == .error || state == .stopped {
440
+ reload(startFromCurrentTime: state == .error)
441
+ }
442
+ if playWhenReady {
443
+ startPlayback()
444
+ } else {
445
+ pausePlayback()
446
+ }
447
+
448
+ if oldValue != playWhenReady {
449
+ callbacks?.playerDidChangePlayWhenReady(playWhenReady)
450
+ playingStateManager.update(playWhenReady: playWhenReady, state: state)
451
+ }
452
+ }
453
+ }
454
+
455
+ /**
456
+ The amount of milliseconds to be buffered by the player. Default value is 0, this means the AVPlayer will choose an appropriate level of buffering. Setting `bufferDuration` to larger than zero automatically disables `automaticallyWaitsToMinimizeStalling`. Setting it back to zero automatically enables `automaticallyWaitsToMinimizeStalling`.
457
+
458
+ [Read more from Apple Documentation](https://developer.apple.com/documentation/avfoundation/avplayeritem/1643630-preferredforwardbufferduration)
459
+ */
460
+ var bufferDuration: Double = 0 {
461
+ didSet {
462
+ avPlayer.automaticallyWaitsToMinimizeStalling = bufferDuration == 0
463
+ }
464
+ }
465
+
466
+ /**
467
+ Indicates whether the player should automatically delay playback in order to minimize stalling. Setting this to true will also set `bufferDuration` back to `0`.
468
+
469
+ [Read more from Apple Documentation](https://developer.apple.com/documentation/avfoundation/avplayer/1643482-automaticallywaitstominimizestal)
470
+ */
471
+ var automaticallyWaitsToMinimizeStalling: Bool {
472
+ get { avPlayer.automaticallyWaitsToMinimizeStalling }
473
+ set {
474
+ if newValue {
475
+ bufferDuration = 0
476
+ }
477
+ avPlayer.automaticallyWaitsToMinimizeStalling = newValue
478
+ }
479
+ }
480
+
481
+ var volume: Float {
482
+ get { avPlayer.volume }
483
+ set { avPlayer.volume = newValue }
484
+ }
485
+
486
+ var isMuted: Bool {
487
+ get { avPlayer.isMuted }
488
+ set { avPlayer.isMuted = newValue }
489
+ }
490
+
491
+ var rate: Float = 1.0 {
492
+ didSet {
493
+ avPlayer.rate = rate
494
+ updateNowPlayingPlaybackValues()
495
+ }
496
+ }
497
+
498
+ // MARK: - Init
499
+
500
+ init(
501
+ nowPlayingInfoController: NowPlayingInfoController = NowPlayingInfoController(),
502
+ callbacks: TrackPlayerCallbacks? = nil,
503
+ ) {
504
+ self.nowPlayingInfoController = nowPlayingInfoController
505
+ remoteCommandController = RemoteCommandController(callbacks: callbacks)
506
+ self.callbacks = callbacks
507
+
508
+ // Configure sleep timer
509
+ sleepTimerManager.onComplete = { [weak self] in
510
+ self?.pause()
511
+ }
512
+
513
+ // Configure retry manager
514
+ retryManager.shouldRetry = { [weak self] in
515
+ self?.playWhenReady ?? false
516
+ }
517
+ retryManager.onRetry = { [weak self] startFromCurrentTime in
518
+ self?.reload(startFromCurrentTime: startFromCurrentTime)
519
+ }
520
+
521
+ // Handle command center changes when MPNowPlayingSession is created/destroyed (iOS 16+)
522
+ // This callback is guaranteed to be called on the main thread by NowPlayingInfoController
523
+ nowPlayingInfoController.onRemoteCommandCenterChanged = { [weak self] newCommandCenter in
524
+ MainActor.assumeIsolated {
525
+ self?.remoteCommandController.switchCommandCenter(newCommandCenter)
526
+ }
527
+ }
528
+
529
+ setupAVPlayer()
530
+ }
531
+
532
+ // MARK: - Player Actions
533
+
534
+ /**
535
+ Will replace the current track with a new one and load it into the player.
536
+
537
+ - parameter track: The Track to replace the current track.
538
+ - parameter playWhenReady: Optional, whether to start playback when the track is ready.
539
+ */
540
+ func load(_ track: Track, playWhenReady: Bool? = nil) {
541
+ handlePlayWhenReady(playWhenReady) {
542
+ if currentIndex == -1 {
543
+ tracks.append(track)
544
+ currentIndex = 0
545
+ } else {
546
+ setTrack(at: currentIndex, track)
547
+ }
548
+ handleCurrentTrackChanged()
549
+ }
550
+ }
551
+
552
+ /**
553
+ Toggle playback status.
554
+ */
555
+ func togglePlaying() {
556
+ switch avPlayer.timeControlStatus {
557
+ case .playing, .waitingToPlayAtSpecifiedRate:
558
+ pause()
559
+ case .paused:
560
+ play()
561
+ @unknown default:
562
+ fatalError("Unknown AVPlayer.timeControlStatus")
563
+ }
564
+ }
565
+
566
+ /**
567
+ Start playback
568
+ */
569
+ func play() {
570
+ playWhenReady = true
571
+ }
572
+
573
+ /**
574
+ Pause playback
575
+ */
576
+ func pause() {
577
+ playWhenReady = false
578
+ }
579
+
580
+ /**
581
+ Toggle playback between play and pause
582
+ */
583
+ func togglePlayback() {
584
+ playWhenReady = !playWhenReady
585
+ }
586
+
587
+ /**
588
+ Stop playback
589
+ */
590
+ func stop() {
591
+ state = .stopped
592
+ if currentTrack?.live != true {
593
+ seekTo(0)
594
+ }
595
+ playWhenReady = false
596
+ }
597
+
598
+ /**
599
+ Reload the current track.
600
+ */
601
+ func reload(startFromCurrentTime: Bool) {
602
+ var time: Double? = nil
603
+ if startFromCurrentTime {
604
+ if let currentItem = avPlayer.currentItem {
605
+ if !currentItem.duration.isIndefinite {
606
+ time = currentItem.currentTime().seconds
607
+ }
608
+ }
609
+ }
610
+ loadAVPlayer()
611
+ if let time {
612
+ seekTo(time)
613
+ }
614
+ }
615
+
616
+ /**
617
+ Seek to a specific time in the track.
618
+ */
619
+ func seekTo(_ seconds: TimeInterval) {
620
+ seekTo(seconds, completion: { _ in })
621
+ }
622
+
623
+ /**
624
+ Seek to a specific time in the track with a completion handler.
625
+
626
+ - parameter seconds: The time to seek to.
627
+ - parameter completion: Called when the seek operation completes. The Bool parameter indicates whether the seek finished successfully (true) or was interrupted/deferred (false).
628
+ */
629
+ func seekTo(_ seconds: TimeInterval, completion: @escaping @Sendable (Bool) -> Void) {
630
+ // If an track is currently being loaded asynchronously, defer the seek until it's ready.
631
+ if state == .loading {
632
+ // Cancel any previous pending seek before creating a new one
633
+ pendingSeek?.cancel()
634
+ pendingSeek = PendingSeek(time: seconds, completion: completion)
635
+ } else if avPlayer.currentItem != nil {
636
+ let time = CMTime(seconds: seconds, preferredTimescale: 1000)
637
+ let seekSeconds = seconds
638
+ avPlayer
639
+ .seek(to: time, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero) { [weak self] finished in
640
+ Task { @MainActor in
641
+ self?.handleSeekCompleted(to: Double(seekSeconds), didFinish: finished)
642
+ }
643
+ completion(finished)
644
+ }
645
+ } else {
646
+ // No track loaded and not loading - seek fails immediately
647
+ completion(false)
648
+ }
649
+ }
650
+
651
+ /**
652
+ Seek by relative a time offset in the track.
653
+ */
654
+ func seekBy(_ offset: TimeInterval) {
655
+ // Calculate the target time based on current state
656
+ let targetTime: TimeInterval
657
+ if state == .loading {
658
+ // If loading, offset from pending seek (or 0 if no pending seek)
659
+ targetTime = (pendingSeek?.time ?? 0) + offset
660
+ } else if let currentItem = avPlayer.currentItem {
661
+ // If playing, offset from current position
662
+ targetTime = currentItem.currentTime().seconds + offset
663
+ } else {
664
+ // No track and not loading - nothing to seek in
665
+ return
666
+ }
667
+
668
+ // Delegate to absolute seek
669
+ seekTo(targetTime)
670
+ }
671
+
672
+ // MARK: - Remote Command Center
673
+
674
+ func enableRemoteCommands(_ commands: [RemoteCommand]) {
675
+ remoteCommandController.enable(commands: commands)
676
+ }
677
+
678
+ // MARK: - NowPlayingInfo
679
+
680
+ /**
681
+ Loads NowPlayingInfo-meta values with the values found in the current track. Use this if a change to the track is made and you want to update the `NowPlayingInfoController`s values.
682
+
683
+ Reloads:
684
+ - Artist
685
+ - Title
686
+ - Album title
687
+ - Album artwork
688
+ */
689
+ func loadNowPlayingMetaValues() {
690
+ guard let track = currentTrack else { return }
691
+
692
+ nowPlayingInfoController.set(keyValues: [
693
+ MediaItemProperty.artist(track.artist),
694
+ MediaItemProperty.title(track.title),
695
+ MediaItemProperty.albumTitle(track.album),
696
+ NowPlayingInfoProperty.playbackRate(Double(rate)),
697
+ NowPlayingInfoProperty.isLiveStream(track.live),
698
+ ])
699
+ loadArtworkForTrack(track)
700
+ }
701
+
702
+ /**
703
+ Resyncs the playbackvalues of the currently playing track.
704
+
705
+ Will resync:
706
+ - Current time
707
+ - Duration
708
+ - Playback rate
709
+ */
710
+ func updateNowPlayingPlaybackValues() {
711
+ logger.debug("updateNowPlayingPlaybackValues: duration=\(self.duration), rate=\(self.rate), currentTime=\(self.currentTime), playWhenReady=\(self.playWhenReady)")
712
+ nowPlayingInfoController.set(keyValues: [
713
+ MediaItemProperty.duration(duration),
714
+ NowPlayingInfoProperty.playbackRate(Double(rate)),
715
+ NowPlayingInfoProperty.elapsedPlaybackTime(currentTime),
716
+ ])
717
+ }
718
+
719
+ /// Updates the Now Playing playback state for CarPlay.
720
+ /// This is separate from playbackRate and required for CarPlay to show correct play/pause button.
721
+ private func updateNowPlayingPlaybackState() {
722
+ let state: MPNowPlayingPlaybackState = playWhenReady ? .playing : .paused
723
+ logger.debug("updateNowPlayingPlaybackState: \(state.rawValue) (playWhenReady=\(self.playWhenReady))")
724
+ nowPlayingInfoController.setPlaybackState(state)
725
+ }
726
+
727
+ func clear() {
728
+ clearTracks()
729
+ unloadAVPlayer()
730
+ nowPlayingInfoController.unlinkPlayer()
731
+ nowPlayingInfoController.clear()
732
+ }
733
+
734
+ // MARK: - Private
735
+
736
+ private func setNowPlayingCurrentTime(seconds: Double) {
737
+ nowPlayingInfoController.set(
738
+ keyValue: NowPlayingInfoProperty.elapsedPlaybackTime(seconds),
739
+ )
740
+ }
741
+
742
+ private func loadArtworkForTrack(_ track: Track) {
743
+ let artworkUrl = track.artworkSource?.uri ?? track.artwork
744
+ logger.debug("loadArtworkForTrack: \(track.title), artworkUrl: \(artworkUrl ?? "nil")")
745
+
746
+ // Now Playing artwork: use screen width in pixels, capped at 1200px
747
+ let screenScale = UIScreen.main.scale
748
+ let screenWidth = UIScreen.main.bounds.width * screenScale
749
+ let artworkSize = min(screenWidth, 1200)
750
+ let nowPlayingSize = ImageContext(width: artworkSize, height: artworkSize)
751
+
752
+ Task {
753
+ let image: UIImage?
754
+
755
+ // Try to resolve artwork URL with size context for CDN optimization
756
+ if let resolver = artworkUrlResolver,
757
+ let imageSource = await resolver(track, nowPlayingSize)
758
+ {
759
+ logger.debug("loadArtworkForTrack: using resolved URL: \(imageSource.uri)")
760
+ image = await loadImage(from: imageSource)
761
+ } else {
762
+ // Fall back to loading from track's existing artwork URL
763
+ image = await track.loadArtwork()
764
+ }
765
+
766
+ // Verify we're still on the same track after async load
767
+ guard currentTrack?.src == track.src else { return }
768
+
769
+ if let image {
770
+ logger.debug("loadArtworkForTrack: loaded image \(image.size.width)x\(image.size.height)")
771
+ // Note: The requestHandler closure is called from MediaPlayer's background queue,
772
+ // so we must mark it @Sendable to break @MainActor isolation inheritance.
773
+ let artwork = MPMediaItemArtwork(boundsSize: image.size) { @Sendable requestedSize in
774
+ return image
775
+ }
776
+ nowPlayingInfoController.set(keyValue: MediaItemProperty.artwork(artwork))
777
+ } else {
778
+ logger.debug("loadArtworkForTrack: no image loaded")
779
+ nowPlayingInfoController.set(keyValue: MediaItemProperty.artwork(nil))
780
+ }
781
+ }
782
+ }
783
+
784
+ /// Loads an image from an ImageSource using Kingfisher.
785
+ private func loadImage(from imageSource: ImageSource) async -> UIImage? {
786
+ guard let url = URL(string: imageSource.uri) else { return nil }
787
+
788
+ if url.isFileURL {
789
+ return UIImage(contentsOfFile: url.path)
790
+ }
791
+
792
+ // Build Kingfisher options with headers if provided
793
+ var options: KingfisherOptionsInfo = []
794
+ if let headers = imageSource.headers, !headers.isEmpty {
795
+ let modifier = AnyModifier { request in
796
+ var mutableRequest = request
797
+ for (key, value) in headers {
798
+ mutableRequest.setValue(value, forHTTPHeaderField: key)
799
+ }
800
+ return mutableRequest
801
+ }
802
+ options.append(.requestModifier(modifier))
803
+ }
804
+
805
+ do {
806
+ let result = try await KingfisherManager.shared.retrieveImage(with: url, options: options)
807
+ return result.image
808
+ } catch {
809
+ logger.error("Failed to load artwork from \(imageSource.uri): \(error.localizedDescription)")
810
+ return nil
811
+ }
812
+ }
813
+
814
+ private func setTimePitchingAlgorithmForCurrentItem() {
815
+ // Use player's default pitch algorithm (per-track pitch control not in Nitro API)
816
+ avPlayer.currentItem?.audioTimePitchAlgorithm = audioTimePitchAlgorithm
817
+ }
818
+
819
+ // MARK: - AVPlayer Management Methods (from AVPlayerWrapper)
820
+
821
+ /// Starts playback at the configured rate
822
+ private func startPlayback() {
823
+ avPlayer.play()
824
+ }
825
+
826
+ /// Pauses playback
827
+ private func pausePlayback() {
828
+ avPlayer.pause()
829
+ }
830
+
831
+ private func clearCurrentAVItem() {
832
+ guard let currentAsset = asset else {
833
+ avPlayer.replaceCurrentItem(with: nil)
834
+ return
835
+ }
836
+
837
+ stopObservingAVPlayerItem()
838
+
839
+ // Don't call currentAsset.cancelLoading() - it blocks the main thread for 500ms+
840
+ // Instead, cancel on a background queue
841
+ DispatchQueue.global(qos: .utility).async {
842
+ currentAsset.cancelLoading()
843
+ }
844
+
845
+ asset = nil
846
+ pendingSeek?.cancel()
847
+ pendingSeek = nil
848
+
849
+ avPlayer.replaceCurrentItem(with: nil)
850
+ }
851
+
852
+ private func startObservingAVPlayerItem(_ avItem: AVPlayerItem) {
853
+ playerItemObserver.startObserving(item: avItem)
854
+ playerItemNotificationObserver.startObserving(item: avItem)
855
+ }
856
+
857
+ private func stopObservingAVPlayerItem() {
858
+ playerItemObserver.stopObservingCurrentItem()
859
+ playerItemNotificationObserver.stopObservingCurrentItem()
860
+ }
861
+
862
+ private func recreateAVPlayer() {
863
+ playbackError = nil
864
+ playerTimeObserver.unregisterForBoundaryTimeEvents()
865
+ playerTimeObserver.unregisterForPeriodicEvents()
866
+ playerObserver.stopObserving()
867
+ stopObservingAVPlayerItem()
868
+ clearCurrentAVItem()
869
+
870
+ // Unlink old player before creating new one
871
+ nowPlayingInfoController.unlinkPlayer()
872
+
873
+ avPlayer = AVPlayer()
874
+ setupAVPlayer()
875
+ }
876
+
877
+ private func setupAVPlayer() {
878
+ // disabled since we're not making use of video playback
879
+ avPlayer.allowsExternalPlayback = false
880
+
881
+ playerObserver.avPlayer = avPlayer
882
+ playerObserver.startObserving()
883
+
884
+ playerTimeObserver.avPlayer = avPlayer
885
+ playerTimeObserver.registerForBoundaryTimeEvents()
886
+ playerTimeObserver.registerForPeriodicTimeEvents()
887
+
888
+ // Link AVPlayer to NowPlayingInfoController for automatic publishing on iOS 16+
889
+ nowPlayingInfoController.linkPlayer(avPlayer)
890
+
891
+ // Apply initial playback state
892
+ if playWhenReady {
893
+ startPlayback()
894
+ } else {
895
+ // Ensure defaultRate is set for when playback starts later
896
+ if #available(iOS 16.0, *) {
897
+ avPlayer.defaultRate = rate
898
+ }
899
+ }
900
+ }
901
+
902
+ func loadAVPlayer() {
903
+ if state == .error {
904
+ recreateAVPlayer()
905
+ } else if let oldAsset = asset {
906
+ // Prepare for new item: cancel in-flight tasks, stop observing, cancel asset loading
907
+ metadataLoadTask?.cancel()
908
+ playableLoadTask?.cancel()
909
+ stopObservingAVPlayerItem()
910
+ pausePlayback()
911
+ DispatchQueue.global(qos: .utility).async {
912
+ oldAsset.cancelLoading()
913
+ }
914
+ asset = nil
915
+ pendingSeek?.cancel()
916
+ pendingSeek = nil
917
+ }
918
+ if let url {
919
+ let pendingAsset = AVURLAsset(url: url, options: urlOptions)
920
+ asset = pendingAsset
921
+ state = .loading
922
+
923
+ // Load metadata asynchronously, separate from playable to allow playback to start faster
924
+ metadataLoadTask = Task { [weak self] in
925
+ guard let self else { return }
926
+
927
+ guard let (commonMetadata, chapterLocales, metadataFormats) = try? await pendingAsset.load(
928
+ .commonMetadata,
929
+ .availableChapterLocales,
930
+ .availableMetadataFormats,
931
+ ) else { return }
932
+
933
+ guard !Task.isCancelled, pendingAsset == asset else { return }
934
+
935
+ if !commonMetadata.isEmpty {
936
+ callbacks?.playerDidReceiveCommonMetadata(commonMetadata)
937
+ }
938
+
939
+ if !chapterLocales.isEmpty {
940
+ for locale in chapterLocales {
941
+ guard !Task.isCancelled else { return }
942
+ if let chapters = try? await pendingAsset.loadChapterMetadataGroups(
943
+ withTitleLocale: locale,
944
+ containingItemsWithCommonKeys: [],
945
+ ) {
946
+ callbacks?.playerDidReceiveChapterMetadata(chapters)
947
+ }
948
+ }
949
+ } else {
950
+ let duration = await (try? pendingAsset.load(.duration)) ?? .zero
951
+ for format in metadataFormats {
952
+ guard !Task.isCancelled else { return }
953
+ if let metadata = try? await pendingAsset.loadMetadata(for: format) {
954
+ let timeRange = CMTimeRange(
955
+ start: CMTime(seconds: 0, preferredTimescale: 1000),
956
+ end: duration,
957
+ )
958
+ let group = AVTimedMetadataGroup(items: metadata, timeRange: timeRange)
959
+ callbacks?.playerDidReceiveTimedMetadata([group])
960
+ }
961
+ }
962
+ }
963
+ }
964
+
965
+ // Load playable and start playback when ready
966
+ playableLoadTask = Task { [weak self] in
967
+ guard let self else { return }
968
+
969
+ do {
970
+ let isPlayable = try await pendingAsset.load(.isPlayable)
971
+
972
+ guard !Task.isCancelled else { return }
973
+
974
+ await MainActor.run {
975
+ guard pendingAsset == self.asset else { return }
976
+
977
+ if !isPlayable {
978
+ self.playbackError = TrackPlayerError.PlaybackError.trackWasUnplayable
979
+ return
980
+ }
981
+
982
+ let avItem = AVPlayerItem(asset: pendingAsset)
983
+ avItem.preferredForwardBufferDuration = self.bufferDuration / 1000.0
984
+ // Set metadata on item before it becomes current, so there's no gap
985
+ self.nowPlayingInfoController.prepareItem(avItem)
986
+ self.logger.debug("AVPlayerItem created, calling replaceCurrentItem")
987
+ self.avPlayer.replaceCurrentItem(with: avItem)
988
+ self.startObservingAVPlayerItem(avItem)
989
+ self.logger.debug("AVPlayerItem loaded, currentItem: \(String(describing: self.avPlayer.currentItem)), playWhenReady: \(self.playWhenReady), avPlayer.status=\(self.avPlayer.status.rawValue)")
990
+ if self.playWhenReady {
991
+ self.startPlayback()
992
+ }
993
+
994
+ // Execute any pending seek operation
995
+ if let pending = self.pendingSeek {
996
+ self.pendingSeek = nil
997
+ pending.execute(on: self.avPlayer, delegate: self)
998
+ }
999
+ }
1000
+ } catch {
1001
+ guard !Task.isCancelled else { return }
1002
+
1003
+ // Try retry before setting error
1004
+ if self.retryManager.isRetryable(error) {
1005
+ let retried = await self.retryManager.attemptRetry(startFromCurrentTime: false)
1006
+ if retried {
1007
+ return // Retry was triggered, don't set error
1008
+ }
1009
+ }
1010
+
1011
+ await MainActor.run {
1012
+ guard pendingAsset == self.asset else { return }
1013
+ self.playbackError = TrackPlayerError.PlaybackError.failedToLoadKeyValue
1014
+ }
1015
+ }
1016
+ }
1017
+ }
1018
+ }
1019
+
1020
+ func unloadAVPlayer() {
1021
+ clearCurrentAVItem()
1022
+ state = .none
1023
+ }
1024
+
1025
+ // MARK: - Internal Event Handlers
1026
+
1027
+ /**
1028
+ Sets the progress update interval.
1029
+ - Parameter interval: The interval in seconds, or nil to disable progress updates
1030
+ */
1031
+ func setProgressUpdateInterval(_ interval: TimeInterval?) {
1032
+ progressUpdateManager.setUpdateInterval(interval)
1033
+ }
1034
+
1035
+ private func handleSeekCompleted(to seconds: Double, didFinish: Bool) {
1036
+ setNowPlayingCurrentTime(seconds: seconds)
1037
+ callbacks?.playerDidCompleteSeek(position: seconds, didFinish: didFinish)
1038
+ }
1039
+
1040
+ func handleTrackDidPlayToEndTime() {
1041
+ // Check if sleep timer should trigger on track end
1042
+ sleepTimerManager.onTrackPlayedToEnd()
1043
+
1044
+ if repeatMode == .track {
1045
+ replay()
1046
+ } else if repeatMode == .queue || !isLastInPlaybackOrder {
1047
+ next()
1048
+ } else {
1049
+ state = .ended
1050
+ }
1051
+ }
1052
+
1053
+ // MARK: - Observer Callbacks
1054
+
1055
+ func avPlayerDidChangeTimeControlStatus(_ status: AVPlayer.TimeControlStatus) {
1056
+ switch status {
1057
+ case .paused:
1058
+ let currentState = state
1059
+ let currentTime = currentTime
1060
+ let duration = duration
1061
+ // Ignore pauses when near track end - let handleTrackDidPlayToEndTime handle track
1062
+ // completion
1063
+ let nearTrackEnd = currentTime >= duration - 0.5 && duration > 0
1064
+
1065
+ // Completely ignore pause events when near track end to avoid race with
1066
+ // handleTrackDidPlayToEndTime
1067
+ if nearTrackEnd {
1068
+ // Ignore - track completion will be handled by handleTrackDidPlayToEndTime
1069
+ } else if asset == nil, currentState != .stopped {
1070
+ state = .none
1071
+ } else if currentState != .error, currentState != .stopped {
1072
+ // Only update state, never modify playWhenReady
1073
+ // playWhenReady represents user intent and should only change via explicit user actions
1074
+ if !playWhenReady {
1075
+ state = .paused
1076
+ }
1077
+ // If playWhenReady is true, this is likely buffering/seeking - don't change state
1078
+ }
1079
+ case .waitingToPlayAtSpecifiedRate:
1080
+ if asset != nil {
1081
+ state = .buffering
1082
+ }
1083
+ case .playing:
1084
+ state = .playing
1085
+ @unknown default:
1086
+ break
1087
+ }
1088
+ }
1089
+
1090
+ func avPlayerStatusDidChange(_ status: AVPlayer.Status) {
1091
+ if status == .failed {
1092
+ handlePlaybackFailure(error: avPlayer.currentItem?.error)
1093
+ }
1094
+ }
1095
+
1096
+ /// Handles AVPlayerItem status changes - this catches errors that don't show up in AVPlayer.status
1097
+ func avItemStatusDidChange(_ status: AVPlayerItem.Status, error: Error?) {
1098
+ if status == .failed {
1099
+ let effectiveError = error ?? avPlayer.currentItem?.error
1100
+ handlePlaybackFailure(error: effectiveError)
1101
+ }
1102
+ }
1103
+
1104
+ /// Common handler for playback failures from either AVPlayer or AVPlayerItem
1105
+ private func handlePlaybackFailure(error: Error?) {
1106
+ if let error {
1107
+ let nsError = error as NSError
1108
+ logger.error("Playback failure: domain=\(nsError.domain), code=\(nsError.code), localizedDescription=\(error.localizedDescription)")
1109
+ } else {
1110
+ logger.error("Playback failure with nil error")
1111
+ }
1112
+
1113
+ // Try retry before setting error state
1114
+ if retryManager.isRetryable(error) {
1115
+ pendingRetryTask?.cancel()
1116
+ pendingRetryTask = Task {
1117
+ let retried = await retryManager.attemptRetry(startFromCurrentTime: true)
1118
+ if !retried {
1119
+ // Max retries exceeded or retry cancelled, surface error
1120
+ self.setPlaybackError(from: error)
1121
+ }
1122
+ }
1123
+ return
1124
+ }
1125
+
1126
+ logger.warning("Error not retryable, surfacing playback_failed")
1127
+ setPlaybackError(from: error)
1128
+ }
1129
+
1130
+ /// Sets the playback error from an Error, with appropriate classification
1131
+ private func setPlaybackError(from error: Error?) {
1132
+ let nsError = error as NSError?
1133
+ playbackError = nsError?.code == URLError.notConnectedToInternet.rawValue
1134
+ ? TrackPlayerError.PlaybackError.notConnectedToInternet
1135
+ : TrackPlayerError.PlaybackError.playbackFailed
1136
+ }
1137
+
1138
+ /// Handles AVPlayerItemFailedToPlayToEndTime notification with retry logic
1139
+ private func handleItemFailedToPlayToEndTime(error: Error?) {
1140
+ let effectiveError = error ?? avPlayer.currentItem?.error
1141
+ handlePlaybackFailure(error: effectiveError)
1142
+ }
1143
+
1144
+ func audioDidStart() {
1145
+ state = .playing
1146
+ }
1147
+
1148
+ func avItemDidUpdatePlaybackLikelyToKeepUp(_ playbackLikelyToKeepUp: Bool) {
1149
+ logger.debug("avItemDidUpdatePlaybackLikelyToKeepUp: \(playbackLikelyToKeepUp), state=\(self.state.rawValue)")
1150
+ if playbackLikelyToKeepUp, state != .playing {
1151
+ logger.debug("setting state = .ready")
1152
+ state = .ready
1153
+ }
1154
+ }
1155
+
1156
+ // MARK: - Queue Validation
1157
+
1158
+ private func throwIfQueueEmpty() throws {
1159
+ if tracks.isEmpty {
1160
+ throw TrackPlayerError.QueueError.empty
1161
+ }
1162
+ }
1163
+
1164
+ private func throwIfIndexInvalid(
1165
+ index: Int,
1166
+ name: String = "index",
1167
+ min: Int? = nil,
1168
+ max: Int? = nil,
1169
+ ) throws {
1170
+ guard index >= (min ?? 0), (max ?? tracks.count) > index else {
1171
+ throw TrackPlayerError.QueueError.invalidIndex(
1172
+ index: index,
1173
+ message: "\(name) must be non-negative and less than \(tracks.count)",
1174
+ )
1175
+ }
1176
+ }
1177
+
1178
+ // MARK: - Queue Methods
1179
+
1180
+ /**
1181
+ Set the track at a specific index.
1182
+
1183
+ - parameter index: The index of the track to set.
1184
+ - parameter track: The track to set.
1185
+ */
1186
+ func setTrack(at index: Int, _ track: Track) {
1187
+ guard index >= 0, index < tracks.count else { return }
1188
+ tracks[index] = track
1189
+ }
1190
+
1191
+ /**
1192
+ Replace the entire queue with new tracks.
1193
+
1194
+ - parameter tracks: The tracks to set as the new queue.
1195
+ - parameter initialIndex: The index to start at. Defaults to 0.
1196
+ - parameter playWhenReady: Optional, whether to start playback when the track is ready.
1197
+ - parameter sourcePath: Optional path from which this queue was expanded (for contextual URL optimization).
1198
+ */
1199
+ func setQueue(_ newTracks: [Track], initialIndex: Int = 0, playWhenReady: Bool? = nil, sourcePath: String? = nil) {
1200
+ guard !newTracks.isEmpty else {
1201
+ clear()
1202
+ return
1203
+ }
1204
+
1205
+ // Replace tracks and index atomically to avoid intermediate nil state
1206
+ let clampedIndex = max(0, min(initialIndex, newTracks.count - 1))
1207
+ tracks = newTracks
1208
+ currentIndex = clampedIndex
1209
+ queueSourcePath = sourcePath
1210
+
1211
+ // Generate new shuffle order for the new queue
1212
+ // Like Media3, this is a fresh randomized order - not reshuffled based on current track
1213
+ shuffleOrder = ShuffleOrder(length: newTracks.count)
1214
+
1215
+ // Handle playWhenReady and load the new track
1216
+ handlePlayWhenReady(playWhenReady) {
1217
+ handleCurrentTrackChanged()
1218
+ }
1219
+ }
1220
+
1221
+ /**
1222
+ Add tracks to the queue.
1223
+
1224
+ - parameter tracks: The tracks to add to the queue.
1225
+ - parameter initialIndex: Optional, the index to start at when queue was empty. Defaults to 0.
1226
+ - parameter playWhenReady: Optional, whether to start playback when the track is ready.
1227
+ */
1228
+ func add(_ tracks: [Track], initialIndex: Int? = nil, playWhenReady: Bool? = nil) {
1229
+ handlePlayWhenReady(playWhenReady) {
1230
+ add(tracks, initialIndex: initialIndex ?? 0)
1231
+ }
1232
+ }
1233
+
1234
+ private func add(_ newTracks: [Track], initialIndex: Int) {
1235
+ guard !newTracks.isEmpty else { return }
1236
+ let wasEmpty = tracks.isEmpty
1237
+ let insertIndex = tracks.count
1238
+ tracks.append(contentsOf: newTracks)
1239
+
1240
+ // Update shuffle order - inserts new items at random positions (like Media3)
1241
+ shuffleOrder.insert(at: insertIndex, count: newTracks.count)
1242
+
1243
+ if wasEmpty {
1244
+ // Use initialIndex, clamped to valid range
1245
+ currentIndex = max(0, min(initialIndex, tracks.count - 1))
1246
+ handleCurrentTrackChanged()
1247
+ }
1248
+ }
1249
+
1250
+ func add(_ tracks: [Track], at index: Int) throws {
1251
+ guard !tracks.isEmpty else { return }
1252
+ guard index >= 0, self.tracks.count >= index else {
1253
+ throw TrackPlayerError.QueueError.invalidIndex(
1254
+ index: index,
1255
+ message: "Index to insert at has to be non-negative and equal to or smaller than the number of tracks: (\(self.tracks.count))",
1256
+ )
1257
+ }
1258
+ let wasEmpty = self.tracks.isEmpty
1259
+ // Correct index when tracks were inserted in front of it:
1260
+ if self.tracks.count > 1, currentIndex >= index {
1261
+ currentIndex += tracks.count
1262
+ }
1263
+ self.tracks.insert(contentsOf: tracks, at: index)
1264
+
1265
+ // Update shuffle order - inserts new items at random positions (like Media3)
1266
+ shuffleOrder.insert(at: index, count: tracks.count)
1267
+
1268
+ if wasEmpty {
1269
+ currentIndex = 0
1270
+ handleCurrentTrackChanged()
1271
+ }
1272
+ }
1273
+
1274
+ /**
1275
+ Step to the next track in the queue.
1276
+ */
1277
+ func next() {
1278
+ guard currentTrack != nil, !tracks.isEmpty else { return }
1279
+
1280
+ let wrap = repeatMode == .queue
1281
+
1282
+ if tracks.count == 1 {
1283
+ if wrap, playWhenReady {
1284
+ replay()
1285
+ }
1286
+ return
1287
+ }
1288
+
1289
+ var newIndex: Int?
1290
+ if shuffleEnabled {
1291
+ // Use shuffle order for navigation
1292
+ newIndex = shuffleOrder.getNextIndex(after: currentIndex)
1293
+ if newIndex == nil {
1294
+ // Wrap to start of shuffle order (same order, like Media3)
1295
+ newIndex = shuffleOrder.firstIndex
1296
+ }
1297
+ } else {
1298
+ // Sequential navigation
1299
+ let nextIndex = currentIndex + 1
1300
+ if nextIndex < tracks.count {
1301
+ newIndex = nextIndex
1302
+ } else if wrap {
1303
+ newIndex = 0
1304
+ }
1305
+ }
1306
+
1307
+ if let newIndex, newIndex != currentIndex {
1308
+ currentIndex = newIndex
1309
+ handleCurrentTrackChanged()
1310
+ }
1311
+ }
1312
+
1313
+ /**
1314
+ Step to the previous track in the queue.
1315
+ */
1316
+ func previous() {
1317
+ guard currentTrack != nil, !tracks.isEmpty else { return }
1318
+
1319
+ let wrap = repeatMode == .queue
1320
+
1321
+ if tracks.count == 1 {
1322
+ if wrap, playWhenReady {
1323
+ replay()
1324
+ }
1325
+ return
1326
+ }
1327
+
1328
+ var newIndex: Int?
1329
+ if shuffleEnabled {
1330
+ // Use shuffle order for navigation
1331
+ newIndex = shuffleOrder.getPreviousIndex(before: currentIndex)
1332
+ if newIndex == nil {
1333
+ // Wrap to end of shuffle order (same order, like Media3)
1334
+ newIndex = shuffleOrder.lastIndex
1335
+ }
1336
+ } else {
1337
+ // Sequential navigation
1338
+ let prevIndex = currentIndex - 1
1339
+ if prevIndex >= 0 {
1340
+ newIndex = prevIndex
1341
+ } else if wrap {
1342
+ newIndex = tracks.count - 1
1343
+ }
1344
+ }
1345
+
1346
+ if let newIndex, newIndex != currentIndex {
1347
+ currentIndex = newIndex
1348
+ handleCurrentTrackChanged()
1349
+ }
1350
+ }
1351
+
1352
+ /**
1353
+ Remove a track from the queue.
1354
+
1355
+ - parameter index: The index of the track to remove.
1356
+ - throws: `TrackPlayerError.QueueError`
1357
+ */
1358
+ func remove(_ index: Int) throws {
1359
+ try throwIfQueueEmpty()
1360
+ try throwIfIndexInvalid(index: index)
1361
+ tracks.remove(at: index)
1362
+
1363
+ // Update shuffle order
1364
+ shuffleOrder.remove(from: index, to: index + 1)
1365
+
1366
+ if index == currentIndex {
1367
+ currentIndex = tracks.count > 0 ? currentIndex % tracks.count : -1
1368
+ handleCurrentTrackChanged()
1369
+ } else if index < currentIndex {
1370
+ currentIndex -= 1
1371
+ }
1372
+ }
1373
+
1374
+ /**
1375
+ Skip to a certain track in the queue.
1376
+
1377
+ - parameter index: The index of the track to skip to.
1378
+ - parameter playWhenReady: Optional, whether to start playback when the track is ready.
1379
+ - throws: `TrackPlayerError`
1380
+ */
1381
+ func skipTo(_ index: Int, playWhenReady: Bool? = nil) throws {
1382
+ try handlePlayWhenReady(playWhenReady) {
1383
+ if index == currentIndex {
1384
+ seekTo(0)
1385
+ } else {
1386
+ try skipTo(index)
1387
+ }
1388
+ }
1389
+ }
1390
+
1391
+ private func skipTo(_ index: Int) throws {
1392
+ try throwIfQueueEmpty()
1393
+ try throwIfIndexInvalid(index: index)
1394
+
1395
+ if index == currentIndex {
1396
+ if playWhenReady {
1397
+ replay()
1398
+ }
1399
+ } else {
1400
+ currentIndex = index
1401
+ handleCurrentTrackChanged()
1402
+ }
1403
+ }
1404
+
1405
+ /**
1406
+ Move a track in the queue from one position to another.
1407
+
1408
+ - parameter fromIndex: The index of the track to move.
1409
+ - parameter toIndex: The index to move the track to.
1410
+ - throws: `TrackPlayerError.QueueError`
1411
+ */
1412
+ func move(fromIndex: Int, toIndex: Int) throws {
1413
+ try throwIfQueueEmpty()
1414
+ try throwIfIndexInvalid(index: fromIndex, name: "fromIndex")
1415
+ try throwIfIndexInvalid(index: toIndex, name: "toIndex", max: Int.max)
1416
+
1417
+ // Mutate a copy and assign once to trigger didSet only once
1418
+ var newTracks = tracks
1419
+ let track = newTracks.remove(at: fromIndex)
1420
+ newTracks.insert(track, at: min(newTracks.count, toIndex))
1421
+ tracks = newTracks
1422
+
1423
+ if fromIndex == currentIndex {
1424
+ currentIndex = toIndex
1425
+ handleCurrentTrackChanged()
1426
+ }
1427
+ }
1428
+
1429
+ /**
1430
+ Remove all upcoming tracks, those returned by `next()`
1431
+ */
1432
+ func removeUpcomingTracks() {
1433
+ guard !tracks.isEmpty else { return }
1434
+ let nextIndex = currentIndex + 1
1435
+ guard nextIndex < tracks.count else { return }
1436
+ tracks.removeSubrange(nextIndex ..< tracks.count)
1437
+ }
1438
+
1439
+ /**
1440
+ Removes all tracks from queue
1441
+ */
1442
+ private func clearTracks() {
1443
+ guard currentIndex != -1 else { return }
1444
+ currentIndex = -1
1445
+ tracks.removeAll()
1446
+ queueSourcePath = nil
1447
+ handleCurrentTrackChanged()
1448
+ }
1449
+
1450
+ func replay() {
1451
+ seekTo(0) { [weak self] succeeded in
1452
+ if succeeded {
1453
+ Task { @MainActor in
1454
+ self?.play()
1455
+ }
1456
+ }
1457
+ }
1458
+ }
1459
+
1460
+ func handleCurrentTrackChanged() {
1461
+ // Reset end-of-track sleep timer when track changes
1462
+ sleepTimerManager.onTrackChanged()
1463
+
1464
+ // Cancel any pending retry and reset count when track changes
1465
+ pendingRetryTask?.cancel()
1466
+ pendingRetryTask = nil
1467
+ retryManager.reset()
1468
+
1469
+ // Clear any previous playback error when switching tracks
1470
+ if playbackError != nil {
1471
+ playbackError = nil
1472
+ }
1473
+
1474
+ let lastPosition = currentTime
1475
+ let shouldContinuePlayback = playWhenReady
1476
+ if let currentTrack {
1477
+ // Ensure playWhenReady is set before loading to preserve playback state
1478
+ playWhenReady = shouldContinuePlayback
1479
+
1480
+ // Reset playback values without updating, because that will happen in
1481
+ // the loadNowPlayingMetaValues call straight after:
1482
+ nowPlayingInfoController.setWithoutUpdate(keyValues: [
1483
+ MediaItemProperty.duration(nil),
1484
+ NowPlayingInfoProperty.playbackRate(nil),
1485
+ NowPlayingInfoProperty.elapsedPlaybackTime(nil),
1486
+ ])
1487
+ loadNowPlayingMetaValues()
1488
+
1489
+ // Load the track - resolve media URL first if resolver is configured
1490
+ guard let src = currentTrack.src else {
1491
+ logger.error("Failed to load track - no src")
1492
+ logger.error(" track.title: \(currentTrack.title)")
1493
+ logger.error(" track.url: \(currentTrack.url ?? "nil")")
1494
+ clearCurrentAVItem()
1495
+ playbackError = TrackPlayerError.PlaybackError.invalidSourceUrl("nil")
1496
+ return
1497
+ }
1498
+
1499
+ logger.debug("Loading track: \(currentTrack.title)")
1500
+ logger.debug(" track.url: \(currentTrack.url ?? "nil")")
1501
+ logger.debug(" track.src: \(src)")
1502
+
1503
+ // Check if it's already a full URL (http/https) or local file
1504
+ if src.hasPrefix("http://") || src.hasPrefix("https://") || src.hasPrefix("file://") {
1505
+ // Already a full URL, use directly (may still need transform for headers)
1506
+ resolveAndLoadMedia(src: src, track: currentTrack)
1507
+ } else {
1508
+ // Relative path - needs media URL resolution
1509
+ resolveAndLoadMedia(src: src, track: currentTrack)
1510
+ }
1511
+ } else {
1512
+ unloadAVPlayer()
1513
+ nowPlayingInfoController.clear()
1514
+ }
1515
+
1516
+ let eventData = PlaybackActiveTrackChangedEvent(
1517
+ lastIndex: lastIndex == -1 ? nil : Double(lastIndex),
1518
+ lastTrack: lastTrack,
1519
+ lastPosition: lastPosition,
1520
+ index: currentIndex == -1 ? nil : Double(currentIndex),
1521
+ track: currentTrack,
1522
+ )
1523
+ callbacks?.playerDidChangeActiveTrack(eventData)
1524
+ lastTrack = currentTrack
1525
+ lastIndex = currentIndex
1526
+ }
1527
+
1528
+ /// Resolves the media URL (applying transform if configured) and loads the player
1529
+ private func resolveAndLoadMedia(src: String, track: Track) {
1530
+ // If we have a resolver, use it asynchronously
1531
+ if let resolver = mediaUrlResolver {
1532
+ // Don't use @MainActor for the entire Task - this can cause deadlocks
1533
+ // when the JS callback needs to schedule work back on the main thread.
1534
+ // Instead, only hop to main thread when we need to access/modify state.
1535
+ Task {
1536
+ self.logger.debug("resolveAndLoadMedia: starting resolution for \(src)")
1537
+
1538
+ // Check on main thread that this track is still the current one
1539
+ let isCurrentTrack = await MainActor.run { self.currentTrack?.src == track.src }
1540
+ guard isCurrentTrack else {
1541
+ self.logger.debug("Track changed during media resolution, skipping load")
1542
+ return
1543
+ }
1544
+
1545
+ self.logger.debug("resolveAndLoadMedia: calling resolver...")
1546
+ let resolved = await resolver(src)
1547
+ self.logger.debug("resolveAndLoadMedia: resolver returned, resolved URL: \(resolved.url)")
1548
+ if let headers = resolved.headers {
1549
+ self.logger.debug(" headers: \(headers)")
1550
+ }
1551
+ if let userAgent = resolved.userAgent {
1552
+ self.logger.debug(" userAgent: \(userAgent)")
1553
+ }
1554
+
1555
+ // Load on main thread
1556
+ await MainActor.run {
1557
+ self.loadMediaWithResolvedUrl(resolved, track: track)
1558
+ }
1559
+ }
1560
+ } else {
1561
+ // No resolver, use src directly
1562
+ let resolved = MediaResolvedUrl(url: src, headers: nil, userAgent: nil)
1563
+ loadMediaWithResolvedUrl(resolved, track: track)
1564
+ }
1565
+ }
1566
+
1567
+ /// Loads the AVPlayer with a resolved media URL
1568
+ private func loadMediaWithResolvedUrl(_ resolved: MediaResolvedUrl, track _: Track) {
1569
+ guard let mediaUrl = URL(string: resolved.url) else {
1570
+ logger.error("Invalid media URL: \(resolved.url)")
1571
+ playbackError = TrackPlayerError.PlaybackError.invalidSourceUrl(resolved.url)
1572
+ return
1573
+ }
1574
+
1575
+ // Build URL options with headers if provided
1576
+ var options: [String: Any] = [:]
1577
+ if let headers = resolved.headers, !headers.isEmpty {
1578
+ options["AVURLAssetHTTPHeaderFieldsKey"] = headers
1579
+ }
1580
+
1581
+ let isLocalFile = mediaUrl.isFileURL
1582
+ url = isLocalFile ? URL(fileURLWithPath: mediaUrl.path) : mediaUrl
1583
+ urlOptions = options.isEmpty ? nil : options
1584
+
1585
+ logger.debug(" final playbackUrl: \(mediaUrl.absoluteString)")
1586
+ logger.debug(" isLocalFile: \(isLocalFile)")
1587
+
1588
+ loadAVPlayer()
1589
+ }
1590
+ }