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.
- package/README.md +1 -610
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +37 -29
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +4 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +16 -0
- package/ios/HybridAudioRoutePicker.swift +47 -46
- package/ios/HybridTrackPlayer.swift +4 -0
- package/ios/core/TrackPlayerCore.swift +41 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JRepeatMode.hpp +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/RepeatMode.kt +22 -0
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +11 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +12 -0
- package/nitrogen/generated/ios/swift/RepeatMode.swift +44 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/RepeatMode.hpp +80 -0
- package/package.json +7 -7
- package/src/index.ts +1 -1
- package/src/specs/TrackPlayer.nitro.ts +3 -0
- package/lib/hooks/index.d.ts +0 -6
- package/lib/hooks/index.js +0 -6
- package/lib/hooks/useAndroidAutoConnection.d.ts +0 -13
- package/lib/hooks/useAndroidAutoConnection.js +0 -26
- package/lib/hooks/useAudioDevices.d.ts +0 -26
- package/lib/hooks/useAudioDevices.js +0 -55
- package/lib/hooks/useOnChangeTrack.d.ts +0 -9
- package/lib/hooks/useOnChangeTrack.js +0 -17
- package/lib/hooks/useOnPlaybackProgressChange.d.ts +0 -9
- package/lib/hooks/useOnPlaybackProgressChange.js +0 -19
- package/lib/hooks/useOnPlaybackStateChange.d.ts +0 -9
- package/lib/hooks/useOnPlaybackStateChange.js +0 -17
- package/lib/hooks/useOnSeek.d.ts +0 -8
- package/lib/hooks/useOnSeek.js +0 -17
- package/lib/index.d.ts +0 -14
- package/lib/index.js +0 -24
- package/lib/specs/AndroidAutoMediaLibrary.nitro.d.ts +0 -21
- package/lib/specs/AndroidAutoMediaLibrary.nitro.js +0 -1
- package/lib/specs/AudioDevices.nitro.d.ts +0 -24
- package/lib/specs/AudioDevices.nitro.js +0 -1
- package/lib/specs/AudioRoutePicker.nitro.d.ts +0 -10
- package/lib/specs/AudioRoutePicker.nitro.js +0 -1
- package/lib/specs/TrackPlayer.nitro.d.ts +0 -39
- package/lib/specs/TrackPlayer.nitro.js +0 -1
- package/lib/types/AndroidAutoMediaLibrary.d.ts +0 -44
- package/lib/types/AndroidAutoMediaLibrary.js +0 -1
- package/lib/types/PlayerQueue.d.ts +0 -32
- package/lib/types/PlayerQueue.js +0 -1
- package/lib/utils/androidAutoMediaLibrary.d.ts +0 -47
- 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 =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt
CHANGED
|
@@ -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;
|