react-native-audio-browser 0.1.1 → 0.2.0-next.2

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 (902) hide show
  1. package/AudioBrowser.podspec +1 -1
  2. package/README.md +180 -2
  3. package/android/build.gradle +10 -0
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +15 -0
  6. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +401 -141
  7. package/android/src/main/java/com/audiobrowser/Callbacks.kt +4 -6
  8. package/android/src/main/java/com/audiobrowser/Service.kt +67 -18
  9. package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +37 -0
  10. package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +34 -0
  11. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +443 -178
  12. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +300 -0
  13. package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +79 -0
  14. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +41 -4
  15. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +43 -0
  16. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
  17. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +35 -0
  18. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +109 -97
  19. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +6 -10
  20. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +40 -8
  21. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +31 -37
  22. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +4 -1
  23. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +119 -0
  24. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +18 -1
  25. package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +153 -0
  26. package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +141 -0
  27. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +15 -3
  28. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +415 -131
  29. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +154 -276
  30. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +348 -0
  31. package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +129 -0
  32. package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +85 -0
  33. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +27 -5
  34. package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +56 -0
  35. package/android/src/main/java/com/audiobrowser/player/Player.kt +452 -576
  36. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +20 -0
  37. package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +130 -0
  38. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +190 -67
  39. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +117 -53
  40. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +37 -3
  41. package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +80 -0
  42. package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +50 -0
  43. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +85 -40
  44. package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +81 -0
  45. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +141 -0
  46. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +37 -0
  47. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +41 -0
  48. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +209 -0
  49. package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +161 -0
  50. package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +28 -0
  51. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +26 -0
  52. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +24 -0
  53. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +49 -0
  54. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +36 -0
  55. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +23 -300
  56. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +13 -23
  57. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
  58. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +4 -3
  59. package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +211 -0
  60. package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +58 -0
  61. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +2 -1
  62. package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +14 -0
  63. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +6 -111
  64. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +22 -8
  65. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +111 -80
  66. package/android/src/main/res/values/strings.xml +4 -0
  67. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +166 -0
  68. package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +46 -0
  69. package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +39 -0
  70. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +114 -0
  71. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +141 -0
  72. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +4 -0
  73. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +177 -0
  74. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +54 -0
  75. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +96 -0
  76. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +1 -2
  77. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +72 -0
  78. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +159 -0
  79. package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +56 -0
  80. package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +216 -0
  81. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +442 -0
  82. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +191 -0
  83. package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +198 -0
  84. package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +137 -0
  85. package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +36 -0
  86. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +268 -0
  87. package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +68 -0
  88. package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +40 -0
  89. package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +193 -0
  90. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +107 -0
  91. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +73 -0
  92. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +75 -0
  93. package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +18 -0
  94. package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +163 -0
  95. package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +34 -0
  96. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +28 -0
  97. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +53 -0
  98. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +58 -0
  99. package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +57 -0
  100. package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +40 -0
  101. package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +34 -0
  102. package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +50 -0
  103. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +63 -0
  104. package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +35 -0
  105. package/android/src/test/resources/certs/isrg-root-x1.pem +31 -0
  106. package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
  107. package/android/src/test/resources/certs/letsencrypt-r13.pem +29 -0
  108. package/android/src/test/resources/certs/stationplaylist-leaf.pem +34 -0
  109. package/ios/Browser/BrowserConfig.swift +41 -11
  110. package/ios/Browser/BrowserManager+URLResolution.swift +213 -93
  111. package/ios/Browser/BrowserManager.swift +303 -110
  112. package/ios/Browser/BrowserPathHelper.swift +32 -3
  113. package/ios/Browser/JsonModels.swift +287 -66
  114. package/ios/Browser/MediaResolveComposer.swift +114 -0
  115. package/ios/Browser/SearchDrillIn.swift +44 -0
  116. package/ios/Browser/SectionScope.swift +35 -0
  117. package/ios/Browser/TabBarEntries.swift +15 -0
  118. package/ios/CarPlay/CPInterfaceController+Safe.swift +126 -0
  119. package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
  120. package/ios/CarPlay/CarPlayController.swift +739 -149
  121. package/ios/CarPlay/CarPlayImageLoader.swift +57 -8
  122. package/ios/CarPlay/CarPlayListItemFactory.swift +44 -35
  123. package/ios/CarPlay/CarPlayNowPlayingManager.swift +180 -36
  124. package/ios/CarPlay/ImageRowItem+CarPlay.swift +19 -0
  125. package/ios/CarPlay/RNABAudioBrowser.h +15 -10
  126. package/ios/CarPlay/RNABAudioBrowser.m +15 -14
  127. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +2 -0
  128. package/ios/CarPlay/RNABMediaAddHandler.swift +75 -0
  129. package/ios/CarPlay/RNABMediaAffinityHandler.swift +69 -0
  130. package/ios/CarPlay/RNABMediaIntentHandler.swift +53 -43
  131. package/ios/Extension/Capability+RemoteCommand.swift +7 -9
  132. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  133. package/ios/Extension/NavigationError+Conversion.swift +8 -1
  134. package/ios/Extension/PlayerCapabilities+Favorite.swift +20 -0
  135. package/ios/Extension/RequestConfig+Copying.swift +31 -0
  136. package/ios/Extension/ResolvedTrack+Copying.swift +10 -4
  137. package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
  138. package/ios/Extension/Track+AVPlayer.swift +4 -4
  139. package/ios/Extension/Track+Copying.swift +9 -3
  140. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  141. package/ios/Extension/Variant+Artwork.swift +49 -0
  142. package/ios/HybridAudioBrowser.swift +750 -173
  143. package/ios/Model/NitroTypeStubs.swift +299 -224
  144. package/ios/Model/PlayerUpdateOptions.swift +23 -23
  145. package/ios/Model/RemoteCommand.swift +6 -6
  146. package/ios/Model/TrackPlayerError.swift +82 -18
  147. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +99 -121
  148. package/ios/NowPlayingInfo/SilentAudioPrimer.swift +73 -0
  149. package/ios/Observer/PlayerItemNotificationObserver.swift +45 -5
  150. package/ios/Observer/PlayerItemPropertyObserver.swift +27 -4
  151. package/ios/Observer/PlayerTimeObserver.swift +3 -53
  152. package/ios/Option/SessionCategories.swift +33 -11
  153. package/ios/Player/AirPlayStallJudgement.swift +25 -0
  154. package/ios/Player/EndOfTrackJudgement.swift +32 -0
  155. package/ios/Player/LoadSeekCoordinator.swift +16 -1
  156. package/ios/Player/MediaIntentCriteria.swift +139 -0
  157. package/ios/Player/MediaLoader.swift +31 -11
  158. package/ios/Player/NowPlayingUpdater.swift +119 -26
  159. package/ios/Player/PersistedPlaybackState.swift +11 -0
  160. package/ios/Player/PlaybackCoordinator.swift +285 -51
  161. package/ios/Player/PlaybackCoordinatorCallbacks.swift +6 -1
  162. package/ios/Player/PlaybackEffectHandler.swift +19 -9
  163. package/ios/Player/PlaybackErrorHandler.swift +97 -13
  164. package/ios/Player/PlaybackStateMachine.swift +18 -13
  165. package/ios/Player/PlaybackStateStore.swift +27 -0
  166. package/ios/Player/PlaybackTimer.swift +61 -0
  167. package/ios/Player/PlayingStateManager.swift +3 -2
  168. package/ios/Player/QueueManager.swift +67 -61
  169. package/ios/Player/RetryManager.swift +97 -21
  170. package/ios/Player/SleepTimerHandling.swift +8 -0
  171. package/ios/Player/SleepTimerManager.swift +72 -11
  172. package/ios/Player/VolumeFader.swift +77 -0
  173. package/ios/RemoteCommand/RemoteCommandController.swift +31 -15
  174. package/ios/Tests/AirPlayStallJudgementTests.swift +52 -0
  175. package/ios/Tests/BrowserPathHelperTests.swift +28 -0
  176. package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
  177. package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
  178. package/ios/Tests/EndOfTrackJudgementTests.swift +35 -0
  179. package/ios/Tests/JsonModelsTests.swift +58 -0
  180. package/ios/Tests/LoadSeekCoordinatorTests.swift +38 -7
  181. package/ios/Tests/MediaIntentCriteriaTests.swift +170 -0
  182. package/ios/Tests/MediaLoaderAssetOptionsTests.swift +46 -0
  183. package/ios/Tests/MediaLoaderTests.swift +32 -20
  184. package/ios/Tests/MediaResolveTests.swift +126 -0
  185. package/ios/Tests/OnceValueTests.swift +79 -0
  186. package/ios/Tests/PlaybackCoordinatorTests.swift +787 -13
  187. package/ios/Tests/PlaybackErrorHandlerTests.swift +380 -46
  188. package/ios/Tests/PlaybackStateMachineTests.swift +33 -8
  189. package/ios/Tests/PlaybackStateStoreTests.swift +48 -0
  190. package/ios/Tests/PlaybackTimerTests.swift +55 -0
  191. package/ios/Tests/PlayingStateManagerTests.swift +57 -0
  192. package/ios/Tests/QueueManagerTests.swift +149 -18
  193. package/ios/Tests/ResolvedTrackCopyingTests.swift +15 -8
  194. package/ios/Tests/RetryManagerTests.swift +89 -0
  195. package/ios/Tests/SearchDrillInTests.swift +63 -0
  196. package/ios/Tests/SectionScopeTests.swift +82 -0
  197. package/ios/Tests/SleepTimerManagerTests.swift +107 -0
  198. package/ios/Tests/Support/ManualSleepTimerScheduler.swift +47 -0
  199. package/ios/Tests/Support/TestTypes.swift +61 -20
  200. package/ios/Tests/TabBarEntriesTests.swift +71 -0
  201. package/ios/Tests/TrackSelectorTests.swift +15 -15
  202. package/ios/TrackPlayer.swift +380 -58
  203. package/ios/TrackPlayerCallbacks.swift +0 -6
  204. package/ios/TrackSelector.swift +5 -5
  205. package/ios/Util/ArtworkImageFetcher.swift +4 -2
  206. package/ios/Util/NetworkMonitor.swift +7 -3
  207. package/ios/Util/OnceValue.swift +34 -0
  208. package/lib/commonjs/features/browser-config.js +227 -0
  209. package/lib/commonjs/features/browser-config.js.map +1 -0
  210. package/lib/commonjs/features/browser.js +59 -158
  211. package/lib/commonjs/features/browser.js.map +1 -1
  212. package/lib/commonjs/features/carConnection.js +42 -0
  213. package/lib/commonjs/features/carConnection.js.map +1 -0
  214. package/lib/commonjs/features/errors.js +34 -2
  215. package/lib/commonjs/features/errors.js.map +1 -1
  216. package/lib/commonjs/features/gate.js +149 -0
  217. package/lib/commonjs/features/gate.js.map +1 -0
  218. package/lib/commonjs/features/index.js +22 -0
  219. package/lib/commonjs/features/index.js.map +1 -1
  220. package/lib/commonjs/features/metadata.js.map +1 -1
  221. package/lib/commonjs/features/nowPlaying.js +35 -0
  222. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  223. package/lib/commonjs/features/output.js +37 -23
  224. package/lib/commonjs/features/output.js.map +1 -1
  225. package/lib/commonjs/features/playback/controls.js +9 -0
  226. package/lib/commonjs/features/playback/controls.js.map +1 -1
  227. package/lib/commonjs/features/playback/index.js +11 -0
  228. package/lib/commonjs/features/playback/index.js.map +1 -1
  229. package/lib/commonjs/features/playback/progress.js +28 -12
  230. package/lib/commonjs/features/playback/progress.js.map +1 -1
  231. package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
  232. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
  233. package/lib/commonjs/features/playback/volume.js +1 -1
  234. package/lib/commonjs/features/player/options.js +49 -13
  235. package/lib/commonjs/features/player/options.js.map +1 -1
  236. package/lib/commonjs/features/player/setup.js +249 -3
  237. package/lib/commonjs/features/player/setup.js.map +1 -1
  238. package/lib/commonjs/features/queue/queue.js +10 -3
  239. package/lib/commonjs/features/queue/queue.js.map +1 -1
  240. package/lib/commonjs/features/remoteControls.js +1 -12
  241. package/lib/commonjs/features/remoteControls.js.map +1 -1
  242. package/lib/commonjs/features/sleepTimer.js +9 -4
  243. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  244. package/lib/commonjs/native.js +5 -0
  245. package/lib/commonjs/native.js.map +1 -1
  246. package/lib/commonjs/native.web.js +4 -1
  247. package/lib/commonjs/native.web.js.map +1 -1
  248. package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
  249. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  250. package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
  251. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  252. package/lib/commonjs/utils/artwork.js +31 -0
  253. package/lib/commonjs/utils/artwork.js.map +1 -0
  254. package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
  255. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  256. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
  257. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  258. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
  259. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  260. package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
  261. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  262. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
  263. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  264. package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
  265. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
  266. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
  267. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
  268. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  269. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  270. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
  271. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  272. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
  273. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
  274. package/lib/commonjs/web/TrackPlayer/index.js +13 -5
  275. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  276. package/lib/commonjs/web/browser/BrowserManager.js +176 -50
  277. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  278. package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
  279. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  280. package/lib/commonjs/web/browser/SearchManager.js +11 -9
  281. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  282. package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
  283. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
  284. package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
  285. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
  286. package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
  287. package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
  288. package/lib/commonjs/web/http/HttpClient.js +4 -23
  289. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  290. package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
  291. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  292. package/lib/commonjs/web/playbackErrorKind.js +57 -0
  293. package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
  294. package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
  295. package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
  296. package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
  297. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  298. package/lib/commonjs/web/player/OptionsManager.js +9 -17
  299. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  300. package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
  301. package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
  302. package/lib/module/features/browser-config.js +221 -0
  303. package/lib/module/features/browser-config.js.map +1 -0
  304. package/lib/module/features/browser.js +53 -156
  305. package/lib/module/features/browser.js.map +1 -1
  306. package/lib/module/features/carConnection.js +37 -0
  307. package/lib/module/features/carConnection.js.map +1 -0
  308. package/lib/module/features/errors.js +34 -2
  309. package/lib/module/features/errors.js.map +1 -1
  310. package/lib/module/features/gate.js +144 -0
  311. package/lib/module/features/gate.js.map +1 -0
  312. package/lib/module/features/index.js +2 -0
  313. package/lib/module/features/index.js.map +1 -1
  314. package/lib/module/features/metadata.js.map +1 -1
  315. package/lib/module/features/nowPlaying.js +33 -0
  316. package/lib/module/features/nowPlaying.js.map +1 -1
  317. package/lib/module/features/output.js +32 -19
  318. package/lib/module/features/output.js.map +1 -1
  319. package/lib/module/features/playback/controls.js +8 -0
  320. package/lib/module/features/playback/controls.js.map +1 -1
  321. package/lib/module/features/playback/index.js +1 -0
  322. package/lib/module/features/playback/index.js.map +1 -1
  323. package/lib/module/features/playback/progress.js +28 -12
  324. package/lib/module/features/playback/progress.js.map +1 -1
  325. package/lib/module/features/playback/trackPlaybackTime.js +88 -0
  326. package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
  327. package/lib/module/features/playback/volume.js +1 -1
  328. package/lib/module/features/player/options.js +48 -13
  329. package/lib/module/features/player/options.js.map +1 -1
  330. package/lib/module/features/player/setup.js +249 -3
  331. package/lib/module/features/player/setup.js.map +1 -1
  332. package/lib/module/features/queue/queue.js +10 -3
  333. package/lib/module/features/queue/queue.js.map +1 -1
  334. package/lib/module/features/remoteControls.js +0 -11
  335. package/lib/module/features/remoteControls.js.map +1 -1
  336. package/lib/module/features/sleepTimer.js +9 -4
  337. package/lib/module/features/sleepTimer.js.map +1 -1
  338. package/lib/module/native.js +5 -0
  339. package/lib/module/native.js.map +1 -1
  340. package/lib/module/native.web.js +4 -1
  341. package/lib/module/native.web.js.map +1 -1
  342. package/lib/module/utils/LazyNativeEmitter.js +0 -3
  343. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  344. package/lib/module/utils/NativeUpdatedValue.js +0 -3
  345. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  346. package/lib/module/utils/artwork.js +26 -0
  347. package/lib/module/utils/artwork.js.map +1 -0
  348. package/lib/module/web/NativeAudioBrowser.js +302 -125
  349. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  350. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
  351. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  352. package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
  353. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  354. package/lib/module/web/TrackPlayer/Player.js +90 -26
  355. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  356. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
  357. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  358. package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
  359. package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
  360. package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
  361. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
  362. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  363. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  364. package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
  365. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  366. package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
  367. package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
  368. package/lib/module/web/TrackPlayer/index.js +2 -1
  369. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  370. package/lib/module/web/browser/BrowserManager.js +176 -50
  371. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  372. package/lib/module/web/browser/NavigationErrorManager.js +3 -1
  373. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  374. package/lib/module/web/browser/SearchManager.js +11 -9
  375. package/lib/module/web/browser/SearchManager.js.map +1 -1
  376. package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
  377. package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
  378. package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
  379. package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
  380. package/lib/module/web/browser/parseSearchResponse.js +16 -0
  381. package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
  382. package/lib/module/web/http/HttpClient.js +4 -23
  383. package/lib/module/web/http/HttpClient.js.map +1 -1
  384. package/lib/module/web/http/RequestConfigBuilder.js +107 -58
  385. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  386. package/lib/module/web/playbackErrorKind.js +52 -0
  387. package/lib/module/web/playbackErrorKind.js.map +1 -0
  388. package/lib/module/web/player/MediaSessionManager.js +116 -0
  389. package/lib/module/web/player/MediaSessionManager.js.map +1 -0
  390. package/lib/module/web/player/NowPlayingManager.js +7 -5
  391. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  392. package/lib/module/web/player/OptionsManager.js +9 -17
  393. package/lib/module/web/player/OptionsManager.js.map +1 -1
  394. package/lib/module/web/player/RemoteCommandController.js +92 -0
  395. package/lib/module/web/player/RemoteCommandController.js.map +1 -0
  396. package/lib/typescript/src/features/browser-config.d.ts +12 -0
  397. package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
  398. package/lib/typescript/src/features/browser.d.ts +40 -1
  399. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  400. package/lib/typescript/src/features/carConnection.d.ts +20 -0
  401. package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
  402. package/lib/typescript/src/features/errors.d.ts +58 -3
  403. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  404. package/lib/typescript/src/features/gate.d.ts +77 -0
  405. package/lib/typescript/src/features/gate.d.ts.map +1 -0
  406. package/lib/typescript/src/features/index.d.ts +2 -0
  407. package/lib/typescript/src/features/index.d.ts.map +1 -1
  408. package/lib/typescript/src/features/metadata.d.ts +6 -4
  409. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  410. package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
  411. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  412. package/lib/typescript/src/features/output.d.ts +28 -18
  413. package/lib/typescript/src/features/output.d.ts.map +1 -1
  414. package/lib/typescript/src/features/playback/controls.d.ts +5 -0
  415. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  416. package/lib/typescript/src/features/playback/index.d.ts +1 -0
  417. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  418. package/lib/typescript/src/features/playback/progress.d.ts +3 -0
  419. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  420. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
  421. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
  422. package/lib/typescript/src/features/playback/volume.d.ts +1 -1
  423. package/lib/typescript/src/features/player/options.d.ts +92 -93
  424. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  425. package/lib/typescript/src/features/player/setup.d.ts +206 -167
  426. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  427. package/lib/typescript/src/features/queue/queue.d.ts +9 -2
  428. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  429. package/lib/typescript/src/features/remoteControls.d.ts +0 -13
  430. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  431. package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
  432. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  433. package/lib/typescript/src/index.d.ts.map +1 -1
  434. package/lib/typescript/src/native.d.ts +1 -2
  435. package/lib/typescript/src/native.d.ts.map +1 -1
  436. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
  437. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  438. package/lib/typescript/src/types/browser-native.d.ts +9 -3
  439. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  440. package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
  441. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  442. package/lib/typescript/src/types/browser.d.ts +349 -85
  443. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  444. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
  445. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  446. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
  447. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  448. package/lib/typescript/src/utils/artwork.d.ts +19 -0
  449. package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
  450. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  451. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
  452. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
  453. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  454. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
  455. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
  456. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
  457. package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
  458. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  459. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
  460. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
  461. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
  462. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
  463. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
  464. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
  465. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
  466. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
  467. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
  468. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
  469. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
  470. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
  471. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
  472. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
  473. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -0
  474. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +131 -0
  475. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
  476. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
  477. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
  478. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
  479. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
  480. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
  481. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
  482. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
  483. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  484. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
  485. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
  486. package/nitrogen/generated/android/c++/JGate.hpp +62 -0
  487. package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
  488. package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
  489. package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
  490. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
  491. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
  492. package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
  493. package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
  494. package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
  495. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
  496. package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
  497. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
  498. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
  499. package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
  500. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
  501. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
  502. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
  503. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
  504. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
  505. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
  506. package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
  507. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
  508. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
  509. package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
  510. package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
  511. package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
  512. package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
  513. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
  514. package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
  515. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
  516. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
  517. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  518. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
  519. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
  520. package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
  521. package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
  522. package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
  523. package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
  524. package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
  525. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
  526. package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
  527. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
  528. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
  529. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
  530. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
  531. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
  532. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
  533. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
  534. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  535. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
  536. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
  537. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
  538. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  539. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
  540. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
  541. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
  542. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  543. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
  544. 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 +80 -0
  545. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
  546. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
  547. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
  548. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
  549. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
  550. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt} +12 -12
  551. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
  552. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
  553. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  554. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
  555. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
  556. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
  557. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
  558. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
  559. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
  560. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
  561. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
  562. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
  563. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
  564. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
  565. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
  566. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
  567. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  568. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
  569. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  570. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
  571. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
  572. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
  573. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
  574. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
  575. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
  576. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  577. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
  578. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
  579. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
  580. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
  581. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  582. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  583. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
  584. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
  585. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
  586. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
  587. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
  588. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
  589. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
  590. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
  591. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
  592. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
  593. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
  594. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
  595. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
  596. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
  597. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
  598. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  599. package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
  600. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
  601. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
  602. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  603. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
  604. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
  605. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
  606. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
  607. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
  608. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
  609. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
  610. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
  611. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
  612. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
  613. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
  614. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +77 -0
  615. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
  616. package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
  617. package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
  618. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
  619. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  620. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
  621. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
  622. package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift → Func_void_std__shared_ptr_Promise_GateDecision__.swift} +17 -17
  623. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
  624. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
  625. package/nitrogen/generated/ios/swift/Gate.swift +47 -0
  626. package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
  627. package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
  628. package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
  629. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
  630. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
  631. package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
  632. package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
  633. package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
  634. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
  635. package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
  636. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
  637. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
  638. package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
  639. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  640. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
  641. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
  642. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
  643. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
  644. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
  645. package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
  646. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
  647. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
  648. package/nitrogen/generated/ios/swift/Options.swift +10 -4
  649. package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
  650. package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
  651. package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
  652. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
  653. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  654. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
  655. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
  656. package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
  657. package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
  658. package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
  659. package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
  660. package/nitrogen/generated/ios/swift/Track.swift +74 -8
  661. package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
  662. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
  663. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
  664. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
  665. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
  666. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  667. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
  668. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
  669. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
  670. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  671. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
  672. package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
  673. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
  674. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
  675. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
  676. package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
  677. package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
  678. package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
  679. package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
  680. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
  681. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
  682. package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
  683. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
  684. package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
  685. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
  686. package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
  687. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
  688. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
  689. package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
  690. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  691. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
  692. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
  693. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
  694. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
  695. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
  696. package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
  697. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
  698. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
  699. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  700. package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
  701. package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
  702. package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
  703. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
  704. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  705. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
  706. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
  707. package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
  708. package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
  709. package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
  710. package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
  711. package/nitrogen/generated/shared/c++/Track.hpp +24 -5
  712. package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
  713. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
  714. package/package.json +11 -6
  715. package/src/codegen-no-config-variant.test.ts +70 -0
  716. package/src/features/browser-config.test.ts +110 -0
  717. package/src/features/browser-config.ts +293 -0
  718. package/src/features/browser.test.ts +19 -0
  719. package/src/features/browser.ts +58 -201
  720. package/src/features/carConnection.ts +36 -0
  721. package/src/features/errors.ts +68 -2
  722. package/src/features/gate.test.ts +72 -0
  723. package/src/features/gate.ts +155 -0
  724. package/src/features/index.ts +2 -0
  725. package/src/features/metadata.ts +6 -12
  726. package/src/features/nowPlaying.ts +36 -0
  727. package/src/features/output.ts +35 -22
  728. package/src/features/playback/controls.ts +8 -0
  729. package/src/features/playback/index.ts +1 -0
  730. package/src/features/playback/progress.ts +31 -12
  731. package/src/features/playback/trackPlaybackTime.test.ts +66 -0
  732. package/src/features/playback/trackPlaybackTime.ts +106 -0
  733. package/src/features/playback/volume.ts +1 -1
  734. package/src/features/player/options.test.ts +38 -0
  735. package/src/features/player/options.ts +140 -75
  736. package/src/features/player/setup.test.ts +117 -0
  737. package/src/features/player/setup.ts +390 -175
  738. package/src/features/queue/queue.test.ts +36 -0
  739. package/src/features/queue/queue.ts +15 -4
  740. package/src/features/remoteControls.ts +0 -23
  741. package/src/features/sleepTimer.ts +23 -4
  742. package/src/native.ts +5 -0
  743. package/src/native.web.ts +4 -1
  744. package/src/specs/audio-browser.nitro.ts +131 -41
  745. package/src/types/browser-native.ts +19 -6
  746. package/src/types/browser-nodes.ts +160 -13
  747. package/src/types/browser.ts +377 -89
  748. package/src/utils/LazyNativeEmitter.ts +0 -2
  749. package/src/utils/NativeUpdatedValue.ts +0 -2
  750. package/src/utils/artwork.ts +30 -0
  751. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
  752. package/src/web/NativeAudioBrowser.ts +365 -158
  753. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
  754. package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
  755. package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
  756. package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
  757. package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
  758. package/src/web/TrackPlayer/Player.load.test.ts +86 -0
  759. package/src/web/TrackPlayer/Player.ts +113 -39
  760. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
  761. package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
  762. package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
  763. package/src/web/TrackPlayer/QueueManager.ts +302 -0
  764. package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
  765. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  766. package/src/web/TrackPlayer/SleepTimer.ts +38 -3
  767. package/src/web/TrackPlayer/VolumeFader.ts +74 -0
  768. package/src/web/TrackPlayer/index.ts +2 -1
  769. package/src/web/browser/BrowserManager.ts +231 -62
  770. package/src/web/browser/NavigationErrorManager.ts +3 -1
  771. package/src/web/browser/SearchManager.ts +11 -15
  772. package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
  773. package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
  774. package/src/web/browser/assertBrowsePageShape.ts +27 -0
  775. package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
  776. package/src/web/browser/classifyTrackNavigation.ts +35 -0
  777. package/src/web/browser/parseSearchResponse.test.ts +25 -0
  778. package/src/web/browser/parseSearchResponse.ts +15 -0
  779. package/src/web/http/HttpClient.ts +5 -35
  780. package/src/web/http/RequestConfigBuilder.test.ts +59 -0
  781. package/src/web/http/RequestConfigBuilder.ts +120 -63
  782. package/src/web/playbackErrorKind.test.ts +55 -0
  783. package/src/web/playbackErrorKind.ts +56 -0
  784. package/src/web/player/MediaSessionManager.test.ts +220 -0
  785. package/src/web/player/MediaSessionManager.ts +151 -0
  786. package/src/web/player/NowPlayingManager.test.ts +46 -0
  787. package/src/web/player/NowPlayingManager.ts +6 -5
  788. package/src/web/player/OptionsManager.ts +12 -18
  789. package/src/web/player/RemoteCommandController.test.ts +171 -0
  790. package/src/web/player/RemoteCommandController.ts +166 -0
  791. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
  792. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
  793. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
  794. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
  795. package/ios/CarPlay/Track+CarPlay.swift +0 -63
  796. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
  797. package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
  798. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
  799. package/lib/commonjs/features/rating.js +0 -2
  800. package/lib/commonjs/features/rating.js.map +0 -1
  801. package/lib/commonjs/types/player.js +0 -2
  802. package/lib/commonjs/types/player.js.map +0 -1
  803. package/lib/commonjs/web/SimpleRouter.test.js +0 -174
  804. package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
  805. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
  806. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  807. package/lib/module/features/rating.js +0 -2
  808. package/lib/module/features/rating.js.map +0 -1
  809. package/lib/module/types/player.js +0 -2
  810. package/lib/module/types/player.js.map +0 -1
  811. package/lib/module/web/SimpleRouter.test.js +0 -174
  812. package/lib/module/web/SimpleRouter.test.js.map +0 -1
  813. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
  814. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  815. package/lib/typescript/src/features/rating.d.ts +0 -14
  816. package/lib/typescript/src/features/rating.d.ts.map +0 -1
  817. package/lib/typescript/src/native.web.d.ts +0 -3
  818. package/lib/typescript/src/native.web.d.ts.map +0 -1
  819. package/lib/typescript/src/types/player.d.ts +0 -64
  820. package/lib/typescript/src/types/player.d.ts.map +0 -1
  821. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
  822. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
  823. package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
  824. package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
  825. package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
  826. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
  827. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
  828. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
  829. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
  830. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
  831. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
  832. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
  833. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
  834. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
  835. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
  836. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
  837. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
  838. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
  839. package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
  840. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
  841. package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
  842. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
  843. package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
  844. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
  845. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
  846. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
  847. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
  848. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
  849. package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
  850. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
  851. package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
  852. package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
  853. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
  854. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
  855. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
  856. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
  857. package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
  858. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
  859. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
  860. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
  861. package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
  862. package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
  863. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
  864. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
  865. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
  866. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
  867. package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
  868. package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
  869. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
  870. package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
  871. package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
  872. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
  873. package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
  874. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
  875. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
  876. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
  881. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
  882. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
  883. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
  884. package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
  885. package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
  886. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
  887. package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
  888. package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
  889. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
  890. package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
  891. package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
  892. package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
  893. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
  894. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
  895. package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
  896. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
  897. package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
  898. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
  899. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
  900. package/src/features/rating.ts +0 -17
  901. package/src/types/player.ts +0 -69
  902. package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
