tirtc-react-native 2.2.0

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 (104) hide show
  1. package/LICENSE +11 -0
  2. package/README.md +140 -0
  3. package/TiRtcReactNative.podspec +35 -0
  4. package/android/build.gradle +37 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcModule.kt +482 -0
  7. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcPackage.kt +43 -0
  8. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeErrors.kt +32 -0
  9. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeEventBinder.kt +99 -0
  10. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeEventSink.kt +168 -0
  11. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeMaps.kt +49 -0
  12. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeMetricsMaps.kt +173 -0
  13. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeModuleSupport.kt +91 -0
  14. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeOptions.kt +127 -0
  15. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeRegistry.kt +71 -0
  16. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcVideoInputPreviewManager.kt +109 -0
  17. package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcVideoOutputViewManager.kt +109 -0
  18. package/ios/TiRtcReactNative+Conn.mm +112 -0
  19. package/ios/TiRtcReactNative+Input.mm +196 -0
  20. package/ios/TiRtcReactNative+Output.mm +172 -0
  21. package/ios/TiRtcReactNative+Private.h +28 -0
  22. package/ios/TiRtcReactNative.h +6 -0
  23. package/ios/TiRtcReactNative.mm +189 -0
  24. package/ios/TiRtcReactNativeErrors.h +18 -0
  25. package/ios/TiRtcReactNativeErrors.mm +105 -0
  26. package/ios/TiRtcReactNativeEventBinder.h +19 -0
  27. package/ios/TiRtcReactNativeEventBinder.mm +226 -0
  28. package/ios/TiRtcReactNativeEventSink.h +29 -0
  29. package/ios/TiRtcReactNativeEventSink.mm +125 -0
  30. package/ios/TiRtcReactNativeMaps.h +21 -0
  31. package/ios/TiRtcReactNativeMaps.mm +249 -0
  32. package/ios/TiRtcReactNativeNative.h +8 -0
  33. package/ios/TiRtcReactNativeOptions.h +11 -0
  34. package/ios/TiRtcReactNativeOptions.mm +123 -0
  35. package/ios/TiRtcReactNativeRegistry.h +20 -0
  36. package/ios/TiRtcReactNativeRegistry.mm +119 -0
  37. package/ios/TiRtcVideoInputPreview.h +5 -0
  38. package/ios/TiRtcVideoInputPreview.mm +149 -0
  39. package/ios/TiRtcVideoOutputView.h +5 -0
  40. package/ios/TiRtcVideoOutputView.mm +149 -0
  41. package/lib/module/audio_input.js +177 -0
  42. package/lib/module/audio_input.js.map +1 -0
  43. package/lib/module/audio_output.js +168 -0
  44. package/lib/module/audio_output.js.map +1 -0
  45. package/lib/module/conn.js +174 -0
  46. package/lib/module/conn.js.map +1 -0
  47. package/lib/module/errors.js +63 -0
  48. package/lib/module/errors.js.map +1 -0
  49. package/lib/module/events.js +37 -0
  50. package/lib/module/events.js.map +1 -0
  51. package/lib/module/index.js +9 -0
  52. package/lib/module/index.js.map +1 -0
  53. package/lib/module/logging.js +26 -0
  54. package/lib/module/logging.js.map +1 -0
  55. package/lib/module/native.js +5 -0
  56. package/lib/module/native.js.map +1 -0
  57. package/lib/module/native_object_id.js +47 -0
  58. package/lib/module/native_object_id.js.map +1 -0
  59. package/lib/module/runtime.js +27 -0
  60. package/lib/module/runtime.js.map +1 -0
  61. package/lib/module/specs/NativeTiRtc.js +3 -0
  62. package/lib/module/specs/NativeTiRtc.js.map +1 -0
  63. package/lib/module/specs/TiRtcVideoInputPreviewNativeComponent.js +24 -0
  64. package/lib/module/specs/TiRtcVideoOutputViewNativeComponent.js +24 -0
  65. package/lib/module/types.js +93 -0
  66. package/lib/module/types.js.map +1 -0
  67. package/lib/module/video_input.js +266 -0
  68. package/lib/module/video_input.js.map +1 -0
  69. package/lib/module/video_output.js +224 -0
  70. package/lib/module/video_output.js.map +1 -0
  71. package/lib/typescript/audio_input.d.ts +25 -0
  72. package/lib/typescript/audio_output.d.ts +25 -0
  73. package/lib/typescript/conn.d.ts +28 -0
  74. package/lib/typescript/errors.d.ts +19 -0
  75. package/lib/typescript/events.d.ts +6 -0
  76. package/lib/typescript/index.d.ts +9 -0
  77. package/lib/typescript/logging.d.ts +9 -0
  78. package/lib/typescript/native.d.ts +5 -0
  79. package/lib/typescript/native_object_id.d.ts +12 -0
  80. package/lib/typescript/runtime.d.ts +8 -0
  81. package/lib/typescript/specs/NativeTiRtc.d.ts +223 -0
  82. package/lib/typescript/specs/TiRtcVideoInputPreviewNativeComponent.d.ts +8 -0
  83. package/lib/typescript/specs/TiRtcVideoOutputViewNativeComponent.d.ts +8 -0
  84. package/lib/typescript/types.d.ts +281 -0
  85. package/lib/typescript/video_input.d.ts +50 -0
  86. package/lib/typescript/video_output.d.ts +46 -0
  87. package/package.json +80 -0
  88. package/react-native.config.js +10 -0
  89. package/src/audio_input.ts +205 -0
  90. package/src/audio_output.ts +202 -0
  91. package/src/conn.ts +222 -0
  92. package/src/errors.ts +81 -0
  93. package/src/events.ts +44 -0
  94. package/src/index.ts +61 -0
  95. package/src/logging.ts +33 -0
  96. package/src/native.ts +6 -0
  97. package/src/native_object_id.ts +63 -0
  98. package/src/runtime.ts +32 -0
  99. package/src/specs/NativeTiRtc.ts +256 -0
  100. package/src/specs/TiRtcVideoInputPreviewNativeComponent.ts +14 -0
  101. package/src/specs/TiRtcVideoOutputViewNativeComponent.ts +12 -0
  102. package/src/types.ts +340 -0
  103. package/src/video_input.ts +314 -0
  104. package/src/video_output.ts +273 -0
