react-native-audio-browser 0.2.0-next.3 → 0.2.0-next.31
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.
- package/README.md +36 -22
- package/android/build.gradle +35 -12
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +541 -278
- package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
- package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +52 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +27 -9
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +288 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -7
- package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
- package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
- package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
- package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
- package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +62 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +110 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +56 -52
- package/android/src/main/res/values/strings.xml +25 -5
- package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +100 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +40 -2
- package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +301 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +3 -2
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +168 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +160 -0
- package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
- package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
- package/android/src/test/java/com/audiobrowser/model/IcyTitleTest.kt +49 -0
- package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
- package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +55 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
- package/ios/AVPlayerEngine.swift +330 -0
- package/ios/AVPlayerEngineCallbacks.swift +15 -0
- package/ios/Browser/BrowseGate.swift +58 -0
- package/ios/Browser/BrowserConfig.swift +117 -78
- package/ios/Browser/BrowserManager.swift +209 -603
- package/ios/Browser/BrowserPathHelper.swift +50 -46
- package/ios/Browser/InertStyleDiagnostic.swift +296 -0
- package/ios/Browser/JsonModels.swift +264 -106
- package/ios/Browser/NavigationErrorState.swift +41 -0
- package/ios/Browser/PageResolver.swift +227 -0
- package/ios/Browser/RequestLayer.swift +90 -0
- package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +193 -121
- package/ios/Browser/SearchDrillIn.swift +7 -7
- package/ios/Browser/SectionScope.swift +58 -24
- package/ios/Browser/StyleResolver.swift +58 -0
- package/ios/Browser/TabBarEntries.swift +9 -3
- package/ios/Browser/TrackIdTemplate.swift +37 -0
- package/ios/CarPlay/CPInterfaceController+Safe.swift +100 -43
- package/ios/CarPlay/CarPlayArtworkResolver.swift +36 -83
- package/ios/CarPlay/CarPlayController.swift +42 -1296
- package/ios/CarPlay/CarPlayImageLoader.swift +78 -97
- package/ios/CarPlay/CarPlayListItemFactory.swift +303 -92
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +129 -136
- package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
- package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
- package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
- package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
- package/ios/CarPlay/CarPlaySession.swift +209 -0
- package/ios/CarPlay/CarPlayTemplates.swift +63 -0
- package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
- package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +17 -9
- package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +8 -24
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +7 -23
- package/ios/CarPlay/RNABMediaIntentHandler.swift +18 -19
- package/ios/CarPlay/SectionPresentation.swift +77 -0
- package/ios/CarPlay/TopTemplateReplacer.swift +96 -0
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/NavigationError+Conversion.swift +14 -4
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
- package/ios/Extension/Section+Copying.swift +29 -0
- package/ios/Extension/String+IcyCharset.swift +21 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
- package/ios/Extension/Track+Copying.swift +8 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Extension/UIImage+Adaptive.swift +12 -0
- package/ios/Extension/URLError+Connectivity.swift +15 -0
- package/ios/Http/HttpClient.swift +66 -142
- package/ios/HybridAudioBrowser+Browser.swift +153 -0
- package/ios/HybridAudioBrowser+Options.swift +144 -0
- package/ios/HybridAudioBrowser+Player.swift +397 -0
- package/ios/HybridAudioBrowser+PlayerCallbacks.swift +189 -0
- package/ios/HybridAudioBrowser+Stubs.swift +46 -0
- package/ios/HybridAudioBrowser.swift +153 -1610
- package/ios/Model/NitroTypeStubs.swift +146 -24
- package/ios/Model/PlayerUpdateOptions.swift +8 -1
- package/ios/Model/RemoteCommand.swift +18 -0
- package/ios/Model/TrackPlayerError.swift +2 -2
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
- package/ios/Observer/ItemObserver.swift +90 -0
- package/ios/Observer/PlayerObserver.swift +59 -0
- package/ios/Option/SessionCategories.swift +42 -92
- package/ios/Player/AudioSessionController.swift +189 -0
- package/ios/Player/DeferredSeek.swift +70 -0
- package/ios/Player/ErrorStatus.swift +27 -0
- package/ios/Player/MediaLoader.swift +62 -35
- package/ios/Player/NowPlayingUpdater.swift +197 -50
- package/ios/Player/PlaybackFailure.swift +125 -0
- package/ios/Player/PlaybackPersistence.swift +73 -0
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/Player.swift +1078 -0
- package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
- package/ios/Player/PlayerEngine.swift +87 -0
- package/ios/Player/PlayerStatusTypes.swift +2 -6
- package/ios/Player/QueueManager.swift +93 -67
- package/ios/Player/RetryLoop.swift +261 -0
- package/ios/Player/ShuffleOrder.swift +33 -0
- package/ios/Player/SleepTimerManager.swift +1 -1
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +46 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +87 -331
- package/ios/Tests/BrowserPathHelperTests.swift +56 -15
- package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -373
- package/ios/Tests/DeferredSeekTests.swift +70 -0
- package/ios/Tests/EmitterTests.swift +29 -0
- package/ios/Tests/GenerationMemoTests.swift +121 -0
- package/ios/Tests/InertStyleDiagnosticTests.swift +209 -0
- package/ios/Tests/JsonModelsTests.swift +164 -1
- package/ios/Tests/LRUCacheTests.swift +110 -0
- package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
- package/ios/Tests/MediaLoaderTests.swift +12 -48
- package/ios/Tests/ObserverTests.swift +88 -0
- package/ios/Tests/PlaybackErrorTests.swift +76 -0
- package/ios/Tests/PlaybackFailureTests.swift +189 -0
- package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
- package/ios/Tests/PlayerPolicyTests.swift +420 -0
- package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +300 -248
- package/ios/Tests/PlayingStateTests.swift +42 -0
- package/ios/Tests/QueueManagerTests.swift +196 -115
- package/ios/Tests/ReadyValueTests.swift +73 -0
- package/ios/Tests/RemoteCommandControllerTests.swift +152 -0
- package/ios/Tests/RemoteCommandTests.swift +65 -0
- package/ios/Tests/RequestLayerTests.swift +112 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
- package/ios/Tests/RetryLoopTests.swift +270 -0
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +98 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +132 -0
- package/ios/Tests/Support/TestTypes.swift +108 -104
- package/ios/Tests/TabBarEntriesTests.swift +19 -19
- package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
- package/ios/Tests/TopTemplateReplacerTests.swift +172 -0
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
- package/ios/TrackSelector.swift +46 -31
- package/ios/Util/ArtworkImageFetcher.swift +58 -1
- package/ios/Util/Emitter.swift +42 -0
- package/ios/Util/GenerationMemo.swift +36 -0
- package/ios/Util/LRUCache.swift +23 -159
- package/ios/Util/NetworkMonitor.swift +43 -26
- package/ios/Util/ReadyValue.swift +56 -0
- package/ios/Util/SFSymbolRenderer.swift +59 -31
- package/ios/Util/SVGProcessor.swift +9 -12
- package/lib/commonjs/AudioBrowser.js +8 -8
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/CLAUDE.md +52 -0
- package/lib/commonjs/features/browser-config.js +12 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +11 -3
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +1 -1
- package/lib/commonjs/features/equalizer.js +1 -1
- package/lib/commonjs/features/errors.js +3 -3
- package/lib/commonjs/features/favorites.js +14 -11
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/gate.js +16 -1
- package/lib/commonjs/features/gate.js.map +1 -1
- package/lib/commonjs/features/metadata.js +20 -3
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/network.js +1 -1
- package/lib/commonjs/features/nowPlaying.js +1 -1
- package/lib/commonjs/features/output.js +1 -1
- package/lib/commonjs/features/playback/controls.js +4 -2
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/playWhenReady.js +1 -1
- package/lib/commonjs/features/playback/playing.js +1 -1
- package/lib/commonjs/features/playback/progress.js +3 -2
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/rate.js +8 -1
- package/lib/commonjs/features/playback/rate.js.map +1 -1
- package/lib/commonjs/features/playback/state.js +3 -4
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +48 -34
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +18 -9
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +23 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +15 -4
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +13 -6
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/queue/repeatMode.js +1 -1
- package/lib/commonjs/features/queue/shuffle.js +1 -1
- package/lib/commonjs/features/remoteControls.js +13 -92
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +13 -1
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
- package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/getTrackIdentity.js +24 -0
- package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +201 -76
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +175 -100
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +18 -23
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/commonjs/web/browser/sections.js +89 -0
- package/lib/commonjs/web/browser/sections.js.map +1 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js +110 -27
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
- package/lib/commonjs/web/http/followMediaRedirect.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/util/BrowserPathHelper.js +62 -11
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/module/AudioBrowser.js +2 -1
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/CLAUDE.md +52 -0
- package/lib/module/features/browser-config.js +12 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +11 -3
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +1 -1
- package/lib/module/features/equalizer.js +1 -1
- package/lib/module/features/errors.js +3 -3
- package/lib/module/features/favorites.js +14 -11
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/gate.js +16 -1
- package/lib/module/features/gate.js.map +1 -1
- package/lib/module/features/metadata.js +20 -3
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/network.js +1 -1
- package/lib/module/features/nowPlaying.js +1 -1
- package/lib/module/features/output.js +1 -1
- package/lib/module/features/playback/controls.js +4 -2
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/playWhenReady.js +1 -1
- package/lib/module/features/playback/playing.js +1 -1
- package/lib/module/features/playback/progress.js +3 -2
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/rate.js +8 -1
- package/lib/module/features/playback/rate.js.map +1 -1
- package/lib/module/features/playback/state.js +3 -4
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +0 -5
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +47 -32
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +17 -8
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +19 -0
- package/lib/module/features/player/validateOptions.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +15 -4
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +13 -6
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/queue/repeatMode.js +1 -1
- package/lib/module/features/queue/shuffle.js +1 -1
- package/lib/module/features/remoteControls.js +13 -92
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +13 -1
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/test-utils/reactNativeStub.js +58 -0
- package/lib/module/test-utils/reactNativeStub.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +28 -14
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +31 -13
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/getTrackIdentity.js +20 -0
- package/lib/module/utils/getTrackIdentity.js.map +1 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +201 -76
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
- package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/module/web/TrackPlayer/Player.js +254 -39
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
- package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +175 -100
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/FavoriteManager.js +31 -21
- package/lib/module/web/browser/FavoriteManager.js.map +1 -1
- package/lib/module/web/browser/NavigationErrorManager.js +3 -1
- package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +18 -23
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/module/web/browser/sections.js +83 -0
- package/lib/module/web/browser/sections.js.map +1 -0
- package/lib/module/web/http/RequestConfigBuilder.js +110 -27
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/http/followMediaRedirect.js +215 -0
- package/lib/module/web/http/followMediaRedirect.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +4 -3
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/util/BrowserPathHelper.js +62 -11
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +1 -1
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
- package/lib/typescript/src/features/browser.d.ts +10 -2
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +1 -1
- package/lib/typescript/src/features/equalizer.d.ts +1 -1
- package/lib/typescript/src/features/errors.d.ts +3 -3
- package/lib/typescript/src/features/favorites.d.ts +14 -11
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +18 -2
- package/lib/typescript/src/features/gate.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +20 -3
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/network.d.ts +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
- package/lib/typescript/src/features/output.d.ts +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +4 -2
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
- package/lib/typescript/src/features/playback/playing.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/rate.d.ts +8 -1
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/state.d.ts +3 -4
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +108 -56
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +14 -4
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +7 -4
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
- package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +23 -22
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +3 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +387 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +93 -61
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
- package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts +1 -2
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -2
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +4 -2
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +2 -2
- package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +2 -2
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +12 -12
- package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +2 -2
- package/nitrogen/generated/android/c++/JArtworkRendering.hpp +58 -0
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +10 -5
- package/nitrogen/generated/android/c++/JArtworkVariants.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JBrowseError.hpp +2 -2
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +19 -7
- package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +2 -2
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +2 -2
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JCarPlaySiriListButtonPosition.hpp +2 -2
- package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
- package/nitrogen/generated/android/c++/JChapterMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +10 -10
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +11 -5
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +10 -5
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +4 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +18 -12
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +10 -4
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__string__.hpp +102 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +18 -6
- package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -12
- package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_double.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +17 -5
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +2 -2
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +16 -16
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +24 -18
- package/nitrogen/generated/android/c++/JGate.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateDecision.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JGateReason.hpp +2 -2
- package/nitrogen/generated/android/c++/JGridTile.hpp +64 -0
- package/nitrogen/generated/android/c++/JHttpMethod.hpp +2 -2
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +77 -53
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +3 -3
- package/nitrogen/generated/android/c++/JIOSCategory.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +2 -2
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +17 -11
- package/nitrogen/generated/android/c++/JImageContext.hpp +2 -2
- package/nitrogen/generated/android/c++/JImageQueryParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
- package/nitrogen/generated/android/c++/JImageSource.hpp +2 -2
- package/nitrogen/generated/android/c++/JMediaReference.hpp +2 -2
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +10 -5
- package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeAndroidSetupOptions.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +48 -21
- package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JNativeIOSSetupOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +16 -4
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +17 -14
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +9 -12
- package/nitrogen/generated/android/c++/JNavigationError.hpp +2 -2
- package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JNavigationErrorKind.hpp +58 -0
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +2 -2
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +12 -12
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +17 -11
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +2 -2
- package/nitrogen/generated/android/c++/JOptions.hpp +9 -12
- package/nitrogen/generated/android/c++/JOutput.hpp +2 -2
- package/nitrogen/generated/android/c++/JOutputType.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlayback.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +10 -5
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +2 -2
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +7 -13
- package/nitrogen/generated/android/c++/JPlayingState.hpp +2 -2
- package/nitrogen/generated/android/c++/JProgress.hpp +2 -2
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRepeatMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +2 -2
- package/nitrogen/generated/android/c++/JRequestConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +67 -59
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JSearchMode.hpp +2 -2
- package/nitrogen/generated/android/c++/JSearchParams.hpp +2 -2
- package/nitrogen/generated/android/c++/JSection.hpp +116 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
- package/nitrogen/generated/android/c++/JSleepTimer.hpp +4 -4
- package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +2 -2
- package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +2 -2
- package/nitrogen/generated/android/c++/JStallReason.hpp +2 -2
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTimedMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrack.hpp +27 -48
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +18 -12
- package/nitrogen/generated/android/c++/JTrackMetadata.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrackRequest.hpp +2 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +47 -19
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +2 -2
- package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +20 -8
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +20 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +37 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayPlayingIndicatorLocation.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CardImage.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ChapterMetadata.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__string__.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_GateEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Output.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Gate.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateDecision.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeAndroidSetupOptions.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +51 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeIOSSetupOptions.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorKind.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +20 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +25 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Output.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +19 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +37 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +67 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Section.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +18 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +13 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +55 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackLoadEvent.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +43 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +17 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +58 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +16 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +24 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +18 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +16 -7
- package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +2 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +38 -29
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +779 -665
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +34 -16
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +36 -18
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/BrowseResult.swift +12 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
- package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +7 -2
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +48 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +52 -5
- package/nitrogen/generated/ios/swift/NavigationErrorKind.swift +40 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
- package/nitrogen/generated/ios/swift/Section.swift +82 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
- package/nitrogen/generated/ios/swift/SleepTimer.swift +13 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +28 -63
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +12 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_RemoteButtonLayout.swift +30 -0
- package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +13 -0
- package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +12 -0
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
- package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +9 -2
- package/nitrogen/generated/shared/c++/GridTile.hpp +84 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +10 -6
- package/nitrogen/generated/shared/c++/NavigationErrorKind.hpp +76 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
- package/nitrogen/generated/shared/c++/Section.hpp +102 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +18 -30
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +24 -11
- package/src/AudioBrowser.ts +2 -1
- package/src/CLAUDE.md +52 -0
- package/src/features/battery.test.ts +79 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +12 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +11 -3
- package/src/features/carConnection.ts +1 -1
- package/src/features/equalizer.ts +1 -1
- package/src/features/errors.ts +3 -3
- package/src/features/favorites.ts +14 -11
- package/src/features/gate.ts +16 -1
- package/src/features/hook-wiring.test.ts +302 -0
- package/src/features/metadata.ts +20 -3
- package/src/features/network.ts +1 -1
- package/src/features/nowPlaying.ts +1 -1
- package/src/features/output.ts +1 -1
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/playWhenReady.ts +1 -1
- package/src/features/playback/playing.ts +1 -1
- package/src/features/playback/progress.test.ts +169 -0
- package/src/features/playback/progress.ts +3 -2
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +3 -4
- package/src/features/playback/trackPlaybackTime.test.ts +16 -6
- package/src/features/playback/trackPlaybackTime.ts +1 -6
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.ts +126 -76
- package/src/features/player/setup.test.ts +24 -7
- package/src/features/player/setup.ts +22 -10
- package/src/features/player/validateOptions.ts +21 -0
- package/src/features/queue/activeTrack.ts +15 -4
- package/src/features/queue/queue.ts +13 -6
- package/src/features/queue/repeatMode.ts +1 -1
- package/src/features/queue/shuffle.ts +1 -1
- package/src/features/remoteControls.ts +13 -92
- package/src/features/sleepTimer.test.ts +172 -0
- package/src/features/sleepTimer.ts +9 -1
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +147 -0
- package/src/specs/audio-browser.nitro.ts +5 -4
- package/src/style-resolution.test.ts +210 -0
- package/src/test-utils/reactNativeStub.ts +60 -0
- package/src/types/browser-native.ts +7 -3
- package/src/types/browser-nodes.ts +403 -134
- package/src/types/browser.ts +97 -63
- package/src/utils/LazyNativeEmitter.ts +28 -15
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useDebug.test.ts +182 -0
- package/src/utils/useNativeUpdatedValue.test.ts +103 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
- package/src/web/NativeAudioBrowser.ts +240 -83
- package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
- package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
- package/src/web/TrackPlayer/Player.load.test.ts +137 -1
- package/src/web/TrackPlayer/Player.ts +284 -37
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
- package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
- package/src/web/__tests__/lifecycle.test.ts +345 -0
- package/src/web/__tests__/lifecycleHarness.ts +351 -0
- package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
- package/src/web/__tests__/loadSupersession.test.ts +175 -0
- package/src/web/__tests__/retry.test.ts +169 -0
- package/src/web/browser/BrowserManager.ts +209 -111
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/NavigationErrorManager.ts +3 -1
- package/src/web/browser/SearchManager.test.ts +75 -0
- package/src/web/browser/SearchManager.ts +25 -28
- package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
- package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
- package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
- package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
- package/src/web/browser/assertBrowsePageShape.ts +5 -3
- package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
- package/src/web/browser/classifyTrackNavigation.ts +9 -9
- package/src/web/browser/parseSearchResponse.test.ts +8 -2
- package/src/web/browser/sections.test.ts +91 -0
- package/src/web/browser/sections.ts +72 -0
- package/src/web/http/RequestConfigBuilder.test.ts +241 -1
- package/src/web/http/RequestConfigBuilder.ts +140 -33
- package/src/web/http/followMediaRedirect.test.ts +289 -0
- package/src/web/http/followMediaRedirect.ts +253 -0
- package/src/web/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +68 -0
- package/src/web/util/BrowserPathHelper.ts +70 -13
- package/website/guide/android-auto.md +114 -0
- package/website/guide/android-certificates.md +409 -0
- package/website/guide/artwork.md +255 -0
- package/website/guide/audio-output.md +135 -0
- package/website/guide/automotive.md +86 -0
- package/website/guide/basic-usage.md +151 -0
- package/website/guide/battery.md +115 -0
- package/website/guide/browser.md +587 -0
- package/website/guide/carplay.md +650 -0
- package/website/guide/configuration.md +173 -0
- package/website/guide/equalizer.md +231 -0
- package/website/guide/errors.md +310 -0
- package/website/guide/favorites.md +154 -0
- package/website/guide/gate.md +143 -0
- package/website/guide/getting-started.md +46 -0
- package/website/guide/hooks.md +238 -0
- package/website/guide/live-streams.md +125 -0
- package/website/guide/metadata.md +239 -0
- package/website/guide/migrating-from-track-player.md +244 -0
- package/website/guide/native-callback-fetch.md +127 -0
- package/website/guide/network.md +86 -0
- package/website/guide/now-playing.md +175 -0
- package/website/guide/playback.md +328 -0
- package/website/guide/queue.md +300 -0
- package/website/guide/remote-controls.md +256 -0
- package/website/guide/search.md +255 -0
- package/website/guide/sleep-timer.md +268 -0
- package/website/guide/track.md +247 -0
- package/ios/Bridge.h +0 -8
- package/ios/Browser/MediaResolveComposer.swift +0 -114
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/ios/Model/MediaURL.swift +0 -67
- package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
- package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
- package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
- package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
- package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
- package/ios/Observer/PlayerStateObserver.swift +0 -50
- package/ios/Observer/PlayerTimeObserver.swift +0 -55
- package/ios/Option/PitchAlgorithms.swift +0 -17
- package/ios/Option/TimeEventFrequency.swift +0 -18
- package/ios/Player/LoadSeekCoordinator.swift +0 -99
- package/ios/Player/MediaLoaderDelegate.swift +0 -11
- package/ios/Player/PlaybackCoordinator.swift +0 -754
- package/ios/Player/PlaybackEffectHandler.swift +0 -54
- package/ios/Player/PlaybackErrorHandler.swift +0 -175
- package/ios/Player/PlaybackStateStore.swift +0 -27
- package/ios/Player/PlayingStateManager.swift +0 -33
- package/ios/Player/RetryManager.swift +0 -322
- package/ios/Player/SeekCompletionHandler.swift +0 -3
- package/ios/Player/SleepTimerHandling.swift +0 -15
- package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
- package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -325
- package/ios/Tests/MediaResolveTests.swift +0 -126
- package/ios/Tests/OnceValueTests.swift +0 -79
- package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -547
- package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
- package/ios/Tests/PlayingStateManagerTests.swift +0 -57
- package/ios/Tests/RetryManagerTests.swift +0 -89
- package/ios/TrackPlayer.swift +0 -1014
- package/ios/TrackPlayerCallbacks.swift +0 -86
- package/ios/Util/MetadataAdapter.swift +0 -131
- package/ios/Util/OnceValue.swift +0 -104
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteConfig.kt +0 -38
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
package com.audiobrowser.player
|
|
2
2
|
|
|
3
|
+
import com.audiobrowser.extension.identity
|
|
3
4
|
import com.audiobrowser.util.url
|
|
4
|
-
|
|
5
5
|
import com.margelo.nitro.audiobrowser.FormatNowPlayingParams
|
|
6
6
|
import com.margelo.nitro.audiobrowser.NowPlayingMetadata
|
|
7
7
|
import com.margelo.nitro.audiobrowser.NowPlayingUpdate
|
|
@@ -106,10 +106,11 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
106
106
|
private var lastPublished: Published? = null
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* The track id
|
|
110
|
-
*
|
|
109
|
+
* The track identity (id-or-src, falling back to path — same key as [Published]) whose
|
|
110
|
+
* now-playing artwork has been resolved (or is being resolved), so a `nowPlayingArtwork` resolve
|
|
111
|
+
* runs once per track — id-less tracks included — instead of on every render.
|
|
111
112
|
*/
|
|
112
|
-
private var
|
|
113
|
+
private var artworkResolvedForTrack: String? = null
|
|
113
114
|
|
|
114
115
|
/** Size hint (px, square) for now-playing artwork. Mirrors iOS (screen-width-capped to 1200). */
|
|
115
116
|
private val artworkSizePx = 1200.0
|
|
@@ -165,7 +166,7 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
165
166
|
duration = track.duration,
|
|
166
167
|
artwork = track.artwork?.url,
|
|
167
168
|
description = track.description,
|
|
168
|
-
mediaId = track.src ?: track.
|
|
169
|
+
mediaId = track.src ?: track.path,
|
|
169
170
|
genre = track.genre,
|
|
170
171
|
)
|
|
171
172
|
}
|
|
@@ -228,7 +229,7 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
228
229
|
// default on null/throw.
|
|
229
230
|
val activeFormatter = if (enabled) formatter else null
|
|
230
231
|
if (activeFormatter != null) {
|
|
231
|
-
val capturedId = track.src ?: track.
|
|
232
|
+
val capturedId = track.src ?: track.path
|
|
232
233
|
// Gate the raw load-control signal to the buffering state so `stalled` is correct on its
|
|
233
234
|
// own: ExoPlayer's rebuffering flag is polled on a different cadence than state transitions
|
|
234
235
|
// and can linger true into the PLAYING transition as a rebuffer recovers. Classify by
|
|
@@ -267,7 +268,7 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
267
268
|
formatted != null &&
|
|
268
269
|
current != null &&
|
|
269
270
|
currentIdx != null &&
|
|
270
|
-
(current.src ?: current.
|
|
271
|
+
(current.src ?: current.path) == capturedId &&
|
|
271
272
|
renderGeneration == generation
|
|
272
273
|
) {
|
|
273
274
|
applyFields(
|
|
@@ -294,7 +295,7 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
294
295
|
// the same fields are recomputed often; an unconditional stamp would churn the MediaSession
|
|
295
296
|
// (and flicker Android Auto / now-playing) for no visible change. Keyed on the track identity
|
|
296
297
|
// so a new track with a coincidentally identical line still publishes.
|
|
297
|
-
val published = Published(index, track.
|
|
298
|
+
val published = Published(index, track.identity ?: track.path, title, secondaryLine, album)
|
|
298
299
|
if (published == lastPublished) return
|
|
299
300
|
lastPublished = published
|
|
300
301
|
|
|
@@ -308,28 +309,23 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
308
309
|
|
|
309
310
|
/**
|
|
310
311
|
* Resolves the playing track's now-playing artwork and stamps it onto the playing media item.
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* artworkUri — which came from `artwork` (browse
|
|
312
|
+
* Runs for EVERY playing track when `nowPlayingArtwork` is configured — id or not, exactly like
|
|
313
|
+
* iOS (an id-less track leaves any `{id}` token unfilled; the resolver warns and the request
|
|
314
|
+
* visibly 404s). Without a config, the existing artworkUri — which came from `artwork` (browse
|
|
315
|
+
* list path) — is left in place.
|
|
314
316
|
*/
|
|
315
317
|
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
318
|
if (!surface.hasNowPlayingArtworkConfig) {
|
|
325
319
|
// No now-playing artwork config (or no browser) → fall back to the existing artworkUri.
|
|
326
|
-
|
|
320
|
+
artworkResolvedForTrack = null
|
|
327
321
|
return
|
|
328
322
|
}
|
|
329
323
|
|
|
330
|
-
// Already resolved (or resolving) for this track
|
|
331
|
-
|
|
332
|
-
|
|
324
|
+
// Already resolved (or resolving) for this track — avoid a redundant resolve per render.
|
|
325
|
+
// Keyed on track identity (id-or-src, falling back to path) so id-less tracks dedupe too.
|
|
326
|
+
val trackKey = track.identity ?: track.path
|
|
327
|
+
if (trackKey != null && artworkResolvedForTrack == trackKey) return
|
|
328
|
+
artworkResolvedForTrack = trackKey
|
|
333
329
|
|
|
334
330
|
scope.launch {
|
|
335
331
|
val uri =
|
|
@@ -337,10 +333,10 @@ class NowPlayingUpdater(private val surface: NowPlayingSurface, private val scop
|
|
|
337
333
|
?: return@launch
|
|
338
334
|
|
|
339
335
|
// Apply only if still the same track (a fast skip must not be overwritten by a stale
|
|
340
|
-
// result).
|
|
336
|
+
// result), compared on the same identity key the resolve was launched under.
|
|
341
337
|
val currentIdx = surface.currentIndex ?: return@launch
|
|
342
338
|
val current = surface.currentTrack ?: return@launch
|
|
343
|
-
if (current.
|
|
339
|
+
if ((current.identity ?: current.path) != trackKey) return@launch
|
|
344
340
|
|
|
345
341
|
surface.stampArtwork(currentIdx, current, uri)
|
|
346
342
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
package com.audiobrowser.player
|
|
2
2
|
|
|
3
|
-
import com.audiobrowser.util.artworkOf
|
|
4
|
-
|
|
5
|
-
import com.audiobrowser.util.url
|
|
6
|
-
|
|
7
3
|
import android.content.Context
|
|
8
4
|
import android.content.SharedPreferences
|
|
9
5
|
import androidx.core.content.edit
|
|
10
6
|
import androidx.media3.common.C
|
|
7
|
+
import com.audiobrowser.util.EMPTY_TRACK_STYLE
|
|
8
|
+
import com.audiobrowser.util.artworkOf
|
|
9
|
+
import com.audiobrowser.util.toArtworkRendering
|
|
10
|
+
import com.audiobrowser.util.toCardImage
|
|
11
|
+
import com.audiobrowser.util.toImageShape
|
|
12
|
+
import com.audiobrowser.util.toStyleDisplay
|
|
13
|
+
import com.audiobrowser.util.toWireString
|
|
14
|
+
import com.audiobrowser.util.url
|
|
11
15
|
import com.margelo.nitro.audiobrowser.PlaybackState
|
|
12
16
|
import com.margelo.nitro.audiobrowser.RepeatMode
|
|
13
17
|
import com.margelo.nitro.audiobrowser.Track
|
|
@@ -20,12 +24,12 @@ import org.json.JSONObject
|
|
|
20
24
|
import timber.log.Timber
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
|
-
* Persists playback state for resumption after app restart. Stores the current track
|
|
24
|
-
* and player settings to enable playback resumption via MediaButtonReceiver
|
|
25
|
-
* etc.).
|
|
27
|
+
* Persists playback state for resumption after app restart. Stores the current track (including its
|
|
28
|
+
* path), position, and player settings to enable playback resumption via MediaButtonReceiver
|
|
29
|
+
* (Bluetooth play button, etc.).
|
|
26
30
|
*
|
|
27
31
|
* Settings (repeatMode, shuffleEnabled, playbackSpeed) are auto-persisted when set via properties.
|
|
28
|
-
* Position/
|
|
32
|
+
* Position/track are persisted via save() on pause or track change.
|
|
29
33
|
*/
|
|
30
34
|
class PlaybackStateStore(private val player: Player) {
|
|
31
35
|
private val prefs: SharedPreferences =
|
|
@@ -34,7 +38,7 @@ class PlaybackStateStore(private val player: Player) {
|
|
|
34
38
|
/**
|
|
35
39
|
* Persisted playback state for resumption.
|
|
36
40
|
*
|
|
37
|
-
* @param track The track being played (includes
|
|
41
|
+
* @param track The track being played (includes path for queue expansion)
|
|
38
42
|
* @param positionMs The playback position in milliseconds (C.TIME_UNSET for default/live edge)
|
|
39
43
|
* @param repeatMode The repeat mode setting
|
|
40
44
|
* @param shuffleEnabled Whether shuffle mode was enabled
|
|
@@ -150,78 +154,11 @@ class PlaybackStateStore(private val player: Player) {
|
|
|
150
154
|
Timber.d("Saved position: positionMs=0 (queue ended)")
|
|
151
155
|
}
|
|
152
156
|
|
|
153
|
-
private fun trackToJson(track: Track): String =
|
|
154
|
-
JSONObject()
|
|
155
|
-
.apply {
|
|
156
|
-
put("id", track.id)
|
|
157
|
-
put("url", track.url)
|
|
158
|
-
put("src", track.src)
|
|
159
|
-
put("title", track.title)
|
|
160
|
-
put("subtitle", track.subtitle)
|
|
161
|
-
put("artist", track.artist)
|
|
162
|
-
put("albumUrl", track.albumUrl)
|
|
163
|
-
put("album", track.album)
|
|
164
|
-
put("artwork", track.artwork?.url)
|
|
165
|
-
put("description", track.description)
|
|
166
|
-
put("genre", track.genre)
|
|
167
|
-
put("duration", track.duration)
|
|
168
|
-
put("style", track.style?.name)
|
|
169
|
-
put("childrenStyle", track.childrenStyle?.name)
|
|
170
|
-
put("favorited", track.favorited)
|
|
171
|
-
put("groupTitle", track.groupTitle)
|
|
172
|
-
put("live", track.live)
|
|
173
|
-
}
|
|
174
|
-
.toString()
|
|
175
|
-
|
|
176
|
-
private fun trackFromJson(json: String): Track? =
|
|
177
|
-
runCatching {
|
|
178
|
-
val obj = JSONObject(json)
|
|
179
|
-
Track(
|
|
180
|
-
id = obj.optString("id").takeIf { it.isNotEmpty() },
|
|
181
|
-
url = obj.optString("url").takeIf { it.isNotEmpty() },
|
|
182
|
-
src = obj.optString("src").takeIf { it.isNotEmpty() },
|
|
183
|
-
title = obj.getString("title"),
|
|
184
|
-
subtitle = obj.optString("subtitle").takeIf { it.isNotEmpty() },
|
|
185
|
-
artist = obj.optString("artist").takeIf { it.isNotEmpty() },
|
|
186
|
-
albumUrl = obj.optString("albumUrl").takeIf { it.isNotEmpty() },
|
|
187
|
-
album = obj.optString("album").takeIf { it.isNotEmpty() },
|
|
188
|
-
artwork = artworkOf(obj.optString("artwork").takeIf { it.isNotEmpty() }),
|
|
189
|
-
artworkSource = null, // Not persisted - will be re-transformed on browse
|
|
190
|
-
artworkCarPlayTinted = null, // iOS-only, not persisted
|
|
191
|
-
description = obj.optString("description").takeIf { it.isNotEmpty() },
|
|
192
|
-
genre = obj.optString("genre").takeIf { it.isNotEmpty() },
|
|
193
|
-
duration =
|
|
194
|
-
if (obj.has("duration") && !obj.isNull("duration")) obj.getDouble("duration") else null,
|
|
195
|
-
style =
|
|
196
|
-
obj
|
|
197
|
-
.optString("style")
|
|
198
|
-
.takeIf { it.isNotEmpty() }
|
|
199
|
-
?.let { runCatching { TrackStyle.valueOf(it) }.getOrNull() },
|
|
200
|
-
childrenStyle =
|
|
201
|
-
obj
|
|
202
|
-
.optString("childrenStyle")
|
|
203
|
-
.takeIf { it.isNotEmpty() }
|
|
204
|
-
?.let { runCatching { TrackStyle.valueOf(it) }.getOrNull() },
|
|
205
|
-
favorited =
|
|
206
|
-
if (obj.has("favorited") && !obj.isNull("favorited")) obj.getBoolean("favorited")
|
|
207
|
-
else null,
|
|
208
|
-
groupTitle = obj.optString("groupTitle").takeIf { it.isNotEmpty() },
|
|
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,
|
|
214
|
-
imageRow = null, // Not persisted
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
.onFailure { e -> Timber.w(e, "Failed to parse persisted track JSON") }
|
|
218
|
-
.getOrNull()
|
|
219
|
-
|
|
220
157
|
/**
|
|
221
158
|
* Restores player settings from persisted state and returns the state for queue setup.
|
|
222
159
|
*
|
|
223
160
|
* Applies repeatMode, shuffleMode, and playbackSpeed to the player. The caller is responsible for
|
|
224
|
-
* using the returned
|
|
161
|
+
* using the returned path and positionMs to set up the playback queue.
|
|
225
162
|
*
|
|
226
163
|
* @return PersistedState if available, null otherwise
|
|
227
164
|
*/
|
|
@@ -230,7 +167,11 @@ class PlaybackStateStore(private val player: Player) {
|
|
|
230
167
|
// Apply player settings from persisted state
|
|
231
168
|
player.repeatMode = state.repeatMode
|
|
232
169
|
player.shuffleMode = state.shuffleEnabled
|
|
233
|
-
|
|
170
|
+
// Guarded because this input is untrusted: ExoPlayer's setPlaybackSpeed rejects a
|
|
171
|
+
// non-positive speed with IllegalArgumentException, and a snapshot holding one (a
|
|
172
|
+
// corrupted prefs file — the normal write path can't produce it) would then throw on
|
|
173
|
+
// every resume, permanently, since the bad value stays persisted.
|
|
174
|
+
if (state.playbackSpeed > 0f) player.playbackSpeed = state.playbackSpeed
|
|
234
175
|
|
|
235
176
|
Timber.d(
|
|
236
177
|
"Restored player settings: repeatMode=${state.repeatMode}, shuffle=${state.shuffleEnabled}, speed=${state.playbackSpeed}"
|
|
@@ -257,6 +198,100 @@ class PlaybackStateStore(private val player: Player) {
|
|
|
257
198
|
}
|
|
258
199
|
|
|
259
200
|
companion object {
|
|
201
|
+
// Internal (not private) so the round-trip is testable without a Player.
|
|
202
|
+
internal fun trackToJson(track: Track): String =
|
|
203
|
+
JSONObject()
|
|
204
|
+
.apply {
|
|
205
|
+
put("id", track.id)
|
|
206
|
+
put("path", track.path)
|
|
207
|
+
put("src", track.src)
|
|
208
|
+
put("title", track.title)
|
|
209
|
+
put("subtitle", track.subtitle)
|
|
210
|
+
put("artist", track.artist)
|
|
211
|
+
put("albumPath", track.albumPath)
|
|
212
|
+
put("album", track.album)
|
|
213
|
+
put("artwork", track.artwork?.url)
|
|
214
|
+
put("description", track.description)
|
|
215
|
+
put("genre", track.genre)
|
|
216
|
+
put("duration", track.duration)
|
|
217
|
+
// The style block persists as its wire shape (nested object, wire
|
|
218
|
+
// strings) and `disabled` beside it: a restored queue keeps its
|
|
219
|
+
// visible fidelity across process death (ADR 0011).
|
|
220
|
+
put(
|
|
221
|
+
"style",
|
|
222
|
+
track.style?.let { style ->
|
|
223
|
+
JSONObject().apply {
|
|
224
|
+
put("display", style.display?.toWireString())
|
|
225
|
+
put("artworkRendering", style.artworkRendering?.toWireString())
|
|
226
|
+
put("imageShape", style.imageShape?.toWireString())
|
|
227
|
+
put("accessorySymbol", style.accessorySymbol)
|
|
228
|
+
put("cardTint", style.cardTint)
|
|
229
|
+
put("cardImage", style.cardImage?.toWireString())
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
)
|
|
233
|
+
put("disabled", track.disabled)
|
|
234
|
+
put("favorited", track.favorited)
|
|
235
|
+
put("live", track.live)
|
|
236
|
+
put("icyCharset", track.icyCharset)
|
|
237
|
+
}
|
|
238
|
+
.toString()
|
|
239
|
+
|
|
240
|
+
internal fun trackFromJson(json: String): Track? =
|
|
241
|
+
runCatching {
|
|
242
|
+
val obj = JSONObject(json)
|
|
243
|
+
Track(
|
|
244
|
+
id = obj.optString("id").takeIf { it.isNotEmpty() },
|
|
245
|
+
path = obj.optString("path").takeIf { it.isNotEmpty() },
|
|
246
|
+
src = obj.optString("src").takeIf { it.isNotEmpty() },
|
|
247
|
+
title = obj.getString("title"),
|
|
248
|
+
subtitle = obj.optString("subtitle").takeIf { it.isNotEmpty() },
|
|
249
|
+
artist = obj.optString("artist").takeIf { it.isNotEmpty() },
|
|
250
|
+
albumPath = obj.optString("albumPath").takeIf { it.isNotEmpty() },
|
|
251
|
+
album = obj.optString("album").takeIf { it.isNotEmpty() },
|
|
252
|
+
artwork = artworkOf(obj.optString("artwork").takeIf { it.isNotEmpty() }),
|
|
253
|
+
artworkSource = null, // Not persisted - will be re-transformed on browse
|
|
254
|
+
description = obj.optString("description").takeIf { it.isNotEmpty() },
|
|
255
|
+
genre = obj.optString("genre").takeIf { it.isNotEmpty() },
|
|
256
|
+
duration =
|
|
257
|
+
if (obj.has("duration") && !obj.isNull("duration")) obj.getDouble("duration")
|
|
258
|
+
else null,
|
|
259
|
+
// Tolerant (ADR 0011): a snapshot written before the block model —
|
|
260
|
+
// `style` as an enum-name string — is not an object, so optJSONObject
|
|
261
|
+
// yields null and the track restores without a declaration.
|
|
262
|
+
style =
|
|
263
|
+
obj
|
|
264
|
+
.optJSONObject("style")
|
|
265
|
+
?.let { style ->
|
|
266
|
+
TrackStyle(
|
|
267
|
+
display = style.optString("display").toStyleDisplay(),
|
|
268
|
+
artworkRendering = style.optString("artworkRendering").toArtworkRendering(),
|
|
269
|
+
imageShape = style.optString("imageShape").toImageShape(),
|
|
270
|
+
accessorySymbol = style.optString("accessorySymbol").takeIf { it.isNotEmpty() },
|
|
271
|
+
cardTint = style.optString("cardTint").takeIf { it.isNotEmpty() },
|
|
272
|
+
cardImage = style.optString("cardImage").toCardImage(),
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
// An empty block collapses to "no declaration" — one shape on
|
|
276
|
+
// every platform, matching the browse decoders.
|
|
277
|
+
?.takeIf { it != EMPTY_TRACK_STYLE },
|
|
278
|
+
disabled =
|
|
279
|
+
if (obj.has("disabled") && !obj.isNull("disabled")) obj.getBoolean("disabled")
|
|
280
|
+
else null,
|
|
281
|
+
favorited =
|
|
282
|
+
if (obj.has("favorited") && !obj.isNull("favorited")) obj.getBoolean("favorited")
|
|
283
|
+
else null,
|
|
284
|
+
live = if (obj.has("live") && !obj.isNull("live")) obj.getBoolean("live") else null,
|
|
285
|
+
icyCharset = obj.optString("icyCharset").takeIf { it.isNotEmpty() },
|
|
286
|
+
// Not persisted: on resumption the contextual path is re-browsed
|
|
287
|
+
// (expandQueueFromContextualPath), which re-parses each track's request
|
|
288
|
+
// from the API's current response and re-caches it.
|
|
289
|
+
request = null,
|
|
290
|
+
)
|
|
291
|
+
}
|
|
292
|
+
.onFailure { e -> Timber.w(e, "Failed to parse persisted track JSON") }
|
|
293
|
+
.getOrNull()
|
|
294
|
+
|
|
260
295
|
private const val PREFS_NAME = "audio_browser_playback_state_v3"
|
|
261
296
|
private const val KEY_POSITION_MS = "position_ms"
|
|
262
297
|
private const val KEY_REPEAT_MODE = "repeat_mode"
|
|
@@ -20,6 +20,7 @@ import com.audiobrowser.browser.displayArtworkSource
|
|
|
20
20
|
import com.audiobrowser.browser.resolveArtworkUrl
|
|
21
21
|
import com.audiobrowser.browser.unattributedArtworkSource
|
|
22
22
|
import com.audiobrowser.extension.NumberExt.Companion.toSeconds
|
|
23
|
+
import com.audiobrowser.extension.identity
|
|
23
24
|
import com.audiobrowser.model.PlayerSetupOptions
|
|
24
25
|
import com.audiobrowser.model.PlayerUpdateOptions
|
|
25
26
|
import com.audiobrowser.util.CoilBitmapLoader
|
|
@@ -36,7 +37,6 @@ import com.margelo.nitro.audiobrowser.ImageSource
|
|
|
36
37
|
import com.margelo.nitro.audiobrowser.NativeGateRequest
|
|
37
38
|
import com.margelo.nitro.audiobrowser.NowPlayingMetadata
|
|
38
39
|
import com.margelo.nitro.audiobrowser.Playback
|
|
39
|
-
import com.margelo.nitro.audiobrowser.PlaybackActiveTrackChangedEvent
|
|
40
40
|
import com.margelo.nitro.audiobrowser.PlaybackError
|
|
41
41
|
import com.margelo.nitro.audiobrowser.PlaybackPlayWhenReadyChangedEvent
|
|
42
42
|
import com.margelo.nitro.audiobrowser.PlaybackProgressUpdatedEvent
|
|
@@ -168,13 +168,26 @@ class Player(internal val context: Context) {
|
|
|
168
168
|
mediaSessionCallback.updateMediaSession(
|
|
169
169
|
mediaSession,
|
|
170
170
|
options.capabilities,
|
|
171
|
-
options.
|
|
171
|
+
options.remoteButtonLayout,
|
|
172
172
|
searchAvailable,
|
|
173
|
+
options.forwardJumpInterval,
|
|
174
|
+
options.backwardJumpInterval,
|
|
173
175
|
)
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Drops a completed browser registration so [awaitBrowser] waits for the replacement instead of
|
|
182
|
+
* handing out the disposed browser. A [CompletableDeferred] completes once, so it would otherwise
|
|
183
|
+
* pin the first browser for the life of the process.
|
|
184
|
+
*/
|
|
185
|
+
fun forgetBrowserRegistration() {
|
|
186
|
+
if (browserRegistered.isCompleted) {
|
|
187
|
+
browserRegistered = CompletableDeferred()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
178
191
|
/**
|
|
179
192
|
* Suspends until the browser is registered, with a timeout.
|
|
180
193
|
*
|
|
@@ -338,7 +351,7 @@ class Player(internal val context: Context) {
|
|
|
338
351
|
get() = exoPlayer.nextMediaItemIndex == C.INDEX_UNSET
|
|
339
352
|
|
|
340
353
|
/**
|
|
341
|
-
* The source path from which the current queue was expanded (e.g., from a contextual
|
|
354
|
+
* The source path from which the current queue was expanded (e.g., from a contextual path). Used
|
|
342
355
|
* to avoid re-expanding the queue when selecting tracks from the same source.
|
|
343
356
|
*/
|
|
344
357
|
var queueSourcePath: String? = null
|
|
@@ -644,7 +657,7 @@ class Player(internal val context: Context) {
|
|
|
644
657
|
* @param tracks The tracks to set as the new queue.
|
|
645
658
|
* @param startIndex The index to start playback from (default: 0).
|
|
646
659
|
* @param startPositionMs The position in milliseconds to start from (default: 0).
|
|
647
|
-
* @param sourcePath Optional path from which this queue was expanded (for contextual
|
|
660
|
+
* @param sourcePath Optional path from which this queue was expanded (for contextual path
|
|
648
661
|
* optimization).
|
|
649
662
|
*/
|
|
650
663
|
fun setQueue(
|
|
@@ -655,6 +668,9 @@ class Player(internal val context: Context) {
|
|
|
655
668
|
) {
|
|
656
669
|
val mediaItems = TrackFactory.toMedia3(tracks).toMutableList()
|
|
657
670
|
exoPlayer.setMediaItems(mediaItems, startIndex, startPositionMs)
|
|
671
|
+
if (mediaItems.isNotEmpty()) {
|
|
672
|
+
exoPlayer.setShuffleOrder(shuffleOrderLedBy(startIndex, mediaItems.size))
|
|
673
|
+
}
|
|
658
674
|
queueSourcePath = sourcePath
|
|
659
675
|
exoPlayer.prepare()
|
|
660
676
|
}
|
|
@@ -672,17 +688,27 @@ class Player(internal val context: Context) {
|
|
|
672
688
|
/**
|
|
673
689
|
* Sets the favorited state of the currently playing track. Updates the heart icon in media
|
|
674
690
|
* controllers without interrupting playback.
|
|
691
|
+
*
|
|
692
|
+
* @return whether the gesture applied — false only when there is no current track (nothing to
|
|
693
|
+
* favorite), so MediaSession callers can report an invalid state instead of a success the
|
|
694
|
+
* controller then watches revert.
|
|
675
695
|
*/
|
|
676
|
-
fun setActiveTrackFavorited(favorited: Boolean) {
|
|
677
|
-
val currentTrack = this.currentTrack ?: return
|
|
696
|
+
fun setActiveTrackFavorited(favorited: Boolean): Boolean {
|
|
697
|
+
val currentTrack = this.currentTrack ?: return false
|
|
678
698
|
|
|
679
699
|
// Persist to the native favorites cache regardless of player state — the
|
|
680
700
|
// user's gesture is durable even when there's no active media item to
|
|
681
|
-
// update (queue tear-down, between-track gaps, etc.).
|
|
682
|
-
|
|
701
|
+
// update (queue tear-down, between-track gaps, etc.). Keyed by the track
|
|
702
|
+
// identity (id when non-blank, else src).
|
|
703
|
+
currentTrack.identity?.let { identity ->
|
|
704
|
+
browser?.browserManager?.updateFavorite(identity, favorited)
|
|
705
|
+
}
|
|
683
706
|
|
|
707
|
+
// Cache written above: the gesture is durably recorded even without a media
|
|
708
|
+
// item to restamp (queue tear-down, between-track gaps) — that counts as
|
|
709
|
+
// applied; there is also no visible heart to revert in that state.
|
|
684
710
|
val index = exoPlayer.currentMediaItemIndex
|
|
685
|
-
if (index == C.INDEX_UNSET) return
|
|
711
|
+
if (index == C.INDEX_UNSET) return true
|
|
686
712
|
|
|
687
713
|
// Create updated Track with new favorited state
|
|
688
714
|
val updatedTrack = currentTrack.copy(favorited = favorited)
|
|
@@ -706,28 +732,23 @@ class Player(internal val context: Context) {
|
|
|
706
732
|
// Update the heart button icon in notification/Android Auto
|
|
707
733
|
updateFavoriteButtonState(favorited)
|
|
708
734
|
|
|
709
|
-
// Notify JS of the favorite state change
|
|
735
|
+
// Notify JS of the favorite state change. This is the ONLY emit: a favorite
|
|
736
|
+
// toggle is an in-place mutation of the active track, not a transition —
|
|
737
|
+
// onPlaybackActiveTrackChanged / onPlaybackQueueChanged stay
|
|
738
|
+
// transition-only, and the useActiveTrack / useQueue hooks subscribe to
|
|
739
|
+
// onFavoriteChanged themselves.
|
|
710
740
|
callbacks?.onFavoriteChanged(FavoriteChangedEvent(updatedTrack, favorited))
|
|
711
|
-
|
|
712
|
-
// Emit active track changed so useActiveTrack() hook updates
|
|
713
|
-
val activeTrackEvent =
|
|
714
|
-
PlaybackActiveTrackChangedEvent(
|
|
715
|
-
lastIndex = index.toDouble(),
|
|
716
|
-
lastTrack = currentTrack,
|
|
717
|
-
lastPosition = exoPlayer.currentPosition.toSeconds(),
|
|
718
|
-
index = index.toDouble(),
|
|
719
|
-
track = updatedTrack,
|
|
720
|
-
)
|
|
721
|
-
callbacks?.onPlaybackActiveTrackChanged(activeTrackEvent)
|
|
722
|
-
|
|
723
|
-
// Emit queue changed so useQueue() hook updates
|
|
724
|
-
callbacks?.onPlaybackQueueChanged(tracks)
|
|
741
|
+
return true
|
|
725
742
|
}
|
|
726
743
|
|
|
727
|
-
/**
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
744
|
+
/**
|
|
745
|
+
* Toggles the favorited state of the currently playing track.
|
|
746
|
+
*
|
|
747
|
+
* @return whether the toggle applied — false when there is no current track.
|
|
748
|
+
*/
|
|
749
|
+
fun toggleActiveTrackFavorited(): Boolean {
|
|
750
|
+
val currentTrack = this.currentTrack ?: return false
|
|
751
|
+
return setActiveTrackFavorited(currentTrack.favorited != true)
|
|
731
752
|
}
|
|
732
753
|
|
|
733
754
|
// MARK: - Now Playing Metadata
|
|
@@ -834,8 +855,8 @@ class Player(internal val context: Context) {
|
|
|
834
855
|
* A restart from a terminal error begins a new load of the same track: fresh retry budgets and
|
|
835
856
|
* unproven playback, so the user's tap yields a visible first-connect retry window instead of a
|
|
836
857
|
* single silent attempt — the same behavior as re-selecting the track (ADR 0004). Hooked off the
|
|
837
|
-
* player error clearing: every recovery path (retry(), play(), the transport controls'
|
|
838
|
-
*
|
|
858
|
+
* player error clearing: every recovery path (retry(), play(), the transport controls' idle-error
|
|
859
|
+
* recovery) goes through exoPlayer.prepare(), which clears the error.
|
|
839
860
|
*/
|
|
840
861
|
internal fun resetForNewLoad() {
|
|
841
862
|
resetRetryTimer()
|
|
@@ -913,10 +934,23 @@ class Player(internal val context: Context) {
|
|
|
913
934
|
}
|
|
914
935
|
}
|
|
915
936
|
|
|
916
|
-
/**
|
|
937
|
+
/**
|
|
938
|
+
* Jump to the live edge of the current track; no-op unless it declares `live` — the track's own
|
|
939
|
+
* declaration is the gate (matching iOS and the spec), not ExoPlayer's stream-derived liveness,
|
|
940
|
+
* which never marks progressive ICY radio live. A stream with a live window seeks to its edge;
|
|
941
|
+
* anything else reconnects — for a non-seekable stream a fresh connection IS the live edge. A
|
|
942
|
+
* stale URL recovers through the failure-armed re-resolve in [TransformingDataSource].
|
|
943
|
+
*/
|
|
917
944
|
fun seekToLiveEdge() {
|
|
945
|
+
if (currentTrack?.live != true) return
|
|
918
946
|
if (exoPlayer.isCurrentMediaItemLive) {
|
|
919
947
|
exoPlayer.seekToDefaultPosition()
|
|
948
|
+
} else {
|
|
949
|
+
// ExoPlayer.prepare() only re-prepares from STATE_IDLE, hence the raw stop() — not
|
|
950
|
+
// Player.stop(), which would drop the play intent this reconnect must preserve.
|
|
951
|
+
exoPlayer.stop()
|
|
952
|
+
exoPlayer.seekToDefaultPosition()
|
|
953
|
+
exoPlayer.prepare()
|
|
920
954
|
}
|
|
921
955
|
}
|
|
922
956
|
|
|
@@ -1215,8 +1249,8 @@ class Player(internal val context: Context) {
|
|
|
1215
1249
|
val backwardJumpIntervalChanged =
|
|
1216
1250
|
previousOptions.backwardJumpInterval != options.backwardJumpInterval
|
|
1217
1251
|
val capabilitiesChanged = previousOptions.capabilities != options.capabilities
|
|
1218
|
-
val
|
|
1219
|
-
previousOptions.
|
|
1252
|
+
val remoteButtonLayoutChanged =
|
|
1253
|
+
!previousOptions.remoteButtonLayout.sameAs(options.remoteButtonLayout)
|
|
1220
1254
|
val appKilledPlaybackBehaviorChanged =
|
|
1221
1255
|
previousOptions.appKilledPlaybackBehavior != options.appKilledPlaybackBehavior
|
|
1222
1256
|
|
|
@@ -1226,7 +1260,7 @@ class Player(internal val context: Context) {
|
|
|
1226
1260
|
forwardJumpIntervalChanged ||
|
|
1227
1261
|
backwardJumpIntervalChanged ||
|
|
1228
1262
|
capabilitiesChanged ||
|
|
1229
|
-
|
|
1263
|
+
remoteButtonLayoutChanged ||
|
|
1230
1264
|
appKilledPlaybackBehaviorChanged
|
|
1231
1265
|
|
|
1232
1266
|
// Apply only changed properties
|
|
@@ -1236,21 +1270,30 @@ class Player(internal val context: Context) {
|
|
|
1236
1270
|
|
|
1237
1271
|
if (capabilitiesChanged) {
|
|
1238
1272
|
// The `favorite` capability is the single favoriting switch — propagate
|
|
1239
|
-
//
|
|
1240
|
-
browser?.browserManager?.
|
|
1273
|
+
// it to the browser so it can hydrate row hearts.
|
|
1274
|
+
browser?.browserManager?.setFavoriteEnabled(options.capabilities.favoriteEnabled)
|
|
1241
1275
|
}
|
|
1242
1276
|
|
|
1243
1277
|
if (progressUpdateEventIntervalChanged) {
|
|
1244
1278
|
setProgressUpdateInterval(options.progressUpdateEventInterval)
|
|
1245
1279
|
}
|
|
1246
1280
|
|
|
1247
|
-
|
|
1281
|
+
// The jump intervals pick the button icons (ICON_SKIP_BACK_15 and friends), so a changed
|
|
1282
|
+
// interval has to rebuild the layout even when capabilities and placement are untouched.
|
|
1283
|
+
if (
|
|
1284
|
+
capabilitiesChanged ||
|
|
1285
|
+
remoteButtonLayoutChanged ||
|
|
1286
|
+
forwardJumpIntervalChanged ||
|
|
1287
|
+
backwardJumpIntervalChanged
|
|
1288
|
+
) {
|
|
1248
1289
|
val searchAvailable = browser?.browserManager?.config?.hasSearch ?: false
|
|
1249
1290
|
mediaSessionCallback.updateMediaSession(
|
|
1250
1291
|
mediaSession,
|
|
1251
1292
|
options.capabilities,
|
|
1252
|
-
options.
|
|
1293
|
+
options.remoteButtonLayout,
|
|
1253
1294
|
searchAvailable,
|
|
1295
|
+
options.forwardJumpInterval,
|
|
1296
|
+
options.backwardJumpInterval,
|
|
1254
1297
|
)
|
|
1255
1298
|
}
|
|
1256
1299
|
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
package com.audiobrowser.player
|
|
2
2
|
|
|
3
|
-
import com.margelo.nitro.audiobrowser.FavoritesMatchMode
|
|
4
3
|
import com.margelo.nitro.audiobrowser.PlayerCapabilities
|
|
5
4
|
|
|
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. */
|
|
5
|
+
/** Whether the favorite/like control is enabled. Opt-in: only an explicit `true` enables it. */
|
|
19
6
|
val PlayerCapabilities.favoriteEnabled: Boolean
|
|
20
|
-
get() =
|
|
7
|
+
get() = favorite == true
|
|
@@ -59,7 +59,7 @@ class PlayerListener(private val player: Player) : MediaPlayer.Listener {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Extract and emit timed metadata (ICY, ID3, etc.)
|
|
62
|
-
PlaybackMetadata.from(metadata)?.let {
|
|
62
|
+
PlaybackMetadata.from(metadata, player.currentTrack?.icyCharset)?.let {
|
|
63
63
|
val timed = it.toNitro()
|
|
64
64
|
player.callbacks?.onTimedMetadata(timed)
|
|
65
65
|
player.nowPlaying.onTimedMetadataReceived(timed)
|
|
@@ -107,7 +107,8 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
107
107
|
*/
|
|
108
108
|
private fun exhaustedBudget(currentTime: Long): String? {
|
|
109
109
|
firstErrorTime?.let { start ->
|
|
110
|
-
if (currentTime - start >= maxRetryDurationMs)
|
|
110
|
+
if (currentTime - start >= maxRetryDurationMs)
|
|
111
|
+
return "max retry duration ($maxRetryDurationMs ms)"
|
|
111
112
|
}
|
|
112
113
|
if (!hasPlayed() && isOnline()) {
|
|
113
114
|
firstOnlineErrorTime?.let { start ->
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
package com.audiobrowser.player
|
|
2
|
+
|
|
3
|
+
import androidx.media3.exoplayer.source.ShuffleOrder
|
|
4
|
+
import kotlin.random.Random
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A shuffle order over [count] items with [startIndex] pinned to shuffle position 0.
|
|
8
|
+
*
|
|
9
|
+
* Media3 does not do this for us. `ExoPlayerImpl.setMediaSources` hands the start index to
|
|
10
|
+
* `ShuffleOrder.cloneAndSet(insertionCount, startIndex)`, but that is an interface default of
|
|
11
|
+
* `cloneAndClear().cloneAndInsert(0, insertionCount)` — the start index is discarded — and
|
|
12
|
+
* `DefaultShuffleOrder` does not override it (verified against the pinned media3 build). So with
|
|
13
|
+
* shuffle on, the track playback starts from lands at a random position in the order, and a 1-in-N
|
|
14
|
+
* share of queues put it last: `nextMediaItemIndex` is then `INDEX_UNSET` from the very first
|
|
15
|
+
* track, so auto-advance ends the queue after one track and fires `onQueueEnded`. The
|
|
16
|
+
* voice-assistant cold resume expands a queue exactly this way, so it sits squarely on that path.
|
|
17
|
+
*
|
|
18
|
+
* Applied unconditionally by `Player.setQueue`, like the Swift twin's `adoptInitialCurrent`:
|
|
19
|
+
* enabling shuffle later does not regenerate the order, so it has to be sane whether or not shuffle
|
|
20
|
+
* is on right now.
|
|
21
|
+
*/
|
|
22
|
+
internal fun shuffleOrderLedBy(startIndex: Int, count: Int, random: Random = Random): ShuffleOrder {
|
|
23
|
+
val first = startIndex.coerceIn(0, (count - 1).coerceAtLeast(0))
|
|
24
|
+
val indices = IntArray(count)
|
|
25
|
+
if (count > 0) {
|
|
26
|
+
indices[0] = first
|
|
27
|
+
((0 until count) - first).shuffled().forEachIndexed { i, index -> indices[i + 1] = index }
|
|
28
|
+
}
|
|
29
|
+
return ShuffleOrder.DefaultShuffleOrder(indices, random.nextLong())
|
|
30
|
+
}
|