react-native-audio-browser 0.1.0 → 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 -34
- 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 +42 -10
- 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 +16 -16
- 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 +368 -157
- package/src/web/SimpleRouter.test.ts +9 -9
- 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
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
package com.audiobrowser.player
|
|
2
2
|
|
|
3
3
|
import androidx.media3.common.C
|
|
4
|
-
import androidx.media3.common.
|
|
4
|
+
import androidx.media3.common.ParserException
|
|
5
|
+
import androidx.media3.datasource.DataSourceException
|
|
5
6
|
import androidx.media3.datasource.HttpDataSource
|
|
6
7
|
import androidx.media3.exoplayer.upstream.DefaultLoadErrorHandlingPolicy
|
|
7
8
|
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy
|
|
9
|
+
import androidx.media3.exoplayer.upstream.Loader
|
|
10
|
+
import java.io.FileNotFoundException
|
|
11
|
+
import java.io.IOException
|
|
8
12
|
import kotlin.math.min
|
|
9
13
|
import kotlin.math.pow
|
|
10
14
|
import timber.log.Timber
|
|
@@ -16,19 +20,37 @@ import timber.log.Timber
|
|
|
16
20
|
* will use a shorter retry delay and the network restoration callback can trigger an immediate
|
|
17
21
|
* retry when connectivity is restored.
|
|
18
22
|
*
|
|
23
|
+
* Two duration budgets apply, chosen by whether the current load has ever produced audio
|
|
24
|
+
* ([hasPlayed]): a short first-connect budget — a stream that fails before ever playing is usually
|
|
25
|
+
* dead, and the listener is actively waiting for a verdict — and the full recovery budget for a
|
|
26
|
+
* stream that played and then dropped (tunnels, handovers, encoder restarts). The short budget
|
|
27
|
+
* counts only online time, so a station tapped in a tunnel still gets its online seconds once
|
|
28
|
+
* connectivity returns. Both budgets are enforced here at the policy level, never via ExoPlayer's
|
|
29
|
+
* [LoadErrorHandlingPolicy.LoadErrorInfo.errorCount] — that counts per *loadable* (an HLS stream
|
|
30
|
+
* has playlist and segment loadables, each with its own count), so it cannot express a per-load
|
|
31
|
+
* promise.
|
|
32
|
+
*
|
|
19
33
|
* @param maxRetries Maximum number of retries, or null for infinite retries
|
|
20
|
-
* @param maxRetryDurationMs Maximum duration to keep retrying before giving up, or null for default
|
|
34
|
+
* @param maxRetryDurationMs Maximum duration to keep retrying before giving up, or null for default
|
|
35
|
+
* (2 minutes)
|
|
36
|
+
* @param firstConnectMaxRetryDurationMs Maximum duration to keep retrying a load that has never
|
|
37
|
+
* produced audio, while online, or null for default (12 seconds)
|
|
21
38
|
* @param shouldRetry Optional callback to check if retry should proceed (e.g., check playWhenReady)
|
|
22
39
|
* @param isOnline Optional callback to check current network state
|
|
23
|
-
* @param
|
|
24
|
-
*
|
|
40
|
+
* @param hasPlayed Optional callback: whether the current load has produced audio. Must be safe to
|
|
41
|
+
* call from ExoPlayer's loader thread (e.g. backed by a volatile cache).
|
|
42
|
+
* @param onRetryPending Optional callback invoked when a retry is pending, with the load error
|
|
43
|
+
* being retried (for surfacing it while the retry runs, and for network restoration
|
|
44
|
+
* acceleration). Invoked on ExoPlayer's loader thread.
|
|
25
45
|
*/
|
|
26
46
|
class RetryLoadErrorHandlingPolicy(
|
|
27
47
|
private val maxRetries: Int? = null,
|
|
28
48
|
maxRetryDurationMs: Long? = null,
|
|
49
|
+
firstConnectMaxRetryDurationMs: Long? = null,
|
|
29
50
|
private val shouldRetry: () -> Boolean = { true },
|
|
30
51
|
private val isOnline: () -> Boolean = { true },
|
|
31
|
-
private val
|
|
52
|
+
private val hasPlayed: () -> Boolean = { false },
|
|
53
|
+
private val onRetryPending: ((exception: IOException, isNetworkError: Boolean) -> Unit)? = null,
|
|
32
54
|
) : DefaultLoadErrorHandlingPolicy() {
|
|
33
55
|
|
|
34
56
|
companion object {
|
|
@@ -42,6 +64,8 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
42
64
|
private const val OFFLINE_RETRY_DELAY_MS = 1000L
|
|
43
65
|
// Default maximum duration to keep retrying before giving up (in milliseconds).
|
|
44
66
|
private const val DEFAULT_MAX_RETRY_DURATION_MS = 120_000L // 2 minutes
|
|
67
|
+
// Default maximum duration for a load that has never produced audio, while online.
|
|
68
|
+
private const val DEFAULT_FIRST_CONNECT_MAX_RETRY_DURATION_MS = 12_000L
|
|
45
69
|
|
|
46
70
|
// HTTP status codes that are worth retrying
|
|
47
71
|
private val RETRYABLE_HTTP_STATUS_CODES =
|
|
@@ -59,13 +83,40 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
59
83
|
// This prevents surprising playback resumption after long periods offline.
|
|
60
84
|
private val maxRetryDurationMs: Long = maxRetryDurationMs ?: DEFAULT_MAX_RETRY_DURATION_MS
|
|
61
85
|
|
|
86
|
+
private val firstConnectMaxRetryDurationMs: Long =
|
|
87
|
+
firstConnectMaxRetryDurationMs ?: DEFAULT_FIRST_CONNECT_MAX_RETRY_DURATION_MS
|
|
88
|
+
|
|
62
89
|
// Track when we started retrying to enforce max duration
|
|
63
|
-
@Volatile
|
|
64
|
-
|
|
90
|
+
@Volatile private var firstErrorTime: Long? = null
|
|
91
|
+
|
|
92
|
+
// First error observed while online — the first-connect budget's clock. Never set while
|
|
93
|
+
// offline, and wiped by any offline observation, so an offline stretch cannot burn the short
|
|
94
|
+
// budget: the clock restarts at the next error observed online.
|
|
95
|
+
@Volatile private var firstOnlineErrorTime: Long? = null
|
|
65
96
|
|
|
66
97
|
/** Resets the retry timer. Call when track changes. */
|
|
67
98
|
fun reset() {
|
|
68
99
|
firstErrorTime = null
|
|
100
|
+
firstOnlineErrorTime = null
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The name of the exhausted budget, or null while budget remains. The recovery duration bounds
|
|
105
|
+
* everything (including offline waits); the first-connect duration additionally bounds
|
|
106
|
+
* never-played loads, online only.
|
|
107
|
+
*/
|
|
108
|
+
private fun exhaustedBudget(currentTime: Long): String? {
|
|
109
|
+
firstErrorTime?.let { start ->
|
|
110
|
+
if (currentTime - start >= maxRetryDurationMs) return "max retry duration ($maxRetryDurationMs ms)"
|
|
111
|
+
}
|
|
112
|
+
if (!hasPlayed() && isOnline()) {
|
|
113
|
+
firstOnlineErrorTime?.let { start ->
|
|
114
|
+
if (currentTime - start >= firstConnectMaxRetryDurationMs) {
|
|
115
|
+
return "first-connect retry duration ($firstConnectMaxRetryDurationMs ms)"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null
|
|
69
120
|
}
|
|
70
121
|
|
|
71
122
|
/** Calculates exponential backoff delay: 1s -> 1.5s -> 2.3s -> 3.4s -> 5s (capped) */
|
|
@@ -76,22 +127,6 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
76
127
|
return min(exponentialDelay.toLong(), MAX_RETRY_DELAY_MS)
|
|
77
128
|
}
|
|
78
129
|
|
|
79
|
-
/**
|
|
80
|
-
* Checks if an HTTP error is worth retrying based on status code. Only server errors (5xx) and
|
|
81
|
-
* specific client errors (408, 429) are retryable.
|
|
82
|
-
*/
|
|
83
|
-
private fun isRetryableHttpError(exception: Throwable): Boolean {
|
|
84
|
-
// Check the exception chain for HttpDataSource.InvalidResponseCodeException
|
|
85
|
-
var current: Throwable? = exception
|
|
86
|
-
while (current != null) {
|
|
87
|
-
if (current is HttpDataSource.InvalidResponseCodeException) {
|
|
88
|
-
return current.responseCode in RETRYABLE_HTTP_STATUS_CODES
|
|
89
|
-
}
|
|
90
|
-
current = current.cause
|
|
91
|
-
}
|
|
92
|
-
return false
|
|
93
|
-
}
|
|
94
|
-
|
|
95
130
|
override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorHandlingPolicy.LoadErrorInfo): Long {
|
|
96
131
|
val exception = loadErrorInfo.exception
|
|
97
132
|
val errorCount = loadErrorInfo.errorCount
|
|
@@ -113,15 +148,20 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
113
148
|
if (firstErrorTime == null) {
|
|
114
149
|
firstErrorTime = currentTime
|
|
115
150
|
}
|
|
151
|
+
if (isOnline()) {
|
|
152
|
+
if (firstOnlineErrorTime == null) firstOnlineErrorTime = currentTime
|
|
153
|
+
} else {
|
|
154
|
+
// Seeing the device offline restarts the first-connect clock: a station that lost
|
|
155
|
+
// connectivity mid-budget gets its full online seconds again after restoration,
|
|
156
|
+
// instead of the offline gap counting against it.
|
|
157
|
+
firstOnlineErrorTime = null
|
|
158
|
+
}
|
|
116
159
|
|
|
117
|
-
// Check if we've been retrying too long (prevents surprising resumption after long
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
Timber.d("Max retry duration (${maxRetryDurationMs}ms) exceeded after ${elapsed}ms, giving up")
|
|
123
|
-
return C.TIME_UNSET
|
|
124
|
-
}
|
|
160
|
+
// Check if we've been retrying too long (prevents surprising resumption after long
|
|
161
|
+
// offline periods, and grants dead-on-arrival streams a fast verdict)
|
|
162
|
+
exhaustedBudget(currentTime)?.let { budget ->
|
|
163
|
+
Timber.d("$budget exceeded, giving up")
|
|
164
|
+
return C.TIME_UNSET
|
|
125
165
|
}
|
|
126
166
|
|
|
127
167
|
// Classify the error
|
|
@@ -148,40 +188,64 @@ class RetryLoadErrorHandlingPolicy(
|
|
|
148
188
|
)
|
|
149
189
|
|
|
150
190
|
// Notify that a retry is pending (for network restoration acceleration)
|
|
151
|
-
onRetryPending?.invoke(isNetworkError)
|
|
191
|
+
onRetryPending?.invoke(exception, isNetworkError)
|
|
152
192
|
|
|
153
193
|
delay
|
|
154
194
|
} else {
|
|
155
|
-
//
|
|
156
|
-
|
|
195
|
+
// Non-recoverable error: stop now. We can't delegate to super here —
|
|
196
|
+
// DefaultLoadErrorHandlingPolicy still schedules a backoff retry for some errors it doesn't
|
|
197
|
+
// consider fatal (e.g. a 404 InvalidResponseCodeException), which combined with our infinite
|
|
198
|
+
// getMinimumLoadableRetryCount would retry a dead URL until the max-retry-duration timeout.
|
|
199
|
+
C.TIME_UNSET
|
|
157
200
|
}
|
|
158
201
|
}
|
|
159
202
|
|
|
160
203
|
/** Classification result for an error */
|
|
161
204
|
private data class ErrorClassification(val isRecoverable: Boolean, val isNetworkError: Boolean)
|
|
162
205
|
|
|
163
|
-
/**
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Classifies whether an error is recoverable and whether it's network-related.
|
|
208
|
+
*
|
|
209
|
+
* Load errors are delivered as a raw [IOException] (e.g.
|
|
210
|
+
* [HttpDataSource.HttpDataSourceException], `UnknownHostException`, `SocketTimeoutException`) —
|
|
211
|
+
* never as a `PlaybackException`, which is only surfaced at the player level *after* retries are
|
|
212
|
+
* exhausted. So we classify by walking the IOException cause chain. This is essential: a plain
|
|
213
|
+
* Wi-Fi drop surfaces as a socket/DNS IOException, and unless we flag it as a network error the
|
|
214
|
+
* connectivity-restoration path can't fire an immediate retry, leaving playback stuck buffering
|
|
215
|
+
* until it returns.
|
|
216
|
+
*/
|
|
217
|
+
private fun classifyError(exception: IOException): ErrorClassification {
|
|
218
|
+
val nonRecoverable = ErrorClassification(isRecoverable = false, isNetworkError = false)
|
|
219
|
+
|
|
220
|
+
var current: Throwable? = exception
|
|
221
|
+
while (current != null) {
|
|
222
|
+
when (current) {
|
|
223
|
+
// HTTP responses: only retry server errors (5xx) and specific client errors (408, 429).
|
|
224
|
+
// Other status codes (e.g. 403/404) will never succeed on retry.
|
|
225
|
+
is HttpDataSource.InvalidResponseCodeException -> {
|
|
226
|
+
val retryable = current.responseCode in RETRYABLE_HTTP_STATUS_CODES
|
|
227
|
+
return ErrorClassification(isRecoverable = retryable, isNetworkError = retryable)
|
|
178
228
|
}
|
|
229
|
+
// Errors that retrying cannot fix — mirror DefaultLoadErrorHandlingPolicy's
|
|
230
|
+
// non-retryable set so we don't spin until the max-retry-duration timeout.
|
|
231
|
+
is HttpDataSource.CleartextNotPermittedException,
|
|
232
|
+
is ParserException,
|
|
233
|
+
is FileNotFoundException,
|
|
234
|
+
is Loader.UnexpectedLoaderException -> return nonRecoverable
|
|
179
235
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
236
|
+
current = current.cause
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// A read at a position the source can no longer provide (e.g. behind a live window) won't
|
|
240
|
+
// recover via an in-place loader retry.
|
|
241
|
+
if (DataSourceException.isCausedByPositionOutOfRange(exception)) {
|
|
242
|
+
return nonRecoverable
|
|
184
243
|
}
|
|
244
|
+
|
|
245
|
+
// Any other IOException is a transient network/transport failure (connection reset, DNS
|
|
246
|
+
// failure, socket timeout, network interface lost, ...): recoverable, and flagged as a network
|
|
247
|
+
// error so connectivity restoration can trigger an immediate retry.
|
|
248
|
+
return ErrorClassification(isRecoverable = true, isNetworkError = true)
|
|
185
249
|
}
|
|
186
250
|
|
|
187
251
|
override fun getMinimumLoadableRetryCount(dataType: Int): Int {
|
|
@@ -7,7 +7,8 @@ import android.os.Looper
|
|
|
7
7
|
* Manages a sleep timer that calls a completion callback after a specified duration.
|
|
8
8
|
*
|
|
9
9
|
* The timer stores the expiration time as a timestamp and uses a Handler to schedule the completion
|
|
10
|
-
* callback. Supports both time-based and end-of-track modes
|
|
10
|
+
* callback. Supports both time-based and end-of-track modes, plus an optional fade-out that starts
|
|
11
|
+
* `fadeDuration` seconds before the deadline so silence lands exactly when the timer completes.
|
|
11
12
|
*/
|
|
12
13
|
open class SleepTimer {
|
|
13
14
|
var time: Double? = null
|
|
@@ -17,6 +18,7 @@ open class SleepTimer {
|
|
|
17
18
|
private set
|
|
18
19
|
|
|
19
20
|
private var runnable: Runnable? = null
|
|
21
|
+
private var fadeRunnable: Runnable? = null
|
|
20
22
|
private val handler = Handler(Looper.getMainLooper())
|
|
21
23
|
|
|
22
24
|
val isRunning: Boolean
|
|
@@ -26,15 +28,27 @@ open class SleepTimer {
|
|
|
26
28
|
* Sets a timer to complete after the specified number of seconds.
|
|
27
29
|
*
|
|
28
30
|
* @param seconds Number of seconds until the timer completes
|
|
31
|
+
* @param fadeDuration Seconds over which to fade out before completion; clamped to [seconds]
|
|
29
32
|
*/
|
|
30
|
-
fun sleepAfter(seconds: Double) {
|
|
33
|
+
fun sleepAfter(seconds: Double, fadeDuration: Double? = null) {
|
|
31
34
|
stopTimer()
|
|
35
|
+
onFadeCancel()
|
|
32
36
|
sleepWhenPlayedToEnd = false
|
|
33
37
|
|
|
34
38
|
val runnable = Runnable { complete() }
|
|
35
39
|
this.runnable = runnable
|
|
36
40
|
handler.postDelayed(runnable, (seconds * 1000).toLong())
|
|
37
41
|
time = System.currentTimeMillis() + (seconds * 1000)
|
|
42
|
+
|
|
43
|
+
if (fadeDuration != null && fadeDuration > 0) {
|
|
44
|
+
val fade = minOf(fadeDuration, seconds)
|
|
45
|
+
val fadeRunnable = Runnable {
|
|
46
|
+
this.fadeRunnable = null
|
|
47
|
+
onFadeStart(fade)
|
|
48
|
+
}
|
|
49
|
+
this.fadeRunnable = fadeRunnable
|
|
50
|
+
handler.postDelayed(fadeRunnable, ((seconds - fade) * 1000).toLong())
|
|
51
|
+
}
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
/**
|
|
@@ -43,6 +57,7 @@ open class SleepTimer {
|
|
|
43
57
|
*/
|
|
44
58
|
fun sleepWhenPlayedToEnd() {
|
|
45
59
|
stopTimer()
|
|
60
|
+
onFadeCancel()
|
|
46
61
|
time = null
|
|
47
62
|
sleepWhenPlayedToEnd = true
|
|
48
63
|
}
|
|
@@ -55,6 +70,7 @@ open class SleepTimer {
|
|
|
55
70
|
fun clear(): Boolean {
|
|
56
71
|
val wasRunning = isRunning
|
|
57
72
|
stopTimer()
|
|
73
|
+
onFadeCancel()
|
|
58
74
|
time = null
|
|
59
75
|
sleepWhenPlayedToEnd = false
|
|
60
76
|
return wasRunning
|
|
@@ -65,9 +81,23 @@ open class SleepTimer {
|
|
|
65
81
|
// Default implementation does nothing - override in subclass
|
|
66
82
|
}
|
|
67
83
|
|
|
84
|
+
/** Override to begin fading the volume; the timer still completes at its deadline. */
|
|
85
|
+
open fun onFadeStart(durationSeconds: Double) {
|
|
86
|
+
// Default implementation does nothing - override in subclass
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Override to handle a fade cancelled before completion — restore the volume. */
|
|
90
|
+
open fun onFadeCancel() {
|
|
91
|
+
// Default implementation does nothing - override in subclass
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
private fun complete() {
|
|
69
95
|
if (!isRunning) return
|
|
70
|
-
|
|
96
|
+
// Tear down without onFadeCancel: completion pauses first, then the completion handler
|
|
97
|
+
// restores the volume.
|
|
98
|
+
stopTimer()
|
|
99
|
+
time = null
|
|
100
|
+
sleepWhenPlayedToEnd = false
|
|
71
101
|
onComplete()
|
|
72
102
|
}
|
|
73
103
|
|
|
@@ -76,5 +106,9 @@ open class SleepTimer {
|
|
|
76
106
|
handler.removeCallbacks(it)
|
|
77
107
|
runnable = null
|
|
78
108
|
}
|
|
109
|
+
fadeRunnable?.let {
|
|
110
|
+
handler.removeCallbacks(it)
|
|
111
|
+
fadeRunnable = null
|
|
112
|
+
}
|
|
79
113
|
}
|
|
80
114
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
package com.audiobrowser.player
|
|
2
|
+
|
|
3
|
+
import com.margelo.nitro.audiobrowser.SleepTimer as NitroSleepTimer
|
|
4
|
+
import com.margelo.nitro.audiobrowser.SleepTimerEndOfTrack
|
|
5
|
+
import com.margelo.nitro.audiobrowser.SleepTimerTime
|
|
6
|
+
import com.margelo.nitro.core.NullType
|
|
7
|
+
import timber.log.Timber
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Owns the Sleep Timer's interplay with the volume fade and its JS event emission: the timer counts
|
|
11
|
+
* down natively (the webview may be asleep), an optional fade finishes exactly at the deadline, and
|
|
12
|
+
* completion pauses — never stops — with the pre-fade volume restored so a half-asleep listener can
|
|
13
|
+
* resume at full volume. Mirrors iOS's SleepTimerManager. [pause] is the player's pause;
|
|
14
|
+
* [onChanged] emits onSleepTimerChanged.
|
|
15
|
+
*/
|
|
16
|
+
internal class SleepTimerManager(
|
|
17
|
+
private val volumeFader: VolumeFader,
|
|
18
|
+
private val pause: () -> Unit,
|
|
19
|
+
private val onChanged: (NitroSleepTimer) -> Unit,
|
|
20
|
+
) {
|
|
21
|
+
|
|
22
|
+
private val timer =
|
|
23
|
+
object : SleepTimer() {
|
|
24
|
+
override fun onFadeStart(durationSeconds: Double) {
|
|
25
|
+
volumeFader.start(durationSeconds)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun onFadeCancel() {
|
|
29
|
+
volumeFader.cancel(restoreVolume = true)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun onComplete() {
|
|
33
|
+
Timber.d("Sleep timer completed, pausing playback")
|
|
34
|
+
volumeFader.resolve { pause() }
|
|
35
|
+
onChanged(none())
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private fun none(): NitroSleepTimer = NitroSleepTimer.create(NullType.NULL)
|
|
40
|
+
|
|
41
|
+
/** The current state: a time-based deadline, end-of-track, or none. */
|
|
42
|
+
fun get(): NitroSleepTimer =
|
|
43
|
+
when {
|
|
44
|
+
timer.time != null -> NitroSleepTimer.create(SleepTimerTime(timer.time!!))
|
|
45
|
+
timer.sleepWhenPlayedToEnd -> NitroSleepTimer.create(SleepTimerEndOfTrack(true))
|
|
46
|
+
else -> none()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Pauses playback after [seconds], optionally fading out over the last [fadeDuration] seconds
|
|
51
|
+
* (clamped to [seconds]).
|
|
52
|
+
*/
|
|
53
|
+
fun setAfter(seconds: Double, fadeDuration: Double? = null) {
|
|
54
|
+
timer.sleepAfter(seconds, fadeDuration)
|
|
55
|
+
onChanged(get())
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Pauses playback when the current track finishes playing. */
|
|
59
|
+
fun setEndOfTrack() {
|
|
60
|
+
timer.sleepWhenPlayedToEnd()
|
|
61
|
+
onChanged(get())
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Clears the active timer. @return true when a timer was actually cleared. */
|
|
65
|
+
fun clear(): Boolean {
|
|
66
|
+
val wasRunning = timer.clear()
|
|
67
|
+
if (wasRunning) onChanged(none())
|
|
68
|
+
return wasRunning
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Pauses when an end-of-track sleep is armed; called when a track finishes naturally. */
|
|
72
|
+
fun onTrackEnd() {
|
|
73
|
+
if (timer.sleepWhenPlayedToEnd) {
|
|
74
|
+
Timber.d("Sleep timer triggered on track end, pausing playback")
|
|
75
|
+
timer.clear()
|
|
76
|
+
pause()
|
|
77
|
+
onChanged(none())
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package com.audiobrowser.player
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Caps how many times the player auto-recovers from a media3
|
|
5
|
+
* [androidx.media3.common.util.StuckPlayerException] before surfacing a terminal error.
|
|
6
|
+
*
|
|
7
|
+
* media3 1.9.0 detects a stuck player and reports it through Player.Listener.onPlayerError. We
|
|
8
|
+
* recover (re-prepare / rejoin live edge) rather than going to ERROR, because for a live-radio app
|
|
9
|
+
* a transient stall should reconnect, not stop playback. But a genuinely dead stream would re-fire
|
|
10
|
+
* forever, so we allow at most [maxRecoveries] recoveries. The budget refills only when the caller
|
|
11
|
+
* has proof the stream is alive (sustained playback) or on a track change — both via [reset]. Once
|
|
12
|
+
* the cap is exceeded the decision stays [Decision.GIVE_UP] (it does not self-refill), so a dead
|
|
13
|
+
* stream produces one clean terminal error instead of a recover/error sawtooth.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately holds no clock or time-window: a time-window keyed on recovery timing lets a stream
|
|
16
|
+
* that re-stalls just outside the window recover indefinitely. "Is it alive?" is answered by the
|
|
17
|
+
* caller from actual playback progress, not elapsed time.
|
|
18
|
+
*
|
|
19
|
+
* @param maxRecoveries Maximum recoveries allowed before giving up.
|
|
20
|
+
*/
|
|
21
|
+
class StuckRecoveryPolicy(private val maxRecoveries: Int = DEFAULT_MAX_RECOVERIES) {
|
|
22
|
+
enum class Decision {
|
|
23
|
+
RECOVER,
|
|
24
|
+
GIVE_UP,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private var recoveryCount = 0
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Records a stuck event and decides what to do. [Decision.RECOVER] means the caller should
|
|
31
|
+
* re-prepare; [Decision.GIVE_UP] means recovery is exhausted and the caller should surface a
|
|
32
|
+
* terminal error. Stays [Decision.GIVE_UP] until [reset] is called.
|
|
33
|
+
*/
|
|
34
|
+
fun onStuck(): Decision {
|
|
35
|
+
recoveryCount++
|
|
36
|
+
return if (recoveryCount > maxRecoveries) Decision.GIVE_UP else Decision.RECOVER
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Refills the recovery budget. Call on proof the stream is alive (sustained playback) or on a
|
|
41
|
+
* track change.
|
|
42
|
+
*/
|
|
43
|
+
fun reset() {
|
|
44
|
+
recoveryCount = 0
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
companion object {
|
|
48
|
+
private const val DEFAULT_MAX_RECOVERIES = 3
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -7,25 +7,24 @@ import androidx.media3.datasource.DataSpec
|
|
|
7
7
|
import androidx.media3.datasource.TransferListener
|
|
8
8
|
import com.audiobrowser.util.BrowserPathHelper
|
|
9
9
|
import com.margelo.nitro.audiobrowser.MediaRequestConfig
|
|
10
|
+
import java.io.IOException
|
|
10
11
|
import timber.log.Timber
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* A DataSource wrapper that defers media URL transformation to ExoPlayer's IO thread.
|
|
14
15
|
*
|
|
15
16
|
* ExoPlayer calls [MediaSource.Factory.createMediaSource] on the main thread during
|
|
16
|
-
* `addMediaItem()`, but calls [DataSource.open] on a background IO thread when it
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* `addMediaItem()`, but calls [DataSource.open] on a background IO thread when it needs to fetch
|
|
18
|
+
* data. By deferring URL transformation (which may invoke a JS callback via `runBlocking`) to
|
|
19
|
+
* [open], we avoid blocking the main thread and prevent deadlocks when the JS thread is occupied by
|
|
20
|
+
* synchronous Nitro calls (e.g., `seekTo`).
|
|
20
21
|
*
|
|
21
|
-
* The transform is resolved once per track on the first [open] call (the manifest/media
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* The transform is resolved once per track on the first [open] call (the manifest/media URL). The
|
|
23
|
+
* resulting headers and user-agent are cached on the [Factory] and reused for subsequent requests
|
|
24
|
+
* (segments, encryption keys) without calling the JS transform again.
|
|
24
25
|
*/
|
|
25
|
-
class TransformingDataSource(
|
|
26
|
-
|
|
27
|
-
private val factory: Factory,
|
|
28
|
-
) : DataSource {
|
|
26
|
+
class TransformingDataSource(private val upstream: DataSource, private val factory: Factory) :
|
|
27
|
+
DataSource {
|
|
29
28
|
|
|
30
29
|
companion object {
|
|
31
30
|
private const val DEFAULT_USER_AGENT = "react-native-audio-browser"
|
|
@@ -36,19 +35,28 @@ class TransformingDataSource(
|
|
|
36
35
|
override fun open(dataSpec: DataSpec): Long {
|
|
37
36
|
val originalUrl = dataSpec.uri.toString()
|
|
38
37
|
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// All subsequent opens (segments, keys, replays) reuse the cached
|
|
42
|
-
// headers/user-agent but keep their original URLs.
|
|
38
|
+
// The first open() resolves the transform and caches it on the Factory; subsequent opens
|
|
39
|
+
// (segments, keys, replays) reuse the cached headers/user-agent but keep their own URLs.
|
|
43
40
|
val cached = factory.cachedTransform
|
|
44
|
-
val (finalUrl, headers, userAgent) =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
val (finalUrl, headers, userAgent) =
|
|
42
|
+
when {
|
|
43
|
+
cached == null -> resolveAndCache(originalUrl)
|
|
44
|
+
// Re-open of the same media URL (e.g. a retry after a network drop). By default reuse the
|
|
45
|
+
// resolved URL: re-emitting the schemeless original ("/listen/<id>/x.mp3") would hit the
|
|
46
|
+
// file data source -> FileNotFoundException. But if the previous media-URL load failed,
|
|
47
|
+
// re-resolve once (see the catch below): the URL/token may be stale. The fresh URL is still
|
|
48
|
+
// absolute, so that hazard stays avoided.
|
|
49
|
+
originalUrl == factory.cachedOriginalUrl ->
|
|
50
|
+
if (factory.reresolveOnNextMediaOpen) {
|
|
51
|
+
factory.reresolveOnNextMediaOpen = false
|
|
52
|
+
resolveAndCache(originalUrl)
|
|
53
|
+
} else {
|
|
54
|
+
cached
|
|
55
|
+
}
|
|
56
|
+
// A different URL (already-absolute HLS segment or key): reuse the cached headers but keep
|
|
57
|
+
// its own URL.
|
|
58
|
+
else -> Triple(originalUrl, cached.second, cached.third)
|
|
59
|
+
}
|
|
52
60
|
|
|
53
61
|
// Build merged headers including user-agent override
|
|
54
62
|
val mergedHeaders = buildMap {
|
|
@@ -64,7 +72,27 @@ class TransformingDataSource(
|
|
|
64
72
|
dataSpec.buildUpon().setUri(finalUrl.toUri()).setHttpRequestHeaders(mergedHeaders).build()
|
|
65
73
|
|
|
66
74
|
resolvedUri = transformedSpec.uri
|
|
67
|
-
return
|
|
75
|
+
return try {
|
|
76
|
+
upstream.open(transformedSpec)
|
|
77
|
+
} catch (e: IOException) {
|
|
78
|
+
// The media-URL load failed: if ExoPlayer retries, re-resolve so a stale URL/token is
|
|
79
|
+
// refreshed instead of replayed. Scoped to the media URL (segment/key failures keep their own
|
|
80
|
+
// URL). The flag lives on this item's Factory, so it stays correct when several tracks'
|
|
81
|
+
// factories are alive at once (a queue).
|
|
82
|
+
if (originalUrl == factory.cachedOriginalUrl) {
|
|
83
|
+
factory.reresolveOnNextMediaOpen = true
|
|
84
|
+
}
|
|
85
|
+
throw e
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Resolves the transform for [originalUrl] and caches the result on the [Factory]. */
|
|
90
|
+
private fun resolveAndCache(originalUrl: String): Triple<String, Map<String, String>, String> {
|
|
91
|
+
val resolved = resolveRequestConfig(originalUrl)
|
|
92
|
+
factory.cachedTransform = resolved
|
|
93
|
+
factory.cachedOriginalUrl = originalUrl
|
|
94
|
+
Timber.d("TransformingDataSource: resolved $originalUrl -> ${resolved.first}")
|
|
95
|
+
return resolved
|
|
68
96
|
}
|
|
69
97
|
|
|
70
98
|
override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
|
|
@@ -79,6 +107,18 @@ class TransformingDataSource(
|
|
|
79
107
|
return resolvedUri ?: upstream.uri
|
|
80
108
|
}
|
|
81
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Forward the upstream response headers. ExoPlayer's `ProgressiveMediaPeriod` reads these back
|
|
112
|
+
* through the data-source chain to parse `IcyHeaders` (the `icy-metaint` interval) and only then
|
|
113
|
+
* installs the `IcyDataSource` that emits in-stream ICY/Shoutcast song metadata via
|
|
114
|
+
* `Player.Listener.onMetadata`. The `DataSource` default returns an empty map, so without this
|
|
115
|
+
* override this transparent wrapper would swallow the ICY headers — playback keeps working but
|
|
116
|
+
* `onMetadata` never fires (live "now playing" song goes missing).
|
|
117
|
+
*/
|
|
118
|
+
override fun getResponseHeaders(): Map<String, List<String>> {
|
|
119
|
+
return upstream.responseHeaders
|
|
120
|
+
}
|
|
121
|
+
|
|
82
122
|
override fun close() {
|
|
83
123
|
upstream.close()
|
|
84
124
|
resolvedUri = null
|
|
@@ -129,19 +169,29 @@ class TransformingDataSource(
|
|
|
129
169
|
) : DataSource.Factory {
|
|
130
170
|
|
|
131
171
|
/**
|
|
132
|
-
* Cached transform result (url, headers, userAgent) from the first open() call.
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
172
|
+
* Cached transform result (url, headers, userAgent) from the first open() call. Shared across
|
|
173
|
+
* all DataSource instances created by this factory. A new Factory is created per
|
|
174
|
+
* [MediaFactory.createMediaSource] call (per track), so the cache naturally resets on track
|
|
175
|
+
* transitions.
|
|
176
|
+
*/
|
|
177
|
+
@Volatile internal var cachedTransform: Triple<String, Map<String, String>, String>? = null
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* The original (pre-transform) URL that [cachedTransform] was resolved from. Used to recognise
|
|
181
|
+
* a re-open of the same media URL (e.g. a retry) so it reuses the resolved URL instead of the
|
|
182
|
+
* raw original.
|
|
183
|
+
*/
|
|
184
|
+
@Volatile internal var cachedOriginalUrl: String? = null
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Set when a media-URL load fails so the next media-URL open re-runs the transform instead of
|
|
188
|
+
* replaying [cachedTransform] — recovers an expired short-lived URL/token across a retry.
|
|
189
|
+
* Self-clearing: consumed by the first re-resolve.
|
|
136
190
|
*/
|
|
137
|
-
@Volatile
|
|
138
|
-
internal var cachedTransform: Triple<String, Map<String, String>, String>? = null
|
|
191
|
+
@Volatile internal var reresolveOnNextMediaOpen: Boolean = false
|
|
139
192
|
|
|
140
193
|
override fun createDataSource(): DataSource {
|
|
141
|
-
return TransformingDataSource(
|
|
142
|
-
upstream = upstreamFactory.createDataSource(),
|
|
143
|
-
factory = this,
|
|
144
|
-
)
|
|
194
|
+
return TransformingDataSource(upstream = upstreamFactory.createDataSource(), factory = this)
|
|
145
195
|
}
|
|
146
196
|
}
|
|
147
197
|
}
|