@5stones/react-native-audio-browser 0.1.0
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 +43 -0
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/android/CMakeLists.txt +32 -0
- package/android/build.gradle +210 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +36 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +1191 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +21 -0
- package/android/src/main/java/com/audiobrowser/Callbacks.kt +92 -0
- package/android/src/main/java/com/audiobrowser/HeadlessTaskService.kt +59 -0
- package/android/src/main/java/com/audiobrowser/Service.kt +336 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +1169 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +103 -0
- package/android/src/main/java/com/audiobrowser/browser/RouteMatch.kt +9 -0
- package/android/src/main/java/com/audiobrowser/browser/SimpleRouter.kt +150 -0
- package/android/src/main/java/com/audiobrowser/extension/EnumExtensions.kt +5 -0
- package/android/src/main/java/com/audiobrowser/extension/NumberExt.kt +13 -0
- package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +171 -0
- package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +251 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +80 -0
- package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +101 -0
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +125 -0
- package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +256 -0
- package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +163 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +177 -0
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +580 -0
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +578 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +58 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +245 -0
- package/android/src/main/java/com/audiobrowser/player/Player.kt +1509 -0
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +230 -0
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +191 -0
- package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +80 -0
- package/android/src/main/java/com/audiobrowser/util/AndroidAudioContentTypeFactory.kt +17 -0
- package/android/src/main/java/com/audiobrowser/util/BatteryOptimizationHelper.kt +95 -0
- package/android/src/main/java/com/audiobrowser/util/BatteryWarningStore.kt +38 -0
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +155 -0
- package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +390 -0
- package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +197 -0
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +75 -0
- package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +97 -0
- package/android/src/main/java/com/audiobrowser/util/NetworkConnectivityMonitor.kt +121 -0
- package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +25 -0
- package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +72 -0
- package/android/src/main/java/com/audiobrowser/util/RepeatModeFactory.kt +22 -0
- package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +36 -0
- package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +130 -0
- package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +50 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +125 -0
- package/android/src/main/res/values/strings.xml +6 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +273 -0
- package/android/src/test/java/com/audiobrowser/browser/SimpleBrowserTest.kt +33 -0
- package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +156 -0
- package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +240 -0
- package/ios/Bridge.h +8 -0
- package/ios/Browser/BrowserConfig.swift +85 -0
- package/ios/Browser/BrowserManager.swift +985 -0
- package/ios/Browser/BrowserPathHelper.swift +156 -0
- package/ios/Browser/JsonModels.swift +165 -0
- package/ios/Browser/SimpleRouter.swift +184 -0
- package/ios/CarPlay/CarPlayController.swift +1342 -0
- package/ios/CarPlay/RNABCarPlaySceneDelegate.h +15 -0
- package/ios/CarPlay/RNABCarPlaySceneDelegate.m +59 -0
- package/ios/CarPlay/Track+CarPlay.swift +49 -0
- package/ios/Extension/Capability+RemoteCommand.swift +76 -0
- package/ios/Extension/ChapterMetadata+AVFoundation.swift +37 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +126 -0
- package/ios/Extension/Track+AVPlayer.swift +68 -0
- package/ios/Extension/TrackMetadata+AVFoundation.swift +128 -0
- package/ios/Http/HttpClient.swift +237 -0
- package/ios/HybridAudioBrowser.swift +1309 -0
- package/ios/Model/MediaURL.swift +66 -0
- package/ios/Model/PlayerUpdateOptions.swift +116 -0
- package/ios/Model/RemoteCommand.swift +71 -0
- package/ios/Model/SourceType.swift +6 -0
- package/ios/Model/TrackPlayerError.swift +69 -0
- package/ios/NowPlayingInfo/MediaItemProperty.swift +78 -0
- package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +9 -0
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +283 -0
- package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +6 -0
- package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +220 -0
- package/ios/Observer/PlayerItemNotificationObserver.swift +83 -0
- package/ios/Observer/PlayerItemPropertyObserver.swift +110 -0
- package/ios/Observer/PlayerStateObserver.swift +52 -0
- package/ios/Observer/PlayerTimeObserver.swift +109 -0
- package/ios/Option/PitchAlgorithms.swift +17 -0
- package/ios/Option/SessionCategories.swift +100 -0
- package/ios/Option/TimeEventFrequency.swift +18 -0
- package/ios/Player/PlaybackProgressUpdateManager.swift +60 -0
- package/ios/Player/PlayingStateManager.swift +29 -0
- package/ios/Player/RetryManager.swift +281 -0
- package/ios/Player/ShuffleOrder.swift +191 -0
- package/ios/Player/SleepTimerManager.swift +137 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +400 -0
- package/ios/Support/RNTrackPlayer-Bridging-Header.h +7 -0
- package/ios/TrackPlayer.swift +1590 -0
- package/ios/TrackPlayerCallbacks.swift +121 -0
- package/ios/Util/Emitter.swift +46 -0
- package/ios/Util/LRUCache.swift +182 -0
- package/ios/Util/MetadataAdapter.swift +131 -0
- package/ios/Util/NetworkMonitor.swift +68 -0
- package/ios/Util/OnceValue.swift +70 -0
- package/ios/Util/SVGProcessor.swift +56 -0
- package/lib/commonjs/AudioBrowser.js +50 -0
- package/lib/commonjs/AudioBrowser.js.map +1 -0
- package/lib/commonjs/features/battery.js +154 -0
- package/lib/commonjs/features/battery.js.map +1 -0
- package/lib/commonjs/features/browser.js +271 -0
- package/lib/commonjs/features/browser.js.map +1 -0
- package/lib/commonjs/features/equalizer.js +69 -0
- package/lib/commonjs/features/equalizer.js.map +1 -0
- package/lib/commonjs/features/errors.js +165 -0
- package/lib/commonjs/features/errors.js.map +1 -0
- package/lib/commonjs/features/favorites.js +101 -0
- package/lib/commonjs/features/favorites.js.map +1 -0
- package/lib/commonjs/features/index.js +160 -0
- package/lib/commonjs/features/index.js.map +1 -0
- package/lib/commonjs/features/metadata.js +54 -0
- package/lib/commonjs/features/metadata.js.map +1 -0
- package/lib/commonjs/features/network.js +40 -0
- package/lib/commonjs/features/network.js.map +1 -0
- package/lib/commonjs/features/nowPlaying.js +61 -0
- package/lib/commonjs/features/nowPlaying.js.map +1 -0
- package/lib/commonjs/features/output.js +54 -0
- package/lib/commonjs/features/output.js.map +1 -0
- package/lib/commonjs/features/playback/controls.js +79 -0
- package/lib/commonjs/features/playback/controls.js.map +1 -0
- package/lib/commonjs/features/playback/index.js +83 -0
- package/lib/commonjs/features/playback/index.js.map +1 -0
- package/lib/commonjs/features/playback/playWhenReady.js +55 -0
- package/lib/commonjs/features/playback/playWhenReady.js.map +1 -0
- package/lib/commonjs/features/playback/playing.js +41 -0
- package/lib/commonjs/features/playback/playing.js.map +1 -0
- package/lib/commonjs/features/playback/progress.js +104 -0
- package/lib/commonjs/features/playback/progress.js.map +1 -0
- package/lib/commonjs/features/playback/rate.js +29 -0
- package/lib/commonjs/features/playback/rate.js.map +1 -0
- package/lib/commonjs/features/playback/state.js +62 -0
- package/lib/commonjs/features/playback/state.js.map +1 -0
- package/lib/commonjs/features/playback/volume.js +68 -0
- package/lib/commonjs/features/playback/volume.js.map +1 -0
- package/lib/commonjs/features/player/index.js +28 -0
- package/lib/commonjs/features/player/index.js.map +1 -0
- package/lib/commonjs/features/player/options.js +182 -0
- package/lib/commonjs/features/player/options.js.map +1 -0
- package/lib/commonjs/features/player/setup.js +143 -0
- package/lib/commonjs/features/player/setup.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +52 -0
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -0
- package/lib/commonjs/features/queue/index.js +50 -0
- package/lib/commonjs/features/queue/index.js.map +1 -0
- package/lib/commonjs/features/queue/queue.js +177 -0
- package/lib/commonjs/features/queue/queue.js.map +1 -0
- package/lib/commonjs/features/queue/repeatMode.js +58 -0
- package/lib/commonjs/features/queue/repeatMode.js.map +1 -0
- package/lib/commonjs/features/queue/shuffle.js +57 -0
- package/lib/commonjs/features/queue/shuffle.js.map +1 -0
- package/lib/commonjs/features/rating.js +2 -0
- package/lib/commonjs/features/rating.js.map +1 -0
- package/lib/commonjs/features/remoteControls.js +286 -0
- package/lib/commonjs/features/remoteControls.js.map +1 -0
- package/lib/commonjs/features/sleepTimer.js +164 -0
- package/lib/commonjs/features/sleepTimer.js.map +1 -0
- package/lib/commonjs/index.js +22 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/native.js +9 -0
- package/lib/commonjs/native.js.map +1 -0
- package/lib/commonjs/native.web.js +10 -0
- package/lib/commonjs/native.web.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/specs/audio-browser.nitro.js +6 -0
- package/lib/commonjs/specs/audio-browser.nitro.js.map +1 -0
- package/lib/commonjs/types/browser-native.js +6 -0
- package/lib/commonjs/types/browser-native.js.map +1 -0
- package/lib/commonjs/types/browser-nodes.js +6 -0
- package/lib/commonjs/types/browser-nodes.js.map +1 -0
- package/lib/commonjs/types/browser.js +6 -0
- package/lib/commonjs/types/browser.js.map +1 -0
- package/lib/commonjs/types/index.js +28 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/types/player.js +2 -0
- package/lib/commonjs/types/player.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +58 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -0
- package/lib/commonjs/utils/NativeUpdatedValue.js +59 -0
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -0
- package/lib/commonjs/utils/resolveAssetSource.js +11 -0
- package/lib/commonjs/utils/resolveAssetSource.js.map +1 -0
- package/lib/commonjs/utils/useDebug.js +221 -0
- package/lib/commonjs/utils/useDebug.js.map +1 -0
- package/lib/commonjs/utils/useNativeUpdatedValue.js +44 -0
- package/lib/commonjs/utils/useNativeUpdatedValue.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +668 -0
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -0
- package/lib/commonjs/web/SimpleRouter.js +144 -0
- package/lib/commonjs/web/SimpleRouter.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/Event.js +19 -0
- package/lib/commonjs/web/TrackPlayer/Event.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/Player.js +276 -0
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +284 -0
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js +12 -0
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/SetupNotCalledError.js +13 -0
- package/lib/commonjs/web/TrackPlayer/SetupNotCalledError.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js +75 -0
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/State.js +18 -0
- package/lib/commonjs/web/TrackPlayer/State.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/index.js +52 -0
- package/lib/commonjs/web/TrackPlayer/index.js.map +1 -0
- package/lib/commonjs/web/browser/BrowserManager.js +594 -0
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -0
- package/lib/commonjs/web/browser/FavoriteManager.js +80 -0
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -0
- package/lib/commonjs/web/browser/NavigationErrorManager.js +106 -0
- package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -0
- package/lib/commonjs/web/browser/SearchManager.js +80 -0
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -0
- package/lib/commonjs/web/http/HttpClient.js +81 -0
- package/lib/commonjs/web/http/HttpClient.js.map +1 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js +294 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +70 -0
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -0
- package/lib/commonjs/web/player/OptionsManager.js +88 -0
- package/lib/commonjs/web/player/OptionsManager.js.map +1 -0
- package/lib/commonjs/web/util/BrowserPathHelper.js +138 -0
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -0
- package/lib/commonjs/web/util/shuffle.js +21 -0
- package/lib/commonjs/web/util/shuffle.js.map +1 -0
- package/lib/module/AudioBrowser.js +7 -0
- package/lib/module/AudioBrowser.js.map +1 -0
- package/lib/module/features/battery.js +144 -0
- package/lib/module/features/battery.js.map +1 -0
- package/lib/module/features/browser.js +257 -0
- package/lib/module/features/browser.js.map +1 -0
- package/lib/module/features/equalizer.js +60 -0
- package/lib/module/features/equalizer.js.map +1 -0
- package/lib/module/features/errors.js +156 -0
- package/lib/module/features/errors.js.map +1 -0
- package/lib/module/features/favorites.js +95 -0
- package/lib/module/features/favorites.js.map +1 -0
- package/lib/module/features/index.js +26 -0
- package/lib/module/features/index.js.map +1 -0
- package/lib/module/features/metadata.js +51 -0
- package/lib/module/features/metadata.js.map +1 -0
- package/lib/module/features/network.js +35 -0
- package/lib/module/features/network.js.map +1 -0
- package/lib/module/features/nowPlaying.js +54 -0
- package/lib/module/features/nowPlaying.js.map +1 -0
- package/lib/module/features/output.js +47 -0
- package/lib/module/features/output.js.map +1 -0
- package/lib/module/features/playback/controls.js +69 -0
- package/lib/module/features/playback/controls.js.map +1 -0
- package/lib/module/features/playback/index.js +10 -0
- package/lib/module/features/playback/index.js.map +1 -0
- package/lib/module/features/playback/playWhenReady.js +49 -0
- package/lib/module/features/playback/playWhenReady.js.map +1 -0
- package/lib/module/features/playback/playing.js +36 -0
- package/lib/module/features/playback/playing.js.map +1 -0
- package/lib/module/features/playback/progress.js +98 -0
- package/lib/module/features/playback/progress.js.map +1 -0
- package/lib/module/features/playback/rate.js +25 -0
- package/lib/module/features/playback/rate.js.map +1 -0
- package/lib/module/features/playback/state.js +57 -0
- package/lib/module/features/playback/state.js.map +1 -0
- package/lib/module/features/playback/volume.js +60 -0
- package/lib/module/features/playback/volume.js.map +1 -0
- package/lib/module/features/player/index.js +5 -0
- package/lib/module/features/player/index.js.map +1 -0
- package/lib/module/features/player/options.js +176 -0
- package/lib/module/features/player/options.js.map +1 -0
- package/lib/module/features/player/setup.js +140 -0
- package/lib/module/features/player/setup.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +46 -0
- package/lib/module/features/queue/activeTrack.js.map +1 -0
- package/lib/module/features/queue/index.js +7 -0
- package/lib/module/features/queue/index.js.map +1 -0
- package/lib/module/features/queue/queue.js +162 -0
- package/lib/module/features/queue/queue.js.map +1 -0
- package/lib/module/features/queue/repeatMode.js +52 -0
- package/lib/module/features/queue/repeatMode.js.map +1 -0
- package/lib/module/features/queue/shuffle.js +50 -0
- package/lib/module/features/queue/shuffle.js.map +1 -0
- package/lib/module/features/rating.js +2 -0
- package/lib/module/features/rating.js.map +1 -0
- package/lib/module/features/remoteControls.js +275 -0
- package/lib/module/features/remoteControls.js.map +1 -0
- package/lib/module/features/sleepTimer.js +155 -0
- package/lib/module/features/sleepTimer.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native.js +5 -0
- package/lib/module/native.js.map +1 -0
- package/lib/module/native.web.js +7 -0
- package/lib/module/native.web.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/audio-browser.nitro.js +4 -0
- package/lib/module/specs/audio-browser.nitro.js.map +1 -0
- package/lib/module/types/browser-native.js +4 -0
- package/lib/module/types/browser-native.js.map +1 -0
- package/lib/module/types/browser-nodes.js +4 -0
- package/lib/module/types/browser-nodes.js.map +1 -0
- package/lib/module/types/browser.js +4 -0
- package/lib/module/types/browser.js.map +1 -0
- package/lib/module/types/index.js +5 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/types/player.js +2 -0
- package/lib/module/types/player.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +53 -0
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -0
- package/lib/module/utils/NativeUpdatedValue.js +54 -0
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -0
- package/lib/module/utils/resolveAssetSource.js +7 -0
- package/lib/module/utils/resolveAssetSource.js.map +1 -0
- package/lib/module/utils/useDebug.js +218 -0
- package/lib/module/utils/useDebug.js.map +1 -0
- package/lib/module/utils/useNativeUpdatedValue.js +40 -0
- package/lib/module/utils/useNativeUpdatedValue.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +664 -0
- package/lib/module/web/NativeAudioBrowser.js.map +1 -0
- package/lib/module/web/SimpleRouter.js +139 -0
- package/lib/module/web/SimpleRouter.js.map +1 -0
- package/lib/module/web/TrackPlayer/Event.js +15 -0
- package/lib/module/web/TrackPlayer/Event.js.map +1 -0
- package/lib/module/web/TrackPlayer/Player.js +271 -0
- package/lib/module/web/TrackPlayer/Player.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js +279 -0
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
- package/lib/module/web/TrackPlayer/RepeatMode.js +8 -0
- package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -0
- package/lib/module/web/TrackPlayer/SetupNotCalledError.js +8 -0
- package/lib/module/web/TrackPlayer/SetupNotCalledError.js.map +1 -0
- package/lib/module/web/TrackPlayer/SleepTimer.js +70 -0
- package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -0
- package/lib/module/web/TrackPlayer/State.js +14 -0
- package/lib/module/web/TrackPlayer/State.js.map +1 -0
- package/lib/module/web/TrackPlayer/index.js +7 -0
- package/lib/module/web/TrackPlayer/index.js.map +1 -0
- package/lib/module/web/browser/BrowserManager.js +590 -0
- package/lib/module/web/browser/BrowserManager.js.map +1 -0
- package/lib/module/web/browser/FavoriteManager.js +75 -0
- package/lib/module/web/browser/FavoriteManager.js.map +1 -0
- package/lib/module/web/browser/NavigationErrorManager.js +101 -0
- package/lib/module/web/browser/NavigationErrorManager.js.map +1 -0
- package/lib/module/web/browser/SearchManager.js +76 -0
- package/lib/module/web/browser/SearchManager.js.map +1 -0
- package/lib/module/web/http/HttpClient.js +76 -0
- package/lib/module/web/http/HttpClient.js.map +1 -0
- package/lib/module/web/http/RequestConfigBuilder.js +291 -0
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +65 -0
- package/lib/module/web/player/NowPlayingManager.js.map +1 -0
- package/lib/module/web/player/OptionsManager.js +83 -0
- package/lib/module/web/player/OptionsManager.js.map +1 -0
- package/lib/module/web/util/BrowserPathHelper.js +134 -0
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -0
- package/lib/module/web/util/shuffle.js +17 -0
- package/lib/module/web/util/shuffle.js.map +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +5 -0
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -0
- package/lib/typescript/src/features/battery.d.ts +112 -0
- package/lib/typescript/src/features/battery.d.ts.map +1 -0
- package/lib/typescript/src/features/browser.d.ts +68 -0
- package/lib/typescript/src/features/browser.d.ts.map +1 -0
- package/lib/typescript/src/features/equalizer.d.ts +35 -0
- package/lib/typescript/src/features/equalizer.d.ts.map +1 -0
- package/lib/typescript/src/features/errors.d.ts +136 -0
- package/lib/typescript/src/features/errors.d.ts.map +1 -0
- package/lib/typescript/src/features/favorites.d.ts +84 -0
- package/lib/typescript/src/features/favorites.d.ts.map +1 -0
- package/lib/typescript/src/features/index.d.ts +23 -0
- package/lib/typescript/src/features/index.d.ts.map +1 -0
- package/lib/typescript/src/features/metadata.d.ts +103 -0
- package/lib/typescript/src/features/metadata.d.ts.map +1 -0
- package/lib/typescript/src/features/network.d.ts +18 -0
- package/lib/typescript/src/features/network.d.ts.map +1 -0
- package/lib/typescript/src/features/nowPlaying.d.ts +36 -0
- package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -0
- package/lib/typescript/src/features/output.d.ts +28 -0
- package/lib/typescript/src/features/output.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/controls.d.ts +40 -0
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/index.d.ts +8 -0
- package/lib/typescript/src/features/playback/index.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/playWhenReady.d.ts +30 -0
- package/lib/typescript/src/features/playback/playWhenReady.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/playing.d.ts +21 -0
- package/lib/typescript/src/features/playback/playing.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/progress.d.ts +51 -0
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/rate.d.ts +12 -0
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/state.d.ts +43 -0
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/volume.d.ts +32 -0
- package/lib/typescript/src/features/playback/volume.d.ts.map +1 -0
- package/lib/typescript/src/features/player/index.d.ts +3 -0
- package/lib/typescript/src/features/player/index.d.ts.map +1 -0
- package/lib/typescript/src/features/player/options.d.ts +413 -0
- package/lib/typescript/src/features/player/options.d.ts.map +1 -0
- package/lib/typescript/src/features/player/setup.d.ts +471 -0
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +38 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/index.d.ts +5 -0
- package/lib/typescript/src/features/queue/index.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/queue.d.ts +111 -0
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/repeatMode.d.ts +34 -0
- package/lib/typescript/src/features/queue/repeatMode.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/shuffle.d.ts +27 -0
- package/lib/typescript/src/features/queue/shuffle.d.ts.map +1 -0
- package/lib/typescript/src/features/rating.d.ts +14 -0
- package/lib/typescript/src/features/rating.d.ts.map +1 -0
- package/lib/typescript/src/features/remoteControls.d.ts +164 -0
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -0
- package/lib/typescript/src/features/sleepTimer.d.ts +80 -0
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/native.d.ts +3 -0
- package/lib/typescript/src/native.d.ts.map +1 -0
- package/lib/typescript/src/native.web.d.ts +3 -0
- package/lib/typescript/src/native.web.d.ts.map +1 -0
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts +242 -0
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +39 -0
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-nodes.d.ts +153 -0
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -0
- package/lib/typescript/src/types/browser.d.ts +710 -0
- package/lib/typescript/src/types/browser.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +3 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -0
- package/lib/typescript/src/types/player.d.ts +64 -0
- package/lib/typescript/src/types/player.d.ts.map +1 -0
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +35 -0
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -0
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +39 -0
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts +4 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -0
- package/lib/typescript/src/utils/useDebug.d.ts +65 -0
- package/lib/typescript/src/utils/useDebug.d.ts.map +1 -0
- package/lib/typescript/src/utils/useNativeUpdatedValue.d.ts +14 -0
- package/lib/typescript/src/utils/useNativeUpdatedValue.d.ts.map +1 -0
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts +176 -0
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -0
- package/lib/typescript/src/web/SimpleRouter.d.ts +40 -0
- package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts +11 -0
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts +71 -0
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +39 -0
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +6 -0
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +4 -0
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +34 -0
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/State.d.ts +13 -0
- package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +1 -0
- package/lib/typescript/src/web/TrackPlayer/index.d.ts +5 -0
- package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +1 -0
- package/lib/typescript/src/web/browser/BrowserManager.d.ts +154 -0
- package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +1 -0
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts +42 -0
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +1 -0
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +40 -0
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +1 -0
- package/lib/typescript/src/web/browser/SearchManager.d.ts +22 -0
- package/lib/typescript/src/web/browser/SearchManager.d.ts.map +1 -0
- package/lib/typescript/src/web/http/HttpClient.d.ts +25 -0
- package/lib/typescript/src/web/http/HttpClient.d.ts.map +1 -0
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +98 -0
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +1 -0
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts +34 -0
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +1 -0
- package/lib/typescript/src/web/player/OptionsManager.d.ts +32 -0
- package/lib/typescript/src/web/player/OptionsManager.d.ts.map +1 -0
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +69 -0
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +1 -0
- package/lib/typescript/src/web/util/shuffle.d.ts +8 -0
- package/lib/typescript/src/web/util/shuffle.d.ts.map +1 -0
- package/nitro.json +24 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +88 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.gradle +27 -0
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +124 -0
- package/nitrogen/generated/android/AudioBrowserOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +68 -0
- package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +61 -0
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +86 -0
- package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +62 -0
- package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +86 -0
- package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +62 -0
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +163 -0
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +62 -0
- package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +58 -0
- package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JBrowseError.hpp +57 -0
- package/nitrogen/generated/android/c++/JBrowseResult.cpp +26 -0
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +83 -0
- package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +76 -0
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +65 -0
- package/nitrogen/generated/android/c++/JChapterMetadata.hpp +70 -0
- package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +125 -0
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +71 -0
- package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +72 -0
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +61 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +111 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +134 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +143 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +136 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +143 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +157 -0
- package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +88 -0
- package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +89 -0
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +98 -0
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +88 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +87 -0
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_double.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +89 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +84 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +98 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +105 -0
- package/nitrogen/generated/android/c++/JHeartRating.hpp +57 -0
- package/nitrogen/generated/android/c++/JHttpMethod.hpp +74 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +1811 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +250 -0
- package/nitrogen/generated/android/c++/JIOSCategory.hpp +71 -0
- package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +80 -0
- package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +74 -0
- package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +62 -0
- package/nitrogen/generated/android/c++/JImageContext.hpp +61 -0
- package/nitrogen/generated/android/c++/JImageQueryParams.hpp +62 -0
- package/nitrogen/generated/android/c++/JImageSource.hpp +86 -0
- package/nitrogen/generated/android/c++/JIosOutput.hpp +67 -0
- package/nitrogen/generated/android/c++/JIosOutputType.hpp +86 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +153 -0
- package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +69 -0
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +196 -0
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +147 -0
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +105 -0
- package/nitrogen/generated/android/c++/JNavigationError.hpp +72 -0
- package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +62 -0
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +68 -0
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +86 -0
- package/nitrogen/generated/android/c++/JNotificationButton.hpp +68 -0
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +94 -0
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +104 -0
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +62 -0
- package/nitrogen/generated/android/c++/JOptions.hpp +97 -0
- package/nitrogen/generated/android/c++/JPartialAndroidSetupPlayerOptions.hpp +104 -0
- package/nitrogen/generated/android/c++/JPartialIOSSetupPlayerOptions.hpp +100 -0
- package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +96 -0
- package/nitrogen/generated/android/c++/JPercentageRating.hpp +57 -0
- package/nitrogen/generated/android/c++/JPlayback.hpp +66 -0
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +83 -0
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +61 -0
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +60 -0
- package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +69 -0
- package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +61 -0
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +80 -0
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +101 -0
- package/nitrogen/generated/android/c++/JPlayingState.hpp +61 -0
- package/nitrogen/generated/android/c++/JProgress.hpp +65 -0
- package/nitrogen/generated/android/c++/JRatingType.hpp +74 -0
- package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +62 -0
- package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +66 -0
- package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +57 -0
- package/nitrogen/generated/android/c++/JRepeatMode.hpp +62 -0
- package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +58 -0
- package/nitrogen/generated/android/c++/JRequestConfig.hpp +115 -0
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +154 -0
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +61 -0
- package/nitrogen/generated/android/c++/JSearchMode.hpp +71 -0
- package/nitrogen/generated/android/c++/JSearchParams.hpp +84 -0
- package/nitrogen/generated/android/c++/JSleepTimer.cpp +30 -0
- package/nitrogen/generated/android/c++/JSleepTimer.hpp +88 -0
- package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +57 -0
- package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +57 -0
- package/nitrogen/generated/android/c++/JStarRating.hpp +57 -0
- package/nitrogen/generated/android/c++/JThumbsRating.hpp +57 -0
- package/nitrogen/generated/android/c++/JTimedMetadata.hpp +74 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +129 -0
- package/nitrogen/generated/android/c++/JTrackMetadata.hpp +118 -0
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +59 -0
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +134 -0
- package/nitrogen/generated/android/c++/JUpdateOptions.hpp +105 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +70 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +70 -0
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +34 -0
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +105 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +69 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidPlayerWakeMode.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AppKilledPlaybackBehavior.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AudioBrowserOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatus.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ChapterMetadata.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.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 +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_IosOutput.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSetRatingEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HeartRating.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HttpMethod.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1137 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategory.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryMode.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryOptions.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryPolicy.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutput.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +30 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +69 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +69 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +63 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialAndroidSetupPlayerOptions.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialIOSSetupPlayerOptions.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PercentageRating.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RatingType.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSetRatingEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatMode.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +89 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +72 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StarRating.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ThumbsRating.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +83 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +85 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout.kt +59 -0
- package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +60 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +407 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +2822 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +300 -0
- package/nitrogen/generated/ios/AudioBrowserAutolinking.mm +33 -0
- package/nitrogen/generated/ios/AudioBrowserAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +1190 -0
- package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +52 -0
- package/nitrogen/generated/ios/swift/AndroidAudioOffloadSettings.swift +85 -0
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +125 -0
- package/nitrogen/generated/ios/swift/AndroidPlayerWakeMode.swift +44 -0
- package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +187 -0
- package/nitrogen/generated/ios/swift/AppKilledPlaybackBehavior.swift +44 -0
- package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +445 -0
- package/nitrogen/generated/ios/swift/BatteryOptimizationStatus.swift +44 -0
- package/nitrogen/generated/ios/swift/BatteryOptimizationStatusChangedEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/BatteryWarningPendingChangedEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/BrowseError.swift +36 -0
- package/nitrogen/generated/ios/swift/BrowseResult.swift +18 -0
- package/nitrogen/generated/ios/swift/BrowserSourceCallbackParam.swift +86 -0
- package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +48 -0
- package/nitrogen/generated/ios/swift/ChapterMetadata.swift +107 -0
- package/nitrogen/generated/ios/swift/EqualizerSettings.swift +168 -0
- package/nitrogen/generated/ios/swift/FavoriteChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +58 -0
- package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.swift +62 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +77 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.swift +62 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.swift +68 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_BatteryOptimizationStatusChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_BatteryWarningPendingChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_EqualizerSettings.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_FavoriteChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_IosOutput.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_NavigationErrorEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_NowPlayingMetadata.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_Options.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_Playback.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackActiveTrackChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackErrorEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackPlayWhenReadyChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackProgressUpdatedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlaybackQueueEndedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_PlayingState.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemoteJumpBackwardEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemoteJumpForwardEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemotePlayIdEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemotePlaySearchEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemoteSeekEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemoteSetRatingEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RemoteSkipEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RepeatModeChangedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RequestConfig.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_TrackMetadata.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_double.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_FormattedNavigationError_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_ResolvedTrack_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_RequestConfig__.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_Track___.swift +67 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError_.swift +59 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_ChapterMetadata_.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_Track_.swift +47 -0
- package/nitrogen/generated/ios/swift/HeartRating.swift +36 -0
- package/nitrogen/generated/ios/swift/HttpMethod.swift +60 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +181 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2352 -0
- package/nitrogen/generated/ios/swift/IOSCategory.swift +56 -0
- package/nitrogen/generated/ios/swift/IOSCategoryMode.swift +68 -0
- package/nitrogen/generated/ios/swift/IOSCategoryOptions.swift +60 -0
- package/nitrogen/generated/ios/swift/IOSCategoryPolicy.swift +44 -0
- package/nitrogen/generated/ios/swift/ImageContext.swift +71 -0
- package/nitrogen/generated/ios/swift/ImageQueryParams.swift +85 -0
- package/nitrogen/generated/ios/swift/ImageSource.swift +139 -0
- package/nitrogen/generated/ios/swift/IosOutput.swift +58 -0
- package/nitrogen/generated/ios/swift/IosOutputType.swift +76 -0
- package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +434 -0
- package/nitrogen/generated/ios/swift/MediaTransformParams.swift +59 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +360 -0
- package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +275 -0
- package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +215 -0
- package/nitrogen/generated/ios/swift/NavigationError.swift +100 -0
- package/nitrogen/generated/ios/swift/NavigationErrorEvent.swift +48 -0
- package/nitrogen/generated/ios/swift/NavigationErrorType.swift +52 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +187 -0
- package/nitrogen/generated/ios/swift/NotificationButton.swift +52 -0
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +159 -0
- package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +351 -0
- package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +85 -0
- package/nitrogen/generated/ios/swift/Options.swift +148 -0
- package/nitrogen/generated/ios/swift/PartialAndroidSetupPlayerOptions.swift +328 -0
- package/nitrogen/generated/ios/swift/PartialIOSSetupPlayerOptions.swift +159 -0
- package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +157 -0
- package/nitrogen/generated/ios/swift/PercentageRating.swift +36 -0
- package/nitrogen/generated/ios/swift/Playback.swift +59 -0
- package/nitrogen/generated/ios/swift/PlaybackActiveTrackChangedEvent.swift +128 -0
- package/nitrogen/generated/ios/swift/PlaybackError.swift +47 -0
- package/nitrogen/generated/ios/swift/PlaybackErrorEvent.swift +48 -0
- package/nitrogen/generated/ios/swift/PlaybackPlayWhenReadyChangedEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/PlaybackProgressUpdatedEvent.swift +69 -0
- package/nitrogen/generated/ios/swift/PlaybackQueueEndedEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/PlaybackState.swift +68 -0
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +385 -0
- package/nitrogen/generated/ios/swift/PlayingState.swift +47 -0
- package/nitrogen/generated/ios/swift/Progress.swift +58 -0
- package/nitrogen/generated/ios/swift/RatingType.swift +60 -0
- package/nitrogen/generated/ios/swift/RemoteJumpBackwardEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RemoteJumpForwardEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RemotePlayIdEvent.swift +59 -0
- package/nitrogen/generated/ios/swift/RemotePlaySearchEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RemoteSeekEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +76 -0
- package/nitrogen/generated/ios/swift/RemoteSkipEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
- package/nitrogen/generated/ios/swift/RepeatModeChangedEvent.swift +36 -0
- package/nitrogen/generated/ios/swift/RequestConfig.swift +298 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +511 -0
- package/nitrogen/generated/ios/swift/RetryConfig.swift +59 -0
- package/nitrogen/generated/ios/swift/SearchMode.swift +56 -0
- package/nitrogen/generated/ios/swift/SearchParams.swift +209 -0
- package/nitrogen/generated/ios/swift/SleepTimer.swift +19 -0
- package/nitrogen/generated/ios/swift/SleepTimerEndOfTrack.swift +36 -0
- package/nitrogen/generated/ios/swift/SleepTimerTime.swift +36 -0
- package/nitrogen/generated/ios/swift/StarRating.swift +36 -0
- package/nitrogen/generated/ios/swift/ThumbsRating.swift +36 -0
- package/nitrogen/generated/ios/swift/TimedMetadata.swift +175 -0
- package/nitrogen/generated/ios/swift/Track.swift +488 -0
- package/nitrogen/generated/ios/swift/TrackMetadata.swift +505 -0
- package/nitrogen/generated/ios/swift/TrackStyle.swift +40 -0
- package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +372 -0
- package/nitrogen/generated/ios/swift/UpdateOptions.swift +215 -0
- package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +20 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +18 -0
- package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +88 -0
- package/nitrogen/generated/shared/c++/AndroidAudioOffloadSettings.hpp +79 -0
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +101 -0
- package/nitrogen/generated/shared/c++/AndroidPlayerWakeMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +101 -0
- package/nitrogen/generated/shared/c++/AppKilledPlaybackBehavior.hpp +80 -0
- package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +133 -0
- package/nitrogen/generated/shared/c++/BatteryOptimizationStatus.hpp +80 -0
- package/nitrogen/generated/shared/c++/BatteryOptimizationStatusChangedEvent.hpp +76 -0
- package/nitrogen/generated/shared/c++/BatteryWarningPendingChangedEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/BrowseError.hpp +75 -0
- package/nitrogen/generated/shared/c++/BrowserSourceCallbackParam.hpp +81 -0
- package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +84 -0
- package/nitrogen/generated/shared/c++/ChapterMetadata.hpp +88 -0
- package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +105 -0
- package/nitrogen/generated/shared/c++/FavoriteChangedEvent.hpp +80 -0
- package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +88 -0
- package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +79 -0
- package/nitrogen/generated/shared/c++/HeartRating.hpp +75 -0
- package/nitrogen/generated/shared/c++/HttpMethod.hpp +96 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +207 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +375 -0
- package/nitrogen/generated/shared/c++/IOSCategory.hpp +92 -0
- package/nitrogen/generated/shared/c++/IOSCategoryMode.hpp +104 -0
- package/nitrogen/generated/shared/c++/IOSCategoryOptions.hpp +96 -0
- package/nitrogen/generated/shared/c++/IOSCategoryPolicy.hpp +80 -0
- package/nitrogen/generated/shared/c++/ImageContext.hpp +79 -0
- package/nitrogen/generated/shared/c++/ImageQueryParams.hpp +80 -0
- package/nitrogen/generated/shared/c++/ImageSource.hpp +91 -0
- package/nitrogen/generated/shared/c++/IosOutput.hpp +85 -0
- package/nitrogen/generated/shared/c++/IosOutputType.hpp +112 -0
- package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +123 -0
- package/nitrogen/generated/shared/c++/MediaTransformParams.hpp +84 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +135 -0
- package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +131 -0
- package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +103 -0
- package/nitrogen/generated/shared/c++/NavigationError.hpp +90 -0
- package/nitrogen/generated/shared/c++/NavigationErrorEvent.hpp +77 -0
- package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +88 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +101 -0
- package/nitrogen/generated/shared/c++/NotificationButton.hpp +88 -0
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +124 -0
- package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +80 -0
- package/nitrogen/generated/shared/c++/Options.hpp +105 -0
- package/nitrogen/generated/shared/c++/PartialAndroidSetupPlayerOptions.hpp +121 -0
- package/nitrogen/generated/shared/c++/PartialIOSSetupPlayerOptions.hpp +103 -0
- package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +96 -0
- package/nitrogen/generated/shared/c++/PercentageRating.hpp +75 -0
- package/nitrogen/generated/shared/c++/Playback.hpp +84 -0
- package/nitrogen/generated/shared/c++/PlaybackActiveTrackChangedEvent.hpp +93 -0
- package/nitrogen/generated/shared/c++/PlaybackError.hpp +79 -0
- package/nitrogen/generated/shared/c++/PlaybackErrorEvent.hpp +77 -0
- package/nitrogen/generated/shared/c++/PlaybackPlayWhenReadyChangedEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/PlaybackProgressUpdatedEvent.hpp +87 -0
- package/nitrogen/generated/shared/c++/PlaybackQueueEndedEvent.hpp +79 -0
- package/nitrogen/generated/shared/c++/PlaybackState.hpp +104 -0
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +119 -0
- package/nitrogen/generated/shared/c++/PlayingState.hpp +79 -0
- package/nitrogen/generated/shared/c++/Progress.hpp +83 -0
- package/nitrogen/generated/shared/c++/RatingType.hpp +96 -0
- package/nitrogen/generated/shared/c++/RemoteJumpBackwardEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/RemoteJumpForwardEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/RemotePlayIdEvent.hpp +80 -0
- package/nitrogen/generated/shared/c++/RemotePlaySearchEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/RemoteSeekEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +86 -0
- package/nitrogen/generated/shared/c++/RemoteSkipEvent.hpp +75 -0
- package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/RepeatModeChangedEvent.hpp +76 -0
- package/nitrogen/generated/shared/c++/RequestConfig.hpp +107 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +153 -0
- package/nitrogen/generated/shared/c++/RetryConfig.hpp +79 -0
- package/nitrogen/generated/shared/c++/SearchMode.hpp +92 -0
- package/nitrogen/generated/shared/c++/SearchParams.hpp +102 -0
- package/nitrogen/generated/shared/c++/SleepTimerEndOfTrack.hpp +75 -0
- package/nitrogen/generated/shared/c++/SleepTimerTime.hpp +75 -0
- package/nitrogen/generated/shared/c++/StarRating.hpp +75 -0
- package/nitrogen/generated/shared/c++/ThumbsRating.hpp +75 -0
- package/nitrogen/generated/shared/c++/TimedMetadata.hpp +92 -0
- package/nitrogen/generated/shared/c++/Track.hpp +145 -0
- package/nitrogen/generated/shared/c++/TrackMetadata.hpp +136 -0
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +76 -0
- package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +116 -0
- package/nitrogen/generated/shared/c++/UpdateOptions.hpp +103 -0
- package/package.json +120 -0
- package/src/AudioBrowser.ts +4 -0
- package/src/features/battery.ts +176 -0
- package/src/features/browser.ts +315 -0
- package/src/features/equalizer.ts +64 -0
- package/src/features/errors.ts +196 -0
- package/src/features/favorites.ts +102 -0
- package/src/features/index.ts +23 -0
- package/src/features/metadata.ts +130 -0
- package/src/features/network.ts +34 -0
- package/src/features/nowPlaying.ts +56 -0
- package/src/features/output.ts +50 -0
- package/src/features/playback/controls.ts +66 -0
- package/src/features/playback/index.ts +7 -0
- package/src/features/playback/playWhenReady.ts +57 -0
- package/src/features/playback/playing.ts +40 -0
- package/src/features/playback/progress.ts +122 -0
- package/src/features/playback/rate.ts +22 -0
- package/src/features/playback/state.ts +72 -0
- package/src/features/playback/volume.ts +59 -0
- package/src/features/player/index.ts +2 -0
- package/src/features/player/options.ts +479 -0
- package/src/features/player/setup.ts +551 -0
- package/src/features/queue/activeTrack.ts +59 -0
- package/src/features/queue/index.ts +4 -0
- package/src/features/queue/queue.ts +173 -0
- package/src/features/queue/repeatMode.ts +58 -0
- package/src/features/queue/shuffle.ts +49 -0
- package/src/features/rating.ts +17 -0
- package/src/features/remoteControls.ts +341 -0
- package/src/features/sleepTimer.ts +186 -0
- package/src/index.ts +5 -0
- package/src/native.ts +5 -0
- package/src/native.web.ts +4 -0
- package/src/specs/audio-browser.nitro.ts +326 -0
- package/src/types/browser-native.ts +66 -0
- package/src/types/browser-nodes.ts +174 -0
- package/src/types/browser.ts +792 -0
- package/src/types/index.ts +2 -0
- package/src/types/player.ts +69 -0
- package/src/utils/LazyNativeEmitter.ts +58 -0
- package/src/utils/NativeUpdatedValue.ts +56 -0
- package/src/utils/resolveAssetSource.ts +4 -0
- package/src/utils/useDebug.ts +283 -0
- package/src/utils/useNativeUpdatedValue.ts +41 -0
- package/src/web/NativeAudioBrowser.ts +781 -0
- package/src/web/SimpleRouter.ts +177 -0
- package/src/web/TrackPlayer/Event.ts +11 -0
- package/src/web/TrackPlayer/Player.ts +323 -0
- package/src/web/TrackPlayer/PlaylistPlayer.ts +337 -0
- package/src/web/TrackPlayer/RepeatMode.ts +7 -0
- package/src/web/TrackPlayer/SetupNotCalledError.ts +5 -0
- package/src/web/TrackPlayer/SleepTimer.ts +71 -0
- package/src/web/TrackPlayer/State.ts +15 -0
- package/src/web/TrackPlayer/index.ts +4 -0
- package/src/web/browser/BrowserManager.ts +642 -0
- package/src/web/browser/FavoriteManager.ts +77 -0
- package/src/web/browser/NavigationErrorManager.ts +112 -0
- package/src/web/browser/SearchManager.ts +82 -0
- package/src/web/http/HttpClient.ts +107 -0
- package/src/web/http/RequestConfigBuilder.ts +347 -0
- package/src/web/player/NowPlayingManager.ts +83 -0
- package/src/web/player/OptionsManager.ts +101 -0
- package/src/web/util/BrowserPathHelper.ts +147 -0
- package/src/web/util/shuffle.ts +14 -0
|
@@ -0,0 +1,1509 @@
|
|
|
1
|
+
package com.audiobrowser.player
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import androidx.media3.common.AudioAttributes
|
|
6
|
+
import androidx.media3.common.C
|
|
7
|
+
import androidx.media3.common.ForwardingPlayer
|
|
8
|
+
import androidx.media3.common.HeartRating
|
|
9
|
+
import androidx.media3.common.MediaItem
|
|
10
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
11
|
+
import androidx.media3.database.StandaloneDatabaseProvider
|
|
12
|
+
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
|
13
|
+
import androidx.media3.datasource.cache.SimpleCache
|
|
14
|
+
import androidx.media3.exoplayer.DefaultRenderersFactory
|
|
15
|
+
import androidx.media3.exoplayer.ExoPlayer
|
|
16
|
+
import androidx.media3.exoplayer.upstream.DefaultBandwidthMeter
|
|
17
|
+
import androidx.media3.session.MediaLibraryService
|
|
18
|
+
import androidx.media3.session.MediaSession
|
|
19
|
+
import com.audiobrowser.AudioBrowser
|
|
20
|
+
import com.audiobrowser.Callbacks
|
|
21
|
+
import com.audiobrowser.extension.NumberExt.Companion.toSeconds
|
|
22
|
+
import com.margelo.nitro.audiobrowser.ImageContext
|
|
23
|
+
import com.audiobrowser.model.PlayerSetupOptions
|
|
24
|
+
import com.audiobrowser.model.PlayerUpdateOptions
|
|
25
|
+
import com.audiobrowser.util.AndroidAudioContentTypeFactory
|
|
26
|
+
import com.audiobrowser.util.CoilBitmapLoader
|
|
27
|
+
import com.audiobrowser.util.EqualizerManager
|
|
28
|
+
import com.audiobrowser.util.NetworkConnectivityMonitor
|
|
29
|
+
import com.audiobrowser.util.PlayingStateFactory
|
|
30
|
+
import com.audiobrowser.util.RepeatModeFactory
|
|
31
|
+
import com.audiobrowser.util.TrackFactory
|
|
32
|
+
import com.margelo.nitro.audiobrowser.AndroidPlayerWakeMode
|
|
33
|
+
import com.margelo.nitro.audiobrowser.AppKilledPlaybackBehavior
|
|
34
|
+
import com.margelo.nitro.audiobrowser.FavoriteChangedEvent
|
|
35
|
+
import com.margelo.nitro.audiobrowser.NowPlayingMetadata
|
|
36
|
+
import com.margelo.nitro.audiobrowser.NowPlayingUpdate
|
|
37
|
+
import com.margelo.nitro.audiobrowser.Playback
|
|
38
|
+
import com.margelo.nitro.audiobrowser.PlaybackActiveTrackChangedEvent
|
|
39
|
+
import com.margelo.nitro.audiobrowser.PlaybackError
|
|
40
|
+
import com.margelo.nitro.audiobrowser.PlaybackProgressUpdatedEvent
|
|
41
|
+
import com.margelo.nitro.audiobrowser.PlaybackQueueEndedEvent
|
|
42
|
+
import com.margelo.nitro.audiobrowser.PlaybackState
|
|
43
|
+
import com.margelo.nitro.audiobrowser.PlayingState
|
|
44
|
+
import com.margelo.nitro.audiobrowser.RatingType
|
|
45
|
+
import com.margelo.nitro.audiobrowser.RemoteJumpBackwardEvent
|
|
46
|
+
import com.margelo.nitro.audiobrowser.RemoteJumpForwardEvent
|
|
47
|
+
import com.margelo.nitro.audiobrowser.RemoteSeekEvent
|
|
48
|
+
import com.margelo.nitro.audiobrowser.RepeatMode
|
|
49
|
+
import com.margelo.nitro.audiobrowser.SearchParams
|
|
50
|
+
import com.margelo.nitro.audiobrowser.SleepTimer as NitroSleepTimer
|
|
51
|
+
import com.margelo.nitro.audiobrowser.SleepTimerEndOfTrack
|
|
52
|
+
import com.margelo.nitro.audiobrowser.SleepTimerTime
|
|
53
|
+
import com.margelo.nitro.audiobrowser.Track
|
|
54
|
+
import com.margelo.nitro.core.NullType
|
|
55
|
+
import java.io.File
|
|
56
|
+
import java.util.concurrent.TimeUnit
|
|
57
|
+
import kotlin.time.Duration.Companion.seconds
|
|
58
|
+
import kotlinx.coroutines.CompletableDeferred
|
|
59
|
+
import kotlinx.coroutines.TimeoutCancellationException
|
|
60
|
+
import kotlinx.coroutines.withTimeout
|
|
61
|
+
import timber.log.Timber
|
|
62
|
+
|
|
63
|
+
@SuppressLint("RestrictedApi")
|
|
64
|
+
class Player(internal val context: Context) {
|
|
65
|
+
val appKilledPlaybackBehavior: AppKilledPlaybackBehavior
|
|
66
|
+
get() = options.appKilledPlaybackBehavior
|
|
67
|
+
|
|
68
|
+
private var options = PlayerUpdateOptions()
|
|
69
|
+
internal var callbacks: Callbacks? = null
|
|
70
|
+
private lateinit var mediaSession: MediaSession
|
|
71
|
+
val networkMonitor: NetworkConnectivityMonitor = NetworkConnectivityMonitor(context)
|
|
72
|
+
private var equalizerManager: EqualizerManager? = null
|
|
73
|
+
private val mediaSessionCallback = MediaSessionCallback(this)
|
|
74
|
+
internal val playbackStateStore = PlaybackStateStore(this)
|
|
75
|
+
private val sleepTimer =
|
|
76
|
+
object : SleepTimer() {
|
|
77
|
+
override fun onComplete() {
|
|
78
|
+
Timber.d("Sleep timer completed, stopping playback")
|
|
79
|
+
stop()
|
|
80
|
+
callbacks?.onSleepTimerChanged(NitroSleepTimer.create(NullType.NULL))
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
lateinit var exoPlayer: ExoPlayer
|
|
85
|
+
lateinit var forwardingPlayer: androidx.media3.common.Player
|
|
86
|
+
/** Thread-safe cache of playWhenReady for access from non-main threads (e.g., retry policy) */
|
|
87
|
+
@Volatile internal var playWhenReadyCache = false
|
|
88
|
+
private lateinit var mediaFactory: MediaFactory
|
|
89
|
+
private lateinit var loadControl: DynamicLoadControl
|
|
90
|
+
private var automaticBufferManager: AutomaticBufferManager? = null
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Tracks whether a network-related retry is pending. When true, network restoration will trigger
|
|
94
|
+
* an immediate retry via exoPlayer.prepare().
|
|
95
|
+
*/
|
|
96
|
+
@Volatile private var pendingNetworkRetry = false
|
|
97
|
+
|
|
98
|
+
private var _browser: AudioBrowser? = null
|
|
99
|
+
private var browserRegistered = CompletableDeferred<AudioBrowser>()
|
|
100
|
+
private var _coilBitmapLoader: CoilBitmapLoader? = null
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Coil ImageLoader for SVG pre-rendering in Android Auto browse items.
|
|
104
|
+
* Set by Service after creation.
|
|
105
|
+
*/
|
|
106
|
+
var imageLoader: coil3.ImageLoader? = null
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Set the CoilBitmapLoader for artwork URL transformation. Called from Service after creation.
|
|
110
|
+
*/
|
|
111
|
+
var coilBitmapLoader: CoilBitmapLoader?
|
|
112
|
+
get() = _coilBitmapLoader
|
|
113
|
+
set(value) {
|
|
114
|
+
_coilBitmapLoader = value
|
|
115
|
+
// If browser is already set, wire up the resolver
|
|
116
|
+
_browser?.let { audioBrowser -> wireUpArtworkResolver(audioBrowser, value) }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
var browser: AudioBrowser?
|
|
120
|
+
get() = _browser
|
|
121
|
+
set(value) {
|
|
122
|
+
_browser = value
|
|
123
|
+
value?.let { audioBrowser ->
|
|
124
|
+
// Wire up artwork URL resolver
|
|
125
|
+
// This ensures the resolver is available when onGetChildren resumes
|
|
126
|
+
wireUpArtworkResolver(audioBrowser, _coilBitmapLoader)
|
|
127
|
+
|
|
128
|
+
// NOTE: We do NOT complete browserRegistered here.
|
|
129
|
+
// Configuration (routes/tabs) must be set before Android Auto can browse.
|
|
130
|
+
// Call notifyBrowserConfigurationReady() after configuration is set.
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Notifies that the browser configuration is ready (routes/tabs are configured).
|
|
136
|
+
* This should be called after setting the browser AND its configuration.
|
|
137
|
+
* Only then will Android Auto be able to browse content.
|
|
138
|
+
*/
|
|
139
|
+
fun notifyBrowserConfigurationReady() {
|
|
140
|
+
val audioBrowser = _browser ?: return
|
|
141
|
+
|
|
142
|
+
if (!browserRegistered.isCompleted) {
|
|
143
|
+
Timber.d("Browser configuration ready - completing deferred")
|
|
144
|
+
browserRegistered.complete(audioBrowser)
|
|
145
|
+
// Notify any subscribed controllers that content is now available
|
|
146
|
+
// This handles the cold-start case where AA subscribed before browser was ready
|
|
147
|
+
mediaSessionCallback.notifyBrowserReady()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Update MediaSession commands when browser becomes available with search configured
|
|
151
|
+
// Only update if search is available, since default state is "no search"
|
|
152
|
+
if (::mediaSession.isInitialized) {
|
|
153
|
+
val searchAvailable = audioBrowser.browserManager.config.hasSearch
|
|
154
|
+
if (searchAvailable) {
|
|
155
|
+
mediaSessionCallback.updateMediaSession(
|
|
156
|
+
mediaSession,
|
|
157
|
+
options.capabilities,
|
|
158
|
+
options.notificationButtons,
|
|
159
|
+
searchAvailable,
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Wires up the artwork URL resolver between BrowserManager and CoilBitmapLoader. This enables
|
|
167
|
+
* artwork URL transformation during browse-time (Phase 2).
|
|
168
|
+
*/
|
|
169
|
+
private fun wireUpArtworkResolver(audioBrowser: AudioBrowser, loader: CoilBitmapLoader?) {
|
|
170
|
+
val browserManager = audioBrowser.browserManager
|
|
171
|
+
if (loader != null) {
|
|
172
|
+
Timber.d("Wiring up artwork URL resolver")
|
|
173
|
+
browserManager.artworkUrlResolver = { track, perRouteConfig, imageContext ->
|
|
174
|
+
loader.transformArtworkUrlForTrack(track, perRouteConfig, imageContext)
|
|
175
|
+
}
|
|
176
|
+
// Clear content cache so that content resolved before the resolver was wired up
|
|
177
|
+
// will be re-fetched with artwork transformation applied
|
|
178
|
+
browserManager.clearContentCache()
|
|
179
|
+
Timber.d("Cleared content cache after wiring artwork resolver")
|
|
180
|
+
} else {
|
|
181
|
+
Timber.d("CoilBitmapLoader not available - artwork URL transformation disabled")
|
|
182
|
+
browserManager.artworkUrlResolver = null
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Suspends until the browser is registered, with a timeout.
|
|
188
|
+
*
|
|
189
|
+
* @throws TimeoutCancellationException if browser is not registered within timeout
|
|
190
|
+
*/
|
|
191
|
+
suspend fun awaitBrowser(): AudioBrowser =
|
|
192
|
+
browser
|
|
193
|
+
?: try {
|
|
194
|
+
withTimeout(10.seconds) {
|
|
195
|
+
Timber.d("Waiting for browser registration...")
|
|
196
|
+
browserRegistered.await()
|
|
197
|
+
}
|
|
198
|
+
} catch (e: TimeoutCancellationException) {
|
|
199
|
+
Timber.e("Timed out waiting for browser registration (10s)")
|
|
200
|
+
throw e
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* ForwardingPlayer that intercepts external player actions and dispatches them to callbacks.
|
|
205
|
+
*
|
|
206
|
+
* This class blocks all external media item modifications to delegate control to RNAB. These
|
|
207
|
+
* overrides prevent media controllers (like Android Auto, notifications) from directly modifying
|
|
208
|
+
* the queue, ensuring all queue changes go through the RNAB API for proper state management and
|
|
209
|
+
* event handling.
|
|
210
|
+
*/
|
|
211
|
+
private inner class InterceptingPlayer(player: ExoPlayer) : ForwardingPlayer(player) {
|
|
212
|
+
|
|
213
|
+
override fun setMediaItems(mediaItems: MutableList<MediaItem>, resetPosition: Boolean) {
|
|
214
|
+
return super.setMediaItems(mediaItems, resetPosition)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
override fun addMediaItems(mediaItems: MutableList<MediaItem>) {
|
|
218
|
+
return super.addMediaItems(mediaItems)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
override fun addMediaItems(index: Int, mediaItems: MutableList<MediaItem>) {
|
|
222
|
+
return super.addMediaItems(index, mediaItems)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override fun setMediaItems(
|
|
226
|
+
mediaItems: MutableList<MediaItem>,
|
|
227
|
+
startIndex: Int,
|
|
228
|
+
startPositionMs: Long,
|
|
229
|
+
) {
|
|
230
|
+
return super.setMediaItems(mediaItems, startIndex, startPositionMs)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
override fun setMediaItems(mediaItems: MutableList<MediaItem>) {
|
|
234
|
+
return super.setMediaItems(mediaItems)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Intercept playback controls and dispatch to callbacks or fall back to default behavior
|
|
238
|
+
override fun play() {
|
|
239
|
+
if (callbacks?.handleRemotePlay() != true) {
|
|
240
|
+
super.play()
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
override fun pause() {
|
|
245
|
+
if (callbacks?.handleRemotePause() != true) {
|
|
246
|
+
super.pause()
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
override fun seekToNext() {
|
|
251
|
+
Timber.Forest.d("InterceptingPlayer.seekToNext() called")
|
|
252
|
+
if (callbacks?.handleRemoteNext() != true) {
|
|
253
|
+
super.seekToNext()
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
override fun seekToNextMediaItem() {
|
|
258
|
+
Timber.Forest.d("InterceptingPlayer.seekToNextMediaItem() called")
|
|
259
|
+
if (callbacks?.handleRemoteNext() != true) {
|
|
260
|
+
super.seekToNextMediaItem()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
override fun seekToPrevious() {
|
|
265
|
+
Timber.Forest.d("InterceptingPlayer.seekToPrevious() called")
|
|
266
|
+
if (callbacks?.handleRemotePrevious() != true) {
|
|
267
|
+
super.seekToPrevious()
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
override fun seekToPreviousMediaItem() {
|
|
272
|
+
Timber.Forest.d("InterceptingPlayer.seekToPreviousMediaItem() called")
|
|
273
|
+
if (callbacks?.handleRemotePrevious() != true) {
|
|
274
|
+
super.seekToPreviousMediaItem()
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
override fun seekForward() {
|
|
279
|
+
Timber.Forest.d("InterceptingPlayer.seekForward() called")
|
|
280
|
+
if (
|
|
281
|
+
callbacks?.handleRemoteJumpForward(
|
|
282
|
+
RemoteJumpForwardEvent(interval = options.forwardJumpInterval)
|
|
283
|
+
) != true
|
|
284
|
+
) {
|
|
285
|
+
super.seekForward()
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
override fun seekBack() {
|
|
290
|
+
if (
|
|
291
|
+
callbacks?.handleRemoteJumpBackward(
|
|
292
|
+
RemoteJumpBackwardEvent(interval = options.backwardJumpInterval)
|
|
293
|
+
) != true
|
|
294
|
+
) {
|
|
295
|
+
super.seekBack()
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
override fun stop() {
|
|
300
|
+
if (callbacks?.handleRemoteStop() != true) {
|
|
301
|
+
super.stop()
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
override fun seekTo(mediaItemIndex: Int, positionMs: Long) {
|
|
306
|
+
if (
|
|
307
|
+
callbacks?.handleRemoteSeek(RemoteSeekEvent(position = positionMs.toDouble() / 1000.0)) !=
|
|
308
|
+
true
|
|
309
|
+
) {
|
|
310
|
+
super.seekTo(mediaItemIndex, positionMs)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
override fun seekTo(positionMs: Long) {
|
|
315
|
+
if (
|
|
316
|
+
callbacks?.handleRemoteSeek(RemoteSeekEvent(position = positionMs.toDouble() / 1000.0)) !=
|
|
317
|
+
true
|
|
318
|
+
) {
|
|
319
|
+
super.seekTo(positionMs)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private lateinit var playerListener: PlayerListener
|
|
325
|
+
private var cache: SimpleCache? = null
|
|
326
|
+
|
|
327
|
+
private val progressUpdateManager: PlaybackProgressUpdateManager by lazy {
|
|
328
|
+
PlaybackProgressUpdateManager {
|
|
329
|
+
val index = currentIndex ?: return@PlaybackProgressUpdateManager
|
|
330
|
+
val event =
|
|
331
|
+
PlaybackProgressUpdatedEvent(
|
|
332
|
+
position = position.toSeconds(),
|
|
333
|
+
duration = duration.toSeconds(),
|
|
334
|
+
buffered = bufferedPosition.toSeconds(),
|
|
335
|
+
track = index.toDouble(),
|
|
336
|
+
)
|
|
337
|
+
callbacks?.onPlaybackProgressUpdated(event)
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
internal var playingState: PlayingState = PlayingState(false, false)
|
|
342
|
+
|
|
343
|
+
val currentTrack: Track?
|
|
344
|
+
get() = exoPlayer.currentMediaItem?.let { TrackFactory.fromMedia3(it) }
|
|
345
|
+
|
|
346
|
+
internal var lastTrack: Track? = null
|
|
347
|
+
internal var lastIndex: Int? = null
|
|
348
|
+
|
|
349
|
+
var playbackError: PlaybackError? = null
|
|
350
|
+
internal set
|
|
351
|
+
|
|
352
|
+
internal var playbackState: PlaybackState = PlaybackState.NONE
|
|
353
|
+
private set
|
|
354
|
+
|
|
355
|
+
/** Current now playing metadata override (null = use track metadata) */
|
|
356
|
+
private var nowPlayingOverride: NowPlayingUpdate? = null
|
|
357
|
+
|
|
358
|
+
fun getPlayback(): Playback {
|
|
359
|
+
return Playback(playbackState, playbackError)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
fun getPlayingState(): PlayingState {
|
|
363
|
+
return playingState
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
var playWhenReady: Boolean
|
|
367
|
+
get() = exoPlayer.playWhenReady
|
|
368
|
+
set(value) {
|
|
369
|
+
playWhenReadyCache = value
|
|
370
|
+
exoPlayer.playWhenReady = value
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
val duration: Long
|
|
374
|
+
get() = if (exoPlayer.duration == C.TIME_UNSET) 0 else exoPlayer.duration
|
|
375
|
+
|
|
376
|
+
internal var oldPosition = 0L
|
|
377
|
+
|
|
378
|
+
val position: Long
|
|
379
|
+
get() =
|
|
380
|
+
if (exoPlayer.currentPosition == C.INDEX_UNSET.toLong()) 0 else exoPlayer.currentPosition
|
|
381
|
+
|
|
382
|
+
val bufferedPosition: Long
|
|
383
|
+
get() =
|
|
384
|
+
if (exoPlayer.bufferedPosition == C.INDEX_UNSET.toLong()) 0 else exoPlayer.bufferedPosition
|
|
385
|
+
|
|
386
|
+
var volume: Float
|
|
387
|
+
get() = exoPlayer.volume
|
|
388
|
+
set(value) {
|
|
389
|
+
exoPlayer.volume = value
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
var playbackSpeed: Float
|
|
393
|
+
get() = exoPlayer.playbackParameters.speed
|
|
394
|
+
set(value) {
|
|
395
|
+
exoPlayer.setPlaybackSpeed(value)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
val isPlaying
|
|
399
|
+
get() = exoPlayer.isPlaying
|
|
400
|
+
|
|
401
|
+
var ratingType: RatingType = RatingType.NONE
|
|
402
|
+
|
|
403
|
+
var repeatMode: RepeatMode
|
|
404
|
+
get() = RepeatModeFactory.fromMedia3(exoPlayer.repeatMode)
|
|
405
|
+
internal set(value) {
|
|
406
|
+
exoPlayer.repeatMode = RepeatModeFactory.toMedia3(value)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
val currentIndex: Int?
|
|
410
|
+
get() =
|
|
411
|
+
if (exoPlayer.currentMediaItemIndex == C.INDEX_UNSET) null
|
|
412
|
+
else exoPlayer.currentMediaItemIndex
|
|
413
|
+
|
|
414
|
+
var shuffleMode: Boolean
|
|
415
|
+
get() = exoPlayer.shuffleModeEnabled
|
|
416
|
+
set(value) {
|
|
417
|
+
exoPlayer.shuffleModeEnabled = value
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
val trackCount: Int
|
|
421
|
+
get() = exoPlayer.mediaItemCount
|
|
422
|
+
|
|
423
|
+
val isEmpty: Boolean
|
|
424
|
+
get() = exoPlayer.mediaItemCount == 0
|
|
425
|
+
|
|
426
|
+
val tracks: Array<Track>
|
|
427
|
+
get() =
|
|
428
|
+
(0 until exoPlayer.mediaItemCount)
|
|
429
|
+
.map { index -> TrackFactory.fromMedia3(exoPlayer.getMediaItemAt(index)) }
|
|
430
|
+
.toTypedArray()
|
|
431
|
+
|
|
432
|
+
val isLastTrack: Boolean
|
|
433
|
+
get() = exoPlayer.currentMediaItemIndex == exoPlayer.mediaItemCount - 1
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* The source path from which the current queue was expanded (e.g., from a contextual URL). Used
|
|
437
|
+
* to avoid re-expanding the queue when selecting tracks from the same source.
|
|
438
|
+
*/
|
|
439
|
+
var queueSourcePath: String? = null
|
|
440
|
+
internal set
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Get track at index with bounds checking.
|
|
444
|
+
*
|
|
445
|
+
* @param index The index of the track to retrieve.
|
|
446
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
447
|
+
*/
|
|
448
|
+
fun getTrack(index: Int): Track {
|
|
449
|
+
if (index < 0 || index >= exoPlayer.mediaItemCount) {
|
|
450
|
+
throw IllegalArgumentException(
|
|
451
|
+
"Track index $index is out of bounds (size: ${exoPlayer.mediaItemCount})"
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
return TrackFactory.fromMedia3(exoPlayer.getMediaItemAt(index))
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
var skipSilence: Boolean
|
|
458
|
+
get() = exoPlayer.skipSilenceEnabled
|
|
459
|
+
internal set(value) {
|
|
460
|
+
exoPlayer.skipSilenceEnabled = value
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Sets up or recreates the ExoPlayer with the provided setup options. This method can be called
|
|
465
|
+
* multiple times to change setup options.
|
|
466
|
+
*/
|
|
467
|
+
fun setup(setupOptions: PlayerSetupOptions) {
|
|
468
|
+
Timber.Forest.d("Setting up player with new options")
|
|
469
|
+
|
|
470
|
+
val isInitialSetup = !::exoPlayer.isInitialized
|
|
471
|
+
|
|
472
|
+
if (!isInitialSetup) {
|
|
473
|
+
forwardingPlayer.removeListener(playerListener)
|
|
474
|
+
exoPlayer.release()
|
|
475
|
+
Timber.Forest.d("Player cleanup completed")
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (setupOptions.maxCacheSize > 0) {
|
|
479
|
+
cache =
|
|
480
|
+
SimpleCache(
|
|
481
|
+
File(context.cacheDir, "RNAB"),
|
|
482
|
+
LeastRecentlyUsedCacheEvictor(
|
|
483
|
+
setupOptions.maxCacheSize.toLong() * 1_000_000
|
|
484
|
+
), // MB to bytes
|
|
485
|
+
StandaloneDatabaseProvider(context),
|
|
486
|
+
)
|
|
487
|
+
} else {
|
|
488
|
+
cache?.release()
|
|
489
|
+
cache = null
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Recreate ExoPlayer with new setup options
|
|
493
|
+
val renderer = DefaultRenderersFactory(context)
|
|
494
|
+
renderer.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
|
|
495
|
+
|
|
496
|
+
// Create bandwidth meter for adaptive bitrate selection in HLS/DASH
|
|
497
|
+
val bandwidthMeter = DefaultBandwidthMeter.Builder(context).build()
|
|
498
|
+
|
|
499
|
+
loadControl = run {
|
|
500
|
+
val minBuffer = setupOptions.minBuffer.toInt()
|
|
501
|
+
val maxBuffer = setupOptions.maxBuffer.toInt()
|
|
502
|
+
val playBuffer = setupOptions.playBuffer.toInt()
|
|
503
|
+
// When automatic (rebufferBuffer is null), start at playBuffer and let AutomaticBufferManager
|
|
504
|
+
// adjust
|
|
505
|
+
// When fixed (rebufferBuffer is set), use that value
|
|
506
|
+
val playAfterRebuffer = setupOptions.rebufferBuffer?.toInt() ?: playBuffer
|
|
507
|
+
val backBuffer = setupOptions.backBuffer.toInt()
|
|
508
|
+
val config =
|
|
509
|
+
BufferConfig(
|
|
510
|
+
minBufferMs = minBuffer,
|
|
511
|
+
maxBufferMs = maxBuffer,
|
|
512
|
+
bufferForPlaybackMs = playBuffer,
|
|
513
|
+
bufferForPlaybackAfterRebufferMs = playAfterRebuffer,
|
|
514
|
+
backBufferMs = backBuffer,
|
|
515
|
+
)
|
|
516
|
+
DynamicLoadControl(initialConfig = config)
|
|
517
|
+
}
|
|
518
|
+
// Create MediaFactory with reference to browser for media URL transformation
|
|
519
|
+
// shouldRetry checks playWhenReady to avoid retrying when paused (e.g., another app took audio
|
|
520
|
+
// focus). Uses thread-safe cache since this is called from ExoPlayer's playback thread.
|
|
521
|
+
// isOnline and onRetryPending enable network-aware retry acceleration.
|
|
522
|
+
mediaFactory =
|
|
523
|
+
MediaFactory(
|
|
524
|
+
context,
|
|
525
|
+
cache,
|
|
526
|
+
setupOptions.retryPolicy,
|
|
527
|
+
shouldRetry = { playWhenReadyCache },
|
|
528
|
+
isOnline = { networkMonitor.getOnline() },
|
|
529
|
+
onRetryPending = { isNetworkError ->
|
|
530
|
+
// Track pending network retries for acceleration when connectivity returns
|
|
531
|
+
pendingNetworkRetry = isNetworkError
|
|
532
|
+
if (isNetworkError) {
|
|
533
|
+
Timber.d("Network retry pending, will accelerate on connectivity restoration")
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
transferListener = bandwidthMeter,
|
|
537
|
+
) { url ->
|
|
538
|
+
browser?.getMediaRequestConfig(url)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
exoPlayer =
|
|
542
|
+
ExoPlayer.Builder(context)
|
|
543
|
+
.setRenderersFactory(renderer)
|
|
544
|
+
.setBandwidthMeter(bandwidthMeter)
|
|
545
|
+
.setHandleAudioBecomingNoisy(setupOptions.handleAudioBecomingNoisy)
|
|
546
|
+
.setMediaSourceFactory(mediaFactory)
|
|
547
|
+
.setWakeMode(
|
|
548
|
+
when (setupOptions.wakeMode) {
|
|
549
|
+
AndroidPlayerWakeMode.NONE -> C.WAKE_MODE_NONE
|
|
550
|
+
AndroidPlayerWakeMode.LOCAL -> C.WAKE_MODE_LOCAL
|
|
551
|
+
AndroidPlayerWakeMode.NETWORK -> C.WAKE_MODE_NETWORK
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
.setLoadControl(loadControl)
|
|
555
|
+
.setName("AudioBrowser")
|
|
556
|
+
.build()
|
|
557
|
+
exoPlayer.setAudioAttributes(
|
|
558
|
+
AudioAttributes.Builder()
|
|
559
|
+
.setUsage(C.USAGE_MEDIA)
|
|
560
|
+
.setContentType(AndroidAudioContentTypeFactory.toMedia3(setupOptions.audioContentType))
|
|
561
|
+
.build(),
|
|
562
|
+
true, // handle audio focus
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
// Apply setup-specific options
|
|
566
|
+
setupOptions.audioOffload?.let {
|
|
567
|
+
val audioOffloadPreferences =
|
|
568
|
+
TrackSelectionParameters.AudioOffloadPreferences.Builder()
|
|
569
|
+
.setAudioOffloadMode(
|
|
570
|
+
TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED
|
|
571
|
+
)
|
|
572
|
+
.setIsGaplessSupportRequired(it.gaplessSupportRequired)
|
|
573
|
+
.setIsSpeedChangeSupportRequired(it.rateChangeSupportRequired)
|
|
574
|
+
.build()
|
|
575
|
+
exoPlayer.trackSelectionParameters.audioOffloadPreferences = audioOffloadPreferences
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Recreate forwarding player with new ExoPlayer
|
|
579
|
+
forwardingPlayer = InterceptingPlayer(exoPlayer)
|
|
580
|
+
|
|
581
|
+
if (isInitialSetup) {
|
|
582
|
+
// Initial setup - create player listener and emit initial state
|
|
583
|
+
playerListener = PlayerListener(this)
|
|
584
|
+
forwardingPlayer.addListener(playerListener)
|
|
585
|
+
callbacks?.onPlaybackChanged(Playback(PlaybackState.NONE, null))
|
|
586
|
+
|
|
587
|
+
// Initialize equalizer with audio session ID
|
|
588
|
+
initializeEqualizer()
|
|
589
|
+
} else {
|
|
590
|
+
// Re-setup - re-add listener and update MediaSession
|
|
591
|
+
forwardingPlayer.addListener(playerListener)
|
|
592
|
+
|
|
593
|
+
// Update MediaSession with new forwardingPlayer reference if MediaSession exists
|
|
594
|
+
if (::mediaSession.isInitialized) {
|
|
595
|
+
Timber.Forest.d("Updating MediaSession with new forwardingPlayer reference")
|
|
596
|
+
mediaSession.player = forwardingPlayer
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
setPlaybackState(PlaybackState.NONE)
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Set up automatic buffer management if enabled
|
|
603
|
+
setupAutomaticBufferManager(setupOptions.automaticBuffer)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** Sets up or tears down the automatic buffer manager based on the enabled flag. */
|
|
607
|
+
private fun setupAutomaticBufferManager(enabled: Boolean) {
|
|
608
|
+
// Detach existing manager if any
|
|
609
|
+
automaticBufferManager?.detach()
|
|
610
|
+
|
|
611
|
+
if (enabled) {
|
|
612
|
+
val defaultConfig = loadControl.getBufferConfig()
|
|
613
|
+
automaticBufferManager =
|
|
614
|
+
AutomaticBufferManager(loadControl, defaultConfig).also { it.attach(exoPlayer) }
|
|
615
|
+
Timber.d("Automatic buffer management enabled")
|
|
616
|
+
} else {
|
|
617
|
+
automaticBufferManager = null
|
|
618
|
+
Timber.d("Automatic buffer management disabled")
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Starts observing network connectivity changes and invokes the callback when state changes.
|
|
624
|
+
* Also handles accelerating pending network retries when connectivity is restored.
|
|
625
|
+
*
|
|
626
|
+
* @param scope The coroutine scope to use for observation
|
|
627
|
+
*/
|
|
628
|
+
fun observeNetworkConnectivity(scope: kotlinx.coroutines.CoroutineScope) {
|
|
629
|
+
networkMonitor.observeOnline(scope) { isOnline ->
|
|
630
|
+
callbacks?.onOnlineChanged(isOnline)
|
|
631
|
+
|
|
632
|
+
// Accelerate pending network retry when connectivity is restored
|
|
633
|
+
if (isOnline && pendingNetworkRetry) {
|
|
634
|
+
Timber.d("Network restored with pending retry, triggering immediate retry")
|
|
635
|
+
pendingNetworkRetry = false
|
|
636
|
+
// Only retry if player is still expecting to play
|
|
637
|
+
if (playWhenReadyCache) {
|
|
638
|
+
exoPlayer.prepare()
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Loads a track into the player. If there is a current track, it will be replaced. If the queue
|
|
646
|
+
* is empty, the track will be added.
|
|
647
|
+
*
|
|
648
|
+
* @param track The [Track] to load.
|
|
649
|
+
*/
|
|
650
|
+
fun load(track: Track) {
|
|
651
|
+
if (exoPlayer.mediaItemCount == 0) {
|
|
652
|
+
add(track)
|
|
653
|
+
} else {
|
|
654
|
+
val index = exoPlayer.currentMediaItemIndex
|
|
655
|
+
replaceTrack(index, track)
|
|
656
|
+
exoPlayer.seekTo(index, C.TIME_UNSET)
|
|
657
|
+
exoPlayer.prepare()
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Add a single track to the queue. If the AudioPlayer has no track loaded, it will load the
|
|
663
|
+
* `track`.
|
|
664
|
+
*
|
|
665
|
+
* @param track The [Track] to add.
|
|
666
|
+
*/
|
|
667
|
+
fun add(track: Track) {
|
|
668
|
+
val mediaItem = TrackFactory.toMedia3(track)
|
|
669
|
+
exoPlayer.addMediaItem(mediaItem)
|
|
670
|
+
exoPlayer.prepare()
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Add multiple tracks to the queue. If the AudioPlayer has no track loaded, it will load the
|
|
675
|
+
* first track in the list.
|
|
676
|
+
*
|
|
677
|
+
* @param tracks The [Track]s to add.
|
|
678
|
+
*/
|
|
679
|
+
fun add(tracks: Array<Track>) {
|
|
680
|
+
val mediaItems = TrackFactory.toMedia3(tracks)
|
|
681
|
+
exoPlayer.addMediaItems(mediaItems.toList())
|
|
682
|
+
exoPlayer.prepare()
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Add multiple tracks to the queue.
|
|
687
|
+
*
|
|
688
|
+
* @param tracks The [Track]s to add.
|
|
689
|
+
* @param atIndex Index to insert tracks at. Use -1 to append to the end of the queue.
|
|
690
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
691
|
+
*/
|
|
692
|
+
fun add(tracks: Array<Track>, atIndex: Int) {
|
|
693
|
+
validateInsertIndex(atIndex)
|
|
694
|
+
val index = if (atIndex == -1) exoPlayer.mediaItemCount else atIndex
|
|
695
|
+
val mediaItems = tracks.map { TrackFactory.toMedia3(it) }
|
|
696
|
+
exoPlayer.addMediaItems(index, mediaItems)
|
|
697
|
+
exoPlayer.prepare()
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Remove a track from the queue.
|
|
702
|
+
*
|
|
703
|
+
* @param index The index of the track to remove.
|
|
704
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
705
|
+
*/
|
|
706
|
+
fun remove(index: Int) {
|
|
707
|
+
validateIndex(index)
|
|
708
|
+
exoPlayer.removeMediaItem(index)
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Remove tracks from the queue.
|
|
713
|
+
*
|
|
714
|
+
* @param indexes The indexes of the tracks to remove.
|
|
715
|
+
* @throws IllegalArgumentException if any index is out of bounds or if duplicate indexes are
|
|
716
|
+
* provided.
|
|
717
|
+
*/
|
|
718
|
+
fun remove(indexes: List<Int>) {
|
|
719
|
+
if (indexes.toSet().size != indexes.size) {
|
|
720
|
+
throw IllegalArgumentException("Duplicate indexes provided")
|
|
721
|
+
}
|
|
722
|
+
indexes.forEach { validateIndex(it) }
|
|
723
|
+
val sorted = indexes.sortedDescending()
|
|
724
|
+
sorted.forEach { exoPlayer.removeMediaItem(it) }
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Skip to the next track in the queue, which may depend on the current repeat mode. Does nothing
|
|
729
|
+
* if there is no next track to skip to.
|
|
730
|
+
*/
|
|
731
|
+
fun next() {
|
|
732
|
+
exoPlayer.seekToNextMediaItem()
|
|
733
|
+
exoPlayer.prepare()
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Skip to the previous track in the queue, which may depend on the current repeat mode. Does
|
|
738
|
+
* nothing if there is no previous track to skip to.
|
|
739
|
+
*/
|
|
740
|
+
fun previous() {
|
|
741
|
+
exoPlayer.seekToPreviousMediaItem()
|
|
742
|
+
exoPlayer.prepare()
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* Move an track in the queue from one position to another.
|
|
747
|
+
*
|
|
748
|
+
* @param fromIndex The index of the track to move.
|
|
749
|
+
* @param toIndex The index to move the track to. If the index is larger than the size of the
|
|
750
|
+
* queue, the track is moved to the end of the queue instead.
|
|
751
|
+
* @throws IllegalArgumentException if fromIndex is out of bounds.
|
|
752
|
+
*/
|
|
753
|
+
fun move(fromIndex: Int, toIndex: Int) {
|
|
754
|
+
validateIndex(fromIndex)
|
|
755
|
+
exoPlayer.moveMediaItem(fromIndex, toIndex)
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Skips to a track in the queue.
|
|
760
|
+
*
|
|
761
|
+
* @param index the index to skip to
|
|
762
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
763
|
+
*/
|
|
764
|
+
fun skipTo(index: Int) {
|
|
765
|
+
validateIndex(index)
|
|
766
|
+
exoPlayer.seekTo(index, C.TIME_UNSET)
|
|
767
|
+
exoPlayer.prepare()
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Sets the queue with new tracks, optionally starting at a specific index and position. This is
|
|
772
|
+
* more efficient than calling clear() + add() + skipTo() separately.
|
|
773
|
+
*
|
|
774
|
+
* @param tracks The tracks to set as the new queue.
|
|
775
|
+
* @param startIndex The index to start playback from (default: 0).
|
|
776
|
+
* @param startPositionMs The position in milliseconds to start from (default: 0).
|
|
777
|
+
* @param sourcePath Optional path from which this queue was expanded (for contextual URL
|
|
778
|
+
* optimization).
|
|
779
|
+
*/
|
|
780
|
+
fun setQueue(
|
|
781
|
+
tracks: Array<Track>,
|
|
782
|
+
startIndex: Int = 0,
|
|
783
|
+
startPositionMs: Long = 0,
|
|
784
|
+
sourcePath: String? = null,
|
|
785
|
+
) {
|
|
786
|
+
val mediaItems = TrackFactory.toMedia3(tracks).toMutableList()
|
|
787
|
+
exoPlayer.setMediaItems(mediaItems, startIndex, startPositionMs)
|
|
788
|
+
queueSourcePath = sourcePath
|
|
789
|
+
exoPlayer.prepare()
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* Replaces track at index in queue.
|
|
794
|
+
*
|
|
795
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
796
|
+
*/
|
|
797
|
+
fun replaceTrack(index: Int, track: Track) {
|
|
798
|
+
validateIndex(index)
|
|
799
|
+
exoPlayer.replaceMediaItem(index, TrackFactory.toMedia3(track))
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Sets the favorited state of the currently playing track. Updates the heart icon in media
|
|
804
|
+
* controllers without interrupting playback.
|
|
805
|
+
*/
|
|
806
|
+
fun setActiveTrackFavorited(favorited: Boolean) {
|
|
807
|
+
val index = exoPlayer.currentMediaItemIndex
|
|
808
|
+
if (index == C.INDEX_UNSET) return
|
|
809
|
+
|
|
810
|
+
val currentTrack = this.currentTrack ?: return
|
|
811
|
+
|
|
812
|
+
// Update native favorites cache (only tracks with src can be favorited)
|
|
813
|
+
currentTrack.src?.let { src -> browser?.browserManager?.updateFavorite(src, favorited) }
|
|
814
|
+
|
|
815
|
+
// Create updated Track with new favorited state
|
|
816
|
+
val updatedTrack =
|
|
817
|
+
Track(
|
|
818
|
+
url = currentTrack.url,
|
|
819
|
+
src = currentTrack.src,
|
|
820
|
+
artwork = currentTrack.artwork,
|
|
821
|
+
artworkSource = currentTrack.artworkSource,
|
|
822
|
+
artworkCarPlayTinted = currentTrack.artworkCarPlayTinted,
|
|
823
|
+
title = currentTrack.title,
|
|
824
|
+
subtitle = currentTrack.subtitle,
|
|
825
|
+
artist = currentTrack.artist,
|
|
826
|
+
album = currentTrack.album,
|
|
827
|
+
description = currentTrack.description,
|
|
828
|
+
genre = currentTrack.genre,
|
|
829
|
+
duration = currentTrack.duration,
|
|
830
|
+
style = currentTrack.style,
|
|
831
|
+
childrenStyle = currentTrack.childrenStyle,
|
|
832
|
+
favorited = favorited,
|
|
833
|
+
groupTitle = currentTrack.groupTitle,
|
|
834
|
+
live = currentTrack.live,
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
// Use buildUpon() on the existing MediaItem to update only the metadata
|
|
838
|
+
// This preserves internal references and avoids playback interruption
|
|
839
|
+
// Note: setTag() requires setUri() to be called, so we must re-set the URI
|
|
840
|
+
val currentMediaItem = exoPlayer.getMediaItemAt(index)
|
|
841
|
+
val updatedMetadata =
|
|
842
|
+
currentMediaItem.mediaMetadata.buildUpon().setUserRating(HeartRating(favorited)).build()
|
|
843
|
+
val updatedMediaItem =
|
|
844
|
+
currentMediaItem
|
|
845
|
+
.buildUpon()
|
|
846
|
+
.setUri(currentMediaItem.localConfiguration?.uri)
|
|
847
|
+
.setMediaMetadata(updatedMetadata)
|
|
848
|
+
.setTag(updatedTrack)
|
|
849
|
+
.build()
|
|
850
|
+
|
|
851
|
+
exoPlayer.replaceMediaItem(index, updatedMediaItem)
|
|
852
|
+
|
|
853
|
+
// Update the heart button icon in notification/Android Auto
|
|
854
|
+
updateFavoriteButtonState(favorited)
|
|
855
|
+
|
|
856
|
+
// Notify JS of the favorite state change
|
|
857
|
+
callbacks?.onFavoriteChanged(FavoriteChangedEvent(updatedTrack, favorited))
|
|
858
|
+
|
|
859
|
+
// Emit active track changed so useActiveTrack() hook updates
|
|
860
|
+
val activeTrackEvent =
|
|
861
|
+
PlaybackActiveTrackChangedEvent(
|
|
862
|
+
lastIndex = index.toDouble(),
|
|
863
|
+
lastTrack = currentTrack,
|
|
864
|
+
lastPosition = exoPlayer.currentPosition.toSeconds(),
|
|
865
|
+
index = index.toDouble(),
|
|
866
|
+
track = updatedTrack,
|
|
867
|
+
)
|
|
868
|
+
callbacks?.onPlaybackActiveTrackChanged(activeTrackEvent)
|
|
869
|
+
|
|
870
|
+
// Emit queue changed so useQueue() hook updates
|
|
871
|
+
callbacks?.onPlaybackQueueChanged(tracks)
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/** Toggles the favorited state of the currently playing track. */
|
|
875
|
+
fun toggleActiveTrackFavorited() {
|
|
876
|
+
val currentTrack = this.currentTrack ?: return
|
|
877
|
+
setActiveTrackFavorited(currentTrack.favorited != true)
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// MARK: - Now Playing Metadata
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Updates the now playing notification metadata. Pass null to clear overrides and revert to track
|
|
884
|
+
* metadata.
|
|
885
|
+
*/
|
|
886
|
+
fun updateNowPlaying(update: NowPlayingUpdate?) {
|
|
887
|
+
nowPlayingOverride = update
|
|
888
|
+
applyNowPlayingMetadata()
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
/** Gets the current now playing metadata (override if set, else track metadata). */
|
|
892
|
+
fun getNowPlaying(): NowPlayingMetadata? {
|
|
893
|
+
val track = currentTrack ?: return null
|
|
894
|
+
val override = nowPlayingOverride
|
|
895
|
+
|
|
896
|
+
return NowPlayingMetadata(
|
|
897
|
+
elapsedTime = null,
|
|
898
|
+
title = override?.title ?: track.title,
|
|
899
|
+
album = track.album,
|
|
900
|
+
artist = override?.artist ?: track.artist,
|
|
901
|
+
duration = track.duration,
|
|
902
|
+
artwork = track.artwork,
|
|
903
|
+
description = track.description,
|
|
904
|
+
mediaId = track.src ?: track.url,
|
|
905
|
+
genre = track.genre,
|
|
906
|
+
rating = null, // TODO: map track.favorited to rating if needed
|
|
907
|
+
)
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Clears the now playing override when track changes. Called from
|
|
912
|
+
* PlayerListener.onMediaItemTransition.
|
|
913
|
+
*/
|
|
914
|
+
internal fun clearNowPlayingOverride() {
|
|
915
|
+
nowPlayingOverride = null
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Resets the retry timer when track changes. Called from PlayerListener.onMediaItemTransition.
|
|
920
|
+
*/
|
|
921
|
+
internal fun resetRetryTimer() {
|
|
922
|
+
mediaFactory.resetRetryTimer()
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* Applies the current now playing metadata to the media notification. Uses the override if set,
|
|
927
|
+
* otherwise uses track metadata.
|
|
928
|
+
*/
|
|
929
|
+
private fun applyNowPlayingMetadata() {
|
|
930
|
+
val index = currentIndex ?: return
|
|
931
|
+
val track = currentTrack ?: return
|
|
932
|
+
val override = nowPlayingOverride
|
|
933
|
+
|
|
934
|
+
val currentMediaItem = exoPlayer.getMediaItemAt(index)
|
|
935
|
+
val updatedMetadata =
|
|
936
|
+
currentMediaItem.mediaMetadata
|
|
937
|
+
.buildUpon()
|
|
938
|
+
.setTitle(override?.title ?: track.title)
|
|
939
|
+
.setDisplayTitle(override?.title ?: track.title)
|
|
940
|
+
.setArtist(override?.artist ?: track.artist)
|
|
941
|
+
.build()
|
|
942
|
+
|
|
943
|
+
val updatedMediaItem =
|
|
944
|
+
currentMediaItem
|
|
945
|
+
.buildUpon()
|
|
946
|
+
.setUri(currentMediaItem.localConfiguration?.uri)
|
|
947
|
+
.setMediaMetadata(updatedMetadata)
|
|
948
|
+
.setTag(track)
|
|
949
|
+
.build()
|
|
950
|
+
|
|
951
|
+
exoPlayer.replaceMediaItem(index, updatedMediaItem)
|
|
952
|
+
|
|
953
|
+
// Notify JS of the now playing metadata change
|
|
954
|
+
getNowPlaying()?.let { callbacks?.onNowPlayingChanged(it) }
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Updates the favorite button icon in the notification/Android Auto. Call this when track changes
|
|
959
|
+
* or favorite state changes.
|
|
960
|
+
*/
|
|
961
|
+
internal fun updateFavoriteButtonState(favorited: Boolean?) {
|
|
962
|
+
if (!::mediaSession.isInitialized) return
|
|
963
|
+
mediaSessionCallback.commandManager.updateFavoriteState(mediaSession, favorited)
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/** Removes all the upcoming tracks, if any (the ones returned by [next]). */
|
|
967
|
+
fun removeUpcomingTracks() {
|
|
968
|
+
val index = exoPlayer.currentMediaItemIndex
|
|
969
|
+
if (index == C.INDEX_UNSET) return
|
|
970
|
+
val lastIndex = exoPlayer.mediaItemCount
|
|
971
|
+
val fromIndex = index + 1
|
|
972
|
+
|
|
973
|
+
exoPlayer.removeMediaItems(fromIndex, lastIndex)
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
fun play() {
|
|
977
|
+
exoPlayer.play()
|
|
978
|
+
if (currentTrack != null) {
|
|
979
|
+
exoPlayer.prepare()
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Executes a search and plays the results. Used for voice commands with structured search
|
|
985
|
+
* parameters.
|
|
986
|
+
*
|
|
987
|
+
* @param params The structured search parameters (mode, query, artist, album, etc.)
|
|
988
|
+
* @return true if search succeeded and playback started, false otherwise
|
|
989
|
+
*/
|
|
990
|
+
suspend fun playFromSearch(params: SearchParams): Boolean {
|
|
991
|
+
return try {
|
|
992
|
+
val browserManager = awaitBrowser().browserManager
|
|
993
|
+
|
|
994
|
+
Timber.d(
|
|
995
|
+
"Executing voice search: mode=${params.mode}, query='${params.query}', artist='${params.artist}', album='${params.album}'"
|
|
996
|
+
)
|
|
997
|
+
val tracks = browserManager.searchPlayable(params)
|
|
998
|
+
|
|
999
|
+
if (tracks != null && tracks.isNotEmpty()) {
|
|
1000
|
+
Timber.d("Found ${tracks.size} track(s), playing first: ${tracks[0].title}")
|
|
1001
|
+
setQueue(tracks)
|
|
1002
|
+
play()
|
|
1003
|
+
true
|
|
1004
|
+
} else {
|
|
1005
|
+
Timber.w("No tracks found for search: ${params}")
|
|
1006
|
+
false
|
|
1007
|
+
}
|
|
1008
|
+
} catch (e: Exception) {
|
|
1009
|
+
Timber.e(e, "Error handling voice search: ${params}")
|
|
1010
|
+
false
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
fun prepare() {
|
|
1015
|
+
if (currentTrack != null) {
|
|
1016
|
+
exoPlayer.prepare()
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
fun pause() {
|
|
1021
|
+
exoPlayer.pause()
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
fun togglePlayback() {
|
|
1025
|
+
if (exoPlayer.playWhenReady) {
|
|
1026
|
+
pause()
|
|
1027
|
+
} else {
|
|
1028
|
+
play()
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Stops playback, without clearing the active track. Calling this method will cause the playback
|
|
1034
|
+
* state to transition to State.NONE and the player will release the loaded media and resources
|
|
1035
|
+
* required for playback.
|
|
1036
|
+
*/
|
|
1037
|
+
fun stop() {
|
|
1038
|
+
playbackState = PlaybackState.STOPPED
|
|
1039
|
+
exoPlayer.playWhenReady = false
|
|
1040
|
+
exoPlayer.stop()
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
fun clear() {
|
|
1044
|
+
exoPlayer.clearMediaItems()
|
|
1045
|
+
queueSourcePath = null
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* Stops and destroys the player. Only call this when you are finished using the player, otherwise
|
|
1050
|
+
* use [pause].
|
|
1051
|
+
*/
|
|
1052
|
+
fun destroy() {
|
|
1053
|
+
stop()
|
|
1054
|
+
forwardingPlayer.removeListener(playerListener)
|
|
1055
|
+
automaticBufferManager?.detach()
|
|
1056
|
+
automaticBufferManager = null
|
|
1057
|
+
exoPlayer.release()
|
|
1058
|
+
cache?.release()
|
|
1059
|
+
cache = null
|
|
1060
|
+
networkMonitor.destroy()
|
|
1061
|
+
equalizerManager?.release()
|
|
1062
|
+
equalizerManager = null
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
fun seekTo(duration: Long, unit: TimeUnit) {
|
|
1066
|
+
val positionMs = TimeUnit.MILLISECONDS.convert(duration, unit)
|
|
1067
|
+
exoPlayer.seekTo(positionMs)
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
fun seekBy(offset: Long, unit: TimeUnit) {
|
|
1071
|
+
val positionMs = exoPlayer.currentPosition + TimeUnit.MILLISECONDS.convert(offset, unit)
|
|
1072
|
+
exoPlayer.seekTo(positionMs)
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Updates the player state and emits a state change event if the state has changed. Only emits an
|
|
1077
|
+
* event if the new state differs from the current state.
|
|
1078
|
+
*
|
|
1079
|
+
* IMPORTANT: This method also triggers the queue ended event when the player reaches State.ENDED
|
|
1080
|
+
* and is on the last track. All state transitions should go through this method to ensure proper
|
|
1081
|
+
* event dispatching. Direct assignments to playerState will bypass event emission.
|
|
1082
|
+
*
|
|
1083
|
+
* @param state The new player state to set
|
|
1084
|
+
*/
|
|
1085
|
+
internal fun setPlaybackState(state: PlaybackState) {
|
|
1086
|
+
if (state != playbackState) {
|
|
1087
|
+
val oldState = playbackState
|
|
1088
|
+
playbackState = state
|
|
1089
|
+
|
|
1090
|
+
// Clear error when transitioning away from error state
|
|
1091
|
+
if (oldState == PlaybackState.ERROR) {
|
|
1092
|
+
playbackError = null
|
|
1093
|
+
callbacks?.onPlaybackError(null)
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
val playback = Playback(state, playbackError)
|
|
1097
|
+
callbacks?.onPlaybackChanged(playback)
|
|
1098
|
+
|
|
1099
|
+
// Emit queue ended event when playback ends on the last track
|
|
1100
|
+
// This coupling ensures queue ended events are always triggered consistently with state
|
|
1101
|
+
// changes
|
|
1102
|
+
if (state == PlaybackState.ENDED && isLastTrack) {
|
|
1103
|
+
currentIndex?.let { index ->
|
|
1104
|
+
val event =
|
|
1105
|
+
PlaybackQueueEndedEvent(track = index.toDouble(), position = position.toSeconds())
|
|
1106
|
+
callbacks?.onPlaybackQueueEnded(event)
|
|
1107
|
+
}
|
|
1108
|
+
// Reset saved position to 0 so resumption starts from beginning (only when not repeating)
|
|
1109
|
+
if (repeatMode == RepeatMode.OFF) {
|
|
1110
|
+
playbackStateStore.savePositionZero()
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
progressUpdateManager.onPlaybackStateChanged(state)
|
|
1115
|
+
val newPlayingState = PlayingStateFactory.derive(playWhenReady, state)
|
|
1116
|
+
if (newPlayingState != playingState) {
|
|
1117
|
+
Timber.d(
|
|
1118
|
+
"PlayingState changed: playing=${newPlayingState.playing}, buffering=${newPlayingState.buffering}"
|
|
1119
|
+
)
|
|
1120
|
+
playingState = newPlayingState
|
|
1121
|
+
callbacks?.onPlaybackPlayingState(playingState)
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/**
|
|
1127
|
+
* Sets the progress update interval.
|
|
1128
|
+
*
|
|
1129
|
+
* @param interval The interval in seconds, or null to disable progress updates
|
|
1130
|
+
*/
|
|
1131
|
+
fun setProgressUpdateInterval(interval: Double?) {
|
|
1132
|
+
progressUpdateManager.setUpdateInterval(interval)
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/**
|
|
1136
|
+
* Applies update options with change detection. Only updates properties that have actually
|
|
1137
|
+
* changed and emits events accordingly.
|
|
1138
|
+
*
|
|
1139
|
+
* @param options The new options to apply
|
|
1140
|
+
* @param mediaSession The MediaSession to update when capabilities change
|
|
1141
|
+
*/
|
|
1142
|
+
fun applyOptions(options: PlayerUpdateOptions) {
|
|
1143
|
+
// Store previous values for change detection
|
|
1144
|
+
val previousOptions = this.options
|
|
1145
|
+
|
|
1146
|
+
// Update current options
|
|
1147
|
+
this.options = options.copy()
|
|
1148
|
+
|
|
1149
|
+
// Check what changed
|
|
1150
|
+
val skipSilenceChanged = previousOptions.skipSilence != options.skipSilence
|
|
1151
|
+
val ratingTypeChanged = previousOptions.ratingType != options.ratingType
|
|
1152
|
+
val shuffleChanged = previousOptions.shuffle != options.shuffle
|
|
1153
|
+
val progressUpdateEventIntervalChanged =
|
|
1154
|
+
previousOptions.progressUpdateEventInterval != options.progressUpdateEventInterval
|
|
1155
|
+
val forwardJumpIntervalChanged =
|
|
1156
|
+
previousOptions.forwardJumpInterval != options.forwardJumpInterval
|
|
1157
|
+
val backwardJumpIntervalChanged =
|
|
1158
|
+
previousOptions.backwardJumpInterval != options.backwardJumpInterval
|
|
1159
|
+
val capabilitiesChanged = previousOptions.capabilities != options.capabilities
|
|
1160
|
+
val notificationButtonsChanged =
|
|
1161
|
+
previousOptions.notificationButtons != options.notificationButtons
|
|
1162
|
+
val appKilledPlaybackBehaviorChanged =
|
|
1163
|
+
previousOptions.appKilledPlaybackBehavior != options.appKilledPlaybackBehavior
|
|
1164
|
+
|
|
1165
|
+
val hasChanged =
|
|
1166
|
+
skipSilenceChanged ||
|
|
1167
|
+
ratingTypeChanged ||
|
|
1168
|
+
shuffleChanged ||
|
|
1169
|
+
progressUpdateEventIntervalChanged ||
|
|
1170
|
+
forwardJumpIntervalChanged ||
|
|
1171
|
+
backwardJumpIntervalChanged ||
|
|
1172
|
+
capabilitiesChanged ||
|
|
1173
|
+
notificationButtonsChanged ||
|
|
1174
|
+
appKilledPlaybackBehaviorChanged
|
|
1175
|
+
|
|
1176
|
+
// Apply only changed properties
|
|
1177
|
+
if (skipSilenceChanged) {
|
|
1178
|
+
skipSilence = options.skipSilence
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
if (ratingTypeChanged) {
|
|
1182
|
+
options.ratingType?.let { ratingType = it }
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
if (shuffleChanged) {
|
|
1186
|
+
shuffleMode = options.shuffle
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
if (progressUpdateEventIntervalChanged) {
|
|
1190
|
+
setProgressUpdateInterval(options.progressUpdateEventInterval)
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
if (capabilitiesChanged || notificationButtonsChanged) {
|
|
1194
|
+
val searchAvailable = browser?.browserManager?.config?.hasSearch ?: false
|
|
1195
|
+
mediaSessionCallback.updateMediaSession(
|
|
1196
|
+
mediaSession,
|
|
1197
|
+
options.capabilities,
|
|
1198
|
+
options.notificationButtons,
|
|
1199
|
+
searchAvailable,
|
|
1200
|
+
)
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (hasChanged) {
|
|
1204
|
+
callbacks?.onOptionsChanged(options)
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Sets the callbacks for player events.
|
|
1210
|
+
*
|
|
1211
|
+
* @param callbacks The callbacks to set, or null to clear callbacks
|
|
1212
|
+
*/
|
|
1213
|
+
fun setCallbacks(callbacks: Callbacks?) {
|
|
1214
|
+
this.callbacks = callbacks
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Gets the current callbacks instance.
|
|
1219
|
+
*
|
|
1220
|
+
* @return The current callbacks, or null if none are set
|
|
1221
|
+
*/
|
|
1222
|
+
fun getCallbacks(): Callbacks? {
|
|
1223
|
+
return this.callbacks
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
fun setMediaSession(mediaSession: MediaSession) {
|
|
1227
|
+
this.mediaSession = mediaSession
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
fun getOptions(): PlayerUpdateOptions {
|
|
1231
|
+
return options
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/**
|
|
1235
|
+
* Gets the current network connectivity state.
|
|
1236
|
+
*
|
|
1237
|
+
* @return true if device is online, false otherwise
|
|
1238
|
+
*/
|
|
1239
|
+
fun getOnline(): Boolean {
|
|
1240
|
+
return networkMonitor.getOnline()
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
/** Initializes the equalizer with the player's audio session ID. */
|
|
1244
|
+
private fun initializeEqualizer() {
|
|
1245
|
+
val audioSessionId = exoPlayer.audioSessionId
|
|
1246
|
+
if (audioSessionId == C.AUDIO_SESSION_ID_UNSET) {
|
|
1247
|
+
Timber.d("Skipping equalizer init - no audio session yet, will init on first playback")
|
|
1248
|
+
return
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
try {
|
|
1252
|
+
equalizerManager =
|
|
1253
|
+
EqualizerManager(audioSessionId).apply {
|
|
1254
|
+
setOnSettingsChanged { settings -> callbacks?.onEqualizerChanged(settings) }
|
|
1255
|
+
}
|
|
1256
|
+
Timber.d("Equalizer initialized with session ID: $audioSessionId")
|
|
1257
|
+
} catch (e: Exception) {
|
|
1258
|
+
Timber.e(e, "Failed to initialize equalizer")
|
|
1259
|
+
equalizerManager = null
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/**
|
|
1264
|
+
* Reinitializes the equalizer when the audio session ID changes. Preserves current settings
|
|
1265
|
+
* (enabled state, preset, or custom levels). Also handles first-time initialization when the
|
|
1266
|
+
* equalizer was skipped at startup due to unset audio session ID.
|
|
1267
|
+
*/
|
|
1268
|
+
internal fun reinitializeEqualizer(newAudioSessionId: Int) {
|
|
1269
|
+
val oldManager = equalizerManager
|
|
1270
|
+
|
|
1271
|
+
// First-time initialization (skipped at startup because session was unset)
|
|
1272
|
+
if (oldManager == null) {
|
|
1273
|
+
Timber.d("First-time equalizer initialization with session ID: $newAudioSessionId")
|
|
1274
|
+
try {
|
|
1275
|
+
equalizerManager =
|
|
1276
|
+
EqualizerManager(newAudioSessionId).apply {
|
|
1277
|
+
setOnSettingsChanged { settings -> callbacks?.onEqualizerChanged(settings) }
|
|
1278
|
+
}
|
|
1279
|
+
Timber.d("Equalizer initialized with session ID: $newAudioSessionId")
|
|
1280
|
+
} catch (e: Exception) {
|
|
1281
|
+
Timber.e(e, "Failed to initialize equalizer")
|
|
1282
|
+
equalizerManager = null
|
|
1283
|
+
}
|
|
1284
|
+
return
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// Same session ID, no need to reinitialize
|
|
1288
|
+
if (oldManager.audioSessionId == newAudioSessionId) {
|
|
1289
|
+
return
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
try {
|
|
1293
|
+
// Capture current settings before releasing old equalizer
|
|
1294
|
+
val currentSettings = oldManager.getSettings()
|
|
1295
|
+
|
|
1296
|
+
// Release old equalizer
|
|
1297
|
+
oldManager.release()
|
|
1298
|
+
|
|
1299
|
+
// Create new equalizer with new session ID
|
|
1300
|
+
equalizerManager =
|
|
1301
|
+
EqualizerManager(newAudioSessionId).apply {
|
|
1302
|
+
setOnSettingsChanged { settings -> callbacks?.onEqualizerChanged(settings) }
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// Restore previous settings if available
|
|
1306
|
+
currentSettings?.let { settings ->
|
|
1307
|
+
if (settings.activePreset != null) {
|
|
1308
|
+
// Restore preset
|
|
1309
|
+
equalizerManager?.setPreset(settings.activePreset)
|
|
1310
|
+
} else if (settings.enabled) {
|
|
1311
|
+
// Restore custom levels
|
|
1312
|
+
equalizerManager?.setLevels(settings.bandLevels)
|
|
1313
|
+
}
|
|
1314
|
+
// Restore enabled state
|
|
1315
|
+
equalizerManager?.setEnabled(settings.enabled)
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
Timber.d("Equalizer reinitialized for new session ID: $newAudioSessionId")
|
|
1319
|
+
} catch (e: Exception) {
|
|
1320
|
+
Timber.e(e, "Failed to reinitialize equalizer")
|
|
1321
|
+
equalizerManager = null
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Gets the current equalizer settings.
|
|
1327
|
+
*
|
|
1328
|
+
* @return Current equalizer settings or null if not available
|
|
1329
|
+
*/
|
|
1330
|
+
fun getEqualizerSettings(): com.margelo.nitro.audiobrowser.EqualizerSettings? {
|
|
1331
|
+
return equalizerManager?.getSettings()
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
/**
|
|
1335
|
+
* Enables or disables the equalizer.
|
|
1336
|
+
*
|
|
1337
|
+
* @param enabled true to enable, false to disable
|
|
1338
|
+
*/
|
|
1339
|
+
fun setEqualizerEnabled(enabled: Boolean) {
|
|
1340
|
+
equalizerManager?.setEnabled(enabled)
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
/**
|
|
1344
|
+
* Applies a preset to the equalizer.
|
|
1345
|
+
*
|
|
1346
|
+
* @param preset Name of the preset to apply
|
|
1347
|
+
*/
|
|
1348
|
+
fun setEqualizerPreset(preset: String) {
|
|
1349
|
+
equalizerManager?.setPreset(preset)
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
/**
|
|
1353
|
+
* Sets custom band levels for the equalizer.
|
|
1354
|
+
*
|
|
1355
|
+
* @param levels Array of level values in millibels for each band
|
|
1356
|
+
*/
|
|
1357
|
+
fun setEqualizerLevels(levels: DoubleArray) {
|
|
1358
|
+
equalizerManager?.setLevels(levels)
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
// MARK: - Sleep Timer
|
|
1362
|
+
|
|
1363
|
+
/**
|
|
1364
|
+
* Gets the current sleep timer state.
|
|
1365
|
+
*
|
|
1366
|
+
* @return Sleep timer state or null if no timer is active
|
|
1367
|
+
*/
|
|
1368
|
+
fun getSleepTimer(): NitroSleepTimer {
|
|
1369
|
+
return when {
|
|
1370
|
+
sleepTimer.time != null -> {
|
|
1371
|
+
NitroSleepTimer.create(SleepTimerTime(sleepTimer.time!!))
|
|
1372
|
+
}
|
|
1373
|
+
sleepTimer.sleepWhenPlayedToEnd -> {
|
|
1374
|
+
NitroSleepTimer.create(SleepTimerEndOfTrack(true))
|
|
1375
|
+
}
|
|
1376
|
+
else -> {
|
|
1377
|
+
NitroSleepTimer.create(NullType.NULL)
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* Sets a sleep timer to stop playback after the specified duration.
|
|
1384
|
+
*
|
|
1385
|
+
* @param seconds Number of seconds until playback stops
|
|
1386
|
+
*/
|
|
1387
|
+
fun setSleepTimer(seconds: Double) {
|
|
1388
|
+
sleepTimer.sleepAfter(seconds)
|
|
1389
|
+
callbacks?.onSleepTimerChanged(getSleepTimer())
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
/** Sets a sleep timer to stop playback when the current track finishes playing. */
|
|
1393
|
+
fun setSleepTimerToEndOfTrack() {
|
|
1394
|
+
sleepTimer.sleepWhenPlayedToEnd()
|
|
1395
|
+
callbacks?.onSleepTimerChanged(getSleepTimer())
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* Clears the active sleep timer.
|
|
1400
|
+
*
|
|
1401
|
+
* @return true if a timer was cleared, false if no timer was active
|
|
1402
|
+
*/
|
|
1403
|
+
fun clearSleepTimer(): Boolean {
|
|
1404
|
+
val wasRunning = sleepTimer.clear()
|
|
1405
|
+
if (wasRunning) {
|
|
1406
|
+
callbacks?.onSleepTimerChanged(NitroSleepTimer.create(NullType.NULL))
|
|
1407
|
+
}
|
|
1408
|
+
return wasRunning
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/**
|
|
1412
|
+
* Checks if the sleep timer is set to end on track completion and stops playback if so. Called
|
|
1413
|
+
* when a track naturally finishes playing.
|
|
1414
|
+
*/
|
|
1415
|
+
internal fun checkSleepTimerOnTrackEnd() {
|
|
1416
|
+
if (sleepTimer.sleepWhenPlayedToEnd) {
|
|
1417
|
+
Timber.d("Sleep timer triggered on track end, stopping playback")
|
|
1418
|
+
sleepTimer.clear()
|
|
1419
|
+
stop()
|
|
1420
|
+
callbacks?.onSleepTimerChanged(NitroSleepTimer.create(NullType.NULL))
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
/**
|
|
1425
|
+
* Validates that an index is within bounds [0, trackCount).
|
|
1426
|
+
*
|
|
1427
|
+
* @param index The index to validate.
|
|
1428
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
1429
|
+
*/
|
|
1430
|
+
private fun validateIndex(index: Int) {
|
|
1431
|
+
if (index < 0 || index >= exoPlayer.mediaItemCount) {
|
|
1432
|
+
throw IllegalArgumentException(
|
|
1433
|
+
"Track index $index is out of bounds (size: ${exoPlayer.mediaItemCount})"
|
|
1434
|
+
)
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Validates that an insertion index is within bounds [0, trackCount] or -1 (append).
|
|
1440
|
+
*
|
|
1441
|
+
* @param index The index to validate.
|
|
1442
|
+
* @throws IllegalArgumentException if index is out of bounds.
|
|
1443
|
+
*/
|
|
1444
|
+
private fun validateInsertIndex(index: Int) {
|
|
1445
|
+
if (index < -1 || index > exoPlayer.mediaItemCount) {
|
|
1446
|
+
throw IllegalArgumentException(
|
|
1447
|
+
"Insert index $index is out of bounds (size: ${exoPlayer.mediaItemCount}, use -1 to append)"
|
|
1448
|
+
)
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
/**
|
|
1453
|
+
* Gets the MediaSessionCallback for this AudioBrowser.
|
|
1454
|
+
*
|
|
1455
|
+
* @return MediaLibrarySession.Callback instance
|
|
1456
|
+
*/
|
|
1457
|
+
fun getMediaSessionCallback(): MediaLibraryService.MediaLibrarySession.Callback {
|
|
1458
|
+
return mediaSessionCallback
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Notifies external controllers (Android Auto, etc.) that content at the given path has changed.
|
|
1463
|
+
* Controllers subscribed to this path will refresh their UI.
|
|
1464
|
+
*
|
|
1465
|
+
* @param path The path where content has changed
|
|
1466
|
+
*/
|
|
1467
|
+
fun notifyContentChanged(path: String) {
|
|
1468
|
+
mediaSessionCallback.notifyContentChanged(path)
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/**
|
|
1472
|
+
* Returns the recommended artwork size in pixels from the connected media browser (e.g., Android
|
|
1473
|
+
* Auto), or null if not provided.
|
|
1474
|
+
*/
|
|
1475
|
+
val artworkSizeHintPixels: Int?
|
|
1476
|
+
get() = mediaSessionCallback.artworkSizeHintPixels
|
|
1477
|
+
|
|
1478
|
+
/** Returns true if the current media item is a live stream. */
|
|
1479
|
+
val isCurrentItemLive: Boolean
|
|
1480
|
+
get() = exoPlayer.isCurrentMediaItemLive
|
|
1481
|
+
|
|
1482
|
+
// MARK: - Buffer Configuration
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
* Updates the buffer configuration at runtime.
|
|
1486
|
+
*
|
|
1487
|
+
* The new configuration takes effect immediately for future buffering decisions. Already-buffered
|
|
1488
|
+
* data is not affected.
|
|
1489
|
+
*
|
|
1490
|
+
* @param config The new buffer configuration to apply.
|
|
1491
|
+
*/
|
|
1492
|
+
fun updateBufferConfig(config: BufferConfig) {
|
|
1493
|
+
loadControl.updateBufferConfig(config)
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
/**
|
|
1497
|
+
* Gets the current buffer configuration.
|
|
1498
|
+
*
|
|
1499
|
+
* @return The current buffer configuration.
|
|
1500
|
+
*/
|
|
1501
|
+
fun getBufferConfig(): BufferConfig {
|
|
1502
|
+
return loadControl.getBufferConfig()
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
/** Resets the buffer configuration to defaults. */
|
|
1506
|
+
fun resetBufferConfig() {
|
|
1507
|
+
loadControl.resetToDefaults()
|
|
1508
|
+
}
|
|
1509
|
+
}
|