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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (901) 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 +84 -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 +28 -10
  158. package/ios/Player/NowPlayingUpdater.swift +119 -26
  159. package/ios/Player/PersistedPlaybackState.swift +11 -0
  160. package/ios/Player/PlaybackCoordinator.swift +282 -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 +38 -5
  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 +23 -8
  184. package/ios/Tests/MediaResolveTests.swift +126 -0
  185. package/ios/Tests/OnceValueTests.swift +79 -0
  186. package/ios/Tests/PlaybackCoordinatorTests.swift +784 -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 +104 -0
  198. package/ios/Tests/Support/TestTypes.swift +61 -20
  199. package/ios/Tests/TabBarEntriesTests.swift +71 -0
  200. package/ios/Tests/TrackSelectorTests.swift +15 -15
  201. package/ios/TrackPlayer.swift +380 -58
  202. package/ios/TrackPlayerCallbacks.swift +0 -6
  203. package/ios/TrackSelector.swift +5 -5
  204. package/ios/Util/ArtworkImageFetcher.swift +4 -2
  205. package/ios/Util/NetworkMonitor.swift +7 -3
  206. package/ios/Util/OnceValue.swift +34 -0
  207. package/lib/commonjs/features/browser-config.js +227 -0
  208. package/lib/commonjs/features/browser-config.js.map +1 -0
  209. package/lib/commonjs/features/browser.js +59 -158
  210. package/lib/commonjs/features/browser.js.map +1 -1
  211. package/lib/commonjs/features/carConnection.js +42 -0
  212. package/lib/commonjs/features/carConnection.js.map +1 -0
  213. package/lib/commonjs/features/errors.js +34 -2
  214. package/lib/commonjs/features/errors.js.map +1 -1
  215. package/lib/commonjs/features/gate.js +149 -0
  216. package/lib/commonjs/features/gate.js.map +1 -0
  217. package/lib/commonjs/features/index.js +22 -0
  218. package/lib/commonjs/features/index.js.map +1 -1
  219. package/lib/commonjs/features/metadata.js.map +1 -1
  220. package/lib/commonjs/features/nowPlaying.js +35 -0
  221. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  222. package/lib/commonjs/features/output.js +37 -23
  223. package/lib/commonjs/features/output.js.map +1 -1
  224. package/lib/commonjs/features/playback/controls.js +9 -0
  225. package/lib/commonjs/features/playback/controls.js.map +1 -1
  226. package/lib/commonjs/features/playback/index.js +11 -0
  227. package/lib/commonjs/features/playback/index.js.map +1 -1
  228. package/lib/commonjs/features/playback/progress.js +28 -12
  229. package/lib/commonjs/features/playback/progress.js.map +1 -1
  230. package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
  231. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
  232. package/lib/commonjs/features/playback/volume.js +1 -1
  233. package/lib/commonjs/features/player/options.js +49 -13
  234. package/lib/commonjs/features/player/options.js.map +1 -1
  235. package/lib/commonjs/features/player/setup.js +249 -3
  236. package/lib/commonjs/features/player/setup.js.map +1 -1
  237. package/lib/commonjs/features/queue/queue.js +10 -3
  238. package/lib/commonjs/features/queue/queue.js.map +1 -1
  239. package/lib/commonjs/features/remoteControls.js +1 -12
  240. package/lib/commonjs/features/remoteControls.js.map +1 -1
  241. package/lib/commonjs/features/sleepTimer.js +9 -4
  242. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  243. package/lib/commonjs/native.js +5 -0
  244. package/lib/commonjs/native.js.map +1 -1
  245. package/lib/commonjs/native.web.js +4 -1
  246. package/lib/commonjs/native.web.js.map +1 -1
  247. package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
  248. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  249. package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
  250. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  251. package/lib/commonjs/utils/artwork.js +31 -0
  252. package/lib/commonjs/utils/artwork.js.map +1 -0
  253. package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
  254. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  255. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
  256. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  257. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
  258. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  259. package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
  260. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  261. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
  262. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  263. package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
  264. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
  265. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
  266. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
  267. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  268. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  269. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
  270. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  271. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
  272. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
  273. package/lib/commonjs/web/TrackPlayer/index.js +13 -5
  274. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  275. package/lib/commonjs/web/browser/BrowserManager.js +176 -50
  276. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  277. package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
  278. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  279. package/lib/commonjs/web/browser/SearchManager.js +11 -9
  280. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  281. package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
  282. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
  283. package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
  284. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
  285. package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
  286. package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
  287. package/lib/commonjs/web/http/HttpClient.js +4 -23
  288. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  289. package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
  290. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  291. package/lib/commonjs/web/playbackErrorKind.js +57 -0
  292. package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
  293. package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
  294. package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
  295. package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
  296. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  297. package/lib/commonjs/web/player/OptionsManager.js +9 -17
  298. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  299. package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
  300. package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
  301. package/lib/module/features/browser-config.js +221 -0
  302. package/lib/module/features/browser-config.js.map +1 -0
  303. package/lib/module/features/browser.js +53 -156
  304. package/lib/module/features/browser.js.map +1 -1
  305. package/lib/module/features/carConnection.js +37 -0
  306. package/lib/module/features/carConnection.js.map +1 -0
  307. package/lib/module/features/errors.js +34 -2
  308. package/lib/module/features/errors.js.map +1 -1
  309. package/lib/module/features/gate.js +144 -0
  310. package/lib/module/features/gate.js.map +1 -0
  311. package/lib/module/features/index.js +2 -0
  312. package/lib/module/features/index.js.map +1 -1
  313. package/lib/module/features/metadata.js.map +1 -1
  314. package/lib/module/features/nowPlaying.js +33 -0
  315. package/lib/module/features/nowPlaying.js.map +1 -1
  316. package/lib/module/features/output.js +32 -19
  317. package/lib/module/features/output.js.map +1 -1
  318. package/lib/module/features/playback/controls.js +8 -0
  319. package/lib/module/features/playback/controls.js.map +1 -1
  320. package/lib/module/features/playback/index.js +1 -0
  321. package/lib/module/features/playback/index.js.map +1 -1
  322. package/lib/module/features/playback/progress.js +28 -12
  323. package/lib/module/features/playback/progress.js.map +1 -1
  324. package/lib/module/features/playback/trackPlaybackTime.js +88 -0
  325. package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
  326. package/lib/module/features/playback/volume.js +1 -1
  327. package/lib/module/features/player/options.js +48 -13
  328. package/lib/module/features/player/options.js.map +1 -1
  329. package/lib/module/features/player/setup.js +249 -3
  330. package/lib/module/features/player/setup.js.map +1 -1
  331. package/lib/module/features/queue/queue.js +10 -3
  332. package/lib/module/features/queue/queue.js.map +1 -1
  333. package/lib/module/features/remoteControls.js +0 -11
  334. package/lib/module/features/remoteControls.js.map +1 -1
  335. package/lib/module/features/sleepTimer.js +9 -4
  336. package/lib/module/features/sleepTimer.js.map +1 -1
  337. package/lib/module/native.js +5 -0
  338. package/lib/module/native.js.map +1 -1
  339. package/lib/module/native.web.js +4 -1
  340. package/lib/module/native.web.js.map +1 -1
  341. package/lib/module/utils/LazyNativeEmitter.js +0 -3
  342. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  343. package/lib/module/utils/NativeUpdatedValue.js +0 -3
  344. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  345. package/lib/module/utils/artwork.js +26 -0
  346. package/lib/module/utils/artwork.js.map +1 -0
  347. package/lib/module/web/NativeAudioBrowser.js +302 -125
  348. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  349. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
  350. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  351. package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
  352. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  353. package/lib/module/web/TrackPlayer/Player.js +90 -26
  354. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  355. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
  356. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  357. package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
  358. package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
  359. package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
  360. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
  361. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  362. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  363. package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
  364. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  365. package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
  366. package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
  367. package/lib/module/web/TrackPlayer/index.js +2 -1
  368. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  369. package/lib/module/web/browser/BrowserManager.js +176 -50
  370. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  371. package/lib/module/web/browser/NavigationErrorManager.js +3 -1
  372. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  373. package/lib/module/web/browser/SearchManager.js +11 -9
  374. package/lib/module/web/browser/SearchManager.js.map +1 -1
  375. package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
  376. package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
  377. package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
  378. package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
  379. package/lib/module/web/browser/parseSearchResponse.js +16 -0
  380. package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
  381. package/lib/module/web/http/HttpClient.js +4 -23
  382. package/lib/module/web/http/HttpClient.js.map +1 -1
  383. package/lib/module/web/http/RequestConfigBuilder.js +107 -58
  384. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  385. package/lib/module/web/playbackErrorKind.js +52 -0
  386. package/lib/module/web/playbackErrorKind.js.map +1 -0
  387. package/lib/module/web/player/MediaSessionManager.js +116 -0
  388. package/lib/module/web/player/MediaSessionManager.js.map +1 -0
  389. package/lib/module/web/player/NowPlayingManager.js +7 -5
  390. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  391. package/lib/module/web/player/OptionsManager.js +9 -17
  392. package/lib/module/web/player/OptionsManager.js.map +1 -1
  393. package/lib/module/web/player/RemoteCommandController.js +92 -0
  394. package/lib/module/web/player/RemoteCommandController.js.map +1 -0
  395. package/lib/typescript/src/features/browser-config.d.ts +12 -0
  396. package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
  397. package/lib/typescript/src/features/browser.d.ts +40 -1
  398. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  399. package/lib/typescript/src/features/carConnection.d.ts +20 -0
  400. package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
  401. package/lib/typescript/src/features/errors.d.ts +58 -3
  402. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  403. package/lib/typescript/src/features/gate.d.ts +77 -0
  404. package/lib/typescript/src/features/gate.d.ts.map +1 -0
  405. package/lib/typescript/src/features/index.d.ts +2 -0
  406. package/lib/typescript/src/features/index.d.ts.map +1 -1
  407. package/lib/typescript/src/features/metadata.d.ts +6 -4
  408. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  409. package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
  410. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  411. package/lib/typescript/src/features/output.d.ts +28 -18
  412. package/lib/typescript/src/features/output.d.ts.map +1 -1
  413. package/lib/typescript/src/features/playback/controls.d.ts +5 -0
  414. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  415. package/lib/typescript/src/features/playback/index.d.ts +1 -0
  416. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  417. package/lib/typescript/src/features/playback/progress.d.ts +3 -0
  418. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  419. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
  420. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
  421. package/lib/typescript/src/features/playback/volume.d.ts +1 -1
  422. package/lib/typescript/src/features/player/options.d.ts +92 -93
  423. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  424. package/lib/typescript/src/features/player/setup.d.ts +206 -167
  425. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  426. package/lib/typescript/src/features/queue/queue.d.ts +9 -2
  427. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  428. package/lib/typescript/src/features/remoteControls.d.ts +0 -13
  429. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  430. package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
  431. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  432. package/lib/typescript/src/index.d.ts.map +1 -1
  433. package/lib/typescript/src/native.d.ts +1 -2
  434. package/lib/typescript/src/native.d.ts.map +1 -1
  435. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
  436. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  437. package/lib/typescript/src/types/browser-native.d.ts +9 -3
  438. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  439. package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
  440. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  441. package/lib/typescript/src/types/browser.d.ts +349 -85
  442. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  443. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
  444. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  445. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
  446. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  447. package/lib/typescript/src/utils/artwork.d.ts +19 -0
  448. package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
  449. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  450. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
  451. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
  452. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  453. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
  454. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
  455. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
  456. package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
  457. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  458. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
  459. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
  460. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
  461. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
  462. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
  463. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
  464. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
  465. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
  466. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
  467. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
  468. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
  469. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
  470. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
  471. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
  472. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -0
  473. 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
  474. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
  475. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
  476. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
  477. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
  478. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
  479. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
  480. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
  481. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
  482. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  483. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
  484. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
  485. package/nitrogen/generated/android/c++/JGate.hpp +62 -0
  486. package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
  487. package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
  488. package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
  489. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
  490. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
  491. package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
  492. package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
  493. package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
  494. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
  495. package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
  496. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
  497. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
  498. package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
  499. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
  500. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
  501. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
  502. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
  503. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
  504. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
  505. package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
  506. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
  507. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
  508. package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
  509. package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
  510. package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
  511. package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
  512. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
  513. package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
  514. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
  515. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
  516. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  517. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
  518. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
  519. package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
  520. package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
  521. package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
  522. package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
  523. package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
  524. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
  525. package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
  526. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
  527. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
  528. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
  529. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
  530. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
  531. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
  532. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
  533. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  534. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
  535. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
  536. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
  537. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  538. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
  539. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
  540. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
  541. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  542. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
  543. 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
  544. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
  545. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
  546. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
  547. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
  548. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
  549. 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
  550. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
  551. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
  552. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  553. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
  554. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
  555. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
  556. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
  557. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
  558. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
  559. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
  560. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
  561. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
  562. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
  563. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
  564. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
  565. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
  566. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  567. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
  568. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  569. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
  570. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
  571. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
  572. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
  573. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
  574. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
  575. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  576. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
  577. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
  578. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
  579. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
  580. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  581. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  582. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
  583. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
  584. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
  585. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
  586. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
  587. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
  588. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
  589. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
  590. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
  591. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
  592. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
  593. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
  594. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
  595. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
  596. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
  597. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  598. package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
  599. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
  600. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
  601. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  602. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
  603. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
  604. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
  605. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
  606. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
  607. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
  608. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
  609. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
  610. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
  611. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
  612. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
  613. 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
  614. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
  615. package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
  616. package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
  617. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
  618. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  619. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
  620. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
  621. 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
  622. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
  623. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
  624. package/nitrogen/generated/ios/swift/Gate.swift +47 -0
  625. package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
  626. package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
  627. package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
  628. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
  629. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
  630. package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
  631. package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
  632. package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
  633. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
  634. package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
  635. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
  636. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
  637. package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
  638. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  639. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
  640. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
  641. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
  642. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
  643. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
  644. package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
  645. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
  646. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
  647. package/nitrogen/generated/ios/swift/Options.swift +10 -4
  648. package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
  649. package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
  650. package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
  651. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
  652. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  653. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
  654. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
  655. package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
  656. package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
  657. package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
  658. package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
  659. package/nitrogen/generated/ios/swift/Track.swift +74 -8
  660. package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
  661. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
  662. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
  663. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
  664. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
  665. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  666. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
  667. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
  668. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
  669. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  670. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
  671. package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
  672. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
  673. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
  674. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
  675. package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
  676. package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
  677. package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
  678. package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
  679. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
  680. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
  681. package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
  682. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
  683. package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
  684. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
  685. package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
  686. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
  687. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
  688. package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
  689. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  690. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
  691. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
  692. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
  693. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
  694. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
  695. package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
  696. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
  697. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
  698. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  699. package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
  700. package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
  701. package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
  702. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
  703. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  704. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
  705. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
  706. package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
  707. package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
  708. package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
  709. package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
  710. package/nitrogen/generated/shared/c++/Track.hpp +24 -5
  711. package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
  712. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
  713. package/package.json +11 -6
  714. package/src/codegen-no-config-variant.test.ts +70 -0
  715. package/src/features/browser-config.test.ts +110 -0
  716. package/src/features/browser-config.ts +293 -0
  717. package/src/features/browser.test.ts +19 -0
  718. package/src/features/browser.ts +58 -201
  719. package/src/features/carConnection.ts +36 -0
  720. package/src/features/errors.ts +68 -2
  721. package/src/features/gate.test.ts +72 -0
  722. package/src/features/gate.ts +155 -0
  723. package/src/features/index.ts +2 -0
  724. package/src/features/metadata.ts +6 -12
  725. package/src/features/nowPlaying.ts +36 -0
  726. package/src/features/output.ts +35 -22
  727. package/src/features/playback/controls.ts +8 -0
  728. package/src/features/playback/index.ts +1 -0
  729. package/src/features/playback/progress.ts +31 -12
  730. package/src/features/playback/trackPlaybackTime.test.ts +66 -0
  731. package/src/features/playback/trackPlaybackTime.ts +106 -0
  732. package/src/features/playback/volume.ts +1 -1
  733. package/src/features/player/options.test.ts +38 -0
  734. package/src/features/player/options.ts +140 -75
  735. package/src/features/player/setup.test.ts +117 -0
  736. package/src/features/player/setup.ts +390 -175
  737. package/src/features/queue/queue.test.ts +36 -0
  738. package/src/features/queue/queue.ts +15 -4
  739. package/src/features/remoteControls.ts +0 -23
  740. package/src/features/sleepTimer.ts +23 -4
  741. package/src/native.ts +5 -0
  742. package/src/native.web.ts +4 -1
  743. package/src/specs/audio-browser.nitro.ts +131 -41
  744. package/src/types/browser-native.ts +19 -6
  745. package/src/types/browser-nodes.ts +160 -13
  746. package/src/types/browser.ts +377 -89
  747. package/src/utils/LazyNativeEmitter.ts +0 -2
  748. package/src/utils/NativeUpdatedValue.ts +0 -2
  749. package/src/utils/artwork.ts +30 -0
  750. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
  751. package/src/web/NativeAudioBrowser.ts +365 -158
  752. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
  753. package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
  754. package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
  755. package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
  756. package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
  757. package/src/web/TrackPlayer/Player.load.test.ts +86 -0
  758. package/src/web/TrackPlayer/Player.ts +113 -39
  759. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
  760. package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
  761. package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
  762. package/src/web/TrackPlayer/QueueManager.ts +302 -0
  763. package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
  764. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  765. package/src/web/TrackPlayer/SleepTimer.ts +38 -3
  766. package/src/web/TrackPlayer/VolumeFader.ts +74 -0
  767. package/src/web/TrackPlayer/index.ts +2 -1
  768. package/src/web/browser/BrowserManager.ts +231 -62
  769. package/src/web/browser/NavigationErrorManager.ts +3 -1
  770. package/src/web/browser/SearchManager.ts +11 -15
  771. package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
  772. package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
  773. package/src/web/browser/assertBrowsePageShape.ts +27 -0
  774. package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
  775. package/src/web/browser/classifyTrackNavigation.ts +35 -0
  776. package/src/web/browser/parseSearchResponse.test.ts +25 -0
  777. package/src/web/browser/parseSearchResponse.ts +15 -0
  778. package/src/web/http/HttpClient.ts +5 -35
  779. package/src/web/http/RequestConfigBuilder.test.ts +59 -0
  780. package/src/web/http/RequestConfigBuilder.ts +120 -63
  781. package/src/web/playbackErrorKind.test.ts +55 -0
  782. package/src/web/playbackErrorKind.ts +56 -0
  783. package/src/web/player/MediaSessionManager.test.ts +220 -0
  784. package/src/web/player/MediaSessionManager.ts +151 -0
  785. package/src/web/player/NowPlayingManager.test.ts +46 -0
  786. package/src/web/player/NowPlayingManager.ts +6 -5
  787. package/src/web/player/OptionsManager.ts +12 -18
  788. package/src/web/player/RemoteCommandController.test.ts +171 -0
  789. package/src/web/player/RemoteCommandController.ts +166 -0
  790. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
  791. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
  792. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
  793. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
  794. package/ios/CarPlay/Track+CarPlay.swift +0 -63
  795. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
  796. package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
  797. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
  798. package/lib/commonjs/features/rating.js +0 -2
  799. package/lib/commonjs/features/rating.js.map +0 -1
  800. package/lib/commonjs/types/player.js +0 -2
  801. package/lib/commonjs/types/player.js.map +0 -1
  802. package/lib/commonjs/web/SimpleRouter.test.js +0 -174
  803. package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
  804. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
  805. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  806. package/lib/module/features/rating.js +0 -2
  807. package/lib/module/features/rating.js.map +0 -1
  808. package/lib/module/types/player.js +0 -2
  809. package/lib/module/types/player.js.map +0 -1
  810. package/lib/module/web/SimpleRouter.test.js +0 -174
  811. package/lib/module/web/SimpleRouter.test.js.map +0 -1
  812. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
  813. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  814. package/lib/typescript/src/features/rating.d.ts +0 -14
  815. package/lib/typescript/src/features/rating.d.ts.map +0 -1
  816. package/lib/typescript/src/native.web.d.ts +0 -3
  817. package/lib/typescript/src/native.web.d.ts.map +0 -1
  818. package/lib/typescript/src/types/player.d.ts +0 -64
  819. package/lib/typescript/src/types/player.d.ts.map +0 -1
  820. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
  821. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
  822. package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
  823. package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
  824. package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
  825. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
  826. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
  827. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
  828. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
  829. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
  830. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
  831. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
  832. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
  833. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
  834. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
  835. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
  836. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
  837. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
  838. package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
  839. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
  840. package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
  841. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
  842. package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
  843. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
  844. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
  845. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
  846. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
  847. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
  848. package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
  849. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
  850. package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
  851. package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
  852. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
  853. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
  854. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
  855. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
  856. package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
  857. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
  858. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
  859. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
  860. package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
  861. package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
  862. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
  863. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
  864. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
  865. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
  866. package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
  867. package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
  868. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
  869. package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
  870. package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
  871. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
  872. package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
  873. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
  874. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
  875. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
  876. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
  881. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
  882. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
  883. package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
  884. package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
  885. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
  886. package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
  887. package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
  888. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
  889. package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
  890. package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
  891. package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
  892. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
  893. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
  894. package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
  895. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
  896. package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
  897. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
  898. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
  899. package/src/features/rating.ts +0 -17
  900. package/src/types/player.ts +0 -69
  901. package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
