react-native-queue-player 1.1.2 → 2.0.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/QueuePlayer.podspec +14 -9
- package/README.md +3 -3
- package/android/build.gradle +7 -0
- package/android/consumer-rules.pro +72 -3
- package/android/src/main/cpp/airplay2_control.c +4 -4
- package/android/src/main/cpp/airplay2_control.h +4 -4
- package/android/src/main/cpp/airplay2_jni.cpp +26 -22
- package/android/src/main/cpp/airplay2_pair.c +7 -7
- package/android/src/main/cpp/airplay2_pair.h +2 -2
- package/android/src/main/cpp/airplay2_rtsp.c +8 -8
- package/android/src/main/cpp/airplay2_session.c +2 -2
- package/android/src/main/cpp/airplay_jni.cpp +20 -72
- package/android/src/main/java/com/margelo/nitro/queueplayer/AirPlayEngine.kt +7 -16
- package/android/src/main/java/com/margelo/nitro/queueplayer/CacheMimeTypes.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/queueplayer/CastManager.kt +2 -14
- package/android/src/main/java/com/margelo/nitro/queueplayer/CellularTransportMonitor.kt +77 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/CrossfadeEngine.kt +187 -52
- package/android/src/main/java/com/margelo/nitro/queueplayer/Equalizer.kt +27 -7
- package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerEngine.kt +33 -12
- package/android/src/main/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngine.kt +31 -8
- package/android/src/main/java/com/margelo/nitro/queueplayer/FFTProcessorTee.kt +45 -30
- package/android/src/main/java/com/margelo/nitro/queueplayer/FifoCacheEvictor.kt +111 -15
- package/android/src/main/java/com/margelo/nitro/queueplayer/GaplessEngine.kt +60 -33
- package/android/src/main/java/com/margelo/nitro/queueplayer/HeadlessJsMediaService.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/queueplayer/IEqualizerEngine.kt +3 -1
- package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCache.kt +103 -29
- package/android/src/main/java/com/margelo/nitro/queueplayer/LookaheadCacheWriter.kt +77 -29
- package/android/src/main/java/com/margelo/nitro/queueplayer/MediaItemBuilder.kt +6 -6
- package/android/src/main/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractor.kt +48 -1
- package/android/src/main/java/com/margelo/nitro/queueplayer/PitchCorrection.kt +3 -2
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackEngine.kt +71 -76
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackErrorMapping.kt +3 -3
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackModeStateMachine.kt +2 -2
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackService.kt +68 -46
- package/android/src/main/java/com/margelo/nitro/queueplayer/PlaybackServiceCallback.kt +6 -5
- package/android/src/main/java/com/margelo/nitro/queueplayer/QueueMutationArithmetic.kt +5 -6
- package/android/src/main/java/com/margelo/nitro/queueplayer/QueueSkipArithmetic.kt +11 -8
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessor.kt +26 -6
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainData.kt +22 -3
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainExtractor.kt +38 -12
- package/android/src/main/java/com/margelo/nitro/queueplayer/ReplayGainGain.kt +17 -13
- package/android/src/main/java/com/margelo/nitro/queueplayer/SuppliedReplayGain.kt +66 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/TrackPlayer.kt +870 -278
- package/android/src/main/java/com/margelo/nitro/queueplayer/Visualizer.kt +4 -8
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastBackend.kt +4 -3
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastEventBridge.kt +1 -10
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastSession.kt +17 -3
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/CastTransportRouter.kt +19 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/RemotePlaybackStateMapping.kt +18 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2JNI.kt +0 -2
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2Session.kt +23 -12
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayBackend.kt +16 -9
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayMetadataSync.kt +58 -21
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayRenderersFactory.kt +6 -14
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlaySession.kt +26 -14
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirplayJNI.kt +1 -13
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/MetadataSyncTarget.kt +20 -0
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/MulticastLockHolder.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastBackend.kt +3 -3
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/chromecast/ChromecastSession.kt +73 -13
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServer.kt +11 -35
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaServerHandle.kt +0 -5
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/MediaTokenRegistry.kt +0 -6
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/net/LocalAddressMonitor.kt +32 -33
- package/android/src/test/java/androidx/media3/session/{MediaSessionControllerRequestTestSeam.kt → MediaSessionControllerRequestTestSupport.kt} +1 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/AvrcpMetadataTest.kt +12 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineFocusLossTest.kt +115 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/CrossfadeEngineLifecycleTest.kt +45 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EngineEndSignalOrderTest.kt +70 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerEngineTest.kt +23 -12
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerKtTest.kt +0 -6
- package/android/src/test/java/com/margelo/nitro/queueplayer/EqualizerLegacyEngineTest.kt +43 -15
- package/android/src/test/java/com/margelo/nitro/queueplayer/FFTProcessorTeeTest.kt +15 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/FifoCacheEvictorTest.kt +135 -4
- package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineLifecycleTest.kt +1 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/GaplessEngineReplayGainTest.kt +36 -2
- package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheTest.kt +24 -18
- package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheWriterCancelTest.kt +85 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/LookaheadCacheWriterTest.kt +112 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/MediaItemBuilderTest.kt +5 -3
- package/android/src/test/java/com/margelo/nitro/queueplayer/NowPlayingFormatExtractorTest.kt +45 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PitchAwareAudioProcessorChainTest.kt +1 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackSearchTest.kt +47 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceCallbackTest.kt +53 -29
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackServiceLifecycleTest.kt +8 -8
- package/android/src/test/java/com/margelo/nitro/queueplayer/QueueSkipArithmeticTest.kt +33 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainAudioProcessorTest.kt +128 -5
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainExtractorTest.kt +209 -14
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainGainTest.kt +150 -10
- package/android/src/test/java/com/margelo/nitro/queueplayer/ReplayGainMergeTest.kt +258 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/RobolectricServiceBindHelper.kt +8 -4
- package/android/src/test/java/com/margelo/nitro/queueplayer/SessionCommandForwardingPlayerTest.kt +2 -2
- package/android/src/test/java/com/margelo/nitro/queueplayer/ShadowDynamicsProcessingRejectingEnable.kt +19 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ShadowEqualizer.kt +68 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/ShadowEqualizerRejectingBandWrites.kt +27 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/SuppliedReplayGainTest.kt +61 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAirPlayMetadataWiringTest.kt +4 -4
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerAudioFocusTest.kt +1 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerCastCommandRoutingTest.kt +163 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerCastStateTest.kt +123 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerEventsTest.kt +88 -38
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLifecycleTest.kt +205 -27
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerLookaheadConfigTest.kt +277 -38
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerMutationTest.kt +5 -3
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerProgressThrottleTest.kt +2 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueChangeTest.kt +85 -3
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerQueueTest.kt +11 -7
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerReadersTest.kt +2 -1
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipCapabilityTest.kt +90 -4
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerSkipTest.kt +8 -26
- package/android/src/test/java/com/margelo/nitro/queueplayer/TrackPlayerTransportTest.kt +3 -3
- package/android/src/test/java/com/margelo/nitro/queueplayer/VisualizerKtTest.kt +0 -4
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/FakeRemotePlayer.kt +27 -11
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlayMetadataSyncTest.kt +303 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/net/LocalAddressMonitorTest.kt +173 -0
- package/android/src/test/java/com/margelo/nitro/queueplayer/cast/net/ShadowConnectivityManagerRecordingRequests.kt +27 -0
- package/app.plugin.js +17 -1
- package/ios/AVPlayerItemQueueItemId.swift +26 -12
- package/ios/AVQueueBuilder.swift +120 -85
- package/ios/ArtworkLoader.swift +0 -7
- package/ios/ArtworkResolver.swift +22 -4
- package/ios/AssetReplayGainReader.swift +118 -0
- package/ios/AudioSession.swift +67 -16
- package/ios/AudioTapProvider.swift +284 -149
- package/ios/CarPlayBridge.swift +0 -12
- package/ios/CarPlayCoordinator.swift +18 -2
- package/ios/CarPlaySceneDelegate.swift +2 -2
- package/ios/Cast/AirPlayRouteState.swift +9 -8
- package/ios/Cast/Chromecast/ChromecastSession.swift +90 -11
- package/ios/Cast/Core/CastEventBridge.swift +66 -26
- package/ios/Cast/Core/CastNowPlayingController.swift +38 -16
- package/ios/Cast/Core/CastSession.swift +11 -0
- package/ios/Cast/Core/CastTransportRouter.swift +21 -9
- package/ios/Cast/Core/LocalMediaServer.swift +41 -52
- package/ios/Cast/Core/LocalNetworkPermissionProbe.swift +32 -11
- package/ios/Cast/Core/MediaServerHandle.swift +0 -4
- package/ios/Cast/Core/MediaTokenRegistry.swift +0 -6
- package/ios/CastManager.swift +1 -1
- package/ios/CrossfadeEngine.swift +660 -226
- package/ios/EQTap.swift +20 -17
- package/ios/Equalizer.swift +1 -1
- package/ios/FLACStreamInfo.swift +65 -0
- package/ios/GaplessEngine.swift +57 -30
- package/ios/InputGuards.swift +35 -5
- package/ios/LookaheadCache.swift +202 -58
- package/ios/LookaheadCachePrefetcher.swift +48 -36
- package/ios/MediaServer/MediaHTTPConnection.swift +691 -0
- package/ios/NetworkRecoveryPolicy.swift +32 -0
- package/ios/NowPlayingFormatExtractor.swift +25 -18
- package/ios/NowPlayingInfo.swift +84 -48
- package/ios/OutputRouteMonitor.swift +16 -3
- package/ios/PendingBrowseRequests.swift +1 -1
- package/ios/PlaceholderArtwork.swift +9 -5
- package/ios/PlaybackEngine.swift +165 -76
- package/ios/PlaybackErrorMapping.swift +3 -3
- package/ios/PlaybackModeStateMachine.swift +2 -2
- package/ios/PlaybackNetworkMonitor.swift +73 -0
- package/ios/PlayerStateDerivation.swift +6 -6
- package/ios/QueueMutationArithmetic.swift +25 -0
- package/ios/QueueSkipArithmetic.swift +5 -3
- package/ios/QueueWindowArithmetic.swift +152 -0
- package/ios/ReadThroughServer.swift +283 -0
- package/ios/RemoteCommands.swift +44 -4
- package/ios/ReplayGainData.swift +22 -3
- package/ios/ReplayGainExtractor.swift +70 -27
- package/ios/Siri/VoiceDonation.swift +14 -9
- package/ios/StreamingBitrateProbe.swift +22 -68
- package/ios/SuppliedReplayGain.swift +83 -0
- package/ios/Tests/AVQueueBuilderTests.swift +158 -221
- package/ios/Tests/ActiveItemEngineStub.swift +44 -0
- package/ios/Tests/AssetReplayGainReaderTests.swift +228 -0
- package/ios/Tests/AudioTapProviderDispatchTargetTests.swift +158 -0
- package/ios/Tests/AudioTapProviderReplayGainTests.swift +122 -10
- package/ios/Tests/BitrateReresolveBudgetTests.swift +71 -0
- package/ios/Tests/CastMediaItemTranslationTests.swift +72 -0
- package/ios/Tests/CastNowPlayingControllerTests.swift +5 -0
- package/ios/Tests/CrossfadeAdvanceWithoutFadeTests.swift +120 -0
- package/ios/Tests/CrossfadeEngineIncomingMixTests.swift +122 -0
- package/ios/Tests/CrossfadeEngineTests.swift +164 -0
- package/ios/Tests/CrossfadeMixReapplyTests.swift +66 -0
- package/ios/Tests/CrossfadePlaybackIntentTests.swift +81 -0
- package/ios/Tests/EngineSwapTests.swift +91 -0
- package/ios/Tests/EqualizerAudioMixProviderTests.swift +46 -0
- package/ios/Tests/EqualizerHybridTests.swift +5 -2
- package/ios/Tests/FLACStreamInfoTests.swift +88 -0
- package/ios/Tests/GaplessEngineLifecycleTests.swift +4 -4
- package/ios/Tests/InputGuardsTests.swift +41 -0
- package/ios/Tests/InterruptionIntentTests.swift +77 -0
- package/ios/Tests/LookaheadCacheCellularAccessTests.swift +185 -0
- package/ios/Tests/LookaheadCachePrefetcherTests.swift +53 -30
- package/ios/Tests/LookaheadCacheRuntimeConfigTests.swift +160 -1
- package/ios/Tests/LookaheadCacheTests.swift +44 -18
- package/ios/Tests/MediaHTTPConnectionTests.swift +79 -0
- package/ios/Tests/MutationDeferralTests.swift +220 -0
- package/ios/Tests/NowPlayingInfoTests.swift +86 -99
- package/ios/Tests/NowPlayingSnapshotTests.swift +127 -0
- package/ios/Tests/OriginRestartStitcherTests.swift +60 -0
- package/ios/Tests/PlaybackNetworkMonitorTests.swift +95 -0
- package/ios/Tests/PlaybackStateRouterTests.swift +1 -0
- package/ios/Tests/PlayerFixtures.swift +48 -0
- package/ios/Tests/PlayerStateDerivationTests.swift +10 -10
- package/ios/Tests/QueueMutationGenerationTests.swift +141 -0
- package/ios/Tests/QueueRebuildPrefixTests.swift +317 -0
- package/ios/Tests/QueueStateTests.swift +3 -1
- package/ios/Tests/QueueWindowArithmeticTests.swift +56 -0
- package/ios/Tests/QueueWindowSliceTests.swift +162 -0
- package/ios/Tests/ReadThroughRoutingLifecycleTests.swift +63 -0
- package/ios/Tests/ReadThroughServerTests.swift +345 -0
- package/ios/Tests/RemoteCommandsTests.swift +28 -0
- package/ios/Tests/ReplayGainExtractorTests.swift +216 -6
- package/ios/Tests/ReplayGainMergeTests.swift +230 -0
- package/ios/Tests/RetryRecoveryTests.swift +303 -0
- package/ios/Tests/SkipCapabilityTests.swift +233 -8
- package/ios/Tests/SkipIndexTests.swift +32 -2
- package/ios/Tests/SleepTimerPauseIntentTests.swift +43 -0
- package/ios/Tests/StallRecoveryTests.swift +97 -0
- package/ios/Tests/StreamingBitrateProbeTests.swift +17 -20
- package/ios/Tests/TopUpWindowGateTests.swift +394 -0
- package/ios/Tests/TrackPlayer+TestHops.swift +14 -0
- package/ios/Tests/TrackPlayerCallOrderTests.swift +93 -0
- package/ios/Tests/TrackPlayerCastStateTests.swift +78 -0
- package/ios/Tests/TrackPlayerConfigureTeardownTests.swift +86 -0
- package/ios/Tests/TrackPlayerEndVerdictTests.swift +165 -0
- package/ios/Tests/TrackPlayerSeekTests.swift +137 -0
- package/ios/Tests/TrackPlayerThreadingTests.swift +127 -0
- package/ios/Tests/TrackSourceClassifierTests.swift +33 -7
- package/ios/Tests/VoiceVocabularyOptInTests.swift +38 -0
- package/ios/TrackPlayer+Automotive.swift +101 -0
- package/ios/TrackPlayer+Cache.swift +232 -0
- package/ios/TrackPlayer+Config.swift +291 -0
- package/ios/TrackPlayer+EngineDelegate.swift +209 -0
- package/ios/TrackPlayer+EventsAPI.swift +111 -0
- package/ios/TrackPlayer+EventsDispatch.swift +968 -0
- package/ios/TrackPlayer+EventsWiring.swift +173 -0
- package/ios/TrackPlayer+Lifecycle.swift +930 -0
- package/ios/TrackPlayer+NowPlayingFormat.swift +258 -0
- package/ios/TrackPlayer+Queue.swift +940 -0
- package/ios/TrackPlayer+Recovery.swift +196 -0
- package/ios/TrackPlayer+Skip.swift +455 -0
- package/ios/TrackPlayer+SleepTimer.swift +175 -0
- package/ios/TrackPlayer+State.swift +108 -0
- package/ios/TrackPlayer+Threading.swift +135 -0
- package/ios/TrackPlayer+Transport.swift +267 -0
- package/ios/TrackPlayer+Window.swift +195 -0
- package/ios/TrackPlayer.swift +305 -4610
- package/ios/Visualizer.swift +6 -5
- package/ios/tests-harness/Podfile +1 -1
- package/ios/tests-harness/TestHost.xcodeproj/project.pbxproj +19 -11
- package/ios/tests-harness/scripts/seed-xcodeproj.rb +2 -2
- package/lib/module/hooks/useActiveTrack.js +29 -22
- package/lib/module/hooks/useActiveTrack.js.map +1 -1
- package/lib/module/hooks/useCast.js +8 -26
- package/lib/module/hooks/useCast.js.map +1 -1
- package/lib/module/hooks/useEqualizer.js +19 -12
- package/lib/module/hooks/useEqualizer.js.map +1 -1
- package/lib/module/hooks/useLookaheadCache.js +3 -7
- package/lib/module/hooks/useLookaheadCache.js.map +1 -1
- package/lib/module/hooks/useQueue.js +66 -19
- package/lib/module/hooks/useQueue.js.map +1 -1
- package/lib/module/index.js +6 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/queueDelta.js +41 -0
- package/lib/module/queueDelta.js.map +1 -0
- package/lib/module/types.js +28 -5
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/TrackPlayer.nitro.d.ts +53 -28
- package/lib/typescript/TrackPlayer.nitro.d.ts.map +1 -1
- package/lib/typescript/hooks/useActiveTrack.d.ts +5 -7
- package/lib/typescript/hooks/useActiveTrack.d.ts.map +1 -1
- package/lib/typescript/hooks/useCast.d.ts +6 -1
- package/lib/typescript/hooks/useCast.d.ts.map +1 -1
- package/lib/typescript/hooks/useEqualizer.d.ts +2 -1
- package/lib/typescript/hooks/useEqualizer.d.ts.map +1 -1
- package/lib/typescript/hooks/useLookaheadCache.d.ts.map +1 -1
- package/lib/typescript/hooks/useQueue.d.ts +4 -4
- package/lib/typescript/hooks/useQueue.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/queueDelta.d.ts +10 -0
- package/lib/typescript/queueDelta.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +168 -12
- package/lib/typescript/types.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JFunc_void_QueueChangeDelta_double_QueueChangeReason.hpp +85 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +45 -19
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +3 -3
- package/nitrogen/generated/android/c++/JLookaheadCacheConfig.hpp +8 -4
- package/nitrogen/generated/android/c++/JPlayerConfig.hpp +5 -1
- package/nitrogen/generated/android/c++/JQueueChangeDelta.hpp +128 -0
- package/nitrogen/generated/android/c++/JTrackItem.hpp +19 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_BrowseItem______std__string.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______MediaSearchRequest.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_TrackItem______std__string.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_AudioRoute.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_BufferState.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CacheStatus.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastDiscoveryState.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastLocalNetworkPermissionEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastRoute.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_CastSessionDiedEvent.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlaybackError.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerProgress.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_PlayerState_StateChangeReason.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/{Func_void_std__vector_TrackItem__double_QueueChangeReason.kt → Func_void_QueueChangeDelta_double_QueueChangeReason.kt} +14 -16
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_ServiceReadyReason.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SkipCapability.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_SleepTimerState.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerErrorReason.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_VisualizerFrame.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_bool.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_double_double.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_TrackItem__double_TrackChangeReason_std__optional_double_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__optional_std__variant_nitro__NullType__NowPlayingFormat__.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_CastReceiver_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/Func_void_std__vector_EqualizerBand_.kt +0 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridCastManagerSpec.kt +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridEqualizerSpec.kt +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridTrackPlayerSpec.kt +6 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/HybridVisualizerSpec.kt +2 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/LookaheadCacheConfig.kt +9 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/PlayerConfig.kt +7 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/QueueChangeDelta.kt +86 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/queueplayer/TrackItem.kt +24 -4
- package/nitrogen/generated/android/queueplayerOnLoad.cpp +2 -2
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.cpp +16 -16
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Bridge.hpp +80 -65
- package/nitrogen/generated/ios/QueuePlayer-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +6 -3
- package/nitrogen/generated/ios/swift/Func_void_CacheStatus.swift +5 -5
- package/nitrogen/generated/ios/swift/Func_void_QueueChangeDelta_double_QueueChangeReason.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +3 -3
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +32 -24
- package/nitrogen/generated/ios/swift/LookaheadCacheConfig.swift +20 -2
- package/nitrogen/generated/ios/swift/PlayerConfig.swift +19 -1
- package/nitrogen/generated/ios/swift/QueueChangeDelta.swift +82 -0
- package/nitrogen/generated/ios/swift/TrackItem.swift +73 -1
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +6 -3
- package/nitrogen/generated/shared/c++/LookaheadCacheConfig.hpp +7 -3
- package/nitrogen/generated/shared/c++/PlayerConfig.hpp +5 -1
- package/nitrogen/generated/shared/c++/QueueChangeDelta.hpp +113 -0
- package/nitrogen/generated/shared/c++/TrackItem.hpp +18 -2
- package/package.json +8 -8
- package/src/TrackPlayer.nitro.ts +53 -27
- package/src/hooks/useActiveTrack.ts +29 -22
- package/src/hooks/useCast.ts +14 -15
- package/src/hooks/useEqualizer.ts +19 -12
- package/src/hooks/useLookaheadCache.ts +3 -7
- package/src/hooks/useQueue.ts +66 -17
- package/src/index.ts +13 -3
- package/src/queueDelta.ts +41 -0
- package/src/types.ts +169 -12
- package/android/src/main/java/com/margelo/nitro/queueplayer/PendingIntentBuffer.kt +0 -82
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/airplay/AirPlay2MetadataSync.kt +0 -189
- package/android/src/main/java/com/margelo/nitro/queueplayer/cast/http/LocalMediaServerLifecycle.kt +0 -15
- package/android/src/test/java/com/margelo/nitro/queueplayer/PendingIntentBufferTest.kt +0 -192
- package/android/src/test/java/com/margelo/nitro/queueplayer/PlaybackEngineInterfaceTest.kt +0 -135
- package/android/src/test/java/com/margelo/nitro/queueplayer/SmokeTest.kt +0 -27
- package/ios/Cast/Core/LocalAddressMonitor.swift +0 -110
- package/ios/Cast/Core/MediaHTTPConnection.swift +0 -349
- package/ios/MetadataReader.swift +0 -555
- package/ios/Tests/CrossfadeEngineStubTests.swift +0 -43
- package/ios/Tests/MetadataReaderTests.swift +0 -603
- package/ios/Tests/PlaybackEngineProtocolTests.swift +0 -92
- package/ios/Tests/VoiceDonationTests.swift +0 -26
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_TrackItem__double_QueueChangeReason.hpp +0 -101
- package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem__double_QueueChangeReason.swift +0 -46
- /package/ios/{Cast/Core → MediaServer}/MimeTypes.swift +0 -0
|
@@ -17,8 +17,8 @@ import Network
|
|
|
17
17
|
/// Backends call `acquire(sessionId:)` for a `MediaServerHandle`; the
|
|
18
18
|
/// listener starts on first acquire and stops when the last handle
|
|
19
19
|
/// closes. Range / HEAD / Content-Length are handled by the responder.
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
/// Thread-safe singleton: all mutable state is guarded by `lock`, so it is
|
|
21
|
+
/// safe to capture in the listener's `@Sendable` dispatch closures.
|
|
22
22
|
final class LocalMediaServer: @unchecked Sendable {
|
|
23
23
|
/// Process-wide singleton — only the Chromecast / DLNA / Sonos
|
|
24
24
|
/// backends acquire handles; AirPlay-only apps never touch this and
|
|
@@ -32,7 +32,6 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
32
32
|
private var boundPort: UInt16 = 0
|
|
33
33
|
private var refCount = 0
|
|
34
34
|
private let registry = MediaTokenRegistry()
|
|
35
|
-
private var addressMonitor: LocalAddressMonitor?
|
|
36
35
|
/// Live accepted connections, tracked so `stop()` can cancel any
|
|
37
36
|
/// in-flight transfer. Keyed by identity; each self-removes on finish.
|
|
38
37
|
private var connections: [ObjectIdentifier: MediaHTTPConnection] = [:]
|
|
@@ -43,62 +42,51 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
43
42
|
// acquiring async task suspends instead of busy-waiting a cooperative thread.
|
|
44
43
|
private var readinessWaiters: [CheckedContinuation<Void, Never>] = []
|
|
45
44
|
|
|
46
|
-
// `lifecycleListener` is read from acquire/release (which may run on
|
|
47
|
-
// any thread the consumer routes calls through) and set from caller
|
|
48
|
-
// code on app init. Reads + writes go through this dedicated lock so
|
|
49
|
-
// a concurrent set during a refcount flip doesn't race the read.
|
|
50
|
-
private let listenerLock = NSLock()
|
|
51
|
-
private var _lifecycleListener: ((Bool) -> Void)?
|
|
52
|
-
|
|
53
|
-
var lifecycleListener: ((Bool) -> Void)? {
|
|
54
|
-
get {
|
|
55
|
-
listenerLock.lock(); defer { listenerLock.unlock() }
|
|
56
|
-
return _lifecycleListener
|
|
57
|
-
}
|
|
58
|
-
set {
|
|
59
|
-
listenerLock.lock()
|
|
60
|
-
_lifecycleListener = newValue
|
|
61
|
-
listenerLock.unlock()
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private func fireLifecycle(_ active: Bool) {
|
|
66
|
-
listenerLock.lock()
|
|
67
|
-
let cb = _lifecycleListener
|
|
68
|
-
listenerLock.unlock()
|
|
69
|
-
cb?(active)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
45
|
/// OS-assigned port. `nil` when the listener is not bound.
|
|
73
46
|
var serverPortOrNil: Int? {
|
|
74
47
|
lock.lock(); defer { lock.unlock() }
|
|
75
48
|
return boundPort == 0 ? nil : Int(boundPort)
|
|
76
49
|
}
|
|
77
50
|
|
|
78
|
-
/// LAN IPv4 address for receivers to reach
|
|
79
|
-
/// `
|
|
80
|
-
///
|
|
81
|
-
/// doesn't fail just because the monitor's first path-update
|
|
82
|
-
/// callback hasn't fired yet.
|
|
51
|
+
/// LAN IPv4 address for receivers to reach: the first IPv4 on an `en*`
|
|
52
|
+
/// interface, looked up with `getifaddrs` on every read; `nil` when
|
|
53
|
+
/// there is none.
|
|
83
54
|
var currentLanAddress: String? {
|
|
84
|
-
|
|
85
|
-
return LocalAddressMonitor.firstWifiIPv4()
|
|
55
|
+
Self.firstWifiIPv4()
|
|
86
56
|
}
|
|
87
57
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
func
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
58
|
+
/// The first IPv4 address on an `en*` interface (Wi-Fi), from a
|
|
59
|
+
/// synchronous `getifaddrs` scan; `nil` when no such interface has one.
|
|
60
|
+
/// Cellular addresses can't reach a LAN receiver, so other interfaces
|
|
61
|
+
/// are ignored.
|
|
62
|
+
private static func firstWifiIPv4() -> String? {
|
|
63
|
+
var ifaddrPtr: UnsafeMutablePointer<ifaddrs>?
|
|
64
|
+
guard getifaddrs(&ifaddrPtr) == 0, let first = ifaddrPtr else { return nil }
|
|
65
|
+
defer { freeifaddrs(ifaddrPtr) }
|
|
66
|
+
var ptr: UnsafeMutablePointer<ifaddrs>? = first
|
|
67
|
+
while let current = ptr {
|
|
68
|
+
defer { ptr = current.pointee.ifa_next }
|
|
69
|
+
let name = String(cString: current.pointee.ifa_name)
|
|
70
|
+
guard name.hasPrefix("en") else { continue }
|
|
71
|
+
guard let sa = current.pointee.ifa_addr else { continue }
|
|
72
|
+
guard sa.pointee.sa_family == UInt8(AF_INET) else { continue }
|
|
73
|
+
var hostBuf = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
74
|
+
let result = getnameinfo(
|
|
75
|
+
sa, socklen_t(sa.pointee.sa_len),
|
|
76
|
+
&hostBuf, socklen_t(hostBuf.count),
|
|
77
|
+
nil, 0, NI_NUMERICHOST
|
|
78
|
+
)
|
|
79
|
+
if result == 0 {
|
|
80
|
+
let host = String(cString: hostBuf)
|
|
81
|
+
if !host.isEmpty && host != "0.0.0.0" { return host }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return nil
|
|
96
85
|
}
|
|
97
86
|
|
|
98
87
|
func acquire(sessionId: String) async -> MediaServerHandle {
|
|
99
88
|
if takeRefCountWasFirst() {
|
|
100
89
|
await startAndWait()
|
|
101
|
-
fireLifecycle(true)
|
|
102
90
|
}
|
|
103
91
|
return MediaServerHandle(server: self, sessionId: sessionId)
|
|
104
92
|
}
|
|
@@ -122,7 +110,6 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
122
110
|
lock.unlock()
|
|
123
111
|
if last {
|
|
124
112
|
stop()
|
|
125
|
-
fireLifecycle(false)
|
|
126
113
|
}
|
|
127
114
|
}
|
|
128
115
|
|
|
@@ -130,10 +117,6 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
130
117
|
registry.register(sessionId: sessionId, fileURL: fileURL, contentType: contentType)
|
|
131
118
|
}
|
|
132
119
|
|
|
133
|
-
func revoke(_ token: String) {
|
|
134
|
-
registry.revoke(token)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
120
|
// MARK: - Listener lifecycle
|
|
138
121
|
|
|
139
122
|
/// Start the listener (if not already bound) and suspend, bounded, until it
|
|
@@ -186,7 +169,8 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
186
169
|
// Bind every interface (Wi-Fi LAN, etc.) on an OS-assigned port — the
|
|
187
170
|
// Cast receiver fetches URLs over the LAN, so unlike a loopback proxy
|
|
188
171
|
// this listener must accept en0 connections. URLs handed to receivers
|
|
189
|
-
//
|
|
172
|
+
// go through `MediaServerHandle.register(fileURL:lanAddress:contentType:)`
|
|
173
|
+
// with the host from `currentLanAddress` (the first IPv4 on an `en*` interface);
|
|
190
174
|
// tokens are 32 hex chars (high entropy), so the LAN-reachable surface
|
|
191
175
|
// can't be enumerated. `allowLocalEndpointReuse` avoids bind churn when
|
|
192
176
|
// a prior listener's socket is still in TIME_WAIT.
|
|
@@ -238,7 +222,12 @@ final class LocalMediaServer: @unchecked Sendable {
|
|
|
238
222
|
}
|
|
239
223
|
|
|
240
224
|
private func accept(_ conn: NWConnection) {
|
|
241
|
-
let responder = MediaHTTPConnection(
|
|
225
|
+
let responder = MediaHTTPConnection(
|
|
226
|
+
connection: conn,
|
|
227
|
+
resolve: { [registry] token in
|
|
228
|
+
registry.resolve(token).map { .file($0.fileURL, contentType: $0.contentType) }
|
|
229
|
+
}
|
|
230
|
+
) { [weak self] in
|
|
242
231
|
self?.untrack(conn)
|
|
243
232
|
}
|
|
244
233
|
// Track BEFORE start(): the responder's finish callback (-> untrack)
|
|
@@ -51,15 +51,17 @@ final class LocalNetworkPermissionProbe {
|
|
|
51
51
|
|
|
52
52
|
init() {}
|
|
53
53
|
|
|
54
|
-
///
|
|
55
|
-
///
|
|
56
|
-
///
|
|
54
|
+
/// The most recently resolved permission state, or `.undetermined` if no
|
|
55
|
+
/// probe has resolved yet.
|
|
56
|
+
///
|
|
57
|
+
/// Deliberately not TTL-gated. The TTL governs whether
|
|
58
|
+
/// `requestPermission()` re-probes; expiring the *answer* as well would
|
|
59
|
+
/// report `.undetermined` for a user who granted access a minute ago, and any
|
|
60
|
+
/// consumer rule of the form "granted suppresses the prompt" would then
|
|
61
|
+
/// invert — re-prompting exactly the people who already said yes.
|
|
57
62
|
var cachedState: CastLocalNetworkPermission {
|
|
58
63
|
stateLock.lock(); defer { stateLock.unlock() }
|
|
59
|
-
|
|
60
|
-
return _cachedState
|
|
61
|
-
}
|
|
62
|
-
return .undetermined
|
|
64
|
+
return _cachedState
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
/// Trigger the probe. Returns immediately with a `Promise` that
|
|
@@ -215,6 +217,15 @@ fileprivate final class ProbeRun {
|
|
|
215
217
|
|
|
216
218
|
private func handleBrowserState(_ state: NWBrowser.State) {
|
|
217
219
|
switch state {
|
|
220
|
+
case .waiting(let error):
|
|
221
|
+
// Denial surfaces here, not in `.failed`: refusing local-network access
|
|
222
|
+
// leaves the browser waiting with kDNSServiceErr_PolicyDenied (-65570).
|
|
223
|
+
// `.waiting` is also the ordinary "no connectivity yet" state, so only
|
|
224
|
+
// the error code decides — anything else stays unresolved and lets the
|
|
225
|
+
// timeout or a later state settle it.
|
|
226
|
+
if Self.isLocalNetworkDeniedError(error) {
|
|
227
|
+
resolve(.denied)
|
|
228
|
+
}
|
|
218
229
|
case .failed(let error):
|
|
219
230
|
if Self.isLocalNetworkDeniedError(error) {
|
|
220
231
|
resolve(.denied)
|
|
@@ -252,14 +263,24 @@ fileprivate final class ProbeRun {
|
|
|
252
263
|
for p in resolvedPromises { p.resolve(withResult: state) }
|
|
253
264
|
}
|
|
254
265
|
|
|
255
|
-
/// Detect the
|
|
256
|
-
///
|
|
257
|
-
///
|
|
258
|
-
/// `.
|
|
266
|
+
/// Detect the local-network-denied error.
|
|
267
|
+
///
|
|
268
|
+
/// A denied browse reports `kDNSServiceErr_PolicyDenied` (-65570) as
|
|
269
|
+
/// `NWError.dns`, which is the form that actually arrives on the `.waiting`
|
|
270
|
+
/// path. `NWError.posix(.EACCES)` is kept for the listener side, which
|
|
271
|
+
/// reports the same refusal as a POSIX error. Everything else (no Wi-Fi,
|
|
272
|
+
/// system error) is not a denial and falls through.
|
|
259
273
|
static func isLocalNetworkDeniedError(_ error: NWError) -> Bool {
|
|
260
274
|
if case .posix(let code) = error, code == .EACCES {
|
|
261
275
|
return true
|
|
262
276
|
}
|
|
277
|
+
if case .dns(let code) = error, code == Self.dnsPolicyDenied {
|
|
278
|
+
return true
|
|
279
|
+
}
|
|
263
280
|
return false
|
|
264
281
|
}
|
|
282
|
+
|
|
283
|
+
/// `kDNSServiceErr_PolicyDenied`. Spelled out rather than imported so the
|
|
284
|
+
/// probe does not pull in dnssd for one constant.
|
|
285
|
+
private static let dnsPolicyDenied: DNSServiceErrorType = -65570
|
|
265
286
|
}
|
|
@@ -28,12 +28,6 @@ final class MediaTokenRegistry {
|
|
|
28
28
|
return entries[token]
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
func revoke(_ token: String) {
|
|
32
|
-
lock.lock()
|
|
33
|
-
entries.removeValue(forKey: token)
|
|
34
|
-
lock.unlock()
|
|
35
|
-
}
|
|
36
|
-
|
|
37
31
|
func revokeAll(sessionId: String) {
|
|
38
32
|
lock.lock()
|
|
39
33
|
entries = entries.filter { $0.value.sessionId != sessionId }
|
package/ios/CastManager.swift
CHANGED
|
@@ -30,6 +30,7 @@ class CastManager: HybridCastManagerSpec {
|
|
|
30
30
|
private var nextListenerId: Int64 = 0
|
|
31
31
|
private let listenerLock = NSLock()
|
|
32
32
|
|
|
33
|
+
private let connectLock = NSLock()
|
|
33
34
|
/// Pending JS `connect()` promise for an in-flight Chromecast attempt.
|
|
34
35
|
/// Resolved from `handleSessionLifecycle(.connected)` once the route is
|
|
35
36
|
/// live, rejected on `.error` — the same contract as the Android
|
|
@@ -37,7 +38,6 @@ class CastManager: HybridCastManagerSpec {
|
|
|
37
38
|
/// receiver is actually attached. Guarded by `connectLock`: installed
|
|
38
39
|
/// on the JS thread in `connect`, cleared on the main thread from the
|
|
39
40
|
/// session lifecycle handler.
|
|
40
|
-
private let connectLock = NSLock()
|
|
41
41
|
private var pendingChromecastConnect: Promise<Void>?
|
|
42
42
|
|
|
43
43
|
override init() {
|