react-native-audio-browser 0.2.0-next.8 → 0.2.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 (973) hide show
  1. package/AudioBrowser.podspec +1 -1
  2. package/README.md +2 -180
  3. package/android/build.gradle +1 -17
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +0 -15
  6. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +141 -401
  7. package/android/src/main/java/com/audiobrowser/Callbacks.kt +6 -4
  8. package/android/src/main/java/com/audiobrowser/Service.kt +18 -67
  9. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +178 -442
  10. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +4 -41
  11. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
  12. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +97 -109
  13. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
  14. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +8 -40
  15. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +46 -40
  16. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +1 -4
  17. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +1 -18
  18. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +3 -15
  19. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +134 -422
  20. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +404 -248
  21. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +59 -0
  22. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +5 -25
  23. package/android/src/main/java/com/audiobrowser/player/Player.kt +582 -469
  24. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +67 -190
  25. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +53 -118
  26. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +3 -37
  27. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +40 -85
  28. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +0 -24
  29. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +300 -23
  30. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +23 -13
  31. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
  32. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +3 -4
  33. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +1 -2
  34. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +72 -0
  35. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +36 -0
  36. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +111 -6
  37. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +8 -22
  38. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +80 -112
  39. package/android/src/main/res/values/strings.xml +0 -4
  40. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +0 -4
  41. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +2 -1
  42. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +0 -72
  43. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +146 -0
  44. package/ios/Browser/BrowserConfig.swift +11 -41
  45. package/ios/Browser/BrowserManager+URLResolution.swift +93 -213
  46. package/ios/Browser/BrowserManager.swift +110 -303
  47. package/ios/Browser/BrowserPathHelper.swift +3 -32
  48. package/ios/Browser/JsonModels.swift +66 -287
  49. package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
  50. package/ios/CarPlay/CarPlayController.swift +149 -739
  51. package/ios/CarPlay/CarPlayImageLoader.swift +8 -57
  52. package/ios/CarPlay/CarPlayListItemFactory.swift +35 -44
  53. package/ios/CarPlay/CarPlayNowPlayingManager.swift +36 -180
  54. package/ios/CarPlay/RNABAudioBrowser.h +10 -15
  55. package/ios/CarPlay/RNABAudioBrowser.m +14 -15
  56. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +0 -2
  57. package/ios/CarPlay/RNABMediaIntentHandler.swift +43 -53
  58. package/ios/CarPlay/Track+CarPlay.swift +63 -0
  59. package/ios/Extension/Capability+RemoteCommand.swift +9 -7
  60. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  61. package/ios/Extension/NavigationError+Conversion.swift +1 -8
  62. package/ios/Extension/ResolvedTrack+Copying.swift +4 -10
  63. package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
  64. package/ios/Extension/Track+AVPlayer.swift +4 -4
  65. package/ios/Extension/Track+Copying.swift +3 -9
  66. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  67. package/ios/HybridAudioBrowser.swift +173 -751
  68. package/ios/Model/NitroTypeStubs.swift +224 -299
  69. package/ios/Model/PlayerUpdateOptions.swift +23 -23
  70. package/ios/Model/RemoteCommand.swift +6 -24
  71. package/ios/Model/TrackPlayerError.swift +18 -82
  72. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +9 -0
  73. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +121 -99
  74. package/ios/Observer/PlayerItemNotificationObserver.swift +5 -45
  75. package/ios/Observer/PlayerItemPropertyObserver.swift +4 -27
  76. package/ios/Observer/PlayerTimeObserver.swift +53 -3
  77. package/ios/Option/SessionCategories.swift +11 -34
  78. package/ios/Player/LoadSeekCoordinator.swift +1 -16
  79. package/ios/Player/MediaLoader.swift +11 -31
  80. package/ios/Player/NowPlayingUpdater.swift +26 -119
  81. package/ios/Player/PlaybackCoordinator.swift +51 -285
  82. package/ios/Player/PlaybackCoordinatorCallbacks.swift +1 -6
  83. package/ios/Player/PlaybackEffectHandler.swift +9 -19
  84. package/ios/Player/PlaybackErrorHandler.swift +13 -97
  85. package/ios/Player/PlaybackProgressUpdateManager.swift +68 -0
  86. package/ios/Player/PlaybackStateMachine.swift +13 -18
  87. package/ios/Player/PlayingStateManager.swift +2 -3
  88. package/ios/Player/QueueManager.swift +61 -67
  89. package/ios/Player/RetryManager.swift +21 -98
  90. package/ios/Player/SleepTimerHandling.swift +0 -8
  91. package/ios/Player/SleepTimerManager.swift +11 -72
  92. package/ios/RemoteCommand/RemoteCommandController.swift +21 -40
  93. package/ios/Tests/BrowserPathHelperTests.swift +0 -28
  94. package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
  95. package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
  96. package/ios/Tests/LoadSeekCoordinatorTests.swift +7 -40
  97. package/ios/Tests/MediaLoaderTests.swift +20 -32
  98. package/ios/Tests/PlaybackCoordinatorTests.swift +13 -787
  99. package/ios/Tests/PlaybackErrorHandlerTests.swift +46 -380
  100. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +166 -0
  101. package/ios/Tests/PlaybackStateMachineTests.swift +8 -33
  102. package/ios/Tests/QueueManagerTests.swift +18 -149
  103. package/ios/Tests/ResolvedTrackCopyingTests.swift +8 -15
  104. package/ios/Tests/Support/TestTypes.swift +20 -61
  105. package/ios/Tests/TrackSelectorTests.swift +15 -15
  106. package/ios/TrackPlayer.swift +58 -380
  107. package/ios/TrackPlayerCallbacks.swift +44 -5
  108. package/ios/TrackSelector.swift +5 -5
  109. package/ios/Util/ArtworkImageFetcher.swift +2 -4
  110. package/ios/Util/NetworkMonitor.swift +3 -7
  111. package/ios/Util/OnceValue.swift +0 -34
  112. package/lib/commonjs/AudioBrowser.js +11 -0
  113. package/lib/commonjs/AudioBrowser.js.map +1 -1
  114. package/lib/commonjs/features/browser.js +158 -59
  115. package/lib/commonjs/features/browser.js.map +1 -1
  116. package/lib/commonjs/features/equalizer.js +1 -1
  117. package/lib/commonjs/features/errors.js +5 -37
  118. package/lib/commonjs/features/errors.js.map +1 -1
  119. package/lib/commonjs/features/favorites.js +1 -1
  120. package/lib/commonjs/features/index.js +0 -22
  121. package/lib/commonjs/features/index.js.map +1 -1
  122. package/lib/commonjs/features/metadata.js +3 -3
  123. package/lib/commonjs/features/metadata.js.map +1 -1
  124. package/lib/commonjs/features/network.js +1 -1
  125. package/lib/commonjs/features/nowPlaying.js +1 -36
  126. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  127. package/lib/commonjs/features/output.js +23 -37
  128. package/lib/commonjs/features/output.js.map +1 -1
  129. package/lib/commonjs/features/playback/controls.js +0 -9
  130. package/lib/commonjs/features/playback/controls.js.map +1 -1
  131. package/lib/commonjs/features/playback/index.js +0 -11
  132. package/lib/commonjs/features/playback/index.js.map +1 -1
  133. package/lib/commonjs/features/playback/playWhenReady.js +1 -1
  134. package/lib/commonjs/features/playback/playing.js +1 -1
  135. package/lib/commonjs/features/playback/progress.js +13 -29
  136. package/lib/commonjs/features/playback/progress.js.map +1 -1
  137. package/lib/commonjs/features/playback/state.js +1 -1
  138. package/lib/commonjs/features/playback/volume.js +2 -2
  139. package/lib/commonjs/features/player/options.js +29 -79
  140. package/lib/commonjs/features/player/options.js.map +1 -1
  141. package/lib/commonjs/features/player/setup.js +3 -256
  142. package/lib/commonjs/features/player/setup.js.map +1 -1
  143. package/lib/commonjs/features/queue/activeTrack.js +1 -1
  144. package/lib/commonjs/features/queue/queue.js +5 -12
  145. package/lib/commonjs/features/queue/queue.js.map +1 -1
  146. package/lib/commonjs/features/queue/repeatMode.js +1 -1
  147. package/lib/commonjs/features/queue/shuffle.js +1 -1
  148. package/lib/commonjs/features/rating.js +2 -0
  149. package/lib/commonjs/features/rating.js.map +1 -0
  150. package/lib/commonjs/features/remoteControls.js +104 -14
  151. package/lib/commonjs/features/remoteControls.js.map +1 -1
  152. package/lib/commonjs/features/sleepTimer.js +5 -10
  153. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  154. package/lib/commonjs/native.js +0 -5
  155. package/lib/commonjs/native.js.map +1 -1
  156. package/lib/commonjs/native.web.js +1 -4
  157. package/lib/commonjs/native.web.js.map +1 -1
  158. package/lib/commonjs/types/player.js +2 -0
  159. package/lib/commonjs/types/player.js.map +1 -0
  160. package/lib/commonjs/utils/LazyNativeEmitter.js +8 -8
  161. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  162. package/lib/commonjs/utils/NativeUpdatedValue.js +3 -0
  163. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  164. package/lib/commonjs/web/NativeAudioBrowser.js +124 -301
  165. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  166. package/lib/commonjs/web/SimpleRouter.test.js +174 -0
  167. package/lib/commonjs/web/SimpleRouter.test.js.map +1 -0
  168. package/lib/commonjs/web/TrackPlayer/Player.js +26 -90
  169. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  170. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +293 -0
  171. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  172. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  173. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  174. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +3 -34
  175. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  176. package/lib/commonjs/web/TrackPlayer/index.js +5 -13
  177. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  178. package/lib/commonjs/web/browser/BrowserManager.js +50 -176
  179. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  180. package/lib/commonjs/web/browser/NavigationErrorManager.js +1 -3
  181. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  182. package/lib/commonjs/web/browser/SearchManager.js +9 -11
  183. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  184. package/lib/commonjs/web/http/HttpClient.js +23 -4
  185. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  186. package/lib/commonjs/web/http/RequestConfigBuilder.js +58 -107
  187. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  188. package/lib/commonjs/web/player/NowPlayingManager.js +5 -6
  189. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  190. package/lib/commonjs/web/player/OptionsManager.js +17 -9
  191. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  192. package/lib/module/AudioBrowser.js +1 -4
  193. package/lib/module/AudioBrowser.js.map +1 -1
  194. package/lib/module/features/browser.js +156 -53
  195. package/lib/module/features/browser.js.map +1 -1
  196. package/lib/module/features/equalizer.js +1 -1
  197. package/lib/module/features/errors.js +5 -37
  198. package/lib/module/features/errors.js.map +1 -1
  199. package/lib/module/features/favorites.js +1 -1
  200. package/lib/module/features/index.js +0 -2
  201. package/lib/module/features/index.js.map +1 -1
  202. package/lib/module/features/metadata.js +3 -3
  203. package/lib/module/features/metadata.js.map +1 -1
  204. package/lib/module/features/network.js +1 -1
  205. package/lib/module/features/nowPlaying.js +1 -34
  206. package/lib/module/features/nowPlaying.js.map +1 -1
  207. package/lib/module/features/output.js +19 -32
  208. package/lib/module/features/output.js.map +1 -1
  209. package/lib/module/features/playback/controls.js +0 -8
  210. package/lib/module/features/playback/controls.js.map +1 -1
  211. package/lib/module/features/playback/index.js +0 -1
  212. package/lib/module/features/playback/index.js.map +1 -1
  213. package/lib/module/features/playback/playWhenReady.js +1 -1
  214. package/lib/module/features/playback/playing.js +1 -1
  215. package/lib/module/features/playback/progress.js +13 -29
  216. package/lib/module/features/playback/progress.js.map +1 -1
  217. package/lib/module/features/playback/state.js +1 -1
  218. package/lib/module/features/playback/volume.js +2 -2
  219. package/lib/module/features/player/options.js +29 -79
  220. package/lib/module/features/player/options.js.map +1 -1
  221. package/lib/module/features/player/setup.js +3 -256
  222. package/lib/module/features/player/setup.js.map +1 -1
  223. package/lib/module/features/queue/activeTrack.js +1 -1
  224. package/lib/module/features/queue/queue.js +5 -12
  225. package/lib/module/features/queue/queue.js.map +1 -1
  226. package/lib/module/features/queue/repeatMode.js +1 -1
  227. package/lib/module/features/queue/shuffle.js +1 -1
  228. package/lib/module/features/rating.js +2 -0
  229. package/lib/module/features/rating.js.map +1 -0
  230. package/lib/module/features/remoteControls.js +103 -13
  231. package/lib/module/features/remoteControls.js.map +1 -1
  232. package/lib/module/features/sleepTimer.js +5 -10
  233. package/lib/module/features/sleepTimer.js.map +1 -1
  234. package/lib/module/native.js +0 -5
  235. package/lib/module/native.js.map +1 -1
  236. package/lib/module/native.web.js +1 -4
  237. package/lib/module/native.web.js.map +1 -1
  238. package/lib/module/types/player.js +2 -0
  239. package/lib/module/types/player.js.map +1 -0
  240. package/lib/module/utils/LazyNativeEmitter.js +8 -8
  241. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  242. package/lib/module/utils/NativeUpdatedValue.js +3 -0
  243. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  244. package/lib/module/web/NativeAudioBrowser.js +125 -302
  245. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  246. package/lib/module/web/SimpleRouter.test.js +174 -0
  247. package/lib/module/web/SimpleRouter.test.js.map +1 -0
  248. package/lib/module/web/TrackPlayer/Player.js +26 -90
  249. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  250. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +288 -0
  251. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  252. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  253. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  254. package/lib/module/web/TrackPlayer/SleepTimer.js +3 -34
  255. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  256. package/lib/module/web/TrackPlayer/index.js +1 -2
  257. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  258. package/lib/module/web/browser/BrowserManager.js +50 -176
  259. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  260. package/lib/module/web/browser/NavigationErrorManager.js +1 -3
  261. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  262. package/lib/module/web/browser/SearchManager.js +9 -11
  263. package/lib/module/web/browser/SearchManager.js.map +1 -1
  264. package/lib/module/web/http/HttpClient.js +23 -4
  265. package/lib/module/web/http/HttpClient.js.map +1 -1
  266. package/lib/module/web/http/RequestConfigBuilder.js +58 -107
  267. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  268. package/lib/module/web/player/NowPlayingManager.js +5 -7
  269. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  270. package/lib/module/web/player/OptionsManager.js +17 -9
  271. package/lib/module/web/player/OptionsManager.js.map +1 -1
  272. package/lib/typescript/src/AudioBrowser.d.ts +1 -0
  273. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
  274. package/lib/typescript/src/features/browser.d.ts +1 -40
  275. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  276. package/lib/typescript/src/features/equalizer.d.ts +1 -1
  277. package/lib/typescript/src/features/errors.d.ts +6 -61
  278. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  279. package/lib/typescript/src/features/favorites.d.ts +1 -1
  280. package/lib/typescript/src/features/index.d.ts +0 -2
  281. package/lib/typescript/src/features/index.d.ts.map +1 -1
  282. package/lib/typescript/src/features/metadata.d.ts +7 -9
  283. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  284. package/lib/typescript/src/features/network.d.ts +1 -1
  285. package/lib/typescript/src/features/nowPlaying.d.ts +1 -28
  286. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  287. package/lib/typescript/src/features/output.d.ts +18 -28
  288. package/lib/typescript/src/features/output.d.ts.map +1 -1
  289. package/lib/typescript/src/features/playback/controls.d.ts +0 -5
  290. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  291. package/lib/typescript/src/features/playback/index.d.ts +0 -1
  292. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  293. package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
  294. package/lib/typescript/src/features/playback/playing.d.ts +1 -1
  295. package/lib/typescript/src/features/playback/progress.d.ts +1 -4
  296. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  297. package/lib/typescript/src/features/playback/state.d.ts +1 -1
  298. package/lib/typescript/src/features/playback/volume.d.ts +2 -2
  299. package/lib/typescript/src/features/player/options.d.ts +127 -176
  300. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  301. package/lib/typescript/src/features/player/setup.d.ts +167 -213
  302. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  303. package/lib/typescript/src/features/queue/activeTrack.d.ts +1 -1
  304. package/lib/typescript/src/features/queue/queue.d.ts +4 -11
  305. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  306. package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
  307. package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
  308. package/lib/typescript/src/features/rating.d.ts +14 -0
  309. package/lib/typescript/src/features/rating.d.ts.map +1 -0
  310. package/lib/typescript/src/features/remoteControls.d.ts +35 -23
  311. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  312. package/lib/typescript/src/features/sleepTimer.d.ts +4 -19
  313. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  314. package/lib/typescript/src/index.d.ts.map +1 -1
  315. package/lib/typescript/src/native.d.ts +2 -1
  316. package/lib/typescript/src/native.d.ts.map +1 -1
  317. package/lib/typescript/src/native.web.d.ts +3 -0
  318. package/lib/typescript/src/native.web.d.ts.map +1 -0
  319. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +225 -17
  320. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  321. package/lib/typescript/src/types/browser-native.d.ts +3 -9
  322. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  323. package/lib/typescript/src/types/browser-nodes.d.ts +13 -145
  324. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  325. package/lib/typescript/src/types/browser.d.ts +85 -349
  326. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  327. package/lib/typescript/src/types/player.d.ts +64 -0
  328. package/lib/typescript/src/types/player.d.ts.map +1 -0
  329. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +6 -8
  330. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  331. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +2 -0
  332. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  333. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  334. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +188 -0
  335. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -0
  336. package/lib/typescript/src/web/SimpleRouter.d.ts +40 -0
  337. package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -0
  338. package/lib/typescript/src/web/SimpleRouter.test.d.ts +2 -0
  339. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +1 -0
  340. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +11 -0
  341. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +1 -0
  342. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +59 -0
  343. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +1 -0
  344. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +39 -0
  345. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +1 -0
  346. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +6 -0
  347. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +1 -0
  348. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +4 -0
  349. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +1 -0
  350. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +34 -0
  351. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +1 -0
  352. package/lib/typescript/src/web/TrackPlayer/State.d.ts +13 -0
  353. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +1 -0
  354. package/lib/typescript/src/web/TrackPlayer/index.d.ts +5 -0
  355. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +1 -0
  356. package/lib/typescript/src/web/browser/BrowserManager.d.ts +154 -0
  357. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +1 -0
  358. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +42 -0
  359. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +1 -0
  360. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +40 -0
  361. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +1 -0
  362. package/lib/typescript/src/web/browser/SearchManager.d.ts +22 -0
  363. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +1 -0
  364. package/lib/typescript/src/web/http/HttpClient.d.ts +25 -0
  365. package/lib/typescript/src/web/http/HttpClient.d.ts.map +1 -0
  366. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +98 -0
  367. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +1 -0
  368. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +34 -0
  369. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +1 -0
  370. package/lib/typescript/src/web/player/OptionsManager.d.ts +32 -0
  371. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +1 -0
  372. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +69 -0
  373. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +1 -0
  374. package/lib/typescript/src/web/util/shuffle.d.ts +8 -0
  375. package/lib/typescript/src/web/util/shuffle.d.ts.map +1 -0
  376. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +2 -4
  377. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +10 -24
  378. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  379. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +20 -10
  380. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +86 -0
  381. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +1 -33
  382. package/nitrogen/generated/android/c++/JBrowseResult.hpp +0 -5
  383. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  384. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +0 -6
  385. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -3
  386. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +0 -6
  387. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +147 -0
  388. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +0 -8
  389. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +0 -6
  390. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +0 -6
  391. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +80 -0
  392. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +10 -0
  393. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -14
  394. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +0 -2
  395. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +0 -6
  396. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +0 -2
  397. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +87 -0
  398. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  399. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +0 -6
  400. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +0 -6
  401. package/nitrogen/generated/android/c++/JHeartRating.hpp +57 -0
  402. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +221 -245
  403. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +22 -25
  404. package/nitrogen/generated/android/c++/JImageRowItem.hpp +3 -33
  405. package/nitrogen/generated/android/c++/{JOutput.hpp → JIosOutput.hpp} +15 -15
  406. package/nitrogen/generated/android/c++/JIosOutputType.hpp +85 -0
  407. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +1 -33
  408. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +28 -61
  409. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +9 -20
  410. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +24 -21
  411. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +0 -6
  412. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +20 -10
  413. package/nitrogen/generated/android/c++/{JRemoteButton.hpp → JNotificationButton.hpp} +20 -20
  414. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +94 -0
  415. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +17 -3
  416. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +3 -7
  417. package/nitrogen/generated/android/c++/JOptions.hpp +14 -19
  418. package/nitrogen/generated/android/c++/{JNativeAndroidSetupOptions.hpp → JPartialAndroidSetupPlayerOptions.hpp} +10 -10
  419. package/nitrogen/generated/android/c++/{JNativeIOSSetupOptions.hpp → JPartialIOSSetupPlayerOptions.hpp} +10 -10
  420. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +96 -0
  421. package/nitrogen/generated/android/c++/JPercentageRating.hpp +57 -0
  422. package/nitrogen/generated/android/c++/JPlayback.hpp +0 -2
  423. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +0 -6
  424. package/nitrogen/generated/android/c++/JPlaybackError.hpp +3 -18
  425. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +0 -2
  426. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  427. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
  428. package/nitrogen/generated/android/c++/JRatingType.hpp +73 -0
  429. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +66 -0
  430. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +5 -23
  431. package/nitrogen/generated/android/c++/JRetryConfig.hpp +7 -11
  432. package/nitrogen/generated/android/c++/JSearchMode.hpp +9 -27
  433. package/nitrogen/generated/android/c++/JSearchParams.hpp +3 -9
  434. package/nitrogen/generated/android/c++/JStarRating.hpp +57 -0
  435. package/nitrogen/generated/android/c++/{JGateEvent.hpp → JThumbsRating.hpp} +15 -16
  436. package/nitrogen/generated/android/c++/JTrack.hpp +5 -23
  437. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +0 -6
  438. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +1 -14
  439. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +105 -0
  440. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +34 -0
  441. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +105 -0
  442. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +26 -0
  443. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +75 -0
  444. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  445. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +9 -3
  446. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +50 -0
  447. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +4 -10
  448. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  449. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  450. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt} +12 -12
  451. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_Output.kt → Func_void_IosOutput.kt} +9 -9
  452. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_GateEvent.kt → Func_void_RemoteSetRatingEvent.kt} +9 -9
  453. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  454. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Gate.kt → HeartRating.kt} +6 -9
  455. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +109 -103
  456. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +3 -24
  457. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Output.kt → IosOutput.kt} +6 -6
  458. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +32 -0
  459. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +4 -10
  460. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +6 -18
  461. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  462. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  463. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +1 -3
  464. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +9 -3
  465. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → NotificationButton.kt} +8 -5
  466. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +50 -0
  467. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +6 -3
  468. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +3 -6
  469. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  470. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeAndroidSetupOptions.kt → PartialAndroidSetupPlayerOptions.kt} +5 -5
  471. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeIOSSetupOptions.kt → PartialIOSSetupPlayerOptions.kt} +5 -5
  472. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +47 -0
  473. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateDecision.kt → PercentageRating.kt} +6 -9
  474. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +3 -12
  475. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  476. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  477. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateReason.kt → RatingType.kt} +10 -5
  478. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ArtworkVariants.kt → RemoteSetRatingEvent.kt} +6 -9
  479. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +3 -12
  480. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +4 -7
  481. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +6 -12
  482. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +3 -6
  483. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateEvent.kt → StarRating.kt} +6 -6
  484. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → ThumbsRating.kt} +6 -6
  485. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +3 -12
  486. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +4 -7
  487. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +53 -0
  488. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +77 -0
  489. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_RemoteButtonLayout.kt → Variant_NullType_NotificationButtonLayout.kt} +9 -9
  490. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +28 -139
  491. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +489 -1125
  492. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +45 -66
  493. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +118 -176
  494. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  495. package/nitrogen/generated/ios/swift/AndroidOptions.swift +22 -12
  496. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +119 -0
  497. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +1 -95
  498. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  499. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +4 -17
  500. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +68 -0
  501. package/nitrogen/generated/ios/swift/{Func_void_Output.swift → Func_void_IosOutput.swift} +10 -10
  502. package/nitrogen/generated/ios/swift/{Func_void_GateEvent.swift → Func_void_RemoteSetRatingEvent.swift} +10 -10
  503. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  504. package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_GateDecision__.swift → Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift} +17 -17
  505. package/nitrogen/generated/ios/swift/HeartRating.swift +29 -0
  506. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +14 -20
  507. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +197 -230
  508. package/nitrogen/generated/ios/swift/ImageRowItem.swift +2 -121
  509. package/nitrogen/generated/ios/swift/{Output.swift → IosOutput.swift} +7 -7
  510. package/nitrogen/generated/ios/swift/IosOutputType.swift +76 -0
  511. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +1 -107
  512. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +22 -161
  513. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  514. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +25 -12
  515. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +0 -8
  516. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +41 -12
  517. package/nitrogen/generated/ios/swift/{RemoteButton.swift → NotificationButton.swift} +10 -10
  518. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +92 -0
  519. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +48 -1
  520. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +1 -19
  521. package/nitrogen/generated/ios/swift/Options.swift +4 -10
  522. package/nitrogen/generated/ios/swift/{NativeAndroidSetupOptions.swift → PartialAndroidSetupPlayerOptions.swift} +5 -5
  523. package/nitrogen/generated/ios/swift/{NativeIOSSetupOptions.swift → PartialIOSSetupPlayerOptions.swift} +5 -5
  524. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +101 -0
  525. package/nitrogen/generated/ios/swift/PercentageRating.swift +29 -0
  526. package/nitrogen/generated/ios/swift/PlaybackError.swift +2 -43
  527. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  528. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
  529. package/nitrogen/generated/ios/swift/RatingType.swift +60 -0
  530. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +58 -0
  531. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +8 -74
  532. package/nitrogen/generated/ios/swift/RetryConfig.swift +4 -35
  533. package/nitrogen/generated/ios/swift/SearchMode.swift +12 -36
  534. package/nitrogen/generated/ios/swift/SearchParams.swift +2 -7
  535. package/nitrogen/generated/ios/swift/StarRating.swift +29 -0
  536. package/nitrogen/generated/ios/swift/ThumbsRating.swift +29 -0
  537. package/nitrogen/generated/ios/swift/Track.swift +8 -74
  538. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +1 -60
  539. package/nitrogen/generated/ios/swift/UpdateOptions.swift +143 -0
  540. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +20 -0
  541. package/nitrogen/generated/ios/swift/{Variant_NullType_RemoteButtonLayout.swift → Variant_NullType_NotificationButtonLayout.swift} +3 -3
  542. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  543. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +19 -8
  544. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +109 -0
  545. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +2 -10
  546. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  547. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +2 -0
  548. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +5 -6
  549. package/nitrogen/generated/shared/c++/{GateEvent.hpp → HeartRating.hpp} +17 -18
  550. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +18 -21
  551. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +35 -44
  552. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +2 -33
  553. package/nitrogen/generated/shared/c++/{Output.hpp → IosOutput.hpp} +18 -18
  554. package/nitrogen/generated/shared/c++/IosOutputType.hpp +112 -0
  555. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +2 -10
  556. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +15 -31
  557. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  558. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +7 -9
  559. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +0 -8
  560. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +19 -8
  561. package/nitrogen/generated/shared/c++/{RemoteButton.hpp → NotificationButton.hpp} +25 -25
  562. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +102 -0
  563. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +19 -3
  564. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +2 -6
  565. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  566. package/nitrogen/generated/shared/c++/{NativeAndroidSetupOptions.hpp → PartialAndroidSetupPlayerOptions.hpp} +11 -11
  567. package/nitrogen/generated/shared/c++/{NativeIOSSetupOptions.hpp → PartialIOSSetupPlayerOptions.hpp} +11 -11
  568. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +104 -0
  569. package/nitrogen/generated/shared/c++/{FavoriteConfig.hpp → PercentageRating.hpp} +17 -18
  570. package/nitrogen/generated/shared/c++/PlaybackError.hpp +3 -18
  571. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  572. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
  573. package/nitrogen/generated/shared/c++/RatingType.hpp +96 -0
  574. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +94 -0
  575. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +5 -24
  576. package/nitrogen/generated/shared/c++/RetryConfig.hpp +6 -10
  577. package/nitrogen/generated/shared/c++/SearchMode.hpp +15 -39
  578. package/nitrogen/generated/shared/c++/SearchParams.hpp +2 -9
  579. package/nitrogen/generated/shared/c++/{Gate.hpp → StarRating.hpp} +16 -21
  580. package/nitrogen/generated/shared/c++/{GateDecision.hpp → ThumbsRating.hpp} +17 -23
  581. package/nitrogen/generated/shared/c++/Track.hpp +5 -24
  582. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +2 -6
  583. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +111 -0
  584. package/package.json +5 -12
  585. package/src/AudioBrowser.ts +1 -4
  586. package/src/features/browser.ts +201 -58
  587. package/src/features/equalizer.ts +1 -1
  588. package/src/features/errors.ts +5 -71
  589. package/src/features/favorites.ts +1 -1
  590. package/src/features/index.ts +0 -2
  591. package/src/features/metadata.ts +15 -9
  592. package/src/features/network.ts +1 -1
  593. package/src/features/nowPlaying.ts +1 -37
  594. package/src/features/output.ts +22 -35
  595. package/src/features/playback/controls.ts +0 -8
  596. package/src/features/playback/index.ts +0 -1
  597. package/src/features/playback/playWhenReady.ts +1 -1
  598. package/src/features/playback/playing.ts +1 -1
  599. package/src/features/playback/progress.ts +13 -32
  600. package/src/features/playback/state.ts +1 -1
  601. package/src/features/playback/volume.ts +2 -2
  602. package/src/features/player/options.ts +110 -217
  603. package/src/features/player/setup.ts +175 -397
  604. package/src/features/queue/activeTrack.ts +1 -1
  605. package/src/features/queue/queue.ts +6 -17
  606. package/src/features/queue/repeatMode.ts +1 -1
  607. package/src/features/queue/shuffle.ts +1 -1
  608. package/src/features/rating.ts +17 -0
  609. package/src/features/remoteControls.ts +115 -13
  610. package/src/features/sleepTimer.ts +5 -24
  611. package/src/native.ts +0 -5
  612. package/src/native.web.ts +1 -4
  613. package/src/specs/audio-browser.nitro.ts +41 -131
  614. package/src/types/browser-native.ts +6 -19
  615. package/src/types/browser-nodes.ts +13 -160
  616. package/src/types/browser.ts +89 -377
  617. package/src/types/player.ts +69 -0
  618. package/src/utils/LazyNativeEmitter.ts +8 -9
  619. package/src/utils/NativeUpdatedValue.ts +2 -0
  620. package/src/web/NativeAudioBrowser.ts +158 -365
  621. package/src/web/TrackPlayer/Player.ts +39 -113
  622. package/src/web/TrackPlayer/PlaylistPlayer.ts +346 -0
  623. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  624. package/src/web/TrackPlayer/SleepTimer.ts +3 -38
  625. package/src/web/TrackPlayer/index.ts +1 -2
  626. package/src/web/browser/BrowserManager.ts +62 -231
  627. package/src/web/browser/NavigationErrorManager.ts +1 -3
  628. package/src/web/browser/SearchManager.ts +15 -11
  629. package/src/web/http/HttpClient.ts +35 -5
  630. package/src/web/http/RequestConfigBuilder.ts +63 -120
  631. package/src/web/player/NowPlayingManager.ts +5 -6
  632. package/src/web/player/OptionsManager.ts +18 -12
  633. package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +0 -37
  634. package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +0 -34
  635. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +0 -299
  636. package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +0 -79
  637. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +0 -42
  638. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +0 -35
  639. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +0 -172
  640. package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +0 -153
  641. package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +0 -141
  642. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +0 -347
  643. package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +0 -129
  644. package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +0 -85
  645. package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +0 -56
  646. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +0 -20
  647. package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +0 -130
  648. package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +0 -80
  649. package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +0 -50
  650. package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +0 -81
  651. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +0 -141
  652. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +0 -37
  653. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +0 -41
  654. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +0 -209
  655. package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +0 -161
  656. package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +0 -28
  657. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +0 -24
  658. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +0 -49
  659. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +0 -36
  660. package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +0 -211
  661. package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +0 -58
  662. package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +0 -14
  663. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +0 -165
  664. package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +0 -46
  665. package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +0 -39
  666. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +0 -114
  667. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +0 -141
  668. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +0 -177
  669. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +0 -55
  670. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +0 -94
  671. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +0 -203
  672. package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +0 -56
  673. package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +0 -216
  674. package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +0 -45
  675. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +0 -442
  676. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +0 -190
  677. package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +0 -198
  678. package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +0 -137
  679. package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +0 -36
  680. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +0 -268
  681. package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +0 -68
  682. package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +0 -40
  683. package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +0 -193
  684. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +0 -107
  685. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +0 -73
  686. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +0 -75
  687. package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +0 -18
  688. package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +0 -163
  689. package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +0 -34
  690. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +0 -28
  691. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +0 -53
  692. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +0 -58
  693. package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +0 -57
  694. package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +0 -40
  695. package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +0 -34
  696. package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +0 -50
  697. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +0 -63
  698. package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +0 -35
  699. package/android/src/test/resources/certs/isrg-root-x1.pem +0 -31
  700. package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
  701. package/android/src/test/resources/certs/letsencrypt-r13.pem +0 -29
  702. package/android/src/test/resources/certs/stationplaylist-leaf.pem +0 -34
  703. package/ios/Browser/MediaResolveComposer.swift +0 -114
  704. package/ios/Browser/SearchDrillIn.swift +0 -44
  705. package/ios/Browser/SectionScope.swift +0 -35
  706. package/ios/Browser/TabBarEntries.swift +0 -15
  707. package/ios/CarPlay/CPInterfaceController+Safe.swift +0 -126
  708. package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
  709. package/ios/CarPlay/RNABMediaAddHandler.swift +0 -75
  710. package/ios/CarPlay/RNABMediaAffinityHandler.swift +0 -69
  711. package/ios/Extension/PlayerCapabilities+Favorite.swift +0 -20
  712. package/ios/Extension/RequestConfig+Copying.swift +0 -31
  713. package/ios/Extension/Variant+Artwork.swift +0 -49
  714. package/ios/NowPlayingInfo/SilentAudioPrimer.swift +0 -73
  715. package/ios/Player/AirPlayStallJudgement.swift +0 -25
  716. package/ios/Player/EndOfTrackJudgement.swift +0 -32
  717. package/ios/Player/MediaIntentCriteria.swift +0 -139
  718. package/ios/Player/PersistedPlaybackState.swift +0 -11
  719. package/ios/Player/PlaybackStateStore.swift +0 -27
  720. package/ios/Player/PlaybackTimer.swift +0 -61
  721. package/ios/Player/VolumeFader.swift +0 -77
  722. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +0 -47
  723. package/ios/Tests/AirPlayStallJudgementTests.swift +0 -52
  724. package/ios/Tests/EndOfTrackJudgementTests.swift +0 -35
  725. package/ios/Tests/JsonModelsTests.swift +0 -58
  726. package/ios/Tests/MediaIntentCriteriaTests.swift +0 -170
  727. package/ios/Tests/MediaLoaderAssetOptionsTests.swift +0 -46
  728. package/ios/Tests/MediaResolveTests.swift +0 -126
  729. package/ios/Tests/OnceValueTests.swift +0 -79
  730. package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
  731. package/ios/Tests/PlaybackTimerTests.swift +0 -55
  732. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  733. package/ios/Tests/RemoteCommandControllerTests.swift +0 -156
  734. package/ios/Tests/RemoteCommandTests.swift +0 -67
  735. package/ios/Tests/RetryManagerTests.swift +0 -89
  736. package/ios/Tests/SearchDrillInTests.swift +0 -63
  737. package/ios/Tests/SectionScopeTests.swift +0 -82
  738. package/ios/Tests/SleepTimerManagerTests.swift +0 -107
  739. package/ios/Tests/Support/ManualSleepTimerScheduler.swift +0 -47
  740. package/ios/Tests/TabBarEntriesTests.swift +0 -71
  741. package/lib/commonjs/features/browser-config.js +0 -227
  742. package/lib/commonjs/features/browser-config.js.map +0 -1
  743. package/lib/commonjs/features/carConnection.js +0 -42
  744. package/lib/commonjs/features/carConnection.js.map +0 -1
  745. package/lib/commonjs/features/gate.js +0 -149
  746. package/lib/commonjs/features/gate.js.map +0 -1
  747. package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -86
  748. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +0 -1
  749. package/lib/commonjs/features/player/validateOptions.js +0 -24
  750. package/lib/commonjs/features/player/validateOptions.js.map +0 -1
  751. package/lib/commonjs/utils/artwork.js +0 -31
  752. package/lib/commonjs/utils/artwork.js.map +0 -1
  753. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +0 -71
  754. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  755. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +0 -34
  756. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  757. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +0 -21
  758. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  759. package/lib/commonjs/web/TrackPlayer/QueueManager.js +0 -273
  760. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +0 -1
  761. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +0 -158
  762. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +0 -1
  763. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +0 -75
  764. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +0 -1
  765. package/lib/commonjs/web/browser/assertBrowsePageShape.js +0 -22
  766. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +0 -1
  767. package/lib/commonjs/web/browser/classifyTrackNavigation.js +0 -41
  768. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +0 -1
  769. package/lib/commonjs/web/browser/parseSearchResponse.js +0 -20
  770. package/lib/commonjs/web/browser/parseSearchResponse.js.map +0 -1
  771. package/lib/commonjs/web/playbackErrorKind.js +0 -57
  772. package/lib/commonjs/web/playbackErrorKind.js.map +0 -1
  773. package/lib/commonjs/web/player/MediaSessionManager.js +0 -121
  774. package/lib/commonjs/web/player/MediaSessionManager.js.map +0 -1
  775. package/lib/commonjs/web/player/RemoteCommandController.js +0 -96
  776. package/lib/commonjs/web/player/RemoteCommandController.js.map +0 -1
  777. package/lib/module/features/browser-config.js +0 -221
  778. package/lib/module/features/browser-config.js.map +0 -1
  779. package/lib/module/features/carConnection.js +0 -37
  780. package/lib/module/features/carConnection.js.map +0 -1
  781. package/lib/module/features/gate.js +0 -144
  782. package/lib/module/features/gate.js.map +0 -1
  783. package/lib/module/features/playback/trackPlaybackTime.js +0 -83
  784. package/lib/module/features/playback/trackPlaybackTime.js.map +0 -1
  785. package/lib/module/features/player/validateOptions.js +0 -20
  786. package/lib/module/features/player/validateOptions.js.map +0 -1
  787. package/lib/module/utils/artwork.js +0 -26
  788. package/lib/module/utils/artwork.js.map +0 -1
  789. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +0 -67
  790. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  791. package/lib/module/web/TrackPlayer/PlaybackTimer.js +0 -29
  792. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  793. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +0 -17
  794. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  795. package/lib/module/web/TrackPlayer/QueueManager.js +0 -269
  796. package/lib/module/web/TrackPlayer/QueueManager.js.map +0 -1
  797. package/lib/module/web/TrackPlayer/QueuePlayer.js +0 -154
  798. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +0 -1
  799. package/lib/module/web/TrackPlayer/VolumeFader.js +0 -70
  800. package/lib/module/web/TrackPlayer/VolumeFader.js.map +0 -1
  801. package/lib/module/web/browser/assertBrowsePageShape.js +0 -18
  802. package/lib/module/web/browser/assertBrowsePageShape.js.map +0 -1
  803. package/lib/module/web/browser/classifyTrackNavigation.js +0 -38
  804. package/lib/module/web/browser/classifyTrackNavigation.js.map +0 -1
  805. package/lib/module/web/browser/parseSearchResponse.js +0 -16
  806. package/lib/module/web/browser/parseSearchResponse.js.map +0 -1
  807. package/lib/module/web/playbackErrorKind.js +0 -52
  808. package/lib/module/web/playbackErrorKind.js.map +0 -1
  809. package/lib/module/web/player/MediaSessionManager.js +0 -116
  810. package/lib/module/web/player/MediaSessionManager.js.map +0 -1
  811. package/lib/module/web/player/RemoteCommandController.js +0 -92
  812. package/lib/module/web/player/RemoteCommandController.js.map +0 -1
  813. package/lib/typescript/src/features/browser-config.d.ts +0 -12
  814. package/lib/typescript/src/features/browser-config.d.ts.map +0 -1
  815. package/lib/typescript/src/features/carConnection.d.ts +0 -20
  816. package/lib/typescript/src/features/carConnection.d.ts.map +0 -1
  817. package/lib/typescript/src/features/gate.d.ts +0 -78
  818. package/lib/typescript/src/features/gate.d.ts.map +0 -1
  819. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +0 -34
  820. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +0 -1
  821. package/lib/typescript/src/features/player/validateOptions.d.ts +0 -2
  822. package/lib/typescript/src/features/player/validateOptions.d.ts.map +0 -1
  823. package/lib/typescript/src/utils/artwork.d.ts +0 -19
  824. package/lib/typescript/src/utils/artwork.d.ts.map +0 -1
  825. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +0 -61
  826. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
  827. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
  828. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +0 -100
  829. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +0 -112
  830. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +0 -121
  831. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +0 -123
  832. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +0 -133
  833. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +0 -121
  834. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +0 -139
  835. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +0 -134
  836. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +0 -131
  837. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +0 -79
  838. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +0 -80
  839. package/nitrogen/generated/android/c++/JGate.hpp +0 -62
  840. package/nitrogen/generated/android/c++/JGateDecision.hpp +0 -64
  841. package/nitrogen/generated/android/c++/JGateReason.hpp +0 -58
  842. package/nitrogen/generated/android/c++/JIOSOptions.hpp +0 -95
  843. package/nitrogen/generated/android/c++/JMediaReference.hpp +0 -58
  844. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +0 -74
  845. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +0 -182
  846. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +0 -96
  847. package/nitrogen/generated/android/c++/JOutputType.hpp +0 -82
  848. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +0 -76
  849. package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +0 -86
  850. package/nitrogen/generated/android/c++/JStallReason.hpp +0 -58
  851. package/nitrogen/generated/android/c++/JTrackRequest.hpp +0 -93
  852. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
  853. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
  854. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +0 -26
  855. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +0 -75
  856. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +0 -41
  857. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +0 -121
  858. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +0 -26
  859. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +0 -70
  860. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +0 -50
  861. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -80
  862. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -80
  863. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -80
  864. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -80
  865. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -80
  866. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -80
  867. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -80
  868. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +0 -44
  869. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +0 -23
  870. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +0 -44
  871. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +0 -66
  872. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +0 -44
  873. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +0 -31
  874. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +0 -29
  875. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButton.kt +0 -26
  876. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +0 -44
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +0 -23
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +0 -44
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +0 -65
  881. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +0 -53
  882. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +0 -34
  883. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
  884. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
  885. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +0 -67
  886. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +0 -54
  887. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +0 -69
  888. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +0 -54
  889. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +0 -60
  890. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +0 -60
  891. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +0 -61
  892. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +0 -61
  893. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +0 -77
  894. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +0 -46
  895. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +0 -46
  896. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +0 -46
  897. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -53
  898. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +0 -66
  899. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +0 -81
  900. package/nitrogen/generated/ios/swift/Gate.swift +0 -47
  901. package/nitrogen/generated/ios/swift/GateDecision.swift +0 -40
  902. package/nitrogen/generated/ios/swift/GateEvent.swift +0 -29
  903. package/nitrogen/generated/ios/swift/GateReason.swift +0 -40
  904. package/nitrogen/generated/ios/swift/IOSOptions.swift +0 -51
  905. package/nitrogen/generated/ios/swift/MediaReference.swift +0 -40
  906. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +0 -58
  907. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +0 -206
  908. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +0 -90
  909. package/nitrogen/generated/ios/swift/OutputType.swift +0 -72
  910. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +0 -64
  911. package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +0 -57
  912. package/nitrogen/generated/ios/swift/StallReason.swift +0 -40
  913. package/nitrogen/generated/ios/swift/TrackRequest.swift +0 -106
  914. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
  915. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +0 -19
  916. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +0 -18
  917. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +0 -87
  918. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +0 -76
  919. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +0 -110
  920. package/nitrogen/generated/shared/c++/GateReason.hpp +0 -76
  921. package/nitrogen/generated/shared/c++/IOSOptions.hpp +0 -91
  922. package/nitrogen/generated/shared/c++/MediaReference.hpp +0 -76
  923. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +0 -97
  924. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +0 -138
  925. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +0 -92
  926. package/nitrogen/generated/shared/c++/OutputType.hpp +0 -108
  927. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +0 -100
  928. package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +0 -94
  929. package/nitrogen/generated/shared/c++/StallReason.hpp +0 -76
  930. package/nitrogen/generated/shared/c++/TrackRequest.hpp +0 -93
  931. package/src/codegen-no-config-variant.test.ts +0 -70
  932. package/src/features/browser-config.test.ts +0 -110
  933. package/src/features/browser-config.ts +0 -293
  934. package/src/features/browser.test.ts +0 -19
  935. package/src/features/carConnection.ts +0 -36
  936. package/src/features/gate.test.ts +0 -72
  937. package/src/features/gate.ts +0 -155
  938. package/src/features/playback/trackPlaybackTime.test.ts +0 -80
  939. package/src/features/playback/trackPlaybackTime.ts +0 -101
  940. package/src/features/player/options.test.ts +0 -38
  941. package/src/features/player/setup.test.ts +0 -125
  942. package/src/features/player/validateOptions.ts +0 -22
  943. package/src/features/queue/queue.test.ts +0 -36
  944. package/src/public-surface.test.ts +0 -116
  945. package/src/utils/artwork.ts +0 -30
  946. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +0 -301
  947. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +0 -139
  948. package/src/web/TrackPlayer/PlaybackStateMachine.ts +0 -82
  949. package/src/web/TrackPlayer/PlaybackTimer.test.ts +0 -67
  950. package/src/web/TrackPlayer/PlaybackTimer.ts +0 -33
  951. package/src/web/TrackPlayer/Player.dispatch.test.ts +0 -229
  952. package/src/web/TrackPlayer/Player.load.test.ts +0 -86
  953. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +0 -51
  954. package/src/web/TrackPlayer/PlayingStateFactory.ts +0 -24
  955. package/src/web/TrackPlayer/QueueManager.test.ts +0 -289
  956. package/src/web/TrackPlayer/QueueManager.ts +0 -302
  957. package/src/web/TrackPlayer/QueuePlayer.ts +0 -188
  958. package/src/web/TrackPlayer/VolumeFader.ts +0 -74
  959. package/src/web/browser/__tests__/layer-resolver.test.ts +0 -69
  960. package/src/web/browser/assertBrowsePageShape.test.ts +0 -27
  961. package/src/web/browser/assertBrowsePageShape.ts +0 -27
  962. package/src/web/browser/classifyTrackNavigation.test.ts +0 -41
  963. package/src/web/browser/classifyTrackNavigation.ts +0 -35
  964. package/src/web/browser/parseSearchResponse.test.ts +0 -25
  965. package/src/web/browser/parseSearchResponse.ts +0 -15
  966. package/src/web/http/RequestConfigBuilder.test.ts +0 -59
  967. package/src/web/playbackErrorKind.test.ts +0 -55
  968. package/src/web/playbackErrorKind.ts +0 -56
  969. package/src/web/player/MediaSessionManager.test.ts +0 -220
  970. package/src/web/player/MediaSessionManager.ts +0 -151
  971. package/src/web/player/NowPlayingManager.test.ts +0 -46
  972. package/src/web/player/RemoteCommandController.test.ts +0 -171
  973. package/src/web/player/RemoteCommandController.ts +0 -166