@@ -0,0 +1,20 @@
1
+ package com.audiobrowser.player
2
+
3
+ import com.margelo.nitro.audiobrowser.FavoritesMatchMode
4
+ import com.margelo.nitro.audiobrowser.PlayerCapabilities
5
+
6
+ /**
7
+ * Resolved favorite match mode, or null when favoriting is disabled.
8
+ *
9
+ * `false`/unset → null; `true` → EXACT; `{ match }` → that match.
10
+ */
11
+ val PlayerCapabilities.favoriteMatch: FavoritesMatchMode?
12
+ get() =
13
+ favorite?.match(
14
+ first = { enabled -> if (enabled) FavoritesMatchMode.EXACT else null },
15
+ second = { config -> config.match },
16
+ )
17
+
18
+ /** Whether the favorite/like control is enabled. */
19
+ val PlayerCapabilities.favoriteEnabled: Boolean
20
+ get() = favoriteMatch != null
@@ -0,0 +1,130 @@
1
+ package com.audiobrowser.player
2
+
3
+ import android.content.Context
4
+ import androidx.media3.common.AudioAttributes
5
+ import androidx.media3.common.C
6
+ import androidx.media3.common.TrackSelectionParameters
7
+ import androidx.media3.datasource.cache.SimpleCache
8
+ import androidx.media3.exoplayer.DefaultRenderersFactory
9
+ import androidx.media3.exoplayer.ExoPlayer
10
+ import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
11
+ import com.audiobrowser.model.PlayerSetupOptions
12
+ import com.audiobrowser.util.AndroidAudioContentTypeFactory
13
+ import com.margelo.nitro.audiobrowser.AndroidPlayerWakeMode
14
+ import com.margelo.nitro.audiobrowser.MediaRequestConfig
15
+ import java.io.IOException
16
+
17
+ // media3's configurable stuck-buffering (type-1, STUCK_BUFFERING_NO_PROGRESS) timeout. Fires only
18
+ // on zero loading progress; 60s of silent non-progress is already a bad live-radio experience,
19
+ // while the media3 default of 600s would mean 10 minutes of dead air. (Type-0
20
+ // STUCK_BUFFERING_NOT_LOADING is a separate, uncontrollable fixed-4s check.)
21
+ private const val STUCK_BUFFERING_DETECTION_TIMEOUT_MS = 60_000
22
+
23
+ /** The engine pieces [buildPlayerEngine] constructs together for one setup() generation. */
24
+ internal class PlayerEngine(
25
+ val loadControl: DynamicLoadControl,
26
+ val mediaFactory: MediaFactory,
27
+ val exoPlayer: ExoPlayer,
28
+ )
29
+
30
+ /**
31
+ * The buffer configuration described by the setup options. When `rebufferBuffer` is unset
32
+ * (automatic), post-rebuffer playback starts at `playBuffer` and AutomaticBufferManager adjusts it;
33
+ * when set, that fixed value is used. Pure — pinned by PlayerEngineFactoryTest.
34
+ */
35
+ internal fun bufferConfig(options: PlayerSetupOptions): BufferConfig =
36
+ BufferConfig(
37
+ minBufferMs = options.minBuffer.toInt(),
38
+ maxBufferMs = options.maxBuffer.toInt(),
39
+ bufferForPlaybackMs = options.playBuffer.toInt(),
40
+ bufferForPlaybackAfterRebufferMs = (options.rebufferBuffer ?: options.playBuffer).toInt(),
41
+ backBufferMs = options.backBuffer.toInt(),
42
+ )
43
+
44
+ /**
45
+ * Constructs the playback engine for one `setup()` generation: load control, media factory, and the
46
+ * ExoPlayer they plug into — pure construction, no lifecycle. Tearing down the previous generation,
47
+ * wiring listeners/session, and everything stateful stays in [Player.setup], which provides its
48
+ * mutable context through the lambdas.
49
+ */
50
+ internal fun buildPlayerEngine(
51
+ context: Context,
52
+ options: PlayerSetupOptions,
53
+ cache: SimpleCache?,
54
+ shouldRetry: () -> Boolean,
55
+ isOnline: () -> Boolean,
56
+ hasPlayed: () -> Boolean,
57
+ onRetryPending: (exception: IOException, isNetworkError: Boolean) -> Unit,
58
+ resolveMediaConfig: (url: String) -> MediaRequestConfig?,
59
+ ): PlayerEngine {
60
+ val renderer = DefaultRenderersFactory(context)
61
+ renderer.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
62
+
63
+ // Bandwidth meter for adaptive bitrate selection in HLS/DASH
64
+ val bandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
65
+
66
+ val loadControl = DynamicLoadControl(initialConfig = bufferConfig(options))
67
+
68
+ // shouldRetry checks playWhenReady to avoid retrying when paused (e.g., another app took audio
69
+ // focus) — via a thread-safe cache since this runs on ExoPlayer's playback thread. isOnline and
70
+ // onRetryPending enable network-aware retry acceleration.
71
+ val mediaFactory =
72
+ MediaFactory(
73
+ context,
74
+ cache,
75
+ options.retryPolicy,
76
+ shouldRetry = shouldRetry,
77
+ isOnline = isOnline,
78
+ hasPlayed = hasPlayed,
79
+ onRetryPending = onRetryPending,
80
+ transferListener = bandwidthMeter,
81
+ getRequestConfig = resolveMediaConfig,
82
+ )
83
+
84
+ val exoPlayer =
85
+ ExoPlayer.Builder(context)
86
+ .setRenderersFactory(renderer)
87
+ .setBandwidthMeter(bandwidthMeter)
88
+ .setHandleAudioBecomingNoisy(options.handleAudioBecomingNoisy)
89
+ .setMediaSourceFactory(mediaFactory)
90
+ .setStuckBufferingDetectionTimeoutMs(STUCK_BUFFERING_DETECTION_TIMEOUT_MS)
91
+ .setWakeMode(
92
+ when (options.wakeMode) {
93
+ AndroidPlayerWakeMode.NONE -> C.WAKE_MODE_NONE
94
+ AndroidPlayerWakeMode.LOCAL -> C.WAKE_MODE_LOCAL
95
+ AndroidPlayerWakeMode.NETWORK -> C.WAKE_MODE_NETWORK
96
+ }
97
+ )
98
+ .setLoadControl(loadControl)
99
+ .setName("AudioBrowser")
100
+ .build()
101
+
102
+ exoPlayer.setAudioAttributes(
103
+ AudioAttributes.Builder()
104
+ .setUsage(C.USAGE_MEDIA)
105
+ .setContentType(AndroidAudioContentTypeFactory.toMedia3(options.audioContentType))
106
+ .build(),
107
+ true, // handle audio focus
108
+ )
109
+
110
+ options.audioOffload?.let {
111
+ val audioOffloadPreferences =
112
+ TrackSelectionParameters.AudioOffloadPreferences.Builder()
113
+ .setAudioOffloadMode(
114
+ TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED
115
+ )
116
+ .setIsGaplessSupportRequired(it.gaplessSupportRequired)
117
+ .setIsSpeedChangeSupportRequired(it.rateChangeSupportRequired)
118
+ .build()
119
+ // Assigning the public final field compiles to a putfield that throws
120
+ // IllegalAccessError on ART, and mutating the getter's snapshot wouldn't
121
+ // reach the selector anyway — go through the builder.
122
+ exoPlayer.trackSelectionParameters =
123
+ exoPlayer.trackSelectionParameters
124
+ .buildUpon()
125
+ .setAudioOffloadPreferences(audioOffloadPreferences)
126
+ .build()
127
+ }
128
+
129
+ return PlayerEngine(loadControl, mediaFactory, exoPlayer)
130
+ }
@@ -1,5 +1,7 @@
1
1
  package com.audiobrowser.player
