react-native-nitro-player 1.7.0-alpha.3 → 1.7.0-alpha.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 (59) hide show
  1. package/README.md +9 -0
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridPlayerQueue.kt +45 -7
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerAudioFocus.kt +65 -0
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +46 -14
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +2 -0
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerPlayback.kt +36 -12
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueue.kt +1 -1
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerQueueBuild.kt +9 -3
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerUrlLoader.kt +7 -3
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/AudioFocusController.kt +87 -0
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/ExoPlayerBuilder.kt +3 -0
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +8 -2
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/PlaybackService.kt +26 -1
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +60 -0
  15. package/ios/cast/CastQueueDiff.swift +58 -0
  16. package/ios/cast/CastQueueReconciler.swift +228 -0
  17. package/ios/core/CastSessionManager.swift +215 -31
  18. package/ios/core/TrackPlayerCast.swift +96 -65
  19. package/ios/core/TrackPlayerCore.swift +31 -0
  20. package/ios/core/TrackPlayerListener.swift +19 -3
  21. package/ios/core/TrackPlayerPlayback.swift +12 -10
  22. package/ios/core/TrackPlayerQueue.swift +10 -2
  23. package/ios/core/TrackPlayerQueueBuild.swift +21 -9
  24. package/ios/core/TrackPlayerTempQueue.swift +27 -15
  25. package/ios/core/TrackPlayerUrlLoader.swift +6 -2
  26. package/ios/playlist/PlaylistManager.swift +60 -1
  27. package/ios/queue/HybridPlayerQueue.swift +40 -13
  28. package/lib/hooks/callbackManager.d.ts +2 -0
  29. package/lib/hooks/callbackManager.js +23 -8
  30. package/lib/specs/TrackPlayer.nitro.d.ts +5 -1
  31. package/lib/types/PlayerQueue.d.ts +14 -0
  32. package/nitrogen/generated/android/c++/JAndroidAudioFocusMode.hpp +61 -0
  33. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.cpp +43 -0
  34. package/nitrogen/generated/android/c++/JHybridPlayerQueueSpec.hpp +2 -0
  35. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +4 -0
  36. package/nitrogen/generated/android/c++/JPlayerConfig.hpp +9 -3
  37. package/nitrogen/generated/android/c++/JShufflePlaylistOptions.hpp +57 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/AndroidAudioFocusMode.kt +24 -0
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridPlayerQueueSpec.kt +8 -0
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/PlayerConfig.kt +6 -3
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/ShufflePlaylistOptions.kt +38 -0
  42. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +36 -0
  43. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +6 -0
  44. package/nitrogen/generated/ios/c++/HybridPlayerQueueSpecSwift.hpp +19 -0
  45. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +3 -0
  46. package/nitrogen/generated/ios/swift/AndroidAudioFocusMode.swift +44 -0
  47. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec.swift +2 -0
  48. package/nitrogen/generated/ios/swift/HybridPlayerQueueSpec_cxx.swift +38 -0
  49. package/nitrogen/generated/ios/swift/PlayerConfig.swift +12 -1
  50. package/nitrogen/generated/ios/swift/ShufflePlaylistOptions.swift +42 -0
  51. package/nitrogen/generated/shared/c++/AndroidAudioFocusMode.hpp +80 -0
  52. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.cpp +2 -0
  53. package/nitrogen/generated/shared/c++/HybridPlayerQueueSpec.hpp +5 -0
  54. package/nitrogen/generated/shared/c++/PlayerConfig.hpp +9 -3
  55. package/nitrogen/generated/shared/c++/ShufflePlaylistOptions.hpp +83 -0
  56. package/package.json +1 -1
  57. package/src/hooks/callbackManager.ts +25 -10
  58. package/src/specs/TrackPlayer.nitro.ts +11 -0
  59. package/src/types/PlayerQueue.ts +17 -0
@@ -8,6 +8,8 @@
8
8
  #pragma once
9
9
 
10
10
  // Forward declarations of C++ defined types
11
+ // Forward declaration of `AndroidAudioFocusMode` to properly resolve imports.
12
+ namespace margelo::nitro::nitroplayer { enum class AndroidAudioFocusMode; }
11
13
  // Forward declaration of `CastState` to properly resolve imports.
12
14
  namespace margelo::nitro::nitroplayer { enum class CastState; }
13
15
  // Forward declaration of `CurrentPlayingType` to properly resolve imports.
@@ -66,6 +68,8 @@ namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
66
68
  namespace margelo::nitro::nitroplayer { enum class Reason; }
67
69
  // Forward declaration of `RepeatMode` to properly resolve imports.
68
70
  namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
