react-native-nitro-player 0.0.1 → 0.3.0-alpha.5

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 (53) hide show
  1. package/README.md +1 -610
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +37 -29
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +4 -0
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +16 -0
  5. package/ios/HybridAudioRoutePicker.swift +47 -46
  6. package/ios/HybridTrackPlayer.swift +4 -0
  7. package/ios/core/TrackPlayerCore.swift +41 -0
  8. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -0
  9. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
  10. package/nitrogen/generated/android/c++/JRepeatMode.hpp +62 -0
  11. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +4 -0
  12. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/RepeatMode.kt +22 -0
  13. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +3 -0
  14. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +11 -0
  15. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
  16. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +12 -0
  17. package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
  18. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
  19. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +4 -0
  20. package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
  21. package/package.json +7 -7
  22. package/src/index.ts +1 -1
  23. package/src/specs/TrackPlayer.nitro.ts +3 -0
  24. package/lib/hooks/index.d.ts +0 -6
  25. package/lib/hooks/index.js +0 -6
  26. package/lib/hooks/useAndroidAutoConnection.d.ts +0 -13
  27. package/lib/hooks/useAndroidAutoConnection.js +0 -26
  28. package/lib/hooks/useAudioDevices.d.ts +0 -26
  29. package/lib/hooks/useAudioDevices.js +0 -55
  30. package/lib/hooks/useOnChangeTrack.d.ts +0 -9
  31. package/lib/hooks/useOnChangeTrack.js +0 -17
  32. package/lib/hooks/useOnPlaybackProgressChange.d.ts +0 -9
  33. package/lib/hooks/useOnPlaybackProgressChange.js +0 -19
  34. package/lib/hooks/useOnPlaybackStateChange.d.ts +0 -9
  35. package/lib/hooks/useOnPlaybackStateChange.js +0 -17
  36. package/lib/hooks/useOnSeek.d.ts +0 -8
  37. package/lib/hooks/useOnSeek.js +0 -17
  38. package/lib/index.d.ts +0 -14
  39. package/lib/index.js +0 -24
  40. package/lib/specs/AndroidAutoMediaLibrary.nitro.d.ts +0 -21
  41. package/lib/specs/AndroidAutoMediaLibrary.nitro.js +0 -1
  42. package/lib/specs/AudioDevices.nitro.d.ts +0 -24
  43. package/lib/specs/AudioDevices.nitro.js +0 -1
  44. package/lib/specs/AudioRoutePicker.nitro.d.ts +0 -10
  45. package/lib/specs/AudioRoutePicker.nitro.js +0 -1
  46. package/lib/specs/TrackPlayer.nitro.d.ts +0 -39
  47. package/lib/specs/TrackPlayer.nitro.js +0 -1
  48. package/lib/types/AndroidAutoMediaLibrary.d.ts +0 -44
  49. package/lib/types/AndroidAutoMediaLibrary.js +0 -1
  50. package/lib/types/PlayerQueue.d.ts +0 -32
  51. package/lib/types/PlayerQueue.js +0 -1
  52. package/lib/utils/androidAutoMediaLibrary.d.ts +0 -47
  53. package/lib/utils/androidAutoMediaLibrary.js +0 -62
@@ -7,21 +7,21 @@ import android.os.Build
7
7
  import com.margelo.nitro.NitroModules
8
8
 
9
9
  class HybridAudioDevices : HybridAudioDevicesSpec() {
10
-
11
- val applicationContext = NitroModules.applicationContext;
10
+ val applicationContext = NitroModules.applicationContext
12
11
  private val audioManager = applicationContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
13
-
12
+
14
13
  // Device types that can be set as communication devices
15
14
  private val validCommunicationDeviceTypes: Set<Int> by lazy {
16
- val types = mutableSetOf(
17
- AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
18
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
19
- AudioDeviceInfo.TYPE_WIRED_HEADSET,
20
- AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
21
- AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
22
- AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
23
- AudioDeviceInfo.TYPE_USB_HEADSET
24
- )
15
+ val types =
16
+ mutableSetOf(
17
+ AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
18
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
19
+ AudioDeviceInfo.TYPE_WIRED_HEADSET,
20
+ AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
21
+ AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
22
+ AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
23
+ AudioDeviceInfo.TYPE_USB_HEADSET,
24
+ )
25
25
  // BLE types are only available on Android S (API 31) and above
26
26
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
27
27
  types.add(AudioDeviceInfo.TYPE_BLE_HEADSET)
@@ -29,7 +29,7 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
29
29
  }
30
30
  types
31
31
  }
