@iternio/react-native-auto-play 0.4.5 → 0.4.6
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/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlay.kt +89 -0
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VirtualRenderer.kt +12 -4
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputManager.kt +20 -276
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/ThreadUtil.kt +13 -6
- package/ios/hybrid/HybridAutoPlay.swift +47 -2
- package/ios/utils/VoiceInputManager.swift +40 -141
- package/lib/index.d.ts +1 -3
- package/lib/index.js +1 -2
- package/lib/specs/AutoPlay.nitro.d.ts +29 -0
- package/nitro.json +0 -10
- package/nitrogen/generated/android/ReactNativeAutoPlay+autolinking.cmake +0 -2
- package/nitrogen/generated/android/ReactNativeAutoPlayOnLoad.cpp +0 -18
- package/nitrogen/generated/android/c++/JHybridAutoPlaySpec.cpp +43 -0
- package/nitrogen/generated/android/c++/JHybridAutoPlaySpec.hpp +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlaySpec.kt +17 -0
- package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Bridge.cpp +16 -41
- package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Bridge.hpp +126 -201
- package/nitrogen/generated/ios/ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp +0 -11
- package/nitrogen/generated/ios/ReactNativeAutoPlayAutolinking.mm +0 -8
- package/nitrogen/generated/ios/ReactNativeAutoPlayAutolinking.swift +0 -12
- package/nitrogen/generated/ios/c++/HybridAutoPlaySpecSwift.hpp +34 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
- package/nitrogen/generated/ios/swift/{Func_void_VoiceInputResult.swift → Func_void_std__shared_ptr_ArrayBuffer_.swift} +10 -10
- package/nitrogen/generated/ios/swift/HybridAutoPlaySpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridAutoPlaySpec_cxx.swift +82 -0
- package/nitrogen/generated/shared/c++/HybridAutoPlaySpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridAutoPlaySpec.hpp +5 -0
- package/package.json +1 -1
- package/src/index.ts +1 -3
- package/src/specs/AutoPlay.nitro.ts +37 -0
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridVoice.kt +0 -95
- package/ios/hybrid/HybridVoice.swift +0 -63
- package/lib/HybridAutoPlay.d.ts +0 -2
- package/lib/HybridAutoPlay.js +0 -2
- package/lib/hooks/useIsAutoPlayFocused.d.ts +0 -7
- package/lib/hooks/useIsAutoPlayFocused.js +0 -20
- package/lib/hybrid/HybridVoice.d.ts +0 -12
- package/lib/hybrid/HybridVoice.js +0 -13
- package/lib/hybrid.d.ts +0 -2
- package/lib/hybrid.js +0 -2
- package/lib/specs/AutomotivePermissionRequestTemplate.d.ts +0 -11
- package/lib/specs/AutomotivePermissionRequestTemplate.js +0 -1
- package/lib/specs/AutomotivePermissionRequestTemplate.nitro.d.ts +0 -11
- package/lib/specs/AutomotivePermissionRequestTemplate.nitro.js +0 -1
- package/lib/specs/Voice.nitro.d.ts +0 -51
- package/lib/specs/Voice.nitro.js +0 -1
- package/lib/templates/AutomotivePermissionRequestTemplate.d.ts +0 -23
- package/lib/templates/AutomotivePermissionRequestTemplate.js +0 -18
- package/lib/types/Glyphmap.d.ts +0 -4105
- package/lib/types/Glyphmap.js +0 -4105
- package/lib/types/Voice.d.ts +0 -15
- package/lib/types/Voice.js +0 -1
- package/nitrogen/generated/android/c++/JFunc_void_VoiceInputChunk.hpp +0 -81
- package/nitrogen/generated/android/c++/JHybridVoiceSpec.cpp +0 -104
- package/nitrogen/generated/android/c++/JHybridVoiceSpec.hpp +0 -66
- package/nitrogen/generated/android/c++/JVoiceInputChunk.hpp +0 -64
- package/nitrogen/generated/android/c++/JVoiceInputResult.hpp +0 -64
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/Func_void_VoiceInputChunk.kt +0 -80
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/HybridVoiceSpec.kt +0 -72
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputChunk.kt +0 -41
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/VoiceInputResult.kt +0 -41
- package/nitrogen/generated/ios/c++/HybridVoiceSpecSwift.cpp +0 -11
- package/nitrogen/generated/ios/c++/HybridVoiceSpecSwift.hpp +0 -116
- package/nitrogen/generated/ios/swift/Func_void_VoiceInputChunk.swift +0 -46
- package/nitrogen/generated/ios/swift/HybridVoiceSpec.swift +0 -58
- package/nitrogen/generated/ios/swift/HybridVoiceSpec_cxx.swift +0 -227
- package/nitrogen/generated/ios/swift/VoiceInputChunk.swift +0 -60
- package/nitrogen/generated/ios/swift/VoiceInputResult.swift +0 -60
- package/nitrogen/generated/shared/c++/HybridVoiceSpec.cpp +0 -24
- package/nitrogen/generated/shared/c++/HybridVoiceSpec.hpp +0 -73
- package/nitrogen/generated/shared/c++/VoiceInputChunk.hpp +0 -89
- package/nitrogen/generated/shared/c++/VoiceInputResult.hpp +0 -89
- package/src/hybrid/HybridVoice.ts +0 -30
- package/src/specs/Voice.nitro.ts +0 -58
- package/src/types/Voice.ts +0 -17
|
@@ -1,47 +1,16 @@
|
|
|
1
1
|
import AVFoundation
|
|
2
2
|
import CarPlay
|
|
3
|
-
import NitroModules
|
|
4
|
-
import Speech
|
|
5
3
|
|
|
6
|
-
///
|
|
7
|
-
///
|
|
8
|
-
private final class ResultBox: @unchecked Sendable {
|
|
9
|
-
private var continuation: CheckedContinuation<VoiceInputResult, Error>?
|
|
10
|
-
private let lock = NSLock()
|
|
11
|
-
|
|
12
|
-
init(_ continuation: CheckedContinuation<VoiceInputResult, Error>) {
|
|
13
|
-
self.continuation = continuation
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
func resume(returning result: VoiceInputResult) {
|
|
17
|
-
lock.lock()
|
|
18
|
-
defer { lock.unlock() }
|
|
19
|
-
continuation?.resume(returning: result)
|
|
20
|
-
continuation = nil
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
func resume(throwing error: Error) {
|
|
24
|
-
lock.lock()
|
|
25
|
-
defer { lock.unlock() }
|
|
26
|
-
continuation?.resume(throwing: error)
|
|
27
|
-
continuation = nil
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/// Captures audio from the car microphone and buffers raw 16 kHz / 16-bit / mono PCM,
|
|
32
|
-
/// or transcribes it via SFSpeechRecognizer when preferSpeechToText is true.
|
|
4
|
+
/// Captures audio from the car microphone and buffers raw 16 kHz / 16-bit / mono PCM.
|
|
5
|
+
/// Recording stops automatically when silence is detected or the max duration is reached.
|
|
33
6
|
class VoiceInputManager {
|
|
34
7
|
private var audioEngine: AVAudioEngine?
|
|
35
8
|
private var voiceControlTemplate: CPVoiceControlTemplate?
|
|
36
|
-
private var
|
|
9
|
+
private var continuation: CheckedContinuation<[Int16], Error>?
|
|
37
10
|
private var samples: [Int16] = []
|
|
38
11
|
private var isStopping = false
|
|
39
12
|
private let stopLock = NSLock()
|
|
40
13
|
|
|
41
|
-
// STT
|
|
42
|
-
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
|
|
43
|
-
private var isSTTMode = false
|
|
44
|
-
|
|
45
14
|
// Timing
|
|
46
15
|
private var recordingStart: Date?
|
|
47
16
|
private var silenceStart: Date?
|
|
@@ -64,33 +33,30 @@ class VoiceInputManager {
|
|
|
64
33
|
interfaceController: AutoPlayInterfaceController?,
|
|
65
34
|
silenceThresholdMs: Double,
|
|
66
35
|
maxDurationMs: Double,
|
|
67
|
-
listeningText: String
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
let box = ResultBox(cont)
|
|
73
|
-
self.resultBox = box
|
|
36
|
+
listeningText: String
|
|
37
|
+
) async throws -> Data {
|
|
38
|
+
let samples = try await withCheckedThrowingContinuation {
|
|
39
|
+
(cont: CheckedContinuation<[Int16], Error>) in
|
|
40
|
+
self.continuation = cont
|
|
74
41
|
self.samples = []
|
|
75
42
|
self.isStopping = false
|
|
76
|
-
self.isSTTMode = preferSpeechToText
|
|
77
43
|
|
|
78
44
|
do {
|
|
79
45
|
try self.startCapture(
|
|
80
46
|
interfaceController: interfaceController,
|
|
81
47
|
silenceThresholdMs: silenceThresholdMs,
|
|
82
48
|
maxDurationMs: maxDurationMs,
|
|
83
|
-
listeningText: listeningText
|
|
84
|
-
preferSpeechToText: preferSpeechToText,
|
|
85
|
-
onChunk: onChunk,
|
|
86
|
-
box: box
|
|
49
|
+
listeningText: listeningText
|
|
87
50
|
)
|
|
88
51
|
}
|
|
89
52
|
catch {
|
|
90
|
-
self.
|
|
91
|
-
|
|
53
|
+
self.stopCapture(interfaceController: interfaceController)
|
|
54
|
+
self.continuation = nil
|
|
55
|
+
cont.resume(throwing: error)
|
|
92
56
|
}
|
|
93
57
|
}
|
|
58
|
+
|
|
59
|
+
return samplesAsData(samples)
|
|
94
60
|
}
|
|
95
61
|
|
|
96
62
|
func stop(interfaceController: AutoPlayInterfaceController? = nil) {
|
|
@@ -100,22 +66,14 @@ class VoiceInputManager {
|
|
|
100
66
|
return
|
|
101
67
|
}
|
|
102
68
|
isStopping = true
|
|
103
|
-
let
|
|
104
|
-
let box = resultBox
|
|
69
|
+
let capturedContinuation = continuation
|
|
105
70
|
let capturedSamples = samples
|
|
106
|
-
|
|
71
|
+
continuation = nil
|
|
107
72
|
samples = []
|
|
108
73
|
stopLock.unlock()
|
|
109
74
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// which resumes the box. Engine teardown happens there too.
|
|
113
|
-
recognitionRequest?.endAudio()
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
cleanup(interfaceController: interfaceController)
|
|
117
|
-
box?.resume(returning: makePCMResult(from: capturedSamples))
|
|
118
|
-
}
|
|
75
|
+
stopCapture(interfaceController: interfaceController)
|
|
76
|
+
capturedContinuation?.resume(returning: capturedSamples)
|
|
119
77
|
}
|
|
120
78
|
|
|
121
79
|
// MARK: - Private
|
|
@@ -124,15 +82,13 @@ class VoiceInputManager {
|
|
|
124
82
|
interfaceController: AutoPlayInterfaceController?,
|
|
125
83
|
silenceThresholdMs: Double,
|
|
126
84
|
maxDurationMs: Double,
|
|
127
|
-
listeningText: String
|
|
128
|
-
preferSpeechToText: Bool,
|
|
129
|
-
onChunk: ((_ chunk: VoiceInputChunk) -> Void)?,
|
|
130
|
-
box: ResultBox
|
|
85
|
+
listeningText: String
|
|
131
86
|
) throws {
|
|
132
87
|
guard AVAudioSession.sharedInstance().recordPermission == .granted else {
|
|
133
88
|
throw VoiceInputError.microphonePermissionDenied
|
|
134
89
|
}
|
|
135
90
|
|
|
91
|
+
// Activate the session first so inputNode reports the correct hardware format
|
|
136
92
|
let session = AVAudioSession.sharedInstance()
|
|
137
93
|
try session.setCategory(.playAndRecord, mode: .measurement, options: [])
|
|
138
94
|
try session.setActive(true)
|
|
@@ -141,59 +97,12 @@ class VoiceInputManager {
|
|
|
141
97
|
presentVoiceTemplate(interfaceController: interfaceController, listeningText: listeningText)
|
|
142
98
|
}
|
|
143
99
|
|
|
144
|
-
var activeRecognitionRequest: SFSpeechAudioBufferRecognitionRequest? = nil
|
|
145
|
-
|
|
146
|
-
if preferSpeechToText, SFSpeechRecognizer.authorizationStatus() == .authorized,
|
|
147
|
-
let recognizer = SFSpeechRecognizer(locale: Locale.current),
|
|
148
|
-
recognizer.isAvailable
|
|
149
|
-
{
|
|
150
|
-
let request = SFSpeechAudioBufferRecognitionRequest()
|
|
151
|
-
request.shouldReportPartialResults = true
|
|
152
|
-
recognitionRequest = request
|
|
153
|
-
activeRecognitionRequest = request
|
|
154
|
-
|
|
155
|
-
recognizer.recognitionTask(with: request) { [weak self] result, error in
|
|
156
|
-
guard let self else { return }
|
|
157
|
-
|
|
158
|
-
if error != nil {
|
|
159
|
-
// STT failed — fall back to whatever PCM was accumulated
|
|
160
|
-
self.stopLock.lock()
|
|
161
|
-
let capturedSamples = self.samples
|
|
162
|
-
self.samples = []
|
|
163
|
-
self.stopLock.unlock()
|
|
164
|
-
|
|
165
|
-
self.cleanup(interfaceController: interfaceController)
|
|
166
|
-
box.resume(returning: self.makePCMResult(from: capturedSamples))
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
guard let result else { return }
|
|
171
|
-
|
|
172
|
-
if result.isFinal {
|
|
173
|
-
self.stopLock.lock()
|
|
174
|
-
self.isStopping = true
|
|
175
|
-
self.samples = []
|
|
176
|
-
self.stopLock.unlock()
|
|
177
|
-
|
|
178
|
-
self.cleanup(interfaceController: interfaceController)
|
|
179
|
-
box.resume(
|
|
180
|
-
returning: VoiceInputResult(
|
|
181
|
-
transcription: result.bestTranscription.formattedString,
|
|
182
|
-
audio: nil
|
|
183
|
-
)
|
|
184
|
-
)
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
onChunk?(VoiceInputChunk(partial: result.bestTranscription.formattedString, audio: nil))
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
100
|
let engine = AVAudioEngine()
|
|
193
101
|
let inputNode = engine.inputNode
|
|
194
102
|
let nativeFormat = inputNode.outputFormat(forBus: 0)
|
|
195
103
|
|
|
196
|
-
|
|
104
|
+
let targetFormat = VoiceInputManager.targetFormat
|
|
105
|
+
guard let converter = AVAudioConverter(from: nativeFormat, to: targetFormat) else {
|
|
197
106
|
throw VoiceInputError.converterUnavailable
|
|
198
107
|
}
|
|
199
108
|
|
|
@@ -207,43 +116,36 @@ class VoiceInputManager {
|
|
|
207
116
|
) { [weak self] buffer, _ in
|
|
208
117
|
guard let self, !self.isStopping else { return }
|
|
209
118
|
|
|
210
|
-
// Feed STT if active
|
|
211
|
-
activeRecognitionRequest?.append(buffer)
|
|
212
|
-
|
|
213
|
-
// Convert to 16kHz int16 for accumulation and PCM chunks
|
|
214
119
|
let outputFrameCapacity = AVAudioFrameCount(
|
|
215
|
-
Double(buffer.frameLength)
|
|
120
|
+
Double(buffer.frameLength)
|
|
121
|
+
* VoiceInputManager.sampleRate
|
|
122
|
+
/ nativeFormat.sampleRate
|
|
216
123
|
)
|
|
124
|
+
|
|
217
125
|
guard
|
|
218
126
|
let outputBuffer = AVAudioPCMBuffer(
|
|
219
|
-
pcmFormat:
|
|
127
|
+
pcmFormat: targetFormat,
|
|
220
128
|
frameCapacity: outputFrameCapacity
|
|
221
129
|
)
|
|
222
130
|
else { return }
|
|
223
131
|
|
|
224
132
|
var conversionError: NSError?
|
|
225
|
-
let status = converter.convert(to: outputBuffer, error: &conversionError) {
|
|
133
|
+
let status = converter.convert(to: outputBuffer, error: &conversionError) {
|
|
134
|
+
_,
|
|
135
|
+
outStatus in
|
|
226
136
|
outStatus.pointee = .haveData
|
|
227
137
|
return buffer
|
|
228
138
|
}
|
|
139
|
+
|
|
229
140
|
guard status != .error, let int16Data = outputBuffer.int16ChannelData else { return }
|
|
230
141
|
|
|
231
142
|
let frameCount = Int(outputBuffer.frameLength)
|
|
232
143
|
let newSamples = Array(UnsafeBufferPointer(start: int16Data[0], count: frameCount))
|
|
233
144
|
self.samples.append(contentsOf: newSamples)
|
|
234
145
|
|
|
235
|
-
// PCM chunk callback
|
|
236
|
-
if activeRecognitionRequest == nil, let onChunk {
|
|
237
|
-
if let chunkBuffer = try? ArrayBuffer.copy(
|
|
238
|
-
data: newSamples.withUnsafeBufferPointer { Data(buffer: $0) }
|
|
239
|
-
) {
|
|
240
|
-
onChunk(VoiceInputChunk(partial: nil, audio: chunkBuffer))
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
146
|
let now = Date()
|
|
245
147
|
|
|
246
|
-
// Max duration
|
|
148
|
+
// Max duration check
|
|
247
149
|
if let start = self.recordingStart,
|
|
248
150
|
now.timeIntervalSince(start) * 1000 >= maxDurationMs
|
|
249
151
|
{
|
|
@@ -258,9 +160,7 @@ class VoiceInputManager {
|
|
|
258
160
|
{
|
|
259
161
|
let peak = newSamples.reduce(0) { max($0, abs(Int($1))) }
|
|
260
162
|
if peak < VoiceInputManager.silenceAmplitudeThreshold {
|
|
261
|
-
if self.silenceStart == nil {
|
|
262
|
-
self.silenceStart = now
|
|
263
|
-
}
|
|
163
|
+
if self.silenceStart == nil { self.silenceStart = now }
|
|
264
164
|
if let silenceBegin = self.silenceStart,
|
|
265
165
|
now.timeIntervalSince(silenceBegin) * 1000 >= silenceThresholdMs
|
|
266
166
|
{
|
|
@@ -283,11 +183,10 @@ class VoiceInputManager {
|
|
|
283
183
|
}
|
|
284
184
|
}
|
|
285
185
|
|
|
286
|
-
private func
|
|
186
|
+
private func stopCapture(interfaceController: AutoPlayInterfaceController?) {
|
|
287
187
|
audioEngine?.inputNode.removeTap(onBus: 0)
|
|
288
188
|
audioEngine?.stop()
|
|
289
189
|
audioEngine = nil
|
|
290
|
-
recognitionRequest = nil
|
|
291
190
|
recordingStart = nil
|
|
292
191
|
silenceStart = nil
|
|
293
192
|
try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation)
|
|
@@ -296,12 +195,6 @@ class VoiceInputManager {
|
|
|
296
195
|
}
|
|
297
196
|
}
|
|
298
197
|
|
|
299
|
-
private func makePCMResult(from samples: [Int16]) -> VoiceInputResult {
|
|
300
|
-
let data = samples.withUnsafeBufferPointer { Data(buffer: $0) }
|
|
301
|
-
let buffer = try? ArrayBuffer.copy(data: data)
|
|
302
|
-
return VoiceInputResult(transcription: nil, audio: buffer)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
198
|
private func presentVoiceTemplate(interfaceController: AutoPlayInterfaceController, listeningText: String) {
|
|
306
199
|
let listeningState = CPVoiceControlState(
|
|
307
200
|
identifier: "listening",
|
|
@@ -325,6 +218,12 @@ class VoiceInputManager {
|
|
|
325
218
|
}
|
|
326
219
|
voiceControlTemplate = nil
|
|
327
220
|
}
|
|
221
|
+
|
|
222
|
+
private func samplesAsData(_ samples: [Int16]) -> Data {
|
|
223
|
+
samples.withUnsafeBufferPointer { ptr in
|
|
224
|
+
Data(buffer: ptr)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
328
227
|
}
|
|
329
228
|
|
|
330
229
|
enum VoiceInputError: Error {
|
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
2
2
|
import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
|
|
3
|
-
import { HybridVoice } from './hybrid/HybridVoice';
|
|
4
3
|
import type { AndroidAutomotive } from './specs/AndroidAutomotive.nitro';
|
|
5
|
-
export { HybridAndroidAutoTelemetry, HybridAutoPlay
|
|
4
|
+
export { HybridAndroidAutoTelemetry, HybridAutoPlay };
|
|
6
5
|
export declare const HybridAndroidAutomotive: AndroidAutomotive | null;
|
|
7
6
|
/**
|
|
8
7
|
* These are the static module names for the app running on the mobile device, head unit screen and the CarPlay dashboard.
|
|
@@ -40,7 +39,6 @@ export * from './types/SignInMethod';
|
|
|
40
39
|
export * from './types/Telemetry';
|
|
41
40
|
export * from './types/Text';
|
|
42
41
|
export * from './types/Trip';
|
|
43
|
-
export type { VoiceInputChunk, VoiceInputOptions, VoiceInputResult } from './types/Voice';
|
|
44
42
|
export type { AlertPriority, NavigationAlert as Alert, NavigationAlertAction as AlertAction, } from './utils/NitroAlert';
|
|
45
43
|
export type { ThemedColor } from './utils/NitroColor';
|
|
46
44
|
export type { GridButton } from './utils/NitroGrid';
|
package/lib/index.js
CHANGED
|
@@ -3,9 +3,8 @@ import { NitroModules } from 'react-native-nitro-modules';
|
|
|
3
3
|
import AutoPlayHeadlessJsTask from './AutoPlayHeadlessJsTask';
|
|
4
4
|
import { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
5
5
|
import { HybridAutoPlay } from './hybrid/HybridAutoPlay';
|
|
6
|
-
import { HybridVoice } from './hybrid/HybridVoice';
|
|
7
6
|
AutoPlayHeadlessJsTask.registerHeadlessTask(HybridAutoPlay);
|
|
8
|
-
export { HybridAndroidAutoTelemetry, HybridAutoPlay
|
|
7
|
+
export { HybridAndroidAutoTelemetry, HybridAutoPlay };
|
|
9
8
|
export const HybridAndroidAutomotive = Platform.OS === 'android'
|
|
10
9
|
? NitroModules.createHybridObject('AndroidAutomotive')
|
|
11
10
|
: null;
|
|
@@ -31,6 +31,35 @@ export interface AutoPlay extends HybridObject<{
|
|
|
31
31
|
* @namespace Android
|
|
32
32
|
*/
|
|
33
33
|
addListenerVoiceInput(callback: (coordinates: Location | undefined, query: string | undefined) => void): CleanupCallback;
|
|
34
|
+
/**
|
|
35
|
+
* Returns true if microphone permission has already been granted.
|
|
36
|
+
*/
|
|
37
|
+
hasVoiceInputPermission(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Request microphone permission from the user.
|
|
40
|
+
* On Android: uses the car context when Android Auto is connected, otherwise
|
|
41
|
+
* falls back to the React Native application context.
|
|
42
|
+
* On iOS: uses AVAudioApplication (iOS 17+) or AVAudioSession (iOS 15–16).
|
|
43
|
+
* Returns true if permission was granted, false if denied.
|
|
44
|
+
*/
|
|
45
|
+
requestVoiceInputPermission(): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Start an in-app voice recording session.
|
|
48
|
+
* On Android: acquires audio focus and captures via CarAudioRecord when
|
|
49
|
+
* Android Auto is connected, otherwise uses standard AudioRecord.
|
|
50
|
+
* On iOS: presents CPVoiceControlTemplate (when a car is connected) and
|
|
51
|
+
* captures audio via AVAudioEngine.
|
|
52
|
+
* Resolves with the complete raw PCM buffer (16 kHz, 16-bit, mono) when
|
|
53
|
+
* silence is detected, the max duration is reached, or stopVoiceInput() is called.
|
|
54
|
+
* Rejects if microphone permission has not been granted or recording fails to start.
|
|
55
|
+
*/
|
|
56
|
+
startVoiceInput(silenceThresholdMs?: number, maxDurationMs?: number, listeningText?: string): Promise<ArrayBuffer>;
|
|
57
|
+
/**
|
|
58
|
+
* Stop the active voice recording session early. Causes the Promise returned
|
|
59
|
+
* by startVoiceInput() to resolve with the audio captured so far.
|
|
60
|
+
* No-op if no recording is in progress.
|
|
61
|
+
*/
|
|
62
|
+
stopVoiceInput(): void;
|
|
34
63
|
/**
|
|
35
64
|
* sets the specified template as root template, initializes a new stack
|
|
36
65
|
* Promise might contain an error message in case setting root template failed
|
package/nitro.json
CHANGED
|
@@ -9,16 +9,6 @@
|
|
|
9
9
|
"androidCxxLibName": "ReactNativeAutoPlay"
|
|
10
10
|
},
|
|
11
11
|
"autolinking": {
|
|
12
|
-
"Voice": {
|
|
13
|
-
"android": {
|
|
14
|
-
"implementationClassName": "HybridVoice",
|
|
15
|
-
"language": "kotlin"
|
|
16
|
-
},
|
|
17
|
-
"ios": {
|
|
18
|
-
"implementationClassName": "HybridVoice",
|
|
19
|
-
"language": "swift"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
12
|
"AutoPlay": {
|
|
23
13
|
"android": {
|
|
24
14
|
"implementationClassName": "HybridAutoPlay",
|
|
@@ -45,7 +45,6 @@ target_sources(
|
|
|
45
45
|
../nitrogen/generated/shared/c++/HybridMessageTemplateSpec.cpp
|
|
46
46
|
../nitrogen/generated/shared/c++/HybridSearchTemplateSpec.cpp
|
|
47
47
|
../nitrogen/generated/shared/c++/HybridSignInTemplateSpec.cpp
|
|
48
|
-
../nitrogen/generated/shared/c++/HybridVoiceSpec.cpp
|
|
49
48
|
# Android-specific Nitrogen C++ sources
|
|
50
49
|
../nitrogen/generated/android/c++/JHybridAndroidAutomotiveSpec.cpp
|
|
51
50
|
../nitrogen/generated/android/c++/JHybridAndroidAutoTelemetrySpec.cpp
|
|
@@ -63,7 +62,6 @@ target_sources(
|
|
|
63
62
|
../nitrogen/generated/android/c++/JHybridSearchTemplateSpec.cpp
|
|
64
63
|
../nitrogen/generated/android/c++/JHybridSignInTemplateSpec.cpp
|
|
65
64
|
../nitrogen/generated/android/c++/JVariant_QrSignIn_PinSignIn_InputSignIn_GoogleSignIn.cpp
|
|
66
|
-
../nitrogen/generated/android/c++/JHybridVoiceSpec.cpp
|
|
67
65
|
)
|
|
68
66
|
|
|
69
67
|
# From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake
|
|
@@ -46,8 +46,6 @@
|
|
|
46
46
|
#include "JHybridSearchTemplateSpec.hpp"
|
|
47
47
|
#include "JHybridSignInTemplateSpec.hpp"
|
|
48
48
|
#include "JFunc_void_std__optional_std__string__std__optional_GoogleSignInAccount_.hpp"
|
|
49
|
-
#include "JHybridVoiceSpec.hpp"
|
|
50
|
-
#include "JFunc_void_VoiceInputChunk.hpp"
|
|
51
49
|
#include <NitroModules/DefaultConstructableObject.hpp>
|
|
52
50
|
|
|
53
51
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
@@ -58,14 +56,6 @@ int initialize(JavaVM* vm) {
|
|
|
58
56
|
});
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
struct JHybridVoiceSpecImpl: public jni::JavaClass<JHybridVoiceSpecImpl, JHybridVoiceSpec::JavaPart> {
|
|
62
|
-
static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/swe/iternio/reactnativeautoplay/HybridVoice;";
|
|
63
|
-
static std::shared_ptr<JHybridVoiceSpec> create() {
|
|
64
|
-
static const auto constructorFn = javaClassStatic()->getConstructor<JHybridVoiceSpecImpl::javaobject()>();
|
|
65
|
-
jni::local_ref<JHybridVoiceSpec::JavaPart> javaPart = javaClassStatic()->newObject(constructorFn);
|
|
66
|
-
return javaPart->getJHybridVoiceSpec();
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
59
|
struct JHybridAutoPlaySpecImpl: public jni::JavaClass<JHybridAutoPlaySpecImpl, JHybridAutoPlaySpec::JavaPart> {
|
|
70
60
|
static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/swe/iternio/reactnativeautoplay/HybridAutoPlay;";
|
|
71
61
|
static std::shared_ptr<JHybridAutoPlaySpec> create() {
|
|
@@ -191,16 +181,8 @@ void registerAllNatives() {
|
|
|
191
181
|
margelo::nitro::swe::iternio::reactnativeautoplay::JHybridSearchTemplateSpec::CxxPart::registerNatives();
|
|
192
182
|
margelo::nitro::swe::iternio::reactnativeautoplay::JHybridSignInTemplateSpec::CxxPart::registerNatives();
|
|
193
183
|
margelo::nitro::swe::iternio::reactnativeautoplay::JFunc_void_std__optional_std__string__std__optional_GoogleSignInAccount__cxx::registerNatives();
|
|
194
|
-
margelo::nitro::swe::iternio::reactnativeautoplay::JHybridVoiceSpec::CxxPart::registerNatives();
|
|
195
|
-
margelo::nitro::swe::iternio::reactnativeautoplay::JFunc_void_VoiceInputChunk_cxx::registerNatives();
|
|
196
184
|
|
|
197
185
|
// Register Nitro Hybrid Objects
|
|
198
|
-
HybridObjectRegistry::registerHybridObjectConstructor(
|
|
199
|
-
"Voice",
|
|
200
|
-
[]() -> std::shared_ptr<HybridObject> {
|
|
201
|
-
return JHybridVoiceSpecImpl::create();
|
|
202
|
-
}
|
|
203
|
-
);
|
|
204
186
|
HybridObjectRegistry::registerHybridObjectConstructor(
|
|
205
187
|
"AutoPlay",
|
|
206
188
|
[]() -> std::shared_ptr<HybridObject> {
|
|
@@ -37,6 +37,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay { enum class NitroBu
|
|
|
37
37
|
#include <NitroModules/JNICallable.hpp>
|
|
38
38
|
#include <NitroModules/Promise.hpp>
|
|
39
39
|
#include <NitroModules/JPromise.hpp>
|
|
40
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
41
|
+
#include <NitroModules/JArrayBuffer.hpp>
|
|
40
42
|
#include <NitroModules/JUnit.hpp>
|
|
41
43
|
#include "EventName.hpp"
|
|
42
44
|
#include "JEventName.hpp"
|
|
@@ -143,6 +145,47 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
143
145
|
}
|
|
144
146
|
}();
|
|
145
147
|
}
|
|
148
|
+
bool JHybridAutoPlaySpec::hasVoiceInputPermission() {
|
|
149
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>("hasVoiceInputPermission");
|
|
150
|
+
auto __result = method(_javaPart);
|
|
151
|
+
return static_cast<bool>(__result);
|
|
152
|
+
}
|
|
153
|
+
std::shared_ptr<Promise<bool>> JHybridAutoPlaySpec::requestVoiceInputPermission() {
|
|
154
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("requestVoiceInputPermission");
|
|
155
|
+
auto __result = method(_javaPart);
|
|
156
|
+
return [&]() {
|
|
157
|
+
auto __promise = Promise<bool>::create();
|
|
158
|
+
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
159
|
+
auto __result = jni::static_ref_cast<jni::JBoolean>(__boxedResult);
|
|
160
|
+
__promise->resolve(static_cast<bool>(__result->value()));
|
|
161
|
+
});
|
|
162
|
+
__result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
|
|
163
|
+
jni::JniException __jniError(__throwable);
|
|
164
|
+
__promise->reject(std::make_exception_ptr(__jniError));
|
|
165
|
+
});
|
|
166
|
+
return __promise;
|
|
167
|
+
}();
|
|
168
|
+
}
|
|
169
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> JHybridAutoPlaySpec::startVoiceInput(std::optional<double> silenceThresholdMs, std::optional<double> maxDurationMs, const std::optional<std::string>& listeningText) {
|
|
170
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JDouble> /* silenceThresholdMs */, jni::alias_ref<jni::JDouble> /* maxDurationMs */, jni::alias_ref<jni::JString> /* listeningText */)>("startVoiceInput");
|
|
171
|
+
auto __result = method(_javaPart, silenceThresholdMs.has_value() ? jni::JDouble::valueOf(silenceThresholdMs.value()) : nullptr, maxDurationMs.has_value() ? jni::JDouble::valueOf(maxDurationMs.value()) : nullptr, listeningText.has_value() ? jni::make_jstring(listeningText.value()) : nullptr);
|
|
172
|
+
return [&]() {
|
|
173
|
+
auto __promise = Promise<std::shared_ptr<ArrayBuffer>>::create();
|
|
174
|
+
__result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
|
|
175
|
+
auto __result = jni::static_ref_cast<JArrayBuffer::javaobject>(__boxedResult);
|
|
176
|
+
__promise->resolve(__result->cthis()->getArrayBuffer());
|
|
177
|
+
});
|
|
178
|
+
__result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
|
|
179
|
+
jni::JniException __jniError(__throwable);
|
|
180
|
+
__promise->reject(std::make_exception_ptr(__jniError));
|
|
181
|
+
});
|
|
182
|
+
return __promise;
|
|
183
|
+
}();
|
|
184
|
+
}
|
|
185
|
+
void JHybridAutoPlaySpec::stopVoiceInput() {
|
|
186
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void()>("stopVoiceInput");
|
|
187
|
+
method(_javaPart);
|
|
188
|
+
}
|
|
146
189
|
std::shared_ptr<Promise<void>> JHybridAutoPlaySpec::setRootTemplate(const std::string& templateId) {
|
|
147
190
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>(jni::alias_ref<jni::JString> /* templateId */)>("setRootTemplate");
|
|
148
191
|
auto __result = method(_javaPart, jni::make_jstring(templateId));
|
|
@@ -57,6 +57,10 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
57
57
|
std::function<void()> addListener(EventName eventType, const std::function<void()>& callback) override;
|
|
58
58
|
std::function<void()> addListenerRenderState(const std::string& moduleName, const std::function<void(VisibilityState /* payload */)>& callback) override;
|
|
59
59
|
std::function<void()> addListenerVoiceInput(const std::function<void(const std::optional<Location>& /* coordinates */, const std::optional<std::string>& /* query */)>& callback) override;
|
|
60
|
+
bool hasVoiceInputPermission() override;
|
|
61
|
+
std::shared_ptr<Promise<bool>> requestVoiceInputPermission() override;
|
|
62
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> startVoiceInput(std::optional<double> silenceThresholdMs, std::optional<double> maxDurationMs, const std::optional<std::string>& listeningText) override;
|
|
63
|
+
void stopVoiceInput() override;
|
|
60
64
|
std::shared_ptr<Promise<void>> setRootTemplate(const std::string& templateId) override;
|
|
61
65
|
std::shared_ptr<Promise<void>> pushTemplate(const std::string& templateId) override;
|
|
62
66
|
std::shared_ptr<Promise<void>> popTemplate(std::optional<bool> animate) override;
|
|
@@ -11,6 +11,7 @@ import androidx.annotation.Keep
|
|
|
11
11
|
import com.facebook.jni.HybridData
|
|
12
12
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
13
13
|
import com.margelo.nitro.core.Promise
|
|
14
|
+
import com.margelo.nitro.core.ArrayBuffer
|
|
14
15
|
import com.margelo.nitro.core.HybridObject
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -56,6 +57,22 @@ abstract class HybridAutoPlaySpec: HybridObject() {
|
|
|
56
57
|
return Func_void_java(__result)
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
@DoNotStrip
|
|
61
|
+
@Keep
|
|
62
|
+
abstract fun hasVoiceInputPermission(): Boolean
|
|
63
|
+
|
|
64
|
+
@DoNotStrip
|
|
65
|
+
@Keep
|
|
66
|
+
abstract fun requestVoiceInputPermission(): Promise<Boolean>
|
|
67
|
+
|
|
68
|
+
@DoNotStrip
|
|
69
|
+
@Keep
|
|
70
|
+
abstract fun startVoiceInput(silenceThresholdMs: Double?, maxDurationMs: Double?, listeningText: String?): Promise<ArrayBuffer>
|
|
71
|
+
|
|
72
|
+
@DoNotStrip
|
|
73
|
+
@Keep
|
|
74
|
+
abstract fun stopVoiceInput(): Unit
|
|
75
|
+
|
|
59
76
|
@DoNotStrip
|
|
60
77
|
@Keep
|
|
61
78
|
abstract fun setRootTemplate(templateId: String): Promise<Unit>
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
#include "HybridMapTemplateSpecSwift.hpp"
|
|
18
18
|
#include "HybridMessageTemplateSpecSwift.hpp"
|
|
19
19
|
#include "HybridSearchTemplateSpecSwift.hpp"
|
|
20
|
-
#include "HybridVoiceSpecSwift.hpp"
|
|
21
20
|
#include "ReactNativeAutoPlay-Swift-Cxx-Umbrella.hpp"
|
|
22
21
|
#include <NitroModules/NitroDefines.hpp>
|
|
23
22
|
|
|
@@ -47,6 +46,14 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay::bridge::swift {
|
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
48
|
|
|
49
|
+
// pragma MARK: std::function<void(bool /* result */)>
|
|
50
|
+
Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
51
|
+
auto swiftClosure = ReactNativeAutoPlay::Func_void_bool::fromUnsafe(swiftClosureWrapper);
|
|
52
|
+
return [swiftClosure = std::move(swiftClosure)](bool result) mutable -> void {
|
|
53
|
+
swiftClosure.call(result);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
50
57
|
// pragma MARK: std::function<void(const std::exception_ptr& /* error */)>
|
|
51
58
|
Func_void_std__exception_ptr create_Func_void_std__exception_ptr(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
52
59
|
auto swiftClosure = ReactNativeAutoPlay::Func_void_std__exception_ptr::fromUnsafe(swiftClosureWrapper);
|
|
@@ -55,6 +62,14 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay::bridge::swift {
|
|
|
55
62
|
};
|
|
56
63
|
}
|
|
57
64
|
|
|
65
|
+
// pragma MARK: std::function<void(const std::shared_ptr<ArrayBuffer>& /* result */)>
|
|
66
|
+
Func_void_std__shared_ptr_ArrayBuffer_ create_Func_void_std__shared_ptr_ArrayBuffer_(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
67
|
+
auto swiftClosure = ReactNativeAutoPlay::Func_void_std__shared_ptr_ArrayBuffer_::fromUnsafe(swiftClosureWrapper);
|
|
68
|
+
return [swiftClosure = std::move(swiftClosure)](const std::shared_ptr<ArrayBuffer>& result) mutable -> void {
|
|
69
|
+
swiftClosure.call(ArrayBufferHolder(result));
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
// pragma MARK: std::function<void(const SafeAreaInsets& /* insets */)>
|
|
59
74
|
Func_void_SafeAreaInsets create_Func_void_SafeAreaInsets(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
60
75
|
auto swiftClosure = ReactNativeAutoPlay::Func_void_SafeAreaInsets::fromUnsafe(swiftClosureWrapper);
|
|
@@ -159,14 +174,6 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay::bridge::swift {
|
|
|
159
174
|
};
|
|
160
175
|
}
|
|
161
176
|
|
|
162
|
-
// pragma MARK: std::function<void(bool /* isPanningInterfaceVisible */)>
|
|
163
|
-
Func_void_bool create_Func_void_bool(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
164
|
-
auto swiftClosure = ReactNativeAutoPlay::Func_void_bool::fromUnsafe(swiftClosureWrapper);
|
|
165
|
-
return [swiftClosure = std::move(swiftClosure)](bool isPanningInterfaceVisible) mutable -> void {
|
|
166
|
-
swiftClosure.call(isPanningInterfaceVisible);
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
177
|
// pragma MARK: std::shared_ptr<HybridGridTemplateSpec>
|
|
171
178
|
std::shared_ptr<HybridGridTemplateSpec> create_std__shared_ptr_HybridGridTemplateSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
|
172
179
|
ReactNativeAutoPlay::HybridGridTemplateSpec_cxx swiftPart = ReactNativeAutoPlay::HybridGridTemplateSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
|
@@ -302,37 +309,5 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay::bridge::swift {
|
|
|
302
309
|
ReactNativeAutoPlay::HybridSearchTemplateSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();
|
|
303
310
|
return swiftPart.toUnsafe();
|
|
304
311
|
}
|
|
305
|
-
|
|
306
|
-
// pragma MARK: std::function<void(const VoiceInputResult& /* result */)>
|
|
307
|
-
Func_void_VoiceInputResult create_Func_void_VoiceInputResult(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
308
|
-
auto swiftClosure = ReactNativeAutoPlay::Func_void_VoiceInputResult::fromUnsafe(swiftClosureWrapper);
|
|
309
|
-
return [swiftClosure = std::move(swiftClosure)](const VoiceInputResult& result) mutable -> void {
|
|
310
|
-
swiftClosure.call(result);
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// pragma MARK: std::function<void(const VoiceInputChunk& /* chunk */)>
|
|
315
|
-
Func_void_VoiceInputChunk create_Func_void_VoiceInputChunk(void* NON_NULL swiftClosureWrapper) noexcept {
|
|
316
|
-
auto swiftClosure = ReactNativeAutoPlay::Func_void_VoiceInputChunk::fromUnsafe(swiftClosureWrapper);
|
|
317
|
-
return [swiftClosure = std::move(swiftClosure)](const VoiceInputChunk& chunk) mutable -> void {
|
|
318
|
-
swiftClosure.call(chunk);
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// pragma MARK: std::shared_ptr<HybridVoiceSpec>
|
|
323
|
-
std::shared_ptr<HybridVoiceSpec> create_std__shared_ptr_HybridVoiceSpec_(void* NON_NULL swiftUnsafePointer) noexcept {
|
|
324
|
-
ReactNativeAutoPlay::HybridVoiceSpec_cxx swiftPart = ReactNativeAutoPlay::HybridVoiceSpec_cxx::fromUnsafe(swiftUnsafePointer);
|
|
325
|
-
return std::make_shared<margelo::nitro::swe::iternio::reactnativeautoplay::HybridVoiceSpecSwift>(swiftPart);
|
|
326
|
-
}
|
|
327
|
-
void* NON_NULL get_std__shared_ptr_HybridVoiceSpec_(std__shared_ptr_HybridVoiceSpec_ cppType) {
|
|
328
|
-
std::shared_ptr<margelo::nitro::swe::iternio::reactnativeautoplay::HybridVoiceSpecSwift> swiftWrapper = std::dynamic_pointer_cast<margelo::nitro::swe::iternio::reactnativeautoplay::HybridVoiceSpecSwift>(cppType);
|
|
329
|
-
#ifdef NITRO_DEBUG
|
|
330
|
-
if (swiftWrapper == nullptr) [[unlikely]] {
|
|
331
|
-
throw std::runtime_error("Class \"HybridVoiceSpec\" is not implemented in Swift!");
|
|
332
|
-
}
|
|
333
|
-
#endif
|
|
334
|
-
ReactNativeAutoPlay::HybridVoiceSpec_cxx& swiftPart = swiftWrapper->getSwiftPart();
|
|
335
|
-
return swiftPart.toUnsafe();
|
|
336
|
-
}
|
|
337
312
|
|
|
338
313
|
} // namespace margelo::nitro::swe::iternio::reactnativeautoplay::bridge::swift
|