react-native-audio-browser 0.1.1 → 0.2.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AudioBrowser.podspec +1 -1
- package/README.md +180 -2
- package/android/build.gradle +10 -0
- package/android/gradle.properties +1 -1
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +401 -141
- package/android/src/main/java/com/audiobrowser/Callbacks.kt +4 -6
- package/android/src/main/java/com/audiobrowser/Service.kt +67 -18
- package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +37 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +34 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +443 -178
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +300 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +79 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +41 -4
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +43 -0
- package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +35 -0
- package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +109 -97
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +6 -10
- package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +40 -8
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +31 -37
- package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +4 -1
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +119 -0
- package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +18 -1
- package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +153 -0
- package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +141 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +15 -3
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +415 -131
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +154 -276
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +348 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +129 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +85 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +27 -5
- package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +56 -0
- package/android/src/main/java/com/audiobrowser/player/Player.kt +452 -576
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +20 -0
- package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +130 -0
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +190 -67
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +117 -53
- package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +37 -3
- package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +80 -0
- package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +50 -0
- package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +84 -40
- package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +81 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +141 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +37 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +41 -0
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +209 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +161 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +28 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +26 -0
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +24 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +49 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +36 -0
- package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +23 -300
- package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +13 -23
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
- package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +4 -3
- package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +211 -0
- package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +58 -0
- package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +2 -1
- package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +14 -0
- package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +6 -111
- package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +22 -8
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +111 -80
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +166 -0
- package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +46 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +39 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +114 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +141 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +4 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +177 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +54 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +96 -0
- package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +1 -2
- package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +72 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +159 -0
- package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +56 -0
- package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +216 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +442 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +191 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +198 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +137 -0
- package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +36 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +268 -0
- package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +68 -0
- package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +193 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +107 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +73 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +75 -0
- package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +18 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +163 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +28 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +53 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +58 -0
- package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +57 -0
- package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +50 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +63 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +35 -0
- package/android/src/test/resources/certs/isrg-root-x1.pem +31 -0
- package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
- package/android/src/test/resources/certs/letsencrypt-r13.pem +29 -0
- package/android/src/test/resources/certs/stationplaylist-leaf.pem +34 -0
- package/ios/Browser/BrowserConfig.swift +41 -11
- package/ios/Browser/BrowserManager+URLResolution.swift +213 -93
- package/ios/Browser/BrowserManager.swift +303 -110
- package/ios/Browser/BrowserPathHelper.swift +32 -3
- package/ios/Browser/JsonModels.swift +287 -66
- package/ios/Browser/MediaResolveComposer.swift +114 -0
- package/ios/Browser/SearchDrillIn.swift +44 -0
- package/ios/Browser/SectionScope.swift +35 -0
- package/ios/Browser/TabBarEntries.swift +15 -0
- package/ios/CarPlay/CPInterfaceController+Safe.swift +126 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
- package/ios/CarPlay/CarPlayController.swift +739 -149
- package/ios/CarPlay/CarPlayImageLoader.swift +57 -8
- package/ios/CarPlay/CarPlayListItemFactory.swift +44 -35
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +180 -36
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +19 -0
- package/ios/CarPlay/RNABAudioBrowser.h +15 -10
- package/ios/CarPlay/RNABAudioBrowser.m +15 -14
- package/ios/CarPlay/RNABCarPlaySceneDelegate.m +2 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +75 -0
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +69 -0
- package/ios/CarPlay/RNABMediaIntentHandler.swift +53 -43
- package/ios/Extension/Capability+RemoteCommand.swift +7 -9
- package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/NavigationError+Conversion.swift +8 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +20 -0
- package/ios/Extension/RequestConfig+Copying.swift +31 -0
- package/ios/Extension/ResolvedTrack+Copying.swift +10 -4
- package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Track+AVPlayer.swift +4 -4
- package/ios/Extension/Track+Copying.swift +9 -3
- package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Variant+Artwork.swift +49 -0
- package/ios/HybridAudioBrowser.swift +750 -173
- package/ios/Model/NitroTypeStubs.swift +299 -224
- package/ios/Model/PlayerUpdateOptions.swift +23 -23
- package/ios/Model/RemoteCommand.swift +6 -6
- package/ios/Model/TrackPlayerError.swift +82 -18
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +99 -121
- package/ios/NowPlayingInfo/SilentAudioPrimer.swift +73 -0
- package/ios/Observer/PlayerItemNotificationObserver.swift +45 -5
- package/ios/Observer/PlayerItemPropertyObserver.swift +27 -4
- package/ios/Observer/PlayerTimeObserver.swift +3 -53
- package/ios/Option/SessionCategories.swift +33 -11
- package/ios/Player/AirPlayStallJudgement.swift +25 -0
- package/ios/Player/EndOfTrackJudgement.swift +32 -0
- package/ios/Player/LoadSeekCoordinator.swift +16 -1
- package/ios/Player/MediaIntentCriteria.swift +139 -0
- package/ios/Player/MediaLoader.swift +28 -10
- package/ios/Player/NowPlayingUpdater.swift +119 -26
- package/ios/Player/PersistedPlaybackState.swift +11 -0
- package/ios/Player/PlaybackCoordinator.swift +282 -51
- package/ios/Player/PlaybackCoordinatorCallbacks.swift +6 -1
- package/ios/Player/PlaybackEffectHandler.swift +19 -9
- package/ios/Player/PlaybackErrorHandler.swift +97 -13
- package/ios/Player/PlaybackStateMachine.swift +18 -13
- package/ios/Player/PlaybackStateStore.swift +27 -0
- package/ios/Player/PlaybackTimer.swift +61 -0
- package/ios/Player/PlayingStateManager.swift +3 -2
- package/ios/Player/QueueManager.swift +67 -61
- package/ios/Player/RetryManager.swift +97 -21
- package/ios/Player/SleepTimerHandling.swift +8 -0
- package/ios/Player/SleepTimerManager.swift +38 -5
- package/ios/Player/VolumeFader.swift +77 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +31 -15
- package/ios/Tests/AirPlayStallJudgementTests.swift +52 -0
- package/ios/Tests/BrowserPathHelperTests.swift +28 -0
- package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
- package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
- package/ios/Tests/EndOfTrackJudgementTests.swift +35 -0
- package/ios/Tests/JsonModelsTests.swift +58 -0
- package/ios/Tests/LoadSeekCoordinatorTests.swift +38 -7
- package/ios/Tests/MediaIntentCriteriaTests.swift +170 -0
- package/ios/Tests/MediaLoaderAssetOptionsTests.swift +46 -0
- package/ios/Tests/MediaLoaderTests.swift +23 -8
- package/ios/Tests/MediaResolveTests.swift +126 -0
- package/ios/Tests/OnceValueTests.swift +79 -0
- package/ios/Tests/PlaybackCoordinatorTests.swift +784 -13
- package/ios/Tests/PlaybackErrorHandlerTests.swift +380 -46
- package/ios/Tests/PlaybackStateMachineTests.swift +33 -8
- package/ios/Tests/PlaybackStateStoreTests.swift +48 -0
- package/ios/Tests/PlaybackTimerTests.swift +55 -0
- package/ios/Tests/PlayingStateManagerTests.swift +57 -0
- package/ios/Tests/QueueManagerTests.swift +149 -18
- package/ios/Tests/ResolvedTrackCopyingTests.swift +15 -8
- package/ios/Tests/RetryManagerTests.swift +89 -0
- package/ios/Tests/SearchDrillInTests.swift +63 -0
- package/ios/Tests/SectionScopeTests.swift +82 -0
- package/ios/Tests/SleepTimerManagerTests.swift +104 -0
- package/ios/Tests/Support/TestTypes.swift +61 -20
- package/ios/Tests/TabBarEntriesTests.swift +71 -0
- package/ios/Tests/TrackSelectorTests.swift +15 -15
- package/ios/TrackPlayer.swift +380 -58
- package/ios/TrackPlayerCallbacks.swift +0 -6
- package/ios/TrackSelector.swift +5 -5
- package/ios/Util/ArtworkImageFetcher.swift +4 -2
- package/ios/Util/NetworkMonitor.swift +7 -3
- package/ios/Util/OnceValue.swift +34 -0
- package/lib/commonjs/features/browser-config.js +227 -0
- package/lib/commonjs/features/browser-config.js.map +1 -0
- package/lib/commonjs/features/browser.js +59 -158
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +42 -0
- package/lib/commonjs/features/carConnection.js.map +1 -0
- package/lib/commonjs/features/errors.js +34 -2
- package/lib/commonjs/features/errors.js.map +1 -1
- package/lib/commonjs/features/gate.js +149 -0
- package/lib/commonjs/features/gate.js.map +1 -0
- package/lib/commonjs/features/index.js +22 -0
- package/lib/commonjs/features/index.js.map +1 -1
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/nowPlaying.js +35 -0
- package/lib/commonjs/features/nowPlaying.js.map +1 -1
- package/lib/commonjs/features/output.js +37 -23
- package/lib/commonjs/features/output.js.map +1 -1
- package/lib/commonjs/features/playback/controls.js +9 -0
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/index.js +11 -0
- package/lib/commonjs/features/playback/index.js.map +1 -1
- package/lib/commonjs/features/playback/progress.js +28 -12
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +49 -13
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +249 -3
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +10 -3
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/remoteControls.js +1 -12
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +9 -4
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/native.js +5 -0
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.web.js +4 -1
- package/lib/commonjs/native.web.js.map +1 -1
- package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/artwork.js +31 -0
- package/lib/commonjs/utils/artwork.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/index.js +13 -5
- package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +176 -50
- package/lib/commonjs/web/browser/BrowserManager.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 +11 -9
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/commonjs/web/http/HttpClient.js +4 -23
- package/lib/commonjs/web/http/HttpClient.js.map +1 -1
- package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/playbackErrorKind.js +57 -0
- package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
- package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
- package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/player/OptionsManager.js +9 -17
- package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
- package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
- package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
- package/lib/module/features/browser-config.js +221 -0
- package/lib/module/features/browser-config.js.map +1 -0
- package/lib/module/features/browser.js +53 -156
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +37 -0
- package/lib/module/features/carConnection.js.map +1 -0
- package/lib/module/features/errors.js +34 -2
- package/lib/module/features/errors.js.map +1 -1
- package/lib/module/features/gate.js +144 -0
- package/lib/module/features/gate.js.map +1 -0
- package/lib/module/features/index.js +2 -0
- package/lib/module/features/index.js.map +1 -1
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/nowPlaying.js +33 -0
- package/lib/module/features/nowPlaying.js.map +1 -1
- package/lib/module/features/output.js +32 -19
- package/lib/module/features/output.js.map +1 -1
- package/lib/module/features/playback/controls.js +8 -0
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/index.js +1 -0
- package/lib/module/features/playback/index.js.map +1 -1
- package/lib/module/features/playback/progress.js +28 -12
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +88 -0
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +48 -13
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +249 -3
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/queue/queue.js +10 -3
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/remoteControls.js +0 -11
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +9 -4
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/native.js +5 -0
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.web.js +4 -1
- package/lib/module/native.web.js.map +1 -1
- package/lib/module/utils/LazyNativeEmitter.js +0 -3
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +0 -3
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/artwork.js +26 -0
- package/lib/module/utils/artwork.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +302 -125
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/module/web/TrackPlayer/Player.js +90 -26
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
- package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/module/web/TrackPlayer/index.js +2 -1
- package/lib/module/web/TrackPlayer/index.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +176 -50
- package/lib/module/web/browser/BrowserManager.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 +11 -9
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/module/web/browser/parseSearchResponse.js +16 -0
- package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/module/web/http/HttpClient.js +4 -23
- package/lib/module/web/http/HttpClient.js.map +1 -1
- package/lib/module/web/http/RequestConfigBuilder.js +107 -58
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/playbackErrorKind.js +52 -0
- package/lib/module/web/playbackErrorKind.js.map +1 -0
- package/lib/module/web/player/MediaSessionManager.js +116 -0
- package/lib/module/web/player/MediaSessionManager.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +7 -5
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/player/OptionsManager.js +9 -17
- package/lib/module/web/player/OptionsManager.js.map +1 -1
- package/lib/module/web/player/RemoteCommandController.js +92 -0
- package/lib/module/web/player/RemoteCommandController.js.map +1 -0
- package/lib/typescript/src/features/browser-config.d.ts +12 -0
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
- package/lib/typescript/src/features/browser.d.ts +40 -1
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +20 -0
- package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
- package/lib/typescript/src/features/errors.d.ts +58 -3
- package/lib/typescript/src/features/errors.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +77 -0
- package/lib/typescript/src/features/gate.d.ts.map +1 -0
- package/lib/typescript/src/features/index.d.ts +2 -0
- package/lib/typescript/src/features/index.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +6 -4
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
- package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
- package/lib/typescript/src/features/output.d.ts +28 -18
- package/lib/typescript/src/features/output.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +5 -0
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/index.d.ts +1 -0
- package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +3 -0
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +92 -93
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +206 -167
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +9 -2
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +0 -13
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native.d.ts +1 -2
- package/lib/typescript/src/native.d.ts.map +1 -1
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-native.d.ts +9 -3
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +349 -85
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/artwork.d.ts +19 -0
- package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -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 +131 -0
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
- package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
- package/nitrogen/generated/android/c++/JGate.hpp +62 -0
- package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
- package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
- package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
- package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
- package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
- package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
- package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
- package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
- package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
- package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
- package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
- package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
- package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt} +12 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
- package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
- package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
- package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
- package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
- package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
- package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +77 -0
- package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
- package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
- package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
- package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
- package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
- package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift → Func_void_std__shared_ptr_Promise_GateDecision__.swift} +17 -17
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
- package/nitrogen/generated/ios/swift/Gate.swift +47 -0
- package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
- package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
- package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
- package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
- package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
- package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
- package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
- package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
- package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
- package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
- package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
- package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
- package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
- package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
- package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
- package/nitrogen/generated/ios/swift/Options.swift +10 -4
- package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
- package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
- package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
- package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
- package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
- package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
- package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
- package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
- package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +74 -8
- package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
- package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
- package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
- package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
- package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
- package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
- package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
- package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
- package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
- package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
- package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
- package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
- package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
- package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
- package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
- package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
- package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
- package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
- package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
- package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
- package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
- package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
- package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
- package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
- package/nitrogen/generated/shared/c++/Options.hpp +8 -8
- package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
- package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
- package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
- package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
- package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
- package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
- package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
- package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
- package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +24 -5
- package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
- package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
- package/package.json +11 -6
- package/src/codegen-no-config-variant.test.ts +70 -0
- package/src/features/browser-config.test.ts +110 -0
- package/src/features/browser-config.ts +293 -0
- package/src/features/browser.test.ts +19 -0
- package/src/features/browser.ts +58 -201
- package/src/features/carConnection.ts +36 -0
- package/src/features/errors.ts +68 -2
- package/src/features/gate.test.ts +72 -0
- package/src/features/gate.ts +155 -0
- package/src/features/index.ts +2 -0
- package/src/features/metadata.ts +6 -12
- package/src/features/nowPlaying.ts +36 -0
- package/src/features/output.ts +35 -22
- package/src/features/playback/controls.ts +8 -0
- package/src/features/playback/index.ts +1 -0
- package/src/features/playback/progress.ts +31 -12
- package/src/features/playback/trackPlaybackTime.test.ts +66 -0
- package/src/features/playback/trackPlaybackTime.ts +106 -0
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.test.ts +38 -0
- package/src/features/player/options.ts +140 -75
- package/src/features/player/setup.test.ts +117 -0
- package/src/features/player/setup.ts +390 -175
- package/src/features/queue/queue.test.ts +36 -0
- package/src/features/queue/queue.ts +15 -4
- package/src/features/remoteControls.ts +0 -23
- package/src/features/sleepTimer.ts +23 -4
- package/src/native.ts +5 -0
- package/src/native.web.ts +4 -1
- package/src/specs/audio-browser.nitro.ts +131 -41
- package/src/types/browser-native.ts +19 -6
- package/src/types/browser-nodes.ts +160 -13
- package/src/types/browser.ts +377 -89
- package/src/utils/LazyNativeEmitter.ts +0 -2
- package/src/utils/NativeUpdatedValue.ts +0 -2
- package/src/utils/artwork.ts +30 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
- package/src/web/NativeAudioBrowser.ts +365 -158
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
- package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
- package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
- package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
- package/src/web/TrackPlayer/Player.load.test.ts +86 -0
- package/src/web/TrackPlayer/Player.ts +113 -39
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
- package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
- package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
- package/src/web/TrackPlayer/QueueManager.ts +302 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
- package/src/web/TrackPlayer/RepeatMode.ts +1 -1
- package/src/web/TrackPlayer/SleepTimer.ts +38 -3
- package/src/web/TrackPlayer/VolumeFader.ts +74 -0
- package/src/web/TrackPlayer/index.ts +2 -1
- package/src/web/browser/BrowserManager.ts +231 -62
- package/src/web/browser/NavigationErrorManager.ts +3 -1
- package/src/web/browser/SearchManager.ts +11 -15
- package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
- package/src/web/browser/assertBrowsePageShape.ts +27 -0
- package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
- package/src/web/browser/classifyTrackNavigation.ts +35 -0
- package/src/web/browser/parseSearchResponse.test.ts +25 -0
- package/src/web/browser/parseSearchResponse.ts +15 -0
- package/src/web/http/HttpClient.ts +5 -35
- package/src/web/http/RequestConfigBuilder.test.ts +59 -0
- package/src/web/http/RequestConfigBuilder.ts +120 -63
- package/src/web/playbackErrorKind.test.ts +55 -0
- package/src/web/playbackErrorKind.ts +56 -0
- package/src/web/player/MediaSessionManager.test.ts +220 -0
- package/src/web/player/MediaSessionManager.ts +151 -0
- package/src/web/player/NowPlayingManager.test.ts +46 -0
- package/src/web/player/NowPlayingManager.ts +6 -5
- package/src/web/player/OptionsManager.ts +12 -18
- package/src/web/player/RemoteCommandController.test.ts +171 -0
- package/src/web/player/RemoteCommandController.ts +166 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
- package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
- package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
- package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
- package/ios/CarPlay/Track+CarPlay.swift +0 -63
- package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
- package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
- package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
- package/lib/commonjs/features/rating.js +0 -2
- package/lib/commonjs/features/rating.js.map +0 -1
- package/lib/commonjs/types/player.js +0 -2
- package/lib/commonjs/types/player.js.map +0 -1
- package/lib/commonjs/web/SimpleRouter.test.js +0 -174
- package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/module/features/rating.js +0 -2
- package/lib/module/features/rating.js.map +0 -1
- package/lib/module/types/player.js +0 -2
- package/lib/module/types/player.js.map +0 -1
- package/lib/module/web/SimpleRouter.test.js +0 -174
- package/lib/module/web/SimpleRouter.test.js.map +0 -1
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/typescript/src/features/rating.d.ts +0 -14
- package/lib/typescript/src/features/rating.d.ts.map +0 -1
- package/lib/typescript/src/native.web.d.ts +0 -3
- package/lib/typescript/src/native.web.d.ts.map +0 -1
- package/lib/typescript/src/types/player.d.ts +0 -64
- package/lib/typescript/src/types/player.d.ts.map +0 -1
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
- package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
- package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
- package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
- package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
- package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
- package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
- package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
- package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
- package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
- package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
- package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
- package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
- package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
- package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
- package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
- package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
- package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
- package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
- package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
- package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
- package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
- package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
- package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
- package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
- package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
- package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
- package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
- package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
- package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
- package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
- package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
- package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
- package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
- package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
- package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
- package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
- package/src/features/rating.ts +0 -17
- package/src/types/player.ts +0 -69
- package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
|
@@ -8,6 +8,7 @@ import android.os.Handler
|
|
|
8
8
|
import android.os.IBinder
|
|
9
9
|
import android.os.Looper
|
|
10
10
|
import androidx.annotation.Keep
|
|
11
|
+
import androidx.car.app.connection.CarConnection
|
|
11
12
|
import androidx.lifecycle.DefaultLifecycleObserver
|
|
12
13
|
import androidx.lifecycle.LifecycleOwner
|
|
13
14
|
import androidx.lifecycle.ProcessLifecycleOwner
|
|
@@ -15,38 +16,41 @@ import androidx.media3.session.MediaBrowser
|
|
|
15
16
|
import androidx.media3.session.SessionToken
|
|
16
17
|
import com.audiobrowser.browser.BrowserConfig
|
|
17
18
|
import com.audiobrowser.browser.BrowserManager
|
|
18
|
-
import com.audiobrowser.browser.handleTrackLoad
|
|
19
19
|
import com.audiobrowser.browser.CallbackException
|
|
20
20
|
import com.audiobrowser.browser.ContentNotFoundException
|
|
21
21
|
import com.audiobrowser.browser.HttpStatusException
|
|
22
22
|
import com.audiobrowser.browser.NetworkException
|
|
23
|
+
import com.audiobrowser.browser.handleTrackLoad
|
|
24
|
+
import com.audiobrowser.browser.resolveMediaUrl
|
|
23
25
|
import com.audiobrowser.extension.NumberExt.Companion.toSeconds
|
|
24
|
-
import com.audiobrowser.http.RequestConfigBuilder
|
|
25
|
-
import com.audiobrowser.model.PlaybackMetadata
|
|
26
26
|
import com.audiobrowser.model.PlayerSetupOptions
|
|
27
27
|
import com.audiobrowser.model.PlayerUpdateOptions
|
|
28
|
+
import com.audiobrowser.player.Player
|
|
28
29
|
import com.audiobrowser.util.BatteryOptimizationHelper
|
|
29
30
|
import com.audiobrowser.util.BatteryWarningStore
|
|
30
31
|
import com.audiobrowser.util.BrowserPathHelper
|
|
31
|
-
import com.audiobrowser.util.
|
|
32
|
+
import com.audiobrowser.util.OutputMonitor
|
|
33
|
+
import com.audiobrowser.util.OutputSwitcher
|
|
32
34
|
import com.audiobrowser.util.SystemVolumeMonitor
|
|
33
35
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
34
36
|
import com.google.common.util.concurrent.ListenableFuture
|
|
35
37
|
import com.margelo.nitro.NitroModules
|
|
36
|
-
import com.margelo.nitro.audiobrowser.ChapterMetadata
|
|
37
|
-
import com.margelo.nitro.audiobrowser.TimedMetadata
|
|
38
|
-
import com.margelo.nitro.audiobrowser.TrackMetadata
|
|
39
38
|
import com.margelo.nitro.audiobrowser.BatteryOptimizationStatus
|
|
40
39
|
import com.margelo.nitro.audiobrowser.BatteryOptimizationStatusChangedEvent
|
|
41
40
|
import com.margelo.nitro.audiobrowser.BatteryWarningPendingChangedEvent
|
|
41
|
+
import com.margelo.nitro.audiobrowser.ChapterMetadata
|
|
42
42
|
import com.margelo.nitro.audiobrowser.EqualizerSettings
|
|
43
43
|
import com.margelo.nitro.audiobrowser.FavoriteChangedEvent
|
|
44
44
|
import com.margelo.nitro.audiobrowser.FormatNavigationErrorParams
|
|
45
45
|
import com.margelo.nitro.audiobrowser.FormattedNavigationError
|
|
46
|
+
import com.margelo.nitro.audiobrowser.Gate
|
|
47
|
+
import com.margelo.nitro.audiobrowser.GateDecision
|
|
48
|
+
import com.margelo.nitro.audiobrowser.GateEvent
|
|
46
49
|
import com.margelo.nitro.audiobrowser.HybridAudioBrowserSpec
|
|
47
|
-
import com.margelo.nitro.audiobrowser.IosOutput
|
|
48
50
|
import com.margelo.nitro.audiobrowser.MediaRequestConfig
|
|
49
51
|
import com.margelo.nitro.audiobrowser.NativeBrowserConfiguration
|
|
52
|
+
import com.margelo.nitro.audiobrowser.NativeGateRequest
|
|
53
|
+
import com.margelo.nitro.audiobrowser.NativeSetupPlayerOptions
|
|
50
54
|
import com.margelo.nitro.audiobrowser.NativeUpdateOptions
|
|
51
55
|
import com.margelo.nitro.audiobrowser.NavigationError
|
|
52
56
|
import com.margelo.nitro.audiobrowser.NavigationErrorEvent
|
|
@@ -54,7 +58,7 @@ import com.margelo.nitro.audiobrowser.NavigationErrorType
|
|
|
54
58
|
import com.margelo.nitro.audiobrowser.NowPlayingMetadata
|
|
55
59
|
import com.margelo.nitro.audiobrowser.NowPlayingUpdate
|
|
56
60
|
import com.margelo.nitro.audiobrowser.Options
|
|
57
|
-
import com.margelo.nitro.audiobrowser.
|
|
61
|
+
import com.margelo.nitro.audiobrowser.Output
|
|
58
62
|
import com.margelo.nitro.audiobrowser.Playback
|
|
59
63
|
import com.margelo.nitro.audiobrowser.PlaybackActiveTrackChangedEvent
|
|
60
64
|
import com.margelo.nitro.audiobrowser.PlaybackError
|
|
@@ -62,6 +66,7 @@ import com.margelo.nitro.audiobrowser.PlaybackErrorEvent
|
|
|
62
66
|
import com.margelo.nitro.audiobrowser.PlaybackPlayWhenReadyChangedEvent
|
|
63
67
|
import com.margelo.nitro.audiobrowser.PlaybackProgressUpdatedEvent
|
|
64
68
|
import com.margelo.nitro.audiobrowser.PlaybackQueueEndedEvent
|
|
69
|
+
import com.margelo.nitro.audiobrowser.PlaybackState
|
|
65
70
|
import com.margelo.nitro.audiobrowser.PlayingState
|
|
66
71
|
import com.margelo.nitro.audiobrowser.Progress
|
|
67
72
|
import com.margelo.nitro.audiobrowser.RemoteJumpBackwardEvent
|
|
@@ -69,15 +74,14 @@ import com.margelo.nitro.audiobrowser.RemoteJumpForwardEvent
|
|
|
69
74
|
import com.margelo.nitro.audiobrowser.RemotePlayIdEvent
|
|
70
75
|
import com.margelo.nitro.audiobrowser.RemotePlaySearchEvent
|
|
71
76
|
import com.margelo.nitro.audiobrowser.RemoteSeekEvent
|
|
72
|
-
import com.margelo.nitro.audiobrowser.RemoteSetRatingEvent
|
|
73
77
|
import com.margelo.nitro.audiobrowser.RemoteSkipEvent
|
|
74
78
|
import com.margelo.nitro.audiobrowser.RepeatMode
|
|
75
79
|
import com.margelo.nitro.audiobrowser.RepeatModeChangedEvent
|
|
76
|
-
import com.margelo.nitro.audiobrowser.RequestConfig
|
|
77
80
|
import com.margelo.nitro.audiobrowser.ResolvedTrack
|
|
78
81
|
import com.margelo.nitro.audiobrowser.SleepTimer
|
|
82
|
+
import com.margelo.nitro.audiobrowser.TimedMetadata
|
|
79
83
|
import com.margelo.nitro.audiobrowser.Track
|
|
80
|
-
import com.margelo.nitro.audiobrowser.
|
|
84
|
+
import com.margelo.nitro.audiobrowser.TrackMetadata
|
|
81
85
|
import com.margelo.nitro.core.Promise
|
|
82
86
|
import java.util.concurrent.TimeUnit
|
|
83
87
|
import kotlin.coroutines.resume
|
|
@@ -95,6 +99,14 @@ import timber.log.Timber
|
|
|
95
99
|
@Keep
|
|
96
100
|
@DoNotStrip
|
|
97
101
|
class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
102
|
+
|
|
103
|
+
/** Called by Nitro when the JS object is destroyed (incl. JS runtime reloads). */
|
|
104
|
+
override fun dispose() {
|
|
105
|
+
systemVolumeMonitor.destroy()
|
|
106
|
+
outputMonitor.destroy()
|
|
107
|
+
super.dispose()
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
private val mainScope = MainScope()
|
|
99
111
|
private var navigationJob: Job? = null
|
|
100
112
|
private val handler = Handler(Looper.getMainLooper())
|
|
@@ -107,14 +119,18 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
107
119
|
NativeBrowserConfiguration(
|
|
108
120
|
path = null,
|
|
109
121
|
request = null,
|
|
122
|
+
requestResolver = null,
|
|
123
|
+
browse = null,
|
|
124
|
+
browseResolver = null,
|
|
110
125
|
media = null,
|
|
111
126
|
artwork = null,
|
|
127
|
+
nowPlayingArtwork = null,
|
|
112
128
|
routes = null,
|
|
113
129
|
singleTrack = null,
|
|
114
130
|
handleTrackLoad = null,
|
|
115
131
|
androidControllerOfflineError = null,
|
|
116
|
-
|
|
117
|
-
|
|
132
|
+
carPlayLoadingTitle = null,
|
|
133
|
+
resolveAlbumUrl = null,
|
|
118
134
|
formatNavigationError = null,
|
|
119
135
|
)
|
|
120
136
|
|
|
@@ -123,9 +139,11 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
123
139
|
setOnPathChanged { path -> onPathChanged(path) }
|
|
124
140
|
setOnContentChanged { content -> onContentChanged(content) }
|
|
125
141
|
setOnTabsChanged { tabs -> onTabsChanged(tabs) }
|
|
142
|
+
setOnArtworkRegistriesCleared { connectedService?.player?.browseArtworkRegistry?.clear() }
|
|
126
143
|
}
|
|
127
144
|
|
|
128
145
|
private val systemVolumeMonitor = SystemVolumeMonitor(context)
|
|
146
|
+
private val outputMonitor = OutputMonitor(context)
|
|
129
147
|
|
|
130
148
|
// MARK: Player state
|
|
131
149
|
private var updateOptions: PlayerUpdateOptions = PlayerUpdateOptions()
|
|
@@ -134,6 +152,11 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
134
152
|
private var connectedService: Service? = null
|
|
135
153
|
private var setupPromise: ((Unit) -> Unit)? = null
|
|
136
154
|
|
|
155
|
+
// Initial player state staged before the player exists — from setup options or the imperative
|
|
156
|
+
// setters called pre-bind. Strict last-write-wins; consumed when the player comes up.
|
|
157
|
+
private var pendingPlayWhenReady: Boolean? = null
|
|
158
|
+
private var pendingRepeatMode: RepeatMode? = null
|
|
159
|
+
|
|
137
160
|
/** Post callback to main handler for consistent async delivery to JS - avoids deadlocks */
|
|
138
161
|
private fun post(block: () -> Unit) = handler.post(block)
|
|
139
162
|
|
|
@@ -144,13 +167,21 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
144
167
|
override var onNavigationError: (NavigationErrorEvent) -> Unit = {}
|
|
145
168
|
override var onFormattedNavigationError: (FormattedNavigationError?) -> Unit = {}
|
|
146
169
|
|
|
170
|
+
// MARK: Gate callbacks (native→JS; set from JS, native CALLS them)
|
|
171
|
+
// Default resolver: only reachable in the init window where the native side has recorded
|
|
172
|
+
// hasResolver=true but JS hasn't yet assigned the real `resolveGate` slot. It DENIES by default
|
|
173
|
+
// (gated=true) so an active gate never serves content during that window — same fail-closed
|
|
174
|
+
// direction as the resolver-error path in [gateDecision]. The static-gate fast path skips it
|
|
175
|
+
// entirely once a resolver-less gate is set.
|
|
176
|
+
override var resolveGate: (request: NativeGateRequest) -> Promise<Promise<GateDecision>> = {
|
|
177
|
+
Promise.resolved(Promise.resolved(GateDecision(gated = true, gate = null)))
|
|
178
|
+
}
|
|
179
|
+
override var onGate: (event: GateEvent) -> Unit = {}
|
|
180
|
+
|
|
147
181
|
// MARK: Player callbacks
|
|
148
182
|
override var onPlaybackChanged: (data: Playback) -> Unit = {}
|
|
149
|
-
override var onRemoteBookmark: () -> Unit = {}
|
|
150
|
-
override var onRemoteDislike: () -> Unit = {}
|
|
151
183
|
override var onRemoteJumpBackward: (RemoteJumpBackwardEvent) -> Unit = {}
|
|
152
184
|
override var onRemoteJumpForward: (RemoteJumpForwardEvent) -> Unit = {}
|
|
153
|
-
override var onRemoteLike: () -> Unit = {}
|
|
154
185
|
override var onRemoteNext: () -> Unit = {}
|
|
155
186
|
override var onRemotePause: () -> Unit = {}
|
|
156
187
|
override var onChapterMetadata: (chapters: Array<ChapterMetadata>) -> Unit = {}
|
|
@@ -162,6 +193,7 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
162
193
|
{}
|
|
163
194
|
override var onPlaybackPlayingState: (data: PlayingState) -> Unit = {}
|
|
164
195
|
override var onPlaybackProgressUpdated: (data: PlaybackProgressUpdatedEvent) -> Unit = {}
|
|
196
|
+
override var onPlaybackInterval: () -> Unit = {}
|
|
165
197
|
override var onPlaybackQueueEnded: (data: PlaybackQueueEndedEvent) -> Unit = {}
|
|
166
198
|
override var onPlaybackQueueChanged: (queue: Array<Track>) -> Unit = {}
|
|
167
199
|
override var onPlaybackRepeatModeChanged: (data: RepeatModeChangedEvent) -> Unit = {}
|
|
@@ -171,7 +203,6 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
171
203
|
override var onRemotePlaySearch: (RemotePlaySearchEvent) -> Unit = {}
|
|
172
204
|
override var onRemotePrevious: () -> Unit = {}
|
|
173
205
|
override var onRemoteSeek: (RemoteSeekEvent) -> Unit = {}
|
|
174
|
-
override var onRemoteSetRating: (RemoteSetRatingEvent) -> Unit = {}
|
|
175
206
|
override var onRemoteSkip: (RemoteSkipEvent) -> Unit = {}
|
|
176
207
|
override var onRemoteStop: () -> Unit = {}
|
|
177
208
|
override var onOptionsChanged: (Options) -> Unit = {}
|
|
@@ -184,14 +215,11 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
184
215
|
override var onBatteryOptimizationStatusChanged: (BatteryOptimizationStatusChangedEvent) -> Unit =
|
|
185
216
|
{}
|
|
186
217
|
override var onSystemVolumeChanged: (Double) -> Unit = {}
|
|
187
|
-
override var
|
|
218
|
+
override var onOutputChanged: (Output) -> Unit = {}
|
|
188
219
|
|
|
189
220
|
// MARK: Remote handlers
|
|
190
|
-
override var handleRemoteBookmark: (() -> Unit)? = null
|
|
191
|
-
override var handleRemoteDislike: (() -> Unit)? = null
|
|
192
221
|
override var handleRemoteJumpBackward: ((RemoteJumpBackwardEvent) -> Unit)? = null
|
|
193
222
|
override var handleRemoteJumpForward: ((RemoteJumpForwardEvent) -> Unit)? = null
|
|
194
|
-
override var handleRemoteLike: (() -> Unit)? = null
|
|
195
223
|
override var handleRemoteNext: (() -> Unit)? = null
|
|
196
224
|
override var handleRemotePause: (() -> Unit)? = null
|
|
197
225
|
override var handleRemotePlay: (() -> Unit)? = null
|
|
@@ -232,9 +260,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
232
260
|
handler.post { ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleObserver) }
|
|
233
261
|
|
|
234
262
|
// Observe system volume changes
|
|
235
|
-
systemVolumeMonitor.setOnVolumeChanged { volume ->
|
|
236
|
-
|
|
237
|
-
|
|
263
|
+
systemVolumeMonitor.setOnVolumeChanged { volume -> post { onSystemVolumeChanged(volume) } }
|
|
264
|
+
|
|
265
|
+
// Observe current audio output changes (active media route via AudioManager)
|
|
266
|
+
outputMonitor.setOnOutputChanged { output -> post { onOutputChanged(output) } }
|
|
267
|
+
outputMonitor.start()
|
|
268
|
+
|
|
269
|
+
// Observe the car connection (Android Auto / Android Automotive)
|
|
270
|
+
startCarConnectionObserver(context, handler)
|
|
238
271
|
}
|
|
239
272
|
|
|
240
273
|
// ============================================================================
|
|
@@ -244,8 +277,12 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
244
277
|
internal fun buildConfig(): BrowserConfig {
|
|
245
278
|
return BrowserConfig(
|
|
246
279
|
request = _configuration.request,
|
|
280
|
+
requestResolver = _configuration.requestResolver,
|
|
281
|
+
browse = _configuration.browse,
|
|
282
|
+
browseResolver = _configuration.browseResolver,
|
|
247
283
|
media = _configuration.media,
|
|
248
284
|
artwork = _configuration.artwork,
|
|
285
|
+
nowPlayingArtwork = _configuration.nowPlayingArtwork,
|
|
249
286
|
routes = _configuration.routes,
|
|
250
287
|
singleTrack = _configuration.singleTrack ?: false,
|
|
251
288
|
androidControllerOfflineError = _configuration.androidControllerOfflineError ?: true,
|
|
@@ -253,34 +290,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
253
290
|
}
|
|
254
291
|
|
|
255
292
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
val artworkConfig = _configuration.artwork ?: return null
|
|
261
|
-
val baseConfig =
|
|
262
|
-
_configuration.request?.let { RequestConfigBuilder.toRequestConfig(it) }
|
|
263
|
-
?: RequestConfig(null, null, null, null, null, null, null, null)
|
|
264
|
-
return CoilBitmapLoader.ArtworkConfig(baseConfig, artworkConfig)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Creates a request config for media URL transformation by merging base and media configs.
|
|
269
|
-
* Returns null if no media configuration is set.
|
|
293
|
+
* Media URL transformation for [com.audiobrowser.player.TransformingDataSource]. Resolution lives
|
|
294
|
+
* in [resolveMediaUrl] (browser/BrowserUrlResolution.kt); this shell owns only the blocking
|
|
295
|
+
* bridge: it runs on ExoPlayer's IO thread (TransformingDataSource.open), so blocking here is
|
|
296
|
+
* safe and intentional.
|
|
270
297
|
*/
|
|
271
298
|
fun getMediaRequestConfig(originalUrl: String): MediaRequestConfig? {
|
|
272
|
-
val mediaConfig = _configuration.media ?: return null
|
|
273
|
-
|
|
274
299
|
return try {
|
|
275
|
-
|
|
276
|
-
val baseConfig =
|
|
277
|
-
_configuration.request?.let { RequestConfigBuilder.toRequestConfig(it) }
|
|
278
|
-
?: RequestConfig(null, null, null, null, null, null, null, null)
|
|
279
|
-
val urlRequestConfig = RequestConfig(null, originalUrl, null, null, null, null, null, null)
|
|
280
|
-
val mergedBaseConfig = RequestConfigBuilder.mergeConfig(baseConfig, urlRequestConfig)
|
|
281
|
-
|
|
282
|
-
// Apply media transformation
|
|
283
|
-
runBlocking { RequestConfigBuilder.mergeConfig(mergedBaseConfig, mediaConfig) }
|
|
300
|
+
runBlocking { browserManager.resolveMediaUrl(originalUrl) }
|
|
284
301
|
} catch (e: Exception) {
|
|
285
302
|
Timber.e(e, "Failed to transform media URL: $originalUrl")
|
|
286
303
|
null
|
|
@@ -292,10 +309,15 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
292
309
|
return _configuration.routes?.any { it.path != BrowserManager.SEARCH_ROUTE_PATH } == true
|
|
293
310
|
}
|
|
294
311
|
|
|
295
|
-
|
|
312
|
+
// Suspending on purpose: queryTabs() resolves tabs by invoking JS callbacks,
|
|
313
|
+
// which can only run on the JS thread. Callers MUST invoke this from a
|
|
314
|
+
// coroutine (off the JS thread) — never via runBlocking on a synchronous Nitro
|
|
315
|
+
// setter, which runs on the JS thread and would deadlock (the JS thread blocks
|
|
316
|
+
// waiting for callbacks that need that same thread to run).
|
|
317
|
+
private suspend fun getDefaultPath(): String? {
|
|
296
318
|
return try {
|
|
297
319
|
browserManager.config = buildConfig()
|
|
298
|
-
val tabs =
|
|
320
|
+
val tabs = browserManager.queryTabs()
|
|
299
321
|
if (tabs.isNotEmpty()) {
|
|
300
322
|
Timber.d("Using first tab as default path: ${tabs[0].url}")
|
|
301
323
|
tabs[0].url
|
|
@@ -303,6 +325,8 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
303
325
|
Timber.d("Using root path as default: /")
|
|
304
326
|
"/"
|
|
305
327
|
}
|
|
328
|
+
} catch (e: CancellationException) {
|
|
329
|
+
throw e // Rethrow so cooperative cancellation isn't swallowed
|
|
306
330
|
} catch (e: Exception) {
|
|
307
331
|
Timber.e(e, "Failed to get default path, falling back to /")
|
|
308
332
|
"/"
|
|
@@ -318,23 +342,25 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
318
342
|
set(value) {
|
|
319
343
|
if (hasValidConfiguration()) {
|
|
320
344
|
browserManager.config = buildConfig()
|
|
321
|
-
(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
345
|
+
clearNavigationError()
|
|
346
|
+
|
|
347
|
+
// Cancel previous navigation to avoid race conditions
|
|
348
|
+
navigationJob?.cancel()
|
|
349
|
+
|
|
350
|
+
// Resolve the default path inside the coroutine (getDefaultPath queries
|
|
351
|
+
// tabs via JS callbacks) so it never blocks the JS thread this setter
|
|
352
|
+
// runs on.
|
|
353
|
+
navigationJob =
|
|
354
|
+
mainScope.launch {
|
|
355
|
+
val path = value ?: getDefaultPath() ?: return@launch
|
|
356
|
+
try {
|
|
357
|
+
browserManager.navigate(path)
|
|
358
|
+
} catch (e: CancellationException) {
|
|
359
|
+
throw e // Rethrow to properly cancel
|
|
360
|
+
} catch (e: Exception) {
|
|
361
|
+
handleBrowserException(e, path, "setting path: $path")
|
|
336
362
|
}
|
|
337
|
-
|
|
363
|
+
}
|
|
338
364
|
}
|
|
339
365
|
}
|
|
340
366
|
|
|
@@ -352,45 +378,54 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
352
378
|
// This allows Android Auto to start browsing content
|
|
353
379
|
connectedService?.player?.notifyBrowserConfigurationReady()
|
|
354
380
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
381
|
+
clearNavigationError()
|
|
382
|
+
|
|
383
|
+
// Cancel previous navigation to avoid race conditions
|
|
384
|
+
navigationJob?.cancel()
|
|
385
|
+
|
|
386
|
+
// Navigate to the initial path, or default to the first tab. The default
|
|
387
|
+
// path is resolved inside the coroutine (getDefaultPath queries tabs via
|
|
388
|
+
// JS callbacks) so it never blocks the JS thread this setter runs on —
|
|
389
|
+
// doing it synchronously here via runBlocking deadlocked: the JS callbacks
|
|
390
|
+
// can't run because the JS thread is blocked waiting for them.
|
|
391
|
+
navigationJob =
|
|
392
|
+
mainScope.launch {
|
|
393
|
+
val path = value.path ?: getDefaultPath() ?: return@launch
|
|
394
|
+
try {
|
|
395
|
+
browserManager.navigate(path)
|
|
396
|
+
} catch (e: CancellationException) {
|
|
397
|
+
throw e // Rethrow to properly cancel
|
|
398
|
+
} catch (e: Exception) {
|
|
399
|
+
handleBrowserException(e, path, "setting configuration path: $path")
|
|
371
400
|
}
|
|
372
|
-
|
|
401
|
+
}
|
|
373
402
|
}
|
|
374
403
|
|
|
375
404
|
private var navigationError: NavigationError? = null
|
|
376
405
|
private var formattedNavigationError: FormattedNavigationError? = null
|
|
377
406
|
|
|
378
407
|
override fun getNavigationError(): NavigationError? = navigationError
|
|
408
|
+
|
|
379
409
|
override fun getFormattedNavigationError(): FormattedNavigationError? = formattedNavigationError
|
|
380
410
|
|
|
381
411
|
/** Creates a default formatted error from a NavigationError */
|
|
382
412
|
private fun defaultFormattedError(error: NavigationError): FormattedNavigationError {
|
|
383
|
-
val title =
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
413
|
+
val title =
|
|
414
|
+
when (error.code) {
|
|
415
|
+
NavigationErrorType.CONTENT_NOT_FOUND -> "Content Not Found"
|
|
416
|
+
NavigationErrorType.NETWORK_ERROR -> "Network Error"
|
|
417
|
+
NavigationErrorType.HTTP_ERROR -> {
|
|
418
|
+
// Use system-localized HTTP status text (e.g., "Not Found", "Service Unavailable")
|
|
419
|
+
error.statusCode?.let { httpStatusText(it.toInt()) } ?: "Server Error"
|
|
420
|
+
}
|
|
421
|
+
NavigationErrorType.CALLBACK_ERROR -> "Error"
|
|
422
|
+
NavigationErrorType.UNKNOWN_ERROR -> "Error"
|
|
423
|
+
// Not a failure — a container that resolved with no children. Neutral copy. See ADR 0001.
|
|
424
|
+
NavigationErrorType.EMPTY_CONTENT -> "Nothing here"
|
|
425
|
+
NavigationErrorType.TIMEOUT -> "Couldn't load"
|
|
389
426
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
}
|
|
393
|
-
return FormattedNavigationError(title, error.message)
|
|
427
|
+
// Omit an empty message so it renders as title-only (e.g. the empty-content case).
|
|
428
|
+
return FormattedNavigationError(title, error.message.takeIf { it.isNotEmpty() })
|
|
394
429
|
}
|
|
395
430
|
|
|
396
431
|
/** Returns localized HTTP status text for the given status code */
|
|
@@ -457,19 +492,35 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
457
492
|
}
|
|
458
493
|
is NetworkException -> {
|
|
459
494
|
Timber.e(e, "Network error $logContext")
|
|
460
|
-
setNavigationError(
|
|
495
|
+
setNavigationError(
|
|
496
|
+
NavigationErrorType.NETWORK_ERROR,
|
|
497
|
+
e.message ?: "Network request failed",
|
|
498
|
+
path,
|
|
499
|
+
)
|
|
461
500
|
}
|
|
462
501
|
is ContentNotFoundException -> {
|
|
463
502
|
Timber.e(e, "Content not found $logContext")
|
|
464
|
-
setNavigationError(
|
|
503
|
+
setNavigationError(
|
|
504
|
+
NavigationErrorType.CONTENT_NOT_FOUND,
|
|
505
|
+
e.message ?: "Content not found",
|
|
506
|
+
path,
|
|
507
|
+
)
|
|
465
508
|
}
|
|
466
509
|
is CallbackException -> {
|
|
467
510
|
Timber.e(e, "Callback error $logContext")
|
|
468
|
-
setNavigationError(
|
|
511
|
+
setNavigationError(
|
|
512
|
+
NavigationErrorType.CALLBACK_ERROR,
|
|
513
|
+
e.message ?: "An error occurred",
|
|
514
|
+
path,
|
|
515
|
+
)
|
|
469
516
|
}
|
|
470
517
|
else -> {
|
|
471
518
|
Timber.e(e, "Unexpected error $logContext")
|
|
472
|
-
setNavigationError(
|
|
519
|
+
setNavigationError(
|
|
520
|
+
NavigationErrorType.UNKNOWN_ERROR,
|
|
521
|
+
e.message ?: "An unexpected error occurred",
|
|
522
|
+
path,
|
|
523
|
+
)
|
|
473
524
|
}
|
|
474
525
|
}
|
|
475
526
|
}
|
|
@@ -529,10 +580,17 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
529
580
|
val index = player.tracks.indexOfFirst { it.src == trackId }
|
|
530
581
|
if (index >= 0) {
|
|
531
582
|
Timber.d("Queue already from $parentPath, skipping to index $index")
|
|
532
|
-
handleTrackLoad(
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
583
|
+
handleTrackLoad(
|
|
584
|
+
_configuration.handleTrackLoad,
|
|
585
|
+
track,
|
|
586
|
+
player.tracks,
|
|
587
|
+
index.toDouble(),
|
|
588
|
+
intercepted = {},
|
|
589
|
+
defaultBehavior = {
|
|
590
|
+
player.skipTo(index)
|
|
591
|
+
player.play()
|
|
592
|
+
},
|
|
593
|
+
)
|
|
536
594
|
return@launch
|
|
537
595
|
}
|
|
538
596
|
}
|
|
@@ -545,17 +603,31 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
545
603
|
Timber.d(
|
|
546
604
|
"Loading expanded queue: ${tracks.size} tracks, starting at index $startIndex"
|
|
547
605
|
)
|
|
548
|
-
handleTrackLoad(
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
606
|
+
handleTrackLoad(
|
|
607
|
+
_configuration.handleTrackLoad,
|
|
608
|
+
track,
|
|
609
|
+
tracks,
|
|
610
|
+
startIndex.toDouble(),
|
|
611
|
+
intercepted = {},
|
|
612
|
+
defaultBehavior = {
|
|
613
|
+
// Replace queue and seek to selected track
|
|
614
|
+
// Use internal player methods directly to avoid blocking on main thread
|
|
615
|
+
player.setQueue(tracks, startIndex, sourcePath = parentPath)
|
|
616
|
+
player.play()
|
|
617
|
+
},
|
|
618
|
+
)
|
|
554
619
|
return@launch
|
|
555
620
|
} else {
|
|
556
621
|
// Fallback: just load the single track
|
|
557
622
|
Timber.w("Queue expansion failed, loading single track")
|
|
558
|
-
handleTrackLoad(
|
|
623
|
+
handleTrackLoad(
|
|
624
|
+
_configuration.handleTrackLoad,
|
|
625
|
+
track,
|
|
626
|
+
arrayOf(track),
|
|
627
|
+
0.0,
|
|
628
|
+
intercepted = {},
|
|
629
|
+
defaultBehavior = { player.load(track) },
|
|
630
|
+
)
|
|
559
631
|
}
|
|
560
632
|
}
|
|
561
633
|
// Navigate to browsable track to show browsing UI
|
|
@@ -566,7 +638,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
566
638
|
// If track is playable (has src), load it into player
|
|
567
639
|
track.src != null -> {
|
|
568
640
|
Timber.d("Loading playable track into player: ${track.title}")
|
|
569
|
-
handleTrackLoad(
|
|
641
|
+
handleTrackLoad(
|
|
642
|
+
_configuration.handleTrackLoad,
|
|
643
|
+
track,
|
|
644
|
+
arrayOf(track),
|
|
645
|
+
0.0,
|
|
646
|
+
intercepted = {},
|
|
647
|
+
defaultBehavior = { player.load(track) },
|
|
648
|
+
)
|
|
570
649
|
}
|
|
571
650
|
else -> {
|
|
572
651
|
throw IllegalArgumentException("Track must have either an 'url' or an 'src' property")
|
|
@@ -607,20 +686,125 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
607
686
|
}
|
|
608
687
|
}
|
|
609
688
|
|
|
689
|
+
override fun invalidateAllContent() {
|
|
690
|
+
Timber.d("Invalidating all content")
|
|
691
|
+
|
|
692
|
+
// Clear all cached content so every path re-fetches fresh data
|
|
693
|
+
browserManager.clearContentCache()
|
|
694
|
+
|
|
695
|
+
// Notify external media controllers (Android Auto) to refresh subscribed paths
|
|
696
|
+
connectedService?.player?.invalidateAllContent()
|
|
697
|
+
|
|
698
|
+
// Refresh whatever the browser is currently viewing
|
|
699
|
+
mainScope.launch { browserManager.refresh() }
|
|
700
|
+
}
|
|
701
|
+
|
|
610
702
|
override fun setFavorites(favorites: Array<String>) {
|
|
611
703
|
browserManager.setFavorites(favorites.toList())
|
|
612
704
|
}
|
|
613
705
|
|
|
706
|
+
// MARK: Gate
|
|
707
|
+
|
|
708
|
+
/** A gate decision for one request: whether to gate, and which chrome to render. */
|
|
709
|
+
data class GateOutcome(val gated: Boolean, val chrome: Gate?)
|
|
710
|
+
|
|
711
|
+
// The minimal chrome rendered when a gate is active but no override or stored
|
|
712
|
+
// default chrome exists (the resolver-only setGate overload).
|
|
713
|
+
private val builtInGate = Gate("Unavailable", null)
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* The three gate fields as one immutable triple so [gateDecision] reads them as a unit. Written
|
|
717
|
+
* from the JS thread, read from the Media3 application thread (the enforcement sites in
|
|
718
|
+
* MediaSessionCallback consult it) — hence the single field is @Volatile.
|
|
719
|
+
*
|
|
720
|
+
* Folding the three former @Volatile fields into one reference is what makes the read atomic:
|
|
721
|
+
*
|
|
722
|
+
* @Volatile gives per-field visibility but NO atomicity across a compound read, so reading three
|
|
723
|
+
* separate volatiles in [gateDecision] could interleave with a concurrent [clearGate] and yield
|
|
724
|
+
* a torn `(active=true, chrome=null)` state that crashed the force-unwrap at the serve sites.
|
|
725
|
+
* One volatile reference read once cannot tear.
|
|
726
|
+
*/
|
|
727
|
+
private data class GateState(val active: Boolean, val chrome: Gate?, val hasResolver: Boolean)
|
|
728
|
+
|
|
729
|
+
@Volatile private var gateState = GateState(active = false, chrome = null, hasResolver = false)
|
|
730
|
+
|
|
731
|
+
override fun setGate(gate: Gate?, hasResolver: Boolean) {
|
|
732
|
+
// Single atomic assignment — readers never see a half-updated triple.
|
|
733
|
+
gateState = GateState(active = true, chrome = gate, hasResolver = hasResolver)
|
|
734
|
+
// Re-query every subscribed parent so a connected controller (Android
|
|
735
|
+
// Auto) swaps its lists for the gate tile without reconnecting. Notify
|
|
736
|
+
// only — the content cache stays warm for when the gate clears.
|
|
737
|
+
connectedService?.player?.invalidateAllContent()
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
override fun clearGate() {
|
|
741
|
+
if (!gateState.active) return
|
|
742
|
+
// Single atomic assignment — readers never see a half-cleared triple.
|
|
743
|
+
gateState = GateState(active = false, chrome = null, hasResolver = false)
|
|
744
|
+
connectedService?.player?.invalidateAllContent()
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* The single gate choke point. Each enforcement site (browse / search) calls this for the current
|
|
749
|
+
* request and serves the gate chrome when [GateOutcome.gated] is true. Structurally similar to
|
|
750
|
+
* the iOS `gateDecision(for:)` helper, but note the concurrency model differs: iOS confines gate
|
|
751
|
+
* state to `@MainActor`; here the consistent read comes from snapshotting the single [gateState]
|
|
752
|
+
* reference once (see [GateState]).
|
|
753
|
+
* - No active gate → allow.
|
|
754
|
+
* - Active gate, no resolver → static fast path: gate with the stored default chrome (or built-in
|
|
755
|
+
* if none), no JS hop.
|
|
756
|
+
* - Active gate with a resolver → ask JS per request. A resolver that throws / rejects / times
|
|
757
|
+
* out FAILS CLOSED by design: while a gate is active the consumer has declared content blocked,
|
|
758
|
+
* so the only safe fallback when we cannot compute the per-request decision is the gate's own
|
|
759
|
+
* chrome — never the content. A *successful* `gated:false` still allows. Chrome order on a
|
|
760
|
+
* gated decision: override → stored default → built-in.
|
|
761
|
+
*
|
|
762
|
+
* Every gated return guards chrome against null (`?: builtInGate`) so a gated outcome always
|
|
763
|
+
* carries a renderable chrome — the serve sites force-unwrap it.
|
|
764
|
+
*/
|
|
765
|
+
suspend fun gateDecision(request: NativeGateRequest): GateOutcome {
|
|
766
|
+
// Read the whole gate triple once; a single volatile reference can't tear (see [GateState]).
|
|
767
|
+
val s = gateState
|
|
768
|
+
if (!s.active) return GateOutcome(false, null)
|
|
769
|
+
if (!s.hasResolver) return GateOutcome(true, s.chrome ?: builtInGate) // static fast path
|
|
770
|
+
val decision =
|
|
771
|
+
runCatching { resolveGate(request).await().await() }.getOrNull()
|
|
772
|
+
?: return GateOutcome(true, s.chrome ?: builtInGate) // fail CLOSED on resolver error
|
|
773
|
+
if (!decision.gated) return GateOutcome(false, null) // explicit allow
|
|
774
|
+
return GateOutcome(true, decision.gate ?: s.chrome ?: builtInGate)
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// MARK: Car connection (Android Auto / Android Automotive)
|
|
778
|
+
|
|
779
|
+
override fun isCarConnected(): Boolean = carConnected
|
|
780
|
+
|
|
781
|
+
override var onCarConnectedChanged: (Boolean) -> Unit = {}
|
|
782
|
+
set(value) {
|
|
783
|
+
field = value
|
|
784
|
+
carConnectionTarget = value
|
|
785
|
+
// Immediately notify current state (the car may have connected before
|
|
786
|
+
// this JS runtime subscribed) — mirrors the iOS behavior.
|
|
787
|
+
value(carConnected)
|
|
788
|
+
}
|
|
789
|
+
|
|
614
790
|
// ============================================================================
|
|
615
791
|
// MARK: Player Setup and Options
|
|
616
792
|
// ============================================================================
|
|
617
793
|
|
|
618
|
-
override fun setupPlayer(options:
|
|
794
|
+
override fun setupPlayer(options: NativeSetupPlayerOptions): Promise<Unit> {
|
|
619
795
|
return Promise.async(mainScope) {
|
|
620
796
|
setupOptions.update(options)
|
|
797
|
+
// The bundled runtime options and initial state are part of the atomic launch
|
|
798
|
+
// description: stage them here, apply them together with the engine below (or at
|
|
799
|
+
// service connect). Last-write-wins with their imperative counterparts.
|
|
800
|
+
options.options?.let { updateOptions.updateFromBridge(it) }
|
|
801
|
+
options.repeatMode?.let { pendingRepeatMode = it }
|
|
802
|
+
options.playWhenReady?.let { pendingPlayWhenReady = it }
|
|
621
803
|
|
|
622
804
|
connectedService?.let {
|
|
805
|
+
it.player.applyOptions(updateOptions)
|
|
623
806
|
it.player.setup(setupOptions)
|
|
807
|
+
applyPendingPlayerState(it.player)
|
|
624
808
|
return@async
|
|
625
809
|
}
|
|
626
810
|
|
|
@@ -652,8 +836,10 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
652
836
|
connectedService?.let { player.applyOptions(updateOptions) }
|
|
653
837
|
}
|
|
654
838
|
|
|
655
|
-
override fun getOptions():
|
|
656
|
-
|
|
839
|
+
override fun getOptions(): Options {
|
|
840
|
+
// The holder is the source of truth whether or not the player exists yet — updateOptions
|
|
841
|
+
// merges into it and setup/connect applies it to the player.
|
|
842
|
+
return updateOptions.toNitro()
|
|
657
843
|
}
|
|
658
844
|
|
|
659
845
|
// ============================================================================
|
|
@@ -668,6 +854,9 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
668
854
|
player.stop()
|
|
669
855
|
delay(300) // Allow playback to stop
|
|
670
856
|
player.clear()
|
|
857
|
+
// clear() while IDLE emits no engine event, so the state machine never
|
|
858
|
+
// leaves STOPPED — a reset queue is "nothing loaded".
|
|
859
|
+
player.setPlaybackState(PlaybackState.NONE)
|
|
671
860
|
}
|
|
672
861
|
|
|
673
862
|
override fun play() = runBlockingOnMain { player.play() }
|
|
@@ -679,10 +868,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
679
868
|
override fun stop() = runBlockingOnMain { player.stop() }
|
|
680
869
|
|
|
681
870
|
override fun setPlayWhenReady(playWhenReady: Boolean) = runBlockingOnMain {
|
|
682
|
-
player
|
|
871
|
+
// Pre-setup this stages the intent for the player to come up with — never throws.
|
|
872
|
+
connectedService?.player?.let { it.playWhenReady = playWhenReady }
|
|
873
|
+
?: run { pendingPlayWhenReady = playWhenReady }
|
|
683
874
|
}
|
|
684
875
|
|
|
685
|
-
override fun getPlayWhenReady(): Boolean = runBlockingOnMain {
|
|
876
|
+
override fun getPlayWhenReady(): Boolean = runBlockingOnMain {
|
|
877
|
+
connectedService?.player?.playWhenReady ?: pendingPlayWhenReady ?: false
|
|
878
|
+
}
|
|
686
879
|
|
|
687
880
|
override fun seekTo(position: Double) = runBlockingOnMain {
|
|
688
881
|
player.seekTo((position * 1000).toLong(), TimeUnit.MILLISECONDS)
|
|
@@ -692,6 +885,8 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
692
885
|
player.seekBy((offset * 1000).toLong(), TimeUnit.MILLISECONDS)
|
|
693
886
|
}
|
|
694
887
|
|
|
888
|
+
override fun seekToLiveEdge() = runBlockingOnMain { player.seekToLiveEdge() }
|
|
889
|
+
|
|
695
890
|
override fun setVolume(level: Double) = runBlockingOnMain { player.volume = level.toFloat() }
|
|
696
891
|
|
|
697
892
|
override fun getVolume(): Double = runBlockingOnMain { player.volume.toDouble() }
|
|
@@ -712,9 +907,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
712
907
|
|
|
713
908
|
override fun getPlayingState(): PlayingState = runBlockingOnMain { player.getPlayingState() }
|
|
714
909
|
|
|
715
|
-
override fun getRepeatMode(): RepeatMode = runBlockingOnMain {
|
|
910
|
+
override fun getRepeatMode(): RepeatMode = runBlockingOnMain {
|
|
911
|
+
connectedService?.player?.repeatMode ?: pendingRepeatMode ?: RepeatMode.OFF
|
|
912
|
+
}
|
|
716
913
|
|
|
717
|
-
override fun setRepeatMode(mode: RepeatMode) = runBlockingOnMain {
|
|
914
|
+
override fun setRepeatMode(mode: RepeatMode) = runBlockingOnMain {
|
|
915
|
+
// Pre-setup this stages the mode for the player to come up with — never throws.
|
|
916
|
+
connectedService?.player?.let { it.repeatMode = mode } ?: run { pendingRepeatMode = mode }
|
|
917
|
+
}
|
|
718
918
|
|
|
719
919
|
override fun getShuffleEnabled(): Boolean = runBlockingOnMain { player.shuffleMode }
|
|
720
920
|
|
|
@@ -722,6 +922,10 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
722
922
|
player.shuffleMode = enabled
|
|
723
923
|
}
|
|
724
924
|
|
|
925
|
+
override fun setPlaybackIntervalEnabled(enabled: Boolean) = runBlockingOnMain {
|
|
926
|
+
player.setPlaybackIntervalEnabled(enabled)
|
|
927
|
+
}
|
|
928
|
+
|
|
725
929
|
override fun getPlaybackError(): PlaybackError? = runBlockingOnMain { player.playbackError }
|
|
726
930
|
|
|
727
931
|
override fun retry() = runBlockingOnMain { player.prepare() }
|
|
@@ -770,9 +974,9 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
770
974
|
}
|
|
771
975
|
}
|
|
772
976
|
|
|
773
|
-
override fun setQueue(tracks: Array<Track>, startIndex: Double?,
|
|
977
|
+
override fun setQueue(tracks: Array<Track>, startIndex: Double?, startPosition: Double?) =
|
|
774
978
|
runBlockingOnMain {
|
|
775
|
-
player.setQueue(tracks, startIndex?.toInt() ?: 0,
|
|
979
|
+
player.setQueue(tracks, startIndex?.toInt() ?: 0, ((startPosition ?: 0.0) * 1000).toLong())
|
|
776
980
|
}
|
|
777
981
|
|
|
778
982
|
override fun setActiveTrackFavorited(favorited: Boolean) = runBlockingOnMain {
|
|
@@ -804,10 +1008,20 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
804
1008
|
// ============================================================================
|
|
805
1009
|
|
|
806
1010
|
override fun updateNowPlaying(update: NowPlayingUpdate?) = runBlockingOnMain {
|
|
807
|
-
player.updateNowPlaying(update)
|
|
1011
|
+
player.nowPlaying.updateNowPlaying(update)
|
|
808
1012
|
}
|
|
809
1013
|
|
|
810
|
-
override fun
|
|
1014
|
+
override fun flashNowPlaying(update: NowPlayingUpdate, durationMs: Double) = runBlockingOnMain {
|
|
1015
|
+
player.nowPlaying.flashNowPlaying(update, durationMs)
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
override fun clearNowPlayingFlash() = runBlockingOnMain {
|
|
1019
|
+
player.nowPlaying.clearNowPlayingFlash()
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
override fun getNowPlaying(): NowPlayingMetadata? = runBlockingOnMain {
|
|
1023
|
+
player.nowPlaying.getNowPlaying()
|
|
1024
|
+
}
|
|
811
1025
|
|
|
812
1026
|
// ============================================================================
|
|
813
1027
|
// MARK: Network Connectivity
|
|
@@ -824,13 +1038,15 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
824
1038
|
override fun setSystemVolume(volume: Double) = systemVolumeMonitor.setVolume(volume)
|
|
825
1039
|
|
|
826
1040
|
// ============================================================================
|
|
827
|
-
// MARK: External Audio Output
|
|
1041
|
+
// MARK: External Audio Output
|
|
828
1042
|
// ============================================================================
|
|
829
1043
|
|
|
830
|
-
override fun
|
|
1044
|
+
override fun getOutput(): Output? = outputMonitor.current
|
|
1045
|
+
|
|
1046
|
+
override fun supportsOutputSwitcher(): Boolean = OutputSwitcher.isSupported()
|
|
831
1047
|
|
|
832
|
-
override fun
|
|
833
|
-
|
|
1048
|
+
override fun openOutputPicker() {
|
|
1049
|
+
OutputSwitcher.open(context)
|
|
834
1050
|
}
|
|
835
1051
|
|
|
836
1052
|
// ============================================================================
|
|
@@ -838,34 +1054,34 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
838
1054
|
// ============================================================================
|
|
839
1055
|
|
|
840
1056
|
override fun getEqualizerSettings(): EqualizerSettings? = runBlockingOnMain {
|
|
841
|
-
player.
|
|
1057
|
+
player.equalizer.getSettings()
|
|
842
1058
|
}
|
|
843
1059
|
|
|
844
1060
|
override fun setEqualizerEnabled(enabled: Boolean) = runBlockingOnMain {
|
|
845
|
-
player.
|
|
1061
|
+
player.equalizer.setEnabled(enabled)
|
|
846
1062
|
}
|
|
847
1063
|
|
|
848
1064
|
override fun setEqualizerPreset(preset: String) = runBlockingOnMain {
|
|
849
|
-
player.
|
|
1065
|
+
player.equalizer.setPreset(preset)
|
|
850
1066
|
}
|
|
851
1067
|
|
|
852
1068
|
override fun setEqualizerLevels(levels: DoubleArray) = runBlockingOnMain {
|
|
853
|
-
player.
|
|
1069
|
+
player.equalizer.setLevels(levels)
|
|
854
1070
|
}
|
|
855
1071
|
|
|
856
1072
|
// ============================================================================
|
|
857
1073
|
// MARK: Sleep Timer
|
|
858
1074
|
// ============================================================================
|
|
859
1075
|
|
|
860
|
-
override fun getSleepTimer(): SleepTimer = runBlockingOnMain { player.
|
|
1076
|
+
override fun getSleepTimer(): SleepTimer = runBlockingOnMain { player.sleepTimer.get() }
|
|
861
1077
|
|
|
862
|
-
override fun setSleepTimer(seconds: Double) = runBlockingOnMain {
|
|
863
|
-
|
|
864
|
-
override fun setSleepTimerToEndOfTrack() = runBlockingOnMain {
|
|
865
|
-
player.setSleepTimerToEndOfTrack()
|
|
1078
|
+
override fun setSleepTimer(seconds: Double, fadeDuration: Double?) = runBlockingOnMain {
|
|
1079
|
+
player.sleepTimer.setAfter(seconds, fadeDuration)
|
|
866
1080
|
}
|
|
867
1081
|
|
|
868
|
-
override fun
|
|
1082
|
+
override fun setSleepTimerToEndOfTrack() = runBlockingOnMain { player.sleepTimer.setEndOfTrack() }
|
|
1083
|
+
|
|
1084
|
+
override fun clearSleepTimer(): Boolean = runBlockingOnMain { player.sleepTimer.clear() }
|
|
869
1085
|
|
|
870
1086
|
// ============================================================================
|
|
871
1087
|
// MARK: Battery Optimization (Android only)
|
|
@@ -945,6 +1161,7 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
945
1161
|
player.setCallbacks(callbacks)
|
|
946
1162
|
player.applyOptions(updateOptions)
|
|
947
1163
|
player.setup(setupOptions)
|
|
1164
|
+
applyPendingPlayerState(player)
|
|
948
1165
|
// Start observing network connectivity changes
|
|
949
1166
|
player.observeNetworkConnectivity(mainScope)
|
|
950
1167
|
// Set browser reference for media URL transformation
|
|
@@ -974,6 +1191,21 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
974
1191
|
}
|
|
975
1192
|
}
|
|
976
1193
|
|
|
1194
|
+
/**
|
|
1195
|
+
* Applies initial player state staged before the player existed. Consumed on apply so a later
|
|
1196
|
+
* re-setup doesn't replay stale state.
|
|
1197
|
+
*/
|
|
1198
|
+
private fun applyPendingPlayerState(player: Player) {
|
|
1199
|
+
pendingRepeatMode?.let {
|
|
1200
|
+
player.repeatMode = it
|
|
1201
|
+
pendingRepeatMode = null
|
|
1202
|
+
}
|
|
1203
|
+
pendingPlayWhenReady?.let {
|
|
1204
|
+
player.playWhenReady = it
|
|
1205
|
+
pendingPlayWhenReady = null
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
|
|
977
1209
|
override fun onServiceDisconnected(name: ComponentName) {
|
|
978
1210
|
mainScope.coroutineContext.cancelChildren()
|
|
979
1211
|
mediaBrowserFuture = null
|
|
@@ -1017,6 +1249,10 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1017
1249
|
post { this@AudioBrowser.onPlaybackProgressUpdated(event) }
|
|
1018
1250
|
}
|
|
1019
1251
|
|
|
1252
|
+
override fun onPlaybackInterval() {
|
|
1253
|
+
post { this@AudioBrowser.onPlaybackInterval() }
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1020
1256
|
override fun onPlaybackPlayWhenReadyChanged(event: PlaybackPlayWhenReadyChangedEvent) {
|
|
1021
1257
|
post { this@AudioBrowser.onPlaybackPlayWhenReadyChanged(event) }
|
|
1022
1258
|
}
|
|
@@ -1166,12 +1402,8 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1166
1402
|
return handled
|
|
1167
1403
|
}
|
|
1168
1404
|
|
|
1169
|
-
override fun onRemoteSetRating(event: RemoteSetRatingEvent) {
|
|
1170
|
-
post { this@AudioBrowser.onRemoteSetRating(event) }
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
1405
|
override fun onOptionsChanged(options: PlayerUpdateOptions) {
|
|
1174
|
-
|
|
1406
|
+
post { this@AudioBrowser.onOptionsChanged(options.toNitro()) }
|
|
1175
1407
|
}
|
|
1176
1408
|
|
|
1177
1409
|
override fun onFavoriteChanged(event: FavoriteChangedEvent) {
|
|
@@ -1194,4 +1426,32 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1194
1426
|
post { this@AudioBrowser.onSleepTimerChanged(timer) }
|
|
1195
1427
|
}
|
|
1196
1428
|
}
|
|
1429
|
+
|
|
1430
|
+
companion object {
|
|
1431
|
+
// Process-wide car-connection state, from the androidx.car.app
|
|
1432
|
+
// CarConnection provider — the documented Android Auto / Automotive
|
|
1433
|
+
// connection signal, served by the car system app. Observed ONCE per
|
|
1434
|
+
// process: AudioBrowser instances are re-created on a JS reload, and a
|
|
1435
|
+
// per-instance observeForever would leak each one. The latest instance's
|
|
1436
|
+
// callback registers as the single notification target (mirrors the iOS
|
|
1437
|
+
// static + shared-instance pattern).
|
|
1438
|
+
@Volatile private var carConnected = false
|
|
1439
|
+
@Volatile private var carConnectionTarget: ((Boolean) -> Unit)? = null
|
|
1440
|
+
private var carConnectionObserverStarted = false
|
|
1441
|
+
|
|
1442
|
+
private fun startCarConnectionObserver(context: Context, handler: Handler) {
|
|
1443
|
+
// Posted to main: LiveData observation is main-thread only, and the
|
|
1444
|
+
// single-start guard is then only ever touched from one thread.
|
|
1445
|
+
handler.post {
|
|
1446
|
+
if (carConnectionObserverStarted) return@post
|
|
1447
|
+
carConnectionObserverStarted = true
|
|
1448
|
+
CarConnection(context.applicationContext).type.observeForever { type ->
|
|
1449
|
+
val connected = type != CarConnection.CONNECTION_TYPE_NOT_CONNECTED
|
|
1450
|
+
if (connected == carConnected) return@observeForever
|
|
1451
|
+
carConnected = connected
|
|
1452
|
+
carConnectionTarget?.invoke(connected)
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1197
1457
|
}
|