@@ -1,41 +1,35 @@
1
1
  package com.audiobrowser.player
2
2
 
3
3
  import android.os.Bundle
4
+ import androidx.media3.common.HeartRating
4
5
  import androidx.media3.common.MediaItem
5
6
  import androidx.media3.common.MediaMetadata
6
7
  import androidx.media3.common.Rating
7
8
  import androidx.media3.session.LibraryResult
8
- import androidx.media3.session.MediaConstants
9
9
  import androidx.media3.session.MediaLibraryService
10
10
  import androidx.media3.session.MediaSession
11
+ import androidx.media3.session.MediaConstants
11
12
  import androidx.media3.session.SessionCommand
12
13
  import androidx.media3.session.SessionError
13
14
  import androidx.media3.session.SessionResult
15
+ import com.audiobrowser.AudioBrowser
14
16
  import com.audiobrowser.browser.handleTrackLoad
15
- import com.audiobrowser.extension.toTrack
16
17
  import com.audiobrowser.util.BrowserPathHelper
17
- import com.audiobrowser.util.RatingFavorites
18
+ import com.audiobrowser.util.RatingFactory
19
+ import com.audiobrowser.util.ResolvedTrackFactory
18
20
  import com.audiobrowser.util.TrackFactory
21
+ import com.margelo.nitro.audiobrowser.Track
19
22
  import com.google.common.collect.ImmutableList