32
-
32
+
33
33
  override fun getAudioDevices(): Array<TAudioDevice> {
34
34
  val devices = audioManager.getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
35
35
  var activeDevice: AudioDeviceInfo? = null
@@ -37,20 +37,23 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
37
37
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
38
38
  activeDevice = audioManager.communicationDevice
39
39
  }
40
-
40
+
41
41
  // Filter to only include valid communication devices
42
- return devices.filter { device ->
43
- validCommunicationDeviceTypes.contains(device.type)
44
- }.map { device -> TAudioDevice(
45
- id = device.id.toDouble(),
46
- name = device.productName?.toString() ?: getDeviceTypeName(device.type),
47
- type = device.type.toDouble(),
48
- isActive = device == activeDevice
49
- ) }.toTypedArray()
42
+ return devices
43
+ .filter { device ->
44
+ validCommunicationDeviceTypes.contains(device.type)
45
+ }.map { device ->
46
+ TAudioDevice(
47
+ id = device.id.toDouble(),
48
+ name = device.productName?.toString() ?: getDeviceTypeName(device.type),
49
+ type = device.type.toDouble(),
50
+ isActive = device == activeDevice,
51
+ )
52
+ }.toTypedArray()
50
53
  }
51
-
52
- private fun getDeviceTypeName(type: Int): String {
53
- return when (type) {
54
+
55
+ private fun getDeviceTypeName(type: Int): String =
56
+ when (type) {
54
57
  AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> "Built-in Earpiece"
55
58
  AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> "Built-in Speaker"
56
59
  AudioDeviceInfo.TYPE_WIRED_HEADSET -> "Wired Headset"
@@ -62,11 +65,11 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
62
65
  27 -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) "BLE Speaker" else "Type 27"
63
66
  else -> "Type $type"
64
67
  }
65
- }
66
68
 