2
2
 
3
+ import android.os.Handler
4
+ import android.os.Looper
3
5
  import androidx.media3.common.MediaItem
4
6
  import androidx.media3.common.MediaMetadata
5
7
  import androidx.media3.common.Metadata
@@ -7,19 +9,47 @@ import androidx.media3.common.PlaybackException
7
9
  import androidx.media3.common.PlaybackParameters
8
10
  import androidx.media3.common.Player as MediaPlayer
9
11
  import androidx.media3.common.Timeline
12
+ import androidx.media3.common.util.StuckPlayerException
10
13
  import com.audiobrowser.extension.NumberExt.Companion.toSeconds
11
14
  import com.audiobrowser.model.PlaybackMetadata
12
15
  import com.audiobrowser.util.MetadataAdapter
13
- import com.audiobrowser.util.PlayingStateFactory
14
16
  import com.audiobrowser.util.RepeatModeFactory
15
17
  import com.margelo.nitro.audiobrowser.PlaybackActiveTrackChangedEvent
16
18
  import com.margelo.nitro.audiobrowser.PlaybackError
17
- import com.margelo.nitro.audiobrowser.PlaybackPlayWhenReadyChangedEvent
19
+ import com.margelo.nitro.audiobrowser.PlaybackErrorKind
18
20
  import com.margelo.nitro.audiobrowser.PlaybackState
