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,202 @@
1
+ import {
2
+ isFiniteSafeInteger,
3
+ isPositiveInt32,
4
+ isUInt8,
5
+ normalizeCreateResult,
6
+ returnReleasedIfDisposed,
7
+ TIRTC_ERROR_INVALID_ARGUMENT,
8
+ TIRTC_ERROR_OK,
9
+ } from './errors';
10
+ import {registerNativeEventHandler, unregisterNativeEventHandler} from './events';
11
+ import {readNativeIdentity, clearNativeIdentity, setNativeIdentity, type NativeIdentity} from './native_object_id';
12
+ import {NativeTiRtc, type NativeTiRtcEvent} from './native';
13
+ import {TiRtcConn} from './conn';
14
+ import type {
15
+ TiRtcAudioOutputDebugSnapshotResult,
16
+ TiRtcAudioOutputMetricsResult,
17
+ TiRtcAudioOutputOptions,
18
+ TiRtcAudioOutputState,
19
+ TiRtcOnAudioOutputError,
20
+ TiRtcOnAudioOutputStateChanged,
21
+ } from './types';
22
+
23
+ export class TiRtcAudioOutput {
24
+ private identity: NativeIdentity | null = null;
25
+ private disposed = false;
26
+ private createCode: number = TIRTC_ERROR_OK;
27
+ private currentState: TiRtcAudioOutputState = 'idle';
28
+ private options: Required<Omit<TiRtcAudioOutputOptions, 'maxBufferWatermarkMs'>> &
29
+ Pick<TiRtcAudioOutputOptions, 'maxBufferWatermarkMs'> = {
30
+ agcLevel: 'disabled',
31
+ ansLevel: 'disabled',
32
+ bufferStrategy: 'automatic',
33
+ maxBufferWatermarkMs: undefined,
34
+ };
35
+
36
+ onStateChanged: TiRtcOnAudioOutputStateChanged | null = null;
37
+ onError: TiRtcOnAudioOutputError | null = null;
38
+
39
+ constructor() {
40
+ const result = normalizeCreateResult(NativeTiRtc.createAudioOutput());
41
+ this.createCode = result.code;
42
+ if (result.code === TIRTC_ERROR_OK) {
43
+ this.adoptIdentity({objectId: result.objectId, generation: result.generation});
44
+ }
45
+ }
46
+
47
+ get state(): TiRtcAudioOutputState {
48
+ if (this.identity !== null && !this.disposed) {
49
+ const result = NativeTiRtc.audioOutputGetState(this.identity.objectId);
50
+ if (result.state !== null) {
51
+ this.currentState = result.state as TiRtcAudioOutputState;
52
+ }
53
+ }
54
+ return this.currentState;
55
+ }
56
+
57
+ configure(options: TiRtcAudioOutputOptions): number {
58
+ const normalized = {
59
+ agcLevel: options.agcLevel ?? 'disabled',
60
+ ansLevel: options.ansLevel ?? 'disabled',
61
+ bufferStrategy: options.bufferStrategy ?? 'automatic',
62
+ maxBufferWatermarkMs: options.maxBufferWatermarkMs,
63
+ };
64
+ if (
65
+ normalized.maxBufferWatermarkMs !== undefined
66
+ && !isPositiveInt32(normalized.maxBufferWatermarkMs)
67
+ ) {
68
+ return TIRTC_ERROR_INVALID_ARGUMENT;
69
+ }
70
+ const identity = this.ensureIdentity();
71
+ if (typeof identity === 'number') {
72
+ return identity;
73
+ }
74
+ const code = NativeTiRtc.audioOutputConfigure(identity.objectId, {
75
+ ...normalized,
76
+ maxBufferWatermarkMs: normalized.maxBufferWatermarkMs ?? null,
77
+ });
78
+ if (code === TIRTC_ERROR_OK) {
79
+ this.options = normalized;
80
+ }
81
+ return code;
82
+ }
83
+
84
+ attach(connection: TiRtcConn, streamId: number): number {
85
+ const connIdentity = readNativeIdentity(connection);
86
+ if (!isUInt8(streamId)) {
87
+ return TIRTC_ERROR_INVALID_ARGUMENT;
88
+ }
89
+ if (connIdentity === null) {
90
+ return TIRTC_ERROR_INVALID_ARGUMENT;
91
+ }
92
+ const identity = this.ensureIdentity();
93
+ if (typeof identity === 'number') {
94
+ return identity;
95
+ }
96
+ return NativeTiRtc.audioOutputAttach(identity.objectId, connIdentity.objectId, streamId);
97
+ }
98
+
99
+ detach(): number {
100
+ const released = returnReleasedIfDisposed(this.disposed);
101
+ if (released !== null) {
102
+ return released;
103
+ }
104
+ return this.identity === null ? TIRTC_ERROR_OK : NativeTiRtc.audioOutputDetach(this.identity.objectId);
105
+ }
106
+
107
+ setVolume(volumePercent: number): number {
108
+ if (!isFiniteSafeInteger(volumePercent) || volumePercent < 0 || volumePercent > 100) {
109
+ return TIRTC_ERROR_INVALID_ARGUMENT;
110
+ }
111
+ const identity = this.ensureIdentity();
112
+ if (typeof identity === 'number') {
113
+ return identity;
114
+ }
115
+ return NativeTiRtc.audioOutputSetVolume(identity.objectId, volumePercent);
116
+ }
117
+
118
+ getMetricsSnapshot(): TiRtcAudioOutputMetricsResult {
119
+ const identity = this.ensureIdentity();
120
+ if (typeof identity === 'number') {
121
+ return {code: identity, snapshot: null};
122
+ }
123
+ return NativeTiRtc.audioOutputGetMetricsSnapshot(identity.objectId);
124
+ }
125
+
126
+ resetMetricsSession(): number {
127
+ const identity = this.ensureIdentity();
128
+ if (typeof identity === 'number') {
129
+ return identity;
130
+ }
131
+ return NativeTiRtc.audioOutputResetMetricsSession(identity.objectId);
132
+ }
133
+
134
+ getDebugSnapshot(): TiRtcAudioOutputDebugSnapshotResult {
135
+ const identity = this.ensureIdentity();
136
+ if (typeof identity === 'number') {
137
+ return {code: identity, snapshot: null};
138
+ }
139
+ return NativeTiRtc.audioOutputGetDebugSnapshot(identity.objectId);
140
+ }
141
+
142
+ dispose(): number {
143
+ if (this.disposed) {
144
+ return TIRTC_ERROR_OK;
145
+ }
146
+ if (this.identity === null) {
147
+ this.disposed = true;
148
+ this.clearCallbacks();
149
+ this.currentState = 'idle';
150
+ return TIRTC_ERROR_OK;
151
+ }
152
+ const identity = this.identity;
153
+ const code = NativeTiRtc.audioOutputDispose(identity.objectId);
154
+ if (code === TIRTC_ERROR_OK) {
155
+ this.disposed = true;
156
+ this.identity = null;
157
+ unregisterNativeEventHandler(identity);
158
+ clearNativeIdentity(this);
159
+ this.clearCallbacks();
160
+ this.currentState = 'idle';
161
+ }
162
+ return code;
163
+ }
164
+
165
+ private ensureIdentity(): NativeIdentity | number {
166
+ const released = returnReleasedIfDisposed(this.disposed);
167
+ if (released !== null) {
168
+ return released;
169
+ }
170
+ if (this.identity !== null) {
171
+ return this.identity;
172
+ }
173
+ return this.createCode;
174
+ }
175
+
176
+ private adoptIdentity(identity: NativeIdentity): void {
177
+ this.identity = identity;
178
+ setNativeIdentity(this, identity);
179
+ registerNativeEventHandler(identity, (event) => this.handleEvent(event));
180
+ NativeTiRtc.audioOutputConfigure(identity.objectId, {
181
+ ...this.options,
182
+ maxBufferWatermarkMs: this.options.maxBufferWatermarkMs ?? null,
183
+ });
184
+ }
185
+
186
+ private clearCallbacks(): void {
187
+ this.onStateChanged = null;
188
+ this.onError = null;
189
+ }
190
+
191
+ private handleEvent(event: NativeTiRtcEvent): void {
192
+ if (this.disposed) {
193
+ return;
194
+ }
195
+ if (event.type === 'audioOutputStateChanged' && event.state !== undefined) {
196
+ this.currentState = event.state as TiRtcAudioOutputState;
197
+ this.onStateChanged?.(this.currentState);
198
+ } else if (event.type === 'audioOutputError') {
199
+ this.onError?.(event.code ?? TIRTC_ERROR_INVALID_ARGUMENT);
200
+ }
201
+ }
202
+ }
package/src/conn.ts ADDED
@@ -0,0 +1,222 @@
1
+ import {
2
+ fromNativeBytes,
3
+ isUInt8,
4
+ isUInt32,
5
+ normalizeCreateResult,
6
+ returnReleasedIfDisposed,
7
+ TIRTC_ERROR_INVALID_ARGUMENT,
8
+ TIRTC_ERROR_OK,
9
+ } from './errors';
10
+ import {registerNativeEventHandler, unregisterNativeEventHandler} from './events';
11
+ import {clearNativeIdentity, setNativeIdentity, type NativeIdentity} from './native_object_id';
12
+ import {NativeTiRtc, type NativeTiRtcEvent} from './native';
13
+ import {toNativeBytes} from './errors';
14
+ import type {
15
+ TiRtcConnMetricsResult,
16
+ TiRtcConnState,
17
+ TiRtcOnConnCommand,
18
+ TiRtcOnConnStateChanged,
19
+ TiRtcOnConnStreamMessage,
20
+ } from './types';
21
+
22
+ export class TiRtcConn {
23
+ private identity: NativeIdentity | null = null;
24
+ private disposed = false;
25
+ private createCode: number = TIRTC_ERROR_OK;
26
+ private currentState: TiRtcConnState = 'idle';
27
+
28
+ constructor() {
29
+ const result = normalizeCreateResult(NativeTiRtc.createConn());
30
+ this.createCode = result.code;
31
+ if (result.code === TIRTC_ERROR_OK) {
32
+ this.adoptIdentity({objectId: result.objectId, generation: result.generation});
33
+ }
34
+ }
35
+
36
+ onStateChanged: TiRtcOnConnStateChanged | null = null;
37
+ onCommand: TiRtcOnConnCommand | null = null;
38
+ onStreamMessage: TiRtcOnConnStreamMessage | null = null;
39
+
40
+ get state(): TiRtcConnState {
41
+ if (this.identity !== null && !this.disposed) {
42
+ const result = NativeTiRtc.connGetState(this.identity.objectId);
43
+ if (result.state !== null) {
44
+ this.currentState = result.state as TiRtcConnState;
45
+ }
46
+ }
47
+ return this.currentState;
48
+ }
49
+
50
+ connect(remoteId: string, token: string): number {
51
+ if (typeof remoteId !== 'string' || typeof token !== 'string') {
52
+ return TIRTC_ERROR_INVALID_ARGUMENT;
53
+ }
54
+ const identity = this.ensureIdentity();
55
+ if (typeof identity === 'number') {
56
+ return identity;
57
+ }
58
+ return NativeTiRtc.connConnect(identity.objectId, remoteId, token);
59
+ }
60
+
61
+ disconnect(): number {
62
+ const released = returnReleasedIfDisposed(this.disposed);
63
+ if (released !== null) {
64
+ return released;
65
+ }
66
+ return this.identity === null ? TIRTC_ERROR_OK : NativeTiRtc.connDisconnect(this.identity.objectId);
67
+ }
68
+
69
+ sendCommand(commandId: number, data: Uint8Array): number {
70
+ if (!isUInt32(commandId)) {
71
+ return TIRTC_ERROR_INVALID_ARGUMENT;
72
+ }
73
+ const nativeBytes = toNativeBytes(data);
74
+ if (nativeBytes === null) {
75
+ return TIRTC_ERROR_INVALID_ARGUMENT;
76
+ }
77
+ const identity = this.ensureIdentity();
78
+ if (typeof identity === 'number') {
79
+ return identity;
80
+ }
81
+ return NativeTiRtc.connSendCommand(identity.objectId, commandId, nativeBytes);
82
+ }
83
+
84
+ sendStreamMessage(streamId: number, timestampMs: number, data: Uint8Array): number {
85
+ if (!isUInt8(streamId) || !isUInt32(timestampMs)) {
86
+ return TIRTC_ERROR_INVALID_ARGUMENT;
87
+ }
88
+ const nativeBytes = toNativeBytes(data);
89
+ if (nativeBytes === null) {
90
+ return TIRTC_ERROR_INVALID_ARGUMENT;
91
+ }
92
+ const identity = this.ensureIdentity();
93
+ if (typeof identity === 'number') {
94
+ return identity;
95
+ }
96
+ return NativeTiRtc.connSendStreamMessage(
97
+ identity.objectId,
98
+ streamId,
99
+ timestampMs,
100
+ nativeBytes,
101
+ );
102
+ }
103
+
104
+ subscribeVideo(streamId: number): number {
105
+ return this.callWithStream(streamId, (identity) =>
106
+ NativeTiRtc.connSubscribeVideo(identity.objectId, streamId));
107
+ }
108
+
109
+ unsubscribeVideo(streamId: number): number {
110
+ return this.callWithStream(streamId, (identity) =>
111
+ NativeTiRtc.connUnsubscribeVideo(identity.objectId, streamId));
112
+ }
113
+
114
+ subscribeAudio(streamId: number): number {
115
+ return this.callWithStream(streamId, (identity) =>
116
+ NativeTiRtc.connSubscribeAudio(identity.objectId, streamId));
117
+ }
118
+
119
+ unsubscribeAudio(streamId: number): number {
120
+ return this.callWithStream(streamId, (identity) =>
121
+ NativeTiRtc.connUnsubscribeAudio(identity.objectId, streamId));
122
+ }
123
+
124
+ requestKeyFrame(streamId: number): number {
125
+ return this.callWithStream(streamId, (identity) =>
126
+ NativeTiRtc.connRequestKeyFrame(identity.objectId, streamId));
127
+ }
128
+
129
+ getMetricsSnapshot(): TiRtcConnMetricsResult {
130
+ const identity = this.ensureIdentity();
131
+ if (typeof identity === 'number') {
132
+ return {code: identity, snapshot: null};
133
+ }
134
+ return NativeTiRtc.connGetMetricsSnapshot(identity.objectId);
135
+ }
136
+
137
+ dispose(): number {
138
+ if (this.disposed) {
139
+ return TIRTC_ERROR_OK;
140
+ }
141
+ if (this.identity === null) {
142
+ this.disposed = true;
143
+ this.clearCallbacks();
144
+ return TIRTC_ERROR_OK;
145
+ }
146
+ const identity = this.identity;
147
+ const code = NativeTiRtc.connDispose(identity.objectId);
148
+ if (code === TIRTC_ERROR_OK) {
149
+ this.disposed = true;
150
+ this.identity = null;
151
+ unregisterNativeEventHandler(identity);
152
+ clearNativeIdentity(this);
153
+ this.clearCallbacks();
154
+ this.currentState = 'disconnected';
155
+ }
156
+ return code;
157
+ }
158
+
159
+ private callWithStream(streamId: number, operation: (identity: NativeIdentity) => number): number {
160
+ if (!isUInt8(streamId)) {
161
+ return TIRTC_ERROR_INVALID_ARGUMENT;
162
+ }
163
+ const identity = this.ensureIdentity();
164
+ if (typeof identity === 'number') {
165
+ return identity;
166
+ }
167
+ return operation(identity);
168
+ }
169
+
170
+ private ensureIdentity(): NativeIdentity | number {
171
+ const released = returnReleasedIfDisposed(this.disposed);
172
+ if (released !== null) {
173
+ return released;
174
+ }
175
+ if (this.identity !== null) {
176
+ return this.identity;
177
+ }
178
+ return this.createCode;
179
+ }
180
+
181
+ private adoptIdentity(identity: NativeIdentity): void {
182
+ this.identity = identity;
183
+ setNativeIdentity(this, identity);
184
+ registerNativeEventHandler(identity, (event) => this.handleEvent(event));
185
+ }
186
+
187
+ private clearCallbacks(): void {
188
+ this.onStateChanged = null;
189
+ this.onCommand = null;
190
+ this.onStreamMessage = null;
191
+ }
192
+
193
+ private handleEvent(event: NativeTiRtcEvent): void {
194
+ if (this.disposed) {
195
+ return;
196
+ }
197
+ switch (event.type) {
198
+ case 'connStateChanged':
199
+ if (event.state !== undefined && event.errorCode !== undefined) {
200
+ this.currentState = event.state as TiRtcConnState;
201
+ this.onStateChanged?.(this.currentState, event.errorCode);
202
+ }
203
+ break;
204
+ case 'connCommand':
205
+ if (event.commandId !== undefined) {
206
+ this.onCommand?.(event.commandId, fromNativeBytes(event.data));
207
+ }
208
+ break;
209
+ case 'connStreamMessage':
210
+ if (event.streamId !== undefined && event.timestampMs !== undefined) {
211
+ this.onStreamMessage?.(
212
+ event.streamId,
213
+ event.timestampMs,
214
+ fromNativeBytes(event.data),
215
+ );
216
+ }
217
+ break;
218
+ default:
219
+ break;
220
+ }
221
+ }
222
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,81 @@
1
+ export const TIRTC_ERROR_OK = 0;
2
+ export const TIRTC_ERROR_INVALID_ARGUMENT = 6000;
3
+ export const TIRTC_HOST_ERROR_OBJECT_RELEASED = 1008;
4
+
5
+ export type NativeCreateResultLike = Readonly<{
6
+ code: number;
7
+ objectId: number;
8
+ generation: number;
9
+ message: string | null;
10
+ }>;
11
+
12
+ export function returnReleasedIfDisposed(disposed: boolean): number | null {
13
+ return disposed ? TIRTC_HOST_ERROR_OBJECT_RELEASED : null;
14
+ }
15
+
16
+ export function normalizeCreateResult(result: NativeCreateResultLike): NativeCreateResultLike {
17
+ if (
18
+ result.code === TIRTC_ERROR_OK
19
+ && isPositiveInt32(result.objectId)
20
+ && isPositiveInt32(result.generation)
21
+ ) {
22
+ return result;
23
+ }
24
+ return {
25
+ code: result.code === TIRTC_ERROR_OK ? TIRTC_ERROR_INVALID_ARGUMENT : result.code,
26
+ objectId: 0,
27
+ generation: 0,
28
+ message: result.message ?? null,
29
+ };
30
+ }
31
+
32
+ export function isPlainObject(value: unknown): value is Record<string, unknown> {
33
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
34
+ }
35
+
36
+ export function isFiniteSafeInteger(value: unknown): value is number {
37
+ return typeof value === 'number' && Number.isFinite(value) && Number.isSafeInteger(value);
38
+ }
39
+
40
+ export function isUInt8(value: unknown): value is number {
41
+ return isFiniteSafeInteger(value) && value >= 0 && value <= 255;
42
+ }
43
+
44
+ export function isUInt32(value: unknown): value is number {
45
+ return isFiniteSafeInteger(value) && value >= 0 && value <= 4294967295;
46
+ }
47
+
48
+ export function isPositiveInt32(value: unknown): value is number {
49
+ return isFiniteSafeInteger(value) && value >= 1 && value <= 2147483647;
50
+ }
51
+
52
+ export function isPositiveInt32Size(value: unknown): value is number {
53
+ return isPositiveInt32(value);
54
+ }
55
+
56
+ export function toNativeBytes(data: unknown): ReadonlyArray<number> | null {
57
+ if (!(data instanceof Uint8Array)) {
58
+ return null;
59
+ }
60
+ const out: number[] = [];
61
+ for (let index = 0; index < data.length; index += 1) {
62
+ const value = data[index];
63
+ if (!isUInt8(value)) {
64
+ return null;
65
+ }
66
+ out.push(value);
67
+ }
68
+ return out;
69
+ }
70
+
71
+ export function fromNativeBytes(data: ReadonlyArray<number> | undefined): Uint8Array {
72
+ if (data === undefined) {
73
+ return new Uint8Array();
74
+ }
75
+ const out = new Uint8Array(data.length);
76
+ for (let index = 0; index < data.length; index += 1) {
77
+ const value = data[index];
78
+ out[index] = isUInt8(value) ? value : 0;
79
+ }
80
+ return out;
81
+ }
package/src/events.ts ADDED
@@ -0,0 +1,44 @@
1
+ import {NativeTiRtc, type NativeTiRtcEvent} from './native';
2
+ import {isPositiveInt32} from './errors';
3
+ import type {NativeIdentity} from './native_object_id';
4
+
5
+ type NativeEventHandler = (event: NativeTiRtcEvent) => void;
6
+
7
+ const handlers = new Map<string, NativeEventHandler>();
8
+ let subscription: {remove: () => void} | null = null;
9
+
10
+ function eventKey(identity: NativeIdentity): string {
11
+ return `${identity.objectId}:${identity.generation}`;
12
+ }
13
+
14
+ function ensureSubscribed(): void {
15
+ if (subscription !== null) {
16
+ return;
17
+ }
18
+ subscription = NativeTiRtc.onTiRtcEvent((event) => {
19
+ if (!isPositiveInt32(event.objectId) || !isPositiveInt32(event.generation)) {
20
+ return;
21
+ }
22
+ const handler = handlers.get(eventKey({
23
+ objectId: event.objectId,
24
+ generation: event.generation,
25
+ }));
26
+ if (handler !== undefined) {
27
+ handler(event);
28
+ return;
29
+ }
30
+ });
31
+ }
32
+
33
+ export function registerNativeEventHandler(identity: NativeIdentity, handler: NativeEventHandler): void {
34
+ handlers.set(eventKey(identity), handler);
35
+ ensureSubscribed();
36
+ }
37
+
38
+ export function unregisterNativeEventHandler(identity: NativeIdentity): void {
39
+ handlers.delete(eventKey(identity));
40
+ if (handlers.size === 0 && subscription !== null) {
41
+ subscription.remove();
42
+ subscription = null;
43
+ }
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,61 @@
1
+ export {
2
+ TiRtcOutputBufferStrategy,
3
+ TiRtcConnState,
4
+ TiRtcInputState,
5
+ TiRtcAudioCodec,
6
+ TiRtcAudioSampleRate,
7
+ TiRtcAudioChannelCount,
8
+ TiRtcAudioAecMode,
9
+ TiRtcAudioAgcLevel,
10
+ TiRtcAudioAnsLevel,
11
+ TiRtcVideoCodec,
12
+ TiRtcVideoEncoderCodec,
13
+ TiRtcVideoFrameRate,
14
+ TiRtcCameraFacing,
15
+ TiRtcVideoDecoderPreference,
16
+ TiRtcVideoDecoderBackend,
17
+ TiRtcVideoBitstreamFormat,
18
+ TiRtcAudioOutputState,
19
+ TiRtcVideoOutputState,
20
+ } from './types';
21
+ export type {
22
+ TiRtcSize,
23
+ TiRtcInitOptions,
24
+ TiRtcAudioOutputOptions,
25
+ TiRtcVideoOutputOptions,
26
+ TiRtcVideoOutputViewProps,
27
+ TiRtcAudioInputOptions,
28
+ TiRtcVideoInputOptions,
29
+ TiRtcVideoInputPreviewProps,
30
+ TiRtcOnConnStateChanged,
31
+ TiRtcOnConnCommand,
32
+ TiRtcOnConnStreamMessage,
33
+ TiRtcOnAudioOutputStateChanged,
34
+ TiRtcOnAudioOutputError,
35
+ TiRtcOnVideoOutputStateChanged,
36
+ TiRtcOnVideoOutputRenderSizeChanged,
37
+ TiRtcOnVideoOutputError,
38
+ TiRtcOnInputStateChanged,
39
+ TiRtcOnInputError,
40
+ TiRtcOnVideoInputActualConfigChanged,
41
+ TiRtcConnMetricsResult,
42
+ TiRtcConnMetricsSnapshot,
43
+ TiRtcOutputStartupMetrics,
44
+ TiRtcOutputStutterMetrics,
45
+ TiRtcAudioOutputMetricsResult,
46
+ TiRtcAudioOutputMetricsSnapshot,
47
+ TiRtcVideoOutputMetricsResult,
48
+ TiRtcVideoOutputMetricsSnapshot,
49
+ TiRtcAudioOutputDebugSnapshotResult,
50
+ TiRtcAudioOutputDebugSnapshot,
51
+ TiRtcVideoOutputDebugSnapshotResult,
52
+ TiRtcVideoOutputDebugSnapshot,
53
+ TiRtcLoggingUploadResult,
54
+ } from './types';
55
+ export {TiRtc} from './runtime';
56
+ export {TiRtcConn} from './conn';
57
+ export {TiRtcAudioOutput} from './audio_output';
58
+ export {TiRtcVideoOutput, TiRtcVideoOutputView} from './video_output';
59
+ export {TiRtcAudioInput} from './audio_input';
60
+ export {TiRtcVideoInput, TiRtcVideoInputPreview} from './video_input';
61
+ export {TiRtcLogging} from './logging';
package/src/logging.ts ADDED
@@ -0,0 +1,33 @@
1
+ import {NativeTiRtc} from './native';
2
+ import type {TiRtcLoggingUploadResult} from './types';
3
+
4
+ const LogLevel = {
5
+ debug: 0,
6
+ info: 1,
7
+ warn: 2,
8
+ error: 3,
9
+ } as const;
10
+
11
+ export class TiRtcLogging {
12
+ private constructor() {}
13
+
14
+ static d(tag: string, message: string): void {
15
+ NativeTiRtc.writeLog(LogLevel.debug, tag, message);
16
+ }
17
+
18
+ static i(tag: string, message: string): void {
19
+ NativeTiRtc.writeLog(LogLevel.info, tag, message);
20
+ }
21
+
22
+ static w(tag: string, message: string): void {
23
+ NativeTiRtc.writeLog(LogLevel.warn, tag, message);
24
+ }
25
+
26
+ static e(tag: string, message: string): void {
27
+ NativeTiRtc.writeLog(LogLevel.error, tag, message);
28
+ }
29
+
30
+ static upload(): Promise<TiRtcLoggingUploadResult> {
31
+ return NativeTiRtc.uploadLogs();
32
+ }
33
+ }
package/src/native.ts ADDED
@@ -0,0 +1,6 @@
1
+ import NativeTiRtc from './specs/NativeTiRtc';
2
+ import NativeTiRtcVideoInputPreview from './specs/TiRtcVideoInputPreviewNativeComponent';
3
+ import NativeTiRtcVideoOutputView from './specs/TiRtcVideoOutputViewNativeComponent';
4
+
5
+ export {NativeTiRtc, NativeTiRtcVideoOutputView, NativeTiRtcVideoInputPreview};
6
+ export type {NativeTiRtcEvent} from './specs/NativeTiRtc';