67
69
  override fun setAudioDevice(deviceId: Double): Boolean {
68
70
  val device =
69
- audioManager.getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
71
+ audioManager
72
+ .getDevices(android.media.AudioManager.GET_DEVICES_OUTPUTS)
70
73
  .firstOrNull { it.id == deviceId.toInt() }
71
74
  ?: return false
72
75
 
@@ -83,21 +86,26 @@ class HybridAudioDevices : HybridAudioDevicesSpec() {
83
86
  // Pre-Android 12 fallback (best-effort)
84
87
  when (device.type) {
85
88
  android.media.AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
86
- android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP -> {
89
+ android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
90
+ -> {
87
91
  audioManager.startBluetoothSco()
88
92
  audioManager.isBluetoothScoOn = true
89
93
  true
90
94
  }
95
+
91
96
  android.media.AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> {
92
97
  audioManager.isSpeakerphoneOn = true
93
98
  true
94
99
  }
100
+
95
101
  android.media.AudioDeviceInfo.TYPE_WIRED_HEADSET,
96
- android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES -> {
102
+ android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
103
+ -> {
97
104
  audioManager.isSpeakerphoneOn = false
98
105
  audioManager.isBluetoothScoOn = false
99
106
  true
100
107
  }
108
+
101
109
  else -> {
102
110
  android.util.Log.w(TAG, "Unsupported device type for pre-Android 12: ${device.type}")
103
111
  false
@@ -57,6 +57,10 @@ class HybridTrackPlayer : HybridTrackPlayerSpec() {
57
57
  @Keep
58
58
  override fun getState(): PlayerState = core.getState()
59
59
 
60
+ @DoNotStrip
61
+ @Keep
62
+ override fun setRepeatMode(mode: RepeatMode): Boolean = core.setRepeatMode(mode)
63
+
60
64
  override fun onChangeTrack(callback: (track: TrackItem, reason: Reason?) -> Unit) {
61
65
  core.onChangeTrack = callback
62
66
  }
@@ -13,6 +13,7 @@ import com.margelo.nitro.core.NullType
13
13
  import com.margelo.nitro.nitroplayer.NitroPlayerPackage
14
14
  import com.margelo.nitro.nitroplayer.PlayerState
15
15
  import com.margelo.nitro.nitroplayer.Reason
16
+ import com.margelo.nitro.nitroplayer.RepeatMode
16
17
  import com.margelo.nitro.nitroplayer.TrackItem
17
18
  import com.margelo.nitro.nitroplayer.TrackPlayerState
18
19
  import com.margelo.nitro.nitroplayer.Variant_NullType_String
@@ -476,6 +477,21 @@ class TrackPlayerCore private constructor(
476
477
  }
477
478
  }
478
479
 
480
+ fun setRepeatMode(mode: RepeatMode): Boolean {
481
+ println("🔁 TrackPlayerCore: setRepeatMode called with mode: $mode")
482
+ handler.post {
483
+ val exoRepeatMode =
484
+ when (mode) {
485
+ RepeatMode.OFF -> Player.REPEAT_MODE_OFF
486
+ RepeatMode.TRACK -> Player.REPEAT_MODE_ONE
487
+ RepeatMode.PLAYLIST -> Player.REPEAT_MODE_ALL
488
+ }
489
+ player.repeatMode = exoRepeatMode
490
+ println("🔁 TrackPlayerCore: ExoPlayer repeat mode set to: $exoRepeatMode")
491
+ }
492
+ return true
493
+ }
494
+
479
495
  fun getState(): PlayerState {
480
496
  // Check if we're already on the main thread
481
497
  if (android.os.Looper.myLooper() == handler.looper) {
@@ -1,53 +1,54 @@
1
- import Foundation
2
- import UIKit
3
1
  import AVKit
2
+ import Foundation
4
3
  import NitroModules
4
+ import UIKit
5
5
 
6
6
  class HybridAudioRoutePicker: HybridAudioRoutePickerSpec {
7
-
8
- // Approximate memory footprint of this instance's reference
9
- private func getSizeOf(_ object: AnyObject) -> Int {
10
- // For class instances, MemoryLayout reports the size of the reference (pointer)
11
- return MemoryLayout.size(ofValue: object)
12
- }
13
-
14
- var memorySize: Int {
15
- return getSizeOf(self)
16
- }
17
-
18
- func showRoutePicker() throws -> Void {
19
- DispatchQueue.main.async {
20
- // Create AVRoutePickerView
21
- let routePickerView = AVRoutePickerView()
22
- routePickerView.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
23
- routePickerView.tintColor = .systemBlue
24
- routePickerView.activeTintColor = .systemBlue
25
-
26
- // Get the key window
27
- guard let window = UIApplication.shared.connectedScenes
28
- .compactMap({ $0 as? UIWindowScene })
29
- .flatMap({ $0.windows })
30
- .first(where: { $0.isKeyWindow }) else {
31
- print("HybridAudioRoutePicker: Could not find key window")
32
- return
33
- }
34
-
35
- // Add the route picker to the window temporarily
36
- window.addSubview(routePickerView)
37
-
38
- // Trigger the route picker button programmatically
39
- for view in routePickerView.subviews {
40
- if let button = view as? UIButton {
41
- button.sendActions(for: .touchUpInside)
42
- break
43
- }
44
- }
45
-
46
- // Remove the view after a short delay
47
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
48
- routePickerView.removeFromSuperview()
49
- }
7
+
8
+ // Approximate memory footprint of this instance's reference
9
+ private func getSizeOf(_ object: AnyObject) -> Int {
10
+ // For class instances, MemoryLayout reports the size of the reference (pointer)
11
+ return MemoryLayout.size(ofValue: object)
12
+ }
13
+
14
+ var memorySize: Int {
15
+ return getSizeOf(self)
16
+ }
17
+
18
+ func showRoutePicker() throws {
19
+ DispatchQueue.main.async {
20
+ // Create AVRoutePickerView
21
+ let routePickerView = AVRoutePickerView()
22
+ routePickerView.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
23
+ routePickerView.tintColor = .systemBlue
24
+ routePickerView.activeTintColor = .systemBlue
25
+
26
+ // Get the key window
27
+ guard
28
+ let window = UIApplication.shared.connectedScenes
29
+ .compactMap({ $0 as? UIWindowScene })
30
+ .flatMap({ $0.windows })
31
+ .first(where: { $0.isKeyWindow })
32
+ else {
33
+ print("HybridAudioRoutePicker: Could not find key window")
34
+ return
35
+ }
36
+
37
+ // Add the route picker to the window temporarily
38
+ window.addSubview(routePickerView)
39
+
40
+ // Trigger the route picker button programmatically
41
+ for view in routePickerView.subviews {
42
+ if let button = view as? UIButton {
43
+ button.sendActions(for: .touchUpInside)
44
+ break
50
45
  }
46
+ }
47
+
48
+ // Remove the view after a short delay
49
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
50
+ routePickerView.removeFromSuperview()
51
+ }
51
52
  }
53
+ }
52
54
  }
53
-
@@ -52,6 +52,10 @@ final class HybridTrackPlayer: HybridTrackPlayerSpec {
52
52
  return core.getState()
53
53
  }
54
54
 
55
+ func setRepeatMode(mode: RepeatMode) throws -> Bool {
56
+ return core.setRepeatMode(mode: mode)
57
+ }
58
+
55
59
  // MARK: - Configuration
56
60
 
57
61
  func configure(config: PlayerConfig) throws {
@@ -42,6 +42,7 @@ class TrackPlayerCore: NSObject {
42
42
  private var currentTrackIndex: Int = -1
43
43
  private var currentTracks: [TrackItem] = []
44
44
  private var isManuallySeeked = false
45
+ private var repeatMode: RepeatMode = .off
45
46
  private var boundaryTimeObserver: Any?
46
47
  private var currentItemObservers: [NSKeyValueObservation] = []
47
48
 
@@ -232,6 +233,38 @@ class TrackPlayerCore: NSObject {
232
233
  print("📋 Remaining items in queue: \(player.items().count)")
233
234
  }
234
235
 
236
+ // Handle repeat modes
237
+ switch repeatMode {
238
+ case .track:
239
+ // Repeat current track - seek to beginning and play
240
+ print("🔁 TrackPlayerCore: Repeat mode is TRACK - replaying current track")
241
+ DispatchQueue.main.async { [weak self] in
242
+ guard let self = self, let player = self.player else { return }
243
+ // Recreate the current track item and play it
244
+ self.playFromIndex(index: self.currentTrackIndex)
245
+ }
246
+ return
247
+
248
+ case .playlist:
249
+ // Check if we're at the end of the playlist
250
+ if currentTrackIndex >= currentTracks.count - 1 {
251
+ print("🔁 TrackPlayerCore: Repeat mode is PLAYLIST - restarting from beginning")
252
+ DispatchQueue.main.async { [weak self] in
253
+ guard let self = self else { return }
254
+ // Go back to the first track
255
+ self.playFromIndex(index: 0)
256
+ }
257
+ return
258
+ } else {
259
+ // Not at end, just continue to next track
260
+ print("🔁 TrackPlayerCore: Repeat mode is PLAYLIST - continuing to next track")
261
+ }
262
+
263
+ case .off:
264
+ // Default behavior - stop at end of playlist
265
+ print("🔁 TrackPlayerCore: Repeat mode is OFF")
266
+ }
267
+
235
268
  // Track ended naturally
236
269
  onChangeTrack?(
237
270
  getCurrentTrack()
@@ -867,6 +900,14 @@ class TrackPlayerCore: NSObject {
867
900
  }
868
901
  }
869
902
 
903
+ // MARK: - Repeat Mode
904
+
905
+ func setRepeatMode(mode: RepeatMode) -> Bool {
906
+ print("🔁 TrackPlayerCore: setRepeatMode called with mode: \(mode)")
907
+ self.repeatMode = mode
908
+ return true
909
+ }
910
+
870
911
  // MARK: - State Management
871
912
 
872
913
  func getState() -> PlayerState {
@@ -13,6 +13,8 @@ namespace margelo::nitro::nitroplayer { struct PlayerState; }
13
13
  namespace margelo::nitro::nitroplayer { struct TrackItem; }
14
14
  // Forward declaration of `TrackPlayerState` to properly resolve imports.
15
15
  namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
16
+ // Forward declaration of `RepeatMode` to properly resolve imports.
17
+ namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
16
18
  // Forward declaration of `PlayerConfig` to properly resolve imports.
17
19
  namespace margelo::nitro::nitroplayer { struct PlayerConfig; }
18
20
  // Forward declaration of `Reason` to properly resolve imports.
@@ -31,6 +33,8 @@ namespace margelo::nitro::nitroplayer { enum class Reason; }
31
33
  #include "JVariant_NullType_String.hpp"
32
34
  #include "TrackPlayerState.hpp"
33
35
  #include "JTrackPlayerState.hpp"
36
+ #include "RepeatMode.hpp"
37
+ #include "JRepeatMode.hpp"
34
38
  #include "PlayerConfig.hpp"
35
39
  #include "JPlayerConfig.hpp"
36
40
  #include "Reason.hpp"
@@ -104,6 +108,11 @@ namespace margelo::nitro::nitroplayer {
104
108
  auto __result = method(_javaPart);
105
109
  return __result->toCpp();
106
110
  }
111
+ bool JHybridTrackPlayerSpec::setRepeatMode(RepeatMode mode) {
112
+ static const auto method = javaClassStatic()->getMethod<jboolean(jni::alias_ref<JRepeatMode> /* mode */)>("setRepeatMode");
113
+ auto __result = method(_javaPart, JRepeatMode::fromCpp(mode));
114
+ return static_cast<bool>(__result);
115
+ }
107
116
  void JHybridTrackPlayerSpec::configure(const PlayerConfig& config) {
108
117
  static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JPlayerConfig> /* config */)>("configure");
109
118
  method(_javaPart, JPlayerConfig::fromCpp(config));
@@ -61,6 +61,7 @@ namespace margelo::nitro::nitroplayer {
61
61
  void skipToPrevious() override;
62
62
  void seek(double position) override;
63
63
  PlayerState getState() override;
64
+ bool setRepeatMode(RepeatMode mode) override;
64
65
  void configure(const PlayerConfig& config) override;
65
66
  void onChangeTrack(const std::function<void(const TrackItem& /* track */, std::optional<Reason> /* reason */)>& callback) override;
66
67
  void onPlaybackStateChange(const std::function<void(TrackPlayerState /* state */, std::optional<Reason> /* reason */)>& callback) override;
@@ -0,0 +1,62 @@
1
+ ///
2
+ /// JRepeatMode.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include "RepeatMode.hpp"
12
+
13
+ namespace margelo::nitro::nitroplayer {
14
+
15
+ using namespace facebook;
16
+
17
+ /**
18
+ * The C++ JNI bridge between the C++ enum "RepeatMode" and the the Kotlin enum "RepeatMode".
19
+ */
20
+ struct JRepeatMode final: public jni::JavaClass<JRepeatMode> {
21
+ public:
22
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/nitroplayer/RepeatMode;";
23
+
24
+ public:
25
+ /**
26
+ * Convert this Java/Kotlin-based enum to the C++ enum RepeatMode.
27
+ */
28
+ [[maybe_unused]]
29
+ [[nodiscard]]
30
+ RepeatMode toCpp() const {
31
+ static const auto clazz = javaClassStatic();
32
+ static const auto fieldOrdinal = clazz->getField<int>("value");
33
+ int ordinal = this->getFieldValue(fieldOrdinal);
34
+ return static_cast<RepeatMode>(ordinal);
35
+ }
36
+
37
+ public:
38
+ /**
39
+ * Create a Java/Kotlin-based enum with the given C++ enum's value.
40
+ */
41
+ [[maybe_unused]]
42
+ static jni::alias_ref<JRepeatMode> fromCpp(RepeatMode value) {
43
+ static const auto clazz = javaClassStatic();
44
+ static const auto fieldOFF = clazz->getStaticField<JRepeatMode>("OFF");
45
+ static const auto fieldPLAYLIST = clazz->getStaticField<JRepeatMode>("PLAYLIST");
46
+ static const auto fieldTRACK = clazz->getStaticField<JRepeatMode>("TRACK");
47
+
48
+ switch (value) {
49
+ case RepeatMode::OFF:
50
+ return clazz->getStaticFieldValue(fieldOFF);
51
+ case RepeatMode::PLAYLIST:
52
+ return clazz->getStaticFieldValue(fieldPLAYLIST);
53
+ case RepeatMode::TRACK:
54
+ return clazz->getStaticFieldValue(fieldTRACK);
55
+ default:
56
+ std::string stringValue = std::to_string(static_cast<int>(value));
57
+ throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
58
+ }
59
+ }
60
+ };
61
+
62
+ } // namespace margelo::nitro::nitroplayer
@@ -73,6 +73,10 @@ abstract class HybridTrackPlayerSpec: HybridObject() {
73
73
  @Keep
74
74
  abstract fun getState(): PlayerState
75
75
 
76
+ @DoNotStrip
77
+ @Keep
78
+ abstract fun setRepeatMode(mode: RepeatMode): Boolean
79
+
76
80
  @DoNotStrip
77
81
  @Keep
78
82
  abstract fun configure(config: PlayerConfig): Unit
@@ -0,0 +1,22 @@
1
+ ///
2
+ /// RepeatMode.kt
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ package com.margelo.nitro.nitroplayer
9
+
10
+ import androidx.annotation.Keep
11
+ import com.facebook.proguard.annotations.DoNotStrip
12
+
13
+ /**
14
+ * Represents the JavaScript enum/union "RepeatMode".
15
+ */
16
+ @DoNotStrip
17
+ @Keep
18
+ enum class RepeatMode(@DoNotStrip @Keep val value: Int) {
19
+ OFF(0),
20
+ PLAYLIST(1),
21
+ TRACK(2);
22
+ }
@@ -24,6 +24,8 @@ namespace margelo::nitro::nitroplayer { struct Playlist; }
24
24
  namespace margelo::nitro::nitroplayer { enum class QueueOperation; }
25
25
  // Forward declaration of `Reason` to properly resolve imports.
26
26
  namespace margelo::nitro::nitroplayer { enum class Reason; }
27
+ // Forward declaration of `RepeatMode` to properly resolve imports.
28
+ namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
27
29
  // Forward declaration of `TrackItem` to properly resolve imports.
28
30
  namespace margelo::nitro::nitroplayer { struct TrackItem; }
29
31
  // Forward declaration of `TrackPlayerState` to properly resolve imports.
@@ -38,6 +40,7 @@ namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
38
40
  #include "Playlist.hpp"
39
41
  #include "QueueOperation.hpp"
40
42
  #include "Reason.hpp"
43
+ #include "RepeatMode.hpp"
41
44
  #include "TrackItem.hpp"
42
45
  #include "TrackPlayerState.hpp"
43
46
  #include <NitroModules/Null.hpp>
@@ -18,6 +18,8 @@ namespace margelo::nitro::nitroplayer { struct PlayerState; }
18
18
  namespace margelo::nitro::nitroplayer { struct TrackItem; }
19
19
  // Forward declaration of `TrackPlayerState` to properly resolve imports.
20
20
  namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
21
+ // Forward declaration of `RepeatMode` to properly resolve imports.
22
+ namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
21
23
  // Forward declaration of `PlayerConfig` to properly resolve imports.
22
24
  namespace margelo::nitro::nitroplayer { struct PlayerConfig; }
23
25
  // Forward declaration of `Reason` to properly resolve imports.
@@ -30,6 +32,7 @@ namespace margelo::nitro::nitroplayer { enum class Reason; }
30
32
  #include "TrackItem.hpp"
31
33
  #include <variant>
32
34
  #include "TrackPlayerState.hpp"
35
+ #include "RepeatMode.hpp"
33
36
  #include "PlayerConfig.hpp"
34
37
  #include "Reason.hpp"
35
38
  #include <functional>
@@ -122,6 +125,14 @@ namespace margelo::nitro::nitroplayer {
122
125
  auto __value = std::move(__result.value());
123
126
  return __value;
124
127
  }
128
+ inline bool setRepeatMode(RepeatMode mode) override {
129
+ auto __result = _swiftPart.setRepeatMode(static_cast<int>(mode));
130
+ if (__result.hasError()) [[unlikely]] {
131
+ std::rethrow_exception(__result.error());
132
+ }
133
+ auto __value = std::move(__result.value());
134
+ return __value;
135
+ }
125
136
  inline void configure(const PlayerConfig& config) override {
126
137
  auto __result = _swiftPart.configure(std::forward<decltype(config)>(config));
127
138
  if (__result.hasError()) [[unlikely]] {
@@ -21,6 +21,7 @@ public protocol HybridTrackPlayerSpec_protocol: HybridObject {
21
21
  func skipToPrevious() throws -> Void
22
22
  func seek(position: Double) throws -> Void
23
23
  func getState() throws -> PlayerState
24
+ func setRepeatMode(mode: RepeatMode) throws -> Bool
24
25
  func configure(config: PlayerConfig) throws -> Void
25
26
  func onChangeTrack(callback: @escaping (_ track: TrackItem, _ reason: Reason?) -> Void) throws -> Void
26
27
  func onPlaybackStateChange(callback: @escaping (_ state: TrackPlayerState, _ reason: Reason?) -> Void) throws -> Void
@@ -202,6 +202,18 @@ open class HybridTrackPlayerSpec_cxx {
202
202
  }
203
203
  }
204
204
 
205
+ @inline(__always)
206
+ public final func setRepeatMode(mode: Int32) -> bridge.Result_bool_ {
207
+ do {
208
+ let __result = try self.__implementation.setRepeatMode(mode: margelo.nitro.nitroplayer.RepeatMode(rawValue: mode)!)
209
+ let __resultCpp = __result
210
+ return bridge.create_Result_bool_(__resultCpp)
211
+ } catch (let __error) {
212
+ let __exceptionPtr = __error.toCpp()
213
+ return bridge.create_Result_bool_(__exceptionPtr)
214
+ }
215
+ }
216
+
205
217
  @inline(__always)
206
218
  public final func configure(config: PlayerConfig) -> bridge.Result_void_ {
207
219
  do {
@@ -0,0 +1,44 @@
1
+ ///
2
+ /// RepeatMode.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ /**
9
+ * Represents the JS union `RepeatMode`, backed by a C++ enum.
10
+ */
11
+ public typealias RepeatMode = margelo.nitro.nitroplayer.RepeatMode
12
+
13
+ public extension RepeatMode {
14
+ /**
15
+ * Get a RepeatMode 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 "off":
21
+ self = .off
22
+ case "Playlist":
23
+ self = .playlist
24
+ case "track":
25
+ self = .track
26
+ default:
27
+ return nil
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Get the String value this RepeatMode represents.
33
+ */
34
+ var stringValue: String {
35
+ switch self {
36
+ case .off:
37
+ return "off"
38
+ case .playlist:
39
+ return "Playlist"
40
+ case .track:
41
+ return "track"
42
+ }
43
+ }
44
+ }
@@ -21,6 +21,7 @@ namespace margelo::nitro::nitroplayer {
21
21
  prototype.registerHybridMethod("skipToPrevious", &HybridTrackPlayerSpec::skipToPrevious);
22
22
  prototype.registerHybridMethod("seek", &HybridTrackPlayerSpec::seek);
23
23
  prototype.registerHybridMethod("getState", &HybridTrackPlayerSpec::getState);
24
+ prototype.registerHybridMethod("setRepeatMode", &HybridTrackPlayerSpec::setRepeatMode);
24
25
  prototype.registerHybridMethod("configure", &HybridTrackPlayerSpec::configure);
25
26
  prototype.registerHybridMethod("onChangeTrack", &HybridTrackPlayerSpec::onChangeTrack);
26
27
  prototype.registerHybridMethod("onPlaybackStateChange", &HybridTrackPlayerSpec::onPlaybackStateChange);
@@ -15,6 +15,8 @@
15
15
 
16
16
  // Forward declaration of `PlayerState` to properly resolve imports.
17
17
  namespace margelo::nitro::nitroplayer { struct PlayerState; }
18
+ // Forward declaration of `RepeatMode` to properly resolve imports.
19
+ namespace margelo::nitro::nitroplayer { enum class RepeatMode; }
18
20
  // Forward declaration of `PlayerConfig` to properly resolve imports.
19
21
  namespace margelo::nitro::nitroplayer { struct PlayerConfig; }
20
22
  // Forward declaration of `TrackItem` to properly resolve imports.
@@ -27,6 +29,7 @@ namespace margelo::nitro::nitroplayer { enum class TrackPlayerState; }
27
29
  #include <string>
28
30
  #include <optional>
29
31
  #include "PlayerState.hpp"
32
+ #include "RepeatMode.hpp"
30
33
  #include "PlayerConfig.hpp"
31
34
  #include "TrackItem.hpp"
32
35
  #include "Reason.hpp"
@@ -71,6 +74,7 @@ namespace margelo::nitro::nitroplayer {
71
74
  virtual void skipToPrevious() = 0;
72
75
  virtual void seek(double position) = 0;
73
76
  virtual PlayerState getState() = 0;
77
+ virtual bool setRepeatMode(RepeatMode mode) = 0;
74
78
  virtual void configure(const PlayerConfig& config) = 0;
75
79
  virtual void onChangeTrack(const std::function<void(const TrackItem& /* track */, std::optional<Reason> /* reason */)>& callback) = 0;
76
80
  virtual void onPlaybackStateChange(const std::function<void(TrackPlayerState /* state */, std::optional<Reason> /* reason */)>& callback) = 0;