71
+ // Forward declaration of `ShufflePlaylistOptions` to properly resolve imports.
72
+ namespace margelo::nitro::nitroplayer { struct ShufflePlaylistOptions; }
69
73
  // Forward declaration of `StorageLocation` to properly resolve imports.
70
74
  namespace margelo::nitro::nitroplayer { enum class StorageLocation; }
71
75
  // Forward declaration of `TimedMetadata` to properly resolve imports.
@@ -90,6 +94,7 @@ namespace NitroPlayer { class HybridPlayerQueueSpec_cxx; }
90
94
  namespace NitroPlayer { class HybridTrackPlayerSpec_cxx; }
91
95
 
92
96
  // Include C++ defined types
97
+ #include "AndroidAudioFocusMode.hpp"
93
98
  #include "CastState.hpp"
94
99
  #include "CurrentPlayingType.hpp"
95
100
  #include "DownloadConfig.hpp"
@@ -119,6 +124,7 @@ namespace NitroPlayer { class HybridTrackPlayerSpec_cxx; }
119
124
  #include "QueueOperation.hpp"
120
125
  #include "Reason.hpp"
121
126
  #include "RepeatMode.hpp"
127
+ #include "ShufflePlaylistOptions.hpp"
122
128
  #include "StorageLocation.hpp"
123
129
  #include "TimedMetadata.hpp"
124
130
  #include "TrackItem.hpp"
@@ -1426,6 +1432,21 @@ namespace margelo::nitro::nitroplayer::bridge::swift {
1426
1432
  return vector;
1427
1433
  }
1428
1434
 
1435
+ // pragma MARK: std::optional<ShufflePlaylistOptions>
1436
+ /**
1437
+ * Specialized version of `std::optional<ShufflePlaylistOptions>`.
1438
+ */
1439
+ using std__optional_ShufflePlaylistOptions_ = std::optional<ShufflePlaylistOptions>;
1440
+ inline std::optional<ShufflePlaylistOptions> create_std__optional_ShufflePlaylistOptions_(const ShufflePlaylistOptions& value) noexcept {
1441
+ return std::optional<ShufflePlaylistOptions>(value);
1442
+ }
1443
+ inline bool has_value_std__optional_ShufflePlaylistOptions_(const std::optional<ShufflePlaylistOptions>& optional) noexcept {
1444
+ return optional.has_value();
1445
+ }
1446
+ inline ShufflePlaylistOptions get_std__optional_ShufflePlaylistOptions_(const std::optional<ShufflePlaylistOptions>& optional) noexcept {
1447
+ return optional.value();
1448
+ }
1449
+
1429
1450
  // pragma MARK: std::optional<QueueOperation>
1430
1451
  /**
1431
1452
  * Specialized version of `std::optional<QueueOperation>`.
@@ -1627,6 +1648,21 @@ namespace margelo::nitro::nitroplayer::bridge::swift {
1627
1648
  return Func_void_PlayerState_Wrapper(std::move(value));
1628
1649
  }
1629
1650
 
1651
+ // pragma MARK: std::optional<AndroidAudioFocusMode>
1652
+ /**
1653
+ * Specialized version of `std::optional<AndroidAudioFocusMode>`.
1654
+ */
1655
+ using std__optional_AndroidAudioFocusMode_ = std::optional<AndroidAudioFocusMode>;
1656
+ inline std::optional<AndroidAudioFocusMode> create_std__optional_AndroidAudioFocusMode_(const AndroidAudioFocusMode& value) noexcept {
1657
+ return std::optional<AndroidAudioFocusMode>(value);
1658
+ }
1659
+ inline bool has_value_std__optional_AndroidAudioFocusMode_(const std::optional<AndroidAudioFocusMode>& optional) noexcept {
1660
+ return optional.has_value();
1661
+ }
1662
+ inline AndroidAudioFocusMode get_std__optional_AndroidAudioFocusMode_(const std::optional<AndroidAudioFocusMode>& optional) noexcept {
1663
+ return optional.value();
1664
+ }
1665
+
1630
1666
  // pragma MARK: std::optional<Reason>