19
21
  import java.util.Locale
20
22
  import timber.log.Timber
21
23
 
24
+ // Continuous playback required to refill the stuck-recovery budget. Long enough that a stream which
25
+ // keeps re-stalling can't "prove liveness" between stalls, short enough to forgive a single hiccup.
26
+ private const val HEALTHY_PLAYBACK_MS = 20_000L
27
+
22
28
  class PlayerListener(private val player: Player) : MediaPlayer.Listener {
29
+ // Caps auto-recovery from media3 stuck-player detection before surfacing a terminal error.
30
+ private val stuckRecoveryPolicy = StuckRecoveryPolicy()
31
+
32
+ // Proof-of-life timer: the recovery budget refills only after the player sustains continuous
33
+ // playback for HEALTHY_PLAYBACK_MS, proving the stream actually delivered audio (not a brief blip
34
+ // before re-stalling). Mirrors AutomaticBufferManager's Handler usage. Runs on the main thread,
35
+ // where Player.Listener callbacks are delivered.
36
+ private val healthyPlaybackHandler = Handler(Looper.getMainLooper())
37
+ private val healthyPlaybackRunnable =
38
+ object : Runnable {
39
+ override fun run() {
40
+ stuckRecoveryPolicy.reset()
41
+ // Refill the load-error retry window too — it otherwise resets only
42
+ // on track change, so a second outage >2min after the first got zero
43
+ // retries (instant terminal error) on a long-lived stream.
44
+ player.resetRetryTimer()
45
+ // Re-post while playing: errors the buffer absorbs never flip
46
+ // isPlaying, so a one-shot refill left the window stale again.
47
+ if (player.isPlaying) {
48
+ healthyPlaybackHandler.postDelayed(this, HEALTHY_PLAYBACK_MS)
49
+ }
50
+ }
51
+ }
52
+
23
53
  /** Called when there is metadata associated with the current playback time. */
24
54
  override fun onMetadata(metadata: Metadata) {
25
55
  // Extract and emit chapter metadata if present
@@ -29,7 +59,11 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
29
59
  }
30
60
 
31
61
  // Extract and emit timed metadata (ICY, ID3, etc.)
32
- PlaybackMetadata.from(metadata)?.let { player.callbacks?.onTimedMetadata(it.toNitro()) }
62
+ PlaybackMetadata.from(metadata)?.let {
63
+ val timed = it.toNitro()
64
+ player.callbacks?.onTimedMetadata(timed)
65
+ player.nowPlaying.onTimedMetadataReceived(timed)
66
+ }
33
67
  }
