@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.
Files changed (437) hide show
  1. package/LICENSE +201 -21
  2. package/README.md +8 -0
  3. package/android/build.gradle +92 -18
  4. package/android/proguard-rules.txt +0 -3
  5. package/android/src/main/AndroidManifest.xml +10 -13
  6. package/android/src/main/java/com/doublesymmetry/trackplayer/HeadlessJsMediaService.kt +199 -0
  7. package/android/src/main/java/com/doublesymmetry/trackplayer/TrackPlayer.kt +33 -0
  8. package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
  9. package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/EnumExtensions.kt +5 -0
  10. package/android/src/main/java/com/doublesymmetry/trackplayer/extensions/NumberExt.kt +13 -0
  11. package/android/src/main/java/com/doublesymmetry/trackplayer/model/MetadataAdapter.kt +227 -0
  12. package/android/src/main/java/com/doublesymmetry/trackplayer/model/NowPlayingMetadata.kt +16 -0
  13. package/android/src/main/java/com/doublesymmetry/trackplayer/model/PlaybackMetadata.kt +203 -0
  14. package/android/src/main/java/com/doublesymmetry/trackplayer/model/State.kt +13 -0
  15. package/android/src/main/java/com/doublesymmetry/trackplayer/model/Track.kt +67 -0
  16. package/android/src/main/java/com/doublesymmetry/trackplayer/model/TrackAudioItem.kt +18 -0
  17. package/android/src/main/java/com/doublesymmetry/trackplayer/model/TrackMetadata.kt +38 -0
  18. package/android/src/main/java/com/doublesymmetry/trackplayer/module/MusicEvents.kt +67 -0
  19. package/android/src/main/java/com/doublesymmetry/trackplayer/module/MusicModule.kt +778 -0
  20. package/android/src/main/java/com/doublesymmetry/trackplayer/service/MusicService.kt +1286 -0
  21. package/android/src/main/java/com/doublesymmetry/trackplayer/utils/AppForegroundTracker.kt +35 -0
  22. package/android/src/main/java/com/doublesymmetry/trackplayer/utils/BundleUtils.kt +147 -0
  23. package/android/src/main/java/com/doublesymmetry/trackplayer/utils/CoilBitmapLoader.kt +65 -0
  24. package/android/src/main/java/com/doublesymmetry/trackplayer/utils/MediaItemBuilder.kt +41 -0
  25. package/android/src/main/java/com/doublesymmetry/trackplayer/utils/RejectionException.kt +11 -0
  26. package/android/src/main/java/com/doublesymmetry/trackplayer/video/TrackPlayerVideoView.kt +42 -0
  27. package/android/src/main/java/com/doublesymmetry/trackplayer/video/TrackPlayerVideoViewManager.kt +18 -0
  28. package/android/src/main/java/com/lovegaoshi/kotlinaudio/event/EventHolder.kt +30 -0
  29. package/android/src/main/java/com/lovegaoshi/kotlinaudio/event/PlayerEventHolder.kt +124 -0
  30. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioContentType.kt +10 -0
  31. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioItem.kt +118 -0
  32. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
  33. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/AudioPlayerState.kt +30 -0
  34. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/BufferConfig.kt +8 -0
  35. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/CacheConfig.kt +17 -0
  36. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/Capability.kt +19 -0
  37. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/CustomButton.kt +19 -0
  38. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/FocusChangeData.kt +3 -0
  39. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/MediaSessionCallback.kt +17 -0
  40. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayWhenReadyChangeData.kt +3 -0
  41. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
  42. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlaybackError.kt +6 -0
  43. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayerConfig.kt +36 -0
  44. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PlayerOptions.kt +40 -0
  45. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/PositionChangedReason.kt +39 -0
  46. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/RepeatMode.kt +16 -0
  47. package/android/src/main/java/com/lovegaoshi/kotlinaudio/models/WakeMode.kt +7 -0
  48. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/AudioPlayer.kt +756 -0
  49. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/ForwardingPlayer.java +1124 -0
  50. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/QueuedAudioPlayer.kt +279 -0
  51. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/APMRenderersFactory.kt +33 -0
  52. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/Buffer.kt +34 -0
  53. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/Cache.kt +27 -0
  54. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/FocusManager.kt +59 -0
  55. package/android/src/main/java/com/lovegaoshi/kotlinaudio/player/components/MediaFactory.kt +130 -0
  56. package/android/src/main/java/com/lovegaoshi/kotlinaudio/processors/TeeListener.kt +171 -0
  57. package/android/src/main/java/com/lovegaoshi/kotlinaudio/service/MusicService.kt +127 -0
  58. package/android/src/main/java/com/lovegaoshi/kotlinaudio/utils/FFT.java +99 -0
  59. package/android/src/main/java/com/lovegaoshi/kotlinaudio/utils/Utils.kt +113 -0
  60. package/android/src/main/res/drawable/baseline_repeat_24.xml +5 -0
  61. package/android/src/main/res/drawable/baseline_repeat_one_24.xml +5 -0
  62. package/android/src/main/res/drawable/forward.xml +5 -0
  63. package/android/src/main/res/drawable/heart_24px.xml +5 -0
  64. package/android/src/main/res/drawable/hearte_24px.xml +5 -0
  65. package/android/src/main/res/drawable/ifl_24px.xml +5 -0
  66. package/android/src/main/res/drawable/rewind.xml +5 -0
  67. package/android/src/main/res/drawable/shuffle_24px.xml +5 -0
  68. package/android/src/main/res/values/strings.xml +5 -0
  69. package/android/src/main/res/xml/automotive_app_desc.xml +3 -0
  70. package/ios/Example/SwiftAudio/Assets.xcassets/22AMI.imageset/22AMillion.jpg +0 -0
  71. package/ios/Example/SwiftAudio/Assets.xcassets/22AMI.imageset/Contents.json +21 -0
  72. package/ios/Example/SwiftAudio/Assets.xcassets/AccentColor.colorset/Contents.json +11 -0
  73. package/ios/Example/SwiftAudio/Assets.xcassets/AppIcon.appiconset/Contents.json +58 -0
  74. package/ios/Example/SwiftAudio/Assets.xcassets/Contents.json +6 -0
  75. package/ios/Example/SwiftAudio/Assets.xcassets/cover.imageset/Contents.json +21 -0
  76. package/ios/Example/SwiftAudio/Assets.xcassets/cover.imageset/cover.jpg +0 -0
  77. package/ios/Example/SwiftAudio/AudioController.swift +46 -0
  78. package/ios/Example/SwiftAudio/Extensions.swift +22 -0
  79. package/ios/Example/SwiftAudio/PlayerView.swift +172 -0
  80. package/ios/Example/SwiftAudio/PlayerViewModel.swift +120 -0
  81. package/ios/Example/SwiftAudio/Preview Content/Preview Assets.xcassets/Contents.json +6 -0
  82. package/ios/Example/SwiftAudio/QueueView.swift +65 -0
  83. package/ios/{TrackPlayer.xcodeproj/xcuserdata/marco.xcuserdatad/xcschemes/xcschememanagement.plist → Example/SwiftAudio/SwiftAudio.entitlements} +6 -8
  84. package/ios/Example/SwiftAudio/SwiftAudioApp.swift +17 -0
  85. package/ios/Example/SwiftAudio.xcodeproj/project.pbxproj +412 -0
  86. package/ios/{TrackPlayer.xcodeproj → Example/SwiftAudio.xcodeproj}/project.xcworkspace/contents.xcworkspacedata +1 -1
  87. package/ios/RNTrackPlayer/Models/Capabilities.swift +39 -4
  88. package/ios/RNTrackPlayer/Models/MediaURL.swift +12 -6
  89. package/ios/RNTrackPlayer/Models/MetadataAdapter.swift +147 -0
  90. package/ios/RNTrackPlayer/Models/PitchAlgorithms.swift +13 -0
  91. package/ios/RNTrackPlayer/Models/SessionCategories.swift +106 -0
  92. package/ios/RNTrackPlayer/Models/State.swift +26 -0
  93. package/ios/RNTrackPlayer/Models/Track.swift +74 -54
  94. package/ios/RNTrackPlayer/RNTrackPlayer.swift +867 -406
  95. package/ios/RNTrackPlayer/Support/RNTrackPlayer-Bridging-Header.h +1 -0
  96. package/ios/RNTrackPlayer/TrackPlayer.h +14 -0
  97. package/ios/RNTrackPlayer/TrackPlayer.mm +249 -0
  98. package/ios/RNTrackPlayer/Utils/EventType.swift +45 -0
  99. package/ios/RNTrackPlayer/Utils/Metadata.swift +60 -0
  100. package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoView.swift +83 -0
  101. package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoViewManager.m +5 -0
  102. package/ios/RNTrackPlayer/Video/RNTrackPlayerVideoViewManager.swift +17 -0
  103. package/ios/SwiftAudioEx/Package.swift +20 -0
  104. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapper.swift +531 -0
  105. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperDelegate.swift +27 -0
  106. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperProtocol.swift +69 -0
  107. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AVPlayerWrapper/AVPlayerWrapperState.swift +43 -0
  108. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioItem.swift +158 -0
  109. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioPlayer.swift +459 -0
  110. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioPlayerError.swift +26 -0
  111. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioSessionController/AudioSession.swift +33 -0
  112. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioSessionController/AudioSessionController.swift +135 -0
  113. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/AudioTap.swift +96 -0
  114. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Event.swift +155 -0
  115. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/MediaItemProperty.swift +95 -0
  116. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoCenter.swift +17 -0
  117. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoController.swift +73 -0
  118. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoControllerProtocol.swift +26 -0
  119. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoKeyValue.swift +14 -0
  120. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/NowPlayingInfoController/NowPlayingInfoProperty.swift +234 -0
  121. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerItemNotificationObserver.swift +102 -0
  122. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerItemObserver.swift +136 -0
  123. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerObserver.swift +120 -0
  124. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Observer/AVPlayerTimeObserver.swift +112 -0
  125. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/QueueManager.swift +356 -0
  126. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/QueuedAudioPlayer.swift +236 -0
  127. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RemoteCommandController/RemoteCommand.swift +170 -0
  128. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RemoteCommandController/RemoteCommandController.swift +206 -0
  129. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/RepeatMode.swift +15 -0
  130. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/TimeEventFrequency.swift +26 -0
  131. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/Utils/DispatchQueueType.swift +18 -0
  132. package/ios/SwiftAudioEx/Sources/SwiftAudioEx/WaveformAudioTap.swift +159 -0
  133. package/lib/specs/NativeTrackPlayer.d.ts +134 -0
  134. package/lib/specs/NativeTrackPlayer.js +4 -0
  135. package/lib/src/TrackPlayerModule.web.d.ts +2 -0
  136. package/lib/src/TrackPlayerModule.web.js +2 -0
  137. package/lib/src/VideoView.d.ts +16 -0
  138. package/lib/src/VideoView.js +25 -0
  139. package/lib/src/constants/AndroidAudioContentType.d.ts +35 -0
  140. package/lib/src/constants/AndroidAudioContentType.js +36 -0
  141. package/lib/src/constants/AndroidAutoContentStyle.d.ts +10 -0
  142. package/lib/src/constants/AndroidAutoContentStyle.js +11 -0
  143. package/lib/src/constants/AppKilledPlaybackBehavior.d.ts +17 -0
  144. package/lib/src/constants/AppKilledPlaybackBehavior.js +18 -0
  145. package/lib/src/constants/Capability.d.ts +17 -0
  146. package/lib/src/constants/Capability.js +19 -0
  147. package/lib/src/constants/Event.d.ts +172 -0
  148. package/lib/src/constants/Event.js +173 -0
  149. package/lib/src/constants/IOSCategory.d.ts +36 -0
  150. package/lib/src/constants/IOSCategory.js +37 -0
  151. package/lib/src/constants/IOSCategoryMode.d.ts +47 -0
  152. package/lib/src/constants/IOSCategoryMode.js +48 -0
  153. package/lib/src/constants/IOSCategoryOptions.d.ts +44 -0
  154. package/lib/src/constants/IOSCategoryOptions.js +45 -0
  155. package/lib/src/constants/MediaItemPlayable.d.ts +4 -0
  156. package/lib/src/constants/MediaItemPlayable.js +5 -0
  157. package/lib/src/constants/PitchAlgorithm.d.ts +14 -0
  158. package/lib/src/constants/PitchAlgorithm.js +16 -0
  159. package/lib/src/constants/RatingType.d.ts +8 -0
  160. package/lib/src/constants/RatingType.js +10 -0
  161. package/lib/src/constants/RepeatMode.d.ts +8 -0
  162. package/lib/src/constants/RepeatMode.js +10 -0
  163. package/lib/src/constants/State.d.ts +34 -0
  164. package/lib/src/constants/State.js +35 -0
  165. package/lib/src/constants/TrackType.d.ts +6 -0
  166. package/lib/src/constants/TrackType.js +7 -0
  167. package/lib/src/constants/index.d.ts +14 -0
  168. package/lib/src/constants/index.js +14 -0
  169. package/lib/src/hooks/index.d.ts +6 -0
  170. package/lib/src/hooks/index.js +6 -0
  171. package/lib/src/hooks/useActiveTrack.d.ts +2 -0
  172. package/lib/src/hooks/useActiveTrack.js +28 -0
  173. package/lib/src/hooks/useAppIsInBackground.d.ts +1 -0
  174. package/lib/src/hooks/useAppIsInBackground.js +16 -0
  175. package/lib/src/hooks/useIsPlaying.d.ts +35 -0
  176. package/lib/src/hooks/useIsPlaying.js +50 -0
  177. package/lib/src/hooks/usePlayWhenReady.d.ts +1 -0
  178. package/lib/src/hooks/usePlayWhenReady.js +27 -0
  179. package/lib/src/hooks/usePlaybackState.d.ts +10 -0
  180. package/lib/src/hooks/usePlaybackState.js +35 -0
  181. package/lib/src/hooks/useProgress.d.ts +7 -0
  182. package/lib/src/hooks/useProgress.js +55 -0
  183. package/lib/src/hooks/useTrackPlayerEvents.d.ts +8 -0
  184. package/lib/src/hooks/useTrackPlayerEvents.js +30 -0
  185. package/lib/src/index.d.ts +6 -0
  186. package/lib/src/index.js +6 -0
  187. package/lib/src/interfaces/AndroidAutoBrowseTree.d.ts +5 -0
  188. package/lib/src/interfaces/AndroidAutoBrowseTree.js +1 -0
  189. package/lib/src/interfaces/AndroidOptions.d.ts +41 -0
  190. package/lib/src/interfaces/AndroidOptions.js +1 -0
  191. package/lib/src/interfaces/CustomButtons.d.ts +5 -0
  192. package/lib/src/interfaces/CustomButtons.js +1 -0
  193. package/lib/src/interfaces/FeedbackOptions.d.ts +6 -0
  194. package/lib/src/interfaces/FeedbackOptions.js +1 -0
  195. package/lib/src/interfaces/MediaItem.d.ts +18 -0
  196. package/lib/src/interfaces/MediaItem.js +1 -0
  197. package/lib/src/interfaces/MetadataOptions.d.ts +3 -0
  198. package/lib/src/interfaces/MetadataOptions.js +1 -0
  199. package/lib/src/interfaces/NowPlayingMetadata.d.ts +4 -0
  200. package/lib/src/interfaces/NowPlayingMetadata.js +1 -0
  201. package/lib/src/interfaces/PlaybackState.d.ts +8 -0
  202. package/lib/src/interfaces/PlaybackState.js +1 -0
  203. package/lib/src/interfaces/PlayerOptions.d.ts +132 -0
  204. package/lib/src/interfaces/PlayerOptions.js +1 -0
  205. package/lib/src/interfaces/Progress.d.ts +15 -0
  206. package/lib/src/interfaces/Progress.js +1 -0
  207. package/lib/src/interfaces/ResourceObject.d.ts +1 -0
  208. package/lib/src/interfaces/ResourceObject.js +1 -0
  209. package/lib/src/interfaces/ServiceHandler.d.ts +1 -0
  210. package/lib/src/interfaces/ServiceHandler.js +1 -0
  211. package/lib/src/interfaces/Track.d.ts +21 -0
  212. package/lib/src/interfaces/Track.js +1 -0
  213. package/lib/src/interfaces/TrackMetadataBase.d.ts +28 -0
  214. package/lib/src/interfaces/TrackMetadataBase.js +1 -0
  215. package/lib/src/interfaces/UpdateOptions.d.ts +52 -0
  216. package/lib/src/interfaces/UpdateOptions.js +1 -0
  217. package/lib/src/interfaces/events/AudioMetadataReceivedEvent.d.ts +33 -0
  218. package/lib/src/interfaces/events/AudioMetadataReceivedEvent.js +1 -0
  219. package/lib/src/interfaces/events/ControllerConnectedEvent.d.ts +8 -0
  220. package/lib/src/interfaces/events/ControllerConnectedEvent.js +1 -0
  221. package/lib/src/interfaces/events/EventPayloadByEvent.d.ts +77 -0
  222. package/lib/src/interfaces/events/EventPayloadByEvent.js +1 -0
  223. package/lib/src/interfaces/events/FFTUpdateEvent.d.ts +7 -0
  224. package/lib/src/interfaces/events/FFTUpdateEvent.js +1 -0
  225. package/lib/src/interfaces/events/PlaybackActiveTrackChangedEvent.d.ts +24 -0
  226. package/lib/src/interfaces/events/PlaybackActiveTrackChangedEvent.js +1 -0
  227. package/lib/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.d.ts +4 -0
  228. package/lib/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.js +1 -0
  229. package/lib/src/interfaces/events/PlaybackErrorEvent.d.ts +6 -0
  230. package/lib/src/interfaces/events/PlaybackErrorEvent.js +1 -0
  231. package/lib/src/interfaces/events/PlaybackMetadataReceivedEvent.d.ts +16 -0
  232. package/lib/src/interfaces/events/PlaybackMetadataReceivedEvent.js +1 -0
  233. package/lib/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.d.ts +4 -0
  234. package/lib/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.js +1 -0
  235. package/lib/src/interfaces/events/PlaybackProgressUpdatedEvent.d.ts +4 -0
  236. package/lib/src/interfaces/events/PlaybackProgressUpdatedEvent.js +1 -0
  237. package/lib/src/interfaces/events/PlaybackQueueEndedEvent.d.ts +9 -0
  238. package/lib/src/interfaces/events/PlaybackQueueEndedEvent.js +1 -0
  239. package/lib/src/interfaces/events/PlaybackResumeEvent.d.ts +3 -0
  240. package/lib/src/interfaces/events/PlaybackResumeEvent.js +1 -0
  241. package/lib/src/interfaces/events/PlaybackTrackChangedEvent.d.ts +11 -0
  242. package/lib/src/interfaces/events/PlaybackTrackChangedEvent.js +1 -0
  243. package/lib/src/interfaces/events/PlayerErrorEvent.d.ts +6 -0
  244. package/lib/src/interfaces/events/PlayerErrorEvent.js +1 -0
  245. package/lib/src/interfaces/events/RemoteBrowseEvent.d.ts +4 -0
  246. package/lib/src/interfaces/events/RemoteBrowseEvent.js +1 -0
  247. package/lib/src/interfaces/events/RemoteCustomActionEvent.d.ts +7 -0
  248. package/lib/src/interfaces/events/RemoteCustomActionEvent.js +1 -0
  249. package/lib/src/interfaces/events/RemoteDuckEvent.d.ts +13 -0
  250. package/lib/src/interfaces/events/RemoteDuckEvent.js +1 -0
  251. package/lib/src/interfaces/events/RemoteJumpBackwardEvent.d.ts +7 -0
  252. package/lib/src/interfaces/events/RemoteJumpBackwardEvent.js +1 -0
  253. package/lib/src/interfaces/events/RemoteJumpForwardEvent.d.ts +7 -0
  254. package/lib/src/interfaces/events/RemoteJumpForwardEvent.js +1 -0
  255. package/lib/src/interfaces/events/RemotePlayIdEvent.d.ts +4 -0
  256. package/lib/src/interfaces/events/RemotePlayIdEvent.js +1 -0
  257. package/lib/src/interfaces/events/RemotePlaySearchEvent.d.ts +9 -0
  258. package/lib/src/interfaces/events/RemotePlaySearchEvent.js +1 -0
  259. package/lib/src/interfaces/events/RemoteSearchEvent.d.ts +3 -0
  260. package/lib/src/interfaces/events/RemoteSearchEvent.js +1 -0
  261. package/lib/src/interfaces/events/RemoteSeekEvent.d.ts +4 -0
  262. package/lib/src/interfaces/events/RemoteSeekEvent.js +1 -0
  263. package/lib/src/interfaces/events/RemoteSetRatingEvent.d.ts +4 -0
  264. package/lib/src/interfaces/events/RemoteSetRatingEvent.js +1 -0
  265. package/lib/src/interfaces/events/RemoteSkipEvent.d.ts +3 -0
  266. package/lib/src/interfaces/events/RemoteSkipEvent.js +1 -0
  267. package/lib/src/interfaces/events/index.d.ts +20 -0
  268. package/lib/src/interfaces/events/index.js +20 -0
  269. package/lib/src/interfaces/index.d.ts +15 -0
  270. package/lib/src/interfaces/index.js +15 -0
  271. package/lib/src/resolveAssetSource.d.ts +2 -0
  272. package/lib/src/resolveAssetSource.js +3 -0
  273. package/lib/src/resolveAssetSource.web.d.ts +2 -0
  274. package/lib/src/resolveAssetSource.web.js +8 -0
  275. package/lib/src/trackPlayer.d.ts +371 -0
  276. package/lib/src/trackPlayer.js +627 -0
  277. package/lib/web/TrackPlayer/Player.d.ts +40 -0
  278. package/lib/web/TrackPlayer/Player.js +188 -0
  279. package/lib/web/TrackPlayer/PlaylistPlayer.d.ts +31 -0
  280. package/lib/web/TrackPlayer/PlaylistPlayer.js +181 -0
  281. package/lib/web/TrackPlayer/RepeatMode.d.ts +5 -0
  282. package/lib/web/TrackPlayer/RepeatMode.js +6 -0
  283. package/lib/web/TrackPlayer/SetupNotCalledError.d.ts +3 -0
  284. package/lib/web/TrackPlayer/SetupNotCalledError.js +5 -0
  285. package/lib/web/TrackPlayer/index.d.ts +3 -0
  286. package/lib/web/TrackPlayer/index.js +3 -0
  287. package/lib/web/TrackPlayerModule.d.ts +63 -0
  288. package/lib/web/TrackPlayerModule.js +153 -0
  289. package/lib/web/index.d.ts +3 -0
  290. package/lib/web/index.js +3 -0
  291. package/package.json +85 -6
  292. package/react-native-track-player.podspec +13 -13
  293. package/specs/NativeTrackPlayer.ts +153 -0
  294. package/src/TrackPlayerModule.web.ts +2 -0
  295. package/src/VideoView.tsx +51 -0
  296. package/src/constants/AndroidAudioContentType.ts +35 -0
  297. package/src/constants/AndroidAutoContentStyle.ts +10 -0
  298. package/src/constants/AppKilledPlaybackBehavior.ts +19 -0
  299. package/src/constants/Capability.ts +19 -0
  300. package/src/constants/Event.ts +173 -0
  301. package/src/constants/IOSCategory.ts +36 -0
  302. package/src/constants/IOSCategoryMode.ts +47 -0
  303. package/src/constants/IOSCategoryOptions.ts +44 -0
  304. package/src/constants/MediaItemPlayable.ts +4 -0
  305. package/src/constants/PitchAlgorithm.ts +16 -0
  306. package/src/constants/RatingType.ts +10 -0
  307. package/src/constants/RepeatMode.ts +10 -0
  308. package/src/constants/State.ts +34 -0
  309. package/src/constants/TrackType.ts +6 -0
  310. package/src/constants/index.ts +14 -0
  311. package/src/hooks/index.ts +6 -0
  312. package/src/hooks/useActiveTrack.ts +36 -0
  313. package/src/hooks/useAppIsInBackground.ts +20 -0
  314. package/src/hooks/useIsPlaying.ts +56 -0
  315. package/src/hooks/usePlayWhenReady.ts +37 -0
  316. package/src/hooks/usePlaybackState.ts +45 -0
  317. package/src/hooks/useProgress.ts +64 -0
  318. package/src/hooks/useTrackPlayerEvents.ts +48 -0
  319. package/src/index.ts +8 -0
  320. package/src/interfaces/AndroidAutoBrowseTree.ts +6 -0
  321. package/src/interfaces/AndroidOptions.ts +48 -0
  322. package/src/interfaces/CustomButtons.ts +6 -0
  323. package/src/interfaces/FeedbackOptions.ts +7 -0
  324. package/src/interfaces/MediaItem.ts +19 -0
  325. package/src/interfaces/MetadataOptions.ts +4 -0
  326. package/src/interfaces/NowPlayingMetadata.ts +5 -0
  327. package/src/interfaces/PlaybackState.ts +11 -0
  328. package/src/interfaces/PlayerOptions.ts +138 -0
  329. package/src/interfaces/Progress.ts +15 -0
  330. package/src/interfaces/ResourceObject.ts +1 -0
  331. package/src/interfaces/ServiceHandler.ts +1 -0
  332. package/src/interfaces/Track.ts +23 -0
  333. package/src/interfaces/TrackMetadataBase.ts +29 -0
  334. package/src/interfaces/UpdateOptions.ts +59 -0
  335. package/src/interfaces/events/AudioMetadataReceivedEvent.ts +37 -0
  336. package/src/interfaces/events/ControllerConnectedEvent.ts +9 -0
  337. package/src/interfaces/events/EventPayloadByEvent.ts +80 -0
  338. package/src/interfaces/events/FFTUpdateEvent.ts +9 -0
  339. package/src/interfaces/events/PlaybackActiveTrackChangedEvent.ts +29 -0
  340. package/src/interfaces/events/PlaybackAnimatedVolumeChangedEvent.ts +4 -0
  341. package/src/interfaces/events/PlaybackErrorEvent.ts +6 -0
  342. package/src/interfaces/events/PlaybackMetadataReceivedEvent.ts +16 -0
  343. package/src/interfaces/events/PlaybackPlayWhenReadyChangedEvent.ts +4 -0
  344. package/src/interfaces/events/PlaybackProgressUpdatedEvent.ts +5 -0
  345. package/src/interfaces/events/PlaybackQueueEndedEvent.ts +9 -0
  346. package/src/interfaces/events/PlaybackResumeEvent.ts +5 -0
  347. package/src/interfaces/events/PlaybackTrackChangedEvent.ts +11 -0
  348. package/src/interfaces/events/PlayerErrorEvent.ts +6 -0
  349. package/src/interfaces/events/RemoteBrowseEvent.ts +4 -0
  350. package/src/interfaces/events/RemoteCustomActionEvent.ts +7 -0
  351. package/src/interfaces/events/RemoteDuckEvent.ts +13 -0
  352. package/src/interfaces/events/RemoteJumpBackwardEvent.ts +7 -0
  353. package/src/interfaces/events/RemoteJumpForwardEvent.ts +7 -0
  354. package/src/interfaces/events/RemotePlayIdEvent.ts +4 -0
  355. package/src/interfaces/events/RemotePlaySearchEvent.ts +21 -0
  356. package/src/interfaces/events/RemoteSearchEvent.ts +3 -0
  357. package/src/interfaces/events/RemoteSeekEvent.ts +4 -0
  358. package/src/interfaces/events/RemoteSetRatingEvent.ts +5 -0
  359. package/src/interfaces/events/RemoteSkipEvent.ts +3 -0
  360. package/src/interfaces/events/index.ts +20 -0
  361. package/src/interfaces/index.ts +15 -0
  362. package/src/resolveAssetSource.ts +3 -0
  363. package/src/resolveAssetSource.web.ts +10 -0
  364. package/src/trackPlayer.ts +806 -0
  365. package/web/TrackPlayer/Player.ts +201 -0
  366. package/web/TrackPlayer/PlaylistPlayer.ts +215 -0
  367. package/web/TrackPlayer/RepeatMode.ts +6 -0
  368. package/web/TrackPlayer/SetupNotCalledError.ts +5 -0
  369. package/web/TrackPlayer/index.ts +3 -0
  370. package/web/TrackPlayerModule.ts +181 -0
  371. package/web/index.ts +4 -0
  372. package/CHANGELOG.md +0 -75
  373. package/android/react-native-music-control.iml +0 -139
  374. package/android/react-native-track-player.iml +0 -151
  375. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
  376. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
  377. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
  378. package/android/src/main/java/com/guichaguri/trackplayer/service/HeadlessJsMediaService.java +0 -174
  379. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
  380. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
  381. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
  382. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
  383. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
  384. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
  385. package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
  386. package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
  387. package/android/src/main/res/drawable-hdpi/ic_forward.png +0 -0
  388. package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
  389. package/android/src/main/res/drawable-hdpi/ic_next.png +0 -0
  390. package/android/src/main/res/drawable-hdpi/ic_pause.png +0 -0
  391. package/android/src/main/res/drawable-hdpi/ic_play.png +0 -0
  392. package/android/src/main/res/drawable-hdpi/ic_previous.png +0 -0
  393. package/android/src/main/res/drawable-hdpi/ic_rewind.png +0 -0
  394. package/android/src/main/res/drawable-hdpi/ic_stop.png +0 -0
  395. package/android/src/main/res/drawable-mdpi/ic_forward.png +0 -0
  396. package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
  397. package/android/src/main/res/drawable-mdpi/ic_next.png +0 -0
  398. package/android/src/main/res/drawable-mdpi/ic_pause.png +0 -0
  399. package/android/src/main/res/drawable-mdpi/ic_play.png +0 -0
  400. package/android/src/main/res/drawable-mdpi/ic_previous.png +0 -0
  401. package/android/src/main/res/drawable-mdpi/ic_rewind.png +0 -0
  402. package/android/src/main/res/drawable-mdpi/ic_stop.png +0 -0
  403. package/android/src/main/res/drawable-xhdpi/ic_forward.png +0 -0
  404. package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
  405. package/android/src/main/res/drawable-xhdpi/ic_next.png +0 -0
  406. package/android/src/main/res/drawable-xhdpi/ic_pause.png +0 -0
  407. package/android/src/main/res/drawable-xhdpi/ic_play.png +0 -0
  408. package/android/src/main/res/drawable-xhdpi/ic_previous.png +0 -0
  409. package/android/src/main/res/drawable-xhdpi/ic_rewind.png +0 -0
  410. package/android/src/main/res/drawable-xhdpi/ic_stop.png +0 -0
  411. package/android/src/main/res/drawable-xxhdpi/ic_forward.png +0 -0
  412. package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
  413. package/android/src/main/res/drawable-xxhdpi/ic_next.png +0 -0
  414. package/android/src/main/res/drawable-xxhdpi/ic_pause.png +0 -0
  415. package/android/src/main/res/drawable-xxhdpi/ic_play.png +0 -0
  416. package/android/src/main/res/drawable-xxhdpi/ic_previous.png +0 -0
  417. package/android/src/main/res/drawable-xxhdpi/ic_rewind.png +0 -0
  418. package/android/src/main/res/drawable-xxhdpi/ic_stop.png +0 -0
  419. package/android/src/main/res/drawable-xxxhdpi/ic_forward.png +0 -0
  420. package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
  421. package/android/src/main/res/drawable-xxxhdpi/ic_next.png +0 -0
  422. package/android/src/main/res/drawable-xxxhdpi/ic_pause.png +0 -0
  423. package/android/src/main/res/drawable-xxxhdpi/ic_play.png +0 -0
  424. package/android/src/main/res/drawable-xxxhdpi/ic_previous.png +0 -0
  425. package/android/src/main/res/drawable-xxxhdpi/ic_rewind.png +0 -0
  426. package/android/src/main/res/drawable-xxxhdpi/ic_stop.png +0 -0
  427. package/index.d.ts +0 -174
  428. package/index.js +0 -4
  429. package/ios/RNTrackPlayer/RNTrackPlayerBridge.h +0 -12
  430. package/ios/RNTrackPlayer/RNTrackPlayerBridge.m +0 -29
  431. package/ios/TrackPlayer.xcodeproj/project.pbxproj +0 -495
  432. package/ios/TrackPlayer.xcodeproj/project.xcworkspace/xcuserdata/marco.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  433. package/lib/ProgressComponent.js +0 -70
  434. package/lib/eventTypes.js +0 -28
  435. package/lib/hooks.js +0 -160
  436. package/lib/index.js +0 -177
  437. /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
+ }