react-native-nitro-player 0.7.0 → 0.7.1-alpha.1

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 (110) hide show
  1. package/README.md +47 -46
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrary.kt +9 -13
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +45 -90
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridDownloadManager.kt +48 -182
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridEqualizer.kt +21 -77
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +55 -104
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +113 -123
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/ExoPlayerCore.kt +82 -0
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/ListenerRegistry.kt +48 -0
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerAndroidAuto.kt +62 -0
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +153 -1887
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +122 -0
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerNotify.kt +44 -0
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerPlayback.kt +162 -0
  15. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueue.kt +179 -0
  16. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueueBuild.kt +170 -0
  17. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerSetup.kt +28 -0
  18. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerTempQueue.kt +121 -0
  19. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerUrlLoader.kt +98 -0
  20. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +27 -18
  21. package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +150 -135
  22. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +13 -30
  23. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +102 -162
  24. package/ios/HybridDownloadManager.swift +32 -26
  25. package/ios/HybridEqualizer.swift +48 -35
  26. package/ios/HybridTrackPlayer.swift +127 -102
  27. package/ios/core/ListenerRegistry.swift +60 -0
  28. package/ios/core/TrackPlayerCore.swift +130 -2356
  29. package/ios/core/TrackPlayerListener.swift +395 -0
  30. package/ios/core/TrackPlayerNotify.swift +52 -0
  31. package/ios/core/TrackPlayerPlayback.swift +274 -0
  32. package/ios/core/TrackPlayerQueue.swift +221 -0
  33. package/ios/core/TrackPlayerQueueBuild.swift +493 -0
  34. package/ios/core/TrackPlayerTempQueue.swift +167 -0
  35. package/ios/core/TrackPlayerUrlLoader.swift +169 -0
  36. package/ios/equalizer/EqualizerCore.swift +63 -123
  37. package/ios/media/MediaSessionManager.swift +32 -49
  38. package/ios/playlist/PlaylistManager.swift +2 -9
  39. package/ios/queue/HybridPlayerQueue.swift +69 -66
  40. package/lib/hooks/useDownloadedTracks.js +16 -13
  41. package/lib/hooks/useEqualizer.d.ts +4 -4
  42. package/lib/hooks/useEqualizer.js +22 -17
  43. package/lib/hooks/useEqualizerPresets.d.ts +3 -3
  44. package/lib/hooks/useEqualizerPresets.js +12 -18
  45. package/lib/specs/AndroidAutoMediaLibrary.nitro.d.ts +2 -2
  46. package/lib/specs/AudioDevices.nitro.d.ts +2 -2
  47. package/lib/specs/DownloadManager.nitro.d.ts +10 -10
  48. package/lib/specs/Equalizer.nitro.d.ts +10 -10
  49. package/lib/specs/TrackPlayer.nitro.d.ts +38 -16
  50. package/lib/types/EqualizerTypes.d.ts +3 -3
  51. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +2 -0
  52. package/nitrogen/generated/android/c++/JFunc_void_std__vector_TrackItem__std__vector_TrackItem_.hpp +122 -0
  53. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.cpp +31 -6
  54. package/nitrogen/generated/android/c++/JHybridAndroidAutoMediaLibrarySpec.hpp +2 -2
  55. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.cpp +16 -3
  56. package/nitrogen/generated/android/c++/JHybridAudioDevicesSpec.hpp +1 -1
  57. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.cpp +154 -44
  58. package/nitrogen/generated/android/c++/JHybridDownloadManagerSpec.hpp +10 -10
  59. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.cpp +130 -34
  60. package/nitrogen/generated/android/c++/JHybridEqualizerSpec.hpp +9 -9
  61. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +115 -24
  62. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +8 -8
  63. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +243 -24
  64. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +16 -8
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_std__vector_TrackItem__std__vector_TrackItem_.kt +80 -0
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAndroidAutoMediaLibrarySpec.kt +3 -2
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridAudioDevicesSpec.kt +2 -1
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridDownloadManagerSpec.kt +10 -10
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridEqualizerSpec.kt +10 -9
  70. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +9 -8
  71. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +45 -8
  72. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +74 -18
  73. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +380 -151
  74. package/nitrogen/generated/ios/c++/HybridDownloadManagerSpecSwift.hpp +10 -10
  75. package/nitrogen/generated/ios/c++/HybridEqualizerSpecSwift.hpp +12 -9
  76. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +23 -8
  77. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +82 -8
  78. package/nitrogen/generated/ios/swift/Func_void_EqualizerState.swift +46 -0
  79. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__DownloadedPlaylist_.swift +58 -0
  80. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__DownloadedTrack_.swift +58 -0
  81. package/nitrogen/generated/ios/swift/Func_void_std__variant_nitro__NullType__std__string_.swift +58 -0
  82. package/nitrogen/generated/ios/swift/Func_void_std__vector_DownloadedPlaylist_.swift +46 -0
  83. package/nitrogen/generated/ios/swift/Func_void_std__vector_DownloadedTrack_.swift +46 -0
  84. package/nitrogen/generated/ios/swift/Func_void_std__vector_EqualizerBand_.swift +5 -5
  85. package/nitrogen/generated/ios/swift/Func_void_std__vector_TrackItem__std__vector_TrackItem_.swift +46 -0
  86. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec.swift +10 -10
  87. package/nitrogen/generated/ios/swift/HybridDownloadManagerSpec_cxx.swift +141 -71
  88. package/nitrogen/generated/ios/swift/HybridEqualizerSpec.swift +9 -9
  89. package/nitrogen/generated/ios/swift/HybridEqualizerSpec_cxx.swift +105 -41
  90. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +8 -8
  91. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +95 -32
  92. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +16 -8
  93. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +267 -32
  94. package/nitrogen/generated/shared/c++/HybridAndroidAutoMediaLibrarySpec.hpp +3 -2
  95. package/nitrogen/generated/shared/c++/HybridAudioDevicesSpec.hpp +2 -1
  96. package/nitrogen/generated/shared/c++/HybridDownloadManagerSpec.hpp +10 -10
  97. package/nitrogen/generated/shared/c++/HybridEqualizerSpec.hpp +10 -9
  98. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +9 -8
  99. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +8 -0
  100. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +16 -8
  101. package/package.json +5 -5
  102. package/src/hooks/useDownloadedTracks.ts +17 -13
  103. package/src/hooks/useEqualizer.ts +26 -21
  104. package/src/hooks/useEqualizerPresets.ts +15 -21
  105. package/src/specs/AndroidAutoMediaLibrary.nitro.ts +2 -2
  106. package/src/specs/AudioDevices.nitro.ts +2 -2
  107. package/src/specs/DownloadManager.nitro.ts +10 -10
  108. package/src/specs/Equalizer.nitro.ts +10 -10
  109. package/src/specs/TrackPlayer.nitro.ts +52 -16
  110. package/src/types/EqualizerTypes.ts +17 -13