1631
1667
  /**
1632
1668
  * Specialized version of `std::optional<Reason>`.
@@ -8,6 +8,8 @@
8
8
  #pragma once
9
9
 
10
10
  // Forward declarations of C++ defined types
11
+ // Forward declaration of `AndroidAudioFocusMode` to properly resolve imports.
12
+ namespace margelo::nitro::nitroplayer { enum class AndroidAudioFocusMode; }
11
13
  // Forward declaration of `CastState` to properly resolve imports.
12
14
  namespace margelo::nitro::nitroplayer { enum class CastState; }
13
15
  // Forward declaration of `CurrentPlayingType` to properly resolve imports.
@@ -68,6 +70,8 @@ namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
68
70
  namespace margelo::nitro::nitroplayer { enum class Reason; }
69
71
  // Forward declaration of `RepeatMode` to properly resolve imports.
70
72
  namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
73
+ // Forward declaration of `ShufflePlaylistOptions` to properly resolve imports.
74
+ namespace margelo::nitro::nitroplayer { struct ShufflePlaylistOptions; }
71
75
  // Forward declaration of `StorageLocation` to properly resolve imports.
72
76
  namespace margelo::nitro::nitroplayer { enum class StorageLocation; }
73
77
  // Forward declaration of `TimedMetadata` to properly resolve imports.
@@ -78,6 +82,7 @@ namespace margelo::nitro::nitroplayer { struct TrackItem; }
78
82
  namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
79
83
 
80
84
  // Include C++ defined types
85
+ #include "AndroidAudioFocusMode.hpp"
81
86
  #include "CastState.hpp"
82
87
  #include "CurrentPlayingType.hpp"
83
88
  #include "DownloadConfig.hpp"
@@ -108,6 +113,7 @@ namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
108
113
  #include "QueueOperation.hpp"
109
114
  #include "Reason.hpp"
110
115
  #include "RepeatMode.hpp"
116
+ #include "ShufflePlaylistOptions.hpp"
111
117
  #include "StorageLocation.hpp"
112
118
  #include "TimedMetadata.hpp"
113
119
  #include "TrackItem.hpp"
@@ -16,6 +16,8 @@ namespace NitroPlayer { class HybridPlayerQueueSpec_cxx; }
16
16
  namespace margelo::nitro::nitroplayer { struct Playlist; }
17
17
  // Forward declaration of `TrackItem` to properly resolve imports.
18
18
  namespace margelo::nitro::nitroplayer { struct TrackItem; }
19
+ // Forward declaration of `ShufflePlaylistOptions` to properly resolve imports.
20
+ namespace margelo::nitro::nitroplayer { struct ShufflePlaylistOptions; }
19
21
  // Forward declaration of `QueueOperation` to properly resolve imports.
20
22
  namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
21
23
 
@@ -28,6 +30,7 @@ namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
28
30
  #include "TrackItem.hpp"
29
31
  #include <vector>
30
32
  #include <NitroModules/AnyMap.hpp>
33
+ #include "ShufflePlaylistOptions.hpp"
31
34
  #include "QueueOperation.hpp"
32
35
  #include <functional>
33
36
 
@@ -153,6 +156,22 @@ namespace margelo::nitro::nitroplayer {
153
156
  auto __value = std::move(__result.value());
154
157
  return __value;
155
158
  }
159
+ inline std::shared_ptr<Promise<void>> removeTracksFromPlaylist(const std::string& playlistId, const std::vector<std::string>& trackIds) override {
160
+ auto __result = _swiftPart.removeTracksFromPlaylist(playlistId, trackIds);
161
+ if (__result.hasError()) [[unlikely]] {
162
+ std::rethrow_exception(__result.error());
163
+ }
164
+ auto __value = std::move(__result.value());
165
+ return __value;
166
+ }
167
+ inline std::shared_ptr<Promise<void>> shufflePlaylist(const std::string& playlistId, const std::optional<ShufflePlaylistOptions>& options) override {
168
+ auto __result = _swiftPart.shufflePlaylist(playlistId, options);
169
+ if (__result.hasError()) [[unlikely]] {
170
+ std::rethrow_exception(__result.error());
171
+ }
172
+ auto __value = std::move(__result.value());
173
+ return __value;
174
+ }
156
175
  inline std::shared_ptr<Promise<void>> loadPlaylist(const std::string& playlistId, std::optional<double> index) override {
157
176
  auto __result = _swiftPart.loadPlaylist(playlistId, index);
158
177
  if (__result.hasError()) [[unlikely]] {
@@ -24,6 +24,8 @@ namespace margelo::nitro::nitroplayer { enum class CurrentPlayingType; }
24
24
  namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
25
25
  // Forward declaration of `PlayerConfig` to properly resolve imports.
26
26
  namespace margelo::nitro::nitroplayer { struct PlayerConfig; }
27
+ // Forward declaration of `AndroidAudioFocusMode` to properly resolve imports.
28
+ namespace margelo::nitro::nitroplayer { enum class AndroidAudioFocusMode; }
27
29
  // Forward declaration of `Reason` to properly resolve imports.
28
30
  namespace margelo::nitro::nitroplayer { enum class Reason; }
29
31
  // Forward declaration of `TimedMetadata` to properly resolve imports.
@@ -42,6 +44,7 @@ namespace margelo::nitro::nitroplayer { struct TimedMetadata; }
42
44
  #include "CurrentPlayingType.hpp"
43
45
  #include "RepeatMode.hpp"
44
46
  #include "PlayerConfig.hpp"
47
+ #include "AndroidAudioFocusMode.hpp"
45
48
  #include "Reason.hpp"
46
49
  #include <functional>
47
50
  #include "TimedMetadata.hpp"
@@ -0,0 +1,44 @@
1
+ ///
2
+ /// AndroidAudioFocusMode.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ /**
9
+ * Represents the JS union `AndroidAudioFocusMode`, backed by a C++ enum.
10
+ */
11
+ public typealias AndroidAudioFocusMode = margelo.nitro.nitroplayer.AndroidAudioFocusMode
12
+
13
+ public extension AndroidAudioFocusMode {
14
+ /**
15
+ * Get a AndroidAudioFocusMode for the given String value, or
16
+ * return `nil` if the given value was invalid/unknown.
17
+ */
18
+ init?(fromString string: String) {
19
+ switch string {
20
+ case "pause":
21
+ self = .pause
22
+ case "duck":
23
+ self = .duck
24
+ case "ignore":
25
+ self = .ignore
26
+ default:
27
+ return nil
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Get the String value this AndroidAudioFocusMode represents.
33
+ */
34
+ var stringValue: String {
35
+ switch self {
36
+ case .pause:
37
+ return "pause"
38
+ case .duck:
39
+ return "duck"
40
+ case .ignore:
41
+ return "ignore"
42
+ }
43
+ }
44
+ }
@@ -22,6 +22,8 @@ public protocol HybridPlayerQueueSpec_protocol: HybridObject {
22
22
  func addTracksToPlaylist(playlistId: String, tracks: [TrackItem], index: Double?) throws -> Promise<Void>
23
23
  func removeTrackFromPlaylist(playlistId: String, trackId: String) throws -> Promise<Void>
24
24
  func reorderTrackInPlaylist(playlistId: String, trackId: String, newIndex: Double) throws -> Promise<Void>
25
+ func removeTracksFromPlaylist(playlistId: String, trackIds: [String]) throws -> Promise<Void>
26
+ func shufflePlaylist(playlistId: String, options: ShufflePlaylistOptions?) throws -> Promise<Void>
25
27
  func loadPlaylist(playlistId: String, index: Double?) throws -> Promise<Void>
26
28
  func getCurrentPlaylistId() throws -> Variant_NullType_String
27
29
  func onPlaylistsChanged(callback: @escaping (_ playlists: [Playlist], _ operation: QueueOperation?) -> Void) throws -> Void
@@ -343,6 +343,44 @@ open class HybridPlayerQueueSpec_cxx {
343
343
  }
344
344
  }
345
345
 
346
+ @inline(__always)
347
+ public final func removeTracksFromPlaylist(playlistId: std.string, trackIds: bridge.std__vector_std__string_) -> bridge.Result_std__shared_ptr_Promise_void___ {
348
+ do {
349
+ let __result = try self.__implementation.removeTracksFromPlaylist(playlistId: String(playlistId), trackIds: trackIds.map({ __item in String(__item) }))
350
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in
351
+ let __promise = bridge.create_std__shared_ptr_Promise_void__()
352
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)
353
+ __result
354
+ .then({ __result in __promiseHolder.resolve() })
355
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
356
+ return __promise
357
+ }()
358
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)
359
+ } catch (let __error) {
360
+ let __exceptionPtr = __error.toCpp()
361
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
362
+ }
363
+ }
364
+
365
+ @inline(__always)
366
+ public final func shufflePlaylist(playlistId: std.string, options: bridge.std__optional_ShufflePlaylistOptions_) -> bridge.Result_std__shared_ptr_Promise_void___ {
367
+ do {
368
+ let __result = try self.__implementation.shufflePlaylist(playlistId: String(playlistId), options: options.value)
369
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_void__ in
370
+ let __promise = bridge.create_std__shared_ptr_Promise_void__()
371
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_void__(__promise)
372
+ __result
373
+ .then({ __result in __promiseHolder.resolve() })
374
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
375
+ return __promise
376
+ }()
377
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__resultCpp)
378
+ } catch (let __error) {
379
+ let __exceptionPtr = __error.toCpp()
380
+ return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
381
+ }
382
+ }
383
+
346
384
  @inline(__always)