@@ -0,0 +1,482 @@
1
+ package com.tange.ai.tirtc.reactnative
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.Promise
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReactMethod
7
+ import com.facebook.react.bridge.ReadableArray
8
+ import com.facebook.react.bridge.ReadableMap
9
+ import com.facebook.react.bridge.WritableMap
10
+ import com.facebook.react.module.annotations.ReactModule
11
+ import com.tange.ai.tirtc.TiRtc
12
+ import com.tange.ai.tirtc.TiRtcAudioInput
13
+ import com.tange.ai.tirtc.TiRtcAudioOutput
14
+ import com.tange.ai.tirtc.TiRtcConn
15
+ import com.tange.ai.tirtc.TiRtcInitOptions
16
+ import com.tange.ai.tirtc.TiRtcVideoInput
17
+ import com.tange.ai.tirtc.TiRtcVideoOutput
18
+
19
+ @ReactModule(name = TiRtcModule.NAME)
20
+ class TiRtcModule(
21
+ private val reactContext: ReactApplicationContext,
22
+ ) : NativeTiRtcSpec(reactContext) {
23
+ private val registry = TiRtcReactNativeRegistry
24
+ private val events =
25
+ TiRtcReactNativeEventSink(registry) { event ->
26
+ reactContext.runOnJSQueueThread {
27
+ emitOnTiRtcEvent(event)
28
+ }
29
+ }
30
+ private val eventBinder = TiRtcReactNativeEventBinder(events)
31
+
32
+ init {
33
+ registry.bindEventSink(events)
34
+ }
35
+
36
+ override fun getName(): String = NAME
37
+
38
+ @ReactMethod
39
+ override fun initialize(
40
+ options: ReadableMap,
41
+ promise: Promise,
42
+ ) {
43
+ val code =
44
+ TiRtc.initialize(
45
+ reactContext,
46
+ TiRtcInitOptions(
47
+ appId = options.getString("appId") ?: "",
48
+ endpoint = options.getString("endpoint") ?: "",
49
+ consoleLogEnabled = options.getBoolean("consoleLogEnabled"),
50
+ ),
51
+ )
52
+ promise.resolve(TiRtcReactNativeErrors.normalizeAndroid(code))
53
+ }
54
+
55
+ override fun shutdown(): Double {
56
+ if (registry.hasLiveObjects()) {
57
+ return TiRtcReactNativeErrors.RUNTIME_OBJECTS_LIVE.toDouble()
58
+ }
59
+ return TiRtcReactNativeErrors.normalizeAndroid(TiRtc.shutdown()).toDouble()
60
+ }
61
+
62
+ override fun errorToString(code: Double): String = TiRtc.errorToString(code.toInt())
63
+
64
+ override fun writeLog(
65
+ level: Double,
66
+ tag: String,
67
+ message: String,
68
+ ) {
69
+ when (level.toInt()) {
70
+ 0 -> com.tange.ai.tirtc.TiRtcLogging.d(tag, message)
71
+ 1 -> com.tange.ai.tirtc.TiRtcLogging.i(tag, message)
72
+ 2 -> com.tange.ai.tirtc.TiRtcLogging.w(tag, message)
73
+ 3 -> com.tange.ai.tirtc.TiRtcLogging.e(tag, message)
74
+ }
75
+ }
76
+
77
+ @ReactMethod
78
+ override fun uploadLogs(promise: Promise) {
79
+ uploadLogsToPromise(promise, TAG)
80
+ }
81
+
82
+ override fun createConn(): WritableMap =
83
+ registerReactNativeObject(
84
+ registry,
85
+ factory = { TiRtcConn() },
86
+ onRegistered = { entry, value -> eventBinder.wireConn(entry.id, value as TiRtcConn) },
87
+ )
88
+
89
+ override fun connGetState(id: Double): WritableMap {
90
+ val conn = registry.conn(id.toInt()) ?: return stateResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null)
91
+ return stateResult(TiRtcReactNativeErrors.OK, conn.state.name.lowercase())
92
+ }
93
+
94
+ override fun connConnect(
95
+ id: Double,
96
+ remoteId: String,
97
+ token: String,
98
+ ): Double {
99
+ val objectId = id.toInt()
100
+ val code = registry.conn(objectId)?.connect(remoteId, token).normalized()
101
+ Log.i(
102
+ TAG,
103
+ "connConnect objectId=$objectId remoteIdPresent=${remoteId.isNotEmpty()} tokenPresent=${token.isNotEmpty()} code=${code.toInt()}",
104
+ )
105
+ return code
106
+ }
107
+
108
+ override fun connDisconnect(id: Double): Double {
109
+ val objectId = id.toInt()
110
+ val code = registry.conn(objectId)?.disconnect().normalized()
111
+ Log.i(TAG, "connDisconnect objectId=$objectId code=${code.toInt()}")
112
+ return code
113
+ }
114
+
115
+ override fun connSendCommand(
116
+ id: Double,
117
+ commandId: Double,
118
+ data: ReadableArray,
119
+ ): Double = registry.conn(id.toInt())?.sendCommand(commandId.toLong(), data.toByteArray()).normalized()
120
+
121
+ override fun connSendStreamMessage(
122
+ id: Double,
123
+ streamId: Double,
124
+ timestampMs: Double,
125
+ data: ReadableArray,
126
+ ): Double =
127
+ registry.conn(id.toInt())
128
+ ?.sendStreamMessage(streamId.toInt(), timestampMs.toLong(), data.toByteArray())
129
+ .normalized()
130
+
131
+ override fun connSubscribeVideo(id: Double, streamId: Double): Double =
132
+ registry.conn(id.toInt())?.subscribeVideo(streamId.toInt()).normalized()
133
+
134
+ override fun connUnsubscribeVideo(id: Double, streamId: Double): Double =
135
+ registry.conn(id.toInt())?.unsubscribeVideo(streamId.toInt()).normalized()
136
+
137
+ override fun connSubscribeAudio(id: Double, streamId: Double): Double =
138
+ registry.conn(id.toInt())?.subscribeAudio(streamId.toInt()).normalized()
139
+
140
+ override fun connUnsubscribeAudio(id: Double, streamId: Double): Double =
141
+ registry.conn(id.toInt())?.unsubscribeAudio(streamId.toInt()).normalized()
142
+
143
+ override fun connRequestKeyFrame(id: Double, streamId: Double): Double =
144
+ registry.conn(id.toInt())?.requestKeyFrame(streamId.toInt()).normalized()
145
+
146
+ override fun connGetMetricsSnapshot(id: Double): WritableMap {
147
+ val conn = registry.conn(id.toInt()) ?: return releasedSnapshotResult()
148
+ return connMetricsResult(conn.getMetricsSnapshot())
149
+ }
150
+
151
+ override fun connDispose(id: Double): Double {
152
+ val objectId = id.toInt()
153
+ val code = registry.conn(objectId)?.dispose().normalized()
154
+ if (code.toInt() == TiRtcReactNativeErrors.OK) {
155
+ registry.release(objectId)
156
+ }
157
+ return code
158
+ }
159
+
160
+ override fun createAudioOutput(): WritableMap =
161
+ registerReactNativeObject(
162
+ registry,
163
+ factory = { TiRtcAudioOutput() },
164
+ onRegistered = { entry, value -> eventBinder.wireAudioOutput(entry.id, value as TiRtcAudioOutput) },
165
+ )
166
+
167
+ override fun audioOutputGetState(id: Double): WritableMap {
168
+ val output = registry.audioOutput(id.toInt()) ?: return stateResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null)
169
+ return stateResult(0, output.state.name.lowercase())
170
+ }
171
+
172
+ override fun audioOutputConfigure(id: Double, options: ReadableMap): Double {
173
+ return registry.audioOutput(id.toInt())
174
+ ?.configure(audioOutputOptions(options))
175
+ .normalized()
176
+ }
177
+
178
+ override fun audioOutputSetVolume(id: Double, volumePercent: Double): Double {
179
+ if (!volumePercent.isFinite() ||
180
+ volumePercent != volumePercent.toInt().toDouble() ||
181
+ volumePercent < 0.0 ||
182
+ volumePercent > 100.0
183
+ ) {
184
+ return TiRtcReactNativeErrors.INVALID_ARGUMENT.toDouble()
185
+ }
186
+ return registry.audioOutput(id.toInt())?.setVolume(volumePercent.toInt()).normalized()
187
+ }
188
+
189
+ override fun audioOutputAttach(id: Double, connId: Double, streamId: Double): Double {
190
+ val conn = registry.conn(connId.toInt()) ?: return TiRtcReactNativeErrors.OBJECT_RELEASED.toDouble()
191
+ return registry.audioOutput(id.toInt())?.attach(conn, streamId.toInt()).normalized()
192
+ }
193
+
194
+ override fun audioOutputDetach(id: Double): Double = registry.audioOutput(id.toInt())?.detach().normalized()
195
+
196
+ override fun audioOutputGetMetricsSnapshot(id: Double): WritableMap {
197
+ val output = registry.audioOutput(id.toInt()) ?: return releasedSnapshotResult()
198
+ return audioMetricsResult(output.getMetricsSnapshot())
199
+ }
200
+
201
+ override fun audioOutputResetMetricsSession(id: Double): Double =
202
+ registry.audioOutput(id.toInt())?.resetMetricsSession().normalized()
203
+
204
+ override fun audioOutputGetDebugSnapshot(id: Double): WritableMap {
205
+ val output = registry.audioOutput(id.toInt()) ?: return releasedSnapshotResult()
206
+ return audioDebugResult(output.getDebugSnapshot())
207
+ }
208
+
209
+ override fun audioOutputDispose(id: Double): Double {
210
+ val objectId = id.toInt()
211
+ val code = registry.audioOutput(objectId)?.dispose().normalized()
212
+ if (code.toInt() == TiRtcReactNativeErrors.OK) {
213
+ registry.release(objectId)
214
+ }
215
+ return code
216
+ }
217
+
218
+ override fun createVideoOutput(): WritableMap =
219
+ registerReactNativeObject(
220
+ registry,
221
+ factory = { TiRtcVideoOutput() },
222
+ onRegistered = { entry, value -> eventBinder.wireVideoOutput(entry.id, value as TiRtcVideoOutput) },
223
+ )
224
+
225
+ override fun videoOutputGetState(id: Double): WritableMap {
226
+ val output = registry.videoOutput(id.toInt()) ?: return stateResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null)
227
+ return stateResult(0, output.state.name.lowercase())
228
+ }
229
+
230
+ override fun videoOutputGetRenderSize(id: Double): WritableMap {
231
+ val output = registry.videoOutput(id.toInt()) ?: return sizeResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null, null)
232
+ val size = output.renderSize
233
+ return sizeResult(0, size?.width, size?.height)
234
+ }
235
+
236
+ override fun videoOutputSetOptions(id: Double, options: ReadableMap): Double {
237
+ return registry.videoOutput(id.toInt())
238
+ ?.setOptions(videoOutputOptions(options))
239
+ .normalized()
240
+ }
241
+
242
+ override fun videoOutputAttach(id: Double, connId: Double, streamId: Double): Double {
243
+ val conn = registry.conn(connId.toInt()) ?: return TiRtcReactNativeErrors.OBJECT_RELEASED.toDouble()
244
+ return registry.videoOutput(id.toInt())?.attach(conn, streamId.toInt()).normalized()
245
+ }
246
+
247
+ override fun videoOutputDetach(id: Double): Double = registry.videoOutput(id.toInt())?.detach().normalized()
248
+
249
+ override fun videoOutputGetMetricsSnapshot(id: Double): WritableMap {
250
+ val output = registry.videoOutput(id.toInt()) ?: return releasedSnapshotResult()
251
+ return videoMetricsResult(output.getMetricsSnapshot())
252
+ }
253
+
254
+ override fun videoOutputResetMetricsSession(id: Double): Double =
255
+ registry.videoOutput(id.toInt())?.resetMetricsSession().normalized()
256
+
257
+ override fun videoOutputGetDebugSnapshot(id: Double): WritableMap {
258
+ val output = registry.videoOutput(id.toInt()) ?: return releasedSnapshotResult()
259
+ return videoDebugResult(output.getDebugSnapshot())
260
+ }
261
+
262
+ override fun videoOutputDispose(id: Double): Double {
263
+ val objectId = id.toInt()
264
+ val code = registry.videoOutput(objectId)?.dispose().normalized()
265
+ if (code.toInt() == TiRtcReactNativeErrors.OK) {
266
+ registry.release(objectId)
267
+ }
268
+ return code
269
+ }
270
+
271
+ override fun createAudioInput(): WritableMap =
272
+ registerReactNativeObject(
273
+ registry,
274
+ factory = { TiRtcAudioInput() },
275
+ onRegistered = { entry, value -> eventBinder.wireAudioInput(entry.id, value as TiRtcAudioInput) },
276
+ )
277
+
278
+ override fun audioInputGetState(id: Double): WritableMap {
279
+ val input = registry.audioInput(id.toInt()) ?: return stateResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null)
280
+ return stateResult(0, input.state.name.lowercase())
281
+ }
282
+
283
+ @ReactMethod
284
+ override fun audioInputSetOptions(
285
+ id: Double,
286
+ options: ReadableMap,
287
+ promise: Promise,
288
+ ) {
289
+ promise.resolve(
290
+ registry.audioInput(id.toInt())
291
+ ?.setOptions(audioInputOptions(options))
292
+ .normalized(),
293
+ )
294
+ }
295
+
296
+ @ReactMethod
297
+ override fun audioInputAttach(
298
+ id: Double,
299
+ connId: Double,
300
+ streamId: Double,
301
+ promise: Promise,
302
+ ) {
303
+ val conn = registry.conn(connId.toInt())
304
+ val code =
305
+ if (conn == null) {
306
+ TiRtcReactNativeErrors.OBJECT_RELEASED
307
+ } else {
308
+ TiRtcReactNativeErrors.normalizeAndroid(
309
+ registry.audioInput(id.toInt())?.attach(conn, streamId.toInt())
310
+ ?: TiRtcReactNativeErrors.OBJECT_RELEASED,
311
+ )
312
+ }
313
+ Log.i(TAG, "audioInputAttach objectId=${id.toInt()} connId=${connId.toInt()} streamId=${streamId.toInt()} code=$code")
314
+ promise.resolve(code.toDouble())
315
+ }
316
+
317
+ @ReactMethod
318
+ override fun audioInputStart(
319
+ id: Double,
320
+ promise: Promise,
321
+ ) {
322
+ val code =
323
+ TiRtcReactNativeErrors.normalizeAndroid(
324
+ registry.audioInput(id.toInt())?.start()
325
+ ?: TiRtcReactNativeErrors.OBJECT_RELEASED,
326
+ )
327
+ Log.i(TAG, "audioInputStart objectId=${id.toInt()} code=$code")
328
+ promise.resolve(code.toDouble())
329
+ }
330
+
331
+ @ReactMethod
332
+ override fun audioInputStop(
333
+ id: Double,
334
+ promise: Promise,
335
+ ) {
336
+ promise.resolve(registry.audioInput(id.toInt())?.stop().normalized())
337
+ }
338
+
339
+ @ReactMethod
340
+ override fun audioInputDetach(
341
+ id: Double,
342
+ connId: Double,
343
+ promise: Promise,
344
+ ) {
345
+ val conn = registry.conn(connId.toInt())
346
+ promise.resolve(
347
+ if (conn == null) {
348
+ TiRtcReactNativeErrors.OBJECT_RELEASED.toDouble()
349
+ } else {
350
+ registry.audioInput(id.toInt())?.detach(conn).normalized()
351
+ },
352
+ )
353
+ }
354
+
355
+ @ReactMethod
356
+ override fun audioInputDispose(
357
+ id: Double,
358
+ promise: Promise,
359
+ ) {
360
+ val objectId = id.toInt()
361
+ val code = registry.audioInput(objectId)?.dispose().normalized()
362
+ if (code.toInt() == TiRtcReactNativeErrors.OK) {
363
+ registry.release(objectId)
364
+ }
365
+ promise.resolve(code)
366
+ }
367
+
368
+ override fun createVideoInput(): WritableMap =
369
+ registerReactNativeObject(
370
+ registry,
371
+ factory = { TiRtcVideoInput() },
372
+ onRegistered = { entry, value -> eventBinder.wireVideoInput(entry.id, value as TiRtcVideoInput) },
373
+ )
374
+
375
+ override fun videoInputGetState(id: Double): WritableMap {
376
+ val input = registry.videoInput(id.toInt()) ?: return stateResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null)
377
+ return stateResult(0, input.state.name.lowercase())
378
+ }
379
+
380
+ override fun videoInputGetActualConfig(id: Double): WritableMap {
381
+ val input = registry.videoInput(id.toInt()) ?: return sizeResult(TiRtcReactNativeErrors.OBJECT_RELEASED, null, null)
382
+ val size = input.outputSize
383
+ return sizeResult(0, size?.width, size?.height).apply {
384
+ val fps = input.outputFps
385
+ if (fps == null) {
386
+ putNull("fps")
387
+ } else {
388
+ putInt("fps", fps)
389
+ }
390
+ }
391
+ }
392
+
393
+ @ReactMethod
394
+ override fun videoInputSetOptions(
395
+ id: Double,
396
+ options: ReadableMap,
397
+ promise: Promise,
398
+ ) {
399
+ promise.resolve(
400
+ registry.videoInput(id.toInt())
401
+ ?.setOptions(videoInputOptions(options))
402
+ .normalized(),
403
+ )
404
+ }
405
+
406
+ @ReactMethod
407
+ override fun videoInputAttach(
408
+ id: Double,
409
+ connId: Double,
410
+ streamId: Double,
411
+ promise: Promise,
412
+ ) {
413
+ val conn = registry.conn(connId.toInt())
414
+ val code =
415
+ if (conn == null) {
416
+ TiRtcReactNativeErrors.OBJECT_RELEASED
417
+ } else {
418
+ TiRtcReactNativeErrors.normalizeAndroid(
419
+ registry.videoInput(id.toInt())?.attach(conn, streamId.toInt())
420
+ ?: TiRtcReactNativeErrors.OBJECT_RELEASED,
421
+ )
422
+ }
423
+ Log.i(TAG, "videoInputAttach objectId=${id.toInt()} connId=${connId.toInt()} streamId=${streamId.toInt()} code=$code")
424
+ promise.resolve(code.toDouble())
425
+ }
426
+
427
+ @ReactMethod
428
+ override fun videoInputStart(
429
+ id: Double,
430
+ promise: Promise,
431
+ ) {
432
+ val code =
433
+ TiRtcReactNativeErrors.normalizeAndroid(
434
+ registry.videoInput(id.toInt())?.start()
435
+ ?: TiRtcReactNativeErrors.OBJECT_RELEASED,
436
+ )
437
+ Log.i(TAG, "videoInputStart objectId=${id.toInt()} code=$code")
438
+ promise.resolve(code.toDouble())
439
+ }
440
+
441
+ @ReactMethod
442
+ override fun videoInputStop(
443
+ id: Double,
444
+ promise: Promise,
445
+ ) {
446
+ promise.resolve(registry.videoInput(id.toInt())?.stop().normalized())
447
+ }
448
+
449
+ @ReactMethod
450
+ override fun videoInputDetach(
451
+ id: Double,
452
+ connId: Double,
453
+ promise: Promise,
454
+ ) {
455
+ val conn = registry.conn(connId.toInt())
456
+ promise.resolve(
457
+ if (conn == null) {
458
+ TiRtcReactNativeErrors.OBJECT_RELEASED.toDouble()
459
+ } else {
460
+ registry.videoInput(id.toInt())?.detach(conn).normalized()
461
+ },
462
+ )
463
+ }
464
+
465
+ @ReactMethod
466
+ override fun videoInputDispose(
467
+ id: Double,
468
+ promise: Promise,
469
+ ) {
470
+ val objectId = id.toInt()
471
+ val code = registry.videoInput(objectId)?.dispose().normalized()
472
+ if (code.toInt() == TiRtcReactNativeErrors.OK) {
473
+ registry.release(objectId)
474
+ }
475
+ promise.resolve(code)
476
+ }
477
+
478
+ companion object {
479
+ const val NAME = "TiRtc"
480
+ private const val TAG = "TiRtcReactNative"
481
+ }
482
+ }
@@ -0,0 +1,43 @@
1
+ package com.tange.ai.tirtc.reactnative
2
+
3
+ import com.facebook.react.TurboReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import com.facebook.react.uimanager.ViewManager
9
+
10
+ class TiRtcPackage : TurboReactPackage() {
11
+ override fun getModule(
12
+ name: String,
13
+ reactContext: ReactApplicationContext,
14
+ ): NativeModule? {
15
+ return if (name == TiRtcModule.NAME) TiRtcModule(reactContext) else null
16
+ }
17
+
18
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
19
+ return ReactModuleInfoProvider {
20
+ mapOf(
21
+ TiRtcModule.NAME to
22
+ ReactModuleInfo(
23
+ TiRtcModule.NAME,
24
+ TiRtcModule.NAME,
25
+ false,
26
+ false,
27
+ true,
28
+ false,
29
+ true,
30
+ ),
31
+ )
32
+ }
33
+ }
34
+
35
+ override fun createViewManagers(
36
+ reactContext: ReactApplicationContext,
37
+ ): MutableList<ViewManager<*, *>> {
38
+ return mutableListOf(
39
+ TiRtcVideoOutputViewManager(),
40
+ TiRtcVideoInputPreviewManager(),
41
+ )
42
+ }
43
+ }
@@ -0,0 +1,32 @@
1
+ package com.tange.ai.tirtc.reactnative
2
+
3
+ internal object TiRtcReactNativeErrors {
4
+ const val OK = 0
5
+ const val INVALID_ARGUMENT = 6000
6
+ const val OBJECT_RELEASED = 1008
7
+ const val PLATFORM_INTERNAL = 1001
8
+ const val RUNTIME_OBJECTS_LIVE = 1007
9
+
10
+ fun normalizeAndroid(code: Int): Int {
11
+ return when (code) {
12
+ 1002 -> INVALID_ARGUMENT
13
+ 1004 -> 1005
14
+ 1005 -> RUNTIME_OBJECTS_LIVE
15
+ 1006 -> OBJECT_RELEASED
16
+ 1007 -> 1010
17
+ 1008 -> 6026
18
+ 1009 -> 6027
19
+ 1010 -> 6028
20
+ 1011 -> 6029
21
+ 1012 -> 1016
22
+ 1013 -> 6024
23
+ 1014 -> 1201
24
+ 1015 -> 1202
25
+ 1016 -> 1203
26
+ 1017 -> 1204
27
+ 1018 -> 1205
28
+ 1019 -> 6034
29
+ else -> code
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,99 @@
1
+ package com.tange.ai.tirtc.reactnative
2
+
3
+ import android.util.Log
4
+ import com.tange.ai.tirtc.TiRtcAudioInput
5
+ import com.tange.ai.tirtc.TiRtcAudioOutput
6
+ import com.tange.ai.tirtc.TiRtcAudioOutputErrorListener
7
+ import com.tange.ai.tirtc.TiRtcAudioOutputStateListener
8
+ import com.tange.ai.tirtc.TiRtcConn
9
+ import com.tange.ai.tirtc.TiRtcConnCommandListener
10
+ import com.tange.ai.tirtc.TiRtcConnStateListener
11
+ import com.tange.ai.tirtc.TiRtcConnStreamMessageListener
12
+ import com.tange.ai.tirtc.TiRtcInputErrorListener
13
+ import com.tange.ai.tirtc.TiRtcInputStateListener
14
+ import com.tange.ai.tirtc.TiRtcVideoInput
15
+ import com.tange.ai.tirtc.TiRtcVideoInputActualConfigListener
16
+ import com.tange.ai.tirtc.TiRtcVideoOutput
17
+ import com.tange.ai.tirtc.TiRtcVideoOutputErrorListener
18
+ import com.tange.ai.tirtc.TiRtcVideoOutputRenderSizeListener
19
+ import com.tange.ai.tirtc.TiRtcVideoOutputStateListener
20
+
21
+ internal class TiRtcReactNativeEventBinder(
22
+ private val events: TiRtcReactNativeEventSink,
23
+ ) {
24
+ fun wireConn(
25
+ id: Int,
26
+ conn: TiRtcConn,
27
+ ) {
28
+ conn.onStateChanged = TiRtcConnStateListener { state, errorCode ->
29
+ Log.i(TAG, "connStateChanged objectId=$id state=${state.name.lowercase()} code=$errorCode")
30
+ events.connStateChanged(id, state.name.lowercase(), errorCode)
31
+ }
32
+ conn.onCommand = TiRtcConnCommandListener { command, data ->
33
+ events.connCommand(id, command, data)
34
+ }
35
+ conn.onStreamMessage = TiRtcConnStreamMessageListener { streamId, timestampMs, data ->
36
+ events.connStreamMessage(id, streamId, timestampMs, data)
37
+ }
38
+ }
39
+
40
+ fun wireAudioOutput(
41
+ id: Int,
42
+ output: TiRtcAudioOutput,
43
+ ) {
44
+ output.onStateChanged = TiRtcAudioOutputStateListener { state ->
45
+ events.audioOutputStateChanged(id, state.name.lowercase())
46
+ }
47
+ output.onError = TiRtcAudioOutputErrorListener { code ->
48
+ events.audioOutputError(id, code)
49
+ }
50
+ }
51
+
52
+ fun wireVideoOutput(
53
+ id: Int,
54
+ output: TiRtcVideoOutput,
55
+ ) {
56
+ output.onStateChanged = TiRtcVideoOutputStateListener { state ->
57
+ events.videoOutputStateChanged(id, state.name.lowercase())
58
+ }
59
+ output.onRenderSizeChanged = TiRtcVideoOutputRenderSizeListener { size ->
60
+ events.videoOutputRenderSizeChanged(id, size)
61
+ }
62
+ output.onError = TiRtcVideoOutputErrorListener { code ->
63
+ events.videoOutputError(id, code)
64
+ }
65
+ }
66
+
67
+ fun wireAudioInput(
68
+ id: Int,
69
+ input: TiRtcAudioInput,
70
+ ) {
71
+ input.onStateChanged = TiRtcInputStateListener { state ->
72
+ Log.i(TAG, "audioInputStateChanged objectId=$id state=${state.name.lowercase()}")
73
+ events.audioInputStateChanged(id, state.name.lowercase())
74
+ }
75
+ input.onError = TiRtcInputErrorListener { code, message ->
76
+ events.audioInputError(id, code, message)
77
+ }
78
+ }
79
+
80
+ fun wireVideoInput(
81
+ id: Int,
82
+ input: TiRtcVideoInput,
83
+ ) {
84
+ input.onStateChanged = TiRtcInputStateListener { state ->
85
+ Log.i(TAG, "videoInputStateChanged objectId=$id state=${state.name.lowercase()}")
86
+ events.videoInputStateChanged(id, state.name.lowercase())
87
+ }
88
+ input.onActualConfigChanged = TiRtcVideoInputActualConfigListener { size, fps ->
89
+ events.videoInputActualConfigChanged(id, size, fps)
90
+ }
91
+ input.onError = TiRtcInputErrorListener { code, message ->
92
+ events.videoInputError(id, code, message)
93
+ }
94
+ }
95
+
96
+ private companion object {
97
+ const val TAG = "TiRtcReactNative"
98
+ }
99
+ }