@@ -0,0 +1,348 @@
1
+ package com.audiobrowser.player
2
+
3
+ import com.audiobrowser.util.url
4
+
5
+ import com.margelo.nitro.audiobrowser.FormatNowPlayingParams
6
+ import com.margelo.nitro.audiobrowser.NowPlayingMetadata
7
+ import com.margelo.nitro.audiobrowser.NowPlayingUpdate
8
+ import com.margelo.nitro.audiobrowser.PlaybackError
9
+ import com.margelo.nitro.audiobrowser.PlaybackState
10
+ import com.margelo.nitro.audiobrowser.StallReason
11
+ import com.margelo.nitro.audiobrowser.TimedMetadata
12
+ import com.margelo.nitro.audiobrowser.Track
13
+ import kotlinx.coroutines.CoroutineScope
14
+ import kotlinx.coroutines.Job
15
+ import kotlinx.coroutines.cancel
16
+ import kotlinx.coroutines.delay
17
+ import kotlinx.coroutines.launch
18
+ import timber.log.Timber
19
+
20
+ /**
21
+ * What the now-playing logic needs from the platform — implemented by [Player] (current playback
22
+ * reads, MediaItem stamping via `replaceMediaItem`, artwork resolution through the browser).
23
+ * Mirrors iOS's NowPlayingUpdater / NowPlayingInfoController split: this seam is what makes the
24
+ * precedence/guard/dedupe logic testable with a fake.
25
+ */
26
+ interface NowPlayingSurface {
27
+ val currentIndex: Int?
28
+ val currentTrack: Track?
29
+ val playbackState: PlaybackState
30
+ val playbackError: PlaybackError?
31
+
32
+ /**
33
+ * MUST be the real play/pause intent read from the underlying ExoPlayer — not the
34
+ * InterceptingPlayer-masked value, which can report false through a masked terminal error to keep
35
+ * the session paused-but-alive. The formatter receives this; feeding it the masked value breaks
36
+ * its output exactly in the error case the mask exists for.
37
+ */
38
+ val playWhenReady: Boolean
39
+ val isRebuffering: Boolean
40
+
41
+ /** Device connectivity, used to classify a stall as offline vs a plain rebuffer. */
42
+ val isOnline: Boolean
43
+
44
+ val hasNowPlayingArtworkConfig: Boolean
45
+
46
+ /** Stamp title/secondary/album onto the playing item. */
47
+ fun stampFields(index: Int, track: Track, title: String?, secondaryLine: String?, album: String?)
48
+
49
+ /** Stamp a resolved artwork uri onto the playing item. */
50
+ fun stampArtwork(index: Int, track: Track, uri: String)
51
+
52
+ /**
53
+ * Resolve the now-playing artwork for [track] via the `nowPlayingArtwork` config kind. Returns
54
+ * the final uri, or null when resolution produced nothing (errors are logged inside).
55
+ */
56
+ suspend fun resolveNowPlayingArtwork(track: Track, sizePx: Double): String?
57
+
58
+ fun emitNowPlayingChanged(metadata: NowPlayingMetadata)
59
+ }
60
+
61
+ /**
62
+ * Owns the Now Playing rendering pipeline: the flash > override > formatter > track precedence, the
63
+ * publish dedupe, the stale-result guards (render generation + track-id keying), timed (ICY)
64
+ * metadata, and the once-per-track artwork keying. Mirrors iOS's NowPlayingUpdater. The platform is
65
+ * reached only through [NowPlayingSurface]; the JS formatter arrives as a plain suspend lambda
66
+ * (wrapped at the Nitro boundary in Player.setup), so every guard here runs under JVM tests.
67
+ */
68
+ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scope: CoroutineScope) {
69
+
70
+ /** Whether now-playing rendering (override/flash/formatter) is enabled (PlayerSetupOptions). */
71
+ var enabled = true
72
+
73
+ /** The JS formatter, wrapped to a plain suspend call at the Nitro boundary (see Player.setup). */
74
+ var formatter: (suspend (FormatNowPlayingParams) -> NowPlayingUpdate?)? = null
75
+
76
+ /** Latest live timed (ICY/ID3) metadata; cleared on track change. */
77
+ @Volatile private var latestTimedMetadata: TimedMetadata? = null
78
+
79
+ /** Imperative override (from `updateNowPlaying()`); cleared on track change. */
80
+ private var override: NowPlayingUpdate? = null
81
+
82
+ /**
83
+ * Transient now-playing fields (e.g. feedback for a refused remote command). Outranks the
84
+ * formatter and the override while active, so live metadata can't stomp it mid-flash. Reverted by
85
+ * a coroutine delay on [scope] — NOT a JS timer, which pauses with a backgrounded host (and the
86
+ * lock screen is exactly the backgrounded case) — and cleared early on track change.
87
+ */
88
+ private var flash: NowPlayingUpdate? = null
89
+ private var flashRevert: Job? = null
90
+
91
+ /**
92
+ * Monotonic stamp for renders. An async formatter result applies only when no newer render —
93
+ * notably a flash — has superseded the one that launched it.
94
+ */
95
+ private var renderGeneration = 0L
96
+
97
+ /** The last fields actually published, to dedupe redundant stamps. */
98
+ private data class Published(
99
+ val index: Int,
100
+ val trackId: String?,
101
+ val title: String?,
102
+ val secondaryLine: String?,
103
+ val album: String?,
104
+ )
105
+
106
+ private var lastPublished: Published? = null
107
+
108
+ /**
109
+ * The track id whose now-playing artwork has been resolved (or is being resolved), so a
110
+ * `nowPlayingArtwork` resolve runs once per track instead of on every render.
111
+ */
112
+ private var artworkResolvedForTrackId: String? = null
113
+
114
+ /** Size hint (px, square) for now-playing artwork. Mirrors iOS (screen-width-capped to 1200). */
115
+ private val artworkSizePx = 1200.0
116
+
117
+ /** Cancels in-flight work. Called from Player.destroy. */
118
+ fun destroy() {
119
+ scope.cancel()
120
+ }
121
+
122
+ /** Sets/clears the imperative override (null reverts to track metadata) and re-renders. */
123
+ fun updateNowPlaying(update: NowPlayingUpdate?) {
124
+ override = update
125
+ render()
126
+ }
127
+
128
+ fun flashNowPlaying(update: NowPlayingUpdate, durationMs: Double) {
129
+ flashRevert?.cancel()
130
+ flash = update
131
+ flashRevert =
132
+ scope.launch {
133
+ delay(durationMs.toLong())
134
+ flash = null
135
+ flashRevert = null
136
+ render()
137
+ }
138
+ render()
139
+ }
140
+
141
+ /** Clears an active flash immediately, reverting to the live metadata. No-op when none. */
142
+ fun clearNowPlayingFlash() {
143
+ if (flash == null) return
144
+ cancelFlash()
145
+ render()
146
+ }
147
+
148
+ private fun cancelFlash() {
149
+ flashRevert?.cancel()
150
+ flashRevert = null
151
+ flash = null
152
+ }
153
+
154
+ /** Gets the current now playing metadata (flash/override if set, else track metadata). */
155
+ fun getNowPlaying(): NowPlayingMetadata? {
156
+ val track = surface.currentTrack ?: return null
157
+ val flash = flash
158
+ val override = override
159
+
160
+ return NowPlayingMetadata(
161
+ elapsedTime = null,
162
+ title = flash?.title ?: override?.title ?: track.title,
163
+ album = flash?.album ?: override?.album ?: track.album,
164
+ artist = flash?.artist ?: override?.artist ?: track.artist,
165
+ duration = track.duration,
166
+ artwork = track.artwork?.url,
167
+ description = track.description,
168
+ mediaId = track.src ?: track.url,
169
+ genre = track.genre,
170
+ )
171
+ }
172
+
173
+ /** Clears override, flash, and timed metadata on track change (PlayerListener transition). */
174
+ fun clearOverride() {
175
+ override = null
176
+ cancelFlash()
177
+ latestTimedMetadata = null
178
+ }
179
+
180
+ /**
181
+ * Records the latest live timed (ICY/ID3) metadata and, when a formatter is configured, re-runs
182
+ * it so the live song is reflected on the now-playing surface.
183
+ */
184
+ fun onTimedMetadataReceived(timed: TimedMetadata) {
185
+ latestTimedMetadata = timed
186
+ if (enabled && formatter != null) {
187
+ render()
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Renders the current now playing metadata to the surface. Flash wins while active (formatter
193
+ * skipped entirely so its async result can't land on top); otherwise the override-or-track
194
+ * default is stamped immediately and a configured formatter customizes it asynchronously, guarded
195
+ * by track identity and [renderGeneration].
196
+ */
197
+ fun render() {
198
+ val index = surface.currentIndex ?: return
199
+ val track = surface.currentTrack ?: return
200
+ renderGeneration += 1
201
+ val generation = renderGeneration
202
+
203
+ // Metadata source. When metadata is disabled, use the raw track (ignore override + formatter);
204
+ // otherwise the imperative `updateNowPlaying` override wins over the track's own fields.
205
+ val activeOverride = if (enabled) override else null
206
+ val defaultTitle = activeOverride?.title ?: track.title
207
+ val defaultSecondary = activeOverride?.artist ?: track.artist
208
+ val defaultAlbum = activeOverride?.album ?: track.album
209
+
210
+ // A flash outranks both the formatter and the override; while one is active the formatter pass
211
+ // is skipped entirely so its async result can't land on top.
212
+ val activeFlash = if (enabled) flash else null
213
+ if (activeFlash != null) {
214
+ applyFields(
215
+ index,
216
+ track,
217
+ activeFlash.title ?: defaultTitle,
218
+ activeFlash.artist ?: defaultSecondary,
219
+ activeFlash.album ?: defaultAlbum,
220
+ )
221
+ return
222
+ }
223
+
224
+ // Apply the default immediately so the now-playing never lags a track/status change.
225
+ applyFields(index, track, defaultTitle, defaultSecondary, defaultAlbum)
226
+
227
+ // If a formatter is configured, let it customize the fields asynchronously. Falls back to the
228
+ // default on null/throw.
229
+ val activeFormatter = if (enabled) formatter else null
230
+ if (activeFormatter != null) {
231
+ val capturedId = track.src ?: track.url
232
+ // Gate the raw load-control signal to the buffering state so `stalled` is correct on its
233
+ // own: ExoPlayer's rebuffering flag is polled on a different cadence than state transitions
234
+ // and can linger true into the PLAYING transition as a rebuffer recovers. Classify by
235
+ // connectivity so the formatter can show "offline" vs a plain rebuffer; null when not
236
+ // stalled.
237
+ val isStalled = surface.playbackState == PlaybackState.BUFFERING && surface.isRebuffering
238
+ val stalled =
239
+ if (isStalled) {
240
+ if (surface.isOnline) StallReason.BUFFERING else StallReason.OFFLINE
241
+ } else {
242
+ null
243
+ }
244
+ val params =
245
+ FormatNowPlayingParams(
246
+ track,
247
+ latestTimedMetadata,
248
+ surface.playWhenReady,
249
+ stalled,
250
+ surface.playbackError,
251
+ )
252
+ scope.launch {
253
+ val formatted =
254
+ try {
255
+ activeFormatter(params)
256
+ } catch (e: Exception) {
257
+ Timber.e(e, "NowPlaying formatter threw; using default")
258
+ null
259
+ }
260
+ // Apply only if still the same track (a fast skip must not be overwritten by a stale
261
+ // result) AND no newer render superseded this one — without the generation check, a
262
+ // formatter round-trip in flight when a flash starts lands a beat later and overwrites
263
+ // the flash (mirrors the iOS renderGeneration guard).
264
+ val current = surface.currentTrack
265
+ val currentIdx = surface.currentIndex
266
+ if (
267
+ formatted != null &&
268
+ current != null &&
269
+ currentIdx != null &&
270
+ (current.src ?: current.url) == capturedId &&
271
+ renderGeneration == generation
272
+ ) {
273
+ applyFields(
274
+ currentIdx,
275
+ current,
276
+ formatted.title ?: defaultTitle,
277
+ formatted.artist ?: defaultSecondary,
278
+ formatted.album ?: defaultAlbum,
279
+ )
280
+ }
281
+ }
282
+ }
283
+ }
284
+
285
+ /** Stamps the fields via the surface, deduped on (index, track identity, fields). */
286
+ private fun applyFields(
287
+ index: Int,
288
+ track: Track,
289
+ title: String?,
290
+ secondaryLine: String?,
291
+ album: String?,
292
+ ) {
293
+ // Skip republishing identical fields. The formatter is re-invoked on every state change, so
294
+ // the same fields are recomputed often; an unconditional stamp would churn the MediaSession
295
+ // (and flicker Android Auto / now-playing) for no visible change. Keyed on the track identity
296
+ // so a new track with a coincidentally identical line still publishes.
297
+ val published = Published(index, track.src ?: track.url, title, secondaryLine, album)
298
+ if (published == lastPublished) return
299
+ lastPublished = published
300
+
301
+ surface.stampFields(index, track, title, secondaryLine, album)
302
+ getNowPlaying()?.let { surface.emitNowPlayingChanged(it) }
303
+
304
+ // Resolve the now-playing-only artwork (lock screen / notification / Android Auto
305
+ // now-playing), keyed on track id so it runs once per track and not on every render.
306
+ maybeResolveArtwork(track)
307
+ }
308
+
309
+ /**
310
+ * Resolves the playing track's now-playing artwork and stamps it onto the playing media item.
311
+ * Guarded exactly like iOS: only when `nowPlayingArtwork` is configured AND the track has a
312
+ * non-empty id (so the `{id}` token never resolves to an empty string). Otherwise the existing
313
+ * artworkUri — which came from `artwork` (browse list path) — is left in place.
314
+ */
315
+ private fun maybeResolveArtwork(track: Track) {
316
+ val trackId =
317
+ track.id?.takeIf { it.isNotEmpty() }
318
+ ?: run {
319
+ // No id → skip nowPlayingArtwork entirely; keep the existing (browse) artworkUri.
320
+ artworkResolvedForTrackId = null
321
+ return
322
+ }
323
+
324
+ if (!surface.hasNowPlayingArtworkConfig) {
325
+ // No now-playing artwork config (or no browser) → fall back to the existing artworkUri.
326
+ artworkResolvedForTrackId = null
327
+ return
328
+ }
329
+
330
+ // Already resolved (or resolving) for this track id — avoid a redundant resolve per render.
331
+ if (artworkResolvedForTrackId == trackId) return
332
+ artworkResolvedForTrackId = trackId
333
+
334
+ scope.launch {
335
+ val uri =
336
+ surface.resolveNowPlayingArtwork(track, artworkSizePx)?.takeIf { it.isNotEmpty() }
337
+ ?: return@launch
338
+
339
+ // Apply only if still the same track (a fast skip must not be overwritten by a stale
340
+ // result).
341
+ val currentIdx = surface.currentIndex ?: return@launch
342
+ val current = surface.currentTrack ?: return@launch
343
+ if (current.id != trackId) return@launch
344
+
345
+ surface.stampArtwork(currentIdx, current, uri)
346
+ }
347
+ }
348
+ }
@@ -0,0 +1,129 @@
1
+ package com.audiobrowser.player
2
+
3
+ import androidx.media3.common.PlaybackException
4
+ import androidx.media3.datasource.HttpDataSource.InvalidResponseCodeException
5
+ import com.margelo.nitro.audiobrowser.PlaybackError
6
+ import com.margelo.nitro.audiobrowser.PlaybackErrorKind
7
+ import java.io.IOException
8
+
9
+ /**
10
+ * Maps ExoPlayer's failure codes onto [PlaybackErrorKind], the cross-platform contract iOS
11
+ * populates from AVFoundation. Consumers branch on the kind; the raw ExoPlayer code still travels
12
+ * alongside it as `PlaybackError.code` for telemetry.
13
+ *
14
+ * Codes that carry no real evidence of a cause (`ERROR_CODE_UNSPECIFIED`,
15
+ * `ERROR_CODE_IO_UNSPECIFIED`, a bad HTTP status whose response code we could not recover) stay
16
+ * [PlaybackErrorKind.UNKNOWN] rather than being guessed into a nicer-sounding bucket — a wrong
17
+ * classification is worse than an honest one, both for the listener and for the aggregates.
18
+ */
19
+ object PlaybackErrorClassifier {
20
+ /**
21
+ * Classifies a player failure.
22
+ *
23
+ * @param online whether the device had connectivity at the moment of failure. ExoPlayer's codes
24
+ * cannot distinguish "the device is offline" from "this stream is unreachable"; only the
25
+ * connectivity monitor can, which is why it is passed in.
26
+ */
27
+ fun classify(error: PlaybackException, online: Boolean): PlaybackErrorKind {
28
+ if (!online) return PlaybackErrorKind.OFFLINE
29
+ val responseCode = responseCode(error)
30
+ if (responseCode != null) return kindForHttpStatus(responseCode)
31
+ return kindForErrorCode(error.errorCode)
32
+ }
33
+
34
+ /** The HTTP status the server answered with, if this failure came from an HTTP response. */
35
+ fun responseCode(error: PlaybackException): Int? =
36
+ generateSequence(error.cause) { it.cause }
37
+ .filterIsInstance<InvalidResponseCodeException>()
38
+ .firstOrNull()
39
+ ?.responseCode
40
+
41
+ /**
42
+ * Classifies a load error the retry policy is still working on, as an advisory (`retrying`)
43
+ * [PlaybackError]. Load errors arrive as raw [IOException]s (see
44
+ * [RetryLoadErrorHandlingPolicy.classifyError]), never as [PlaybackException] — that shape only
45
+ * exists once retries are exhausted. The policy only retries HTTP statuses and transport
46
+ * failures, so a non-HTTP retryable load error is by construction a network one.
47
+ */
48
+ fun retryingLoadError(exception: IOException, online: Boolean): PlaybackError {
49
+ val responseCode =
50
+ generateSequence(exception as Throwable) { it.cause }
51
+ .filterIsInstance<InvalidResponseCodeException>()
52
+ .firstOrNull()
53
+ ?.responseCode
54
+ // Fixed message per classification (mirrors iOS's localized descriptions): raw
55
+ // IOException messages vary between attempts of the same outage, which would defeat
56
+ // the caller's identical-repeat dedupe and churn the wire payload.
57
+ val (kind, code, message) =
58
+ when {
59
+ !online ->
60
+ Triple(PlaybackErrorKind.OFFLINE, "not-connected-to-internet", "No internet connection")
61
+ responseCode != null ->
62
+ Triple(
63
+ kindForHttpStatus(responseCode),
64
+ "io-bad-http-status",
65
+ "Server responded with HTTP $responseCode",
66
+ )
67
+ else ->
68
+ Triple(
69
+ PlaybackErrorKind.UNREACHABLE,
70
+ "io-network-connection-failed",
71
+ "Could not reach the stream host",
72
+ )
73
+ }
74
+ return PlaybackError(kind, code, message, responseCode?.toDouble(), retrying = true)
75
+ }
76
+
77
+ fun kindForHttpStatus(status: Int): PlaybackErrorKind =
78
+ when (status) {
79
+ 404,
80
+ 410 -> PlaybackErrorKind.NOT_FOUND
81
+ in 500..599 -> PlaybackErrorKind.SERVER_ERROR
82
+ // Every other 4xx is the server refusing us — auth, geo-blocking, a rate limit. All of them
83
+ // mean "you can't have this stream", not "retry".
84
+ in 400..499 -> PlaybackErrorKind.REJECTED
85
+ else -> PlaybackErrorKind.UNKNOWN
86
+ }
87
+
88
+ private fun kindForErrorCode(errorCode: Int): PlaybackErrorKind =
89
+ when (errorCode) {
90
+ PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
91
+ PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
92
+ PlaybackException.ERROR_CODE_TIMEOUT -> PlaybackErrorKind.UNREACHABLE
93
+
94
+ PlaybackException.ERROR_CODE_IO_FILE_NOT_FOUND -> PlaybackErrorKind.NOT_FOUND
95
+
96
+ // The server, the licence server, or the session refused us.
97
+ PlaybackException.ERROR_CODE_IO_NO_PERMISSION,
98
+ PlaybackException.ERROR_CODE_AUTHENTICATION_EXPIRED,
99
+ PlaybackException.ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
100
+ PlaybackException.ERROR_CODE_CONCURRENT_STREAM_LIMIT,
101
+ PlaybackException.ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
102
+ PlaybackException.ERROR_CODE_NOT_AVAILABLE_IN_REGION,
103
+ in DRM_CODES -> PlaybackErrorKind.REJECTED
104
+
105
+ // Fetched, but nothing we can turn into audio: wrong content type, malformed or unsupported
106
+ // container, a decoder that refused it, or an output track we could not open.
107
+ PlaybackException.ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
108
+ PlaybackException.ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
109
+ PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE,
110
+ PlaybackException.ERROR_CODE_NOT_SUPPORTED,
111
+ in PARSING_CODES,
112
+ in DECODING_CODES,
113
+ in AUDIO_TRACK_CODES -> PlaybackErrorKind.UNPLAYABLE
114
+
115
+ else -> PlaybackErrorKind.UNKNOWN
116
+ }
117
+
118
+ private val PARSING_CODES =
119
+ PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED..PlaybackException
120
+ .ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED
121
+ private val DECODING_CODES =
122
+ PlaybackException.ERROR_CODE_DECODER_INIT_FAILED..PlaybackException
123
+ .ERROR_CODE_DECODING_RESOURCES_RECLAIMED
124
+ private val AUDIO_TRACK_CODES =
125
+ PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED..PlaybackException
126
+ .ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED
127
+ private val DRM_CODES =
128
+ PlaybackException.ERROR_CODE_DRM_UNSPECIFIED..PlaybackException.ERROR_CODE_DRM_LICENSE_EXPIRED
129
+ }
@@ -0,0 +1,85 @@
1
+ package com.audiobrowser.player
2
+
3
+ import androidx.media3.common.Player as MediaPlayer
4
+ import com.margelo.nitro.audiobrowser.PlaybackState
5
+
6
+ /**
7
+ * An observation that may move the playback state machine. Context (does a track exist, is the
8
+ * engine audibly playing, the queue size) is captured into the event at the call site —
9
+ * [PlaybackStateMachine] itself stays pure.
10
+ */
11
+ sealed interface PlaybackEvent {
12
+ /**
13
+ * ExoPlayer's playback state changed. [exoState] MUST be the real ExoPlayer state, not the
14
+ * InterceptingPlayer-masked value (which reports READY through a masked terminal error to keep
15
+ * the session alive — feeding that back in would clear the ERROR state).
16
+ */
17
+ data class ExoPlaybackStateChanged(
18
+ @get:MediaPlayer.State val exoState: Int,
19
+ val mediaItemCount: Int,
20
+ val playWhenReady: Boolean,
21
+ ) : PlaybackEvent
22
+
23
+ /** The active media item changed (auto-advance, skip, queue swap). */
24
+ data class MediaItemTransition(val hasTrack: Boolean, val isPlaying: Boolean) : PlaybackEvent
25
+
26
+ data class PlayWhenReadyChanged(val playWhenReady: Boolean) : PlaybackEvent
27
+
28
+ data class IsPlayingChanged(val isPlaying: Boolean) : PlaybackEvent
29
+ }
30
+
31
+ /**
32
+ * The playback state transitions: the next states (in order) for an event from the current state,
33
+ * empty to suppress. The Android analog of iOS's `nextPlaybackState(from:on:)` — guards here are
34
+ * state-related ("not from ERROR/STOPPED"); context-related guards live in the event fields.
35
+ * Effects (error clearing, event emission, timers) stay with the caller: the machine only decides.
36
+ */
37
+ object PlaybackStateMachine {
38
+
39
+ fun transitions(current: PlaybackState, event: PlaybackEvent): List<PlaybackState> =
40
+ when (event) {
41
+ is PlaybackEvent.ExoPlaybackStateChanged ->
42
+ when (event.exoState) {
43
+ MediaPlayer.STATE_BUFFERING -> listOf(PlaybackState.BUFFERING)
44
+ MediaPlayer.STATE_READY ->
45
+ // While playing (playWhenReady), READY is a transient before PLAYING —
46
+ // suppress it so consumers don't flash a settled/non-loading state
47
+ // mid-startup (none→loading→buffering→playing). When paused it IS the
48
+ // settled signal a buffer-that-finished-while-paused needs, so consumers
49
+ // can clear their loading spinner (mono#3325).
50
+ if (event.playWhenReady) emptyList() else listOf(PlaybackState.READY)
51
+ MediaPlayer.STATE_IDLE ->
52
+ // A terminal error (or an explicit stop) idles ExoPlayer; transitioning to NONE
53
+ // would clear the ERROR/STOPPED state the session is rendering.
54
+ if (current == PlaybackState.ERROR || current == PlaybackState.STOPPED) emptyList()
55
+ else listOf(PlaybackState.NONE)
56
+ MediaPlayer.STATE_ENDED ->
57
+ // An emptied queue also reports STATE_ENDED; without items that is "nothing
58
+ // loaded", not "played to end".
59
+ listOf(if (event.mediaItemCount > 0) PlaybackState.ENDED else PlaybackState.NONE)
60
+ else -> emptyList()
61
+ }
62
+ is PlaybackEvent.MediaItemTransition ->
63
+ when {
64
+ !event.hasTrack -> emptyList()
65
+ // Already audibly playing (gapless auto-advance): run the full burst so consumers
66
+ // see the canonical loading→ready→playing sequence rather than sticking on LOADING.
67
+ event.isPlaying ->
68
+ listOf(PlaybackState.LOADING, PlaybackState.READY, PlaybackState.PLAYING)
69
+ else -> listOf(PlaybackState.LOADING)
70
+ }
71
+ is PlaybackEvent.PlayWhenReadyChanged ->
72
+ // STOPPED and ENDED are terminal: dropping the intent there (stop()'s own
73
+ // clear, the clear on natural end, or a redundant pause press) must not
74
+ // re-report the state as PAUSED.
75
+ if (
76
+ !event.playWhenReady && current != PlaybackState.STOPPED && current != PlaybackState.ENDED
77
+ ) {
78
+ listOf(PlaybackState.PAUSED)
79
+ } else {
80
+ emptyList()
81
+ }
82
+ is PlaybackEvent.IsPlayingChanged ->
83
+ if (event.isPlaying) listOf(PlaybackState.PLAYING) else emptyList()
84
+ }
85
+ }
@@ -1,9 +1,14 @@
1
1
  package com.audiobrowser.player
2
2
 
3
+ import com.audiobrowser.util.artworkOf
4
+
5
+ import com.audiobrowser.util.url
6
+
3
7
  import android.content.Context
4
8
  import android.content.SharedPreferences
5
9
  import androidx.core.content.edit
6
10
  import androidx.media3.common.C
11
+ import com.margelo.nitro.audiobrowser.PlaybackState
7
12
  import com.margelo.nitro.audiobrowser.RepeatMode
8
13
  import com.margelo.nitro.audiobrowser.Track
9
14
  import com.margelo.nitro.audiobrowser.TrackStyle
@@ -96,11 +101,20 @@ class PlaybackStateStore(private val player: Player) {
96
101
  }
97
102
  }
98
103
 
99
- /** Stops periodic position saving and saves final position. Call when playback stops. */
100
- fun stopPeriodicSave() {
104
+ /** Cancels the periodic save without a final save. Call on engine teardown. */
105
+ fun cancelPeriodicSave() {
101
106
  periodicSaveJob?.cancel()
102
107
  periodicSaveJob = null
103
- if (!player.isCurrentItemLive) {
108
+ }
109
+
110
+ /** Stops periodic position saving and saves final position. Call when playback stops. */
111
+ fun stopPeriodicSave() {
112
+ cancelPeriodicSave()
113
+ // Skip the final save after a natural end: setPlaybackState(ENDED) wrote
114
+ // position 0 for resumption, and the intent-drop's listener echo runs this
115
+ // strictly afterwards — a save here would overwrite that 0 with the
116
+ // end-of-track position, making cold-start resume restart at the very end.
117
+ if (!player.isCurrentItemLive && player.playbackState != PlaybackState.ENDED) {
104
118
  savePosition()
105
119
  }
106
120
  }
@@ -139,13 +153,15 @@ class PlaybackStateStore(private val player: Player) {
139
153
  private fun trackToJson(track: Track): String =
140
154
  JSONObject()
141
155
  .apply {
156
+ put("id", track.id)
142
157
  put("url", track.url)
143
158
  put("src", track.src)
144
159
  put("title", track.title)
145
160
  put("subtitle", track.subtitle)
146
161
  put("artist", track.artist)
162
+ put("albumUrl", track.albumUrl)
147
163
  put("album", track.album)
148
- put("artwork", track.artwork)
164
+ put("artwork", track.artwork?.url)
149
165
  put("description", track.description)
150
166
  put("genre", track.genre)
151
167
  put("duration", track.duration)
@@ -161,13 +177,15 @@ class PlaybackStateStore(private val player: Player) {
161
177
  runCatching {
162
178
  val obj = JSONObject(json)
163
179
  Track(
180
+ id = obj.optString("id").takeIf { it.isNotEmpty() },
164
181
  url = obj.optString("url").takeIf { it.isNotEmpty() },
165
182
  src = obj.optString("src").takeIf { it.isNotEmpty() },
166
183
  title = obj.getString("title"),
167
184
  subtitle = obj.optString("subtitle").takeIf { it.isNotEmpty() },
168
185
  artist = obj.optString("artist").takeIf { it.isNotEmpty() },
186
+ albumUrl = obj.optString("albumUrl").takeIf { it.isNotEmpty() },
169
187
  album = obj.optString("album").takeIf { it.isNotEmpty() },
170
- artwork = obj.optString("artwork").takeIf { it.isNotEmpty() },
188
+ artwork = artworkOf(obj.optString("artwork").takeIf { it.isNotEmpty() }),
171
189
  artworkSource = null, // Not persisted - will be re-transformed on browse
172
190
  artworkCarPlayTinted = null, // iOS-only, not persisted
173
191
  description = obj.optString("description").takeIf { it.isNotEmpty() },
@@ -189,6 +207,10 @@ class PlaybackStateStore(private val player: Player) {
189
207
  else null,
190
208
  groupTitle = obj.optString("groupTitle").takeIf { it.isNotEmpty() },
191
209
  live = if (obj.has("live") && !obj.isNull("live")) obj.getBoolean("live") else null,
210
+ // Not persisted: on resumption the contextual URL is re-browsed
211
+ // (expandQueueFromContextualUrl), which re-parses each track's request
212
+ // from the API's current response and re-caches it.
213
+ request = null,
192
214
  imageRow = null, // Not persisted
193
215
  )
194
216
  }