@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,171 @@
|
|
|
1
|
+
// credits: https://github.com/cora32/Media3Player/blob/df06c3d72598b8e7f75fcfd22c5e9da8bc98e0a0/app/src/main/java/io/iskopasi/player_test/PlayerService.kt#L18
|
|
2
|
+
package com.lovegaoshi.kotlinaudio.processors
|
|
3
|
+
|
|
4
|
+
import androidx.media3.common.util.UnstableApi
|
|
5
|
+
import androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER
|
|
6
|
+
import androidx.media3.exoplayer.audio.TeeAudioProcessor.AudioBufferSink
|
|
7
|
+
import com.lovegaoshi.kotlinaudio.utils.FFT
|
|
8
|
+
import kotlinx.coroutines.CoroutineScope
|
|
9
|
+
import kotlinx.coroutines.Dispatchers
|
|
10
|
+
import kotlinx.coroutines.launch
|
|
11
|
+
import java.nio.ByteBuffer
|
|
12
|
+
import java.nio.ByteOrder
|
|
13
|
+
import kotlin.math.floor
|
|
14
|
+
import kotlin.math.min
|
|
15
|
+
import kotlin.math.pow
|
|
16
|
+
import kotlin.math.sqrt
|
|
17
|
+
|
|
18
|
+
val FREQUENCY_BAND_LIMITS = arrayOf(
|
|
19
|
+
20, 32, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630,
|
|
20
|
+
800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 10000,
|
|
21
|
+
12500, 16000, 20000
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
@UnstableApi
|
|
25
|
+
class TeeListener(
|
|
26
|
+
val sampleRate: Int,
|
|
27
|
+
val emitter: FFTEmitter? ) : AudioBufferSink {
|
|
28
|
+
private var sampleRateHz = 0
|
|
29
|
+
private var channelCount = 1
|
|
30
|
+
private var encoding = 0
|
|
31
|
+
private var fft = FFT( sampleRate)
|
|
32
|
+
private var fftBuffer = EMPTY_BUFFER
|
|
33
|
+
private val chartData = FloatArray(sampleRate)
|
|
34
|
+
private val src = FloatArray(sampleRate)
|
|
35
|
+
private val frequencyMap = DoubleArray(FREQUENCY_BAND_LIMITS.size)
|
|
36
|
+
private var isProcessing = false
|
|
37
|
+
|
|
38
|
+
override fun flush(sampleRateHz: Int, channelCount: Int, encoding: Int) {
|
|
39
|
+
this.sampleRateHz = sampleRateHz
|
|
40
|
+
this.channelCount = channelCount
|
|
41
|
+
this.encoding = encoding
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override fun handleBuffer(buffer: ByteBuffer) {
|
|
45
|
+
if (isProcessing) return
|
|
46
|
+
|
|
47
|
+
isProcessing = true
|
|
48
|
+
|
|
49
|
+
// Cannot access buffer in different thread
|
|
50
|
+
fillBuffer(buffer)
|
|
51
|
+
|
|
52
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
53
|
+
processFFT()
|
|
54
|
+
|
|
55
|
+
isProcessing = false
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* code I copied elsewhere
|
|
59
|
+
val doubleBuffer = buffer.asDoubleBuffer()
|
|
60
|
+
val data = DoubleArray(doubleBuffer.limit())
|
|
61
|
+
doubleBuffer.get(data)
|
|
62
|
+
val numFrames: Int = data.size / channelCount
|
|
63
|
+
val rawData = DoubleArray(numFrames)
|
|
64
|
+
Log.d("APMFFT", "buffer handling size: $numFrames, $sampleRateHz, $channelCount")
|
|
65
|
+
//took average of all channel data
|
|
66
|
+
for (i in 0..<numFrames) {
|
|
67
|
+
var sum = 0.0
|
|
68
|
+
for (ch in 0..<channelCount) {
|
|
69
|
+
sum += (data[channelCount * i + ch] + 32768)
|
|
70
|
+
}
|
|
71
|
+
rawData[i] = (sum / channelCount)
|
|
72
|
+
}
|
|
73
|
+
*/
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private fun fillBuffer(buffer: ByteBuffer) {
|
|
77
|
+
val limit = buffer.limit()
|
|
78
|
+
val frameCount = (limit - buffer.position()) / (2 * channelCount)
|
|
79
|
+
val singleChannelOutputSize = frameCount * 2
|
|
80
|
+
|
|
81
|
+
if (fftBuffer.capacity() < singleChannelOutputSize) {
|
|
82
|
+
fftBuffer =
|
|
83
|
+
ByteBuffer.allocateDirect(singleChannelOutputSize)
|
|
84
|
+
.order(ByteOrder.nativeOrder())
|
|
85
|
+
} else {
|
|
86
|
+
fftBuffer.clear()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Each signal = short (2 bytes)
|
|
90
|
+
// Use average of 2 channels as an input signal
|
|
91
|
+
for (position in buffer.position() until limit step channelCount * 2) {
|
|
92
|
+
var sum = 0
|
|
93
|
+
|
|
94
|
+
for (channelIndex in 0 until channelCount) {
|
|
95
|
+
val current = buffer.getShort(position + channelIndex * 2)
|
|
96
|
+
sum += current
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fftBuffer.putShort((sum / channelCount).toShort())
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
private fun processFFT() {
|
|
103
|
+
val maxLimit = min(fftBuffer.limit(), sampleRate)
|
|
104
|
+
|
|
105
|
+
for (i in 0 until maxLimit step 2) {
|
|
106
|
+
val short = fftBuffer.getShort(i)
|
|
107
|
+
|
|
108
|
+
src[i] = short.toFloat()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
val srcCopy = src.clone()
|
|
112
|
+
// DC bin is located at index 0, 1, nyquist at index n-2, n-1
|
|
113
|
+
fft.fft(srcCopy, FloatArray(sampleRate))
|
|
114
|
+
// Fill amplitude data
|
|
115
|
+
// The resulting graph is mirrored, so get only left part
|
|
116
|
+
for (i in 0 until srcCopy.size / 2) {
|
|
117
|
+
val real = srcCopy[i * 2]
|
|
118
|
+
val imaginary = srcCopy[i * 2 + 1]
|
|
119
|
+
val amplitude = sqrt(real.pow(2) + imaginary.pow(2))
|
|
120
|
+
|
|
121
|
+
chartData[i] = amplitude
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
val size = sampleRate / 2
|
|
125
|
+
var startIndex = 0
|
|
126
|
+
var maxAvgAmplitude = 0f
|
|
127
|
+
var maxRawAmplitude = 0f
|
|
128
|
+
|
|
129
|
+
// Group amplitudes by their frequencies
|
|
130
|
+
for ((index, frequency) in FREQUENCY_BAND_LIMITS.withIndex()) {
|
|
131
|
+
val endIndex = floor(frequency / 20000f * size).toInt()
|
|
132
|
+
|
|
133
|
+
var accum = 0f
|
|
134
|
+
// Sum amplitudes for current frequency bin
|
|
135
|
+
for (i in startIndex until endIndex) {
|
|
136
|
+
val amplitude = chartData[i]
|
|
137
|
+
accum += amplitude
|
|
138
|
+
|
|
139
|
+
// Find max amplitude of all frequencies
|
|
140
|
+
if (amplitude > maxRawAmplitude) {
|
|
141
|
+
maxRawAmplitude = amplitude
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Sometimes frequency group range can be 0
|
|
146
|
+
val amplitude = if (endIndex - startIndex == 0)
|
|
147
|
+
0f
|
|
148
|
+
else {
|
|
149
|
+
// Get avg amplitude for frequency bin
|
|
150
|
+
accum / (endIndex - startIndex).toFloat()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Fill avg amplitude for each frequency
|
|
154
|
+
frequencyMap[index] = amplitude.toDouble()
|
|
155
|
+
|
|
156
|
+
// Get max avg amplitude
|
|
157
|
+
if (amplitude > maxAvgAmplitude) {
|
|
158
|
+
maxAvgAmplitude = amplitude
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
startIndex = endIndex
|
|
162
|
+
}
|
|
163
|
+
emitter?.onSpectrumReady(chartData, maxRawAmplitude)
|
|
164
|
+
emitter?.onFrequencyFFTReady(frequencyMap, maxAvgAmplitude)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface FFTEmitter {
|
|
169
|
+
fun onSpectrumReady(spectrum: FloatArray, maxRawAmp: Float)
|
|
170
|
+
fun onFrequencyFFTReady(fft: DoubleArray, maxAvgAmp: Float)
|
|
171
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
@file: OptIn(UnstableApi::class) package com.lovegaoshi.kotlinaudio.service
|
|
2
|
+
|
|
3
|
+
import android.content.Intent
|
|
4
|
+
import android.os.Binder
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import android.os.IBinder
|
|
7
|
+
import androidx.annotation.OptIn
|
|
8
|
+
import androidx.media3.common.util.UnstableApi
|
|
9
|
+
import androidx.media3.session.MediaLibraryService
|
|
10
|
+
import androidx.media3.session.MediaSession
|
|
11
|
+
import androidx.media3.session.SessionCommand
|
|
12
|
+
import androidx.media3.session.SessionResult
|
|
13
|
+
import com.google.common.util.concurrent.ListenableFuture
|
|
14
|
+
import com.lovegaoshi.kotlinaudio.models.CustomButton
|
|
15
|
+
import com.lovegaoshi.kotlinaudio.models.PlayerOptions
|
|
16
|
+
import com.lovegaoshi.kotlinaudio.player.QueuedAudioPlayer
|
|
17
|
+
import timber.log.Timber
|
|
18
|
+
|
|
19
|
+
class MusicService : MediaLibraryService() {
|
|
20
|
+
private val binder = MusicBinder()
|
|
21
|
+
lateinit var player: QueuedAudioPlayer
|
|
22
|
+
private lateinit var mediaSession: MediaLibrarySession
|
|
23
|
+
|
|
24
|
+
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession =
|
|
25
|
+
mediaSession
|
|
26
|
+
|
|
27
|
+
// Create your player and media session in the onCreate lifecycle event
|
|
28
|
+
override fun onCreate() {
|
|
29
|
+
super.onCreate()
|
|
30
|
+
// Service is immediately set up for the KA example.
|
|
31
|
+
setupService(listOf(
|
|
32
|
+
CustomButton(displayName = CROSSFADE_PREV_PREPARE),
|
|
33
|
+
CustomButton(displayName = CROSSFADE_PREV),
|
|
34
|
+
CustomButton(displayName = CROSSFADE_NEXT_PREPARE),
|
|
35
|
+
CustomButton(displayName = CROSSFADE_NEXT),
|
|
36
|
+
))
|
|
37
|
+
// setMediaNotificationProvider()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private fun setupService(customActions: List<CustomButton> = arrayListOf()) {
|
|
41
|
+
|
|
42
|
+
player = QueuedAudioPlayer(this, PlayerOptions(crossfade = true, nativeExample = true))
|
|
43
|
+
mediaSession = MediaLibrarySession
|
|
44
|
+
.Builder(this, player.player, CustomMediaSessionCallback(customActions))
|
|
45
|
+
.setCustomLayout(customActions.filter { v -> v.onLayout }.map{ v -> v.commandButton})
|
|
46
|
+
.setId("APM")
|
|
47
|
+
.build()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The user dismissed the app from the recent tasks
|
|
51
|
+
override fun onTaskRemoved(rootIntent: Intent?) {
|
|
52
|
+
val player = mediaSession.player
|
|
53
|
+
if (!player.playWhenReady || player.mediaItemCount == 0) {
|
|
54
|
+
// Stop the service if not playing, continue playing in the background
|
|
55
|
+
// otherwise.
|
|
56
|
+
stopSelf()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Remember to release the player and media session in onDestroy
|
|
61
|
+
override fun onDestroy() {
|
|
62
|
+
mediaSession.run {
|
|
63
|
+
player.release()
|
|
64
|
+
release()
|
|
65
|
+
mediaSession.release()
|
|
66
|
+
}
|
|
67
|
+
super.onDestroy()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@UnstableApi private inner class CustomMediaSessionCallback(
|
|
71
|
+
val customActions: List<CustomButton>
|
|
72
|
+
) : MediaLibrarySession.Callback {
|
|
73
|
+
|
|
74
|
+
override fun onCustomCommand(
|
|
75
|
+
session: MediaSession,
|
|
76
|
+
controller: MediaSession.ControllerInfo,
|
|
77
|
+
customCommand: SessionCommand,
|
|
78
|
+
args: Bundle
|
|
79
|
+
): ListenableFuture<SessionResult> {
|
|
80
|
+
Timber.tag("APM").d("custom command triggered: ${customCommand.customAction}")
|
|
81
|
+
when (customCommand.customAction) {
|
|
82
|
+
CROSSFADE_PREV_PREPARE -> { player.crossFadePrepare(true) }
|
|
83
|
+
CROSSFADE_PREV -> { player.switchExoPlayer({ player.previous() }) }
|
|
84
|
+
CROSSFADE_NEXT_PREPARE -> { player.crossFadePrepare() }
|
|
85
|
+
CROSSFADE_NEXT -> {
|
|
86
|
+
player.switchExoPlayer()
|
|
87
|
+
mediaSession.player = player.player
|
|
88
|
+
this@MusicService.onUpdateNotification(mediaSession, true)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return super.onCustomCommand(session, controller, customCommand, args)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Configure commands available to the controller in onConnect()
|
|
95
|
+
override fun onConnect(
|
|
96
|
+
session: MediaSession,
|
|
97
|
+
controller: MediaSession.ControllerInfo
|
|
98
|
+
): MediaSession.ConnectionResult {
|
|
99
|
+
val sessionCommands = MediaSession.ConnectionResult.DEFAULT_SESSION_AND_LIBRARY_COMMANDS.buildUpon()
|
|
100
|
+
customActions.forEach{
|
|
101
|
+
v -> v.commandButton.sessionCommand?.let { sessionCommands.add(it) }
|
|
102
|
+
}
|
|
103
|
+
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
|
|
104
|
+
.setAvailableSessionCommands(sessionCommands.build())
|
|
105
|
+
.setAvailablePlayerCommands(MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS)
|
|
106
|
+
.build()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
inner class MusicBinder : Binder() {
|
|
111
|
+
val service = this@MusicService
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override fun onBind(intent: Intent?): IBinder? {
|
|
115
|
+
val intentAction = intent?.action
|
|
116
|
+
return if (intentAction != null) {
|
|
117
|
+
super.onBind(intent)
|
|
118
|
+
} else {
|
|
119
|
+
binder
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const val CROSSFADE_PREV_PREPARE = "crossfade prev prepare"
|
|
125
|
+
const val CROSSFADE_PREV = "crossfade prev"
|
|
126
|
+
const val CROSSFADE_NEXT_PREPARE = "crossfade next prepare"
|
|
127
|
+
const val CROSSFADE_NEXT = "crossfade next"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/***************************************************************
|
|
2
|
+
00089 * fft.c
|
|
3
|
+
00090 * Douglas L. Jones
|
|
4
|
+
00091 * University of Illinois at Urbana-Champaign
|
|
5
|
+
00092 * January 19, 1992
|
|
6
|
+
00093 * http://cnx.rice.edu/content/m12016/latest/
|
|
7
|
+
00094 *
|
|
8
|
+
00095 * fft: in-place radix-2 DIT DFT of a complex input
|
|
9
|
+
00096 *
|
|
10
|
+
00097 * input:
|
|
11
|
+
00098 * n: length of FFT: must be a power of two
|
|
12
|
+
00099 * m: n = 2**m
|
|
13
|
+
00100 * input/output
|
|
14
|
+
00101 * x: double array of length n with real part of data
|
|
15
|
+
00102 * y: double array of length n with imag part of data
|
|
16
|
+
00103 *
|
|
17
|
+
00104 * Permission to copy and use this program is granted
|
|
18
|
+
00105 * as long as this header is included.
|
|
19
|
+
***************************************************************/
|
|
20
|
+
package com.lovegaoshi.kotlinaudio.utils;
|
|
21
|
+
|
|
22
|
+
public class FFT {
|
|
23
|
+
|
|
24
|
+
int n, m;
|
|
25
|
+
|
|
26
|
+
// Lookup tables. Only need to recompute when size of FFT changes.
|
|
27
|
+
double[] cos;
|
|
28
|
+
double[] sin;
|
|
29
|
+
|
|
30
|
+
public FFT(int n) {
|
|
31
|
+
this.n = n;
|
|
32
|
+
this.m = (int) (Math.log(n) / Math.log(2));
|
|
33
|
+
|
|
34
|
+
// Make sure n is a power of 2
|
|
35
|
+
if (n != (1 << m))
|
|
36
|
+
throw new RuntimeException("FFT length must be power of 2");
|
|
37
|
+
|
|
38
|
+
// precompute tables
|
|
39
|
+
cos = new double[n / 2];
|
|
40
|
+
sin = new double[n / 2];
|
|
41
|
+
|
|
42
|
+
for (int i = 0; i < n / 2; i++) {
|
|
43
|
+
cos[i] = Math.cos(-2 * Math.PI * i / n);
|
|
44
|
+
sin[i] = Math.sin(-2 * Math.PI * i / n);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public void fft(float[] x, float[] y) {
|
|
50
|
+
int i, j, k, n1, n2, a;
|
|
51
|
+
float c, s, t1, t2;
|
|
52
|
+
|
|
53
|
+
// Bit-reverse
|
|
54
|
+
j = 0;
|
|
55
|
+
n2 = n / 2;
|
|
56
|
+
for (i = 1; i < n - 1; i++) {
|
|
57
|
+
n1 = n2;
|
|
58
|
+
while (j >= n1) {
|
|
59
|
+
j = j - n1;
|
|
60
|
+
n1 = n1 / 2;
|
|
61
|
+
}
|
|
62
|
+
j = j + n1;
|
|
63
|
+
|
|
64
|
+
if (i < j) {
|
|
65
|
+
t1 = x[i];
|
|
66
|
+
x[i] = x[j];
|
|
67
|
+
x[j] = t1;
|
|
68
|
+
t1 = y[i];
|
|
69
|
+
y[i] = y[j];
|
|
70
|
+
y[j] = t1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// FFT
|
|
75
|
+
n1 = 0;
|
|
76
|
+
n2 = 1;
|
|
77
|
+
|
|
78
|
+
for (i = 0; i < m; i++) {
|
|
79
|
+
n1 = n2;
|
|
80
|
+
n2 = n2 + n2;
|
|
81
|
+
a = 0;
|
|
82
|
+
|
|
83
|
+
for (j = 0; j < n1; j++) {
|
|
84
|
+
c = (float) cos[a];
|
|
85
|
+
s = (float) sin[a];
|
|
86
|
+
a += 1 << (m - i - 1);
|
|
87
|
+
|
|
88
|
+
for (k = j; k < n; k = k + n2) {
|
|
89
|
+
t1 = c * x[k + n1] - s * y[k + n1];
|
|
90
|
+
t2 = s * x[k + n1] + c * y[k + n1];
|
|
91
|
+
x[k + n1] = x[k] - t1;
|
|
92
|
+
y[k + n1] = y[k] - t2;
|
|
93
|
+
x[k] = x[k] + t1;
|
|
94
|
+
y[k] = y[k] + t2;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
package com.lovegaoshi.kotlinaudio.utils
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.ContentResolver
|
|
5
|
+
import android.content.ContentUris
|
|
6
|
+
import android.content.ContentValues
|
|
7
|
+
import android.graphics.Bitmap
|
|
8
|
+
import android.graphics.BitmapFactory
|
|
9
|
+
import android.media.MediaMetadataRetriever
|
|
10
|
+
import android.net.Uri
|
|
11
|
+
import android.os.Build
|
|
12
|
+
import android.os.Environment
|
|
13
|
+
import android.provider.MediaStore
|
|
14
|
+
import androidx.annotation.RequiresApi
|
|
15
|
+
import java.io.OutputStream
|
|
16
|
+
|
|
17
|
+
fun isUriLocalFile(uri: Uri?): Boolean {
|
|
18
|
+
if (uri == null) return false
|
|
19
|
+
val scheme = uri.scheme
|
|
20
|
+
val host = uri.host
|
|
21
|
+
if((scheme == "http" || scheme == "https") && (host == "localhost" || host == "127.0.0.1" || host == "[::1]"))
|
|
22
|
+
{
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
return scheme == null
|
|
26
|
+
|| scheme == ContentResolver.SCHEME_FILE
|
|
27
|
+
|| scheme == ContentResolver.SCHEME_ANDROID_RESOURCE
|
|
28
|
+
|| scheme == ContentResolver.SCHEME_CONTENT
|
|
29
|
+
|| scheme == "res" || host == null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const val bitmapCoverFileName = "APMCover.png"
|
|
33
|
+
val bitmapCoverDir = "${Environment.DIRECTORY_PICTURES}/APMCache/"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@RequiresApi(Build.VERSION_CODES.R)
|
|
37
|
+
@SuppressLint("Range")
|
|
38
|
+
fun findAPMCacheApi(contentResolver: ContentResolver, contentUri: Uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI): Uri? {
|
|
39
|
+
val selection = "${MediaStore.MediaColumns.RELATIVE_PATH}=?"
|
|
40
|
+
val selectionArgs = arrayOf(bitmapCoverDir)
|
|
41
|
+
val cursor = contentResolver.query(contentUri, null, selection,selectionArgs,null)
|
|
42
|
+
if (cursor != null && cursor.count > 0) {
|
|
43
|
+
while (cursor.moveToNext()) {
|
|
44
|
+
val filename = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME))
|
|
45
|
+
if (filename == bitmapCoverFileName) {
|
|
46
|
+
val id = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID))
|
|
47
|
+
cursor.close()
|
|
48
|
+
return ContentUris.withAppendedId(contentUri, id)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
cursor.close()
|
|
52
|
+
}
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@RequiresApi(Build.VERSION_CODES.R)
|
|
57
|
+
fun getAPMCacheBitmapUri(contentResolver: ContentResolver, contentValues: ContentValues): Uri? {
|
|
58
|
+
val contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
|
59
|
+
val mAPMUri = findAPMCacheApi(contentResolver, contentUri)
|
|
60
|
+
if (mAPMUri != null ) contentResolver.delete(mAPMUri, null)
|
|
61
|
+
return contentResolver.insert(contentUri, contentValues)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fun getEmbeddedBitmapArray(path: String?): ByteArray? {
|
|
65
|
+
if (path == null) return null
|
|
66
|
+
val mmr = MediaMetadataRetriever()
|
|
67
|
+
try {
|
|
68
|
+
mmr.setDataSource(path)
|
|
69
|
+
return mmr.embeddedPicture
|
|
70
|
+
} catch (e: Exception) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fun getEmbeddedBitmap(path: String?): Bitmap? {
|
|
76
|
+
val artworkData = getEmbeddedBitmapArray(path)
|
|
77
|
+
return if (artworkData == null) null else BitmapFactory.decodeByteArray(artworkData, 0, artworkData.size)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var cacheKeyG = ""
|
|
81
|
+
// HACK: this will insert a png file at pictures/APMCache/APMCover.png.
|
|
82
|
+
fun saveMediaCoverToPng(path: String?, contentResolver: ContentResolver, cacheKey: String): String? {
|
|
83
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
84
|
+
if (cacheKey == cacheKeyG) {
|
|
85
|
+
return findAPMCacheApi(contentResolver).toString()
|
|
86
|
+
}
|
|
87
|
+
val contentValues = ContentValues().apply {
|
|
88
|
+
put(MediaStore.MediaColumns.DISPLAY_NAME, bitmapCoverFileName)
|
|
89
|
+
put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
|
|
90
|
+
put(MediaStore.MediaColumns.RELATIVE_PATH, bitmapCoverDir)
|
|
91
|
+
put(MediaStore.MediaColumns.IS_PENDING, 1)
|
|
92
|
+
}
|
|
93
|
+
val imageUri = getAPMCacheBitmapUri(contentResolver, contentValues)
|
|
94
|
+
val bitmap = getEmbeddedBitmap(path) ?: return null
|
|
95
|
+
cacheKeyG = cacheKey
|
|
96
|
+
var fos: OutputStream?
|
|
97
|
+
|
|
98
|
+
contentResolver.also { resolver ->
|
|
99
|
+
fos = imageUri?.let { resolver.openOutputStream(it) }
|
|
100
|
+
}
|
|
101
|
+
// TODO: add error handling
|
|
102
|
+
if (imageUri == null) return null
|
|
103
|
+
fos?.use { bitmap.compress(Bitmap.CompressFormat.PNG, 70, it) }
|
|
104
|
+
contentValues.clear()
|
|
105
|
+
contentValues.put(MediaStore.Video.Media.IS_PENDING, 0)
|
|
106
|
+
contentResolver.update(imageUri, contentValues, null, null)
|
|
107
|
+
return imageUri.toString()
|
|
108
|
+
}
|
|
109
|
+
return null
|
|
110
|
+
// TODO: does this insert without overwriting?
|
|
111
|
+
// return MediaStore.Images.Media.insertImage(contentResolver, bitmap,
|
|
112
|
+
// bitmapCoverFileName,"APMCover")
|
|
113
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:tint="#FFFFFF" android:viewportHeight="24"
|
|
3
|
+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:tint="#FFFFFF" android:viewportHeight="24"
|
|
3
|
+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M7,7h10v3l4,-4 -4,-4v3L5,5v6h2L7,7zM17,17L7,17v-3l-4,4 4,4v-3h12v-6h-2v4zM13,15L13,9h-1l-2,1v1h1.5v4L13,15z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:tint="#FFFFFF" android:viewportHeight="24"
|
|
3
|
+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M18,13c0,3.31 -2.69,6 -6,6s-6,-2.69 -6,-6s2.69,-6 6,-6v4l5,-5l-5,-5v4c-4.42,0 -8,3.58 -8,8c0,4.42 3.58,8 8,8c4.42,0 8,-3.58 8,-8H18z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:viewportHeight="960" android:viewportWidth="960"
|
|
3
|
+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M480,840L422,788Q321,697 255,631Q189,565 150,512.5Q111,460 95.5,416Q80,372 80,326Q80,232 143,169Q206,106 300,106Q352,106 399,128Q446,150 480,190Q514,150 561,128Q608,106 660,106Q754,106 817,169Q880,232 880,326Q880,372 864.5,416Q849,460 810,512.5Q771,565 705,631Q639,697 538,788L480,840Z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:viewportHeight="960" android:viewportWidth="960"
|
|
3
|
+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M480,840L422,788Q321,697 255,631Q189,565 150,512.5Q111,460 95.5,416Q80,372 80,326Q80,232 143,169Q206,106 300,106Q352,106 399,128Q446,150 480,190Q514,150 561,128Q608,106 660,106Q754,106 817,169Q880,232 880,326Q880,372 864.5,416Q849,460 810,512.5Q771,565 705,631Q639,697 538,788L480,840ZM480,732Q576,646 638,584.5Q700,523 736,477.5Q772,432 786,396.5Q800,361 800,326Q800,266 760,226Q720,186 660,186Q613,186 573,212.5Q533,239 518,280L518,280L442,280L442,280Q427,239 387,212.5Q347,186 300,186Q240,186 200,226Q160,266 160,326Q160,361 174,396.5Q188,432 224,477.5Q260,523 322,584.5Q384,646 480,732ZM480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459L480,459L480,459L480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Q480,459 480,459Z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:viewportHeight="960" android:viewportWidth="960"
|
|
3
|
+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M640,700Q665,700 682.5,682.5Q700,665 700,640Q700,615 682.5,597.5Q665,580 640,580Q615,580 597.5,597.5Q580,615 580,640Q580,665 597.5,682.5Q615,700 640,700ZM480,540Q505,540 522.5,522.5Q540,505 540,480Q540,455 522.5,437.5Q505,420 480,420Q455,420 437.5,437.5Q420,455 420,480Q420,505 437.5,522.5Q455,540 480,540ZM320,380Q345,380 362.5,362.5Q380,345 380,320Q380,295 362.5,277.5Q345,260 320,260Q295,260 277.5,277.5Q260,295 260,320Q260,345 277.5,362.5Q295,380 320,380ZM200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L760,120Q793,120 816.5,143.5Q840,167 840,200L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM200,760L760,760Q760,760 760,760Q760,760 760,760L760,200Q760,200 760,200Q760,200 760,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760ZM200,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760L200,760Q200,760 200,760Q200,760 200,760L200,200Q200,200 200,200Q200,200 200,200Z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:tint="#FFFFFF" android:viewportHeight="24"
|
|
3
|
+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M12,5V1L7,6l5,5V7c3.31,0 6,2.69 6,6s-2.69,6 -6,6 -6,-2.69 -6,-6H4c0,4.42 3.58,8 8,8s8,-3.58 8,-8 -3.58,-8 -8,-8z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<vector android:autoMirrored="true" android:height="24dp"
|
|
2
|
+
android:viewportHeight="960" android:viewportWidth="960"
|
|
3
|
+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
|
4
|
+
<path android:fillColor="@android:color/white" android:pathData="M560,800L560,720L664,720L537,593L594,536L720,662L720,560L800,560L800,800L560,800ZM216,800L160,744L664,240L560,240L560,160L800,160L800,400L720,400L720,296L216,800ZM367,423L160,216L216,160L423,367L367,423Z"/>
|
|
5
|
+
</vector>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"images" : [
|
|
3
|
+
{
|
|
4
|
+
"filename" : "22AMillion.jpg",
|
|
5
|
+
"idiom" : "universal",
|
|
6
|
+
"scale" : "1x"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom" : "universal",
|
|
10
|
+
"scale" : "2x"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"idiom" : "universal",
|
|
14
|
+
"scale" : "3x"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"info" : {
|
|
18
|
+
"author" : "xcode",
|
|
19
|
+
"version" : 1
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"images" : [
|
|
3
|
+
{
|
|
4
|
+
"idiom" : "mac",
|
|
5
|
+
"scale" : "1x",
|
|
6
|
+
"size" : "16x16"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"idiom" : "mac",
|
|
10
|
+
"scale" : "2x",
|
|
11
|
+
"size" : "16x16"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"idiom" : "mac",
|
|
15
|
+
"scale" : "1x",
|
|
16
|
+
"size" : "32x32"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"idiom" : "mac",
|
|
20
|
+
"scale" : "2x",
|
|
21
|
+
"size" : "32x32"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"idiom" : "mac",
|
|
25
|
+
"scale" : "1x",
|
|
26
|
+
"size" : "128x128"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"idiom" : "mac",
|
|
30
|
+
"scale" : "2x",
|
|
31
|
+
"size" : "128x128"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"idiom" : "mac",
|
|
35
|
+
"scale" : "1x",
|
|
36
|
+
"size" : "256x256"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"idiom" : "mac",
|
|
40
|
+
"scale" : "2x",
|
|
41
|
+
"size" : "256x256"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"idiom" : "mac",
|
|
45
|
+
"scale" : "1x",
|
|
46
|
+
"size" : "512x512"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"idiom" : "mac",
|
|
50
|
+
"scale" : "2x",
|
|
51
|
+
"size" : "512x512"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"info" : {
|
|
55
|
+
"author" : "xcode",
|
|
56
|
+
"version" : 1
|
|
57
|
+
}
|
|
58
|
+
}
|