@@ -0,0 +1,82 @@
1
+ package com.margelo.nitro.nitroplayer.core
2
+
3
+ import android.os.HandlerThread
4
+ import android.content.Context
5
+ import androidx.media3.common.AudioAttributes
6
+ import androidx.media3.common.C
7
+ import androidx.media3.common.MediaItem
8
+ import androidx.media3.common.Player
9
+ import androidx.media3.exoplayer.DefaultLoadControl
10
+ import androidx.media3.exoplayer.ExoPlayer
11
+
12
+
13
+ class ExoPlayerCore(context: Context, playerThread: HandlerThread) {
14
+
15
+ /** The underlying ExoPlayer instance — accessible for MediaSessionManager wiring. */
16
+ internal val player: ExoPlayer = build(context, playerThread)
17
+
18
+ private fun build(context: Context, playerThread: HandlerThread): ExoPlayer {
19
+ val loadControl = DefaultLoadControl.Builder()
20
+ .setBufferDurationsMs(
21
+ /* minBufferMs */ 30_000,
22
+ /* maxBufferMs */ 120_000,
23
+ /* bufferForPlayback */ 2_500,
24
+ /* bufferForRebuffer */ 5_000,
25
+ )
26
+ .setBackBuffer(30_000, /* retainBackBufferFromKeyframe */ true)
27
+ .setTargetBufferBytes(C.LENGTH_UNSET)
28
+ .setPrioritizeTimeOverSizeThresholds(true)
29
+ .build()
30
+
31
+ val audioAttrs = AudioAttributes.Builder()
32
+ .setUsage(C.USAGE_MEDIA)
33
+ .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
34
+ .build()
35
+
36
+ return ExoPlayer.Builder(context)
37
+ .setLooper(playerThread.looper)
38
+ .setLoadControl(loadControl)
39
+ .setAudioAttributes(audioAttrs, /* handleAudioFocus */ true)
40
+ .setHandleAudioBecomingNoisy(true)
41
+ .setPauseAtEndOfMediaItems(false)
42
+ .build()
43
+ }
44
+
45
+ // ── Playback ───────────────────────────────────────────────────────────
46
+ fun play() = player.play()
47
+ fun pause() = player.pause()
48
+ fun seekTo(positionMs: Long) = player.seekTo(positionMs)
49
+ fun seekToNext() = player.seekToNextMediaItem()
50
+ fun hasNextMediaItem(): Boolean = player.hasNextMediaItem()
51
+ fun setRepeatMode(mode: Int) { player.repeatMode = mode }
52
+ fun setVolume(volume: Float) { player.volume = volume }
53
+ fun setPlaybackSpeed(speed: Float) = player.setPlaybackSpeed(speed)
54
+ fun getPlaybackSpeed(): Float = player.playbackParameters.speed
55
+
56
+ // ── Queue mutations ────────────────────────────────────────────────────
57
+ fun prepare() = player.prepare()
58
+ fun seekToDefaultPosition(windowIndex: Int) = player.seekToDefaultPosition(windowIndex)
59
+ fun clearMediaItems() = player.clearMediaItems()
60
+ fun setMediaItems(items: List<MediaItem>, resetPosition: Boolean = false) =
61
+ player.setMediaItems(items, resetPosition)
62
+ fun addMediaItems(items: List<MediaItem>) = player.addMediaItems(items)
63
+ fun removeMediaItems(fromIndex: Int, toIndex: Int) =
64
+ player.removeMediaItems(fromIndex, toIndex)
65
+ fun replaceMediaItem(index: Int, item: MediaItem) = player.replaceMediaItem(index, item)
66
+
67
+ // ── Listener wiring ────────────────────────────────────────────────────
68
+ fun addListener(listener: Player.Listener) = player.addListener(listener)
69
+ fun removeListener(listener: Player.Listener) = player.removeListener(listener)
70
+
71
+ // ── State reads ────────────────────────────────────────────────────────
72
+ val playbackState: Int get() = player.playbackState
73
+ val isPlaying: Boolean get() = player.isPlaying
74
+ var playWhenReady: Boolean
75
+ get() = player.playWhenReady
76
+ set(value) { player.playWhenReady = value }
77
+ val currentMediaItem: MediaItem? get() = player.currentMediaItem
78
+ val currentMediaItemIndex: Int get() = player.currentMediaItemIndex
79
+ val currentPosition: Long get() = player.currentPosition
80
+ val duration: Long get() = player.duration
81
+ val mediaItemCount: Int get() = player.mediaItemCount
82
+ }
@@ -0,0 +1,48 @@
1
+ package com.margelo.nitro.nitroplayer.core
2
+
3
+ import java.util.concurrent.CopyOnWriteArrayList
4
+ import java.util.concurrent.atomic.AtomicLong
5
+
6
+ /**
7
+ * Thread-safe listener registry with stable numeric IDs for add/remove.
8
+ * Uses CopyOnWriteArrayList for lock-free iteration and AtomicLong for ID generation.
9
+ */
10
+ class ListenerRegistry<T> {
11
+ private data class Entry<T>(val id: Long, val callback: T)
12
+
13
+ private val entries = CopyOnWriteArrayList<Entry<T>>()
14
+ private val nextId = AtomicLong(0)
15
+
16
+ /** Register a callback and return its stable ID for later removal. */
17
+ fun add(callback: T): Long {
18
+ val id = nextId.incrementAndGet()
19
+ entries.add(Entry(id, callback))
20
+ return id
21
+ }
22
+
23
+ /** Remove the callback with the given ID. Returns true if found. */
24
+ fun remove(id: Long): Boolean {
25
+ val iterator = entries.iterator()
26
+ while (iterator.hasNext()) {
27
+ val entry = iterator.next()
28
+ if (entry.id == id) {
29
+ entries.remove(entry)
30
+ return true
31
+ }
32
+ }
33
+ return false
34
+ }
35
+
36
+ /** Remove all registered callbacks. */
37
+ fun clear() = entries.clear()
38
+
39
+ /** Invoke action for every registered callback (snapshot iteration — safe under mutation). */
40
+ fun forEach(action: (T) -> Unit) {
41
+ for (entry in entries) {
42
+ action(entry.callback)
43
+ }
44
+ }
45
+
46
+ /** True when no callbacks are registered. */
47
+ val isEmpty: Boolean get() = entries.isEmpty()
48
+ }
@@ -0,0 +1,62 @@
1
+ @file:Suppress("ktlint:standard:max-line-length")
2
+
3
+ package com.margelo.nitro.nitroplayer.core
4
+
5
+ import com.margelo.nitro.nitroplayer.connection.AndroidAutoConnectionDetector
6
+ import com.margelo.nitro.nitroplayer.media.MediaLibraryParser
7
+ import com.margelo.nitro.nitroplayer.media.NitroPlayerMediaBrowserService
8
+
9
+ /**
10
+ * Android Auto integration — detector setup runs on the main thread (receiver
11
+ * registration), playback commands are suspend and run on the player thread.
12
+ */
13
+
14
+ /** Called on the main thread from TrackPlayerCore.init via handler.post. */
15
+ internal fun TrackPlayerCore.setupAndroidAutoDetector() {
16
+ androidAutoConnectionDetector = AndroidAutoConnectionDetector(context).apply {
17
+ onConnectionChanged = { connected, _ ->
18
+ handler.post {
19
+ isAndroidAutoConnectedField = connected
20
+ NitroPlayerMediaBrowserService.isAndroidAutoConnected = connected
21
+ notifyAndroidAutoConnection(connected)
22
+ }
23
+ }
24
+ registerCarConnectionReceiver()
25
+ }
26
+ }
27
+
28
+ /** Called by MediaBrowserService when the user picks a track in Android Auto. */
29
+ suspend fun TrackPlayerCore.playFromPlaylistTrack(mediaId: String) = withPlayerContext {
30
+ try {
31
+ val colonIndex = mediaId.indexOf(':')
32
+ if (colonIndex <= 0 || colonIndex >= mediaId.length - 1) return@withPlayerContext
33
+ val playlistId = mediaId.substring(0, colonIndex)
34
+ val trackId = mediaId.substring(colonIndex + 1)
35
+ val playlist = playlistManager.getPlaylist(playlistId) ?: return@withPlayerContext
36
+ val trackIndex = playlist.tracks.indexOfFirst { it.id == trackId }
37
+ if (trackIndex < 0) return@withPlayerContext
38
+ if (currentPlaylistId != playlistId) {
39
+ loadPlaylistInternal(playlistId)
40
+ }
41
+ playFromIndexInternal(trackIndex)
42
+ } catch (_: Exception) {}
43
+ }
44
+
45
+ private fun TrackPlayerCore.loadPlaylistInternal(playlistId: String) {
46
+ playNextStack.clear(); upNextQueue.clear()
47
+ currentTemporaryType = TrackPlayerCore.TemporaryType.NONE
48
+ val playlist = playlistManager.getPlaylist(playlistId) ?: return
49
+ currentPlaylistId = playlistId
50
+ updatePlayerQueue(playlist.tracks)
51
+ }
52
+
53
+ suspend fun TrackPlayerCore.setAndroidAutoMediaLibrary(libraryJson: String) = withPlayerContext {
54
+ val library = MediaLibraryParser.fromJson(libraryJson)
55
+ mediaLibraryManager.setMediaLibrary(library)
56
+ NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
57
+ }
58
+
59
+ suspend fun TrackPlayerCore.clearAndroidAutoMediaLibrary() = withPlayerContext {
60
+ mediaLibraryManager.clear()
61
+ NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
62
+ }