@javascriptcommon/react-native-track-player 1.2.9 → 4.1.4
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/LICENSE +201 -21
- package/README.md +8 -0
- package/android/build.gradle +92 -18
- package/android/proguard-rules.txt +0 -3
- package/android/src/main/AndroidManifest.xml +10 -13
- package/android/src/main/java/com/doublesymmetry/trackplayer/HeadlessJsMediaService.kt +199 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/TrackPlayer.kt +33 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/EnumExtensions.kt +5 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/NumberExt.kt +13 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/MetadataAdapter.kt +227 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/NowPlayingMetadata.kt +16 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/PlaybackMetadata.kt +203 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/State.kt +13 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/Track.kt +67 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/TrackAudioItem.kt +18 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/model/TrackMetadata.kt +38 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/module/MusicEvents.kt +67 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/module/MusicModule.kt +778 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/service/MusicService.kt +1286 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/utils/AppForegroundTracker.kt +35 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/utils/BundleUtils.kt +147 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/utils/CoilBitmapLoader.kt +65 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/utils/MediaItemBuilder.kt +41 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/utils/RejectionException.kt +11 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/video/TrackPlayerVideoView.kt +42 -0
- package/android/src/main/java/com/doublesymmetry/trackplayer/video/TrackPlayerVideoViewManager.kt +18 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/event/EventHolder.kt +30 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/event/PlayerEventHolder.kt +124 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioContentType.kt +10 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioItem.kt +118 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioPlayerState.kt +30 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/BufferConfig.kt +8 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/CacheConfig.kt +17 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/Capability.kt +19 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/CustomButton.kt +19 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/FocusChangeData.kt +3 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/MediaSessionCallback.kt +17 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayWhenReadyChangeData.kt +3 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlaybackError.kt +6 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayerConfig.kt +36 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayerOptions.kt +40 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PositionChangedReason.kt +39 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/RepeatMode.kt +16 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/WakeMode.kt +7 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/AudioPlayer.kt +756 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/ForwardingPlayer.java +1124 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/QueuedAudioPlayer.kt +279 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/APMRenderersFactory.kt +33 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/Buffer.kt +34 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/Cache.kt +27 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/FocusManager.kt +59 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/MediaFactory.kt +130 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/processors/TeeListener.kt +171 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/service/MusicService.kt +127 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/utils/FFT.java +99 -0
- package/android/src/main/java/com/lovegaoshi/kotlinaudio/utils/Utils.kt +113 -0
- package/android/src/main/res/drawable/baseline_repeat_24.xml +5 -0
- package/android/src/main/res/drawable/baseline_repeat_one_24.xml +5 -0
- package/android/src/main/res/drawable/forward.xml +5 -0
- package/android/src/main/res/drawable/heart_24px.xml +5 -0
- package/android/src/main/res/drawable/hearte_24px.xml +5 -0
- package/android/src/main/res/drawable/ifl_24px.xml +5 -0
- package/android/src/main/res/drawable/rewind.xml +5 -0
- package/android/src/main/res/drawable/shuffle_24px.xml +5 -0
- package/android/src/main/res/values/strings.xml +5 -0
- package/android/src/main/res/xml/automotive_app_desc.xml +3 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/22AMI.imageset/22AMillion.jpg +0 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/22AMI.imageset/Contents.json +21 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/Contents.json +6 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/cover.imageset/Contents.json +21 -0
- package/ios/Example/SwiftAudio/Assets.xcassets/cover.imageset/cover.jpg +0 -0
- package/ios/Example/SwiftAudio/AudioController.swift +46 -0
- package/ios/Example/SwiftAudio/Extensions.swift +22 -0
- package/ios/Example/SwiftAudio/PlayerView.swift +172 -0
- package/ios/Example/SwiftAudio/PlayerViewModel.swift +120 -0
- package/ios/Example/SwiftAudio/Preview Content/Preview Assets.xcassets/Contents.json +6 -0
- package/ios/Example/SwiftAudio/QueueView.swift +65 -0
- package/ios/{TrackPlayer.xcodeproj/xcuserdata/marco.xcuserdatad/xcschemes/xcschememanagement.plist → Example/SwiftAudio/SwiftAudio.entitlements} +6 -8
- package/ios/Example/SwiftAudio/SwiftAudioApp.swift +17 -0
- package/ios/Example/SwiftAudio.xcodeproj/project.pbxproj +412 -0
- package/ios/{TrackPlayer.xcodeproj → Example/SwiftAudio.xcodeproj}/project.xcworkspace/contents.xcworkspacedata +1 -1
- package/ios/RNTrackPlayer/Models/Capabilities.swift +39 -4
- package/ios/RNTrackPlayer/Models/MediaURL.swift +12 -6
- package/ios/RNTrackPlayer/Models/MetadataAdapter.swift +147 -0
- package/ios/RNTrackPlayer/Models/PitchAlgorithms.swift +13 -0
- package/ios/RNTrackPlayer/Models/SessionCategories.swift +106 -0
- package/ios/RNTrackPlayer/Models/State.swift +26 -0
- package/ios/RNTrackPlayer/Models/Track.swift +74 -54
- package/ios/RNTrackPlayer/RNTrackPlayer.swift +867 -406
- package/ios/RNTrackPlayer/Support/RNTrackPlayer-Bridging-Header.h +1 -0
- package/ios/RNTrackPlayer/TrackPlayer.h +14 -0
- package/ios/RNTrackPlayer/TrackPlayer.mm +249 -0
- package/ios/RNTrackPlayer/Utils/EventType.swift +45 -0
- package/ios/RNTrackPlayer/Utils/Metadata.swift +60 -0
- package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoView.swift +83 -0
- package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoViewManager.m +5 -0
- package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoViewManager.swift +17 -0
- package/ios/SwiftAudioEx/Package.swift +20 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapper.swift +531 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperDelegate.swift +27 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperProtocol.swift +69 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperState.swift +43 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioItem.swift +158 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioPlayer.swift +459 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioPlayerError.swift +26 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioSessionController/AudioSession.swift +33 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioSessionController/AudioSessionController.swift +135 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioTap.swift +96 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Event.swift +155 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/MediaItemProperty.swift +95 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoCenter.swift +17 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoController.swift +73 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoControllerProtocol.swift +26 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoKeyValue.swift +14 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoProperty.swift +234 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerItemNotificationObserver.swift +102 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerItemObserver.swift +136 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerObserver.swift +120 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerTimeObserver.swift +112 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/QueueManager.swift +356 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/QueuedAudioPlayer.swift +236 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RemoteCommandController/RemoteCommand.swift +170 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RemoteCommandController/RemoteCommandController.swift +206 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RepeatMode.swift +15 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/TimeEventFrequency.swift +26 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Utils/DispatchQueueType.swift +18 -0
- package/ios/SwiftAudioEx/Sources/SwiftAudioEx/WaveformAudioTap.swift +159 -0
- package/lib/specs/NativeTrackPlayer.d.ts +134 -0
- package/lib/specs/NativeTrackPlayer.js +4 -0
- package/lib/src/TrackPlayerModule.web.d.ts +2 -0
- package/lib/src/TrackPlayerModule.web.js +2 -0
- package/lib/src/VideoView.d.ts +16 -0
- package/lib/src/VideoView.js +25 -0
- package/lib/src/constants/AndroidAudioContentType.d.ts +35 -0
- package/lib/src/constants/AndroidAudioContentType.js +36 -0
- package/lib/src/constants/AndroidAutoContentStyle.d.ts +10 -0
- package/lib/src/constants/AndroidAutoContentStyle.js +11 -0
- package/lib/src/constants/AppKilledPlaybackBehavior.d.ts +17 -0
- package/lib/src/constants/AppKilledPlaybackBehavior.js +18 -0
- package/lib/src/constants/Capability.d.ts +17 -0
- package/lib/src/constants/Capability.js +19 -0
- package/lib/src/constants/Event.d.ts +172 -0
- package/lib/src/constants/Event.js +173 -0
- package/lib/src/constants/IOSCategory.d.ts +36 -0
- package/lib/src/constants/IOSCategory.js +37 -0
- package/lib/src/constants/IOSCategoryMode.d.ts +47 -0
- package/lib/src/constants/IOSCategoryMode.js +48 -0
- package/lib/src/constants/IOSCategoryOptions.d.ts +44 -0
- package/lib/src/constants/IOSCategoryOptions.js +45 -0
- package/lib/src/constants/MediaItemPlayable.d.ts +4 -0
- package/lib/src/constants/MediaItemPlayable.js +5 -0
- package/lib/src/constants/PitchAlgorithm.d.ts +14 -0
- package/lib/src/constants/PitchAlgorithm.js +16 -0
- package/lib/src/constants/RatingType.d.ts +8 -0
- package/lib/src/constants/RatingType.js +10 -0
- package/lib/src/constants/RepeatMode.d.ts +8 -0
- package/lib/src/constants/RepeatMode.js +10 -0
- package/lib/src/constants/State.d.ts +34 -0
- package/lib/src/constants/State.js +35 -0
- package/lib/src/constants/TrackType.d.ts +6 -0
- package/lib/src/constants/TrackType.js +7 -0
- package/lib/src/constants/index.d.ts +14 -0
- package/lib/src/constants/index.js +14 -0
- package/lib/src/hooks/index.d.ts +6 -0
- package/lib/src/hooks/index.js +6 -0
- package/lib/src/hooks/useActiveTrack.d.ts +2 -0
- package/lib/src/hooks/useActiveTrack.js +28 -0
- package/lib/src/hooks/useAppIsInBackground.d.ts +1 -0
- package/lib/src/hooks/useAppIsInBackground.js +16 -0
- package/lib/src/hooks/useIsPlaying.d.ts +35 -0
- package/lib/src/hooks/useIsPlaying.js +50 -0
- package/lib/src/hooks/usePlayWhenReady.d.ts +1 -0
- package/lib/src/hooks/usePlayWhenReady.js +27 -0
- package/lib/src/hooks/usePlaybackState.d.ts +10 -0
- package/lib/src/hooks/usePlaybackState.js +35 -0
- package/lib/src/hooks/useProgress.d.ts +7 -0
- package/lib/src/hooks/useProgress.js +55 -0
- package/lib/src/hooks/useTrackPlayerEvents.d.ts +8 -0
- package/lib/src/hooks/useTrackPlayerEvents.js +30 -0
- package/lib/src/index.d.ts +6 -0
- package/lib/src/index.js +6 -0
- package/lib/src/interfaces/AndroidAutoBrowseTree.d.ts +5 -0
- package/lib/src/interfaces/AndroidAutoBrowseTree.js +1 -0
- package/lib/src/interfaces/AndroidOptions.d.ts +41 -0
- package/lib/src/interfaces/AndroidOptions.js +1 -0
- package/lib/src/interfaces/CustomButtons.d.ts +5 -0
- package/lib/src/interfaces/CustomButtons.js +1 -0
- package/lib/src/interfaces/FeedbackOptions.d.ts +6 -0
- package/lib/src/interfaces/FeedbackOptions.js +1 -0
- package/lib/src/interfaces/MediaItem.d.ts +18 -0
- package/lib/src/interfaces/MediaItem.js +1 -0
- package/lib/src/interfaces/MetadataOptions.d.ts +3 -0
- package/lib/src/interfaces/MetadataOptions.js +1 -0
- package/lib/src/interfaces/NowPlayingMetadata.d.ts +4 -0
- package/lib/src/interfaces/NowPlayingMetadata.js +1 -0
- package/lib/src/interfaces/PlaybackState.d.ts +8 -0
- package/lib/src/interfaces/PlaybackState.js +1 -0
- package/lib/src/interfaces/PlayerOptions.d.ts +132 -0
- package/lib/src/interfaces/PlayerOptions.js +1 -0
- package/lib/src/interfaces/Progress.d.ts +15 -0
- package/lib/src/interfaces/Progress.js +1 -0
- package/lib/src/interfaces/ResourceObject.d.ts +1 -0
- package/lib/src/interfaces/ResourceObject.js +1 -0
- package/lib/src/interfaces/ServiceHandler.d.ts +1 -0
- package/lib/src/interfaces/ServiceHandler.js +1 -0
- package/lib/src/interfaces/Track.d.ts +21 -0
- package/lib/src/interfaces/Track.js +1 -0
- package/lib/src/interfaces/TrackMetadataBase.d.ts +28 -0
- package/lib/src/interfaces/TrackMetadataBase.js +1 -0
- package/lib/src/interfaces/UpdateOptions.d.ts +52 -0
- package/lib/src/interfaces/UpdateOptions.js +1 -0
- package/lib/src/interfaces/events/AudioMetadataReceivedEvent.d.ts +33 -0
- package/lib/src/interfaces/events/AudioMetadataReceivedEvent.js +1 -0
- package/lib/src/interfaces/events/ControllerConnectedEvent.d.ts +8 -0
- package/lib/src/interfaces/events/ControllerConnectedEvent.js +1 -0
- package/lib/src/interfaces/events/EventPayloadByEvent.d.ts +77 -0
- package/lib/src/interfaces/events/EventPayloadByEvent.js +1 -0
- package/lib/src/interfaces/events/FFTUpdateEvent.d.ts +7 -0
- package/lib/src/interfaces/events/FFTUpdateEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackActiveTrackChangedEvent.d.ts +24 -0
- package/lib/src/interfaces/events/PlaybackActiveTrackChangedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.d.ts +4 -0
- package/lib/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackErrorEvent.d.ts +6 -0
- package/lib/src/interfaces/events/PlaybackErrorEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackMetadataReceivedEvent.d.ts +16 -0
- package/lib/src/interfaces/events/PlaybackMetadataReceivedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.d.ts +4 -0
- package/lib/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackProgressUpdatedEvent.d.ts +4 -0
- package/lib/src/interfaces/events/PlaybackProgressUpdatedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackQueueEndedEvent.d.ts +9 -0
- package/lib/src/interfaces/events/PlaybackQueueEndedEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackResumeEvent.d.ts +3 -0
- package/lib/src/interfaces/events/PlaybackResumeEvent.js +1 -0
- package/lib/src/interfaces/events/PlaybackTrackChangedEvent.d.ts +11 -0
- package/lib/src/interfaces/events/PlaybackTrackChangedEvent.js +1 -0
- package/lib/src/interfaces/events/PlayerErrorEvent.d.ts +6 -0
- package/lib/src/interfaces/events/PlayerErrorEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteBrowseEvent.d.ts +4 -0
- package/lib/src/interfaces/events/RemoteBrowseEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteCustomActionEvent.d.ts +7 -0
- package/lib/src/interfaces/events/RemoteCustomActionEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteDuckEvent.d.ts +13 -0
- package/lib/src/interfaces/events/RemoteDuckEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteJumpBackwardEvent.d.ts +7 -0
- package/lib/src/interfaces/events/RemoteJumpBackwardEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteJumpForwardEvent.d.ts +7 -0
- package/lib/src/interfaces/events/RemoteJumpForwardEvent.js +1 -0
- package/lib/src/interfaces/events/RemotePlayIdEvent.d.ts +4 -0
- package/lib/src/interfaces/events/RemotePlayIdEvent.js +1 -0
- package/lib/src/interfaces/events/RemotePlaySearchEvent.d.ts +9 -0
- package/lib/src/interfaces/events/RemotePlaySearchEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteSearchEvent.d.ts +3 -0
- package/lib/src/interfaces/events/RemoteSearchEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteSeekEvent.d.ts +4 -0
- package/lib/src/interfaces/events/RemoteSeekEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteSetRatingEvent.d.ts +4 -0
- package/lib/src/interfaces/events/RemoteSetRatingEvent.js +1 -0
- package/lib/src/interfaces/events/RemoteSkipEvent.d.ts +3 -0
- package/lib/src/interfaces/events/RemoteSkipEvent.js +1 -0
- package/lib/src/interfaces/events/index.d.ts +20 -0
- package/lib/src/interfaces/events/index.js +20 -0
- package/lib/src/interfaces/index.d.ts +15 -0
- package/lib/src/interfaces/index.js +15 -0
- package/lib/src/resolveAssetSource.d.ts +2 -0
- package/lib/src/resolveAssetSource.js +3 -0
- package/lib/src/resolveAssetSource.web.d.ts +2 -0
- package/lib/src/resolveAssetSource.web.js +8 -0
- package/lib/src/trackPlayer.d.ts +371 -0
- package/lib/src/trackPlayer.js +627 -0
- package/lib/web/TrackPlayer/Player.d.ts +40 -0
- package/lib/web/TrackPlayer/Player.js +188 -0
- package/lib/web/TrackPlayer/PlaylistPlayer.d.ts +31 -0
- package/lib/web/TrackPlayer/PlaylistPlayer.js +181 -0
- package/lib/web/TrackPlayer/RepeatMode.d.ts +5 -0
- package/lib/web/TrackPlayer/RepeatMode.js +6 -0
- package/lib/web/TrackPlayer/SetupNotCalledError.d.ts +3 -0
- package/lib/web/TrackPlayer/SetupNotCalledError.js +5 -0
- package/lib/web/TrackPlayer/index.d.ts +3 -0
- package/lib/web/TrackPlayer/index.js +3 -0
- package/lib/web/TrackPlayerModule.d.ts +63 -0
- package/lib/web/TrackPlayerModule.js +153 -0
- package/lib/web/index.d.ts +3 -0
- package/lib/web/index.js +3 -0
- package/package.json +85 -6
- package/react-native-track-player.podspec +13 -13
- package/specs/NativeTrackPlayer.ts +153 -0
- package/src/TrackPlayerModule.web.ts +2 -0
- package/src/VideoView.tsx +51 -0
- package/src/constants/AndroidAudioContentType.ts +35 -0
- package/src/constants/AndroidAutoContentStyle.ts +10 -0
- package/src/constants/AppKilledPlaybackBehavior.ts +19 -0
- package/src/constants/Capability.ts +19 -0
- package/src/constants/Event.ts +173 -0
- package/src/constants/IOSCategory.ts +36 -0
- package/src/constants/IOSCategoryMode.ts +47 -0
- package/src/constants/IOSCategoryOptions.ts +44 -0
- package/src/constants/MediaItemPlayable.ts +4 -0
- package/src/constants/PitchAlgorithm.ts +16 -0
- package/src/constants/RatingType.ts +10 -0
- package/src/constants/RepeatMode.ts +10 -0
- package/src/constants/State.ts +34 -0
- package/src/constants/TrackType.ts +6 -0
- package/src/constants/index.ts +14 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useActiveTrack.ts +36 -0
- package/src/hooks/useAppIsInBackground.ts +20 -0
- package/src/hooks/useIsPlaying.ts +56 -0
- package/src/hooks/usePlayWhenReady.ts +37 -0
- package/src/hooks/usePlaybackState.ts +45 -0
- package/src/hooks/useProgress.ts +64 -0
- package/src/hooks/useTrackPlayerEvents.ts +48 -0
- package/src/index.ts +8 -0
- package/src/interfaces/AndroidAutoBrowseTree.ts +6 -0
- package/src/interfaces/AndroidOptions.ts +48 -0
- package/src/interfaces/CustomButtons.ts +6 -0
- package/src/interfaces/FeedbackOptions.ts +7 -0
- package/src/interfaces/MediaItem.ts +19 -0
- package/src/interfaces/MetadataOptions.ts +4 -0
- package/src/interfaces/NowPlayingMetadata.ts +5 -0
- package/src/interfaces/PlaybackState.ts +11 -0
- package/src/interfaces/PlayerOptions.ts +138 -0
- package/src/interfaces/Progress.ts +15 -0
- package/src/interfaces/ResourceObject.ts +1 -0
- package/src/interfaces/ServiceHandler.ts +1 -0
- package/src/interfaces/Track.ts +23 -0
- package/src/interfaces/TrackMetadataBase.ts +29 -0
- package/src/interfaces/UpdateOptions.ts +59 -0
- package/src/interfaces/events/AudioMetadataReceivedEvent.ts +37 -0
- package/src/interfaces/events/ControllerConnectedEvent.ts +9 -0
- package/src/interfaces/events/EventPayloadByEvent.ts +80 -0
- package/src/interfaces/events/FFTUpdateEvent.ts +9 -0
- package/src/interfaces/events/PlaybackActiveTrackChangedEvent.ts +29 -0
- package/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.ts +4 -0
- package/src/interfaces/events/PlaybackErrorEvent.ts +6 -0
- package/src/interfaces/events/PlaybackMetadataReceivedEvent.ts +16 -0
- package/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.ts +4 -0
- package/src/interfaces/events/PlaybackProgressUpdatedEvent.ts +5 -0
- package/src/interfaces/events/PlaybackQueueEndedEvent.ts +9 -0
- package/src/interfaces/events/PlaybackResumeEvent.ts +5 -0
- package/src/interfaces/events/PlaybackTrackChangedEvent.ts +11 -0
- package/src/interfaces/events/PlayerErrorEvent.ts +6 -0
- package/src/interfaces/events/RemoteBrowseEvent.ts +4 -0
- package/src/interfaces/events/RemoteCustomActionEvent.ts +7 -0
- package/src/interfaces/events/RemoteDuckEvent.ts +13 -0
- package/src/interfaces/events/RemoteJumpBackwardEvent.ts +7 -0
- package/src/interfaces/events/RemoteJumpForwardEvent.ts +7 -0
- package/src/interfaces/events/RemotePlayIdEvent.ts +4 -0
- package/src/interfaces/events/RemotePlaySearchEvent.ts +21 -0
- package/src/interfaces/events/RemoteSearchEvent.ts +3 -0
- package/src/interfaces/events/RemoteSeekEvent.ts +4 -0
- package/src/interfaces/events/RemoteSetRatingEvent.ts +5 -0
- package/src/interfaces/events/RemoteSkipEvent.ts +3 -0
- package/src/interfaces/events/index.ts +20 -0
- package/src/interfaces/index.ts +15 -0
- package/src/resolveAssetSource.ts +3 -0
- package/src/resolveAssetSource.web.ts +10 -0
- package/src/trackPlayer.ts +806 -0
- package/web/TrackPlayer/Player.ts +201 -0
- package/web/TrackPlayer/PlaylistPlayer.ts +215 -0
- package/web/TrackPlayer/RepeatMode.ts +6 -0
- package/web/TrackPlayer/SetupNotCalledError.ts +5 -0
- package/web/TrackPlayer/index.ts +3 -0
- package/web/TrackPlayerModule.ts +181 -0
- package/web/index.ts +4 -0
- package/CHANGELOG.md +0 -75
- package/android/react-native-music-control.iml +0 -139
- package/android/react-native-track-player.iml +0 -151
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
- package/android/src/main/java/com/guichaguri/trackplayer/service/HeadlessJsMediaService.java +0 -174
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
- package/android/src/main/res/drawable-hdpi/ic_forward.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_next.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_previous.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_rewind.png +0 -0
- package/android/src/main/res/drawable-hdpi/ic_stop.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_forward.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_next.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_previous.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_rewind.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_stop.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_forward.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_next.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_previous.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_rewind.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_stop.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_forward.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_next.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_previous.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_rewind.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_stop.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_forward.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_next.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_pause.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_play.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_previous.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_rewind.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_stop.png +0 -0
- package/index.d.ts +0 -174
- package/index.js +0 -4
- package/ios/RNTrackPlayer/RNTrackPlayerBridge.h +0 -12
- package/ios/RNTrackPlayer/RNTrackPlayerBridge.m +0 -29
- package/ios/TrackPlayer.xcodeproj/project.pbxproj +0 -495
- package/ios/TrackPlayer.xcodeproj/project.xcworkspace/xcuserdata/marco.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/lib/ProgressComponent.js +0 -70
- package/lib/eventTypes.js +0 -28
- package/lib/hooks.js +0 -160
- package/lib/index.js +0 -177
- /package/ios/{TrackPlayer.xcodeproj → Example/SwiftAudio.xcodeproj}/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -0
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
@file: OptIn(UnstableApi::class) package com.lovegaoshi.kotlinaudio.player
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.media.AudioManager
|
|
5
|
+
import android.media.audiofx.Equalizer
|
|
6
|
+
import android.media.audiofx.LoudnessEnhancer
|
|
7
|
+
import androidx.annotation.CallSuper
|
|
8
|
+
import androidx.annotation.OptIn
|
|
9
|
+
import androidx.media3.common.AudioAttributes
|
|
10
|
+
import androidx.media3.common.C
|
|
11
|
+
import androidx.media3.common.MediaItem
|
|
12
|
+
import androidx.media3.common.MediaMetadata
|
|
13
|
+
import androidx.media3.common.Metadata
|
|
14
|
+
import androidx.media3.common.PlaybackException
|
|
15
|
+
import androidx.media3.common.PlaybackParameters
|
|
16
|
+
import androidx.media3.common.Player
|
|
17
|
+
import androidx.media3.common.Player.Listener
|
|
18
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
19
|
+
import androidx.media3.common.util.UnstableApi
|
|
20
|
+
import androidx.media3.datasource.cache.SimpleCache
|
|
21
|
+
import androidx.media3.exoplayer.DefaultRenderersFactory
|
|
22
|
+
import androidx.media3.exoplayer.ExoPlayer
|
|
23
|
+
import androidx.media3.exoplayer.analytics.AnalyticsListener
|
|
24
|
+
import com.lovegaoshi.kotlinaudio.event.PlayerEventHolder
|
|
25
|
+
import com.lovegaoshi.kotlinaudio.models.AudioItem
|
|
26
|
+
import com.lovegaoshi.kotlinaudio.models.audioItem2MediaItem
|
|
27
|
+
import com.lovegaoshi.kotlinaudio.models.AudioItemTransitionReason
|
|
28
|
+
import com.lovegaoshi.kotlinaudio.models.AudioPlayerState
|
|
29
|
+
import com.lovegaoshi.kotlinaudio.models.mediaItem2AudioItem
|
|
30
|
+
import com.lovegaoshi.kotlinaudio.models.MediaSessionCallback
|
|
31
|
+
import com.lovegaoshi.kotlinaudio.models.PlayWhenReadyChangeData
|
|
32
|
+
import com.lovegaoshi.kotlinaudio.models.PlaybackError
|
|
33
|
+
import com.lovegaoshi.kotlinaudio.models.PlayerOptions
|
|
34
|
+
import com.lovegaoshi.kotlinaudio.models.PositionChangedReason
|
|
35
|
+
import com.lovegaoshi.kotlinaudio.models.setWakeMode
|
|
36
|
+
import com.lovegaoshi.kotlinaudio.player.components.APMRenderersFactory
|
|
37
|
+
import com.lovegaoshi.kotlinaudio.player.components.Cache
|
|
38
|
+
import com.lovegaoshi.kotlinaudio.player.components.FocusManager
|
|
39
|
+
import com.lovegaoshi.kotlinaudio.player.components.MediaFactory
|
|
40
|
+
import com.lovegaoshi.kotlinaudio.player.components.setupBuffer
|
|
41
|
+
import com.lovegaoshi.kotlinaudio.processors.FFTEmitter
|
|
42
|
+
import kotlinx.coroutines.Deferred
|
|
43
|
+
import kotlinx.coroutines.MainScope
|
|
44
|
+
import kotlinx.coroutines.async
|
|
45
|
+
import kotlinx.coroutines.delay
|
|
46
|
+
import kotlinx.coroutines.launch
|
|
47
|
+
import timber.log.Timber
|
|
48
|
+
import java.util.Locale
|
|
49
|
+
import java.util.concurrent.TimeUnit
|
|
50
|
+
import kotlin.math.min
|
|
51
|
+
|
|
52
|
+
abstract class AudioPlayer internal constructor(
|
|
53
|
+
private val context: Context,
|
|
54
|
+
val options: PlayerOptions = PlayerOptions()
|
|
55
|
+
) {
|
|
56
|
+
|
|
57
|
+
// for crossfading
|
|
58
|
+
private var exoPlayer1: ExoPlayer
|
|
59
|
+
private var exoPlayer2: ExoPlayer? = null
|
|
60
|
+
private var loudnessEnhancers = ArrayList<LoudnessEnhancer>()
|
|
61
|
+
private var equalizers = ArrayList<Equalizer>()
|
|
62
|
+
private var currentExoPlayer = true
|
|
63
|
+
|
|
64
|
+
var exoPlayer: ExoPlayer
|
|
65
|
+
var player: ForwardingPlayer
|
|
66
|
+
private var playerListener = PlayerListener()
|
|
67
|
+
private val scope = MainScope()
|
|
68
|
+
private var cache: SimpleCache? = null
|
|
69
|
+
val playerEventHolder = PlayerEventHolder()
|
|
70
|
+
private val focusListener = APMFocusListener()
|
|
71
|
+
private val focusManager = FocusManager(context, listener=focusListener, options=options)
|
|
72
|
+
var fftEmitter: (DoubleArray) -> Unit = { v -> Timber.tag("APMFFT").d("FFT emitted $v") }
|
|
73
|
+
|
|
74
|
+
var alwaysPauseOnInterruption: Boolean
|
|
75
|
+
get() = focusManager.alwaysPauseOnInterruption
|
|
76
|
+
set(v) { focusManager.alwaysPauseOnInterruption = v }
|
|
77
|
+
|
|
78
|
+
open val currentItem: AudioItem?
|
|
79
|
+
get() = mediaItem2AudioItem(exoPlayer.currentMediaItem)
|
|
80
|
+
|
|
81
|
+
var playbackError: PlaybackError? = null
|
|
82
|
+
var playerState: AudioPlayerState = AudioPlayerState.IDLE
|
|
83
|
+
private set(value) {
|
|
84
|
+
if (value != field) {
|
|
85
|
+
field = value
|
|
86
|
+
playerEventHolder.updateAudioPlayerState(value)
|
|
87
|
+
if (!options.handleAudioFocus) {
|
|
88
|
+
when (value) {
|
|
89
|
+
AudioPlayerState.IDLE,
|
|
90
|
+
AudioPlayerState.ERROR -> focusManager.abandonAudioFocusIfHeld()
|
|
91
|
+
AudioPlayerState.READY -> focusManager.requestAudioFocus()
|
|
92
|
+
else -> {}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var playWhenReady: Boolean
|
|
99
|
+
get() = exoPlayer.playWhenReady
|
|
100
|
+
set(value) {
|
|
101
|
+
exoPlayer.playWhenReady = value
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
val duration: Long
|
|
105
|
+
get() {
|
|
106
|
+
return if (exoPlayer.duration == C.TIME_UNSET) 0
|
|
107
|
+
else exoPlayer.duration
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
val isCurrentMediaItemLive: Boolean
|
|
111
|
+
get() = exoPlayer.isCurrentMediaItemLive
|
|
112
|
+
|
|
113
|
+
private var oldPosition = 0L
|
|
114
|
+
|
|
115
|
+
val position: Long
|
|
116
|
+
get() {
|
|
117
|
+
return if (exoPlayer.currentPosition == C.INDEX_UNSET.toLong()) 0
|
|
118
|
+
else exoPlayer.currentPosition
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
val bufferedPosition: Long
|
|
122
|
+
get() {
|
|
123
|
+
return if (exoPlayer.bufferedPosition == C.INDEX_UNSET.toLong()) 0
|
|
124
|
+
else exoPlayer.bufferedPosition
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private var volumeMultiplier = 1f
|
|
128
|
+
set(value) {
|
|
129
|
+
field = value
|
|
130
|
+
volume = volume
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
var volume: Float
|
|
134
|
+
get() = exoPlayer.volume
|
|
135
|
+
set(value) {
|
|
136
|
+
exoPlayer.volume = value * volumeMultiplier
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* fade volume of the current exoPlayer by a simple linear function.
|
|
141
|
+
*/
|
|
142
|
+
fun fadeVolume(volume: Float = 1f, duration: Long = 500, interval: Long = 20L, callback: () -> Unit = { }): Deferred<Unit> {
|
|
143
|
+
return scope.async {
|
|
144
|
+
val volumeDiff = (volume - exoPlayer.volume) * interval / duration
|
|
145
|
+
var fadeInDuration = duration
|
|
146
|
+
while (fadeInDuration > 0) {
|
|
147
|
+
fadeInDuration -= interval
|
|
148
|
+
exoPlayer.volume += volumeDiff
|
|
149
|
+
delay(interval)
|
|
150
|
+
}
|
|
151
|
+
exoPlayer.volume = volume
|
|
152
|
+
callback()
|
|
153
|
+
return@async
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
var playbackSpeed: Float
|
|
158
|
+
get() = exoPlayer.playbackParameters.speed
|
|
159
|
+
set(value) {
|
|
160
|
+
exoPlayer.setPlaybackSpeed(value)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
var playbackPitch: Float
|
|
164
|
+
get() = exoPlayer.playbackParameters.pitch
|
|
165
|
+
set(v) {
|
|
166
|
+
exoPlayer.playbackParameters = PlaybackParameters(playbackSpeed, v)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
val isPlaying
|
|
170
|
+
get() = exoPlayer.isPlaying
|
|
171
|
+
|
|
172
|
+
private var wasDucking = false
|
|
173
|
+
|
|
174
|
+
fun players (): List<ExoPlayer> {
|
|
175
|
+
if (options.crossfade) {
|
|
176
|
+
return listOf(exoPlayer1, exoPlayer2!!)
|
|
177
|
+
}
|
|
178
|
+
return listOf(exoPlayer)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fun setAudioOffload(offload: Boolean = true) {
|
|
182
|
+
val audioOffloadPreferences =
|
|
183
|
+
TrackSelectionParameters.AudioOffloadPreferences.Builder()
|
|
184
|
+
.setAudioOffloadMode(
|
|
185
|
+
if (offload) TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED
|
|
186
|
+
else TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED)
|
|
187
|
+
// Add additional options as needed
|
|
188
|
+
.setIsGaplessSupportRequired(true)
|
|
189
|
+
.setIsSpeedChangeSupportRequired(true)
|
|
190
|
+
.build()
|
|
191
|
+
exoPlayer.trackSelectionParameters =
|
|
192
|
+
exoPlayer.trackSelectionParameters
|
|
193
|
+
.buildUpon()
|
|
194
|
+
.setAudioOffloadPreferences(audioOffloadPreferences)
|
|
195
|
+
.build()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private fun initExoPlayer(name: String): ExoPlayer {
|
|
199
|
+
// HACK: horrible memleak, but I cant think of how to track exoplayers
|
|
200
|
+
val nameHolder = arrayOf("")
|
|
201
|
+
val renderer = if (options.useFFTProcessor > 0) APMRenderersFactory(
|
|
202
|
+
context, options.useFFTProcessor, object: FFTEmitter {
|
|
203
|
+
override fun onSpectrumReady(spectrum: FloatArray, maxRawAmp: Float) {
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
override fun onFrequencyFFTReady(fft: DoubleArray, max: Float) {
|
|
207
|
+
if (this@AudioPlayer.exoPlayer.toString() == nameHolder[0]) {
|
|
208
|
+
fftEmitter(fft)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
}) else DefaultRenderersFactory(context)
|
|
213
|
+
renderer.setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
|
|
214
|
+
val mPlayer = ExoPlayer
|
|
215
|
+
.Builder(context)
|
|
216
|
+
.setRenderersFactory(renderer)
|
|
217
|
+
.setHandleAudioBecomingNoisy(options.handleAudioBecomingNoisy)
|
|
218
|
+
.setMediaSourceFactory(MediaFactory(context, cache))
|
|
219
|
+
.setWakeMode(setWakeMode(options.wakeMode))
|
|
220
|
+
.apply {
|
|
221
|
+
setLoadControl(setupBuffer(options.bufferOptions))
|
|
222
|
+
}
|
|
223
|
+
.setSkipSilenceEnabled(options.skipSilence)
|
|
224
|
+
.setName(name)
|
|
225
|
+
.build()
|
|
226
|
+
val audioAttributes = AudioAttributes.Builder()
|
|
227
|
+
.setUsage(C.USAGE_MEDIA)
|
|
228
|
+
.setContentType(options.audioContentType)
|
|
229
|
+
.build()
|
|
230
|
+
mPlayer.setAudioAttributes(audioAttributes, options.handleAudioFocus)
|
|
231
|
+
nameHolder[0] = mPlayer.toString()
|
|
232
|
+
// https://github.com/androidx/media/issues/2319
|
|
233
|
+
mPlayer.addAnalyticsListener(AudioFxInitListener())
|
|
234
|
+
return mPlayer
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
init {
|
|
238
|
+
if (options.cacheSize > 0) {
|
|
239
|
+
cache = Cache.initCache(context, options.cacheSize)
|
|
240
|
+
}
|
|
241
|
+
playerEventHolder.updateAudioPlayerState(AudioPlayerState.IDLE)
|
|
242
|
+
exoPlayer1 = initExoPlayer("APM-Player1")
|
|
243
|
+
if (options.crossfade) { exoPlayer2 = initExoPlayer("APM-Player2") }
|
|
244
|
+
exoPlayer = exoPlayer1
|
|
245
|
+
player = if (options.nativeExample) ExampleForwardingPlayer(exoPlayer1, exoPlayer2) else APMForwardingPlayer(exoPlayer1, exoPlayer2)
|
|
246
|
+
player.addListener(playerListener)
|
|
247
|
+
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Will replace the current item with a new one and load it into the player.
|
|
252
|
+
* @param item The [AudioItem] to replace the current one.
|
|
253
|
+
* @param playWhenReady Whether playback starts automatically.
|
|
254
|
+
*/
|
|
255
|
+
open fun load(item: AudioItem, playWhenReady: Boolean = true) {
|
|
256
|
+
exoPlayer.playWhenReady = playWhenReady
|
|
257
|
+
load(item)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Will replace the current item with a new one and load it into the player.
|
|
262
|
+
* @param item The [AudioItem] to replace the current one.
|
|
263
|
+
*/
|
|
264
|
+
open fun load(item: AudioItem) {
|
|
265
|
+
players().forEach { p -> p.addMediaItem(audioItem2MediaItem(item)) }
|
|
266
|
+
exoPlayer.prepare()
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
fun setLoudnessEnhance(gain: Int) {
|
|
270
|
+
loudnessEnhancers.forEach { l ->
|
|
271
|
+
l.setTargetGain(gain)
|
|
272
|
+
l.enabled = true
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
fun setEqualizerPreset(preset: Int) {
|
|
277
|
+
equalizers.forEach { equalizer ->
|
|
278
|
+
equalizer.usePreset(preset.toShort())
|
|
279
|
+
equalizer.enabled = true
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
fun getCurrentEQPreset(): Int {
|
|
284
|
+
if (equalizers.isEmpty()) {
|
|
285
|
+
return -1
|
|
286
|
+
}
|
|
287
|
+
return equalizers[0].currentPreset.toInt()
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
fun getEqualizerPresets(): List<String> {
|
|
291
|
+
if (equalizers.isEmpty()) {
|
|
292
|
+
return arrayListOf()
|
|
293
|
+
}
|
|
294
|
+
return Array(equalizers[0].numberOfPresets.toInt()) { i -> i }
|
|
295
|
+
.map { i -> equalizers[0].getPresetName(i.toShort()) }
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
fun togglePlaying() {
|
|
299
|
+
if (exoPlayer.isPlaying) {
|
|
300
|
+
pause()
|
|
301
|
+
} else {
|
|
302
|
+
play()
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
var skipSilence: Boolean
|
|
307
|
+
get() = exoPlayer.skipSilenceEnabled
|
|
308
|
+
set(value) {
|
|
309
|
+
players().forEach { p -> p.skipSilenceEnabled = value }
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
fun play() {
|
|
313
|
+
exoPlayer.play()
|
|
314
|
+
if (currentItem != null) {
|
|
315
|
+
exoPlayer.prepare()
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
fun prepare() {
|
|
320
|
+
if (currentItem != null) {
|
|
321
|
+
exoPlayer.prepare()
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
fun pause() {
|
|
326
|
+
exoPlayer.pause()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Stops playback, without clearing the active item. Calling this method will cause the playback
|
|
331
|
+
* state to transition to AudioPlayerState.IDLE and the player will release the loaded media and
|
|
332
|
+
* resources required for playback.
|
|
333
|
+
*/
|
|
334
|
+
@CallSuper
|
|
335
|
+
open fun stop() {
|
|
336
|
+
playerState = AudioPlayerState.STOPPED
|
|
337
|
+
exoPlayer.playWhenReady = false
|
|
338
|
+
exoPlayer.stop()
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@CallSuper
|
|
342
|
+
open fun clear() {
|
|
343
|
+
players().forEach { p -> p.clearMediaItems() }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Pause playback whenever an item plays to its end.
|
|
348
|
+
*/
|
|
349
|
+
fun setPauseAtEndOfItem(pause: Boolean) {
|
|
350
|
+
exoPlayer.pauseAtEndOfMediaItems = pause
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Stops and destroys the player. Only call this when you are finished using the player, otherwise use [pause].
|
|
355
|
+
*/
|
|
356
|
+
@CallSuper
|
|
357
|
+
open fun destroy() {
|
|
358
|
+
focusManager.abandonAudioFocusIfHeld()
|
|
359
|
+
stop()
|
|
360
|
+
|
|
361
|
+
players().forEach { p ->
|
|
362
|
+
p.removeListener(playerListener)
|
|
363
|
+
p.release()
|
|
364
|
+
}
|
|
365
|
+
equalizers.forEach { e -> e.release() }
|
|
366
|
+
loudnessEnhancers.forEach { e -> e.release() }
|
|
367
|
+
cache?.release()
|
|
368
|
+
cache = null
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
open fun seek(duration: Long, unit: TimeUnit) {
|
|
372
|
+
val positionMs = TimeUnit.MILLISECONDS.convert(duration, unit)
|
|
373
|
+
exoPlayer.seekTo(positionMs)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
open fun seekBy(offset: Long, unit: TimeUnit) {
|
|
377
|
+
val positionMs = exoPlayer.currentPosition + TimeUnit.MILLISECONDS.convert(offset, unit)
|
|
378
|
+
exoPlayer.seekTo(positionMs)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
fun crossFadePrepare(previous: Boolean = false, seekTo: Double = 0.0) {
|
|
382
|
+
if (!options.crossfade) { return }
|
|
383
|
+
val mPlayer = if (currentExoPlayer) exoPlayer2!! else exoPlayer1
|
|
384
|
+
// align playing index
|
|
385
|
+
mPlayer.seekTo(exoPlayer.currentMediaItemIndex, C.TIME_UNSET)
|
|
386
|
+
if (previous) { mPlayer.seekToPreviousMediaItem() }
|
|
387
|
+
else { mPlayer.seekToNextMediaItem() }
|
|
388
|
+
mPlayer.prepare()
|
|
389
|
+
if (seekTo > 0) {
|
|
390
|
+
mPlayer.seekTo((seekTo * 1000).toLong())
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* switches rotating exoplayers to achieve crossfade.
|
|
396
|
+
* playerOperation:
|
|
397
|
+
*/
|
|
398
|
+
fun switchExoPlayer(
|
|
399
|
+
playerOperation: () -> Unit = ::play,
|
|
400
|
+
fadeDuration: Long = 2500,
|
|
401
|
+
fadeInterval: Long = 20,
|
|
402
|
+
fadeToVolume: Float = 1f,
|
|
403
|
+
waitUntil: Long = 0,
|
|
404
|
+
){
|
|
405
|
+
if (!options.crossfade) {
|
|
406
|
+
playerOperation()
|
|
407
|
+
return
|
|
408
|
+
}
|
|
409
|
+
scope.launch {
|
|
410
|
+
val delayAmount = if (waitUntil == 0L) 0 else {
|
|
411
|
+
0L.coerceAtLeast(waitUntil - player.currentPosition)
|
|
412
|
+
}
|
|
413
|
+
delay(delayAmount)
|
|
414
|
+
|
|
415
|
+
val prevPlayer: Player
|
|
416
|
+
if (currentExoPlayer) {
|
|
417
|
+
currentExoPlayer = false
|
|
418
|
+
exoPlayer = exoPlayer2!!
|
|
419
|
+
prevPlayer = exoPlayer1
|
|
420
|
+
} else {
|
|
421
|
+
currentExoPlayer = true
|
|
422
|
+
exoPlayer = exoPlayer1
|
|
423
|
+
prevPlayer = exoPlayer2!!
|
|
424
|
+
}
|
|
425
|
+
prevPlayer.setAudioAttributes(prevPlayer.audioAttributes, false)
|
|
426
|
+
player.switchCrossFadePlayer()
|
|
427
|
+
scope.launch {
|
|
428
|
+
var fadeOutDuration = fadeDuration
|
|
429
|
+
val startFadeOutTime = System.currentTimeMillis()
|
|
430
|
+
val fadeFromVolume = prevPlayer.volume
|
|
431
|
+
while (fadeOutDuration > 0) {
|
|
432
|
+
fadeOutDuration -= fadeInterval
|
|
433
|
+
prevPlayer.volume = fadeFromVolume * (1 - min((System.currentTimeMillis() - startFadeOutTime), fadeDuration).toFloat() / fadeDuration)
|
|
434
|
+
delay(fadeInterval)
|
|
435
|
+
}
|
|
436
|
+
prevPlayer.volume = 0f
|
|
437
|
+
prevPlayer.pause()
|
|
438
|
+
}
|
|
439
|
+
scope.launch {
|
|
440
|
+
exoPlayer.volume = 0f
|
|
441
|
+
playerOperation()
|
|
442
|
+
exoPlayer.setAudioAttributes(exoPlayer.audioAttributes, options.handleAudioFocus)
|
|
443
|
+
if (fadeToVolume > 0) {
|
|
444
|
+
var fadeInDuration = fadeDuration
|
|
445
|
+
val startTime = System.currentTimeMillis()
|
|
446
|
+
while (fadeInDuration > 0) {
|
|
447
|
+
fadeInDuration -= fadeInterval
|
|
448
|
+
exoPlayer.volume = fadeToVolume * min((System.currentTimeMillis() - startTime), fadeDuration) / fadeDuration
|
|
449
|
+
delay(fadeInterval)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// player.broadcastMediaItem()
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
inner class AudioFxInitListener: AnalyticsListener {
|
|
458
|
+
@OptIn(UnstableApi::class)
|
|
459
|
+
override fun onAudioSessionIdChanged(eventTime: AnalyticsListener.EventTime, audioSessionId: Int) {
|
|
460
|
+
// Try to add LoudnessEnhancer
|
|
461
|
+
try {
|
|
462
|
+
val enhancer = LoudnessEnhancer(audioSessionId)
|
|
463
|
+
loudnessEnhancers.add(enhancer)
|
|
464
|
+
} catch (e: RuntimeException) {
|
|
465
|
+
Timber.tag("APMAudioFx").e("[AudioFx] failed to load loudnessEnhancer. it's fine if in dev!")
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Try to add Equalizer
|
|
469
|
+
try {
|
|
470
|
+
val equalizer = Equalizer(0, audioSessionId)
|
|
471
|
+
equalizers.add(equalizer)
|
|
472
|
+
} catch (e: RuntimeException) {
|
|
473
|
+
Timber.tag("APMAudioFx").e("[AudioFx] failed to load equalizer. it's fine if in dev!")
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
inner class PlayerListener : Listener {
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Called when there is metadata associated with the current playback time.
|
|
482
|
+
*/
|
|
483
|
+
override fun onMetadata(metadata: Metadata) {
|
|
484
|
+
playerEventHolder.updateOnTimedMetadata(metadata)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
|
|
488
|
+
playerEventHolder.updateOnCommonMetadata(mediaMetadata)
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* A position discontinuity occurs when the playing period changes, the playback position
|
|
493
|
+
* jumps within the period currently being played, or when the playing period has been
|
|
494
|
+
* skipped or removed.
|
|
495
|
+
*/
|
|
496
|
+
override fun onPositionDiscontinuity(
|
|
497
|
+
oldPosition: Player.PositionInfo,
|
|
498
|
+
newPosition: Player.PositionInfo,
|
|
499
|
+
reason: Int
|
|
500
|
+
) {
|
|
501
|
+
this@AudioPlayer.oldPosition = oldPosition.positionMs
|
|
502
|
+
|
|
503
|
+
when (reason) {
|
|
504
|
+
Player.DISCONTINUITY_REASON_AUTO_TRANSITION -> playerEventHolder.updatePositionChangedReason(
|
|
505
|
+
PositionChangedReason.AUTO(oldPosition.positionMs, newPosition.positionMs)
|
|
506
|
+
)
|
|
507
|
+
Player.DISCONTINUITY_REASON_SEEK -> playerEventHolder.updatePositionChangedReason(
|
|
508
|
+
PositionChangedReason.SEEK(oldPosition.positionMs, newPosition.positionMs)
|
|
509
|
+
)
|
|
510
|
+
Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT -> playerEventHolder.updatePositionChangedReason(
|
|
511
|
+
PositionChangedReason.SEEK_FAILED(
|
|
512
|
+
oldPosition.positionMs,
|
|
513
|
+
newPosition.positionMs
|
|
514
|
+
)
|
|
515
|
+
)
|
|
516
|
+
Player.DISCONTINUITY_REASON_REMOVE -> playerEventHolder.updatePositionChangedReason(
|
|
517
|
+
PositionChangedReason.QUEUE_CHANGED(
|
|
518
|
+
oldPosition.positionMs,
|
|
519
|
+
newPosition.positionMs
|
|
520
|
+
)
|
|
521
|
+
)
|
|
522
|
+
Player.DISCONTINUITY_REASON_SKIP -> playerEventHolder.updatePositionChangedReason(
|
|
523
|
+
PositionChangedReason.SKIPPED_PERIOD(
|
|
524
|
+
oldPosition.positionMs,
|
|
525
|
+
newPosition.positionMs
|
|
526
|
+
)
|
|
527
|
+
)
|
|
528
|
+
Player.DISCONTINUITY_REASON_INTERNAL -> playerEventHolder.updatePositionChangedReason(
|
|
529
|
+
PositionChangedReason.UNKNOWN(oldPosition.positionMs, newPosition.positionMs)
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
Player.DISCONTINUITY_REASON_SILENCE_SKIP -> playerEventHolder.updatePositionChangedReason(
|
|
533
|
+
PositionChangedReason.UNKNOWN(oldPosition.positionMs, newPosition.positionMs)
|
|
534
|
+
)
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Called when playback transitions to a media item or starts repeating a media item
|
|
540
|
+
* according to the current repeat mode. Note that this callback is also called when the
|
|
541
|
+
* playlist becomes non-empty or empty as a consequence of a playlist change.
|
|
542
|
+
*/
|
|
543
|
+
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
|
544
|
+
when (reason) {
|
|
545
|
+
Player.MEDIA_ITEM_TRANSITION_REASON_AUTO -> playerEventHolder.updateAudioItemTransition(
|
|
546
|
+
AudioItemTransitionReason.AUTO(oldPosition)
|
|
547
|
+
)
|
|
548
|
+
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED -> playerEventHolder.updateAudioItemTransition(
|
|
549
|
+
AudioItemTransitionReason.QUEUE_CHANGED(oldPosition)
|
|
550
|
+
)
|
|
551
|
+
Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT -> playerEventHolder.updateAudioItemTransition(
|
|
552
|
+
AudioItemTransitionReason.REPEAT(oldPosition)
|
|
553
|
+
)
|
|
554
|
+
Player.MEDIA_ITEM_TRANSITION_REASON_SEEK -> playerEventHolder.updateAudioItemTransition(
|
|
555
|
+
AudioItemTransitionReason.SEEK_TO_ANOTHER_AUDIO_ITEM(oldPosition)
|
|
556
|
+
)
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Called when the value returned from Player.getPlayWhenReady() changes.
|
|
562
|
+
*/
|
|
563
|
+
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
|
564
|
+
val pausedBecauseReachedEnd = reason == Player.PLAY_WHEN_READY_CHANGE_REASON_END_OF_MEDIA_ITEM
|
|
565
|
+
playerEventHolder.updatePlayWhenReadyChange(PlayWhenReadyChangeData(playWhenReady, pausedBecauseReachedEnd))
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* The generic onEvents callback provides access to the Player object and specifies the set
|
|
570
|
+
* of events that occurred together. It’s always called after the callbacks that correspond
|
|
571
|
+
* to the individual events.
|
|
572
|
+
*/
|
|
573
|
+
override fun onEvents(player: Player, events: Player.Events) {
|
|
574
|
+
// Note that it is necessary to set `playerState` in order, since each mutation fires an
|
|
575
|
+
// event.
|
|
576
|
+
for (i in 0 until events.size()) {
|
|
577
|
+
when (events[i]) {
|
|
578
|
+
Player.EVENT_PLAYBACK_STATE_CHANGED -> {
|
|
579
|
+
val state = when (player.playbackState) {
|
|
580
|
+
Player.STATE_BUFFERING -> AudioPlayerState.BUFFERING
|
|
581
|
+
Player.STATE_READY -> AudioPlayerState.READY
|
|
582
|
+
Player.STATE_IDLE ->
|
|
583
|
+
// Avoid transitioning to idle from error or stopped
|
|
584
|
+
if (
|
|
585
|
+
playerState == AudioPlayerState.ERROR ||
|
|
586
|
+
playerState == AudioPlayerState.STOPPED
|
|
587
|
+
)
|
|
588
|
+
null
|
|
589
|
+
else
|
|
590
|
+
AudioPlayerState.IDLE
|
|
591
|
+
Player.STATE_ENDED ->
|
|
592
|
+
if (player.mediaItemCount > 0) AudioPlayerState.ENDED
|
|
593
|
+
else AudioPlayerState.IDLE
|
|
594
|
+
else -> null // noop
|
|
595
|
+
}
|
|
596
|
+
if (state != null && state != playerState) {
|
|
597
|
+
playerState = state
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
Player.EVENT_MEDIA_ITEM_TRANSITION -> {
|
|
601
|
+
playbackError = null
|
|
602
|
+
if (currentItem != null) {
|
|
603
|
+
playerState = AudioPlayerState.LOADING
|
|
604
|
+
if (isPlaying) {
|
|
605
|
+
playerState = AudioPlayerState.READY
|
|
606
|
+
playerState = AudioPlayerState.PLAYING
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
Player.EVENT_PLAY_WHEN_READY_CHANGED -> {
|
|
611
|
+
if (!player.playWhenReady && playerState != AudioPlayerState.STOPPED) {
|
|
612
|
+
playerState = AudioPlayerState.PAUSED
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
Player.EVENT_IS_PLAYING_CHANGED -> {
|
|
616
|
+
if (player.isPlaying) {
|
|
617
|
+
playerState = AudioPlayerState.PLAYING
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
override fun onPlayerError(error: PlaybackException) {
|
|
625
|
+
val _playbackError = PlaybackError(
|
|
626
|
+
error.errorCodeName
|
|
627
|
+
.replace("ERROR_CODE_", "")
|
|
628
|
+
.lowercase(Locale.getDefault())
|
|
629
|
+
.replace("_", "-"),
|
|
630
|
+
error.message
|
|
631
|
+
)
|
|
632
|
+
playerEventHolder.updatePlaybackError(_playbackError)
|
|
633
|
+
playbackError = _playbackError
|
|
634
|
+
playerState = AudioPlayerState.ERROR
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
private open inner class ExampleForwardingPlayer
|
|
640
|
+
(val mPlayer1: ExoPlayer, val mPlayer2: ExoPlayer?): ForwardingPlayer(mPlayer1, mPlayer2) {
|
|
641
|
+
override fun setMediaItems(mediaItems: MutableList<MediaItem>, resetPosition: Boolean) {
|
|
642
|
+
mPlayer1.setMediaItems(mediaItems, resetPosition)
|
|
643
|
+
mPlayer2?.setMediaItems(mediaItems, resetPosition)
|
|
644
|
+
}
|
|
645
|
+
override fun isCommandAvailable(command: Int): Boolean {
|
|
646
|
+
if (options.alwaysShowNext) {
|
|
647
|
+
return when (command) {
|
|
648
|
+
COMMAND_SEEK_TO_NEXT_MEDIA_ITEM -> true
|
|
649
|
+
COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM -> true
|
|
650
|
+
else -> super.isCommandAvailable(command)
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return super.isCommandAvailable(command)
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
override fun getAvailableCommands(): Player.Commands {
|
|
657
|
+
if (options.alwaysShowNext) {
|
|
658
|
+
return super.getAvailableCommands().buildUpon()
|
|
659
|
+
.add(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
|
|
660
|
+
.add(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
|
|
661
|
+
.build()
|
|
662
|
+
}
|
|
663
|
+
return super.getAvailableCommands()
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
private inner class APMForwardingPlayer
|
|
668
|
+
(mPlayer1: ExoPlayer, mPlayer2: ExoPlayer?): ExampleForwardingPlayer(mPlayer1, mPlayer2) {
|
|
669
|
+
override fun setMediaItems(mediaItems: MutableList<MediaItem>, resetPosition: Boolean) {
|
|
670
|
+
// override setMediaItem handling to RNTP
|
|
671
|
+
return
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
override fun addMediaItems(mediaItems: MutableList<MediaItem>) {
|
|
675
|
+
// override setMediaItem handling to RNTP
|
|
676
|
+
return
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
override fun addMediaItems(index: Int, mediaItems: MutableList<MediaItem>) {
|
|
680
|
+
// override setMediaItem handling to RNTP
|
|
681
|
+
return
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
override fun setMediaItems(
|
|
685
|
+
mediaItems: MutableList<MediaItem>,
|
|
686
|
+
startIndex: Int,
|
|
687
|
+
startPositionMs: Long
|
|
688
|
+
) {
|
|
689
|
+
// override setMediaItem handling to RNTP
|
|
690
|
+
return
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
override fun setMediaItems(mediaItems: MutableList<MediaItem>) {
|
|
694
|
+
// override setMediaItem handling to RNTP
|
|
695
|
+
return
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
override fun play() {
|
|
699
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PLAY)
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
override fun pause() {
|
|
703
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PAUSE)
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
override fun seekToNext() {
|
|
707
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.NEXT)
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
override fun seekToNextMediaItem() {
|
|
711
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.NEXT)
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
override fun seekToPrevious() {
|
|
715
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PREVIOUS)
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
override fun seekToPreviousMediaItem() {
|
|
719
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.PREVIOUS)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
override fun seekForward() {
|
|
723
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.FORWARD)
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
override fun seekBack() {
|
|
727
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.REWIND)
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
override fun stop() {
|
|
731
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(MediaSessionCallback.STOP)
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
override fun seekTo(mediaItemIndex: Int, positionMs: Long) {
|
|
735
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(
|
|
736
|
+
MediaSessionCallback.SEEK(
|
|
737
|
+
positionMs
|
|
738
|
+
)
|
|
739
|
+
)
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
override fun seekTo(positionMs: Long) {
|
|
743
|
+
playerEventHolder.updateOnPlayerActionTriggeredExternally(
|
|
744
|
+
MediaSessionCallback.SEEK(
|
|
745
|
+
positionMs
|
|
746
|
+
)
|
|
747
|
+
)
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private inner class APMFocusListener: AudioManager.OnAudioFocusChangeListener {
|
|
752
|
+
override fun onAudioFocusChange(focusChange: Int) {
|
|
753
|
+
// TODO: complete focusManager logic here
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|