react-native-audio-browser 0.1.1 → 0.2.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +85 -40
- package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +81 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +141 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +37 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +41 -0
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +209 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +161 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +28 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +26 -0
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +24 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +49 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +36 -0
- package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +23 -300
- package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +13 -23
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
- package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +4 -3
- package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +211 -0
- package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +58 -0
- package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +2 -1
- package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +14 -0
- package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +6 -111
- package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +22 -8
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +111 -80
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +166 -0
- package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +46 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +39 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +114 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +141 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +4 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +177 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +54 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +96 -0
- package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +1 -2
- package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +72 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +159 -0
- package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +56 -0
- package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +216 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +442 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +191 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +198 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +137 -0
- package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +36 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +268 -0
- package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +68 -0
- package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +193 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +107 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +73 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +75 -0
- package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +18 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +163 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +28 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +53 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +58 -0
- package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +57 -0
- package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +50 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +63 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +35 -0
- package/android/src/test/resources/certs/isrg-root-x1.pem +31 -0
- package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
- package/android/src/test/resources/certs/letsencrypt-r13.pem +29 -0
- package/android/src/test/resources/certs/stationplaylist-leaf.pem +34 -0
- package/ios/Browser/BrowserConfig.swift +41 -11
- package/ios/Browser/BrowserManager+URLResolution.swift +213 -93
- package/ios/Browser/BrowserManager.swift +303 -110
- package/ios/Browser/BrowserPathHelper.swift +32 -3
- package/ios/Browser/JsonModels.swift +287 -66
- package/ios/Browser/MediaResolveComposer.swift +114 -0
- package/ios/Browser/SearchDrillIn.swift +44 -0
- package/ios/Browser/SectionScope.swift +35 -0
- package/ios/Browser/TabBarEntries.swift +15 -0
- package/ios/CarPlay/CPInterfaceController+Safe.swift +126 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
- package/ios/CarPlay/CarPlayController.swift +739 -149
- package/ios/CarPlay/CarPlayImageLoader.swift +57 -8
- package/ios/CarPlay/CarPlayListItemFactory.swift +44 -35
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +180 -36
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +19 -0
- package/ios/CarPlay/RNABAudioBrowser.h +15 -10
- package/ios/CarPlay/RNABAudioBrowser.m +15 -14
- package/ios/CarPlay/RNABCarPlaySceneDelegate.m +2 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +75 -0
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +69 -0
- package/ios/CarPlay/RNABMediaIntentHandler.swift +53 -43
- package/ios/Extension/Capability+RemoteCommand.swift +7 -9
- package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/NavigationError+Conversion.swift +8 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +20 -0
- package/ios/Extension/RequestConfig+Copying.swift +31 -0
- package/ios/Extension/ResolvedTrack+Copying.swift +10 -4
- package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Track+AVPlayer.swift +4 -4
- package/ios/Extension/Track+Copying.swift +9 -3
- package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Variant+Artwork.swift +49 -0
- package/ios/HybridAudioBrowser.swift +750 -173
- package/ios/Model/NitroTypeStubs.swift +299 -224
- package/ios/Model/PlayerUpdateOptions.swift +23 -23
- package/ios/Model/RemoteCommand.swift +6 -6
- package/ios/Model/TrackPlayerError.swift +82 -18
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +99 -121
- package/ios/NowPlayingInfo/SilentAudioPrimer.swift +73 -0
- package/ios/Observer/PlayerItemNotificationObserver.swift +45 -5
- package/ios/Observer/PlayerItemPropertyObserver.swift +27 -4
- package/ios/Observer/PlayerTimeObserver.swift +3 -53
- package/ios/Option/SessionCategories.swift +33 -11
- package/ios/Player/AirPlayStallJudgement.swift +25 -0
- package/ios/Player/EndOfTrackJudgement.swift +32 -0
- package/ios/Player/LoadSeekCoordinator.swift +16 -1
- package/ios/Player/MediaIntentCriteria.swift +139 -0
- package/ios/Player/MediaLoader.swift +31 -11
- package/ios/Player/NowPlayingUpdater.swift +119 -26
- package/ios/Player/PersistedPlaybackState.swift +11 -0
- package/ios/Player/PlaybackCoordinator.swift +285 -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 +72 -11
- 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 +32 -20
- package/ios/Tests/MediaResolveTests.swift +126 -0
- package/ios/Tests/OnceValueTests.swift +79 -0
- package/ios/Tests/PlaybackCoordinatorTests.swift +787 -13
- package/ios/Tests/PlaybackErrorHandlerTests.swift +380 -46
- package/ios/Tests/PlaybackStateMachineTests.swift +33 -8
- package/ios/Tests/PlaybackStateStoreTests.swift +48 -0
- package/ios/Tests/PlaybackTimerTests.swift +55 -0
- package/ios/Tests/PlayingStateManagerTests.swift +57 -0
- package/ios/Tests/QueueManagerTests.swift +149 -18
- package/ios/Tests/ResolvedTrackCopyingTests.swift +15 -8
- package/ios/Tests/RetryManagerTests.swift +89 -0
- package/ios/Tests/SearchDrillInTests.swift +63 -0
- package/ios/Tests/SectionScopeTests.swift +82 -0
- package/ios/Tests/SleepTimerManagerTests.swift +107 -0
- package/ios/Tests/Support/ManualSleepTimerScheduler.swift +47 -0
- package/ios/Tests/Support/TestTypes.swift +61 -20
- package/ios/Tests/TabBarEntriesTests.swift +71 -0
- package/ios/Tests/TrackSelectorTests.swift +15 -15
- package/ios/TrackPlayer.swift +380 -58
- package/ios/TrackPlayerCallbacks.swift +0 -6
- package/ios/TrackSelector.swift +5 -5
- package/ios/Util/ArtworkImageFetcher.swift +4 -2
- package/ios/Util/NetworkMonitor.swift +7 -3
- package/ios/Util/OnceValue.swift +34 -0
- package/lib/commonjs/features/browser-config.js +227 -0
- package/lib/commonjs/features/browser-config.js.map +1 -0
- package/lib/commonjs/features/browser.js +59 -158
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +42 -0
- package/lib/commonjs/features/carConnection.js.map +1 -0
- package/lib/commonjs/features/errors.js +34 -2
- package/lib/commonjs/features/errors.js.map +1 -1
- package/lib/commonjs/features/gate.js +149 -0
- package/lib/commonjs/features/gate.js.map +1 -0
- package/lib/commonjs/features/index.js +22 -0
- package/lib/commonjs/features/index.js.map +1 -1
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/nowPlaying.js +35 -0
- package/lib/commonjs/features/nowPlaying.js.map +1 -1
- package/lib/commonjs/features/output.js +37 -23
- package/lib/commonjs/features/output.js.map +1 -1
- package/lib/commonjs/features/playback/controls.js +9 -0
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/index.js +11 -0
- package/lib/commonjs/features/playback/index.js.map +1 -1
- package/lib/commonjs/features/playback/progress.js +28 -12
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +49 -13
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +249 -3
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +10 -3
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/remoteControls.js +1 -12
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +9 -4
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/native.js +5 -0
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.web.js +4 -1
- package/lib/commonjs/native.web.js.map +1 -1
- package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/artwork.js +31 -0
- package/lib/commonjs/utils/artwork.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/index.js +13 -5
- package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +176 -50
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +11 -9
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/commonjs/web/http/HttpClient.js +4 -23
- package/lib/commonjs/web/http/HttpClient.js.map +1 -1
- package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/playbackErrorKind.js +57 -0
- package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
- package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
- package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/player/OptionsManager.js +9 -17
- package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
- package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
- package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
- package/lib/module/features/browser-config.js +221 -0
- package/lib/module/features/browser-config.js.map +1 -0
- package/lib/module/features/browser.js +53 -156
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +37 -0
- package/lib/module/features/carConnection.js.map +1 -0
- package/lib/module/features/errors.js +34 -2
- package/lib/module/features/errors.js.map +1 -1
- package/lib/module/features/gate.js +144 -0
- package/lib/module/features/gate.js.map +1 -0
- package/lib/module/features/index.js +2 -0
- package/lib/module/features/index.js.map +1 -1
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/nowPlaying.js +33 -0
- package/lib/module/features/nowPlaying.js.map +1 -1
- package/lib/module/features/output.js +32 -19
- package/lib/module/features/output.js.map +1 -1
- package/lib/module/features/playback/controls.js +8 -0
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/index.js +1 -0
- package/lib/module/features/playback/index.js.map +1 -1
- package/lib/module/features/playback/progress.js +28 -12
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +88 -0
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +48 -13
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +249 -3
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/queue/queue.js +10 -3
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/remoteControls.js +0 -11
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +9 -4
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/native.js +5 -0
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.web.js +4 -1
- package/lib/module/native.web.js.map +1 -1
- package/lib/module/utils/LazyNativeEmitter.js +0 -3
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +0 -3
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/artwork.js +26 -0
- package/lib/module/utils/artwork.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +302 -125
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/module/web/TrackPlayer/Player.js +90 -26
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
- package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/module/web/TrackPlayer/index.js +2 -1
- package/lib/module/web/TrackPlayer/index.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +176 -50
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/NavigationErrorManager.js +3 -1
- package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +11 -9
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/module/web/browser/parseSearchResponse.js +16 -0
- package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/module/web/http/HttpClient.js +4 -23
- package/lib/module/web/http/HttpClient.js.map +1 -1
- package/lib/module/web/http/RequestConfigBuilder.js +107 -58
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/playbackErrorKind.js +52 -0
- package/lib/module/web/playbackErrorKind.js.map +1 -0
- package/lib/module/web/player/MediaSessionManager.js +116 -0
- package/lib/module/web/player/MediaSessionManager.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +7 -5
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/player/OptionsManager.js +9 -17
- package/lib/module/web/player/OptionsManager.js.map +1 -1
- package/lib/module/web/player/RemoteCommandController.js +92 -0
- package/lib/module/web/player/RemoteCommandController.js.map +1 -0
- package/lib/typescript/src/features/browser-config.d.ts +12 -0
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
- package/lib/typescript/src/features/browser.d.ts +40 -1
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +20 -0
- package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
- package/lib/typescript/src/features/errors.d.ts +58 -3
- package/lib/typescript/src/features/errors.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +77 -0
- package/lib/typescript/src/features/gate.d.ts.map +1 -0
- package/lib/typescript/src/features/index.d.ts +2 -0
- package/lib/typescript/src/features/index.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +6 -4
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
- package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
- package/lib/typescript/src/features/output.d.ts +28 -18
- package/lib/typescript/src/features/output.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +5 -0
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/index.d.ts +1 -0
- package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +3 -0
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +92 -93
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +206 -167
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +9 -2
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +0 -13
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native.d.ts +1 -2
- package/lib/typescript/src/native.d.ts.map +1 -1
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-native.d.ts +9 -3
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +349 -85
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/artwork.d.ts +19 -0
- package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +131 -0
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
- package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
- package/nitrogen/generated/android/c++/JGate.hpp +62 -0
- package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
- package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
- package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
- package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
- package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
- package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
- package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
- package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
- package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
- package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
- package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
- package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
- package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt} +12 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
- package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
- package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
- package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
- package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
- package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
- package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +77 -0
- package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
- package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
- package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
- package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
- package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
- package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift → Func_void_std__shared_ptr_Promise_GateDecision__.swift} +17 -17
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
- package/nitrogen/generated/ios/swift/Gate.swift +47 -0
- package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
- package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
- package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
- package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
- package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
- package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
- package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
- package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
- package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
- package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
- package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
- package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
- package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
- package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
- package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
- package/nitrogen/generated/ios/swift/Options.swift +10 -4
- package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
- package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
- package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
- package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
- package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
- package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
- package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
- package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
- package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +74 -8
- package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
- package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
- package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
- package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
- package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
- package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
- package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
- package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
- package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
- package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
- package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
- package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
- package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
- package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
- package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
- package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
- package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
- package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
- package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
- package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
- package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
- package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
- package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
- package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
- package/nitrogen/generated/shared/c++/Options.hpp +8 -8
- package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
- package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
- package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
- package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
- package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
- package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
- package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
- package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
- package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +24 -5
- package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
- package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
- package/package.json +11 -6
- package/src/codegen-no-config-variant.test.ts +70 -0
- package/src/features/browser-config.test.ts +110 -0
- package/src/features/browser-config.ts +293 -0
- package/src/features/browser.test.ts +19 -0
- package/src/features/browser.ts +58 -201
- package/src/features/carConnection.ts +36 -0
- package/src/features/errors.ts +68 -2
- package/src/features/gate.test.ts +72 -0
- package/src/features/gate.ts +155 -0
- package/src/features/index.ts +2 -0
- package/src/features/metadata.ts +6 -12
- package/src/features/nowPlaying.ts +36 -0
- package/src/features/output.ts +35 -22
- package/src/features/playback/controls.ts +8 -0
- package/src/features/playback/index.ts +1 -0
- package/src/features/playback/progress.ts +31 -12
- package/src/features/playback/trackPlaybackTime.test.ts +66 -0
- package/src/features/playback/trackPlaybackTime.ts +106 -0
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.test.ts +38 -0
- package/src/features/player/options.ts +140 -75
- package/src/features/player/setup.test.ts +117 -0
- package/src/features/player/setup.ts +390 -175
- package/src/features/queue/queue.test.ts +36 -0
- package/src/features/queue/queue.ts +15 -4
- package/src/features/remoteControls.ts +0 -23
- package/src/features/sleepTimer.ts +23 -4
- package/src/native.ts +5 -0
- package/src/native.web.ts +4 -1
- package/src/specs/audio-browser.nitro.ts +131 -41
- package/src/types/browser-native.ts +19 -6
- package/src/types/browser-nodes.ts +160 -13
- package/src/types/browser.ts +377 -89
- package/src/utils/LazyNativeEmitter.ts +0 -2
- package/src/utils/NativeUpdatedValue.ts +0 -2
- package/src/utils/artwork.ts +30 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
- package/src/web/NativeAudioBrowser.ts +365 -158
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
- package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
- package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
- package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
- package/src/web/TrackPlayer/Player.load.test.ts +86 -0
- package/src/web/TrackPlayer/Player.ts +113 -39
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
- package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
- package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
- package/src/web/TrackPlayer/QueueManager.ts +302 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
- package/src/web/TrackPlayer/RepeatMode.ts +1 -1
- package/src/web/TrackPlayer/SleepTimer.ts +38 -3
- package/src/web/TrackPlayer/VolumeFader.ts +74 -0
- package/src/web/TrackPlayer/index.ts +2 -1
- package/src/web/browser/BrowserManager.ts +231 -62
- package/src/web/browser/NavigationErrorManager.ts +3 -1
- package/src/web/browser/SearchManager.ts +11 -15
- package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
- package/src/web/browser/assertBrowsePageShape.ts +27 -0
- package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
- package/src/web/browser/classifyTrackNavigation.ts +35 -0
- package/src/web/browser/parseSearchResponse.test.ts +25 -0
- package/src/web/browser/parseSearchResponse.ts +15 -0
- package/src/web/http/HttpClient.ts +5 -35
- package/src/web/http/RequestConfigBuilder.test.ts +59 -0
- package/src/web/http/RequestConfigBuilder.ts +120 -63
- package/src/web/playbackErrorKind.test.ts +55 -0
- package/src/web/playbackErrorKind.ts +56 -0
- package/src/web/player/MediaSessionManager.test.ts +220 -0
- package/src/web/player/MediaSessionManager.ts +151 -0
- package/src/web/player/NowPlayingManager.test.ts +46 -0
- package/src/web/player/NowPlayingManager.ts +6 -5
- package/src/web/player/OptionsManager.ts +12 -18
- package/src/web/player/RemoteCommandController.test.ts +171 -0
- package/src/web/player/RemoteCommandController.ts +166 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
- package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
- package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
- package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
- package/ios/CarPlay/Track+CarPlay.swift +0 -63
- package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
- package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
- package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
- package/lib/commonjs/features/rating.js +0 -2
- package/lib/commonjs/features/rating.js.map +0 -1
- package/lib/commonjs/types/player.js +0 -2
- package/lib/commonjs/types/player.js.map +0 -1
- package/lib/commonjs/web/SimpleRouter.test.js +0 -174
- package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/module/features/rating.js +0 -2
- package/lib/module/features/rating.js.map +0 -1
- package/lib/module/types/player.js +0 -2
- package/lib/module/types/player.js.map +0 -1
- package/lib/module/web/SimpleRouter.test.js +0 -174
- package/lib/module/web/SimpleRouter.test.js.map +0 -1
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/typescript/src/features/rating.d.ts +0 -14
- package/lib/typescript/src/features/rating.d.ts.map +0 -1
- package/lib/typescript/src/native.web.d.ts +0 -3
- package/lib/typescript/src/native.web.d.ts.map +0 -1
- package/lib/typescript/src/types/player.d.ts +0 -64
- package/lib/typescript/src/types/player.d.ts.map +0 -1
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
- package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
- package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
- package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
- package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
- package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
- package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
- package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
- package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
- package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
- package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
- package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
- package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
- package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
- package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
- package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
- package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
- package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
- package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
- package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
- package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
- package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
- package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
- package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
- package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
- package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
- package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
- package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
- package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
- package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
- package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
- package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
- package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
- package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
- package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
- package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
- package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
- package/src/features/rating.ts +0 -17
- package/src/types/player.ts +0 -69
- package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
-
|
|
2
|
+
#if canImport(NitroModules)
|
|
3
|
+
import NitroModules
|
|
4
|
+
#endif
|
|
3
5
|
import os.log
|
|
4
6
|
|
|
7
|
+
/// Abstracts `NetworkMonitor` so tests can fake connectivity. Sendable because
|
|
8
|
+
/// the network-restore race reads it from a task-group child.
|
|
9
|
+
protocol NetworkStatusProviding: AnyObject, Sendable {
|
|
10
|
+
var isOnline: Bool { get }
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
/// Manages retry logic for media load errors with exponential backoff.
|
|
6
14
|
/// Similar to Android's RetryLoadErrorHandlingPolicy.
|
|
7
15
|
///
|
|
16
|
+
/// Two duration budgets apply, chosen by whether the current load has ever
|
|
17
|
+
/// produced audio (`hasPlayed`): a short first-connect budget — a stream that
|
|
18
|
+
/// fails before ever playing is usually dead, and the listener is actively
|
|
19
|
+
/// waiting for a verdict — and the full recovery budget for a stream that
|
|
20
|
+
/// played and then dropped (tunnels, handovers, encoder restarts). The short
|
|
21
|
+
/// budget counts only online time, so a station tapped in a tunnel still gets
|
|
22
|
+
/// its online seconds once connectivity returns.
|
|
23
|
+
///
|
|
8
24
|
/// When a network monitor is provided and the device is offline, the retry will
|
|
9
25
|
/// trigger immediately when connectivity is restored instead of waiting for the
|
|
10
26
|
/// full backoff delay.
|
|
@@ -19,28 +35,53 @@ class RetryManager {
|
|
|
19
35
|
}
|
|
20
36
|
|
|
21
37
|
private static let defaultMaxRetryDurationMs: Double = 120_000 // 2 minutes
|
|
38
|
+
private static let defaultFirstConnectMaxRetryDurationMs: Double = 12_000
|
|
22
39
|
|
|
23
40
|
/// Prevents surprising playback resumption after long periods offline.
|
|
24
41
|
private var maxRetryDuration: TimeInterval = defaultMaxRetryDurationMs / 1000
|
|
25
42
|
|
|
43
|
+
/// Bounds retries of a load that has never produced audio, while online.
|
|
44
|
+
private var firstConnectMaxRetryDuration: TimeInterval = defaultFirstConnectMaxRetryDurationMs / 1000
|
|
45
|
+
|
|
46
|
+
/// True once the current load has produced audio; selects between the
|
|
47
|
+
/// first-connect and recovery budgets. Set by the owner when audio starts and
|
|
48
|
+
/// cleared by the owner when a new track loads — deliberately NOT cleared in
|
|
49
|
+
/// `reset()`, which the healthy-playback budget refill also calls mid-play.
|
|
50
|
+
var hasPlayed = false
|
|
51
|
+
|
|
52
|
+
/// First failure observed while online for the current load — the
|
|
53
|
+
/// first-connect budget's clock. Never set while offline, and wiped by any
|
|
54
|
+
/// offline observation, so an offline stretch cannot burn the short budget:
|
|
55
|
+
/// the clock restarts at the next failure observed online.
|
|
56
|
+
private var firstOnlineRetryTime: Date?
|
|
57
|
+
|
|
26
58
|
private var policy: Policy = .disabled
|
|
27
59
|
private var attemptCount = 0
|
|
28
60
|
private var firstRetryTime: Date?
|
|
29
61
|
|
|
30
|
-
weak var networkMonitor:
|
|
31
|
-
|
|
62
|
+
weak var networkMonitor: (any NetworkStatusProviding)?
|
|
63
|
+
/// True only while a scheduled retry is parked polling for connectivity to return. Exposed so the
|
|
64
|
+
/// player's stall-driven reconnect can defer to an in-flight error retry (which owns its own
|
|
65
|
+
/// reload) and avoid a double load.
|
|
66
|
+
private(set) var isWaitingForNetwork = false
|
|
32
67
|
/// Invalidates in-flight retries when reset() is called (e.g. track change)
|
|
33
68
|
private var generation: Int = 0
|
|
34
69
|
|
|
35
70
|
var shouldRetry: () -> Bool = { true }
|
|
36
71
|
var onRetry: ((Bool) -> Void)?
|
|
37
72
|
|
|
73
|
+
var isEnabled: Bool {
|
|
74
|
+
if case .disabled = policy { return false }
|
|
75
|
+
return true
|
|
76
|
+
}
|
|
77
|
+
|
|
38
78
|
// MARK: - Configuration
|
|
39
79
|
|
|
40
80
|
func updatePolicy(from config: Variant_Bool_RetryConfig?) {
|
|
41
81
|
guard let config else {
|
|
42
82
|
policy = .disabled
|
|
43
83
|
maxRetryDuration = Self.defaultMaxRetryDurationMs / 1000
|
|
84
|
+
firstConnectMaxRetryDuration = Self.defaultFirstConnectMaxRetryDurationMs / 1000
|
|
44
85
|
logger.debug("Retry policy: disabled")
|
|
45
86
|
return
|
|
46
87
|
}
|
|
@@ -49,13 +90,22 @@ class RetryManager {
|
|
|
49
90
|
case let .first(enabled):
|
|
50
91
|
policy = enabled ? .infinite : .disabled
|
|
51
92
|
maxRetryDuration = Self.defaultMaxRetryDurationMs / 1000
|
|
93
|
+
firstConnectMaxRetryDuration = Self.defaultFirstConnectMaxRetryDurationMs / 1000
|
|
52
94
|
logger.debug("Retry policy: \(enabled ? "infinite" : "disabled")")
|
|
53
95
|
case let .second(retryConfig):
|
|
54
|
-
let maxRetries = Int(retryConfig.maxRetries)
|
|
55
|
-
policy = .limited(maxRetries: maxRetries)
|
|
56
96
|
let durationMs = retryConfig.maxRetryDurationMs ?? Self.defaultMaxRetryDurationMs
|
|
57
97
|
maxRetryDuration = durationMs / 1000
|
|
58
|
-
|
|
98
|
+
let firstConnectMs = retryConfig.firstConnectMaxRetryDurationMs
|
|
99
|
+
?? Self.defaultFirstConnectMaxRetryDurationMs
|
|
100
|
+
firstConnectMaxRetryDuration = firstConnectMs / 1000
|
|
101
|
+
// No attempt cap = retry indefinitely, bounded only by the duration.
|
|
102
|
+
if let maxRetries = retryConfig.maxRetries.map(Int.init) {
|
|
103
|
+
policy = .limited(maxRetries: maxRetries)
|
|
104
|
+
logger.debug("Retry policy: limited to \(maxRetries) retries, max duration \(self.maxRetryDuration)s")
|
|
105
|
+
} else {
|
|
106
|
+
policy = .infinite
|
|
107
|
+
logger.debug("Retry policy: infinite, max duration \(self.maxRetryDuration)s")
|
|
108
|
+
}
|
|
59
109
|
}
|
|
60
110
|
}
|
|
61
111
|
|
|
@@ -103,11 +153,29 @@ class RetryManager {
|
|
|
103
153
|
func reset() {
|
|
104
154
|
attemptCount = 0
|
|
105
155
|
firstRetryTime = nil
|
|
156
|
+
firstOnlineRetryTime = nil
|
|
106
157
|
isWaitingForNetwork = false
|
|
107
158
|
generation += 1
|
|
108
159
|
logger.debug("Retry count reset (generation \(self.generation))")
|
|
109
160
|
}
|
|
110
161
|
|
|
162
|
+
private var isOnline: Bool { networkMonitor?.isOnline ?? true }
|
|
163
|
+
|
|
164
|
+
/// A description of the exhausted budget, or nil while budget remains.
|
|
165
|
+
/// The recovery duration bounds everything (including offline waits); the
|
|
166
|
+
/// first-connect duration additionally bounds never-played loads, online only.
|
|
167
|
+
private func exhaustedBudget() -> String? {
|
|
168
|
+
let now = Date()
|
|
169
|
+
if let start = firstRetryTime, now.timeIntervalSince(start) >= maxRetryDuration {
|
|
170
|
+
return "max retry duration (\(maxRetryDuration)s)"
|
|
171
|
+
}
|
|
172
|
+
if !hasPlayed, isOnline, let start = firstOnlineRetryTime,
|
|
173
|
+
now.timeIntervalSince(start) >= firstConnectMaxRetryDuration {
|
|
174
|
+
return "first-connect retry duration (\(firstConnectMaxRetryDuration)s)"
|
|
175
|
+
}
|
|
176
|
+
return nil
|
|
177
|
+
}
|
|
178
|
+
|
|
111
179
|
func attemptRetry(startFromCurrentTime: Bool) async -> Bool {
|
|
112
180
|
if case .disabled = policy {
|
|
113
181
|
logger.debug("Retry disabled, not retrying")
|
|
@@ -129,14 +197,20 @@ class RetryManager {
|
|
|
129
197
|
if firstRetryTime == nil {
|
|
130
198
|
firstRetryTime = Date()
|
|
131
199
|
}
|
|
200
|
+
if isOnline {
|
|
201
|
+
if firstOnlineRetryTime == nil { firstOnlineRetryTime = Date() }
|
|
202
|
+
} else {
|
|
203
|
+
// Seeing the device offline restarts the first-connect clock: a station
|
|
204
|
+
// that lost connectivity mid-budget gets its full online seconds again
|
|
205
|
+
// after restoration, instead of the offline gap counting against it.
|
|
206
|
+
firstOnlineRetryTime = nil
|
|
207
|
+
}
|
|
132
208
|
|
|
133
|
-
// Check if we've been retrying too long (prevents surprising resumption
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return false
|
|
139
|
-
}
|
|
209
|
+
// Check if we've been retrying too long (prevents surprising resumption
|
|
210
|
+
// after long offline periods, and grants dead-on-arrival streams a fast verdict)
|
|
211
|
+
if let budget = exhaustedBudget() {
|
|
212
|
+
logger.info("\(budget) exceeded, giving up")
|
|
213
|
+
return false
|
|
140
214
|
}
|
|
141
215
|
|
|
142
216
|
let delaySeconds = calculateDelaySeconds()
|
|
@@ -157,18 +231,20 @@ class RetryManager {
|
|
|
157
231
|
return false
|
|
158
232
|
}
|
|
159
233
|
|
|
234
|
+
// Cancellation can land after the sleep completed — without this check a
|
|
235
|
+
// replaced retry (new error right as the old backoff expires) still fires
|
|
236
|
+
// onRetry, double-reloading and burning the attempt count twice.
|
|
237
|
+
guard !Task.isCancelled else { return false }
|
|
238
|
+
|
|
160
239
|
guard shouldRetry() else {
|
|
161
240
|
logger.debug("shouldRetry returned false after delay, cancelling retry")
|
|
162
241
|
return false
|
|
163
242
|
}
|
|
164
243
|
|
|
165
|
-
// Re-check
|
|
166
|
-
if let
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
logger.info("Max retry duration (\(self.maxRetryDuration)s) exceeded after waiting (\(elapsed)s), giving up")
|
|
170
|
-
return false
|
|
171
|
-
}
|
|
244
|
+
// Re-check the budgets — we may have waited a long time for network restoration
|
|
245
|
+
if let budget = exhaustedBudget() {
|
|
246
|
+
logger.info("\(budget) exceeded after waiting, giving up")
|
|
247
|
+
return false
|
|
172
248
|
}
|
|
173
249
|
|
|
174
250
|
attemptCount += 1
|
|
@@ -218,7 +294,7 @@ class RetryManager {
|
|
|
218
294
|
|
|
219
295
|
/// Returns false when network is restored, true if cancelled.
|
|
220
296
|
@MainActor
|
|
221
|
-
private func waitForNetworkRestored(monitor:
|
|
297
|
+
private func waitForNetworkRestored(monitor: any NetworkStatusProviding) async -> Bool {
|
|
222
298
|
if monitor.isOnline {
|
|
223
299
|
return false
|
|
224
300
|
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
1
3
|
/// Protocol abstracting sleep timer for testability.
|
|
2
4
|
/// PlaybackCoordinator uses this instead of SleepTimerManager directly.
|
|
3
5
|
@MainActor protocol SleepTimerHandling: AnyObject {
|
|
4
6
|
var onComplete: (() -> Void)? { get set }
|
|
7
|
+
/// Invoked when the fade-out window of a time-based timer begins.
|
|
8
|
+
var onFadeStart: ((_ duration: TimeInterval) -> Void)? { get set }
|
|
9
|
+
/// Invoked when a timer is cancelled/replaced while its fade may be running —
|
|
10
|
+
/// the listener restores the pre-fade volume.
|
|
11
|
+
var onFadeCancel: (() -> Void)? { get set }
|
|
12
|
+
@discardableResult func clear() -> Bool
|
|
5
13
|
func onTrackChanged()
|
|
6
14
|
func onTrackPlayedToEnd()
|
|
7
15
|
}
|
|
@@ -1,17 +1,57 @@
|
|
|
1
1
|
import Foundation
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
#if canImport(NitroModules)
|
|
4
|
+
import NitroModules
|
|
5
|
+
#endif
|
|
3
6
|
|
|
4
7
|
/// Type alias for the Nitro SleepTimer variant type
|
|
5
8
|
typealias SleepTimerState = SleepTimer
|
|
6
9
|
|
|
10
|
+
/// A scheduled job that has not run yet. `cancel()` is nonisolated so `deinit`
|
|
11
|
+
/// — always nonisolated in Swift 6 — can tear pending work down.
|
|
12
|
+
protocol SleepTimerJob: AnyObject {
|
|
13
|
+
func cancel()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
extension DispatchWorkItem: SleepTimerJob {}
|
|
17
|
+
|
|
18
|
+
/// Runs work after a delay. Injected into `SleepTimerManager` so tests can
|
|
19
|
+
/// drive the clock instead of racing it: production schedules on the main
|
|
20
|
+
/// queue, tests hand in a scheduler they advance by hand.
|
|
21
|
+
@MainActor
|
|
22
|
+
protocol SleepTimerScheduling {
|
|
23
|
+
func schedule(
|
|
24
|
+
after delay: TimeInterval,
|
|
25
|
+
_ work: @escaping @Sendable @MainActor () -> Void,
|
|
26
|
+
) -> any SleepTimerJob
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
struct MainQueueSleepTimerScheduler: SleepTimerScheduling {
|
|
30
|
+
func schedule(
|
|
31
|
+
after delay: TimeInterval,
|
|
32
|
+
_ work: @escaping @Sendable @MainActor () -> Void,
|
|
33
|
+
) -> any SleepTimerJob {
|
|
34
|
+
let job = DispatchWorkItem { MainActor.assumeIsolated { work() } }
|
|
35
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: job)
|
|
36
|
+
return job
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
7
40
|
/// Manages sleep timer functionality for the audio player.
|
|
8
41
|
/// Supports both time-based timers and end-of-track timers.
|
|
9
42
|
@MainActor
|
|
10
43
|
class SleepTimerManager: SleepTimerHandling {
|
|
11
44
|
// MARK: - Properties
|
|
12
45
|
|
|
46
|
+
private let scheduler: any SleepTimerScheduling
|
|
47
|
+
|
|
13
48
|
// nonisolated(unsafe) for deinit cleanup — deinit is always nonisolated in Swift 6.
|
|
14
|
-
nonisolated(unsafe)
|
|
49
|
+
private nonisolated(unsafe) var sleepTimerJob: (any SleepTimerJob)?
|
|
50
|
+
private nonisolated(unsafe) var fadeJob: (any SleepTimerJob)?
|
|
51
|
+
|
|
52
|
+
init(scheduler: any SleepTimerScheduling = MainQueueSleepTimerScheduler()) {
|
|
53
|
+
self.scheduler = scheduler
|
|
54
|
+
}
|
|
15
55
|
|
|
16
56
|
/// The time when playback should stop (seconds since epoch), or -1 if inactive
|
|
17
57
|
private(set) var sleepTimerTime: TimeInterval = -1 {
|
|
@@ -36,6 +76,14 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
36
76
|
/// Callback invoked when the sleep timer fires
|
|
37
77
|
var onComplete: (() -> Void)?
|
|
38
78
|
|
|
79
|
+
/// Callback invoked when the fade-out window of a time-based timer begins
|
|
80
|
+
var onFadeStart: ((_ duration: TimeInterval) -> Void)?
|
|
81
|
+
|
|
82
|
+
/// Callback invoked when a timer is cancelled/replaced while its fade may be
|
|
83
|
+
/// running — the listener restores the pre-fade volume. Not invoked on
|
|
84
|
+
/// completion: there the pause lands first, then the volume is restored.
|
|
85
|
+
var onFadeCancel: (() -> Void)?
|
|
86
|
+
|
|
39
87
|
/// Callback invoked when the sleep timer state changes
|
|
40
88
|
var onChanged: ((SleepTimerState) -> Void)?
|
|
41
89
|
|
|
@@ -49,6 +97,7 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
49
97
|
if !hasSleepTimer { return false }
|
|
50
98
|
sleepTimerTime = -1
|
|
51
99
|
willSleepWhenCurrentItemReachesEnd = false
|
|
100
|
+
onFadeCancel?()
|
|
52
101
|
onChanged?(.first(NullType.null))
|
|
53
102
|
return true
|
|
54
103
|
}
|
|
@@ -74,17 +123,23 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
74
123
|
}
|
|
75
124
|
|
|
76
125
|
/// Sets a time-based sleep timer.
|
|
77
|
-
/// -
|
|
78
|
-
|
|
126
|
+
/// - Parameters:
|
|
127
|
+
/// - seconds: Number of seconds until playback stops
|
|
128
|
+
/// - fadeDuration: Seconds over which to fade the volume out before the
|
|
129
|
+
/// deadline (clamped to `seconds`); silence lands exactly at the deadline
|
|
130
|
+
func set(seconds: TimeInterval, fadeDuration: TimeInterval? = nil) {
|
|
79
131
|
cancelSleepTimerJob()
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
132
|
+
onFadeCancel?()
|
|
133
|
+
sleepTimerTime = Date().timeIntervalSince1970 + seconds
|
|
134
|
+
sleepTimerJob = scheduler.schedule(after: seconds) { [weak self] in
|
|
135
|
+
self?.complete()
|
|
136
|
+
}
|
|
137
|
+
if let fadeDuration, fadeDuration > 0 {
|
|
138
|
+
let fade = min(fadeDuration, seconds)
|
|
139
|
+
fadeJob = scheduler.schedule(after: seconds - fade) { [weak self] in
|
|
140
|
+
self?.onFadeStart?(fade)
|
|
83
141
|
}
|
|
84
142
|
}
|
|
85
|
-
sleepTimerJob = job
|
|
86
|
-
sleepTimerTime = Date().timeIntervalSince1970 + seconds
|
|
87
|
-
DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: job)
|
|
88
143
|
if let state = get() { onChanged?(state) }
|
|
89
144
|
}
|
|
90
145
|
|
|
@@ -92,7 +147,10 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
92
147
|
func setToEndOfTrack() {
|
|
93
148
|
let changed = !willSleepWhenCurrentItemReachesEnd
|
|
94
149
|
willSleepWhenCurrentItemReachesEnd = true
|
|
95
|
-
if changed
|
|
150
|
+
if changed {
|
|
151
|
+
onFadeCancel?()
|
|
152
|
+
if let state = get() { onChanged?(state) }
|
|
153
|
+
}
|
|
96
154
|
}
|
|
97
155
|
|
|
98
156
|
/// Called when the current track changes. Resets end-of-track timer.
|
|
@@ -116,6 +174,8 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
116
174
|
private func cancelSleepTimerJob() {
|
|
117
175
|
sleepTimerJob?.cancel()
|
|
118
176
|
sleepTimerJob = nil
|
|
177
|
+
fadeJob?.cancel()
|
|
178
|
+
fadeJob = nil
|
|
119
179
|
}
|
|
120
180
|
|
|
121
181
|
private func complete() {
|
|
@@ -127,5 +187,6 @@ class SleepTimerManager: SleepTimerHandling {
|
|
|
127
187
|
|
|
128
188
|
deinit {
|
|
129
189
|
sleepTimerJob?.cancel()
|
|
190
|
+
fadeJob?.cancel()
|
|
130
191
|
}
|
|
131
192
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Ramps the player volume down over a duration (sleep-timer fade).
|
|
4
|
+
/// The gain follows a squared curve: loudness perception is logarithmic, so a
|
|
5
|
+
/// linear gain ramp sounds like a late cutoff rather than a fade.
|
|
6
|
+
@MainActor
|
|
7
|
+
final class VolumeFader {
|
|
8
|
+
private static let stepInterval: TimeInterval = 0.05
|
|
9
|
+
|
|
10
|
+
private let getVolume: () -> Float
|
|
11
|
+
private let setVolume: (Float) -> Void
|
|
12
|
+
// nonisolated(unsafe) for deinit cleanup — deinit is always nonisolated in Swift 6.
|
|
13
|
+
private nonisolated(unsafe) var timer: Timer?
|
|
14
|
+
|
|
15
|
+
/// Volume captured when the fade started; restored after the fade resolves.
|
|
16
|
+
/// Non-nil from fade start until cancel/completion, even once the ramp has
|
|
17
|
+
/// reached silence.
|
|
18
|
+
private(set) var originalVolume: Float?
|
|
19
|
+
|
|
20
|
+
var isActive: Bool { originalVolume != nil }
|
|
21
|
+
|
|
22
|
+
init(getVolume: @escaping () -> Float, setVolume: @escaping (Float) -> Void) {
|
|
23
|
+
self.getVolume = getVolume
|
|
24
|
+
self.setVolume = setVolume
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func start(duration: TimeInterval) {
|
|
28
|
+
// If a fade is already running, keep its captured volume as the baseline —
|
|
29
|
+
// the current (partially faded) volume is not the value to restore.
|
|
30
|
+
let baseVolume = originalVolume ?? getVolume()
|
|
31
|
+
cancel(restoringVolume: false)
|
|
32
|
+
originalVolume = baseVolume
|
|
33
|
+
guard duration > 0 else { return }
|
|
34
|
+
|
|
35
|
+
let startDate = Date()
|
|
36
|
+
let timer = Timer(timeInterval: Self.stepInterval, repeats: true) { [weak self] _ in
|
|
37
|
+
MainActor.assumeIsolated {
|
|
38
|
+
guard let self else { return }
|
|
39
|
+
let progress = min(1, Date().timeIntervalSince(startDate) / duration)
|
|
40
|
+
let remaining = Float(1 - progress)
|
|
41
|
+
self.setVolume(baseVolume * remaining * remaining)
|
|
42
|
+
if progress >= 1 {
|
|
43
|
+
self.timer?.invalidate()
|
|
44
|
+
self.timer = nil
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
self.timer = timer
|
|
49
|
+
RunLoop.main.add(timer, forMode: .common)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Stops the ramp. With `restoringVolume` the pre-fade volume is put back
|
|
53
|
+
/// immediately (cancellation); without it the caller restores after pausing
|
|
54
|
+
/// (completion path — restoring first would let full-volume audio slip out).
|
|
55
|
+
func cancel(restoringVolume: Bool) {
|
|
56
|
+
timer?.invalidate()
|
|
57
|
+
timer = nil
|
|
58
|
+
guard let originalVolume else { return }
|
|
59
|
+
self.originalVolume = nil
|
|
60
|
+
if restoringVolume { setVolume(originalVolume) }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Resolves the fade around a halting action: stops the ramp, runs `halt`,
|
|
64
|
+
/// then restores the pre-fade volume — in that order, because restoring
|
|
65
|
+
/// before halting would let full-volume audio slip out. The restore is
|
|
66
|
+
/// skipped when no fade was running.
|
|
67
|
+
func resolve(around halt: () -> Void) {
|
|
68
|
+
let preFadeVolume = originalVolume
|
|
69
|
+
cancel(restoringVolume: false)
|
|
70
|
+
halt()
|
|
71
|
+
if let preFadeVolume { setVolume(preFadeVolume) }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
deinit {
|
|
75
|
+
timer?.invalidate()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -51,6 +51,19 @@ class RemoteCommandController {
|
|
|
51
51
|
var commandTargetPointers: [String: Any] = [:]
|
|
52
52
|
private var enabledCommands: [RemoteCommand] = []
|
|
53
53
|
|
|
54
|
+
/// Whether there's a next/previous track to skip to. Stored so it survives
|
|
55
|
+
/// command (re)enable and iOS-16 command-center switches; the next/previous
|
|
56
|
+
/// commands are enabled in this state rather than unconditionally.
|
|
57
|
+
private var canNext = true
|
|
58
|
+
private var canPrevious = true
|
|
59
|
+
|
|
60
|
+
/// Shuffle/repeat display state, stored so it survives a command-center switch
|
|
61
|
+
/// (iOS-16 MPNowPlayingSession re-creation). A new center defaults these to
|
|
62
|
+
/// off; without re-applying, the CarPlay/lock-screen shuffle & repeat buttons
|
|
63
|
+
/// flash off on every switch.
|
|
64
|
+
private var shuffleEnabled = false
|
|
65
|
+
private var repeatMode: RepeatMode = .off
|
|
66
|
+
|
|
54
67
|
/**
|
|
55
68
|
Create a new RemoteCommandController.
|
|
56
69
|
|
|
@@ -90,6 +103,11 @@ class RemoteCommandController {
|
|
|
90
103
|
// Re-enable commands on the new center
|
|
91
104
|
enable(commands: commandsToReEnable)
|
|
92
105
|
|
|
106
|
+
// Restore shuffle/repeat display state — the new center defaults them to off,
|
|
107
|
+
// so without this the shuffle & repeat buttons flash off on every switch.
|
|
108
|
+
center.changeShuffleModeCommand.currentShuffleType = shuffleEnabled.mpShuffleType
|
|
109
|
+
center.changeRepeatModeCommand.currentRepeatType = repeatMode.mpRepeatType
|
|
110
|
+
|
|
93
111
|
logger.info("Switched command center, re-enabled \(commandsToReEnable.count) commands")
|
|
94
112
|
}
|
|
95
113
|
|
|
@@ -156,12 +174,14 @@ class RemoteCommandController {
|
|
|
156
174
|
key: command.key,
|
|
157
175
|
handler: handleNextTrackCommand,
|
|
158
176
|
)
|
|
177
|
+
center.nextTrackCommand.isEnabled = canNext
|
|
159
178
|
case .previous:
|
|
160
179
|
enableRemoteCommand(
|
|
161
180
|
center.previousTrackCommand,
|
|
162
181
|
key: command.key,
|
|
163
182
|
handler: handlePreviousTrackCommand,
|
|
164
183
|
)
|
|
184
|
+
center.previousTrackCommand.isEnabled = canPrevious
|
|
165
185
|
case .changePlaybackPosition:
|
|
166
186
|
enableRemoteCommand(
|
|
167
187
|
center.changePlaybackPositionCommand,
|
|
@@ -182,11 +202,6 @@ class RemoteCommandController {
|
|
|
182
202
|
key: command.key,
|
|
183
203
|
handler: handleSkipBackwardCommand,
|
|
184
204
|
)
|
|
185
|
-
case let .like(isActive, localizedTitle, localizedShortTitle):
|
|
186
|
-
center.likeCommand.isActive = isActive
|
|
187
|
-
center.likeCommand.localizedTitle = localizedTitle
|
|
188
|
-
center.likeCommand.localizedShortTitle = localizedShortTitle
|
|
189
|
-
enableRemoteCommand(center.likeCommand, key: command.key, handler: handleLikeCommand)
|
|
190
205
|
case .changeRepeatMode:
|
|
191
206
|
enableRemoteCommand(
|
|
192
207
|
center.changeRepeatModeCommand,
|
|
@@ -229,8 +244,6 @@ class RemoteCommandController {
|
|
|
229
244
|
disableRemoteCommand(center.skipForwardCommand, key: command.key)
|
|
230
245
|
case .skipBackward:
|
|
231
246
|
disableRemoteCommand(center.skipBackwardCommand, key: command.key)
|
|
232
|
-
case .like:
|
|
233
|
-
disableRemoteCommand(center.likeCommand, key: command.key)
|
|
234
247
|
case .changeRepeatMode:
|
|
235
248
|
disableRemoteCommand(center.changeRepeatModeCommand, key: command.key)
|
|
236
249
|
case .changeShuffleMode:
|
|
@@ -244,14 +257,25 @@ class RemoteCommandController {
|
|
|
244
257
|
|
|
245
258
|
/// Updates the repeat mode state shown on CarPlay and lock screen
|
|
246
259
|
func updateRepeatMode(_ mode: RepeatMode) {
|
|
260
|
+
repeatMode = mode
|
|
247
261
|
center.changeRepeatModeCommand.currentRepeatType = mode.mpRepeatType
|
|
248
262
|
}
|
|
249
263
|
|
|
250
264
|
/// Updates the shuffle mode state shown on CarPlay and lock screen
|
|
251
265
|
func updateShuffleMode(_ enabled: Bool) {
|
|
266
|
+
shuffleEnabled = enabled
|
|
252
267
|
center.changeShuffleModeCommand.currentShuffleType = enabled.mpShuffleType
|
|
253
268
|
}
|
|
254
269
|
|
|
270
|
+
/// Greys out next/previous (lock screen / Control Center / CarPlay) when the
|
|
271
|
+
/// queue has nowhere to skip. Applied live when those commands are configured.
|
|
272
|
+
func setSkipAvailability(canNext: Bool, canPrevious: Bool) {
|
|
273
|
+
self.canNext = canNext
|
|
274
|
+
self.canPrevious = canPrevious
|
|
275
|
+
if enabledCommands.contains(.next) { center.nextTrackCommand.isEnabled = canNext }
|
|
276
|
+
if enabledCommands.contains(.previous) { center.previousTrackCommand.isEnabled = canPrevious }
|
|
277
|
+
}
|
|
278
|
+
|
|
255
279
|
// MARK: - Handlers
|
|
256
280
|
|
|
257
281
|
lazy var handlePlayCommand: RemoteCommandHandler = handlePlayCommandDefault
|
|
@@ -266,7 +290,6 @@ class RemoteCommandController {
|
|
|
266
290
|
lazy var handleNextTrackCommand: RemoteCommandHandler = handleNextTrackCommandDefault
|
|
267
291
|
lazy var handlePreviousTrackCommand: RemoteCommandHandler =
|
|
268
292
|
handlePreviousTrackCommandDefault
|
|
269
|
-
lazy var handleLikeCommand: RemoteCommandHandler = handleLikeCommandDefault
|
|
270
293
|
lazy var handleChangeRepeatModeCommand: RemoteCommandHandler =
|
|
271
294
|
handleChangeRepeatModeCommandDefault
|
|
272
295
|
lazy var handleChangeShuffleModeCommand: RemoteCommandHandler =
|
|
@@ -352,13 +375,6 @@ class RemoteCommandController {
|
|
|
352
375
|
return MPRemoteCommandHandlerStatus.success
|
|
353
376
|
}
|
|
354
377
|
|
|
355
|
-
private func handleLikeCommandDefault(event _: MPRemoteCommandEvent)
|
|
356
|
-
-> MPRemoteCommandHandlerStatus
|
|
357
|
-
{
|
|
358
|
-
callbacks?.remoteLike()
|
|
359
|
-
return MPRemoteCommandHandlerStatus.success
|
|
360
|
-
}
|
|
361
|
-
|
|
362
378
|
private func handleChangeRepeatModeCommandDefault(event: MPRemoteCommandEvent)
|
|
363
379
|
-> MPRemoteCommandHandlerStatus
|
|
364
380
|
{
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import Testing
|
|
2
|
+
|
|
3
|
+
@testable import AudioBrowserTestable
|
|
4
|
+
|
|
5
|
+
@Suite("AirPlayStallJudgement")
|
|
6
|
+
struct AirPlayStallJudgementTests {
|
|
7
|
+
/// The exact transition Pocket Casts recovers from: over AirPlay, AVPlayer
|
|
8
|
+
/// drops .waitingToPlayAtSpecifiedRate(.noItemToPlay) → .paused while still
|
|
9
|
+
/// meant to play. That, and only that, should nudge.
|
|
10
|
+
private func judge(
|
|
11
|
+
previous: PlayerTimeControlStatus? = .waitingToPlayAtSpecifiedRate,
|
|
12
|
+
current: PlayerTimeControlStatus = .paused,
|
|
13
|
+
reasonWasNoItemToPlay: Bool = true,
|
|
14
|
+
isAirPlay: Bool = true,
|
|
15
|
+
playWhenReady: Bool = true,
|
|
16
|
+
) -> AirPlayStallJudgement {
|
|
17
|
+
AirPlayStallJudgement(
|
|
18
|
+
previous: previous,
|
|
19
|
+
current: current,
|
|
20
|
+
previousWaitingReasonWasNoItemToPlay: reasonWasNoItemToPlay,
|
|
21
|
+
isAirPlay: isAirPlay,
|
|
22
|
+
playWhenReady: playWhenReady,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Test func exactTransition_nudges() {
|
|
27
|
+
#expect(judge().shouldNudge)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Test func notAirPlay_doesNotNudge() {
|
|
31
|
+
#expect(!judge(isAirPlay: false).shouldNudge)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Test func notPlayWhenReady_doesNotNudge() {
|
|
35
|
+
#expect(!judge(playWhenReady: false).shouldNudge)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Test func previousNotWaiting_doesNotNudge() {
|
|
39
|
+
#expect(!judge(previous: .playing).shouldNudge)
|
|
40
|
+
#expect(!judge(previous: nil).shouldNudge)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Test func currentNotPaused_doesNotNudge() {
|
|
44
|
+
#expect(!judge(current: .playing).shouldNudge)
|
|
45
|
+
#expect(!judge(current: .waitingToPlayAtSpecifiedRate).shouldNudge)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Test func reasonNotNoItemToPlay_doesNotNudge() {
|
|
49
|
+
// A normal stall (.toMinimizeStalls etc.) landing in paused isn't the bug.
|
|
50
|
+
#expect(!judge(reasonWasNoItemToPlay: false).shouldNudge)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -29,6 +29,14 @@ import Testing
|
|
|
29
29
|
#expect(result == "http://example.com/api")
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
@Test func buildUrlEmptyPathReturnsBaseWithoutTrailingSlash() {
|
|
33
|
+
// An endpoint whose baseUrl already includes the full path (e.g. search,
|
|
34
|
+
// `https://host/api/search`) passes an empty path — the base IS the URL, and
|
|
35
|
+
// must not gain a dangling trailing slash.
|
|
36
|
+
let result = BrowserPathHelper.buildUrl(baseUrl: "http://example.com/api/search", path: "")
|
|
37
|
+
#expect(result == "http://example.com/api/search")
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
// MARK: - appendQuery
|
|
33
41
|
|
|
34
42
|
@Test func appendQueryAddsParamsWithQuestionMark() {
|
|
@@ -108,3 +116,23 @@ import Testing
|
|
|
108
116
|
@Test func isContextualReturnsTrueWithAmpersandSeparator() {
|
|
109
117
|
#expect(BrowserPathHelper.isContextual("/lib?q=1&__trackId=x") == true)
|
|
110
118
|
}
|
|
119
|
+
|
|
120
|
+
// MARK: - containsSegment
|
|
121
|
+
|
|
122
|
+
@Test func containsSegmentMatchesFullSegments() {
|
|
123
|
+
let path = "/listen/amsterdam-funk-channel/Gw0LGB8j"
|
|
124
|
+
#expect(BrowserPathHelper.containsSegment(path, "Gw0LGB8j"))
|
|
125
|
+
#expect(BrowserPathHelper.containsSegment(path, "amsterdam-funk-channel"))
|
|
126
|
+
#expect(BrowserPathHelper.containsSegment(path, "listen"))
|
|
127
|
+
#expect(BrowserPathHelper.containsSegment("/listen/x/Gw0LGB8j?hl=en", "Gw0LGB8j"))
|
|
128
|
+
#expect(BrowserPathHelper.containsSegment("/listen/x/Gw0LGB8j#frag", "Gw0LGB8j"))
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@Test func containsSegmentRejectsPartialAndMissing() {
|
|
132
|
+
let path = "/listen/amsterdam-funk-channel/Gw0LGB8j"
|
|
133
|
+
#expect(!BrowserPathHelper.containsSegment(path, "Gw0LGB8"))
|
|
134
|
+
#expect(!BrowserPathHelper.containsSegment(path, "funk"))
|
|
135
|
+
#expect(!BrowserPathHelper.containsSegment(path, "msterdam-funk-channe"))
|
|
136
|
+
#expect(!BrowserPathHelper.containsSegment(path, "NopeNope"))
|
|
137
|
+
#expect(!BrowserPathHelper.containsSegment(path, ""))
|
|
138
|
+
}
|