20
23
  import com.google.common.util.concurrent.Futures
21
24
  import com.google.common.util.concurrent.ListenableFuture
22
- import com.margelo.nitro.audiobrowser.Gate
23
- import com.margelo.nitro.audiobrowser.GateEvent
24
- import com.margelo.nitro.audiobrowser.GateReason
25
- import com.margelo.nitro.audiobrowser.MediaReference
26
- import com.margelo.nitro.audiobrowser.NativeGateRequest
25
+ import com.margelo.nitro.audiobrowser.FavoriteChangedEvent
26
+ import com.margelo.nitro.audiobrowser.NotificationButtonLayout
27
27
  import com.margelo.nitro.audiobrowser.PlayerCapabilities
28
- import com.margelo.nitro.audiobrowser.RemoteButtonLayout
29
- import com.margelo.nitro.audiobrowser.SearchParams
30
- import com.margelo.nitro.audiobrowser.Track
31
- import kotlinx.coroutines.CancellationException
28
+ import com.margelo.nitro.audiobrowser.RemoteSetRatingEvent
32
29
  import kotlinx.coroutines.CoroutineScope
33
30
  import kotlinx.coroutines.Dispatchers
34
31
  import kotlinx.coroutines.SupervisorJob
35
- import kotlinx.coroutines.TimeoutCancellationException
36
- import kotlinx.coroutines.cancel
37
32
  import kotlinx.coroutines.guava.future