347
385
  public final func loadPlaylist(playlistId: std.string, index: bridge.std__optional_double_) -> bridge.Result_std__shared_ptr_Promise_void___ {
348
386
  do {
@@ -18,7 +18,7 @@ public extension PlayerConfig {
18
18
  /**
19
19
  * Create a new instance of `PlayerConfig`.
20
20
  */
21
- init(androidAutoEnabled: Bool?, carPlayEnabled: Bool?, showInNotification: Bool?, remoteSkipForwardInterval: Double?, remoteSkipBackwardInterval: Double?, lookaheadCount: Double?, androidNotificationIcon: String?) {
21
+ init(androidAutoEnabled: Bool?, carPlayEnabled: Bool?, showInNotification: Bool?, remoteSkipForwardInterval: Double?, remoteSkipBackwardInterval: Double?, lookaheadCount: Double?, androidNotificationIcon: String?, androidAudioFocus: AndroidAudioFocusMode?) {
22
22
  self.init({ () -> bridge.std__optional_bool_ in
23
23
  if let __unwrappedValue = androidAutoEnabled {
24
24
  return bridge.create_std__optional_bool_(__unwrappedValue)
@@ -61,6 +61,12 @@ public extension PlayerConfig {
61
61
  } else {
62
62
  return .init()
63
63
  }
64
+ }(), { () -> bridge.std__optional_AndroidAudioFocusMode_ in
65
+ if let __unwrappedValue = androidAudioFocus {
66
+ return bridge.create_std__optional_AndroidAudioFocusMode_(__unwrappedValue)
67
+ } else {
68
+ return .init()
69
+ }
64
70
  }())
65
71
  }
66
72
 
@@ -147,4 +153,9 @@ public extension PlayerConfig {
147
153
  }
148
154
  }()
149
155
  }
156
+
157
+ @inline(__always)
158
+ var androidAudioFocus: AndroidAudioFocusMode? {
159
+ return self.__androidAudioFocus.value
160
+ }
150
161
  }
@@ -0,0 +1,42 @@
1
+ ///
2
+ /// ShufflePlaylistOptions.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ import NitroModules
9
+
10
+ /**
11
+ * Represents an instance of `ShufflePlaylistOptions`, backed by a C++ struct.
12
+ */
13
+ public typealias ShufflePlaylistOptions = margelo.nitro.nitroplayer.ShufflePlaylistOptions
14
+
15
+ public extension ShufflePlaylistOptions {
16
+ private typealias bridge = margelo.nitro.nitroplayer.bridge.swift
17
+
18
+ /**
19
+ * Create a new instance of `ShufflePlaylistOptions`.
20
+ */
21
+ init(keepCurrentTrackFirst: Bool?) {
22
+ self.init({ () -> bridge.std__optional_bool_ in
23
+ if let __unwrappedValue = keepCurrentTrackFirst {
24
+ return bridge.create_std__optional_bool_(__unwrappedValue)
25
+ } else {
26
+ return .init()
27
+ }
28
+ }())
29
+ }
30
+
31
+ @inline(__always)
32
+ var keepCurrentTrackFirst: Bool? {
33
+ return { () -> Bool? in
34
+ if bridge.has_value_std__optional_bool_(self.__keepCurrentTrackFirst) {
35
+ let __unwrapped = bridge.get_std__optional_bool_(self.__keepCurrentTrackFirst)
36
+ return __unwrapped
37
+ } else {
38
+ return nil
39
+ }
40
+ }()
41
+ }
42
+ }
@@ -0,0 +1,80 @@
1
+ ///
2
+ /// AndroidAudioFocusMode.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/NitroHash.hpp>)
11
+ #include <NitroModules/NitroHash.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
16
+ #include <NitroModules/JSIConverter.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
21
+ #include <NitroModules/NitroDefines.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+
26
+ namespace margelo::nitro::nitroplayer {
27
+
28
+ /**
29
+ * An enum which can be represented as a JavaScript union (AndroidAudioFocusMode).
30
+ */
31
+ enum class AndroidAudioFocusMode {
32
+ PAUSE SWIFT_NAME(pause) = 0,
33
+ DUCK SWIFT_NAME(duck) = 1,
34
+ IGNORE SWIFT_NAME(ignore) = 2,
35
+ } CLOSED_ENUM;
36
+
37
+ } // namespace margelo::nitro::nitroplayer
38
+
39
+ namespace margelo::nitro {
40
+
41
+ // C++ AndroidAudioFocusMode <> JS AndroidAudioFocusMode (union)
42
+ template <>
43
+ struct JSIConverter<margelo::nitro::nitroplayer::AndroidAudioFocusMode> final {
44
+ static inline margelo::nitro::nitroplayer::AndroidAudioFocusMode fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
45
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
46
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
47
+ case hashString("pause"): return margelo::nitro::nitroplayer::AndroidAudioFocusMode::PAUSE;
48
+ case hashString("duck"): return margelo::nitro::nitroplayer::AndroidAudioFocusMode::DUCK;
49
+ case hashString("ignore"): return margelo::nitro::nitroplayer::AndroidAudioFocusMode::IGNORE;
50
+ default: [[unlikely]]
51
+ throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum AndroidAudioFocusMode - invalid value!");
52
+ }
53
+ }
54
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::nitroplayer::AndroidAudioFocusMode arg) {
55
+ switch (arg) {
56
+ case margelo::nitro::nitroplayer::AndroidAudioFocusMode::PAUSE: return JSIConverter<std::string>::toJSI(runtime, "pause");
57
+ case margelo::nitro::nitroplayer::AndroidAudioFocusMode::DUCK: return JSIConverter<std::string>::toJSI(runtime, "duck");
58
+ case margelo::nitro::nitroplayer::AndroidAudioFocusMode::IGNORE: return JSIConverter<std::string>::toJSI(runtime, "ignore");
59
+ default: [[unlikely]]
60
+ throw std::invalid_argument("Cannot convert AndroidAudioFocusMode to JS - invalid value: "
61
+ + std::to_string(static_cast<int>(arg)) + "!");
62
+ }
63
+ }
64
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
65
+ if (!value.isString()) {
66
+ return false;
67
+ }
68
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
69
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
70
+ case hashString("pause"):
71
+ case hashString("duck"):
72
+ case hashString("ignore"):
73
+ return true;
74
+ default:
75
+ return false;
76
+ }
77
+ }
78
+ };
79
+
80
+ } // namespace margelo::nitro
@@ -23,6 +23,8 @@ namespace margelo::nitro::nitroplayer {
23
23
  prototype.registerHybridMethod("addTracksToPlaylist", &HybridPlayerQueueSpec::addTracksToPlaylist);
24
24
  prototype.registerHybridMethod("removeTrackFromPlaylist", &HybridPlayerQueueSpec::removeTrackFromPlaylist);
25
25
  prototype.registerHybridMethod("reorderTrackInPlaylist", &HybridPlayerQueueSpec::reorderTrackInPlaylist);
26
+ prototype.registerHybridMethod("removeTracksFromPlaylist", &HybridPlayerQueueSpec::removeTracksFromPlaylist);
27
+ prototype.registerHybridMethod("shufflePlaylist", &HybridPlayerQueueSpec::shufflePlaylist);
26
28
  prototype.registerHybridMethod("loadPlaylist", &HybridPlayerQueueSpec::loadPlaylist);
27
29
  prototype.registerHybridMethod("getCurrentPlaylistId", &HybridPlayerQueueSpec::getCurrentPlaylistId);
28
30
  prototype.registerHybridMethod("onPlaylistsChanged", &HybridPlayerQueueSpec::onPlaylistsChanged);
@@ -17,6 +17,8 @@
17
17
  namespace margelo::nitro::nitroplayer { struct Playlist; }
18
18
  // Forward declaration of `TrackItem` to properly resolve imports.
19
19
  namespace margelo::nitro::nitroplayer { struct TrackItem; }
20
+ // Forward declaration of `ShufflePlaylistOptions` to properly resolve imports.
21
+ namespace margelo::nitro::nitroplayer { struct ShufflePlaylistOptions; }
20
22
  // Forward declaration of `QueueOperation` to properly resolve imports.
21
23
  namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
22
24
 
@@ -28,6 +30,7 @@ namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
28
30
  #include <variant>
29
31
  #include <vector>
30
32
  #include "TrackItem.hpp"
33
+ #include "ShufflePlaylistOptions.hpp"
31
34
  #include "QueueOperation.hpp"
32
35
  #include <functional>
33
36
 
@@ -71,6 +74,8 @@ namespace margelo::nitro::nitroplayer {
71
74
  virtual std::shared_ptr<Promise<void>> addTracksToPlaylist(const std::string& playlistId, const std::vector<TrackItem>& tracks, std::optional<double> index) = 0;
72
75
  virtual std::shared_ptr<Promise<void>> removeTrackFromPlaylist(const std::string& playlistId, const std::string& trackId) = 0;
73
76
  virtual std::shared_ptr<Promise<void>> reorderTrackInPlaylist(const std::string& playlistId, const std::string& trackId, double newIndex) = 0;
77
+ virtual std::shared_ptr<Promise<void>> removeTracksFromPlaylist(const std::string& playlistId, const std::vector<std::string>& trackIds) = 0;
78
+ virtual std::shared_ptr<Promise<void>> shufflePlaylist(const std::string& playlistId, const std::optional<ShufflePlaylistOptions>& options) = 0;
74
79
  virtual std::shared_ptr<Promise<void>> loadPlaylist(const std::string& playlistId, std::optional<double> index) = 0;
75
80
  virtual std::variant<nitro::NullType, std::string> getCurrentPlaylistId() = 0;
76
81
  virtual void onPlaylistsChanged(const std::function<void(const std::vector<Playlist>& /* playlists */, std::optional<QueueOperation> /* operation */)>& callback) = 0;
@@ -28,10 +28,12 @@
28
28
  #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
29
  #endif
30
30
 
31
-
31
+ // Forward declaration of `AndroidAudioFocusMode` to properly resolve imports.
32
+ namespace margelo::nitro::nitroplayer { enum class AndroidAudioFocusMode; }
32
33
 
33
34
  #include <optional>
34
35
  #include <string>
36
+ #include "AndroidAudioFocusMode.hpp"
35
37
 
36
38
  namespace margelo::nitro::nitroplayer {
37
39
 
@@ -47,10 +49,11 @@ namespace margelo::nitro::nitroplayer {
47
49
  std::optional<double> remoteSkipBackwardInterval SWIFT_PRIVATE;
48
50
  std::optional<double> lookaheadCount SWIFT_PRIVATE;
49
51
  std::optional<std::string> androidNotificationIcon SWIFT_PRIVATE;
52
+ std::optional<AndroidAudioFocusMode> androidAudioFocus SWIFT_PRIVATE;
50
53
 
51
54
  public:
52
55
  PlayerConfig() = default;
53
- explicit PlayerConfig(std::optional<bool> androidAutoEnabled, std::optional<bool> carPlayEnabled, std::optional<bool> showInNotification, std::optional<double> remoteSkipForwardInterval, std::optional<double> remoteSkipBackwardInterval, std::optional<double> lookaheadCount, std::optional<std::string> androidNotificationIcon): androidAutoEnabled(androidAutoEnabled), carPlayEnabled(carPlayEnabled), showInNotification(showInNotification), remoteSkipForwardInterval(remoteSkipForwardInterval), remoteSkipBackwardInterval(remoteSkipBackwardInterval), lookaheadCount(lookaheadCount), androidNotificationIcon(androidNotificationIcon) {}
56
+ explicit PlayerConfig(std::optional<bool> androidAutoEnabled, std::optional<bool> carPlayEnabled, std::optional<bool> showInNotification, std::optional<double> remoteSkipForwardInterval, std::optional<double> remoteSkipBackwardInterval, std::optional<double> lookaheadCount, std::optional<std::string> androidNotificationIcon, std::optional<AndroidAudioFocusMode> androidAudioFocus): androidAutoEnabled(androidAutoEnabled), carPlayEnabled(carPlayEnabled), showInNotification(showInNotification), remoteSkipForwardInterval(remoteSkipForwardInterval), remoteSkipBackwardInterval(remoteSkipBackwardInterval), lookaheadCount(lookaheadCount), androidNotificationIcon(androidNotificationIcon), androidAudioFocus(androidAudioFocus) {}
54
57
 
55
58
  public:
56
59
  friend bool operator==(const PlayerConfig& lhs, const PlayerConfig& rhs) = default;
@@ -72,7 +75,8 @@ namespace margelo::nitro {
72
75
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "remoteSkipForwardInterval"))),
73
76
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "remoteSkipBackwardInterval"))),
74
77
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "lookaheadCount"))),
75
- JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "androidNotificationIcon")))
78
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "androidNotificationIcon"))),
79
+ JSIConverter<std::optional<margelo::nitro::nitroplayer::AndroidAudioFocusMode>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "androidAudioFocus")))
76
80
  );