34
68
 
35
69
  override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
@@ -73,7 +107,7 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
73
107
 
74
108
  // Check if sleep timer should trigger on track end
75
109
  if (reason == MediaPlayer.MEDIA_ITEM_TRANSITION_REASON_AUTO) {
76
- player.checkSleepTimerOnTrackEnd()
110
+ player.sleepTimer.onTrackEnd()
77
111
  }
78
112
 
79
113
  // Update last track info for next transition
@@ -84,31 +118,67 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
84
118
  player.updateFavoriteButtonState(player.currentTrack?.favorited)
85
119
 
86
120
  // Clear now playing override when track changes (new track = clean slate)
87
- player.clearNowPlayingOverride()
121
+ player.nowPlaying.clearOverride()
122
+
123
+ // Re-stamp the now-playing metadata for the new track. The browse-list
124
+ // MediaItem carries `artist = subtitle` (the per-context list line), but the
125
+ // now-playing screen / lock screen / Bluetooth should show the canonical
126
+ // `artist` (location). Android Auto derives both from the same MediaItem's
127
+ // `artist`, so we overwrite the playing item's metadata here (the same
128
+ // mechanism ICY song updates already use) to diverge it from the list items.
129
+ // This also fires onNowPlayingChanged, so we don't emit it separately below.
130
+ player.nowPlaying.render()
88
131
 