38
- import kotlinx.coroutines.launch
39
33
  import kotlinx.coroutines.withContext
40
34
  import timber.log.Timber
41
35
 
@@ -48,9 +42,7 @@ class MediaSessionCallback(private val player: Player) :
48
42
  internal val commandManager = MediaSessionCommandManager()
49
43
  private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
50
44
 
51
- // Track which controllers are subscribed to which media IDs.
52
- // Mutated on the Media3 application thread (onSubscribe/onUnsubscribe) but read from other
53
- // threads (network observer, JS-triggered notifies) — guard all access with synchronized(this).
45
+ // Track which controllers are subscribed to which media IDs
54
46
  private val parentIdSubscriptions =
55
47
  mutableMapOf<String, MutableSet<MediaSession.ControllerInfo>>()
56
48
  private var mediaLibrarySession: MediaLibraryService.MediaLibrarySession? = null
@@ -59,8 +51,7 @@ class MediaSessionCallback(private val player: Player) :
59
51
  * Recommended artwork size in pixels from the connected media browser (e.g., Android Auto).
60
52
  * Updated when onGetLibraryRoot is called with EXTRAS_KEY_MEDIA_ART_SIZE_PIXELS hint.
61
53
  */
62
- @Volatile
63
- var artworkSizeHintPixels: Int? = null
54
+ @Volatile var artworkSizeHintPixels: Int? = null
64
55
  private set
