@signalapp/ringrtc 2.72.0 → 2.73.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.
@@ -669,7 +669,7 @@ For more information on this, and how to apply and follow the GNU AGPL, see
669
669
 
670
670
  ```
671
671
 
672
- ## libsignal-account-keys 0.1.0, libsignal-core 0.1.0, libsignal-debug 0.99.1, mrp 2.72.0, protobuf 2.72.0, ringrtc 2.72.0, regex-aot 0.1.0, partial-default-derive 0.1.0, partial-default 0.1.0
672
+ ## libsignal-account-keys 0.1.0, libsignal-core 0.1.0, libsignal-debug 0.99.1, mrp 2.73.0, protobuf 2.73.0, ringrtc 2.73.0, regex-aot 0.1.0, partial-default-derive 0.1.0, partial-default 0.1.0
673
673
 
674
674
  ```
675
675
  GNU AFFERO GENERAL PUBLIC LICENSE
@@ -7457,103 +7457,6 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
7457
7457
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
7458
7458
  SOFTWARE.
7459
7459
 
7460
- ```
7461
-
7462
- ## portaudio
7463
-
7464
- ```
7465
- /*
7466
- * $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
7467
- * Portable Audio I/O Library
7468
- * Memory barrier utilities
7469
- *
7470
- * Author: Bjorn Roche, XO Audio, LLC
7471
- *
7472
- * This program uses the PortAudio Portable Audio Library.
7473
- * For more information see: http://www.portaudio.com
7474
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
7475
- *
7476
- * Permission is hereby granted, free of charge, to any person obtaining
7477
- * a copy of this software and associated documentation files
7478
- * (the "Software"), to deal in the Software without restriction,
7479
- * including without limitation the rights to use, copy, modify, merge,
7480
- * publish, distribute, sublicense, and/or sell copies of the Software,
7481
- * and to permit persons to whom the Software is furnished to do so,
7482
- * subject to the following conditions:
7483
- *
7484
- * The above copyright notice and this permission notice shall be
7485
- * included in all copies or substantial portions of the Software.
7486
- *
7487
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
7488
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7489
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7490
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
7491
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
7492
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
7493
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7494
- */
7495
-
7496
- /*
7497
- * The text above constitutes the entire PortAudio license; however,
7498
- * the PortAudio community also makes the following non-binding requests:
7499
- *
7500
- * Any person wishing to distribute modifications to the Software is
7501
- * requested to send the modifications to the original developer so that
7502
- * they can be incorporated into the canonical version. It is also
7503
- * requested that these non-binding requests be included along with the
7504
- * license above.
7505
- */
7506
-
7507
- /*
7508
- * $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
7509
- * Portable Audio I/O Library
7510
- * Ring Buffer utility.
7511
- *
7512
- * Author: Phil Burk, http://www.softsynth.com
7513
- * modified for SMP safety on Mac OS X by Bjorn Roche
7514
- * modified for SMP safety on Linux by Leland Lucius
7515
- * also, allowed for const where possible
7516
- * modified for multiple-byte-sized data elements by Sven Fischer
7517
- *
7518
- * Note that this is safe only for a single-thread reader and a
7519
- * single-thread writer.
7520
- *
7521
- * This program uses the PortAudio Portable Audio Library.
7522
- * For more information see: http://www.portaudio.com
7523
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
7524
- *
7525
- * Permission is hereby granted, free of charge, to any person obtaining
7526
- * a copy of this software and associated documentation files
7527
- * (the "Software"), to deal in the Software without restriction,
7528
- * including without limitation the rights to use, copy, modify, merge,
7529
- * publish, distribute, sublicense, and/or sell copies of the Software,
7530
- * and to permit persons to whom the Software is furnished to do so,
7531
- * subject to the following conditions:
7532
- *
7533
- * The above copyright notice and this permission notice shall be
7534
- * included in all copies or substantial portions of the Software.
7535
- *
7536
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
7537
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7538
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
7539
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
7540
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
7541
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
7542
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7543
- */
7544
-
7545
- /*
7546
- * The text above constitutes the entire PortAudio license; however,
7547
- * the PortAudio community also makes the following non-binding requests:
7548
- *
7549
- * Any person wishing to distribute modifications to the Software is
7550
- * requested to send the modifications to the original developer so that
7551
- * they can be incorporated into the canonical version. It is also
7552
- * requested that these non-binding requests be included along with the
7553
- * license above.
7554
- */
7555
-
7556
-
7557
7460
  ```
7558
7461
 
7559
7462
  ## protobuf
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { RingRTCType } from './ringrtc/Service';
2
- export type { AudioDevice, CallId, CallSettings, DeviceId, GroupCallObserver, GroupCallSvcConfig, HttpResult, PeekDeviceInfo, PeekInfo, Reaction, UserId, VideoFrameSender, VideoFrameSource, } from './ringrtc/Service';
3
- export { AnswerMessage, DataMode, BusyMessage, Call, CallEndReason, CallLogLevel, CallMessageUrgency, CallRejectReason, CallState, CallingMessage, ConnectionState, GroupCall, GroupCallKind, GroupMemberInfo, HangupMessage, HangupType, HttpMethod, IceCandidateMessage, JoinState, LocalDeviceState, OfferMessage, OfferType, OpaqueMessage, PeekStatusCodes, RemoteDeviceState, RingCancelReason, RingRTCType, RingUpdate, SpeechEvent, VideoPixelFormatEnum, videoPixelFormatToEnum, VideoRequest, callIdFromEra, callIdFromRingId, } from './ringrtc/Service';
2
+ export type { AudioDevice, AudioDeviceInitError, AudioDeviceList, WindowsDefaultAudioDevices, NonWindowsDefaultAudioDevice, CallId, CallSettings, DeviceId, GroupCallObserver, GroupCallSvcConfig, HttpResult, PeekDeviceInfo, PeekInfo, Reaction, UserId, VideoFrameSender, VideoFrameSource, } from './ringrtc/Service';
3
+ export { AnswerMessage, DataMode, BusyMessage, Call, CallEndReason, CallLogLevel, CallMessageUrgency, CallRejectReason, CallState, CallingMessage, ConnectionState, GroupCall, GroupCallKind, GroupMemberInfo, HangupMessage, HangupType, HttpMethod, IceCandidateMessage, JoinState, LocalDeviceState, OfferMessage, OfferType, OpaqueMessage, PeekStatusCodes, RemoteDeviceState, RingCancelReason, RingRTCType, RingUpdate, SpeechEvent, VideoPixelFormatEnum, videoPixelFormatToEnum, VideoRequest, callIdFromEra, callIdFromRingId, cleanAudioDeviceForLogging, cleanAudioDeviceListForLogging, truncateForLogging, } from './ringrtc/Service';
4
4
  export { CallLinkRootKey, CallLinkRestrictions, CallLinkState, } from './ringrtc/CallLinks';
5
5
  export { CallSummary, QualityStats } from './ringrtc/CallSummary';
6
6
  export declare const RingRTC: RingRTCType;
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // SPDX-License-Identifier: AGPL-3.0-only
5
5
  //
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.RingRTC = exports.QualityStats = exports.CallSummary = exports.CallLinkState = exports.CallLinkRestrictions = exports.CallLinkRootKey = exports.callIdFromRingId = exports.callIdFromEra = exports.VideoRequest = exports.videoPixelFormatToEnum = exports.VideoPixelFormatEnum = exports.SpeechEvent = exports.RingUpdate = exports.RingRTCType = exports.RingCancelReason = exports.RemoteDeviceState = exports.PeekStatusCodes = exports.OpaqueMessage = exports.OfferType = exports.OfferMessage = exports.LocalDeviceState = exports.JoinState = exports.IceCandidateMessage = exports.HttpMethod = exports.HangupType = exports.HangupMessage = exports.GroupMemberInfo = exports.GroupCallKind = exports.GroupCall = exports.ConnectionState = exports.CallingMessage = exports.CallState = exports.CallRejectReason = exports.CallMessageUrgency = exports.CallLogLevel = exports.CallEndReason = exports.Call = exports.BusyMessage = exports.DataMode = exports.AnswerMessage = void 0;
7
+ exports.RingRTC = exports.QualityStats = exports.CallSummary = exports.CallLinkState = exports.CallLinkRestrictions = exports.CallLinkRootKey = exports.truncateForLogging = exports.cleanAudioDeviceListForLogging = exports.cleanAudioDeviceForLogging = exports.callIdFromRingId = exports.callIdFromEra = exports.VideoRequest = exports.videoPixelFormatToEnum = exports.VideoPixelFormatEnum = exports.SpeechEvent = exports.RingUpdate = exports.RingRTCType = exports.RingCancelReason = exports.RemoteDeviceState = exports.PeekStatusCodes = exports.OpaqueMessage = exports.OfferType = exports.OfferMessage = exports.LocalDeviceState = exports.JoinState = exports.IceCandidateMessage = exports.HttpMethod = exports.HangupType = exports.HangupMessage = exports.GroupMemberInfo = exports.GroupCallKind = exports.GroupCall = exports.ConnectionState = exports.CallingMessage = exports.CallState = exports.CallRejectReason = exports.CallMessageUrgency = exports.CallLogLevel = exports.CallEndReason = exports.Call = exports.BusyMessage = exports.DataMode = exports.AnswerMessage = void 0;
8
8
  const Service_1 = require("./ringrtc/Service");
9
9
  var Service_2 = require("./ringrtc/Service");
10
10
  Object.defineProperty(exports, "AnswerMessage", { enumerable: true, get: function () { return Service_2.AnswerMessage; } });
@@ -41,6 +41,9 @@ Object.defineProperty(exports, "videoPixelFormatToEnum", { enumerable: true, get
41
41
  Object.defineProperty(exports, "VideoRequest", { enumerable: true, get: function () { return Service_2.VideoRequest; } });
42
42
  Object.defineProperty(exports, "callIdFromEra", { enumerable: true, get: function () { return Service_2.callIdFromEra; } });
43
43
  Object.defineProperty(exports, "callIdFromRingId", { enumerable: true, get: function () { return Service_2.callIdFromRingId; } });
44
+ Object.defineProperty(exports, "cleanAudioDeviceForLogging", { enumerable: true, get: function () { return Service_2.cleanAudioDeviceForLogging; } });
45
+ Object.defineProperty(exports, "cleanAudioDeviceListForLogging", { enumerable: true, get: function () { return Service_2.cleanAudioDeviceListForLogging; } });
46
+ Object.defineProperty(exports, "truncateForLogging", { enumerable: true, get: function () { return Service_2.truncateForLogging; } });
44
47
  var CallLinks_1 = require("./ringrtc/CallLinks");
45
48
  Object.defineProperty(exports, "CallLinkRootKey", { enumerable: true, get: function () { return CallLinks_1.CallLinkRootKey; } });
46
49
  Object.defineProperty(exports, "CallLinkRestrictions", { enumerable: true, get: function () { return CallLinks_1.CallLinkRestrictions; } });
@@ -76,6 +76,11 @@ type RawCallLinkState = {
76
76
  expiration: Date;
77
77
  rootKey: Uint8Array<ArrayBuffer>;
78
78
  };
79
+ export declare class AudioDeviceInitError extends Error {
80
+ #private;
81
+ constructor(device?: AudioDevice);
82
+ get audioDevice(): AudioDevice | undefined;
83
+ }
79
84
  export type EmptyObj = Record<PropertyKey, never>;
80
85
  export type HttpResult<T> = {
81
86
  success: true;
@@ -91,13 +96,16 @@ export declare class RingRTCType {
91
96
  private readonly _peekRequests;
92
97
  private readonly _callLinkRequests;
93
98
  private readonly _emptyRequests;
99
+ private readonly _audioDeviceRequests;
94
100
  private readonly _callInfoByCallId;
95
101
  private getCallInfoKey;
96
102
  handleOutgoingSignaling: ((remoteUserId: UserId, message: CallingMessage) => Promise<boolean>) | null;
97
103
  handleIncomingCall: ((call: Call) => Promise<boolean>) | null;
98
104
  handleStartCall: ((call: Call) => Promise<boolean>) | null;
99
- handleOutputDeviceChanged: ((devices: Array<AudioDevice>) => Promise<void>) | null;
100
- handleInputDeviceChanged: ((devices: Array<AudioDevice>) => Promise<void>) | null;
105
+ handleOutputDeviceChanged: ((devices: AudioDeviceList) => Promise<void>) | null;
106
+ handleInputDeviceChanged: ((devices: AudioDeviceList) => Promise<void>) | null;
107
+ handleSettleStartPlayback: ((success: boolean, device: AudioDevice | undefined) => Promise<void>) | null;
108
+ handleSettleStartRecording: ((success: boolean, device: AudioDevice | undefined) => Promise<void>) | null;
101
109
  handleRejectedIncomingCallRequest: ((callId: CallId, remoteUserId: UserId, reason: CallRejectReason, ageSec: number, wasVideoCall: boolean, receivedAtCounter: number | undefined, receivedAtDate: number | undefined) => void) | null;
102
110
  handleLogMessage: ((level: CallLogLevel, fileName: string, line: number, message: string) => void) | null;
103
111
  handleSendHttpRequest: ((requestId: number, url: string, method: HttpMethod, headers: {
@@ -241,7 +249,7 @@ export declare class RingRTCType {
241
249
  getGroupCall(groupId: GroupId, sfuUrl: string, hkdfExtraInfo: Uint8Array<ArrayBuffer>, audioLevelsIntervalMillis: number | undefined, dredDuration: number | undefined, svcConfig: GroupCallSvcConfig | undefined, observer: GroupCallObserver): GroupCall | undefined;
242
250
  getCallLinkCall(sfuUrl: string, endorsementPublicKey: Uint8Array<ArrayBuffer>, authCredentialPresentation: Uint8Array<ArrayBuffer>, rootKey: CallLinkRootKey, adminPasskey: Uint8Array<ArrayBuffer> | undefined, hkdfExtraInfo: Uint8Array<ArrayBuffer>, audioLevelsIntervalMillis: number | undefined, dredDuration: number | undefined, svcConfig: GroupCallSvcConfig | undefined, observer: GroupCallObserver): GroupCall | undefined;
243
251
  peekGroupCall(sfuUrl: string, membershipProof: Uint8Array<ArrayBuffer>, groupMembers: Array<GroupMemberInfo>): Promise<PeekInfo>;
244
- setMicrophoneWarmupEnabled(warmup: boolean): void;
252
+ setMicrophoneWarmupEnabled(warmup: boolean): Promise<AudioDevice | undefined>;
245
253
  peekCallLinkCall(sfuUrl: string, authCredentialPresentation: Uint8Array<ArrayBuffer>, rootKey: CallLinkRootKey): Promise<HttpResult<PeekInfo>>;
246
254
  requestMembershipProof(clientId: GroupCallClientId): void;
247
255
  requestGroupMembers(clientId: GroupCallClientId): void;
@@ -263,8 +271,11 @@ export declare class RingRTCType {
263
271
  handleSpeechEvent(clientId: GroupCallClientId, event: SpeechEvent): void;
264
272
  onRemoteMute(clientId: GroupCallClientId, demuxId: number): void;
265
273
  onObservedRemoteMute(clientId: GroupCallClientId, sourceDemuxId: number, targetDemuxId: number): void;
266
- onOutputDeviceChanged(devices: Array<AudioDevice>): void;
267
- onInputDeviceChanged(devices: Array<AudioDevice>): void;
274
+ onOutputDeviceChanged(devices: AudioDeviceList): void;
275
+ onInputDeviceChanged(devices: AudioDeviceList): void;
276
+ onSettleStartPlayback(success: boolean, device: AudioDevice | undefined): void;
277
+ onSettleAudioPromise(success: boolean, device: AudioDevice | undefined, requestId: number): void;
278
+ onSettleStartRecording(success: boolean, device: AudioDevice | undefined): void;
268
279
  onLogMessage(level: number, fileName: string, line: number, message: string): void;
269
280
  logError(message: string): void;
270
281
  logWarn(message: string): void;
@@ -295,10 +306,10 @@ export declare class RingRTCType {
295
306
  decline(callId: CallId): void;
296
307
  ignore(callId: CallId): void;
297
308
  hangup(callId: CallId): void;
298
- getAudioInputs(): Array<AudioDevice>;
299
- setAudioInput(index: number): void;
300
- getAudioOutputs(): Array<AudioDevice>;
301
- setAudioOutput(index: number): void;
309
+ getAudioInputs(): AudioDeviceList | undefined;
310
+ setAudioInputById(id: string): Promise<AudioDevice | undefined>;
311
+ getAudioOutputs(): AudioDeviceList | undefined;
312
+ setAudioOutputById(id: string): Promise<AudioDevice | undefined>;
302
313
  /**
303
314
  * Enables or disables different voice processing techniques including:
304
315
  * - Acoustic Echo Cancellation (AEC)
@@ -309,7 +320,7 @@ export declare class RingRTCType {
309
320
  *
310
321
  * @param enabled - whether to enable voice processing
311
322
  */
312
- setVoiceProcessingEnabled(enabled: boolean): void;
323
+ setVoiceProcessingEnabled(enabled: boolean): Promise<AudioDevice | undefined>;
313
324
  }
314
325
  type CallConfig = {
315
326
  dataMode: DataMode;
@@ -337,15 +348,30 @@ type IceServer = {
337
348
  };
338
349
  export type AudioDevice = {
339
350
  name: string;
340
- index: number;
341
351
  uniqueId: string;
342
- i18nKey?: string;
352
+ };
353
+ export type WindowsDefaultAudioDevices = {
354
+ isWindows: true;
355
+ communicationsDevice: AudioDevice | undefined;
356
+ consoleDevice: AudioDevice | undefined;
357
+ };
358
+ export type NonWindowsDefaultAudioDevice = {
359
+ isWindows: false;
360
+ device: AudioDevice | undefined;
361
+ };
362
+ export type AudioDeviceList = {
363
+ devices: Array<AudioDevice>;
364
+ defaults: WindowsDefaultAudioDevices | NonWindowsDefaultAudioDevice;
343
365
  };
344
366
  export declare enum VideoPixelFormatEnum {
345
367
  I420 = 0,
346
368
  Nv12 = 1,
347
369
  Rgba = 2
348
370
  }
371
+ export declare function truncateForLogging(name: string | undefined): string;
372
+ export declare function cleanAudioDeviceForLogging(device: AudioDevice): AudioDevice;
373
+ export declare function cleanAudioDeviceForLogging(device: AudioDevice | undefined): AudioDevice | undefined;
374
+ export declare function cleanAudioDeviceListForLogging(deviceList: AudioDeviceList): AudioDeviceList;
349
375
  export declare function videoPixelFormatToEnum(format: VideoPixelFormat): VideoPixelFormatEnum | undefined;
350
376
  /**
351
377
  * Interface for sending video frames to the RingRTC library.
@@ -681,7 +707,7 @@ export type CallManager = {
681
707
  signalingMessageSent(callId: CallId): void;
682
708
  signalingMessageSendFailed(callId: CallId): void;
683
709
  setOutgoingAudioEnabled(enabled: boolean): void;
684
- setMicrophoneWarmupEnabled(enabled: boolean): void;
710
+ setMicrophoneWarmupEnabled(enabled: boolean, requestId: number): void;
685
711
  setOutgoingVideoEnabled(enabled: boolean): void;
686
712
  setOutgoingVideoIsScreenShare(enabled: boolean): void;
687
713
  updateDataMode(dataMode: DataMode): void;
@@ -728,11 +754,11 @@ export type CallManager = {
728
754
  deleteCallLink(requestId: number, sfuUrl: string, authCredentialPresentation: Uint8Array<ArrayBuffer>, linkRootKey: Uint8Array<ArrayBuffer>, adminPasskey: Uint8Array<ArrayBuffer>): void;
729
755
  peekGroupCall(requestId: number, sfu_url: string, membership_proof: Uint8Array<ArrayBuffer>, group_members: Array<GroupMemberInfo>): void;
730
756
  peekCallLinkCall(requestId: number, sfuUrl: string, authCredentialPresentation: Uint8Array<ArrayBuffer>, linkRootKey: Uint8Array<ArrayBuffer>): void;
731
- getAudioInputs(): Array<AudioDevice>;
732
- setAudioInput(index: number): void;
733
- getAudioOutputs(): Array<AudioDevice>;
734
- setAudioOutput(index: number): void;
735
- setVoiceProcessingEnabled(enabled: boolean): void;
757
+ getAudioInputs(): AudioDeviceList | undefined;
758
+ setAudioInputById(id: string, requestId: number): void;
759
+ getAudioOutputs(): AudioDeviceList | undefined;
760
+ setAudioOutputById(id: string, requestId: number): void;
761
+ setVoiceProcessingEnabled(enabled: boolean, requestId: number): void;
736
762
  };
737
763
  export type CallManagerCallbacks = {
738
764
  onStartOutgoingCall(remoteUserId: UserId, callId: CallId): void;
@@ -3,12 +3,27 @@
3
3
  // Copyright 2019-2021 Signal Messenger, LLC
4
4
  // SPDX-License-Identifier: AGPL-3.0-only
5
5
  //
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
13
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
14
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
15
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
16
+ };
6
17
  var __importDefault = (this && this.__importDefault) || function (mod) {
7
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
8
19
  };
20
+ var _AudioDeviceInitError_audioDevice;
9
21
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.CallLogLevel = exports.CallRejectReason = exports.CallEndReason = exports.CallState = exports.RingCancelReason = exports.DataMode = exports.HangupType = exports.OpaqueMessage = exports.HangupMessage = exports.BusyMessage = exports.IceCandidateMessage = exports.AnswerMessage = exports.OfferType = exports.OfferMessage = exports.CallingMessage = exports.GroupCall = exports.GroupCallKind = exports.VideoRequest = exports.GroupMemberInfo = exports.RemoteDeviceState = exports.LocalDeviceState = exports.HttpMethod = exports.RingUpdate = exports.CallMessageUrgency = exports.SpeechEvent = exports.JoinState = exports.ConnectionState = exports.Call = exports.VideoPixelFormatEnum = exports.RingRTCType = exports.ReceivedAudioLevel = exports.NetworkRoute = exports.PeekStatusCodes = exports.callIdFromEra = void 0;
22
+ exports.CallLogLevel = exports.CallRejectReason = exports.CallEndReason = exports.CallState = exports.RingCancelReason = exports.DataMode = exports.HangupType = exports.OpaqueMessage = exports.HangupMessage = exports.BusyMessage = exports.IceCandidateMessage = exports.AnswerMessage = exports.OfferType = exports.OfferMessage = exports.CallingMessage = exports.GroupCall = exports.GroupCallKind = exports.VideoRequest = exports.GroupMemberInfo = exports.RemoteDeviceState = exports.LocalDeviceState = exports.HttpMethod = exports.RingUpdate = exports.CallMessageUrgency = exports.SpeechEvent = exports.JoinState = exports.ConnectionState = exports.Call = exports.VideoPixelFormatEnum = exports.RingRTCType = exports.AudioDeviceInitError = exports.ReceivedAudioLevel = exports.NetworkRoute = exports.PeekStatusCodes = exports.callIdFromEra = void 0;
11
23
  exports.callIdFromRingId = callIdFromRingId;
24
+ exports.truncateForLogging = truncateForLogging;
25
+ exports.cleanAudioDeviceForLogging = cleanAudioDeviceForLogging;
26
+ exports.cleanAudioDeviceListForLogging = cleanAudioDeviceListForLogging;
12
27
  exports.videoPixelFormatToEnum = videoPixelFormatToEnum;
13
28
  const CallLinks_1 = require("./CallLinks");
14
29
  const Native_1 = __importDefault(require("./Native"));
@@ -31,7 +46,8 @@ class NativeCallManager {
31
46
  const fieldTrials = {
32
47
  'RingRTC-AnyAddressPortsKillSwitch': 'Enabled',
33
48
  'RingRTC-PruneTurnPorts': 'Enabled',
34
- 'WebRTC-Bwe-ProbingConfiguration': 'skip_if_est_larger_than_fraction_of_max:0.99',
49
+ 'WebRTC-Audio-NetEqSmartFlushing': 'enabled:false',
50
+ 'WebRTC-Bwe-ProbingConfiguration': 'skip_if_est_larger_than_fraction_of_max:0.99,probe_max_allocation_without_alr:false',
35
51
  'WebRTC-IncreaseIceCandidatePriorityHostSrflx': 'Enabled',
36
52
  ...config.field_trials,
37
53
  };
@@ -138,10 +154,12 @@ NativeCallManager.prototype.peekGroupCall = Native_1.default.cm_peekGroupCall;
138
154
  NativeCallManager.prototype.peekCallLinkCall =
139
155
  Native_1.default.cm_peekCallLinkCall;
140
156
  NativeCallManager.prototype.getAudioInputs = Native_1.default.cm_getAudioInputs;
141
- NativeCallManager.prototype.setAudioInput = Native_1.default.cm_setAudioInput;
157
+ NativeCallManager.prototype.setAudioInputById =
158
+ Native_1.default.cm_setAudioInputById;
142
159
  NativeCallManager.prototype.getAudioOutputs =
143
160
  Native_1.default.cm_getAudioOutputs;
144
- NativeCallManager.prototype.setAudioOutput = Native_1.default.cm_setAudioOutput;
161
+ NativeCallManager.prototype.setAudioOutputById =
162
+ Native_1.default.cm_setAudioOutputById;
145
163
  NativeCallManager.prototype.setVoiceProcessingEnabled =
146
164
  Native_1.default.cm_setVoiceProcessingEnabled;
147
165
  NativeCallManager.prototype.processEvents = Native_1.default.cm_processEvents;
@@ -240,16 +258,28 @@ class Requests {
240
258
  this._resolveById.delete(id);
241
259
  return true;
242
260
  }
243
- reject(id) {
261
+ reject(id, error) {
244
262
  const callbacks = this._resolveById.get(id);
245
263
  if (!callbacks) {
246
264
  return false;
247
265
  }
248
- callbacks[1]();
266
+ callbacks[1](error);
249
267
  this._resolveById.delete(id);
250
268
  return true;
251
269
  }
252
270
  }
271
+ class AudioDeviceInitError extends Error {
272
+ constructor(device) {
273
+ super(`AudioDeviceInitError: ${JSON.stringify(cleanAudioDeviceForLogging(device))}`);
274
+ _AudioDeviceInitError_audioDevice.set(this, void 0);
275
+ __classPrivateFieldSet(this, _AudioDeviceInitError_audioDevice, device, "f");
276
+ }
277
+ get audioDevice() {
278
+ return __classPrivateFieldGet(this, _AudioDeviceInitError_audioDevice, "f");
279
+ }
280
+ }
281
+ exports.AudioDeviceInitError = AudioDeviceInitError;
282
+ _AudioDeviceInitError_audioDevice = new WeakMap();
253
283
  class CallInfo {
254
284
  constructor(isVideoCall, receivedAtCounter, receivedAtDate) {
255
285
  this.isVideoCall = isVideoCall;
@@ -268,6 +298,8 @@ class RingRTCType {
268
298
  this.handleStartCall = null;
269
299
  this.handleOutputDeviceChanged = null;
270
300
  this.handleInputDeviceChanged = null;
301
+ this.handleSettleStartPlayback = null;
302
+ this.handleSettleStartRecording = null;
271
303
  this.handleRejectedIncomingCallRequest = null;
272
304
  this.handleLogMessage = null;
273
305
  this.handleSendHttpRequest = null;
@@ -282,6 +314,7 @@ class RingRTCType {
282
314
  this._peekRequests = new Requests();
283
315
  this._callLinkRequests = new Requests();
284
316
  this._emptyRequests = new Requests();
317
+ this._audioDeviceRequests = new Requests();
285
318
  this._callInfoByCallId = new Map();
286
319
  }
287
320
  setConfig(config) {
@@ -307,9 +340,7 @@ class RingRTCType {
307
340
  }
308
341
  // Called by UX
309
342
  cancelGroupRing(groupId, ringId, reason) {
310
- sillyDeadlockProtection(() => {
311
- this.callManager.cancelGroupRing(groupId, ringId.toString(), reason);
312
- });
343
+ this.callManager.cancelGroupRing(groupId, ringId.toString(), reason);
313
344
  }
314
345
  // Called by Rust
315
346
  onStartOutgoingCall(remoteUserId, callId) {
@@ -389,15 +420,13 @@ class RingRTCType {
389
420
  });
390
421
  }
391
422
  proceed(callId, settings) {
392
- sillyDeadlockProtection(() => {
393
- this.callManager.proceed(callId, settings.iceServers, settings.hideIp, {
394
- dataMode: settings.dataMode,
395
- dredDuration: settings.dredDuration ?? 0,
396
- enableVp9Encode: settings.enableVp9Encode ?? true,
397
- enableVp9Decode: settings.enableVp9Decode ?? true,
398
- statsIntervalSecs: settings.statsIntervalSecs,
399
- }, settings.audioLevelsIntervalMillis || 0);
400
- });
423
+ this.callManager.proceed(callId, settings.iceServers, settings.hideIp, {
424
+ dataMode: settings.dataMode,
425
+ dredDuration: settings.dredDuration ?? 0,
426
+ enableVp9Encode: settings.enableVp9Encode ?? true,
427
+ enableVp9Decode: settings.enableVp9Decode ?? true,
428
+ statsIntervalSecs: settings.statsIntervalSecs,
429
+ }, settings.audioLevelsIntervalMillis || 0);
401
430
  }
402
431
  // Called by Rust
403
432
  onCallState(remoteUserId, state) {
@@ -587,9 +616,12 @@ class RingRTCType {
587
616
  readCallLink(sfuUrl, authCredentialPresentation, linkRootKey) {
588
617
  const [requestId, promise] = this._callLinkRequests.add();
589
618
  // Response comes back via handleCallLinkResponse
590
- sillyDeadlockProtection(() => {
619
+ try {
591
620
  this.callManager.readCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes);
592
- });
621
+ }
622
+ catch (e) {
623
+ this._callLinkRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
624
+ }
593
625
  return promise;
594
626
  }
595
627
  /**
@@ -631,9 +663,12 @@ class RingRTCType {
631
663
  createCallLink(sfuUrl, createCredentialPresentation, linkRootKey, adminPasskey, callLinkPublicParams, restrictions) {
632
664
  const [requestId, promise] = this._callLinkRequests.add();
633
665
  // Response comes back via handleCallLinkResponse
634
- sillyDeadlockProtection(() => {
666
+ try {
635
667
  this.callManager.createCallLink(requestId, sfuUrl, createCredentialPresentation, linkRootKey.bytes, adminPasskey, callLinkPublicParams, restrictions);
636
- });
668
+ }
669
+ catch (e) {
670
+ this._callLinkRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
671
+ }
637
672
  return promise;
638
673
  }
639
674
  /**
@@ -654,9 +689,12 @@ class RingRTCType {
654
689
  updateCallLinkName(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey, newName) {
655
690
  const [requestId, promise] = this._callLinkRequests.add();
656
691
  // Response comes back via handleCallLinkResponse
657
- sillyDeadlockProtection(() => {
692
+ try {
658
693
  this.callManager.updateCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey, newName, undefined, undefined);
659
- });
694
+ }
695
+ catch (e) {
696
+ this._callLinkRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
697
+ }
660
698
  return promise;
661
699
  }
662
700
  /**
@@ -678,9 +716,12 @@ class RingRTCType {
678
716
  updateCallLinkRestrictions(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey, restrictions) {
679
717
  const [requestId, promise] = this._callLinkRequests.add();
680
718
  // Response comes back via handleCallLinkResponse
681
- sillyDeadlockProtection(() => {
719
+ try {
682
720
  this.callManager.updateCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey, undefined, restrictions, undefined);
683
- });
721
+ }
722
+ catch (e) {
723
+ this._callLinkRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
724
+ }
684
725
  return promise;
685
726
  }
686
727
  /**
@@ -700,33 +741,32 @@ class RingRTCType {
700
741
  deleteCallLink(sfuUrl, authCredentialPresentation, linkRootKey, adminPasskey) {
701
742
  const [requestId, promise] = this._emptyRequests.add();
702
743
  // Response comes back via handleCallLinkResponse
703
- sillyDeadlockProtection(() => {
744
+ try {
704
745
  this.callManager.deleteCallLink(requestId, sfuUrl, authCredentialPresentation, linkRootKey.bytes, adminPasskey);
705
- });
746
+ }
747
+ catch (e) {
748
+ this._emptyRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
749
+ }
706
750
  return promise;
707
751
  }
708
752
  // HTTP callbacks
709
753
  receivedHttpResponse(requestId, status, body) {
710
- sillyDeadlockProtection(() => {
711
- try {
712
- this.callManager.receivedHttpResponse(requestId, status, body);
713
- }
714
- catch {
715
- // We may not have an active connection any more.
716
- // In which case it doesn't matter
717
- }
718
- });
754
+ try {
755
+ this.callManager.receivedHttpResponse(requestId, status, body);
756
+ }
757
+ catch {
758
+ // We may not have an active connection any more.
759
+ // In which case it doesn't matter
760
+ }
719
761
  }
720
762
  httpRequestFailed(requestId, debugInfo) {
721
- sillyDeadlockProtection(() => {
722
- try {
723
- this.callManager.httpRequestFailed(requestId, debugInfo);
724
- }
725
- catch {
726
- // We may not have an active connection any more.
727
- // In which case it doesn't matter
728
- }
729
- });
763
+ try {
764
+ this.callManager.httpRequestFailed(requestId, debugInfo);
765
+ }
766
+ catch {
767
+ // We may not have an active connection any more.
768
+ // In which case it doesn't matter
769
+ }
730
770
  }
731
771
  // Group Calls
732
772
  // Called by UX
@@ -756,9 +796,12 @@ class RingRTCType {
756
796
  peekGroupCall(sfuUrl, membershipProof, groupMembers) {
757
797
  const [requestId, promise] = this._peekRequests.add();
758
798
  // Response comes back via handlePeekResponse
759
- sillyDeadlockProtection(() => {
799
+ try {
760
800
  this.callManager.peekGroupCall(requestId, sfuUrl, membershipProof, groupMembers);
761
- });
801
+ }
802
+ catch (e) {
803
+ this._peekRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
804
+ }
762
805
  return promise.then(result => {
763
806
  if (result.success) {
764
807
  return result.value;
@@ -773,207 +816,196 @@ class RingRTCType {
773
816
  });
774
817
  }
775
818
  // Called by UX
819
+ // Note: the promise here will resolve right away for a "stop" request; it's
820
+ // only useful to detect start failures.
776
821
  setMicrophoneWarmupEnabled(warmup) {
777
- sillyDeadlockProtection(() => {
778
- this.callManager.setMicrophoneWarmupEnabled(warmup);
779
- });
822
+ if (warmup) {
823
+ const [requestId, promise] = this._audioDeviceRequests.add();
824
+ try {
825
+ this.callManager.setMicrophoneWarmupEnabled(warmup, requestId);
826
+ }
827
+ catch (e) {
828
+ this._audioDeviceRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
829
+ }
830
+ return promise;
831
+ }
832
+ try {
833
+ this.callManager.setMicrophoneWarmupEnabled(warmup, 0);
834
+ }
835
+ catch (e) {
836
+ this.logWarn(`Failed to stop microphone warmup: ${e}`);
837
+ }
838
+ // In general we don't plumb through "stop recording" results because there's
839
+ // nothing that the client can do with a failure there. Just resolve this right away.
840
+ return Promise.resolve(undefined);
780
841
  }
781
842
  // Called by UX
782
843
  peekCallLinkCall(sfuUrl, authCredentialPresentation, rootKey) {
783
844
  const [requestId, promise] = this._peekRequests.add();
784
845
  // Response comes back via handlePeekResponse
785
- sillyDeadlockProtection(() => {
846
+ try {
786
847
  this.callManager.peekCallLinkCall(requestId, sfuUrl, authCredentialPresentation, rootKey.bytes);
787
- });
848
+ }
849
+ catch (e) {
850
+ this._peekRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
851
+ }
788
852
  return promise;
789
853
  }
790
854
  // Called by Rust
791
855
  requestMembershipProof(clientId) {
792
- sillyDeadlockProtection(() => {
793
- const groupCall = this._groupCallByClientId.get(clientId);
794
- if (!groupCall) {
795
- this.logError('requestMembershipProof(): GroupCall not found in map!');
796
- return;
797
- }
798
- groupCall.requestMembershipProof();
799
- });
856
+ const groupCall = this._groupCallByClientId.get(clientId);
857
+ if (!groupCall) {
858
+ this.logError('requestMembershipProof(): GroupCall not found in map!');
859
+ return;
860
+ }
861
+ groupCall.requestMembershipProof();
800
862
  }
801
863
  // Called by Rust
802
864
  requestGroupMembers(clientId) {
803
- sillyDeadlockProtection(() => {
804
- const groupCall = this._groupCallByClientId.get(clientId);
805
- if (!groupCall) {
806
- this.logError('requestGroupMembers(): GroupCall not found in map!');
807
- return;
808
- }
809
- groupCall.requestGroupMembers();
810
- });
865
+ const groupCall = this._groupCallByClientId.get(clientId);
866
+ if (!groupCall) {
867
+ this.logError('requestGroupMembers(): GroupCall not found in map!');
868
+ return;
869
+ }
870
+ groupCall.requestGroupMembers();
811
871
  }
812
872
  // Called by Rust
813
873
  handleConnectionStateChanged(clientId, connectionState) {
814
- sillyDeadlockProtection(() => {
815
- const groupCall = this._groupCallByClientId.get(clientId);
816
- if (!groupCall) {
817
- this.logError('handleConnectionStateChanged(): GroupCall not found in map!');
818
- return;
819
- }
820
- groupCall.handleConnectionStateChanged(connectionState);
821
- });
874
+ const groupCall = this._groupCallByClientId.get(clientId);
875
+ if (!groupCall) {
876
+ this.logError('handleConnectionStateChanged(): GroupCall not found in map!');
877
+ return;
878
+ }
879
+ groupCall.handleConnectionStateChanged(connectionState);
822
880
  }
823
881
  // Called by Rust
824
882
  handleJoinStateChanged(clientId, joinState, demuxId) {
825
- sillyDeadlockProtection(() => {
826
- const groupCall = this._groupCallByClientId.get(clientId);
827
- if (!groupCall) {
828
- this.logError('handleJoinStateChanged(): GroupCall not found in map!');
829
- return;
830
- }
831
- groupCall.handleJoinStateChanged(joinState, demuxId);
832
- });
883
+ const groupCall = this._groupCallByClientId.get(clientId);
884
+ if (!groupCall) {
885
+ this.logError('handleJoinStateChanged(): GroupCall not found in map!');
886
+ return;
887
+ }
888
+ groupCall.handleJoinStateChanged(joinState, demuxId);
833
889
  }
834
890
  // Called by Rust
835
891
  handleNetworkRouteChanged(clientId, localNetworkAdapterType) {
836
- sillyDeadlockProtection(() => {
837
- const groupCall = this._groupCallByClientId.get(clientId);
838
- if (!groupCall) {
839
- this.logError('handleNetworkRouteChanged(): GroupCall not found in map!');
840
- return;
841
- }
842
- groupCall.handleNetworkRouteChanged(localNetworkAdapterType);
843
- });
892
+ const groupCall = this._groupCallByClientId.get(clientId);
893
+ if (!groupCall) {
894
+ this.logError('handleNetworkRouteChanged(): GroupCall not found in map!');
895
+ return;
896
+ }
897
+ groupCall.handleNetworkRouteChanged(localNetworkAdapterType);
844
898
  }
845
899
  // Called by Rust
846
900
  handleAudioLevels(clientId, capturedLevel, receivedLevels) {
847
- sillyDeadlockProtection(() => {
848
- const groupCall = this._groupCallByClientId.get(clientId);
849
- if (groupCall) {
850
- groupCall.handleAudioLevels(capturedLevel, receivedLevels);
851
- }
852
- });
901
+ const groupCall = this._groupCallByClientId.get(clientId);
902
+ if (groupCall) {
903
+ groupCall.handleAudioLevels(capturedLevel, receivedLevels);
904
+ }
853
905
  }
854
906
  // Called by Rust
855
907
  handleLowBandwidthForVideo(clientId, recovered) {
856
- sillyDeadlockProtection(() => {
857
- const groupCall = this._groupCallByClientId.get(clientId);
858
- if (groupCall) {
859
- groupCall.handleLowBandwidthForVideo(recovered);
860
- }
861
- });
908
+ const groupCall = this._groupCallByClientId.get(clientId);
909
+ if (groupCall) {
910
+ groupCall.handleLowBandwidthForVideo(recovered);
911
+ }
862
912
  }
863
913
  // Called by Rust
864
914
  handleReactions(clientId, reactions) {
865
- sillyDeadlockProtection(() => {
866
- const groupCall = this._groupCallByClientId.get(clientId);
867
- if (groupCall) {
868
- groupCall.handleReactions(reactions);
869
- }
870
- });
915
+ const groupCall = this._groupCallByClientId.get(clientId);
916
+ if (groupCall) {
917
+ groupCall.handleReactions(reactions);
918
+ }
871
919
  }
872
920
  // Called by Rust
873
921
  handleRaisedHands(clientId, raisedHands) {
874
- sillyDeadlockProtection(() => {
875
- const groupCall = this._groupCallByClientId.get(clientId);
876
- if (groupCall) {
877
- groupCall.handleRaisedHands(raisedHands);
878
- }
879
- });
922
+ const groupCall = this._groupCallByClientId.get(clientId);
923
+ if (groupCall) {
924
+ groupCall.handleRaisedHands(raisedHands);
925
+ }
880
926
  }
881
927
  // Called by Rust
882
928
  handleRemoteDevicesChanged(clientId, remoteDeviceStates) {
883
- sillyDeadlockProtection(() => {
884
- const groupCall = this._groupCallByClientId.get(clientId);
885
- if (!groupCall) {
886
- this.logError('handleRemoteDevicesChanged(): GroupCall not found in map!');
887
- return;
888
- }
889
- groupCall.handleRemoteDevicesChanged(remoteDeviceStates);
890
- });
929
+ const groupCall = this._groupCallByClientId.get(clientId);
930
+ if (!groupCall) {
931
+ this.logError('handleRemoteDevicesChanged(): GroupCall not found in map!');
932
+ return;
933
+ }
934
+ groupCall.handleRemoteDevicesChanged(remoteDeviceStates);
891
935
  }
892
936
  // Called by Rust
893
937
  handlePeekChanged(clientId, rawInfo) {
894
- sillyDeadlockProtection(() => {
895
- const groupCall = this._groupCallByClientId.get(clientId);
896
- if (!groupCall) {
897
- this.logError('handlePeekChanged(): GroupCall not found in map!');
898
- return;
899
- }
900
- const info = rawPeekInfoToPeekInfo(rawInfo);
901
- groupCall.handlePeekChanged(info);
902
- });
938
+ const groupCall = this._groupCallByClientId.get(clientId);
939
+ if (!groupCall) {
940
+ this.logError('handlePeekChanged(): GroupCall not found in map!');
941
+ return;
942
+ }
943
+ const info = rawPeekInfoToPeekInfo(rawInfo);
944
+ groupCall.handlePeekChanged(info);
903
945
  }
904
946
  // Called by Rust
905
947
  handlePeekResponse(requestId, statusCode, rawInfo) {
906
- sillyDeadlockProtection(() => {
907
- let result;
908
- if (rawInfo) {
909
- const info = rawPeekInfoToPeekInfo(rawInfo);
910
- result = { success: true, value: info };
911
- }
912
- else {
913
- result = { success: false, errorStatusCode: statusCode };
914
- }
915
- if (!this._peekRequests.resolve(requestId, result)) {
916
- this.logWarn(`Invalid request ID for handlePeekResponse: ${requestId}`);
917
- }
918
- });
948
+ let result;
949
+ if (rawInfo) {
950
+ const info = rawPeekInfoToPeekInfo(rawInfo);
951
+ result = { success: true, value: info };
952
+ }
953
+ else {
954
+ result = { success: false, errorStatusCode: statusCode };
955
+ }
956
+ if (!this._peekRequests.resolve(requestId, result)) {
957
+ this.logWarn(`Invalid request ID for handlePeekResponse: ${requestId}`);
958
+ }
919
959
  }
920
960
  // Called by Rust
921
961
  handleCallLinkResponse(requestId, statusCode, state) {
922
- sillyDeadlockProtection(() => {
923
- // Recreate the state so that we have the correct prototype, in case we add more methods to CallLinkState.
924
- let result;
925
- const s = rawCallLinkStateToCallLinkState(state);
926
- if (s) {
927
- result = {
928
- success: true,
929
- value: s,
930
- };
931
- }
932
- else {
933
- result = { success: false, errorStatusCode: statusCode };
934
- }
935
- if (!this._callLinkRequests.resolve(requestId, result)) {
936
- this.logWarn(`Invalid request ID for handleCallLinkResponse: ${requestId}`);
937
- }
938
- });
962
+ // Recreate the state so that we have the correct prototype, in case we add more methods to CallLinkState.
963
+ let result;
964
+ const s = rawCallLinkStateToCallLinkState(state);
965
+ if (s) {
966
+ result = {
967
+ success: true,
968
+ value: s,
969
+ };
970
+ }
971
+ else {
972
+ result = { success: false, errorStatusCode: statusCode };
973
+ }
974
+ if (!this._callLinkRequests.resolve(requestId, result)) {
975
+ this.logWarn(`Invalid request ID for handleCallLinkResponse: ${requestId}`);
976
+ }
939
977
  }
940
978
  // Called by Rust
941
979
  handleEmptyResponse(requestId, statusCode, state) {
942
- sillyDeadlockProtection(() => {
943
- let result;
944
- if (state !== undefined) {
945
- result = { success: true, value: undefined };
946
- }
947
- else {
948
- result = { success: false, errorStatusCode: statusCode };
949
- }
950
- if (!this._emptyRequests.resolve(requestId, result)) {
951
- this.logWarn(`Invalid request ID for handleEmptyResponse: ${requestId}`);
952
- }
953
- });
980
+ let result;
981
+ if (state !== undefined) {
982
+ result = { success: true, value: undefined };
983
+ }
984
+ else {
985
+ result = { success: false, errorStatusCode: statusCode };
986
+ }
987
+ if (!this._emptyRequests.resolve(requestId, result)) {
988
+ this.logWarn(`Invalid request ID for handleEmptyResponse: ${requestId}`);
989
+ }
954
990
  }
955
991
  // Called by Rust
956
992
  handleEnded(clientId, reason, summary) {
957
- sillyDeadlockProtection(() => {
958
- const groupCall = this._groupCallByClientId.get(clientId);
959
- if (!groupCall) {
960
- this.logError('handleEnded(): GroupCall not found in map!');
961
- return;
962
- }
963
- this._groupCallByClientId.delete(clientId);
964
- groupCall.handleEnded(reason, summary);
965
- });
993
+ const groupCall = this._groupCallByClientId.get(clientId);
994
+ if (!groupCall) {
995
+ this.logError('handleEnded(): GroupCall not found in map!');
996
+ return;
997
+ }
998
+ this._groupCallByClientId.delete(clientId);
999
+ groupCall.handleEnded(reason, summary);
966
1000
  }
967
1001
  // Called by Rust
968
1002
  groupCallRingUpdate(groupId, ringId, sender, state) {
969
- sillyDeadlockProtection(() => {
970
- if (this.handleGroupCallRingUpdate) {
971
- this.handleGroupCallRingUpdate(groupId, ringId, sender, state);
972
- }
973
- else {
974
- this.logError('RingRTC.handleGroupCallRingUpdate is not set!');
975
- }
976
- });
1003
+ if (this.handleGroupCallRingUpdate) {
1004
+ this.handleGroupCallRingUpdate(groupId, ringId, sender, state);
1005
+ }
1006
+ else {
1007
+ this.logError('RingRTC.handleGroupCallRingUpdate is not set!');
1008
+ }
977
1009
  }
978
1010
  // Called by Rust
979
1011
  handleRtcStatsReportComplete(reportJson) {
@@ -983,30 +1015,24 @@ class RingRTCType {
983
1015
  }
984
1016
  // Called by Rust
985
1017
  handleSpeechEvent(clientId, event) {
986
- sillyDeadlockProtection(() => {
987
- const groupCall = this._groupCallByClientId.get(clientId);
988
- if (groupCall) {
989
- groupCall.handleSpeechEvent(event);
990
- }
991
- });
1018
+ const groupCall = this._groupCallByClientId.get(clientId);
1019
+ if (groupCall) {
1020
+ groupCall.handleSpeechEvent(event);
1021
+ }
992
1022
  }
993
1023
  // Called by Rust
994
1024
  onRemoteMute(clientId, demuxId) {
995
- sillyDeadlockProtection(() => {
996
- const groupCall = this._groupCallByClientId.get(clientId);
997
- if (groupCall) {
998
- groupCall.onRemoteMute(demuxId);
999
- }
1000
- });
1025
+ const groupCall = this._groupCallByClientId.get(clientId);
1026
+ if (groupCall) {
1027
+ groupCall.onRemoteMute(demuxId);
1028
+ }
1001
1029
  }
1002
1030
  // Called by Rust.
1003
1031
  onObservedRemoteMute(clientId, sourceDemuxId, targetDemuxId) {
1004
- sillyDeadlockProtection(() => {
1005
- const groupCall = this._groupCallByClientId.get(clientId);
1006
- if (groupCall) {
1007
- groupCall.onObservedRemoteMute(sourceDemuxId, targetDemuxId);
1008
- }
1009
- });
1032
+ const groupCall = this._groupCallByClientId.get(clientId);
1033
+ if (groupCall) {
1034
+ groupCall.onObservedRemoteMute(sourceDemuxId, targetDemuxId);
1035
+ }
1010
1036
  }
1011
1037
  // Called by Rust
1012
1038
  onOutputDeviceChanged(devices) {
@@ -1025,6 +1051,33 @@ class RingRTCType {
1025
1051
  })().catch(e => this.logError(e.toString()));
1026
1052
  }
1027
1053
  // Called by Rust
1054
+ onSettleStartPlayback(success, device) {
1055
+ (async () => {
1056
+ if (this.handleSettleStartPlayback) {
1057
+ await this.handleSettleStartPlayback(success, device);
1058
+ }
1059
+ })().catch(e => this.logError(e.toString()));
1060
+ }
1061
+ // Resolve an audio-device-related promise. Called by rust
1062
+ onSettleAudioPromise(success, device, requestId) {
1063
+ if (success) {
1064
+ if (!this._audioDeviceRequests.resolve(requestId, device)) {
1065
+ this.logWarn(`Invalid request ID for onSettleAudioPromise: ${requestId}`);
1066
+ }
1067
+ }
1068
+ else if (!this._audioDeviceRequests.reject(requestId, new AudioDeviceInitError(device))) {
1069
+ this.logWarn(`Invalid request ID for onSettleAudioPromise: ${requestId}`);
1070
+ }
1071
+ }
1072
+ // Called by Rust
1073
+ onSettleStartRecording(success, device) {
1074
+ (async () => {
1075
+ if (this.handleSettleStartRecording) {
1076
+ await this.handleSettleStartRecording(success, device);
1077
+ }
1078
+ })().catch(e => this.logError(e.toString()));
1079
+ }
1080
+ // Called by Rust
1028
1081
  onLogMessage(level, fileName, line, message) {
1029
1082
  if (this.handleLogMessage) {
1030
1083
  this.handleLogMessage(level, fileName, line, message);
@@ -1198,17 +1251,39 @@ class RingRTCType {
1198
1251
  }
1199
1252
  call.hangup();
1200
1253
  }
1254
+ // As of mid-2026, we would not expect undefined returns here to be retriable:
1255
+ // They would indicate a poisoned mutex or that we had altogether failed to
1256
+ // initialize the ADM.
1257
+ // It is possible that will change in the future.
1201
1258
  getAudioInputs() {
1202
1259
  return this.callManager.getAudioInputs();
1203
1260
  }
1204
- setAudioInput(index) {
1205
- this.callManager.setAudioInput(index);
1261
+ setAudioInputById(id) {
1262
+ const [requestId, promise] = this._audioDeviceRequests.add();
1263
+ try {
1264
+ this.callManager.setAudioInputById(id, requestId);
1265
+ }
1266
+ catch (e) {
1267
+ this._audioDeviceRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
1268
+ }
1269
+ return promise;
1206
1270
  }
1271
+ // As of mid-2026, we would not expect undefined returns here to be retriable:
1272
+ // They would indicate a poisoned mutex or that we had altogether failed to
1273
+ // initialize the ADM.
1274
+ // It is possible that will change in the future.
1207
1275
  getAudioOutputs() {
1208
1276
  return this.callManager.getAudioOutputs();
1209
1277
  }
1210
- setAudioOutput(index) {
1211
- this.callManager.setAudioOutput(index);
1278
+ setAudioOutputById(id) {
1279
+ const [requestId, promise] = this._audioDeviceRequests.add();
1280
+ try {
1281
+ this.callManager.setAudioOutputById(id, requestId);
1282
+ }
1283
+ catch (e) {
1284
+ this._audioDeviceRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
1285
+ }
1286
+ return promise;
1212
1287
  }
1213
1288
  /**
1214
1289
  * Enables or disables different voice processing techniques including:
@@ -1221,7 +1296,14 @@ class RingRTCType {
1221
1296
  * @param enabled - whether to enable voice processing
1222
1297
  */
1223
1298
  setVoiceProcessingEnabled(enabled) {
1224
- this.callManager.setVoiceProcessingEnabled(enabled);
1299
+ const [requestId, promise] = this._audioDeviceRequests.add();
1300
+ try {
1301
+ this.callManager.setVoiceProcessingEnabled(enabled, requestId);
1302
+ }
1303
+ catch (e) {
1304
+ this._audioDeviceRequests.reject(requestId, e instanceof Error ? e : new Error(String(e)));
1305
+ }
1306
+ return promise;
1225
1307
  }
1226
1308
  }
1227
1309
  exports.RingRTCType = RingRTCType;
@@ -1232,6 +1314,48 @@ var VideoPixelFormatEnum;
1232
1314
  VideoPixelFormatEnum[VideoPixelFormatEnum["Nv12"] = 1] = "Nv12";
1233
1315
  VideoPixelFormatEnum[VideoPixelFormatEnum["Rgba"] = 2] = "Rgba";
1234
1316
  })(VideoPixelFormatEnum || (exports.VideoPixelFormatEnum = VideoPixelFormatEnum = {}));
1317
+ function truncateForLogging(name) {
1318
+ if (!name) {
1319
+ return 'undefined';
1320
+ }
1321
+ if (name.length <= 4) {
1322
+ return name;
1323
+ }
1324
+ return `${name.slice(0, 2)}...${name.slice(-2)}`;
1325
+ }
1326
+ function cleanAudioDeviceForLogging(device) {
1327
+ if (device === undefined) {
1328
+ return device;
1329
+ }
1330
+ return {
1331
+ name: truncateForLogging(device.name),
1332
+ uniqueId: truncateForLogging(device.uniqueId),
1333
+ };
1334
+ }
1335
+ function cleanAudioDeviceListForLogging(deviceList) {
1336
+ const devices = [];
1337
+ for (const device of deviceList.devices) {
1338
+ devices.push(cleanAudioDeviceForLogging(device));
1339
+ }
1340
+ let defaults;
1341
+ if (deviceList.defaults.isWindows) {
1342
+ defaults = {
1343
+ isWindows: true,
1344
+ communicationsDevice: cleanAudioDeviceForLogging(deviceList.defaults.communicationsDevice),
1345
+ consoleDevice: cleanAudioDeviceForLogging(deviceList.defaults.consoleDevice),
1346
+ };
1347
+ }
1348
+ else {
1349
+ defaults = {
1350
+ isWindows: false,
1351
+ device: cleanAudioDeviceForLogging(deviceList.defaults.device),
1352
+ };
1353
+ }
1354
+ return {
1355
+ devices,
1356
+ defaults,
1357
+ };
1358
+ }
1235
1359
  function videoPixelFormatToEnum(format) {
1236
1360
  switch (format) {
1237
1361
  case 'I420': {
@@ -1285,7 +1409,7 @@ class Call {
1285
1409
  if (state === CallState.Accepted) {
1286
1410
  // We might have been in the reconnecting state and already started media.
1287
1411
  if (!this._mediaSessionStarted) {
1288
- sillyDeadlockProtection(() => {
1412
+ try {
1289
1413
  // Set the audio state to the latest setting from the UX.
1290
1414
  this._callManager.setOutgoingAudioEnabled(this._outgoingAudioEnabled);
1291
1415
  if (this._outgoingVideoIsScreenShare) {
@@ -1295,16 +1419,22 @@ class Call {
1295
1419
  else if (this._outgoingVideoEnabled) {
1296
1420
  this._callManager.setOutgoingVideoEnabled(true);
1297
1421
  }
1298
- });
1422
+ }
1423
+ catch {
1424
+ // Don't let a media failure stop the state change from being reported.
1425
+ }
1299
1426
  this._mediaSessionStarted = true;
1300
1427
  }
1301
1428
  }
1302
1429
  else if (state === CallState.Ended) {
1303
- sillyDeadlockProtection(() => {
1430
+ try {
1304
1431
  this._callManager.setOutgoingAudioEnabled(false);
1305
1432
  this._callManager.setOutgoingVideoEnabled(false);
1306
- this._callManager.setMicrophoneWarmupEnabled(false);
1307
- });
1433
+ this._callManager.setMicrophoneWarmupEnabled(false, 0);
1434
+ }
1435
+ catch {
1436
+ // Don't let a media failure stop the state change from being reported.
1437
+ }
1308
1438
  this._outgoingAudioEnabled = false;
1309
1439
  this._outgoingVideoEnabled = false;
1310
1440
  this._outgoingVideoIsScreenShare = false;
@@ -1327,9 +1457,7 @@ class Call {
1327
1457
  this._callManager.ignore(this.callId);
1328
1458
  }
1329
1459
  hangup() {
1330
- sillyDeadlockProtection(() => {
1331
- this._callManager.hangup();
1332
- });
1460
+ this._callManager.hangup();
1333
1461
  }
1334
1462
  get remoteAudioEnabled() {
1335
1463
  return this._remoteAudioEnabled;
@@ -1347,9 +1475,7 @@ class Call {
1347
1475
  const enabled = !muted;
1348
1476
  if (this._mediaSessionStarted && this._outgoingAudioEnabled !== enabled) {
1349
1477
  this._outgoingAudioEnabled = enabled;
1350
- sillyDeadlockProtection(() => {
1351
- this._callManager.setOutgoingAudioEnabled(enabled);
1352
- });
1478
+ this._callManager.setOutgoingAudioEnabled(enabled);
1353
1479
  }
1354
1480
  else {
1355
1481
  this._outgoingAudioEnabled = enabled;
@@ -1359,9 +1485,7 @@ class Call {
1359
1485
  const enabled = !muted;
1360
1486
  if (this._mediaSessionStarted && this._outgoingVideoEnabled !== enabled) {
1361
1487
  this._outgoingVideoEnabled = enabled;
1362
- sillyDeadlockProtection(() => {
1363
- this._callManager.setOutgoingVideoEnabled(enabled);
1364
- });
1488
+ this._callManager.setOutgoingVideoEnabled(enabled);
1365
1489
  }
1366
1490
  else {
1367
1491
  this._outgoingVideoEnabled = enabled;
@@ -1371,9 +1495,7 @@ class Call {
1371
1495
  if (this._mediaSessionStarted &&
1372
1496
  this._outgoingVideoIsScreenShare !== isScreenShare) {
1373
1497
  this._outgoingVideoIsScreenShare = isScreenShare;
1374
- sillyDeadlockProtection(() => {
1375
- this._callManager.setOutgoingVideoIsScreenShare(isScreenShare);
1376
- });
1498
+ this._callManager.setOutgoingVideoIsScreenShare(isScreenShare);
1377
1499
  }
1378
1500
  else {
1379
1501
  this._outgoingVideoIsScreenShare = isScreenShare;
@@ -1388,15 +1510,13 @@ class Call {
1388
1510
  return this._callManager.receiveVideoFrame(buffer, maxWidth, maxHeight);
1389
1511
  }
1390
1512
  updateDataMode(dataMode) {
1391
- sillyDeadlockProtection(() => {
1392
- try {
1393
- this._callManager.updateDataMode(dataMode);
1394
- }
1395
- catch {
1396
- // We may not have an active connection any more.
1397
- // In which case it doesn't matter
1398
- }
1399
- });
1513
+ try {
1514
+ this._callManager.updateDataMode(dataMode);
1515
+ }
1516
+ catch {
1517
+ // We may not have an active connection any more.
1518
+ // In which case it doesn't matter
1519
+ }
1400
1520
  }
1401
1521
  }
1402
1522
  exports.Call = Call;
@@ -1892,11 +2012,4 @@ var CallLogLevel;
1892
2012
  CallLogLevel[CallLogLevel["Debug"] = 4] = "Debug";
1893
2013
  CallLogLevel[CallLogLevel["Trace"] = 5] = "Trace";
1894
2014
  })(CallLogLevel || (exports.CallLogLevel = CallLogLevel = {}));
1895
- function sillyDeadlockProtection(f) {
1896
- void (async () => {
1897
- // Yield so f() runs after unwinding the calling stack.
1898
- await Promise.resolve();
1899
- f();
1900
- })();
1901
- }
1902
2015
  //# sourceMappingURL=Service.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalapp/ringrtc",
3
- "version": "2.72.0",
3
+ "version": "2.73.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/signalapp/ringrtc.git",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "config": {
35
35
  "prebuildUrl": "https://build-artifacts.signal.org/libraries/ringrtc-desktop-build-v${npm_package_version}.tar.gz",
36
- "prebuildChecksum": "5030c683f0f181b0f132e58881c0d5e371f68185141de0e50c865d851b8b01de"
36
+ "prebuildChecksum": "3bae60a74659f832da0ef24ff1d95b59e5d73aebbacebf1186fbf3d0badc30d2"
37
37
  },
38
38
  "author": "",
39
39
  "license": "AGPL-3.0-only",