77
81
  }
78
82
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitroplayer::PlayerConfig& arg) {
@@ -84,6 +88,7 @@ namespace margelo::nitro {
84
88
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "remoteSkipBackwardInterval"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.remoteSkipBackwardInterval));
85
89
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "lookaheadCount"), JSIConverter<std::optional<double>>::toJSI(runtime, arg.lookaheadCount));
86
90
  obj.setProperty(runtime, PropNameIDCache::get(runtime, "androidNotificationIcon"), JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.androidNotificationIcon));
91
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "androidAudioFocus"), JSIConverter<std::optional<margelo::nitro::nitroplayer::AndroidAudioFocusMode>>::toJSI(runtime, arg.androidAudioFocus));
87
92
  return obj;
88
93
  }
89
94
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -101,6 +106,7 @@ namespace margelo::nitro {
101
106
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "remoteSkipBackwardInterval")))) return false;
102
107
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "lookaheadCount")))) return false;
103
108
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "androidNotificationIcon")))) return false;
109
+ if (!JSIConverter<std::optional<margelo::nitro::nitroplayer::AndroidAudioFocusMode>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "androidAudioFocus")))) return false;
104
110
  return true;
105
111
  }
106
112
  };
@@ -0,0 +1,83 @@
1
+ ///
2
+ /// ShufflePlaylistOptions.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/JSIHelpers.hpp>)
21
+ #include <NitroModules/JSIHelpers.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+ #if __has_include(<NitroModules/PropNameIDCache.hpp>)
26
+ #include <NitroModules/PropNameIDCache.hpp>
27
+ #else
28
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
+ #endif
30
+
31
+
32
+
33
+ #include <optional>
34
+
35
+ namespace margelo::nitro::nitroplayer {
36
+
37
+ /**
38
+ * A struct which can be represented as a JavaScript object (ShufflePlaylistOptions).
39
+ */
40
+ struct ShufflePlaylistOptions final {
41
+ public:
42
+ std::optional<bool> keepCurrentTrackFirst SWIFT_PRIVATE;
43
+
44
+ public:
45
+ ShufflePlaylistOptions() = default;
46
+ explicit ShufflePlaylistOptions(std::optional<bool> keepCurrentTrackFirst): keepCurrentTrackFirst(keepCurrentTrackFirst) {}
47
+
48
+ public:
49
+ friend bool operator==(const ShufflePlaylistOptions& lhs, const ShufflePlaylistOptions& rhs) = default;
50
+ };
51
+
52
+ } // namespace margelo::nitro::nitroplayer
53
+
54
+ namespace margelo::nitro {
55
+
56
+ // C++ ShufflePlaylistOptions <> JS ShufflePlaylistOptions (object)
57
+ template <>
58
+ struct JSIConverter<margelo::nitro::nitroplayer::ShufflePlaylistOptions> final {
59
+ static inline margelo::nitro::nitroplayer::ShufflePlaylistOptions fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
60
+ jsi::Object obj = arg.asObject(runtime);
61
+ return margelo::nitro::nitroplayer::ShufflePlaylistOptions(
62
+ JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst")))
63
+ );
64
+ }
65
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::nitroplayer::ShufflePlaylistOptions& arg) {
66
+ jsi::Object obj(runtime);
67
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.keepCurrentTrackFirst));
68
+ return obj;
69
+ }
70
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
71
+ if (!value.isObject()) {
72
+ return false;
73
+ }
74
+ jsi::Object obj = value.getObject(runtime);
75
+ if (!nitro::isPlainObject(runtime, obj)) {
76
+ return false;
77
+ }
78
+ if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "keepCurrentTrackFirst")))) return false;
79
+ return true;
80
+ }
81
+ };
82
+
83
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-player",
3
- "version": "1.7.0-alpha.3",
3
+ "version": "1.7.0-alpha.4",
4
4
  "description": "A powerful audio player library for React Native with playlist management, playback controls, and support for Android Auto and CarPlay",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",