65
56
 
66
57
  init {
@@ -81,99 +72,36 @@ class MediaSessionCallback(private val player: Player) :
81
72
  }
82
73
 
83
74
  /** Creates an offline error MediaItem. */
84
- private fun createOfflineMediaItem(): MediaItem =
85
- createErrorMediaItem(
86
- mediaId = BrowserPathHelper.OFFLINE_PATH,
87
- title = player.context.getString(com.audiobrowser.R.string.audio_browser_offline_error),
88
- subtitle =
89
- player.context.getString(com.audiobrowser.R.string.audio_browser_offline_error_subtitle),
90
- )
91
-
92
- /**
93
- * Builds a non-browsable, non-playable [MediaItem] used to surface an error inside an Android
94
- * Auto / AAOS browse list. Rendered as a greyed-out, non-interactive tile, which is the only
95
- * side-effect-free way to communicate a browse failure to legacy controllers (Media3 drops
96
- * [LibraryResult.ofError] on the legacy browse bridge, leaving an empty "No items" screen).
97
- */
98
- private fun createErrorMediaItem(mediaId: String, title: String, subtitle: String): MediaItem =
99
- MediaItem.Builder()
100
- .setMediaId(mediaId)
75
+ private fun createOfflineMediaItem(): MediaItem {
76
+ val errorTitle = player.context.getString(com.audiobrowser.R.string.audio_browser_offline_error)
77
+ val errorSubtitle =
78
+ player.context.getString(com.audiobrowser.R.string.audio_browser_offline_error_subtitle)
79
+ return MediaItem.Builder()
80
+ .setMediaId(BrowserPathHelper.OFFLINE_PATH)
101
81
  .setMediaMetadata(
102
82
  MediaMetadata.Builder()
103
- .setTitle(title)
104
- .setSubtitle(subtitle)
105
- // Non-browsable, non-playable. Android Auto ignores these flags and still drills into a
106
- // tapped tile, but onGetChildren returns an empty list for the sentinel paths so it's a
107
- // harmless "No Items" dead-end rather than an endless stack of error pages.
83
+ .setTitle(errorTitle)
84
+ .setSubtitle(errorSubtitle)
108
85
  .setIsBrowsable(false)
109
86
  .setIsPlayable(false)
110
87
  .build()
111
88
  )
112
89
  .build()
113
-
114
- /**
115
- * Builds the gate tile from a per-request chrome: while a gate is active, tabs stay visible but a
116
- * gated browse/search level serves this single tile (see the gate checks in [onGetChildren] /
117
- * [onGetSearchResult]). Same shape as the error tiles — non-browsable, non-playable — and
118
- * deliberately NOT accompanied by a SessionError: a gate is deliberate app state, not a failure.
119
- * The message renders as the tile's subtitle (newlines collapse to spaces — list rows are
120
- * single-line).
121
- */
122
- /**
123
- * Wraps a raw external-search query string into the structured [SearchParams] the gate request
124
- * carries. The car search surfaces only give a free-text query, so the other fields stay null —
125
- * mirrors BrowserManager's query→SearchParams construction.
126
- */
127
- private fun searchParams(query: String): SearchParams =
128
- SearchParams(
129
- mode = null,
130
- query = query,
131
- genre = null,
132
- artist = null,
133
- album = null,
134
- title = null,
135
- playlist = null,
136
- reference = MediaReference.UNKNOWN,
137
- )
138
-
139
- private fun createGateMediaItem(gate: Gate): MediaItem =
140
- createErrorMediaItem(
141
- mediaId = BrowserPathHelper.GATE_PATH,
142
- title = gate.title,
143
- subtitle = gate.message?.replace('\n', ' ') ?: "",
144
- )
145
-
146
- /**
147
- * Builds a generic "something went wrong" error tile for a browse failure. The true offline case
148
- * is handled separately by the [networkMonitor] guard in [onGetChildren]; anything reaching the
149
- * catch block is an online-but-failed request (e.g. server down, bad status), so it must NOT be
150
- * labelled "no internet connection".
151
- */
152
- private fun createBrowseErrorMediaItem(): MediaItem =
153
- createErrorMediaItem(
154
- mediaId = BrowserPathHelper.ERROR_PATH,
155
- title = player.context.getString(com.audiobrowser.R.string.audio_browser_browse_error),
156
- subtitle =
157
- player.context.getString(com.audiobrowser.R.string.audio_browser_browse_error_subtitle),
158
- )
90
+ }
159
91
 