89
- // Reset retry timer so new track gets fresh 2-minute window
132
+ // Reset retry timer so the new track gets fresh duration budgets, and mark
133
+ // the new load unproven — its failures get the short first-connect budget
134
+ // until it renders audio.
90
135
  player.resetRetryTimer()
136
+ player.hasPlayedCache = false
137
+
138
+ // A retrying error belongs to the outgoing track; drop it (with its own emit —
139
+ // the incoming track may hold the state on LOADING/BUFFERING, emitting nothing).
140
+ player.clearRetryingError()
91
141
 
92
- // Notify JS of the now playing metadata for the new track
93
- player.getNowPlaying()?.let { player.callbacks?.onNowPlayingChanged(it) }
142
+ // A new station starts with a clean stuck-recovery budget, mirroring the retry timer reset.
143
+ healthyPlaybackHandler.removeCallbacks(healthyPlaybackRunnable)
144
+ stuckRecoveryPolicy.reset()
94
145
 
95
146
  player.playbackStateStore.save()
96
147
  player.playbackStateStore.resetPeriodicSave()
97
148
  }
98
149
 
150
+ /**
151
+ * Schedules a stuck-recovery budget refill once the player has been continuously playing for
152
+ * [HEALTHY_PLAYBACK_MS], and cancels it the moment playback stops (pause, rebuffer, stall,
153
+ * error). Sustained real playback is our proof the stream is alive and the budget can be trusted
154
+ * again.
155
+ */
156
+ override fun onIsPlayingChanged(isPlaying: Boolean) {
157
+ healthyPlaybackHandler.removeCallbacks(healthyPlaybackRunnable)
158
+ if (isPlaying) {
159
+ healthyPlaybackHandler.postDelayed(healthyPlaybackRunnable, HEALTHY_PLAYBACK_MS)
160
+ }
161
+ }
162
+
99
163
  /** Called when the value returned from Player.getPlayWhenReady() changes. */