@@ -37,6 +37,7 @@ class CallbackSubscriptionManager {
37
37
  private androidAutoConnectionSubscribers =
38
38
  new Set<AndroidAutoConnectionCallback>()
39
39
  private isPlaylistsChangedRegistered = false
40
+ private playlistsChangedFanOutScheduled = false
40
41
  private isAndroidAutoConnectionRegistered = false
41
42
  private isPlaybackStateRegistered = false
42
43
  private isTrackChangeRegistered = false
@@ -204,21 +205,35 @@ class CallbackSubscriptionManager {
204
205
  }
205
206
  }
206
207
 
208
+ // Task-level, not a microtask: native callbacks arrive as separate JS tasks.
209
+ private schedulePlaylistsChangedFanOut(): void {
210
+ if (this.playlistsChangedFanOutScheduled) return
211
+ this.playlistsChangedFanOutScheduled = true
212
+ setTimeout(() => {
213
+ this.playlistsChangedFanOutScheduled = false
214
+ this.playlistsChangedSubscribers.forEach((subscriber) => {
215
+ try {
216
+ subscriber()
217
+ } catch (error) {
218
+ console.error(
219
+ '[CallbackManager] Error in playlists changed subscriber:',
220
+ error
221
+ )
222
+ }
223
+ })
224
+ }, 0)
225
+ }
226
+
207
227
  private ensurePlaylistsChangedRegistered(): void {
208
228
  if (this.isPlaylistsChangedRegistered) return
209
229
 
210
230
  try {
211
231
  PlayerQueue.onPlaylistsChanged(() => {
212
- this.playlistsChangedSubscribers.forEach((subscriber) => {
213
- try {
214
- subscriber()
215
- } catch (error) {
216
- console.error(
217
- '[CallbackManager] Error in playlists changed subscriber:',
218
- error
219
- )
220
- }
221
- })
232
+ this.schedulePlaylistsChangedFanOut()
233
+ })
234
+ // Track-level mutations only fire the per-playlist event.
235
+ PlayerQueue.onPlaylistChanged(() => {
236
+ this.schedulePlaylistsChangedFanOut()
222
237
  })
223
238
  this.isPlaylistsChangedRegistered = true
224
239
  } catch (error) {