160
92
  fun updateMediaSession(
161
93
  mediaSession: MediaSession,
162
94
  capabilities: PlayerCapabilities,
163
- remoteButtonLayout: RemoteButtonLayout?,
95
+ notificationButtons: NotificationButtonLayout?,
164
96
  searchAvailable: Boolean,
165
- forwardJumpInterval: Double,
166
- backwardJumpInterval: Double,
167
97
  ) {
168
98
  // Store as MediaLibrarySession for notifyChildrenChanged support
169
99
  this.mediaLibrarySession = mediaSession as? MediaLibraryService.MediaLibrarySession
170
100
  commandManager.updateMediaSession(
171
101
  mediaSession,
172
102
  capabilities,
173
- remoteButtonLayout,
103
+ notificationButtons,
174
104
  searchAvailable,
175
- forwardJumpInterval,
176
- backwardJumpInterval,
177
105
  )
178
106
  }
179
107
 
@@ -185,6 +113,18 @@ class MediaSessionCallback(private val player: Player) :
185
113
  return commandManager.buildConnectionResult(session)
186
114
  }
187
115
 
116
+ /** Updates the favorite state of the current track and emits onFavoriteChanged. */
117
+ private fun setFavorited(favorited: Boolean) {
118
+ val currentTrack = player.currentTrack ?: return
119
+
120
+ // Update native favorites cache (only tracks with src can be favorited)
121
+ currentTrack.src?.let { src -> player.browser?.browserManager?.updateFavorite(src, favorited) }
122
+
123
+ player.setActiveTrackFavorited(favorited)
124
+ val event = FavoriteChangedEvent(player.currentTrack ?: currentTrack, favorited)
125
+ player.callbacks?.onFavoriteChanged(event)
126
+ }
127
+
188
128
  override fun onCustomCommand(
189
129
  session: MediaSession,
190
130
  controller: MediaSession.ControllerInfo,
@@ -195,7 +135,7 @@ class MediaSessionCallback(private val player: Player) :
195
135
  if (command.customAction == MediaSessionCommandManager.CUSTOM_ACTION_FAVORITE) {
196
136
  val currentFavorited = player.currentTrack?.favorited ?: false
197
137
  Timber.d("Favorite button tapped - toggling from $currentFavorited to ${!currentFavorited}")
198
- player.setActiveTrackFavorited(!currentFavorited)
138
+ setFavorited(!currentFavorited)
199
139
  return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
200
140
  }
201
141
 
@@ -210,10 +150,15 @@ class MediaSessionCallback(private val player: Player) :
210
150
  controller: MediaSession.ControllerInfo,
211
151
  rating: Rating,
212
152
  ): ListenableFuture<SessionResult> {
213
- // A heart rating from a controller (e.g. Google Assistant "I like this") toggles the
214
- // now-playing favorite. setActiveTrackFavorited fires onFavoriteChanged so the consumer
215
- // persists it — the same path as the notification / CarPlay heart button.
216
- RatingFavorites.favoritedFor(rating)?.let { player.setActiveTrackFavorited(it) }
153
+ if (rating is HeartRating) {
154
+ setFavorited(rating.isHeart)
155
+ }
156
+
157
+ // Also emit onRemoteSetRating for listeners
158
+ RatingFactory.media3ToBridge(rating)?.let {
159
+ val event = RemoteSetRatingEvent(it)
160
+ player.callbacks?.onRemoteSetRating(event)
161
+ }
217
162
  return super.onSetRating(session, controller, rating)
218
163
  }
219
164
 
@@ -275,55 +220,25 @@ class MediaSessionCallback(private val player: Player) :
275
220
  )
276
221
  return scope.future {
277
222
  // Wait for browser to be registered if it's not available yet
278
- val audioBrowser =
279
- player.awaitBrowser().also { Timber.d("Browser ready, proceeding with onGetChildren") }
280
- val browserManager = audioBrowser.browserManager
281
-
282
- // While a gate is active, tabs stay visible (the root keeps serving them below) but each
283
- // non-root level is resolved per request: a gated path — including re-queries of the gate
284
- // tile's own sentinel path — serves the single gate tile, so drilling into it re-shows the
285
- // message instead of dead-ending in "No items"; an allowed path falls through to real
286
- // children. Checked before the offline guard: gated content isn't coming back with
287
- // connectivity, so the gate copy is the truer message.
288
- if (parentId != BrowserPathHelper.ROOT_PATH) {
289
- val outcome =
290
- audioBrowser.gateDecision(
291
- NativeGateRequest(reason = GateReason.BROWSE, path = parentId, search = null)
292
- )
293
- if (outcome.gated) {
294
- audioBrowser.onGate(GateEvent(GateReason.BROWSE))
295
- // gateDecision guarantees non-null chrome on a gated decision (override → default →
296
- // built-in).
297
- return@future LibraryResult.ofItemList(
298
- ImmutableList.of(createGateMediaItem(outcome.chrome!!)),
299
- params,
300
- )
301
- }
302
- }
303
-
304
- // The error / offline tiles are dead-ends. Some controllers (e.g. Android Auto when online)
305
- // treat a non-browsable tile as tappable and subscribe to its mediaId anyway; returning the
306
- // error tile again here would push an endless stack of error pages. Return nothing instead.
307
- // For the offline tile, re-send the alert when still offline so a tap surfaces the
308
- // explanation again — but only then, since these paths are also re-queried by
309
- // notifyChildrenChanged (e.g. when connectivity returns) without any user action.
310
- if (parentId == BrowserPathHelper.OFFLINE_PATH || parentId == BrowserPathHelper.ERROR_PATH) {
311
- if (parentId == BrowserPathHelper.OFFLINE_PATH && !player.networkMonitor.isOnline.value) {
312
- sendBrowseError(session, browser, offline = true)
313
- }
314
- return@future LibraryResult.ofItemList(ImmutableList.of<MediaItem>(), params)
315
- }
223
+ val browserManager =
224
+ player
225
+ .awaitBrowser()
226
+ .also { Timber.d("Browser ready, proceeding with onGetChildren") }
227
+ .browserManager
316
228
 
317
229
  // Show offline error when offline:
318
230
  if (
319
231
  !player.networkMonitor.isOnline.value && browserManager.config.androidControllerOfflineError
320
232
  ) {
321
233
  Timber.w("Network offline - returning error message for: $parentId")
322
- sendBrowseError(session, browser, offline = true)
323
234
  return@future LibraryResult.ofItemList(ImmutableList.of(createOfflineMediaItem()), params)
324
235
  }
325
236
 
326
237
  try {
238
+ // Get context and imageLoader for SVG pre-rendering
239
+ val context = player.context
240
+ val imageLoader = player.imageLoader
241
+
327
242
  val children =
328
243
  if (parentId == BrowserPathHelper.RECENT_PATH) {
329
244
  // TODO: implement recent media items
@@ -331,90 +246,36 @@ class MediaSessionCallback(private val player: Player) :
331
246
  } else if (parentId == BrowserPathHelper.ROOT_PATH) {
332
247
  // Return tabs as root children (limited to 4 for automotive platform compatibility)
333
248
  // TODO: Check what Android Auto does with empty tabs list - may need to return error?
334
- val tabs = browserManager.queryTabs()
335
- if (tabs.size > 4) {
336
- Timber.w(
337
- "Root has ${tabs.size} tabs; dropping ${tabs.size - 4} (Android Auto root limit)"
338
- )
249
+ val tabs = browserManager.queryTabs().take(4)
250
+ if (imageLoader != null) {
251
+ tabs.map { tab -> TrackFactory.toMedia3WithSvgSupport(tab, context, imageLoader) }
252
+ } else {
253
+ tabs.map { tab -> TrackFactory.toMedia3(tab) }
339
254
  }
340
- toMediaItems(tabs.take(4))
341
255
  } else {
342
256
  // Resolve the specific path and get its children
343
257
  val resolvedTrack = browserManager.resolve(parentId)
344
258
 
345
259
  // Convert children to MediaItems (url is already set to contextual URL)
346
- val trackChildren =
347
- resolvedTrack.children
348
- ?: throw IllegalStateException(
349
- "Expected browsed ResolvedTrack to have a children array"
350
- )
351
- toMediaItems(trackChildren.toList())
260
+ val trackChildren = resolvedTrack.children
261
+ ?: throw IllegalStateException(
262
+ "Expected browsed ResolvedTrack to have a children array"
263
+ )
264
+ if (imageLoader != null) {
265
+ trackChildren.map { track -> TrackFactory.toMedia3WithSvgSupport(track, context, imageLoader) }
266
+ } else {
267
+ trackChildren.map { track -> TrackFactory.toMedia3(track) }
268
+ }
352
269
  }
353
270
 
354
271
  LibraryResult.ofItemList(ImmutableList.copyOf(children.paginate(page, pageSize)), params)
355
272
  } catch (e: Exception) {
356
- // A cancelled browse (controller disconnected) is not a failure — don't render it as an
357
- // error tile. awaitBrowser's TimeoutCancellationException IS a real failure, keep that.
358
- if (e is CancellationException && e !is TimeoutCancellationException) throw e
359
273
  Timber.e(e, "Error getting children for parentId: $parentId")
360
- // Surface an error tile instead of a bare ofError(): Media3 drops the error message on the
361
- // legacy browse bridge, which would otherwise leave an empty "No items" screen in Android
362
- // Auto. See https://github.com/androidx/media/issues/2901
363
- //
364
- // Verified on a head unit (2026-06): the AA browse list NEVER renders error text — not for
365
- // transient sendError, sticky non-fatal replication, or fatal replication
366
- // (setLibraryErrorReplicationMode). Fatal replication does show the message on the
367
- // playback screen, but presents the session as STATE_ERROR with no actions, hiding the
368
- // now-playing item and transport controls — not worth it. Tiles remain the only in-browse
369
- // signal we control.
370
- sendBrowseError(session, browser, offline = false)
371
- LibraryResult.ofItemList(ImmutableList.of(createBrowseErrorMediaItem()), params)
274
+ LibraryResult.ofError(SessionError.ERROR_UNKNOWN)
372
275
  }
373
276
  }
374
277
  }
375
278
 
376
- /**
377
- * Sends a non-fatal [SessionError] to the controller whose browse failed, complementing the error
378
- * tile. Media3 browsers receive it via MediaController.Listener.onError; for legacy controllers
379
- * Media3 transiently attaches the error code/message to the platform session's playback state
380
- * without entering STATE_ERROR.
381
- *
382
- * NOTE: current Android Auto renders NOTHING for this (verified on a head unit — see
383
- * androidx/media#2901; the transient state is cleared microseconds after being set). It is kept
384
- * because it is the correct Media3-API error signal, costs nothing, and becomes user-visible if
385
- * Android Auto moves to consuming SessionError via the Media3 controller API.
386
- *
387
- * Dispatched to the main thread: the session and its legacy stub are application-thread bound.
388
- */
389
- @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
390
- private fun sendBrowseError(
391
- session: MediaLibraryService.MediaLibrarySession,
392
- browser: MediaSession.ControllerInfo,
393
- offline: Boolean,
394
- ) {
395
- val message =
396
- player.context.getString(
397
- if (offline) com.audiobrowser.R.string.audio_browser_offline_error
398
- else com.audiobrowser.R.string.audio_browser_browse_error
399
- )
400
- val code = if (offline) SessionError.ERROR_IO else SessionError.ERROR_UNKNOWN
401
- scope.launch(Dispatchers.Main) { session.sendError(browser, SessionError(code, message)) }
402
- }
403
-
404
- /**
405
- * Converts tracks to MediaItems for browse delivery, routing http(s) artwork through the
406
- * content:// provider so Android Auto can load it via the ArtworkContentProvider. Image-row
407
- * tracks (a CarPlay-only rendering) are expanded into their items as regular grouped rows first —
408
- * see [TrackFactory.expandImageRows].
409
- */
410
- private fun toMediaItems(tracks: List<Track>): List<MediaItem> {
411
- val registry = player.browseArtworkRegistry
412
- val authority = com.audiobrowser.util.ArtworkUris.authorityFor(player.context.packageName)
413
- return TrackFactory.expandImageRows(tracks).map {
414
- TrackFactory.toBrowseMediaItem(it, registry, authority)
415
- }
416
- }
417
-
418
279
  override fun onGetItem(
419
280
  session: MediaLibraryService.MediaLibrarySession,
420
281
  browser: MediaSession.ControllerInfo,
@@ -427,30 +288,6 @@ class MediaSessionCallback(private val player: Player) :
427
288
  return@future LibraryResult.ofItem(createOfflineMediaItem(), null)
428
289
  }