100
164
  override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
101
- // Update thread-safe cache for access from non-main threads (e.g., retry policy)
102
- player.playWhenReadyCache = playWhenReady
103
- player.callbacks?.onPlaybackPlayWhenReadyChanged(
104
- PlaybackPlayWhenReadyChangedEvent(playWhenReady)
105
- )
106
- val newPlayingState = PlayingStateFactory.derive(playWhenReady, player.playbackState)
107
- if (newPlayingState != player.playingState) {
108
- player.playingState = newPlayingState
109
- player.callbacks?.onPlaybackPlayingState(player.playingState)
165
+ // An explicit pause during the sleep fade is the timer's goal arriving early: clear the
166
+ // timer (restores the pre-fade volume). The timer's own completion cancels the fader
167
+ // before pausing, so it never re-enters here.
168
+ if (!playWhenReady && player.volumeFader.isActive) {
169
+ player.sleepTimer.clear()
110
170
  }
111
171
 
172
+ // Update thread-safe cache for access from non-main threads (e.g., retry policy).
173
+ // Deliberately the second writer: Player.playWhenReady's setter writes eagerly so
174
+ // non-main readers see the new intent before ExoPlayer round-trips; this event is
175
+ // the authoritative sync for changes ExoPlayer makes on its own (e.g. audio focus).
176
+ player.playWhenReadyCache = playWhenReady
177
+ // Through the dedupe guard: the ENDED clear in setPlaybackState already
178
+ // emitted this change synchronously (ordered before queue-ended).
179
+ player.emitPlayWhenReadyChanged(playWhenReady)
180
+ player.refreshPlayingState()
181
+
112
182
  if (playWhenReady) {
113
183
  player.playbackStateStore.startPeriodicSave()
114
184
  } else {
@@ -125,56 +195,44 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
125
195
  // Note that it is necessary to set `playerState` in order, since each mutation fires an
126
196
  // event.
127
197
  for (i in 0 until events.size()) {
128
- when (events[i]) {
129
- MediaPlayer.EVENT_PLAYBACK_STATE_CHANGED -> {
130
- val state =
131
- when (media3Player.playbackState) {
132
- MediaPlayer.STATE_BUFFERING -> PlaybackState.BUFFERING
133
- MediaPlayer.STATE_READY -> PlaybackState.READY
134
- MediaPlayer.STATE_IDLE ->
135
- // Avoid transitioning to idle from error or stopped
136
- if (
137
- player.playbackState == PlaybackState.ERROR ||
138
- player.playbackState == PlaybackState.STOPPED
139
- )
140
- null
141
- else PlaybackState.NONE
142
- MediaPlayer.STATE_ENDED ->
143
- if (media3Player.mediaItemCount > 0) PlaybackState.ENDED else PlaybackState.NONE
144
- else -> null // noop
145
- }
146
- if (state != null && state != player.playbackState) {
147
- // Clear error when recovering from ERROR state to a successful state
148
- if (player.playbackState == PlaybackState.ERROR) {
149
- player.playbackError = null
150
- }
151
- player.setPlaybackState(state)
152
- }
153
- }
154
- MediaPlayer.EVENT_MEDIA_ITEM_TRANSITION -> {
155
- player.playbackError = null
156
- if (player.currentTrack != null) {
157
- player.setPlaybackState(PlaybackState.LOADING)
158
- if (player.isPlaying) {
159
- player.setPlaybackState(PlaybackState.READY)
160
- player.setPlaybackState(PlaybackState.PLAYING)
161
- }
162
- }
163
- }
164
- MediaPlayer.EVENT_PLAY_WHEN_READY_CHANGED -> {
165
- if (!player.playWhenReady && player.playbackState != PlaybackState.STOPPED) {
166
- player.setPlaybackState(PlaybackState.PAUSED)
167
- }
168
- }
169
- MediaPlayer.EVENT_IS_PLAYING_CHANGED -> {
170
- if (player.isPlaying) {
171
- player.setPlaybackState(PlaybackState.PLAYING)
172
- }
173
- }
198
+ // A new item clears any prior error even when no state transition follows (e.g. the queue
199
+ // was emptied) — silently, matching the pre-state-machine behavior. Kept out of the event
200
+ // mapping below so that stays pure; ordering within the batch is unchanged.
201
+ if (events[i] == MediaPlayer.EVENT_MEDIA_ITEM_TRANSITION) {
202
+ player.playbackError = null
203
+ }
204
+
205
+ val event =
206
+ when (events[i]) {
207
+ MediaPlayer.EVENT_PLAYBACK_STATE_CHANGED ->
208
+ // Read the real ExoPlayer state, not the forwarding player's — the InterceptingPlayer
209
+ // masks STATE_IDLE→READY on a terminal error, and that mask must not feed back into
210
+ // our own state machine (it would clear the ERROR state/subtitle).
211
+ PlaybackEvent.ExoPlaybackStateChanged(
212
+ player.exoPlayer.playbackState,
213
+ media3Player.mediaItemCount,
214
+ player.exoPlayer.playWhenReady,
215
+ )
216
+ MediaPlayer.EVENT_MEDIA_ITEM_TRANSITION ->
217
+ PlaybackEvent.MediaItemTransition(player.currentTrack != null, player.isPlaying)
218
+ MediaPlayer.EVENT_PLAY_WHEN_READY_CHANGED ->
219
+ PlaybackEvent.PlayWhenReadyChanged(player.playWhenReady)
220
+ MediaPlayer.EVENT_IS_PLAYING_CHANGED -> PlaybackEvent.IsPlayingChanged(player.isPlaying)
221
+ else -> null
222
+ } ?: continue
223
+
224
+ for (state in PlaybackStateMachine.transitions(player.playbackState, event)) {
225
+ player.setPlaybackState(state)
174
226
  }
175
227
  }
176
228
  }
177
229
 
230
+ override fun onPlayerErrorChanged(error: PlaybackException?) {
231
+ // The error clearing means a recovery path ran prepare() — a restart from
232
+ // terminal error, which begins a new load (see Player.resetForNewLoad).
233
+ if (error == null) player.resetForNewLoad()
234
+ }
235
+
178
236
  override fun onPlayerError(error: PlaybackException) {
179
237
  // Handle live stream recovery when playback position falls behind the live window
180
238
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
@@ -184,19 +242,84 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
184
242
  return
185
243
  }
186
244
 
187
- val playbackError =
188
- PlaybackError(
245
+ // media3 1.9.0+ stuck-player detection arrives here wrapped in a PlaybackException: the actual
246
+ // StuckPlayerException (an IllegalStateException, not a PlaybackException) sits in the cause
247
+ // chain, and the wrapper's errorCode varies by stuck type — so we detect by cause, not code.
248
+ // For a live-radio app a transient stall should reconnect, not stop playback.
249
+ val stuck =
250
+ generateSequence(error.cause) { it.cause }
251
+ .filterIsInstance<StuckPlayerException>()
252
+ .firstOrNull()
253
+ if (stuck != null) {
254
+ handleStuckPlayer(stuck)
255
+ return
256
+ }
257
+
258
+ val online = player.networkMonitor.getOnline()
259
+ // `code` stays the raw ExoPlayer name for telemetry; `kind` is the normalized classification
260
+ // consumers branch on. Offline is the one distinction ExoPlayer's codes cannot make on their
261
+ // own, so it overrides the code name too.
262
+ val code =
263
+ if (!online) {
264
+ "not-connected-to-internet"
265
+ } else {
189
266
  error.errorCodeName
190
267
  .replace("ERROR_CODE_", "")
191
268
  .lowercase(Locale.getDefault())
192
- .replace("_", "-"),
269
+ .replace("_", "-")
270
+ }
271
+ val playbackError =
272
+ PlaybackError(
273
+ PlaybackErrorClassifier.classify(error, online),
274
+ code,
193
275
  error.message ?: "An unknown error occurred",
276
+ PlaybackErrorClassifier.responseCode(error)?.toDouble(),
277
+ retrying = null,
194
278
  )
195
279
  player.callbacks?.onPlaybackError(playbackError)
196
280
  player.playbackError = playbackError
197
281
  player.setPlaybackState(PlaybackState.ERROR)
198
282
  }
199
283
 
284
+ /**
285
+ * Recovers from a media3 stuck-player detection or, once the recovery budget is exhausted,
286
+ * surfaces a distinct terminal error. Live items rejoin the live edge (a stale buffered live
287
+ * window is the common stuck cause); on-demand items re-prepare in place so the saved position is
288
+ * preserved.
289
+ */
290
+ private fun handleStuckPlayer(error: StuckPlayerException) {
291
+ // Defensive: media3 only fires stuck detection while playWhenReady is true, but never do
292
+ // recovery work for a deliberately-paused player (matches RetryLoadErrorHandlingPolicy).
293
+ if (!player.playWhenReady) return
294
+
295
+ when (stuckRecoveryPolicy.onStuck()) {
296
+ StuckRecoveryPolicy.Decision.RECOVER -> {
297
+ Timber.w(
298
+ "Stuck player recovery: type=${error.stuckType} timeoutMs=${error.timeoutMs} " +
299
+ "live=${player.isCurrentItemLive}"
300
+ )
301
+ if (player.isCurrentItemLive) {
302
+ player.exoPlayer.seekToDefaultPosition()
303
+ }
304
+ player.exoPlayer.prepare()
305
+ }
306
+ StuckRecoveryPolicy.Decision.GIVE_UP -> {
307
+ Timber.w("Stuck player recovery exhausted (type=${error.stuckType}), surfacing error")
308
+ val playbackError =
309
+ PlaybackError(
310
+ PlaybackErrorKind.STALLED,
311
+ "playback-stalled",
312
+ error.message ?: "Playback stalled",
313
+ null,
314
+ retrying = null,
315
+ )
316
+ player.callbacks?.onPlaybackError(playbackError)
317
+ player.playbackError = playbackError
318
+ player.setPlaybackState(PlaybackState.ERROR)
319
+ }
320
+ }
321
+ }
322
+
200
323
  override fun onRepeatModeChanged(repeatMode: Int) {
201
324
  val mode = RepeatModeFactory.fromMedia3(repeatMode)
202
325
  player.callbacks?.onPlaybackRepeatModeChanged(mode)
@@ -225,6 +348,6 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
225
348
 
226
349
  override fun onAudioSessionIdChanged(audioSessionId: Int) {
227
350
  Timber.d("Audio session ID changed to: $audioSessionId")
228
- player.reinitializeEqualizer(audioSessionId)
351
+ player.equalizer.onAudioSessionChanged(audioSessionId)
229
352
  }
230
353
  }