429
290
 
430
- // Return the error tile as a non-browsable item so tapping it can't re-browse into a
431
- // failing path (which would push another error page onto the stack).
432
- if (mediaId == BrowserPathHelper.ERROR_PATH) {
433
- return@future LibraryResult.ofItem(createBrowseErrorMediaItem(), null)
434
- }
435
-
436
- if (mediaId == BrowserPathHelper.GATE_PATH) {
437
- // A direct fetch of the gate tile's own sentinel (a controller re-reading the item it was
438
- // served). Resolve the chrome for the gate path but do NOT emit onGate — that fires at the
439
- // browse/search serve sites, not on an item lookup.
440
- val outcome =
441
- player
442
- .awaitBrowser()
443
- .gateDecision(
444
- NativeGateRequest(
445
- reason = GateReason.BROWSE,
446
- path = BrowserPathHelper.GATE_PATH,
447
- search = null,
448
- )
449
- )
450
- if (!outcome.gated) return@future LibraryResult.ofError(SessionError.ERROR_BAD_VALUE)
451
- return@future LibraryResult.ofItem(createGateMediaItem(outcome.chrome!!), null)
452
- }
453
-
454
291
  if (mediaId == BrowserPathHelper.ROOT_PATH || mediaId == BrowserPathHelper.RECENT_PATH) {
455
292
  return@future LibraryResult.ofItem(
456
293
  MediaItem.Builder()
@@ -466,33 +303,11 @@ class MediaSessionCallback(private val player: Player) :
466
303
  // Wait for browser to be registered if it's not available yet
467
304
  val browserManager = player.awaitBrowser().browserManager
468
305
 
469
- // Serve tracks from the track cache first (keyed by url and src). Besides avoiding an HTTP
470
- // resolve, this keeps item identity correct for contextual mediaIds: resolve() strips
471
- // __trackId and would return the *parent container's* metadata as the item.
472
- val browseAuthority =
473
- com.audiobrowser.util.ArtworkUris.authorityFor(player.context.packageName)
474
- browserManager.getCachedTrack(mediaId)?.let { track ->
475
- return@future LibraryResult.ofItem(
476
- TrackFactory.toBrowseMediaItem(track, player.browseArtworkRegistry, browseAuthority),
477
- null,
478
- )
479
- }
480
-
481
306
  try {
482
307
  val resolvedTrack = browserManager.resolve(mediaId)
483
- // Through the one Track conversion, so the resolve path renders identically
484
- // to the cached-track path above (list line from subtitle, favorited heart)
485
- // and the item's tag is a Track, as fromMedia3 expects.
486
- LibraryResult.ofItem(
487
- TrackFactory.toBrowseMediaItem(
488
- resolvedTrack.toTrack(),
489
- player.browseArtworkRegistry,
490
- browseAuthority,
491
- ),
492
- null,
493
- )
308
+ val mediaItem = ResolvedTrackFactory.toMedia3(resolvedTrack)
309
+ LibraryResult.ofItem(mediaItem, null)
494
310
  } catch (e: Exception) {
495
- if (e is CancellationException && e !is TimeoutCancellationException) throw e
496
311
  Timber.e(e, "Error getting item for mediaId: $mediaId")
497
312
  LibraryResult.ofError(SessionError.ERROR_UNKNOWN)
498
313
  }
@@ -507,17 +322,8 @@ class MediaSessionCallback(private val player: Player) :
507
322
  ): ListenableFuture<LibraryResult<Void>> {
508
323
  Timber.d("onSubscribe: ${browser.packageName}, parentId = $parentId")
509
324
 
510
- synchronized(this) { parentIdSubscriptions.getOrPut(parentId) { mutableSetOf() }.add(browser) }
511
-
512
- // Don't call super: Media3's default onSubscribe validates the parent by calling
513
- // onGetItem(parentId), which for us is a full resolve() — an HTTP fetch whose result the
514
- // legacy stub discards for Android Auto controllers. onGetChildren already surfaces browse
515
- // failures. Keep the default's other behavior: notify Media3 (non-legacy) browsers so they
516
- // fetch the children; legacy browsers get onLoadChildren from the framework after subscribing.
517
- if (browser.controllerVersion != MediaSession.ControllerInfo.LEGACY_CONTROLLER_VERSION) {
518
- session.notifyChildrenChanged(browser, parentId, Int.MAX_VALUE, params)
519
- }
520
- return Futures.immediateFuture(LibraryResult.ofVoid())
325
+ parentIdSubscriptions.getOrPut(parentId) { mutableSetOf() }.add(browser)
326
+ return super.onSubscribe(session, browser, parentId, params)
521
327
  }
522
328
 
523
329
  override fun onUnsubscribe(
@@ -527,11 +333,9 @@ class MediaSessionCallback(private val player: Player) :
527
333
  ): ListenableFuture<LibraryResult<Void>> {
528
334
  Timber.d("onUnsubscribe: ${browser.packageName}, parentId = $parentId")
529
335
 
530
- synchronized(this) {
531
- parentIdSubscriptions[parentId]?.remove(browser)
532
- if (parentIdSubscriptions[parentId]?.isEmpty() == true) {
533
- parentIdSubscriptions.remove(parentId)
534
- }
336
+ parentIdSubscriptions[parentId]?.remove(browser)
337
+ if (parentIdSubscriptions[parentId]?.isEmpty() == true) {
338
+ parentIdSubscriptions.remove(parentId)
535
339
  }
536
340
 
537
341
  return super.onUnsubscribe(session, browser, parentId)
@@ -540,38 +344,22 @@ class MediaSessionCallback(private val player: Player) :
540
344
  /**
541
345
  * Notifies all subscribed controllers to refresh their content. Called internally when network
542
346
  * state changes to refresh all subscribed paths.
543
- *
544
- * Safe to call from any thread: snapshots the subscribed paths and dispatches the session calls
545
- * to the main (Media3 application) thread.
546
347
  */
547
348
  private fun notifySubscribedChildrenChanged() {
548
- val session = mediaLibrarySession ?: return
549
- val parentIds = synchronized(this) { parentIdSubscriptions.keys.toList() }
550
- scope.launch(Dispatchers.Main) {
551
- parentIds.forEach { parentId -> session.notifyChildrenChanged(parentId, Int.MAX_VALUE, null) }
349
+ parentIdSubscriptions.keys.forEach { parentId ->
350
+ mediaLibrarySession?.notifyChildrenChanged(parentId, Int.MAX_VALUE, null)
552
351
  }
553
352
  }
554
353
 
555
354
  /**
556
355
  * Notifies external controllers that content at the given path has changed. Controllers
557
- * subscribed to this path will refresh their UI. Safe to call from any thread.
356
+ * subscribed to this path will refresh their UI.
558
357
  *
559
358
  * @param path The path where content has changed
560
359
  */
561
360
  fun notifyContentChanged(path: String) {
562
361
  Timber.d("Notifying content changed for path: $path")
563
- val session = mediaLibrarySession ?: return
564
- scope.launch(Dispatchers.Main) { session.notifyChildrenChanged(path, Int.MAX_VALUE, null) }
565
- }
566
-
567
- /**
568
- * Notifies all subscribed controllers that content everywhere has changed (e.g. on a locale
569
- * switch) so they re-query their children. Pairs with AudioBrowser.invalidateAllContent(), which
570
- * clears the content cache first.
571
- */
572
- fun invalidateAllContent() {
573
- Timber.d("Invalidating all content - notifying all subscribed paths")
574
- notifySubscribedChildrenChanged()
362
+ mediaLibrarySession?.notifyChildrenChanged(path, Int.MAX_VALUE, null)
575
363
  }
576
364
 
577
365
  /**
@@ -579,15 +367,10 @@ class MediaSessionCallback(private val player: Player) :
579
367
  * controllers to refresh their content.
580
368
  */
581
369
  fun notifyBrowserReady() {
582
- Timber.d("Browser ready - notifying all subscribed paths")
370
+ Timber.d("Browser ready - notifying ${parentIdSubscriptions.size} subscribed paths")
583
371
  notifySubscribedChildrenChanged()
584
372
  }
585
373
 
586
- /** Cancels in-flight browse/search work. Call when the owning player is destroyed. */
587
- fun destroy() {
588
- scope.cancel()
589
- }
590
-
591
374
  override fun onSearch(
592
375
  session: MediaLibraryService.MediaLibrarySession,
593
376
  browser: MediaSession.ControllerInfo,
@@ -596,27 +379,11 @@ class MediaSessionCallback(private val player: Player) :
596
379
  ): ListenableFuture<LibraryResult<Void>> {
597
380
  Timber.d("onSearch: ${browser.packageName}, query = $query")
598
381
  return scope.future {
599
- // Wait for browser registration like onGetChildren does, so a cold-start voice search
600
- // doesn't fail before JS has configured the browser.
601
- val audioBrowser =
602
- try {
603
- player.awaitBrowser()
604
- } catch (e: TimeoutCancellationException) {
605
- Timber.w("Timed out waiting for browser - search not available")
606
- return@future LibraryResult.ofError(SessionError.ERROR_NOT_SUPPORTED)
607
- }
608
- val browserManager = audioBrowser.browserManager
382
+ val browserManager = player.browser?.browserManager
609
383
 
610
- // External-surface search is gated with the rest of the browse tree — otherwise search is
611
- // a way around the gate. One "result": the gate tile (see onGetSearchResult).
612
- val searchOutcome =
613
- audioBrowser.gateDecision(
614
- NativeGateRequest(reason = GateReason.SEARCH, path = null, search = searchParams(query))
615
- )
616
- if (searchOutcome.gated) {
617
- audioBrowser.onGate(GateEvent(GateReason.SEARCH))
618
- session.notifySearchResultChanged(browser, query, 1, params)
619
- return@future LibraryResult.ofVoid()
384
+ if (browserManager == null) {
385
+ Timber.w("AudioBrowser not registered - search not available")
386
+ return@future LibraryResult.ofError(SessionError.ERROR_NOT_SUPPORTED)
620
387
  }
621
388
 
622
389
  // Check if search is configured
@@ -637,7 +404,6 @@ class MediaSessionCallback(private val player: Player) :
637
404
 
638
405
  LibraryResult.ofVoid()
639
406
  } catch (e: Exception) {
640
- if (e is CancellationException && e !is TimeoutCancellationException) throw e
641
407
  Timber.e(e, "Error during search for query: $query")
642
408
  LibraryResult.ofError(SessionError.ERROR_UNKNOWN)
643
409
  }
@@ -656,38 +422,21 @@ class MediaSessionCallback(private val player: Player) :
656
422
  "onGetSearchResult: ${browser.packageName}, query = $query, page = $page, pageSize = $pageSize"
657
423
  )
658
424
  return scope.future {
659
- val audioBrowser =
660
- try {
661
- player.awaitBrowser()
662
- } catch (e: TimeoutCancellationException) {
663
- Timber.w("Timed out waiting for browser - search not available")
664
- return@future LibraryResult.ofError(SessionError.ERROR_NOT_SUPPORTED)
665
- }
666
- val browserManager = audioBrowser.browserManager
425
+ val browserManager = player.browser?.browserManager
667
426
 
668
- // Gated: the single search "result" is the gate tile (paired with onSearch's count of 1).
669
- val searchOutcome =
670
- audioBrowser.gateDecision(
671
- NativeGateRequest(reason = GateReason.SEARCH, path = null, search = searchParams(query))
672
- )
673
- if (searchOutcome.gated) {
674
- audioBrowser.onGate(GateEvent(GateReason.SEARCH))
675
- return@future LibraryResult.ofItemList(
676
- ImmutableList.of(createGateMediaItem(searchOutcome.chrome!!)),
677
- params,
678
- )
427
+ if (browserManager == null) {
428
+ Timber.w("AudioBrowser not registered - search not available")
429
+ return@future LibraryResult.ofError(SessionError.ERROR_NOT_SUPPORTED)
679
430
  }
680
431
 
681
432
  try {
682
433
  // Get cached search results from BrowserManager
683
434
  browserManager.getCachedSearchResults(query)?.let { tracks ->
684
435
  // Convert to MediaItems
685
- val searchAuthority =
686
- com.audiobrowser.util.ArtworkUris.authorityFor(player.context.packageName)
687
436
  val mediaItems =
688
437
  tracks.map { track ->
689
438
  Timber.d("Search result: ${track.title} (url=${track.url}, src=${track.src})")
690
- TrackFactory.toBrowseMediaItem(track, player.browseArtworkRegistry, searchAuthority)
439
+ TrackFactory.toMedia3(track)
691
440
  }
692
441
 
693
442
  val paginatedItems = mediaItems.paginate(page, pageSize)
@@ -699,7 +448,6 @@ class MediaSessionCallback(private val player: Player) :
699
448
  LibraryResult.ofItemList(ImmutableList.of(), params)
700
449
  }
701
450
  } catch (e: Exception) {
702
- if (e is CancellationException && e !is TimeoutCancellationException) throw e
703
451
  Timber.e(e, "Error getting search results for query: $query")
704
452
  LibraryResult.ofError(SessionError.ERROR_UNKNOWN)
705
453
  }
@@ -714,84 +462,65 @@ class MediaSessionCallback(private val player: Player) :
714
462
  startPositionMs: Long,
715
463
  ): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
716
464
  Timber.Forest.d(
717
- "onSetMediaItems: ${controller.packageName}, count=${mediaItems.size}, mediaId=${mediaItems.firstOrNull()?.mediaId}, uri=${mediaItems.firstOrNull()?.localConfiguration?.uri}, title=${mediaItems.firstOrNull()?.mediaMetadata?.title}"
465
+ "onSetMediaItems: ${controller.packageName}, count=${mediaItems.size}, mediaId=${mediaItems[0].mediaId}, uri=${mediaItems[0].localConfiguration?.uri}, title=${mediaItems[0].mediaMetadata.title}"
718
466
  )
719
467
 
720
- if (mediaItems.isEmpty()) {
721
- return Futures.immediateFuture(
722
- MediaSession.MediaItemsWithStartPosition(emptyList(), 0, startPositionMs)
723
- )
724
- }
725
-
726
468
  return scope.future {
727
469
  val audioBrowser = player.awaitBrowser()
728
470
 
729
- // Helper: returns the current player state unchanged so Media3 doesn't modify playback.
730
- // ExoPlayer is main-thread confined; this future runs on IO, so hop to Main for the reads.
731
- suspend fun currentPlayerState(): MediaSession.MediaItemsWithStartPosition =
732
- withContext(Dispatchers.Main) {
733
- val currentItems = player.tracks.map { TrackFactory.toMedia3(it) }
734
- val currentIndex = player.currentIndex ?: 0
735
- MediaSession.MediaItemsWithStartPosition(currentItems, currentIndex, startPositionMs)
736
- }
737
-
738
- val browserManager = audioBrowser.browserManager
471
+ // Helper: returns the current player state unchanged so Media3 doesn't modify playback
472
+ fun currentPlayerState(): MediaSession.MediaItemsWithStartPosition {
473
+ val currentItems = player.tracks.map { TrackFactory.toMedia3(it) }
474
+ val currentIndex = player.currentIndex ?: 0
475
+ return MediaSession.MediaItemsWithStartPosition(
476
+ currentItems,
477
+ currentIndex,
478
+ startPositionMs,
479
+ )
480
+ }
739
481
 
740
- // A single tapped item resolves to the contextual url of the list it was
741
- // tapped in: directly for contextual mediaIds, via the track cache for
742
- // stable-id mediaIds (see BrowserManager.contextualUrlFor). A search
743
- // selection is not a list tap — its queue comes from the search results
744
- // (resolveMediaItemsForPlayback), never from a browsed container.
745
- val singleContextualUrl =
746
- mediaItems
747
- .singleOrNull()
748
- ?.takeIf { it.requestMetadata.searchQuery == null }
749
- ?.let { browserManager.contextualUrlFor(it.mediaId) }
750
-
751
- // Check if this is a single item from the current queue source
752
- if (singleContextualUrl != null) {
753
- val parentPath = BrowserPathHelper.stripTrackId(singleContextualUrl)
754
- val trackId = BrowserPathHelper.extractTrackId(singleContextualUrl)
755
-
756
- // Check if queue already came from this parent path - just skip to the track
757
- if (trackId != null && parentPath == player.queueSourcePath) {
758
- val queueTracks = withContext(Dispatchers.Main) { player.tracks }
759
- val index = queueTracks.indexOfFirst { it.src == trackId }
760
- if (index >= 0) {
761
- Timber.d("Queue already from $parentPath, skipping to index $index")
762
- val track = queueTracks[index]
763
- return@future handleTrackLoad(
764
- audioBrowser.configuration.handleTrackLoad,
765
- track,
766
- queueTracks,
767
- index.toDouble(),
768
- ::currentPlayerState,
769
- ) {
770
- // Return the existing queue items with the new start index
771
- val existingItems = queueTracks.map { TrackFactory.toMedia3(it) }
772
- MediaSession.MediaItemsWithStartPosition(existingItems, index, startPositionMs)
482
+ // Check if this is a single contextual URL that matches the current queue source
483
+ if (mediaItems.size == 1) {
484
+ val mediaId = mediaItems[0].mediaId
485
+ if (BrowserPathHelper.isContextual(mediaId)) {
486
+ val parentPath = BrowserPathHelper.stripTrackId(mediaId)
487
+ val trackId = BrowserPathHelper.extractTrackId(mediaId)
488
+
489
+ // Check if queue already came from this parent path - just skip to the track
490
+ if (trackId != null && parentPath == player.queueSourcePath) {
491
+ val index = player.tracks.indexOfFirst { it.src == trackId }
492
+ if (index >= 0) {
493
+ Timber.d("Queue already from $parentPath, skipping to index $index")
494
+ val track = player.tracks[index]
495
+ return@future handleTrackLoad(audioBrowser.configuration.handleTrackLoad, track, player.tracks, index.toDouble(), ::currentPlayerState) {
496
+ // Return the existing queue items with the new start index
497
+ val existingItems = player.tracks.map { TrackFactory.toMedia3(it) }
498
+ MediaSession.MediaItemsWithStartPosition(
499
+ existingItems,
500
+ index,
501
+ startPositionMs,
502
+ )
503
+ }
773
504
  }
774
505
  }
775
506
  }
776
507
  }
777
508
 
509
+ val browserManager = audioBrowser.browserManager
778
510
  val result =
779
511
  browserManager.resolveMediaItemsForPlayback(mediaItems, startIndex, startPositionMs)
780
512
 
781
513
  val tracks = result.mediaItems.map { TrackFactory.fromMedia3(it) }.toTypedArray()
782
514
  val selectedTrack = tracks.getOrElse(result.startIndex) { tracks.first() }
783
515
 
784
- handleTrackLoad(
785
- audioBrowser.configuration.handleTrackLoad,
786
- selectedTrack,
787
- tracks,
788
- result.startIndex.toDouble(),
789
- ::currentPlayerState,
790
- ) {
516
+ handleTrackLoad(audioBrowser.configuration.handleTrackLoad, selectedTrack, tracks, result.startIndex.toDouble(), ::currentPlayerState) {
791
517
  // If this was a contextual URL expansion, track the source path (only for default behavior)
792
- if (singleContextualUrl != null) {
793
- val parentPath = BrowserPathHelper.stripTrackId(singleContextualUrl)
794
- withContext(Dispatchers.Main) { player.queueSourcePath = parentPath }
518
+ if (mediaItems.size == 1) {
519
+ val mediaId = mediaItems[0].mediaId
520
+ if (BrowserPathHelper.isContextual(mediaId)) {
521
+ val parentPath = BrowserPathHelper.stripTrackId(mediaId)
522
+ withContext(Dispatchers.Main) { player.queueSourcePath = parentPath }
523
+ }
795
524
  }
796
525
  result
797
526
  }
@@ -808,42 +537,25 @@ class MediaSessionCallback(private val player: Player) :
808
537
  *
809
538
  * @param mediaSession The media session
810
539
  * @param controller The controller requesting resumption
811
- * @param isForPlayback True if this should start playback; false if just gathering info for the
812
- * boot-time resumption notification (no network; local metadata only).
540
+ * @param playback True if playback should start, false if just gathering info for UI
813
541
  * @see https://developer.android.com/media/media3/session/background-playback#resumption
814
542
  */
815
543
  override fun onPlaybackResumption(
816
544
  mediaSession: MediaSession,
817
545
  controller: MediaSession.ControllerInfo,
818
- isForPlayback: Boolean,
819
546
  ): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
820
547
  Timber.d("${controller.packageName}")
821
548
 
822
549
  return scope.future {
823
- // A pure read first: restore()'s side effects (it applies repeat/shuffle/speed to the
824
- // live player, emitting option-changed events to JS) belong to actual resumption only.
550
+ // Restore player settings and persisted state
825
551
  val state =
826
- player.playbackStateStore.get()
552
+ // restore() sets player properties which must happen on main thread
553
+ withContext(Dispatchers.Main) { player.playbackStateStore.restore() }
827
554
  ?: run {
828
555
  Timber.w("No persisted playback state found")
829
556
  throw IllegalStateException("No playback state to resume")
830
557
  }
831
558
 
832
- // isForPlayback == false is the device-boot-time notification case: network may be
833
- // unavailable and we must not start playback. Return just the locally-stored track with its
834
- // already-local metadata; skip the settings restore and network queue expansion below.
835
- if (!isForPlayback) {
836
- Timber.d("Info-gathering resumption (boot-time); returning stored track without expansion")
837
- return@future MediaSession.MediaItemsWithStartPosition(
838
- ImmutableList.of(TrackFactory.toMedia3(state.track)),
839
- 0,
840
- state.positionMs,
841
- )
842
- }
843
-
844
- // restore() sets player properties which must happen on main thread
845
- withContext(Dispatchers.Main) { player.playbackStateStore.restore() }
846
-
847
559
  val url = state.track.url
848
560
  Timber.d("Resuming from url=$url, positionMs=${state.positionMs}")
849
561