@signalwire/js 4.0.0-dev-20260910191529 → 4.0.0-dev-20260911172704
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +572 -193
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +573 -192
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +507 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2116 -2028
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2116 -2028
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +506 -174
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-Bn4Ij3VB.cjs → operators-5r8VWBHn.cjs} +72 -1
- package/dist/operators-5r8VWBHn.cjs.map +1 -0
- package/dist/{operators-Zxmwpb0j.mjs → operators-CeYVsmi4.mjs} +49 -2
- package/dist/operators-CeYVsmi4.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/operators-Bn4Ij3VB.cjs.map +0 -1
- package/dist/operators-Zxmwpb0j.mjs.map +0 -1
package/dist/browser.mjs
CHANGED
|
@@ -4186,7 +4186,7 @@ var require_merge$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4186
4186
|
var empty_1$7 = require_empty();
|
|
4187
4187
|
var args_1$8 = require_args();
|
|
4188
4188
|
var from_1$4 = require_from();
|
|
4189
|
-
function merge$
|
|
4189
|
+
function merge$7() {
|
|
4190
4190
|
var args = [];
|
|
4191
4191
|
for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
|
|
4192
4192
|
var scheduler = args_1$8.popScheduler(args);
|
|
@@ -4194,7 +4194,7 @@ var require_merge$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4194
4194
|
var sources = args;
|
|
4195
4195
|
return !sources.length ? empty_1$7.EMPTY : sources.length === 1 ? innerFrom_1$31.innerFrom(sources[0]) : mergeAll_1$3.mergeAll(concurrent)(from_1$4.from(sources, scheduler));
|
|
4196
4196
|
}
|
|
4197
|
-
exports.merge = merge$
|
|
4197
|
+
exports.merge = merge$7;
|
|
4198
4198
|
}));
|
|
4199
4199
|
|
|
4200
4200
|
//#endregion
|
|
@@ -4325,13 +4325,13 @@ var require_race$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4325
4325
|
var innerFrom_1$28 = require_innerFrom();
|
|
4326
4326
|
var argsOrArgArray_1$4 = require_argsOrArgArray();
|
|
4327
4327
|
var OperatorSubscriber_1$48 = require_OperatorSubscriber();
|
|
4328
|
-
function race$
|
|
4328
|
+
function race$4() {
|
|
4329
4329
|
var sources = [];
|
|
4330
4330
|
for (var _i = 0; _i < arguments.length; _i++) sources[_i] = arguments[_i];
|
|
4331
4331
|
sources = argsOrArgArray_1$4.argsOrArgArray(sources);
|
|
4332
4332
|
return sources.length === 1 ? innerFrom_1$28.innerFrom(sources[0]) : new Observable_1$6.Observable(raceInit(sources));
|
|
4333
4333
|
}
|
|
4334
|
-
exports.race = race$
|
|
4334
|
+
exports.race = race$4;
|
|
4335
4335
|
function raceInit(sources) {
|
|
4336
4336
|
return function(subscriber) {
|
|
4337
4337
|
var subscriptions = [];
|
|
@@ -6076,7 +6076,7 @@ var require_merge = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6076
6076
|
var mergeAll_1$2 = require_mergeAll();
|
|
6077
6077
|
var args_1$3 = require_args();
|
|
6078
6078
|
var from_1$1 = require_from();
|
|
6079
|
-
function merge$
|
|
6079
|
+
function merge$6() {
|
|
6080
6080
|
var args = [];
|
|
6081
6081
|
for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
|
|
6082
6082
|
var scheduler = args_1$3.popScheduler(args);
|
|
@@ -6085,7 +6085,7 @@ var require_merge = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6085
6085
|
mergeAll_1$2.mergeAll(concurrent)(from_1$1.from(__spreadArray$8([source], __read$8(args)), scheduler)).subscribe(subscriber);
|
|
6086
6086
|
});
|
|
6087
6087
|
}
|
|
6088
|
-
exports.merge = merge$
|
|
6088
|
+
exports.merge = merge$6;
|
|
6089
6089
|
}));
|
|
6090
6090
|
|
|
6091
6091
|
//#endregion
|
|
@@ -6932,7 +6932,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6932
6932
|
var innerFrom_1$6 = require_innerFrom();
|
|
6933
6933
|
var lift_1$13 = require_lift();
|
|
6934
6934
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6935
|
-
function switchMap$
|
|
6935
|
+
function switchMap$8(project, resultSelector) {
|
|
6936
6936
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6937
6937
|
var innerSubscriber = null;
|
|
6938
6938
|
var index = 0;
|
|
@@ -6956,7 +6956,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6956
6956
|
}));
|
|
6957
6957
|
});
|
|
6958
6958
|
}
|
|
6959
|
-
exports.switchMap = switchMap$
|
|
6959
|
+
exports.switchMap = switchMap$8;
|
|
6960
6960
|
}));
|
|
6961
6961
|
|
|
6962
6962
|
//#endregion
|
|
@@ -9022,6 +9022,25 @@ const DEFAULT_ICE_CANDIDATE_TIMEOUT_MS = 600;
|
|
|
9022
9022
|
const DEFAULT_ICE_GATHERING_TIMEOUT_MS = 6e3;
|
|
9023
9023
|
const DEFAULT_RECONNECT_CALLS_TIMEOUT_MS = 300 * 1e3;
|
|
9024
9024
|
const DEFAULT_CONNECTION_TIMEOUT_MS = 1e4;
|
|
9025
|
+
/**
|
|
9026
|
+
* How long call setup may wait for the network, measured from local media
|
|
9027
|
+
* settling until the member id arrives.
|
|
9028
|
+
*
|
|
9029
|
+
* Local media acquisition is deliberately NOT inside this: a permission prompt
|
|
9030
|
+
* or a device picker is human time, and a human may take as long as they like
|
|
9031
|
+
* without spending the server's budget. The clock starts when acquisition ends.
|
|
9032
|
+
*
|
|
9033
|
+
* Must exceed `iceGatheringTimeout + the RPC timeout`, which both run inside it.
|
|
9034
|
+
*/
|
|
9035
|
+
const DEFAULT_CALL_SIGNALING_TIMEOUT_MS = 12e3;
|
|
9036
|
+
/**
|
|
9037
|
+
* How long an auxiliary leg (screen share, additional device) may take to
|
|
9038
|
+
* connect once its media is in hand.
|
|
9039
|
+
*
|
|
9040
|
+
* One bound for both: the picker is human time and sits outside it. What remains
|
|
9041
|
+
* — offer, ICE, invite, answer, DTLS — is the same work for either leg kind.
|
|
9042
|
+
*/
|
|
9043
|
+
const DEFAULT_AUX_LEG_CONNECT_TIMEOUT_MS = 15e3;
|
|
9025
9044
|
const DEFAULT_RECONNECT_DELAY_MIN_MS = 100;
|
|
9026
9045
|
const DEFAULT_RECONNECT_DELAY_MAX_MS = 3e3;
|
|
9027
9046
|
const DEFAULT_DEVICE_DEBOUNCE_TIME_MS = 1500;
|
|
@@ -9374,6 +9393,18 @@ var CollectionFetchError = class extends Error {
|
|
|
9374
9393
|
this.name = "CollectionFetchError";
|
|
9375
9394
|
}
|
|
9376
9395
|
};
|
|
9396
|
+
/**
|
|
9397
|
+
* An auxiliary leg did not connect within its budget. Typed rather than a bare
|
|
9398
|
+
* RxJS `TimeoutError` so the leg and cause survive.
|
|
9399
|
+
*/
|
|
9400
|
+
var AuxiliaryLegTimeoutError = class extends Error {
|
|
9401
|
+
constructor(leg, originalError) {
|
|
9402
|
+
super(`Timed out waiting for the ${leg} connection to be established`, { cause: originalError });
|
|
9403
|
+
this.leg = leg;
|
|
9404
|
+
this.originalError = originalError;
|
|
9405
|
+
this.name = "AuxiliaryLegTimeoutError";
|
|
9406
|
+
}
|
|
9407
|
+
};
|
|
9377
9408
|
var MediaTrackError = class extends Error {
|
|
9378
9409
|
constructor(operation, kind, originalError) {
|
|
9379
9410
|
super(`Media track ${operation} failed for ${kind}`, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
@@ -9410,6 +9441,22 @@ var MediaAccessError = class extends Error {
|
|
|
9410
9441
|
return isMediaAccessDenial(this.originalError);
|
|
9411
9442
|
}
|
|
9412
9443
|
};
|
|
9444
|
+
/**
|
|
9445
|
+
* Thrown by `startScreenShare()` when the call is already sharing a screen.
|
|
9446
|
+
*
|
|
9447
|
+
* A call carries at most one screen share. Accepting a second one would
|
|
9448
|
+
* overwrite the only reference the SDK holds to the first, leaving it
|
|
9449
|
+
* capturing and sending with no way to stop it — so the second request is
|
|
9450
|
+
* rejected and the live share is left untouched. Call `stopScreenShare()`
|
|
9451
|
+
* first to replace it.
|
|
9452
|
+
*/
|
|
9453
|
+
var ScreenShareAlreadyActiveError = class extends Error {
|
|
9454
|
+
constructor(screenShareId, options) {
|
|
9455
|
+
super(`A screen share is already active on this call (${screenShareId}). Call stopScreenShare() before starting another one.`, options);
|
|
9456
|
+
this.screenShareId = screenShareId;
|
|
9457
|
+
this.name = "ScreenShareAlreadyActiveError";
|
|
9458
|
+
}
|
|
9459
|
+
};
|
|
9413
9460
|
var DPoPInitError = class extends Error {
|
|
9414
9461
|
constructor(originalError, message = "Failed to initialize DPoP key pair") {
|
|
9415
9462
|
super(message, { cause: originalError instanceof Error ? originalError : void 0 });
|
|
@@ -9650,9 +9697,9 @@ var require_loglevel = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
9650
9697
|
defaultLogger$1 = new Logger();
|
|
9651
9698
|
defaultLogger$1.getLogger = function getLogger$1(name) {
|
|
9652
9699
|
if (typeof name !== "symbol" && typeof name !== "string" || name === "") throw new TypeError("You must supply a name when creating a logger.");
|
|
9653
|
-
var logger$
|
|
9654
|
-
if (!logger$
|
|
9655
|
-
return logger$
|
|
9700
|
+
var logger$34 = _loggersByName[name];
|
|
9701
|
+
if (!logger$34) logger$34 = _loggersByName[name] = new Logger(name, defaultLogger$1.methodFactory);
|
|
9702
|
+
return logger$34;
|
|
9656
9703
|
};
|
|
9657
9704
|
var _log = typeof window !== undefinedType ? window.log : void 0;
|
|
9658
9705
|
defaultLogger$1.noConflict = function() {
|
|
@@ -9688,8 +9735,8 @@ const defaultLoggerLevel = defaultLogger.levels.WARN;
|
|
|
9688
9735
|
defaultLogger.setLevel(defaultLoggerLevel);
|
|
9689
9736
|
let userLogger = null;
|
|
9690
9737
|
/** Replace the built-in logger with a custom implementation. Pass `null` to restore defaults. */
|
|
9691
|
-
const setLogger = (logger$
|
|
9692
|
-
userLogger = logger$
|
|
9738
|
+
const setLogger = (logger$34) => {
|
|
9739
|
+
userLogger = logger$34;
|
|
9693
9740
|
};
|
|
9694
9741
|
let debugOptions = {};
|
|
9695
9742
|
/** Configure debug options (e.g., `{ logWsTraffic: true }`). */
|
|
@@ -9733,8 +9780,8 @@ const wsTraffic = (options) => {
|
|
|
9733
9780
|
loggerInstance.debug(`${options.type.toUpperCase()}: \n`, msg, "\n");
|
|
9734
9781
|
};
|
|
9735
9782
|
const getLogger = () => {
|
|
9736
|
-
const logger$
|
|
9737
|
-
return new Proxy(logger$
|
|
9783
|
+
const logger$34 = getLoggerInstance();
|
|
9784
|
+
return new Proxy(logger$34, { get(_target, prop, _receiver) {
|
|
9738
9785
|
if (prop === "wsTraffic") return wsTraffic;
|
|
9739
9786
|
const instance = getLoggerInstance();
|
|
9740
9787
|
const value = Reflect.get(instance, prop);
|
|
@@ -9786,7 +9833,7 @@ const asyncRetry = async ({ asyncCallable, maxRetries: retries = DEFAULT_MAX_RET
|
|
|
9786
9833
|
|
|
9787
9834
|
//#endregion
|
|
9788
9835
|
//#region src/controllers/HTTPRequestController.ts
|
|
9789
|
-
const logger$
|
|
9836
|
+
const logger$33 = getLogger();
|
|
9790
9837
|
const GET_PARAMS = {
|
|
9791
9838
|
method: "GET",
|
|
9792
9839
|
headers: { Accept: "application/json" }
|
|
@@ -9850,7 +9897,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9850
9897
|
this._responses$.next(response);
|
|
9851
9898
|
return response;
|
|
9852
9899
|
} catch (error) {
|
|
9853
|
-
logger$
|
|
9900
|
+
logger$33.error("[HTTPRequestController] Request error:", error);
|
|
9854
9901
|
this._status$.next("error");
|
|
9855
9902
|
const err = error instanceof Error ? error : new Error("HTTP request failed", { cause: error });
|
|
9856
9903
|
this._errors$.next(err);
|
|
@@ -9877,7 +9924,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9877
9924
|
const url = this.buildURL(request.url);
|
|
9878
9925
|
const headers = this.buildHeaders(request.headers);
|
|
9879
9926
|
const timeout$5 = request.timeout ?? this.requestTimeout;
|
|
9880
|
-
logger$
|
|
9927
|
+
logger$33.debug("[HTTPRequestController] Executing request:", {
|
|
9881
9928
|
method: request.method,
|
|
9882
9929
|
url,
|
|
9883
9930
|
headers: Object.keys(headers).reduce((acc, key) => {
|
|
@@ -9897,7 +9944,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9897
9944
|
});
|
|
9898
9945
|
clearTimeout(timeoutId);
|
|
9899
9946
|
const httpResponse = await this.convertResponse(response);
|
|
9900
|
-
logger$
|
|
9947
|
+
logger$33.debug("[HTTPRequestController] Response received:", {
|
|
9901
9948
|
status: response.status,
|
|
9902
9949
|
statusText: response.statusText,
|
|
9903
9950
|
headers: [...response.headers.entries()],
|
|
@@ -9907,7 +9954,7 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9907
9954
|
} catch (error) {
|
|
9908
9955
|
clearTimeout(timeoutId);
|
|
9909
9956
|
if (error instanceof Error && error.name === "AbortError") throw new RequestTimeoutError(`Request timeout after ${timeout$5}ms`, { cause: error });
|
|
9910
|
-
logger$
|
|
9957
|
+
logger$33.error("[HTTPRequestController] Request failed:", error);
|
|
9911
9958
|
throw error;
|
|
9912
9959
|
}
|
|
9913
9960
|
}
|
|
@@ -9921,8 +9968,8 @@ var HTTPRequestController = class HTTPRequestController extends Destroyable {
|
|
|
9921
9968
|
const credential = this.getCredential();
|
|
9922
9969
|
if (credential.token) {
|
|
9923
9970
|
headers.Authorization = `Bearer ${credential.token}`;
|
|
9924
|
-
logger$
|
|
9925
|
-
} else logger$
|
|
9971
|
+
logger$33.debug("[HTTPRequestController] Using Bearer token auth, token length:", credential.token.length);
|
|
9972
|
+
} else logger$33.warn("[HTTPRequestController] No credentials available for authentication");
|
|
9926
9973
|
return headers;
|
|
9927
9974
|
}
|
|
9928
9975
|
/**
|
|
@@ -10070,7 +10117,7 @@ function fromMsToSec(milliseconds) {
|
|
|
10070
10117
|
|
|
10071
10118
|
//#endregion
|
|
10072
10119
|
//#region src/containers/PreferencesContainer.ts
|
|
10073
|
-
const logger$
|
|
10120
|
+
const logger$32 = getLogger();
|
|
10074
10121
|
var PreferencesContainer = class PreferencesContainer {
|
|
10075
10122
|
static get instance() {
|
|
10076
10123
|
this._instance ??= new PreferencesContainer();
|
|
@@ -10732,7 +10779,7 @@ var ClientPreferences = class {
|
|
|
10732
10779
|
if (!this._storage) return;
|
|
10733
10780
|
const data = collectStoredPreferences();
|
|
10734
10781
|
this._storage.setItem(PREFERENCES_STORAGE_KEY, data, "local").catch((error) => {
|
|
10735
|
-
logger$
|
|
10782
|
+
logger$32.error(`[ClientPreferences] Failed to save preferences: ${String(error)}`);
|
|
10736
10783
|
});
|
|
10737
10784
|
}
|
|
10738
10785
|
/** Loads preferences from storage and applies them to the container. */
|
|
@@ -10741,7 +10788,7 @@ var ClientPreferences = class {
|
|
|
10741
10788
|
this._storage.getItem(PREFERENCES_STORAGE_KEY, "local").then((stored) => {
|
|
10742
10789
|
if (stored) applyStoredPreferences(stored);
|
|
10743
10790
|
}).catch((error) => {
|
|
10744
|
-
logger$
|
|
10791
|
+
logger$32.error(`[ClientPreferences] Failed to load preferences: ${String(error)}`);
|
|
10745
10792
|
});
|
|
10746
10793
|
}
|
|
10747
10794
|
};
|
|
@@ -10763,7 +10810,7 @@ function toError(value) {
|
|
|
10763
10810
|
//#endregion
|
|
10764
10811
|
//#region src/controllers/NavigatorDeviceController.ts
|
|
10765
10812
|
var import_cjs$29 = require_cjs();
|
|
10766
|
-
const logger$
|
|
10813
|
+
const logger$31 = getLogger();
|
|
10767
10814
|
/** Maps a device kind to its storage key. */
|
|
10768
10815
|
const DEVICE_STORAGE_KEYS = {
|
|
10769
10816
|
audioinput: DEVICE_STORAGE_KEY_AUDIO_INPUT,
|
|
@@ -10785,7 +10832,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10785
10832
|
super();
|
|
10786
10833
|
this.webRTCApiProvider = webRTCApiProvider;
|
|
10787
10834
|
this.deviceChangeHandler = () => {
|
|
10788
|
-
logger$
|
|
10835
|
+
logger$31.debug("[DeviceController] Device change detected");
|
|
10789
10836
|
this.enumerateDevices();
|
|
10790
10837
|
};
|
|
10791
10838
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
@@ -10850,13 +10897,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10850
10897
|
return this.cachedObservable("videoInputDevices$", () => this._devicesState$.pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$)));
|
|
10851
10898
|
}
|
|
10852
10899
|
get selectedAudioInputDevice$() {
|
|
10853
|
-
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audioinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10900
|
+
return this.cachedObservable("selectedAudioInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audioinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$31.debug("[DeviceController] Selected audio input device changed:", info))));
|
|
10854
10901
|
}
|
|
10855
10902
|
get selectedAudioOutputDevice$() {
|
|
10856
|
-
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audiooutput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10903
|
+
return this.cachedObservable("selectedAudioOutputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.audiooutput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$31.debug("[DeviceController] Selected audio output device changed:", info))));
|
|
10857
10904
|
}
|
|
10858
10905
|
get selectedVideoInputDevice$() {
|
|
10859
|
-
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$
|
|
10906
|
+
return this.cachedObservable("selectedVideoInputDevice$", () => this._selectedDevicesState$.asObservable().pipe((0, import_cjs$29.map)((state) => state.videoinput), (0, import_cjs$29.distinctUntilChanged)(), (0, import_cjs$29.takeUntil)(this.destroyed$), (0, import_cjs$29.tap)((info) => logger$31.debug("[DeviceController] Selected video input device changed:", info))));
|
|
10860
10907
|
}
|
|
10861
10908
|
get selectedAudioInputDevice() {
|
|
10862
10909
|
if (this._audioInputDisabled$.value) return null;
|
|
@@ -10931,7 +10978,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10931
10978
|
if (device) this.persistDeviceSelection("audioinput", device);
|
|
10932
10979
|
}
|
|
10933
10980
|
selectVideoInputDevice(device) {
|
|
10934
|
-
logger$
|
|
10981
|
+
logger$31.debug("[DeviceController] Setting selected video input device:", device);
|
|
10935
10982
|
if (this._videoInputDisabled$.value && device) this._videoInputDisabled$.next(false);
|
|
10936
10983
|
const previous = this._selectedDevicesState$.value.videoinput;
|
|
10937
10984
|
if (previous && previous.deviceId !== device?.deviceId) this._deviceHistory.push("videoinput", previous);
|
|
@@ -10988,7 +11035,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
10988
11035
|
}
|
|
10989
11036
|
const fromHistory = this._deviceHistory.findInHistory(kind, devices);
|
|
10990
11037
|
if (fromHistory) {
|
|
10991
|
-
logger$
|
|
11038
|
+
logger$31.debug(`[DeviceController] Device disappeared, falling back to history: ${fromHistory.label}`);
|
|
10992
11039
|
this.emitDeviceRecovered(kind, selected, fromHistory, "device_disconnected");
|
|
10993
11040
|
return fromHistory;
|
|
10994
11041
|
}
|
|
@@ -11041,7 +11088,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11041
11088
|
try {
|
|
11042
11089
|
await this._storageManager.setItem(DEVICE_STORAGE_KEYS[kind], stored, "local");
|
|
11043
11090
|
} catch (error) {
|
|
11044
|
-
logger$
|
|
11091
|
+
logger$31.error(`[DeviceController] Failed to persist device selection for ${kind}:`, error);
|
|
11045
11092
|
}
|
|
11046
11093
|
}
|
|
11047
11094
|
async loadPersistedDevices() {
|
|
@@ -11057,7 +11104,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11057
11104
|
[kind]: stored
|
|
11058
11105
|
};
|
|
11059
11106
|
} catch (error) {
|
|
11060
|
-
logger$
|
|
11107
|
+
logger$31.error(`[DeviceController] Failed to load persisted device for ${kind}:`, error);
|
|
11061
11108
|
}
|
|
11062
11109
|
}
|
|
11063
11110
|
/** Clears device history, persisted selections, and re-enumerates devices. */
|
|
@@ -11075,7 +11122,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11075
11122
|
this.disableDeviceMonitoring();
|
|
11076
11123
|
this.webRTCApiProvider.mediaDevices.addEventListener("devicechange", this.deviceChangeHandler);
|
|
11077
11124
|
if (PreferencesContainer.instance.devicePollingInterval > 0) this._devicesPoolingSubscription = (0, import_cjs$29.interval)(PreferencesContainer.instance.devicePollingInterval).subscribe(() => {
|
|
11078
|
-
logger$
|
|
11125
|
+
logger$31.debug("[DeviceController] Polling devices due to interval");
|
|
11079
11126
|
this.enumerateDevices();
|
|
11080
11127
|
});
|
|
11081
11128
|
this.enumerateDevices();
|
|
@@ -11101,13 +11148,13 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11101
11148
|
videoinput: []
|
|
11102
11149
|
});
|
|
11103
11150
|
this._devicesState$.next(devicesByKind);
|
|
11104
|
-
logger$
|
|
11151
|
+
logger$31.debug("[DeviceController] Devices enumerated:", {
|
|
11105
11152
|
audioInputs: devicesByKind.audioinput.length,
|
|
11106
11153
|
audioOutputs: devicesByKind.audiooutput.length,
|
|
11107
11154
|
videoInputs: devicesByKind.videoinput.length
|
|
11108
11155
|
});
|
|
11109
11156
|
} catch (error) {
|
|
11110
|
-
logger$
|
|
11157
|
+
logger$31.error("[DeviceController] Failed to enumerate devices:", error);
|
|
11111
11158
|
this._errors$.next(toError(error));
|
|
11112
11159
|
}
|
|
11113
11160
|
}
|
|
@@ -11123,7 +11170,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
11123
11170
|
stream.getTracks().forEach((t) => t.stop());
|
|
11124
11171
|
return capabilities;
|
|
11125
11172
|
} catch (error) {
|
|
11126
|
-
logger$
|
|
11173
|
+
logger$31.error("[DeviceController] Failed to get device capabilities:", error);
|
|
11127
11174
|
this._errors$.next(toError(error));
|
|
11128
11175
|
throw error;
|
|
11129
11176
|
}
|
|
@@ -11374,7 +11421,7 @@ var DependencyContainer = class {
|
|
|
11374
11421
|
|
|
11375
11422
|
//#endregion
|
|
11376
11423
|
//#region src/controllers/CryptoController.ts
|
|
11377
|
-
const logger$
|
|
11424
|
+
const logger$30 = getLogger();
|
|
11378
11425
|
const DPOP_DB_NAME = "sw-dpop";
|
|
11379
11426
|
const DPOP_DB_VERSION = 1;
|
|
11380
11427
|
const DPOP_STORE_NAME = "keys";
|
|
@@ -11433,7 +11480,7 @@ async function loadKeyPairFromDB() {
|
|
|
11433
11480
|
tx.oncomplete = () => db.close();
|
|
11434
11481
|
});
|
|
11435
11482
|
} catch (error) {
|
|
11436
|
-
logger$
|
|
11483
|
+
logger$30.warn("[DPoP] Failed to load key pair from IndexedDB:", error);
|
|
11437
11484
|
return null;
|
|
11438
11485
|
}
|
|
11439
11486
|
}
|
|
@@ -11453,7 +11500,7 @@ async function saveKeyPairToDB(keyPair) {
|
|
|
11453
11500
|
};
|
|
11454
11501
|
});
|
|
11455
11502
|
} catch (error) {
|
|
11456
|
-
logger$
|
|
11503
|
+
logger$30.warn("[DPoP] Failed to save key pair to IndexedDB:", error);
|
|
11457
11504
|
}
|
|
11458
11505
|
}
|
|
11459
11506
|
async function deleteKeyPairFromDB() {
|
|
@@ -11472,7 +11519,7 @@ async function deleteKeyPairFromDB() {
|
|
|
11472
11519
|
};
|
|
11473
11520
|
});
|
|
11474
11521
|
} catch (error) {
|
|
11475
|
-
logger$
|
|
11522
|
+
logger$30.warn("[DPoP] Failed to delete key pair from IndexedDB:", error);
|
|
11476
11523
|
}
|
|
11477
11524
|
}
|
|
11478
11525
|
/**
|
|
@@ -11532,13 +11579,13 @@ var CryptoController = class {
|
|
|
11532
11579
|
this._publicJwk = await crypto.subtle.exportKey("jwk", stored.publicKey);
|
|
11533
11580
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11534
11581
|
this._initialized = true;
|
|
11535
|
-
logger$
|
|
11582
|
+
logger$30.debug("[DPoP] Key pair restored from IndexedDB, fingerprint:", this._fingerprint);
|
|
11536
11583
|
return this._fingerprint;
|
|
11537
11584
|
} catch (error) {
|
|
11538
|
-
logger$
|
|
11585
|
+
logger$30.warn("[DPoP] Stored key pair unusable, generating new one:", error);
|
|
11539
11586
|
await deleteKeyPairFromDB();
|
|
11540
11587
|
}
|
|
11541
|
-
logger$
|
|
11588
|
+
logger$30.debug("[DPoP] Generating RSA key pair");
|
|
11542
11589
|
this._keyPair = await crypto.subtle.generateKey({
|
|
11543
11590
|
name: "RSASSA-PKCS1-v1_5",
|
|
11544
11591
|
modulusLength: 2048,
|
|
@@ -11553,7 +11600,7 @@ var CryptoController = class {
|
|
|
11553
11600
|
this._fingerprint = await computeJwkThumbprint(this._publicJwk);
|
|
11554
11601
|
this._initialized = true;
|
|
11555
11602
|
await saveKeyPairToDB(this._keyPair);
|
|
11556
|
-
logger$
|
|
11603
|
+
logger$30.debug("[DPoP] Key pair generated and persisted, fingerprint:", this._fingerprint);
|
|
11557
11604
|
return this._fingerprint;
|
|
11558
11605
|
}
|
|
11559
11606
|
/**
|
|
@@ -11619,7 +11666,7 @@ var CryptoController = class {
|
|
|
11619
11666
|
this._fingerprint = null;
|
|
11620
11667
|
this._initialized = false;
|
|
11621
11668
|
deleteKeyPairFromDB();
|
|
11622
|
-
logger$
|
|
11669
|
+
logger$30.debug("[DPoP] Controller destroyed");
|
|
11623
11670
|
}
|
|
11624
11671
|
get publicJwk() {
|
|
11625
11672
|
if (!this._publicJwk) throw new DPoPInitError("CryptoController not initialized. Call init() first.");
|
|
@@ -11643,7 +11690,7 @@ var CryptoController = class {
|
|
|
11643
11690
|
//#endregion
|
|
11644
11691
|
//#region src/controllers/NetworkMonitor.ts
|
|
11645
11692
|
var import_cjs$28 = require_cjs();
|
|
11646
|
-
const logger$
|
|
11693
|
+
const logger$29 = getLogger();
|
|
11647
11694
|
/**
|
|
11648
11695
|
* Safely check whether we are running in a browser environment
|
|
11649
11696
|
* with `window` and the relevant event targets.
|
|
@@ -11700,7 +11747,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11700
11747
|
}
|
|
11701
11748
|
attachListeners() {
|
|
11702
11749
|
if (!hasBrowserNetworkEvents()) {
|
|
11703
|
-
logger$
|
|
11750
|
+
logger$29.debug("NetworkMonitor: no browser environment detected, skipping event listeners");
|
|
11704
11751
|
return;
|
|
11705
11752
|
}
|
|
11706
11753
|
window.addEventListener("online", this._onOnline);
|
|
@@ -11708,7 +11755,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11708
11755
|
const connection = getNetworkConnection();
|
|
11709
11756
|
if (connection) connection.addEventListener("change", this._onConnectionChange);
|
|
11710
11757
|
this._listenersAttached = true;
|
|
11711
|
-
logger$
|
|
11758
|
+
logger$29.debug("NetworkMonitor: event listeners attached");
|
|
11712
11759
|
}
|
|
11713
11760
|
removeListeners() {
|
|
11714
11761
|
if (!this._listenersAttached) return;
|
|
@@ -11719,10 +11766,10 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11719
11766
|
if (connection) connection.removeEventListener("change", this._onConnectionChange);
|
|
11720
11767
|
}
|
|
11721
11768
|
this._listenersAttached = false;
|
|
11722
|
-
logger$
|
|
11769
|
+
logger$29.debug("NetworkMonitor: event listeners removed");
|
|
11723
11770
|
}
|
|
11724
11771
|
handleOnline() {
|
|
11725
|
-
logger$
|
|
11772
|
+
logger$29.info("NetworkMonitor: browser went online");
|
|
11726
11773
|
this._isOnline$.next(true);
|
|
11727
11774
|
this._networkChange$.next({
|
|
11728
11775
|
type: "online",
|
|
@@ -11731,7 +11778,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11731
11778
|
});
|
|
11732
11779
|
}
|
|
11733
11780
|
handleOffline() {
|
|
11734
|
-
logger$
|
|
11781
|
+
logger$29.info("NetworkMonitor: browser went offline");
|
|
11735
11782
|
this._isOnline$.next(false);
|
|
11736
11783
|
this._networkChange$.next({
|
|
11737
11784
|
type: "offline",
|
|
@@ -11740,7 +11787,7 @@ var NetworkMonitor = class extends Destroyable {
|
|
|
11740
11787
|
}
|
|
11741
11788
|
handleConnectionChange() {
|
|
11742
11789
|
const networkType = getNetworkType();
|
|
11743
|
-
logger$
|
|
11790
|
+
logger$29.info(`NetworkMonitor: connection changed — effectiveType=${networkType ?? "unknown"}`);
|
|
11744
11791
|
this._networkChange$.next({
|
|
11745
11792
|
type: "connection_change",
|
|
11746
11793
|
timestamp: Date.now(),
|
|
@@ -11856,7 +11903,7 @@ function getNavigatorMediaDevices() {
|
|
|
11856
11903
|
//#endregion
|
|
11857
11904
|
//#region src/controllers/PreflightRunner.ts
|
|
11858
11905
|
var import_cjs$27 = require_cjs();
|
|
11859
|
-
const logger$
|
|
11906
|
+
const logger$28 = getLogger();
|
|
11860
11907
|
const DEFAULT_MEDIA_TEST_DURATION_S = 10;
|
|
11861
11908
|
const ICE_GATHERING_TIMEOUT_MS = 1e4;
|
|
11862
11909
|
const SIGNALING_RTT_TIMEOUT_MS = 5e3;
|
|
@@ -11905,7 +11952,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11905
11952
|
if (!this._options.skipMediaTest) try {
|
|
11906
11953
|
bandwidth = await this.testMediaBandwidth(destination);
|
|
11907
11954
|
} catch (error) {
|
|
11908
|
-
logger$
|
|
11955
|
+
logger$28.warn("[PreflightRunner] Media bandwidth test failed:", error);
|
|
11909
11956
|
warnings.push("Media bandwidth test failed");
|
|
11910
11957
|
}
|
|
11911
11958
|
return {
|
|
@@ -11917,7 +11964,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11917
11964
|
warnings
|
|
11918
11965
|
};
|
|
11919
11966
|
} catch (error) {
|
|
11920
|
-
logger$
|
|
11967
|
+
logger$28.error("[PreflightRunner] Preflight test failed:", error);
|
|
11921
11968
|
throw new PreflightError("preflight", error instanceof Error ? error : new Error(String(error)));
|
|
11922
11969
|
} finally {
|
|
11923
11970
|
this.destroy();
|
|
@@ -11948,7 +11995,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
11948
11995
|
if (track.kind === "video" && track.readyState === "live") videoWorking = true;
|
|
11949
11996
|
}
|
|
11950
11997
|
} catch (error) {
|
|
11951
|
-
logger$
|
|
11998
|
+
logger$28.warn("[PreflightRunner] Device test failed:", error);
|
|
11952
11999
|
} finally {
|
|
11953
12000
|
if (audioStream) audioStream.getTracks().forEach((t) => t.stop());
|
|
11954
12001
|
}
|
|
@@ -12006,7 +12053,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
12006
12053
|
rttMs
|
|
12007
12054
|
};
|
|
12008
12055
|
} catch (error) {
|
|
12009
|
-
logger$
|
|
12056
|
+
logger$28.warn("[PreflightRunner] ICE connectivity test failed:", error);
|
|
12010
12057
|
return {
|
|
12011
12058
|
type: "failed",
|
|
12012
12059
|
turnReachable: false,
|
|
@@ -12054,7 +12101,7 @@ var PreflightRunner = class extends Destroyable {
|
|
|
12054
12101
|
//#endregion
|
|
12055
12102
|
//#region src/controllers/VisibilityController.ts
|
|
12056
12103
|
var import_cjs$26 = require_cjs();
|
|
12057
|
-
const logger$
|
|
12104
|
+
const logger$27 = getLogger();
|
|
12058
12105
|
/**
|
|
12059
12106
|
* Checks whether the document visibility API is available.
|
|
12060
12107
|
*/
|
|
@@ -12091,8 +12138,8 @@ var VisibilityController = class extends Destroyable {
|
|
|
12091
12138
|
this._boundHandler = this._handleVisibilityChange.bind(this);
|
|
12092
12139
|
if (this._hasVisibilityApi) {
|
|
12093
12140
|
document.addEventListener("visibilitychange", this._boundHandler);
|
|
12094
|
-
logger$
|
|
12095
|
-
} else logger$
|
|
12141
|
+
logger$27.debug("VisibilityController: listening for visibilitychange events");
|
|
12142
|
+
} else logger$27.debug("VisibilityController: document visibility API not available, defaulting to visible");
|
|
12096
12143
|
}
|
|
12097
12144
|
/**
|
|
12098
12145
|
* Observable of the current visibility state.
|
|
@@ -12117,7 +12164,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
12117
12164
|
destroy() {
|
|
12118
12165
|
if (this._hasVisibilityApi) {
|
|
12119
12166
|
document.removeEventListener("visibilitychange", this._boundHandler);
|
|
12120
|
-
logger$
|
|
12167
|
+
logger$27.debug("VisibilityController: removed visibilitychange listener");
|
|
12121
12168
|
}
|
|
12122
12169
|
super.destroy();
|
|
12123
12170
|
}
|
|
@@ -12135,7 +12182,7 @@ var VisibilityController = class extends Destroyable {
|
|
|
12135
12182
|
timestamp: Date.now()
|
|
12136
12183
|
};
|
|
12137
12184
|
this._visibilityChange$.next(changeEvent);
|
|
12138
|
-
logger$
|
|
12185
|
+
logger$27.debug("VisibilityController: visibility changed", {
|
|
12139
12186
|
from: previousState,
|
|
12140
12187
|
to: newState
|
|
12141
12188
|
});
|
|
@@ -12417,7 +12464,7 @@ function isRequesterValidationError(error) {
|
|
|
12417
12464
|
|
|
12418
12465
|
//#endregion
|
|
12419
12466
|
//#region src/managers/AttachManager.ts
|
|
12420
|
-
const logger$
|
|
12467
|
+
const logger$26 = getLogger();
|
|
12421
12468
|
var AttachManager = class {
|
|
12422
12469
|
constructor(storage, deviceController, reconnectCallsTimeout, attachKey, credentialRecovered) {
|
|
12423
12470
|
this.storage = storage;
|
|
@@ -12439,7 +12486,7 @@ var AttachManager = class {
|
|
|
12439
12486
|
try {
|
|
12440
12487
|
return await this.storage.getItem(this.attachKey) ?? {};
|
|
12441
12488
|
} catch (error) {
|
|
12442
|
-
logger$
|
|
12489
|
+
logger$26.warn("[AttachManager] Failed to retrieve attached calls from storage", error);
|
|
12443
12490
|
return {};
|
|
12444
12491
|
}
|
|
12445
12492
|
}
|
|
@@ -12447,7 +12494,7 @@ var AttachManager = class {
|
|
|
12447
12494
|
try {
|
|
12448
12495
|
await this.storage.setItem(this.attachKey, attached);
|
|
12449
12496
|
} catch (error) {
|
|
12450
|
-
logger$
|
|
12497
|
+
logger$26.warn("[AttachManager] Failed to write attached calls to storage", error);
|
|
12451
12498
|
}
|
|
12452
12499
|
}
|
|
12453
12500
|
/**
|
|
@@ -12466,7 +12513,7 @@ var AttachManager = class {
|
|
|
12466
12513
|
}
|
|
12467
12514
|
async attach(call) {
|
|
12468
12515
|
if (!call.to) {
|
|
12469
|
-
logger$
|
|
12516
|
+
logger$26.warn("[AttachManager] Skip attach for calls with no destination");
|
|
12470
12517
|
return;
|
|
12471
12518
|
}
|
|
12472
12519
|
const destination = call.to;
|
|
@@ -12526,25 +12573,25 @@ var AttachManager = class {
|
|
|
12526
12573
|
callId,
|
|
12527
12574
|
...options
|
|
12528
12575
|
});
|
|
12529
|
-
logger$
|
|
12576
|
+
logger$26.info(`[AttachManager] Reattached call ${callId} (attempt ${attempt})`);
|
|
12530
12577
|
succeeded = true;
|
|
12531
12578
|
break;
|
|
12532
12579
|
} catch (error) {
|
|
12533
|
-
logger$
|
|
12580
|
+
logger$26.warn(`[AttachManager] Reattach attempt ${attempt}/3 failed for call ${callId}:`, error);
|
|
12534
12581
|
if (isRequesterValidationError(error)) {
|
|
12535
12582
|
refusedOnCredentials = true;
|
|
12536
|
-
logger$
|
|
12583
|
+
logger$26.warn(`[AttachManager] Reattach of ${callId} was refused on credentials; not retrying.`);
|
|
12537
12584
|
break;
|
|
12538
12585
|
}
|
|
12539
12586
|
if (attempt < 3) await new Promise((r) => setTimeout(r, (attempt + 1) * 1e3));
|
|
12540
12587
|
}
|
|
12541
12588
|
if (!succeeded) if (this.credentialRecovered() && !refusedOnCredentials) {
|
|
12542
|
-
logger$
|
|
12589
|
+
logger$26.warn(`[AttachManager] Reattach of ${callId} was denied after a verified reauthentication, removing reference`);
|
|
12543
12590
|
await this.detach({
|
|
12544
12591
|
id: callId,
|
|
12545
12592
|
mediaDirections: attachment.mediaDirections
|
|
12546
12593
|
});
|
|
12547
|
-
} else logger$
|
|
12594
|
+
} else logger$26.warn(`[AttachManager] Reattach failed for call ${callId}; keeping the reference (credential refused or never proven good)`);
|
|
12548
12595
|
}
|
|
12549
12596
|
}
|
|
12550
12597
|
/**
|
|
@@ -12645,12 +12692,12 @@ var require_race = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
12645
12692
|
exports.race = void 0;
|
|
12646
12693
|
var argsOrArgArray_1 = require_argsOrArgArray();
|
|
12647
12694
|
var raceWith_1$1 = require_raceWith();
|
|
12648
|
-
function race$
|
|
12695
|
+
function race$3() {
|
|
12649
12696
|
var args = [];
|
|
12650
12697
|
for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
|
|
12651
12698
|
return raceWith_1$1.raceWith.apply(void 0, __spreadArray([], __read(argsOrArgArray_1.argsOrArgArray(args))));
|
|
12652
12699
|
}
|
|
12653
|
-
exports.race = race$
|
|
12700
|
+
exports.race = race$3;
|
|
12654
12701
|
}));
|
|
12655
12702
|
|
|
12656
12703
|
//#endregion
|
|
@@ -13710,7 +13757,7 @@ function toggleHandraiseMethod(is) {
|
|
|
13710
13757
|
|
|
13711
13758
|
//#endregion
|
|
13712
13759
|
//#region src/core/entities/Participant.ts
|
|
13713
|
-
const logger$
|
|
13760
|
+
const logger$25 = getLogger();
|
|
13714
13761
|
const initialState = {};
|
|
13715
13762
|
/**
|
|
13716
13763
|
* Represents a participant in a call.
|
|
@@ -14182,8 +14229,16 @@ var SelfParticipant = class extends Participant {
|
|
|
14182
14229
|
/**
|
|
14183
14230
|
* Starts sharing the local screen.
|
|
14184
14231
|
*
|
|
14232
|
+
* A call carries at most one screen share. Read `screenShareStatus` before
|
|
14233
|
+
* calling and treat `'starting'`/`'stopping'` as busy.
|
|
14234
|
+
*
|
|
14185
14235
|
* The call is unaffected when acquisition fails.
|
|
14186
14236
|
*
|
|
14237
|
+
* Known issue: stopping the share before its leg connects can leave this
|
|
14238
|
+
* promise pending until the call ends, so do not gate UI on it.
|
|
14239
|
+
*
|
|
14240
|
+
* @throws {ScreenShareAlreadyActiveError} When this call is already
|
|
14241
|
+
* sharing a screen. Call {@link stopScreenShare} before starting another.
|
|
14187
14242
|
* @throws The raw `getDisplayMedia` error. A dismissed picker or a
|
|
14188
14243
|
* permission denial rejects with a `NotAllowedError` `DOMException` —
|
|
14189
14244
|
* inspect `error.name` to tell benign cancels apart from real failures.
|
|
@@ -14192,7 +14247,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14192
14247
|
try {
|
|
14193
14248
|
await this.vertoManager.addScreenMedia();
|
|
14194
14249
|
} catch (error) {
|
|
14195
|
-
logger$
|
|
14250
|
+
logger$25.error("[Participant.startScreenShare] Screen share error:", error);
|
|
14196
14251
|
throw error;
|
|
14197
14252
|
}
|
|
14198
14253
|
}
|
|
@@ -14213,14 +14268,18 @@ var SelfParticipant = class extends Participant {
|
|
|
14213
14268
|
*
|
|
14214
14269
|
* The call is unaffected when acquisition fails.
|
|
14215
14270
|
*
|
|
14271
|
+
* Known issue: removing the device before its leg connects can leave this
|
|
14272
|
+
* promise pending until the call ends, so do not gate UI on it.
|
|
14273
|
+
*
|
|
14216
14274
|
* @throws The raw `getUserMedia` error (e.g. `NotAllowedError` on
|
|
14217
|
-
* permission denial) — inspect `error.name` to decide how to react
|
|
14275
|
+
* permission denial) — inspect `error.name` to decide how to react — or
|
|
14276
|
+
* `AuxiliaryLegTimeoutError` if the leg does not connect in time.
|
|
14218
14277
|
*/
|
|
14219
14278
|
async addAdditionalDevice(options) {
|
|
14220
14279
|
try {
|
|
14221
14280
|
await this.vertoManager.addInputDevice(options);
|
|
14222
14281
|
} catch (error) {
|
|
14223
|
-
logger$
|
|
14282
|
+
logger$25.error("[Participant.addAdditionalDevice] Additional device error:", error);
|
|
14224
14283
|
throw error;
|
|
14225
14284
|
}
|
|
14226
14285
|
}
|
|
@@ -14283,7 +14342,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14283
14342
|
*/
|
|
14284
14343
|
exitStudioModeIfActive() {
|
|
14285
14344
|
if (this._studioAudio$.value) {
|
|
14286
|
-
logger$
|
|
14345
|
+
logger$25.debug("[SelfParticipant] Exiting studio audio mode due to individual flag toggle");
|
|
14287
14346
|
this._studioAudio$.next(false);
|
|
14288
14347
|
}
|
|
14289
14348
|
}
|
|
@@ -14307,7 +14366,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14307
14366
|
try {
|
|
14308
14367
|
await super.mute();
|
|
14309
14368
|
} catch (error) {
|
|
14310
|
-
logger$
|
|
14369
|
+
logger$25.warn("[Participant.toggleAudioInput] Server Error while muting audio input, proceeding with local toggle anyway", error);
|
|
14311
14370
|
} finally {
|
|
14312
14371
|
this.vertoManager.muteMainAudioInputDevice();
|
|
14313
14372
|
}
|
|
@@ -14317,7 +14376,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14317
14376
|
try {
|
|
14318
14377
|
await super.unmute();
|
|
14319
14378
|
} catch (error) {
|
|
14320
|
-
logger$
|
|
14379
|
+
logger$25.warn("[Participant.toggleAudioInput] Server Error while unmuting audio input, proceeding with local toggle anyway", error);
|
|
14321
14380
|
} finally {
|
|
14322
14381
|
await this.vertoManager.unmuteMainAudioInputDevice();
|
|
14323
14382
|
}
|
|
@@ -14327,7 +14386,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14327
14386
|
try {
|
|
14328
14387
|
await super.muteVideo();
|
|
14329
14388
|
} catch (error) {
|
|
14330
|
-
logger$
|
|
14389
|
+
logger$25.warn("[Participant.toggleVideoInput] Server Error while muting video input, proceeding with local toggle anyway", error);
|
|
14331
14390
|
} finally {
|
|
14332
14391
|
this.vertoManager.muteMainVideoInputDevice();
|
|
14333
14392
|
}
|
|
@@ -14337,7 +14396,7 @@ var SelfParticipant = class extends Participant {
|
|
|
14337
14396
|
try {
|
|
14338
14397
|
await super.unmuteVideo();
|
|
14339
14398
|
} catch (error) {
|
|
14340
|
-
logger$
|
|
14399
|
+
logger$25.warn("[Participant.toggleVideoInput] Server Error while unmuting video input, proceeding with local toggle anyway", error);
|
|
14341
14400
|
} finally {
|
|
14342
14401
|
await this.vertoManager.unmuteMainVideoInputDevice();
|
|
14343
14402
|
}
|
|
@@ -14542,7 +14601,7 @@ function filterAs(predicate, resultPath) {
|
|
|
14542
14601
|
//#endregion
|
|
14543
14602
|
//#region src/operators/throwOnRPCError.ts
|
|
14544
14603
|
var import_cjs$21 = require_cjs();
|
|
14545
|
-
const logger$
|
|
14604
|
+
const logger$24 = getLogger();
|
|
14546
14605
|
/**
|
|
14547
14606
|
* RxJS operator that throws a {@link JSONRPCError} when the RPC response contains an error.
|
|
14548
14607
|
* Passes successful responses through unchanged.
|
|
@@ -14550,14 +14609,14 @@ const logger$23 = getLogger();
|
|
|
14550
14609
|
function throwOnRPCError() {
|
|
14551
14610
|
return (0, import_cjs$21.map)((response) => {
|
|
14552
14611
|
if (response.error) {
|
|
14553
|
-
logger$
|
|
14612
|
+
logger$24.error("[throwOnRPCError] RPC error response:", {
|
|
14554
14613
|
code: response.error.code,
|
|
14555
14614
|
message: response.error.message,
|
|
14556
14615
|
data: response.error.data
|
|
14557
14616
|
});
|
|
14558
14617
|
throw new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14559
14618
|
}
|
|
14560
|
-
logger$
|
|
14619
|
+
logger$24.debug("[throwOnRPCError] RPC successful response:", response);
|
|
14561
14620
|
return response;
|
|
14562
14621
|
});
|
|
14563
14622
|
}
|
|
@@ -14565,7 +14624,7 @@ function throwOnRPCError() {
|
|
|
14565
14624
|
//#endregion
|
|
14566
14625
|
//#region src/managers/CallEventsManager.ts
|
|
14567
14626
|
var import_cjs$20 = require_cjs();
|
|
14568
|
-
const logger$
|
|
14627
|
+
const logger$23 = getLogger();
|
|
14569
14628
|
const initialSessionState = {};
|
|
14570
14629
|
/** @internal */
|
|
14571
14630
|
var CallEventsManager = class extends Destroyable {
|
|
@@ -14669,7 +14728,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14669
14728
|
}
|
|
14670
14729
|
initSubscriptions() {
|
|
14671
14730
|
this.subscribeTo(this.callJoinedEvent$, (callJoinedEvent) => {
|
|
14672
|
-
logger$
|
|
14731
|
+
logger$23.debug("[CallEventsManager] Handling call.joined event for call/session IDs:", {
|
|
14673
14732
|
callId: callJoinedEvent.call_id,
|
|
14674
14733
|
roomSessionId: callJoinedEvent.room_session_id
|
|
14675
14734
|
});
|
|
@@ -14696,19 +14755,19 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14696
14755
|
if (this._self$.value?.capabilities.setLayout) this.updateLayouts();
|
|
14697
14756
|
});
|
|
14698
14757
|
this.subscribeTo(this.memberUpdates$, (member) => {
|
|
14699
|
-
logger$
|
|
14758
|
+
logger$23.debug("[CallEventsManager] Handling member update event for member ID:", member);
|
|
14700
14759
|
this.upsertParticipant(member);
|
|
14701
14760
|
});
|
|
14702
14761
|
this.subscribeTo(this.webRtcCallSession.memberLeft$, (memberLeftEvent) => {
|
|
14703
|
-
logger$
|
|
14762
|
+
logger$23.debug("[CallEventsManager] Handling member.left event for member ID:", memberLeftEvent.member.member_id);
|
|
14704
14763
|
const participants = { ...this._participants$.value };
|
|
14705
14764
|
if (memberLeftEvent.member.member_id in participants) {
|
|
14706
14765
|
delete participants[memberLeftEvent.member.member_id];
|
|
14707
14766
|
this._participants$.next(participants);
|
|
14708
|
-
} else logger$
|
|
14767
|
+
} else logger$23.warn(`[CallEventsManager] Received member.left event for unknown member ID: ${memberLeftEvent.member.member_id}`);
|
|
14709
14768
|
});
|
|
14710
14769
|
this.subscribeTo(this.webRtcCallSession.callUpdated$, (callUpdatedEvent) => {
|
|
14711
|
-
logger$
|
|
14770
|
+
logger$23.debug("[CallEventsManager] Handling call.updated event:", callUpdatedEvent);
|
|
14712
14771
|
const roomSession = callUpdatedEvent.room_session;
|
|
14713
14772
|
this._sessionState$.next({
|
|
14714
14773
|
...this._sessionState$.value,
|
|
@@ -14723,7 +14782,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14723
14782
|
});
|
|
14724
14783
|
});
|
|
14725
14784
|
this.subscribeTo(this.layoutChangedEvent$, (layoutChangedEvent) => {
|
|
14726
|
-
logger$
|
|
14785
|
+
logger$23.debug("[CallEventsManager] Handling layout.changed event:", layoutChangedEvent);
|
|
14727
14786
|
this._sessionState$.next({
|
|
14728
14787
|
...this._sessionState$.value,
|
|
14729
14788
|
layout_name: layoutChangedEvent.id,
|
|
@@ -14733,10 +14792,10 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14733
14792
|
});
|
|
14734
14793
|
}
|
|
14735
14794
|
updateParticipantPositions(layoutChangedEvent) {
|
|
14736
|
-
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$
|
|
14795
|
+
if (Object.keys(this._participants$.value).length > 0 && !layoutChangedEvent.layers.some((layer) => !!layer.member_id)) logger$23.warn("[CallEventsManager] No layers with member_id found in layout.changed event. Nothing to update.");
|
|
14737
14796
|
layoutChangedEvent.layers.filter((layer) => !!layer.member_id).filter((layer) => {
|
|
14738
14797
|
if (!(layer.member_id in this._participants$.value)) {
|
|
14739
|
-
logger$
|
|
14798
|
+
logger$23.warn(`[CallEventsManager] Skipping layout layer for unknown member_id: ${layer.member_id}`);
|
|
14740
14799
|
return false;
|
|
14741
14800
|
}
|
|
14742
14801
|
return true;
|
|
@@ -14756,7 +14815,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14756
14815
|
this.webRtcCallSession.executeMethod(this.selfId, "call.layout.list", {}).then((response) => {
|
|
14757
14816
|
const layouts = response.result?.layouts;
|
|
14758
14817
|
if (!layouts) {
|
|
14759
|
-
logger$
|
|
14818
|
+
logger$23.warn("[CallEventsManager] Layout list response carried no layouts; keeping current layouts");
|
|
14760
14819
|
return;
|
|
14761
14820
|
}
|
|
14762
14821
|
this._sessionState$.next({
|
|
@@ -14764,7 +14823,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14764
14823
|
layouts
|
|
14765
14824
|
});
|
|
14766
14825
|
}).catch((error) => {
|
|
14767
|
-
logger$
|
|
14826
|
+
logger$23.error("[CallEventsManager] Error fetching layouts:", error);
|
|
14768
14827
|
});
|
|
14769
14828
|
}
|
|
14770
14829
|
updateParticipants(members) {
|
|
@@ -14780,7 +14839,7 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14780
14839
|
}
|
|
14781
14840
|
const participant = this._participants$.value[member.member_id];
|
|
14782
14841
|
const oldValue = participant.value;
|
|
14783
|
-
logger$
|
|
14842
|
+
logger$23.debug("[CallEventsManager] Updating participant:", member.member_id, {
|
|
14784
14843
|
oldValue,
|
|
14785
14844
|
newValue: member
|
|
14786
14845
|
});
|
|
@@ -14793,17 +14852,17 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14793
14852
|
}
|
|
14794
14853
|
get callJoinedEvent$() {
|
|
14795
14854
|
return this.cachedObservable("callJoinedEvent$", () => this.webRtcCallSession.callEvent$.pipe((0, import_cjs$20.filter)(isCallJoinedPayload), (0, import_cjs$20.tap)((event) => {
|
|
14796
|
-
logger$
|
|
14855
|
+
logger$23.debug("[CallEventsManager] Call joined event:", event);
|
|
14797
14856
|
})));
|
|
14798
14857
|
}
|
|
14799
14858
|
get layoutChangedEvent$() {
|
|
14800
14859
|
return this.cachedObservable("layoutChangedEvent$", () => this.webRtcCallSession.callEvent$.pipe(filterAs(isLayoutChangedPayload, "layout"), (0, import_cjs$20.tap)((event) => {
|
|
14801
|
-
logger$
|
|
14860
|
+
logger$23.debug("[CallEventsManager] Layout changed event:", event);
|
|
14802
14861
|
})));
|
|
14803
14862
|
}
|
|
14804
14863
|
get memberUpdates$() {
|
|
14805
14864
|
return this.cachedObservable("memberUpdates$", () => (0, import_cjs$20.merge)(this.webRtcCallSession.memberJoined$, this.webRtcCallSession.memberUpdated$, this.webRtcCallSession.memberTalking$).pipe((0, import_cjs$20.map)((event) => event.member), (0, import_cjs$20.tap)((event) => {
|
|
14806
|
-
logger$
|
|
14865
|
+
logger$23.debug("[CallEventsManager] Member update event:", event);
|
|
14807
14866
|
})));
|
|
14808
14867
|
}
|
|
14809
14868
|
destroy() {
|
|
@@ -14822,6 +14881,111 @@ var CallEventsManager = class extends Destroyable {
|
|
|
14822
14881
|
}
|
|
14823
14882
|
};
|
|
14824
14883
|
|
|
14884
|
+
//#endregion
|
|
14885
|
+
//#region src/controllers/ConstraintFallbackHelper.ts
|
|
14886
|
+
/**
|
|
14887
|
+
* ConstraintFallbackHelper - Provides getUserMedia with automatic constraint
|
|
14888
|
+
* fallback on OverconstrainedError.
|
|
14889
|
+
*
|
|
14890
|
+
* When a specific device ID is requested, the helper tries progressively
|
|
14891
|
+
* looser constraints:
|
|
14892
|
+
* 1. `{ deviceId: { exact: deviceId } }` -- exact match
|
|
14893
|
+
* 2. `{ deviceId: deviceId }` -- preferred (browser may pick another)
|
|
14894
|
+
* 3. `{}` -- no constraint, browser default
|
|
14895
|
+
*
|
|
14896
|
+
* This prevents stale device IDs from blocking call setup.
|
|
14897
|
+
*
|
|
14898
|
+
* @see Section 5.8 and Section 11 of the Implementation Guide
|
|
14899
|
+
*/
|
|
14900
|
+
const logger$22 = getLogger();
|
|
14901
|
+
/**
|
|
14902
|
+
* Attempts getUserMedia with progressively looser constraints.
|
|
14903
|
+
*
|
|
14904
|
+
* The function tries three levels of constraint specificity for the given
|
|
14905
|
+
* device kind. Each level is only attempted if the previous one fails with
|
|
14906
|
+
* an OverconstrainedError. Non-OverconstrainedError failures (e.g.,
|
|
14907
|
+
* NotAllowedError) are thrown immediately without fallback.
|
|
14908
|
+
*
|
|
14909
|
+
* @param mediaDevices - Anything exposing `getUserMedia` (a full
|
|
14910
|
+
* `WebRTCMediaDevices`, or a shim wrapping one)
|
|
14911
|
+
* @param constraints - The full MediaStreamConstraints to use as a base
|
|
14912
|
+
* @param kind - Which track kind to apply fallback to ('audio' | 'video')
|
|
14913
|
+
* @param deviceId - The device ID to try (if undefined, calls getUserMedia as-is)
|
|
14914
|
+
* @returns The stream and the fallback level that succeeded
|
|
14915
|
+
* @throws When all fallback levels fail, or when a non-OverconstrainedError occurs
|
|
14916
|
+
*/
|
|
14917
|
+
async function getUserMediaWithFallback(mediaDevices, constraints, kind, deviceId) {
|
|
14918
|
+
if (!deviceId) return {
|
|
14919
|
+
stream: await mediaDevices.getUserMedia(constraints),
|
|
14920
|
+
fallbackLevel: "default"
|
|
14921
|
+
};
|
|
14922
|
+
const baseConstraints = typeof constraints[kind] === "object" ? constraints[kind] : {};
|
|
14923
|
+
try {
|
|
14924
|
+
const exactConstraints = {
|
|
14925
|
+
...constraints,
|
|
14926
|
+
[kind]: {
|
|
14927
|
+
...baseConstraints,
|
|
14928
|
+
deviceId: { exact: deviceId }
|
|
14929
|
+
}
|
|
14930
|
+
};
|
|
14931
|
+
return {
|
|
14932
|
+
stream: await mediaDevices.getUserMedia(exactConstraints),
|
|
14933
|
+
fallbackLevel: "exact"
|
|
14934
|
+
};
|
|
14935
|
+
} catch (error) {
|
|
14936
|
+
if (!isOverconstrainedError(error)) throw error;
|
|
14937
|
+
logger$22.debug(`[ConstraintFallbackHelper] Exact constraint failed for ${kind}, trying preferred`, { deviceId });
|
|
14938
|
+
}
|
|
14939
|
+
try {
|
|
14940
|
+
const preferredConstraints = {
|
|
14941
|
+
...constraints,
|
|
14942
|
+
[kind]: {
|
|
14943
|
+
...baseConstraints,
|
|
14944
|
+
deviceId
|
|
14945
|
+
}
|
|
14946
|
+
};
|
|
14947
|
+
return {
|
|
14948
|
+
stream: await mediaDevices.getUserMedia(preferredConstraints),
|
|
14949
|
+
fallbackLevel: "preferred"
|
|
14950
|
+
};
|
|
14951
|
+
} catch (error) {
|
|
14952
|
+
if (!isOverconstrainedError(error)) throw error;
|
|
14953
|
+
logger$22.debug(`[ConstraintFallbackHelper] Preferred constraint failed for ${kind}, trying default`, { deviceId });
|
|
14954
|
+
}
|
|
14955
|
+
try {
|
|
14956
|
+
const defaultConstraints = {
|
|
14957
|
+
...constraints,
|
|
14958
|
+
[kind]: { ...baseConstraints }
|
|
14959
|
+
};
|
|
14960
|
+
if (typeof defaultConstraints[kind] === "object") {
|
|
14961
|
+
const { deviceId: _removed, ...rest } = defaultConstraints[kind];
|
|
14962
|
+
defaultConstraints[kind] = rest;
|
|
14963
|
+
}
|
|
14964
|
+
const stream = await mediaDevices.getUserMedia(defaultConstraints);
|
|
14965
|
+
logger$22.warn(`[ConstraintFallbackHelper] Fell back to browser default for ${kind}`, { requestedDeviceId: deviceId });
|
|
14966
|
+
return {
|
|
14967
|
+
stream,
|
|
14968
|
+
fallbackLevel: "default"
|
|
14969
|
+
};
|
|
14970
|
+
} catch (error) {
|
|
14971
|
+
logger$22.error(`[ConstraintFallbackHelper] All fallback levels exhausted for ${kind}`, {
|
|
14972
|
+
deviceId,
|
|
14973
|
+
error
|
|
14974
|
+
});
|
|
14975
|
+
throw error;
|
|
14976
|
+
}
|
|
14977
|
+
}
|
|
14978
|
+
/**
|
|
14979
|
+
* Checks whether an error is an OverconstrainedError.
|
|
14980
|
+
*
|
|
14981
|
+
* Browsers may throw either a native OverconstrainedError or a DOMException
|
|
14982
|
+
* with a specific name.
|
|
14983
|
+
*/
|
|
14984
|
+
function isOverconstrainedError(error) {
|
|
14985
|
+
if (error instanceof Error) return error.name === "OverconstrainedError" || error.name === "ConstraintNotSatisfiedError";
|
|
14986
|
+
return false;
|
|
14987
|
+
}
|
|
14988
|
+
|
|
14825
14989
|
//#endregion
|
|
14826
14990
|
//#region src/helpers/SDPHelper.ts
|
|
14827
14991
|
/**
|
|
@@ -15380,6 +15544,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15380
15544
|
this._localAudioTracks$ = this.createBehaviorSubject([]);
|
|
15381
15545
|
this._localVideoTracks$ = this.createBehaviorSubject([]);
|
|
15382
15546
|
this._mediaTrackEnded$ = this.createSubject();
|
|
15547
|
+
this._trackOrigins = /* @__PURE__ */ new WeakMap();
|
|
15383
15548
|
}
|
|
15384
15549
|
get localStream$() {
|
|
15385
15550
|
return this._localStream$.asObservable().pipe((0, import_cjs$17.takeUntil)(this.destroyed$));
|
|
@@ -15402,6 +15567,22 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15402
15567
|
get localVideoTracks() {
|
|
15403
15568
|
return this._localVideoTracks$.value;
|
|
15404
15569
|
}
|
|
15570
|
+
tagTracks(tracks, origin) {
|
|
15571
|
+
for (const track of tracks) this._trackOrigins.set(track, origin);
|
|
15572
|
+
}
|
|
15573
|
+
setTrackOrigin(track, origin) {
|
|
15574
|
+
this._trackOrigins.set(track, origin);
|
|
15575
|
+
}
|
|
15576
|
+
getTrackOrigin(track) {
|
|
15577
|
+
return this._trackOrigins.get(track);
|
|
15578
|
+
}
|
|
15579
|
+
/**
|
|
15580
|
+
* Fail-safe: an unrecorded track reads as not-a-device-capture, so a missed
|
|
15581
|
+
* tagging site leaves media alone rather than destroying it.
|
|
15582
|
+
*/
|
|
15583
|
+
isDeviceCapture(track) {
|
|
15584
|
+
return this._trackOrigins.get(track) === "device";
|
|
15585
|
+
}
|
|
15405
15586
|
/**
|
|
15406
15587
|
* Build the local media stream based on the provided options.
|
|
15407
15588
|
*/
|
|
@@ -15411,6 +15592,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15411
15592
|
if (this.options.inputAudioStream ?? this.options.inputVideoStream) {
|
|
15412
15593
|
const tracks = [...this.options.inputAudioStream?.getTracks() ?? [], ...this.options.inputVideoStream?.getTracks() ?? []];
|
|
15413
15594
|
stream = new MediaStream(tracks);
|
|
15595
|
+
this.tagTracks(tracks, "application");
|
|
15414
15596
|
} else if (this.options.propose === "screenshare") {
|
|
15415
15597
|
logger$19.debug("[LocalStreamController] Requesting display media for screen sharing with audio:", Boolean(this.options.inputAudioDeviceConstraints));
|
|
15416
15598
|
stream = await this.options.getDisplayMedia({
|
|
@@ -15418,6 +15600,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15418
15600
|
audio: Boolean(this.options.inputAudioDeviceConstraints)
|
|
15419
15601
|
});
|
|
15420
15602
|
logger$19.debug("[LocalStreamController] Screen share media obtained:", stream);
|
|
15603
|
+
this.tagTracks(stream.getTracks(), "display");
|
|
15421
15604
|
} else {
|
|
15422
15605
|
const constraints = {
|
|
15423
15606
|
audio: this.options.inputAudioDeviceConstraints,
|
|
@@ -15426,6 +15609,7 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15426
15609
|
logger$19.debug("[LocalStreamController] Requesting user media with constraints:", constraints);
|
|
15427
15610
|
stream = await this.options.getUserMedia(constraints);
|
|
15428
15611
|
logger$19.debug("[LocalStreamController] User media obtained:", stream);
|
|
15612
|
+
this.tagTracks(stream.getTracks(), "device");
|
|
15429
15613
|
}
|
|
15430
15614
|
this._localStream$.next(stream);
|
|
15431
15615
|
this._localAudioTracks$.next(stream.getAudioTracks());
|
|
@@ -15435,10 +15619,13 @@ var LocalStreamController = class extends Destroyable {
|
|
|
15435
15619
|
/**
|
|
15436
15620
|
* Add a local media track to the local stream.
|
|
15437
15621
|
* @param track - The MediaStreamTrack to add
|
|
15622
|
+
* @param origin - Defaults to `'device'`; every internal caller passes a
|
|
15623
|
+
* fresh `getUserMedia` capture.
|
|
15438
15624
|
* @returns The MediaStream (either existing or newly created)
|
|
15439
15625
|
*/
|
|
15440
|
-
addTrack(track) {
|
|
15626
|
+
addTrack(track, origin = "device") {
|
|
15441
15627
|
const localStream = this._localStream$.value ?? new MediaStream();
|
|
15628
|
+
this._trackOrigins.set(track, origin);
|
|
15442
15629
|
track.addEventListener("ended", this.mediaTrackEndedHandler);
|
|
15443
15630
|
localStream.addTrack(track);
|
|
15444
15631
|
this._localStream$.next(localStream);
|
|
@@ -15708,15 +15895,27 @@ var TransceiverController = class extends Destroyable {
|
|
|
15708
15895
|
for (let i = 0; i < Number(msStreamsNumber); i++) this.peerConnection.addTransceiver("video", { direction: "recvonly" });
|
|
15709
15896
|
}
|
|
15710
15897
|
}
|
|
15898
|
+
/**
|
|
15899
|
+
* @returns whether every live sender of the kind took the constraints. A
|
|
15900
|
+
* skipped non-device sender, an exhausted fallback, and having no live sender
|
|
15901
|
+
* at all all report `false` — `mediaParamsUpdated.applied` is built from this,
|
|
15902
|
+
* and an application told `true` cannot tell a working push from a no-op.
|
|
15903
|
+
*/
|
|
15711
15904
|
async updateSendersConstraints(kind, constraints) {
|
|
15712
15905
|
if (!constraints) {
|
|
15713
15906
|
this.stopTrackSender(kind);
|
|
15714
|
-
return
|
|
15907
|
+
return false;
|
|
15715
15908
|
}
|
|
15716
15909
|
const senders = this.peerConnection.getSenders().filter((sender) => sender.track?.kind === kind && sender.track.readyState === "live");
|
|
15910
|
+
let applied = senders.length > 0;
|
|
15717
15911
|
for (const sender of senders) {
|
|
15718
15912
|
const { track } = sender;
|
|
15719
15913
|
if (track) {
|
|
15914
|
+
if (!this.options.localStreamController.isDeviceCapture(track)) {
|
|
15915
|
+
logger$18.debug(`[TransceiverController] Skipping ${kind} constraints for a non-device track (origin: ${this.options.localStreamController.getTrackOrigin(track) ?? "unrecorded"}), track ${track.id}`);
|
|
15916
|
+
applied = false;
|
|
15917
|
+
continue;
|
|
15918
|
+
}
|
|
15720
15919
|
const constraintsToApply = {
|
|
15721
15920
|
...track.getConstraints(),
|
|
15722
15921
|
...constraints
|
|
@@ -15732,33 +15931,39 @@ var TransceiverController = class extends Destroyable {
|
|
|
15732
15931
|
} catch (fallbackError) {
|
|
15733
15932
|
logger$18.warn(`[TransceiverController] Track replacement fallback also failed for ${kind} track:`, fallbackError);
|
|
15734
15933
|
this.options.onError?.(new MediaTrackError("updateSendersConstraints", kind, fallbackError));
|
|
15934
|
+
applied = false;
|
|
15735
15935
|
}
|
|
15736
15936
|
}
|
|
15737
15937
|
}
|
|
15738
15938
|
}
|
|
15939
|
+
return applied;
|
|
15739
15940
|
}
|
|
15740
15941
|
/**
|
|
15741
|
-
* Fallback when applyConstraints fails
|
|
15742
|
-
* one via getUserMedia with the merged constraints (preserving the current
|
|
15743
|
-
* deviceId), replace the sender track, and update the localStream.
|
|
15942
|
+
* Fallback when applyConstraints fails, which on iOS Safari it silently does.
|
|
15744
15943
|
*
|
|
15745
|
-
*
|
|
15746
|
-
*
|
|
15944
|
+
* Order matters: acquiring before stopping means a failed acquisition leaves
|
|
15945
|
+
* the existing media playing. The deviceId goes through the fallback ladder
|
|
15946
|
+
* rather than pinned `{ exact }`, so a stale id degrades instead of failing.
|
|
15747
15947
|
*/
|
|
15748
15948
|
async replaceTrackFallback(sender, oldTrack, kind, mergedConstraints) {
|
|
15749
15949
|
const { deviceId } = oldTrack.getSettings();
|
|
15750
|
-
const
|
|
15751
|
-
|
|
15752
|
-
|
|
15753
|
-
|
|
15754
|
-
|
|
15950
|
+
const { stream, fallbackLevel } = await getUserMediaWithFallback({ getUserMedia: this.options.getUserMedia }, { [kind]: mergedConstraints }, kind, deviceId);
|
|
15951
|
+
const newTrack = stream.getTracks().find((t) => t.kind === kind);
|
|
15952
|
+
if (!newTrack) {
|
|
15953
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
15954
|
+
throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15955
|
+
}
|
|
15956
|
+
try {
|
|
15957
|
+
await sender.replaceTrack(newTrack);
|
|
15958
|
+
} catch (error) {
|
|
15959
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
15960
|
+
throw error;
|
|
15961
|
+
}
|
|
15962
|
+
const oldTrackId = oldTrack.id;
|
|
15963
|
+
this.options.localStreamController.removeTrack(oldTrackId);
|
|
15755
15964
|
oldTrack.stop();
|
|
15756
|
-
this.options.localStreamController.removeTrack(trackId);
|
|
15757
|
-
const newTrack = (await this.options.getUserMedia({ [kind]: constraintsWithDevice })).getTracks().find((t) => t.kind === kind);
|
|
15758
|
-
if (!newTrack) throw new MediaTrackError("replaceTrackFallback", kind, /* @__PURE__ */ new Error("getUserMedia returned no track of the requested kind"));
|
|
15759
|
-
await sender.replaceTrack(newTrack);
|
|
15760
15965
|
this.options.localStreamController.addTrack(newTrack);
|
|
15761
|
-
logger$18.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind}. New track: ${newTrack.id}`);
|
|
15966
|
+
logger$18.debug(`[TransceiverController] Track replacement fallback succeeded for ${kind} (deviceId fallback level: ${fallbackLevel}). New track: ${newTrack.id}`);
|
|
15762
15967
|
}
|
|
15763
15968
|
getMediaDirections() {
|
|
15764
15969
|
if (this.peerConnection.connectionState === "connected") return this.peerConnection.getTransceivers().reduce((acc, transceiver) => {
|
|
@@ -15870,6 +16075,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15870
16075
|
this._iceGatheringState$ = this.createReplaySubject(1);
|
|
15871
16076
|
this._errors$ = this.createReplaySubject(1);
|
|
15872
16077
|
this._iceCandidates$ = this.createReplaySubject(1);
|
|
16078
|
+
this._localMediaSettled$ = this.createReplaySubject(1);
|
|
15873
16079
|
this._initialized$ = this.createReplaySubject(1);
|
|
15874
16080
|
this._remoteDescription$ = this.createReplaySubject(1);
|
|
15875
16081
|
this._remoteStream$ = this.createBehaviorSubject(null);
|
|
@@ -15973,6 +16179,10 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
15973
16179
|
get remoteDescription$() {
|
|
15974
16180
|
return this.cachedObservable("remoteDescription$", () => this._remoteDescription$.asObservable().pipe((0, import_cjs$16.takeUntil)(this.destroyed$)));
|
|
15975
16181
|
}
|
|
16182
|
+
/** Emits once local media is settled — acquired, or knowingly receive-only. */
|
|
16183
|
+
get localMediaSettled$() {
|
|
16184
|
+
return this.cachedObservable("localMediaSettled$", () => this._localMediaSettled$.asObservable().pipe((0, import_cjs$16.takeUntil)(this.destroyed$)));
|
|
16185
|
+
}
|
|
15976
16186
|
get localStream$() {
|
|
15977
16187
|
return this.cachedObservable("localStream$", () => this.localStreamController.localStream$.pipe((0, import_cjs$16.takeUntil)(this.destroyed$)));
|
|
15978
16188
|
}
|
|
@@ -16128,7 +16338,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16128
16338
|
this._isNegotiating$.next(true);
|
|
16129
16339
|
await this._setRemoteDescription(this.sdpInit);
|
|
16130
16340
|
} else {
|
|
16131
|
-
await this.setupTrackHandling();
|
|
16341
|
+
if (!await this.setupTrackHandling()) return;
|
|
16132
16342
|
this._initialized$.next(true);
|
|
16133
16343
|
}
|
|
16134
16344
|
} catch (error) {
|
|
@@ -16252,7 +16462,10 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16252
16462
|
inputVideoDeviceConstraints: this.inputVideoDeviceConstraints
|
|
16253
16463
|
});
|
|
16254
16464
|
}
|
|
16255
|
-
await this.setupLocalTracks()
|
|
16465
|
+
if (!await this.setupLocalTracks()) {
|
|
16466
|
+
logger$17.debug("[RTCPeerConnectionController] Inbound answer abandoned; the connection went away.");
|
|
16467
|
+
return;
|
|
16468
|
+
}
|
|
16256
16469
|
const { answerOptions } = this;
|
|
16257
16470
|
logger$17.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
16258
16471
|
await this.createAnswer(answerOptions);
|
|
@@ -16390,35 +16603,52 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16390
16603
|
}
|
|
16391
16604
|
/**
|
|
16392
16605
|
* Setup track handling for remote tracks.
|
|
16606
|
+
*
|
|
16607
|
+
* @returns `false` when the connection went away while local media was being
|
|
16608
|
+
* acquired — see {@link setupLocalTracks}.
|
|
16393
16609
|
*/
|
|
16394
16610
|
async setupTrackHandling() {
|
|
16395
16611
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
16396
|
-
await this.setupLocalTracks();
|
|
16612
|
+
if (!await this.setupLocalTracks()) return false;
|
|
16397
16613
|
await this.setupRemoteTracks();
|
|
16614
|
+
return true;
|
|
16398
16615
|
}
|
|
16616
|
+
/**
|
|
16617
|
+
* @returns `false` when the connection was torn down while getUserMedia was
|
|
16618
|
+
* in flight. The acquisition is not cancellable, so the caller must stop
|
|
16619
|
+
* rather than go on to touch a peer connection that is closed or gone.
|
|
16620
|
+
*/
|
|
16399
16621
|
async setupLocalTracks() {
|
|
16400
16622
|
logger$17.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
16401
16623
|
if (this.hasNoLocalMediaToSend()) {
|
|
16402
16624
|
if (!this.receiveAudio && !this.receiveVideo) throw new InvalidParams("Call requests no media: enable audio/video or receiveAudio/receiveVideo");
|
|
16403
16625
|
logger$17.debug("[RTCPeerConnectionController] No local media requested; negotiating receive-only.");
|
|
16404
16626
|
this.setupReceiveOnlyTransceivers();
|
|
16405
|
-
|
|
16627
|
+
this._localMediaSettled$.next();
|
|
16628
|
+
return true;
|
|
16406
16629
|
}
|
|
16407
16630
|
let localStream;
|
|
16408
16631
|
try {
|
|
16409
16632
|
localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
16410
16633
|
} catch (error) {
|
|
16411
16634
|
this.handleLocalMediaFailure(error);
|
|
16412
|
-
|
|
16635
|
+
this._localMediaSettled$.next();
|
|
16636
|
+
return true;
|
|
16637
|
+
}
|
|
16638
|
+
if (!this.peerConnection || this.peerConnection.signalingState === "closed") {
|
|
16639
|
+
logger$17.debug("[RTCPeerConnectionController] Local media arrived after teardown; releasing it.");
|
|
16640
|
+
localStream.getTracks().forEach((track) => track.stop());
|
|
16641
|
+
return false;
|
|
16413
16642
|
}
|
|
16643
|
+
this._localMediaSettled$.next();
|
|
16414
16644
|
if (this.transceiverController?.useAddStream ?? false) {
|
|
16415
16645
|
logger$17.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
16416
|
-
this.peerConnection
|
|
16646
|
+
this.peerConnection.addStream(localStream);
|
|
16417
16647
|
if (!this.isNegotiating) {
|
|
16418
16648
|
logger$17.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
16419
16649
|
this.negotiationNeeded$.next();
|
|
16420
16650
|
}
|
|
16421
|
-
return;
|
|
16651
|
+
return true;
|
|
16422
16652
|
}
|
|
16423
16653
|
for (const kind of ["audio", "video"]) {
|
|
16424
16654
|
const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
|
|
@@ -16432,10 +16662,11 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16432
16662
|
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
16433
16663
|
} else {
|
|
16434
16664
|
logger$17.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
16435
|
-
this.peerConnection
|
|
16665
|
+
this.peerConnection.addTrack(track, localStream);
|
|
16436
16666
|
}
|
|
16437
16667
|
}
|
|
16438
16668
|
}
|
|
16669
|
+
return true;
|
|
16439
16670
|
}
|
|
16440
16671
|
/** True for a main connection with no local media to send. */
|
|
16441
16672
|
hasNoLocalMediaToSend() {
|
|
@@ -16556,6 +16787,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16556
16787
|
const sender = (this.transceiverController?.audioTransceivers.at(0))?.sender ?? this.peerConnection.getSenders().find((s) => s.track?.kind === "audio");
|
|
16557
16788
|
if (!sender || !raw) return;
|
|
16558
16789
|
try {
|
|
16790
|
+
this.localStreamController.setTrackOrigin(this._localAudioPipeline.outputTrack, "processed");
|
|
16559
16791
|
await sender.replaceTrack(this._localAudioPipeline.outputTrack);
|
|
16560
16792
|
} catch (error) {
|
|
16561
16793
|
logger$17.warn("[RTCPeerConnectionController] Failed to route audio sender through pipeline:", error);
|
|
@@ -16616,37 +16848,62 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
16616
16848
|
for (const existingTrack of existingTracks) this.removeLocalTrack(existingTrack.id);
|
|
16617
16849
|
this.addLocalTrack(track);
|
|
16618
16850
|
}
|
|
16851
|
+
/**
|
|
16852
|
+
* @returns whether the constraints reached the media the leg is sending.
|
|
16853
|
+
*
|
|
16854
|
+
* With the pipeline engaged the audio sender carries the processed
|
|
16855
|
+
* destination track, so the sender scan would find nothing it may touch and
|
|
16856
|
+
* every audio constraint API would silently no-op. The constraints belong to
|
|
16857
|
+
* the pipeline's device source, which is the capture that sender ultimately
|
|
16858
|
+
* carries.
|
|
16859
|
+
*/
|
|
16619
16860
|
async updateSendersConstraints(kind, constraints) {
|
|
16620
|
-
|
|
16861
|
+
if (kind === "audio" && constraints && this._localAudioPipeline) return this.applyPipelineSourceConstraints(constraints);
|
|
16862
|
+
return await this.transceiverController?.updateSendersConstraints(kind, constraints) ?? false;
|
|
16621
16863
|
}
|
|
16622
16864
|
/**
|
|
16623
|
-
*
|
|
16624
|
-
*
|
|
16625
|
-
*
|
|
16626
|
-
*
|
|
16865
|
+
* Mirror of the sender path for a piped audio leg: same merge, same fallback
|
|
16866
|
+
* ladder, same device-capture invariant — but the swap target is the pipeline
|
|
16867
|
+
* input, so the sender keeps emitting the pipeline's output track and its
|
|
16868
|
+
* identity survives the change.
|
|
16627
16869
|
*/
|
|
16628
|
-
async
|
|
16629
|
-
const
|
|
16630
|
-
|
|
16631
|
-
|
|
16632
|
-
|
|
16870
|
+
async applyPipelineSourceConstraints(constraints) {
|
|
16871
|
+
const pipeline = this._localAudioPipeline;
|
|
16872
|
+
const source = this.localStreamController.localAudioTracks.at(0);
|
|
16873
|
+
if (!pipeline || !source) {
|
|
16874
|
+
logger$17.debug("[RTCPeerConnectionController] No pipeline input to constrain.");
|
|
16875
|
+
return false;
|
|
16633
16876
|
}
|
|
16634
|
-
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
|
|
16645
|
-
|
|
16646
|
-
|
|
16647
|
-
|
|
16877
|
+
if (!this.localStreamController.isDeviceCapture(source)) {
|
|
16878
|
+
logger$17.debug(`[RTCPeerConnectionController] Skipping audio constraints for a non-device pipeline input (origin: ${this.localStreamController.getTrackOrigin(source) ?? "unrecorded"}).`);
|
|
16879
|
+
return false;
|
|
16880
|
+
}
|
|
16881
|
+
const merged = {
|
|
16882
|
+
...source.getConstraints(),
|
|
16883
|
+
...constraints
|
|
16884
|
+
};
|
|
16885
|
+
try {
|
|
16886
|
+
await source.applyConstraints(merged);
|
|
16887
|
+
logger$17.debug("[RTCPeerConnectionController] Pipeline input constraints updated:", merged);
|
|
16888
|
+
return true;
|
|
16889
|
+
} catch (error) {
|
|
16890
|
+
logger$17.warn("[RTCPeerConnectionController] applyConstraints failed on the pipeline input, re-acquiring:", error);
|
|
16891
|
+
}
|
|
16892
|
+
try {
|
|
16893
|
+
const { stream } = await getUserMediaWithFallback({ getUserMedia: async (c) => this.getUserMedia(c) }, { audio: merged }, "audio", source.getSettings().deviceId);
|
|
16894
|
+
const newTrack = stream.getAudioTracks().at(0);
|
|
16895
|
+
if (!newTrack) {
|
|
16896
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
16897
|
+
throw new Error("getUserMedia returned no audio track");
|
|
16898
|
+
}
|
|
16899
|
+
this.localStreamController.removeTrack(source.id);
|
|
16648
16900
|
this.localStreamController.addTrack(newTrack);
|
|
16649
|
-
|
|
16901
|
+
pipeline.setInputTrack(newTrack);
|
|
16902
|
+
return true;
|
|
16903
|
+
} catch (error) {
|
|
16904
|
+
logger$17.warn("[RTCPeerConnectionController] Failed to re-acquire the pipeline input for constraints:", error);
|
|
16905
|
+
this._errors$.next(new MediaTrackError("updateSendersConstraints", "audio", error));
|
|
16906
|
+
return false;
|
|
16650
16907
|
}
|
|
16651
16908
|
}
|
|
16652
16909
|
/**
|
|
@@ -16830,7 +17087,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16830
17087
|
this._signalingStatus$ = this.createReplaySubject(1);
|
|
16831
17088
|
this._screenShareStatus$ = this.createBehaviorSubject("none");
|
|
16832
17089
|
this._rtcPeerConnectionsMap = /* @__PURE__ */ new Map();
|
|
16833
|
-
this.
|
|
17090
|
+
this._legErrors$ = this.createSubject();
|
|
16834
17091
|
this._nodeId$ = this.createBehaviorSubject(options.nodeId ?? null);
|
|
16835
17092
|
this.onError = options.onError;
|
|
16836
17093
|
this.onModifyFailed = options.onModifyFailed;
|
|
@@ -16878,6 +17135,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16878
17135
|
get selfId$() {
|
|
16879
17136
|
return this._selfId$.asObservable();
|
|
16880
17137
|
}
|
|
17138
|
+
/** Separates the media phase of call creation from the signalling phase. */
|
|
17139
|
+
get localMediaSettled$() {
|
|
17140
|
+
return this.mainPeerConnection.localMediaSettled$;
|
|
17141
|
+
}
|
|
16881
17142
|
get localStream() {
|
|
16882
17143
|
return this._rtcPeerConnectionsMap.get(this.webRtcCallSession.id)?.localStream ?? null;
|
|
16883
17144
|
}
|
|
@@ -16934,20 +17195,11 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16934
17195
|
const { mediaParams, callID } = event;
|
|
16935
17196
|
const rtcPeerConnController = this._rtcPeerConnectionsMap.get(callID);
|
|
16936
17197
|
const { audio, video } = mediaParams;
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
|
|
16942
|
-
audio,
|
|
16943
|
-
video,
|
|
16944
|
-
timestamp: Date.now()
|
|
16945
|
-
});
|
|
16946
|
-
} catch (error) {
|
|
16947
|
-
logger$16.warn("[WebRTCManager] Error applying server-pushed media params:", error);
|
|
16948
|
-
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16949
|
-
}
|
|
16950
|
-
})();
|
|
17198
|
+
if (!rtcPeerConnController) {
|
|
17199
|
+
logger$16.warn(`[WebRTCManager] Ignoring server-pushed media params for unknown leg ${callID}`);
|
|
17200
|
+
return;
|
|
17201
|
+
}
|
|
17202
|
+
this.applyServerMediaParams(rtcPeerConnController, audio, video);
|
|
16951
17203
|
});
|
|
16952
17204
|
this.subscribeTo(this.vertoPing$, (vertoPing) => {
|
|
16953
17205
|
this.attachManager.attach(this.buildAttachableCall());
|
|
@@ -16955,6 +17207,75 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16955
17207
|
});
|
|
16956
17208
|
}
|
|
16957
17209
|
/**
|
|
17210
|
+
* An auxiliary-leg failure must never destroy the call; main-leg and
|
|
17211
|
+
* call-level errors keep `CallFactory.isFatalError`'s classification.
|
|
17212
|
+
*
|
|
17213
|
+
* Every site holding a peer connection reports through here, so the invariant
|
|
17214
|
+
* is structural rather than per-call-site — which is how cloud-product#20523
|
|
17215
|
+
* happened, with only one of fourteen sites passing `{ fatal: false }`.
|
|
17216
|
+
*
|
|
17217
|
+
* `override` composes rather than replaces: a caller may force non-fatal for a
|
|
17218
|
+
* reason of its own (a `verto.info` frame is best-effort whichever leg carries
|
|
17219
|
+
* it), and an auxiliary leg stays non-fatal regardless.
|
|
17220
|
+
*/
|
|
17221
|
+
reportLegError(error, rtcPeerConnController, override) {
|
|
17222
|
+
const leg = rtcPeerConnController?.propose;
|
|
17223
|
+
const legId = rtcPeerConnController?.id;
|
|
17224
|
+
const auxiliary = Boolean(rtcPeerConnController) && !rtcPeerConnController?.isMainDevice;
|
|
17225
|
+
this.onError?.(error, {
|
|
17226
|
+
...override?.fatal === false || auxiliary ? { fatal: false } : {},
|
|
17227
|
+
...leg ? { leg } : {},
|
|
17228
|
+
...legId ? { legId } : {}
|
|
17229
|
+
});
|
|
17230
|
+
if (legId) this._legErrors$.next({
|
|
17231
|
+
legId,
|
|
17232
|
+
error
|
|
17233
|
+
});
|
|
17234
|
+
}
|
|
17235
|
+
/**
|
|
17236
|
+
* Errors reported for one leg, as a stream that fails with them.
|
|
17237
|
+
*
|
|
17238
|
+
* Signaling failures are reported, never thrown — so nothing that waits on a
|
|
17239
|
+
* leg's progress would otherwise learn of a rejected invite. Merging this in
|
|
17240
|
+
* lets the wait end with the reason the server gave.
|
|
17241
|
+
*/
|
|
17242
|
+
legError$(legId) {
|
|
17243
|
+
return this._legErrors$.pipe((0, import_cjs$15.filter)((report) => report.legId === legId), (0, import_cjs$15.map)((report) => {
|
|
17244
|
+
throw report.error;
|
|
17245
|
+
}));
|
|
17246
|
+
}
|
|
17247
|
+
/**
|
|
17248
|
+
* Audio and video are applied independently so a failure in one cannot
|
|
17249
|
+
* suppress the other, and `mediaParamsUpdated` is emitted whatever happens —
|
|
17250
|
+
* an application should not be starved of the params by a constraint failure.
|
|
17251
|
+
*/
|
|
17252
|
+
async applyServerMediaParams(rtcPeerConnController, audio, video) {
|
|
17253
|
+
const failures = [];
|
|
17254
|
+
let applied = true;
|
|
17255
|
+
if (audio) try {
|
|
17256
|
+
applied = await rtcPeerConnController.updateSendersConstraints("audio", audio) && applied;
|
|
17257
|
+
} catch (error) {
|
|
17258
|
+
applied = false;
|
|
17259
|
+
failures.push(toError(error));
|
|
17260
|
+
}
|
|
17261
|
+
if (video) try {
|
|
17262
|
+
applied = await rtcPeerConnController.updateSendersConstraints("video", video) && applied;
|
|
17263
|
+
} catch (error) {
|
|
17264
|
+
applied = false;
|
|
17265
|
+
failures.push(toError(error));
|
|
17266
|
+
}
|
|
17267
|
+
this.webRtcCallSession.emitMediaParamsUpdated({
|
|
17268
|
+
audio,
|
|
17269
|
+
video,
|
|
17270
|
+
timestamp: Date.now(),
|
|
17271
|
+
applied
|
|
17272
|
+
});
|
|
17273
|
+
for (const failure of failures) {
|
|
17274
|
+
logger$16.warn("[WebRTCManager] Error applying server-pushed media params:", failure);
|
|
17275
|
+
this.reportLegError(failure, rtcPeerConnController, { fatal: false });
|
|
17276
|
+
}
|
|
17277
|
+
}
|
|
17278
|
+
/**
|
|
16958
17279
|
* Set node_id/selfId only when the current value is null.
|
|
16959
17280
|
*
|
|
16960
17281
|
* During reattach, `call.joined` and `verto.answer` events can deliver
|
|
@@ -16992,7 +17313,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
16992
17313
|
if (video) await this.mainPeerConnection.updateSendersConstraints("video", video);
|
|
16993
17314
|
} catch (error) {
|
|
16994
17315
|
logger$16.warn("[WebRTCManager] Error updating media constraints:", error);
|
|
16995
|
-
this.
|
|
17316
|
+
this.reportLegError(toError(error), this.mainPeerConnection);
|
|
16996
17317
|
throw error;
|
|
16997
17318
|
}
|
|
16998
17319
|
}
|
|
@@ -17160,23 +17481,24 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17160
17481
|
return response;
|
|
17161
17482
|
}
|
|
17162
17483
|
async executeVerto(message, optionals = {}) {
|
|
17163
|
-
const
|
|
17484
|
+
const params = {
|
|
17164
17485
|
callID: optionals.callID ?? this.webRtcCallSession.id,
|
|
17165
17486
|
node_id: optionals.node_id ?? this._nodeId$.value ?? "",
|
|
17166
17487
|
message,
|
|
17167
17488
|
subscribe: optionals.subscribe
|
|
17168
|
-
}
|
|
17489
|
+
};
|
|
17490
|
+
const webrtcVertoMessage = WebrtcVerto(params);
|
|
17169
17491
|
const response = await this.webRtcCallSession.execute(webrtcVertoMessage);
|
|
17170
17492
|
const nonFatal = message.method === "verto.info" ? { fatal: false } : void 0;
|
|
17171
17493
|
if (response.error) {
|
|
17172
17494
|
const error = new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
17173
|
-
this.
|
|
17495
|
+
this.reportLegError(error, this._rtcPeerConnectionsMap.get(params.callID), nonFatal);
|
|
17174
17496
|
return response;
|
|
17175
17497
|
}
|
|
17176
17498
|
const innerResult = getValueFrom(response, "result.result");
|
|
17177
17499
|
if (innerResult?.error) {
|
|
17178
17500
|
const error = new JSONRPCError(innerResult.error.code, innerResult.error.message, innerResult.error.data);
|
|
17179
|
-
this.
|
|
17501
|
+
this.reportLegError(error, this._rtcPeerConnectionsMap.get(params.callID), nonFatal);
|
|
17180
17502
|
return response;
|
|
17181
17503
|
}
|
|
17182
17504
|
return response;
|
|
@@ -17197,7 +17519,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17197
17519
|
}
|
|
17198
17520
|
} catch (error) {
|
|
17199
17521
|
logger$16.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
17200
|
-
this.
|
|
17522
|
+
this.reportLegError(toError(error), rtcPeerConnController);
|
|
17201
17523
|
if (vertoMethod === "verto.modify") this.onModifyFailed?.();
|
|
17202
17524
|
}
|
|
17203
17525
|
}
|
|
@@ -17213,7 +17535,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17213
17535
|
} catch (error) {
|
|
17214
17536
|
logger$16.warn("[WebRTCManager] Error processing modify response:", error);
|
|
17215
17537
|
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
17216
|
-
this.
|
|
17538
|
+
this.reportLegError(modifyError, rtcPeerConnController);
|
|
17217
17539
|
}
|
|
17218
17540
|
}
|
|
17219
17541
|
}
|
|
@@ -17226,7 +17548,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17226
17548
|
status,
|
|
17227
17549
|
signalingError
|
|
17228
17550
|
});
|
|
17229
|
-
this.
|
|
17551
|
+
this.reportLegError(signalingError, null, { fatal: false });
|
|
17230
17552
|
return;
|
|
17231
17553
|
}
|
|
17232
17554
|
if (rtcPeerConnController.isMainDevice) this._signalingStatus$.next(status);
|
|
@@ -17256,7 +17578,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17256
17578
|
} else {
|
|
17257
17579
|
logger$16.error("[WebRTCManager] Verto invite failed:", response);
|
|
17258
17580
|
const inviteError = response.error ? new JSONRPCError(response.error.code, response.error.message, response.error.data) : /* @__PURE__ */ new Error("Verto invite failed: unexpected response");
|
|
17259
|
-
this.
|
|
17581
|
+
this.reportLegError(inviteError, rtcPeerConnController);
|
|
17260
17582
|
}
|
|
17261
17583
|
}
|
|
17262
17584
|
get RTCPeerConnectionConfig() {
|
|
@@ -17295,7 +17617,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17295
17617
|
this._rtcPeerConnectionsMap.set(rtcPeerConnController.id, rtcPeerConnController);
|
|
17296
17618
|
this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()));
|
|
17297
17619
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
17298
|
-
this.
|
|
17620
|
+
this.reportLegError(error, rtcPeerConnController);
|
|
17299
17621
|
});
|
|
17300
17622
|
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
17301
17623
|
}
|
|
@@ -17324,7 +17646,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17324
17646
|
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
17325
17647
|
} catch (error) {
|
|
17326
17648
|
logger$16.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
17327
|
-
this.
|
|
17649
|
+
this.reportLegError(toError(error), rtcPeerConnController);
|
|
17328
17650
|
}
|
|
17329
17651
|
}
|
|
17330
17652
|
}
|
|
@@ -17428,7 +17750,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17428
17750
|
await this.attachManager.attach(this.buildAttachableCall());
|
|
17429
17751
|
} catch (error) {
|
|
17430
17752
|
logger$16.error("[WebRTCManager] Error sending Verto answer:", error);
|
|
17431
|
-
this.
|
|
17753
|
+
this.reportLegError(toError(error), rtcPeerConnectionController);
|
|
17432
17754
|
await rtcPeerConnectionController.updateAnswerStatus({ status: "failed" });
|
|
17433
17755
|
}
|
|
17434
17756
|
}
|
|
@@ -17500,7 +17822,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17500
17822
|
await this.mainPeerConnection.restoreTrackSender(deviceKind);
|
|
17501
17823
|
} else {
|
|
17502
17824
|
const error = new InvalidParams("No valid device to be added");
|
|
17503
|
-
this.
|
|
17825
|
+
this.reportLegError(error, this.mainPeerConnection);
|
|
17504
17826
|
throw error;
|
|
17505
17827
|
}
|
|
17506
17828
|
}
|
|
@@ -17509,6 +17831,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17509
17831
|
}
|
|
17510
17832
|
async initAdditionalPeerConnection(propose, options) {
|
|
17511
17833
|
const isScreenShare = propose === "screenshare";
|
|
17834
|
+
if (isScreenShare && this._screenShareId && this._rtcPeerConnectionsMap.has(this._screenShareId)) throw new ScreenShareAlreadyActiveError(this._screenShareId);
|
|
17512
17835
|
let firstPeerConnectionError;
|
|
17513
17836
|
let rtcPeerConnController = null;
|
|
17514
17837
|
try {
|
|
@@ -17525,21 +17848,30 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17525
17848
|
this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()));
|
|
17526
17849
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
17527
17850
|
firstPeerConnectionError ??= error;
|
|
17528
|
-
this.
|
|
17851
|
+
this.reportLegError(error, rtcPeerConnController);
|
|
17529
17852
|
});
|
|
17530
|
-
|
|
17853
|
+
const pc = rtcPeerConnController;
|
|
17854
|
+
await (0, import_cjs$15.firstValueFrom)((0, import_cjs$15.merge)(pc.localMediaSettled$.pipe((0, import_cjs$15.take)(1), (0, import_cjs$15.switchMap)(() => pc.connectionState$.pipe((0, import_cjs$15.filter)((state) => state === "connected"), (0, import_cjs$15.take)(1), (0, import_cjs$15.timeout)(DEFAULT_AUX_LEG_CONNECT_TIMEOUT_MS)))), this.legError$(pc.id)).pipe((0, import_cjs$15.takeUntil)(this.destroyed$)));
|
|
17531
17855
|
if (isScreenShare) this._screenShareStatus$.next("started");
|
|
17532
17856
|
logger$16.info(`[WebRTCManager] Additional peer connection connected (${propose}).`);
|
|
17533
17857
|
return rtcPeerConnController.id;
|
|
17534
17858
|
} catch (error) {
|
|
17535
17859
|
logger$16.warn("[WebRTCManager] Error initializing additional peer connection:", error);
|
|
17536
|
-
if (rtcPeerConnController)
|
|
17537
|
-
|
|
17860
|
+
if (rtcPeerConnController) {
|
|
17861
|
+
rtcPeerConnController.destroy();
|
|
17862
|
+
this._rtcPeerConnectionsMap.delete(rtcPeerConnController.id);
|
|
17863
|
+
this._rtcPeerConnections$.next(Array.from(this._rtcPeerConnectionsMap.values()));
|
|
17864
|
+
}
|
|
17865
|
+
if (isScreenShare) {
|
|
17866
|
+
this._screenShareId = void 0;
|
|
17867
|
+
this._screenShareStatus$.next("none");
|
|
17868
|
+
}
|
|
17538
17869
|
if (firstPeerConnectionError) throw firstPeerConnectionError instanceof MediaAccessError && firstPeerConnectionError.originalError instanceof Error ? firstPeerConnectionError.originalError : firstPeerConnectionError;
|
|
17539
17870
|
if (error instanceof import_cjs$15.EmptyError) {
|
|
17540
17871
|
logger$16.debug("[WebRTCManager] Additional peer connection aborted before connecting.");
|
|
17541
17872
|
return;
|
|
17542
17873
|
}
|
|
17874
|
+
if (error instanceof import_cjs$15.TimeoutError) throw new AuxiliaryLegTimeoutError(propose, error);
|
|
17543
17875
|
throw error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
17544
17876
|
}
|
|
17545
17877
|
}
|
|
@@ -17556,7 +17888,10 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17556
17888
|
if (removeTrack) return this.mainPeerConnection.stopTrackSender(removeTrack, { updateTransceiverDirection: true });
|
|
17557
17889
|
}
|
|
17558
17890
|
async removeScreenMedia() {
|
|
17559
|
-
if (!["starting", "started"].includes(this._screenShareStatus$.value))
|
|
17891
|
+
if (!["starting", "started"].includes(this._screenShareStatus$.value)) {
|
|
17892
|
+
logger$16.warn("[WebRTCManager] No active screen share to stop.");
|
|
17893
|
+
return;
|
|
17894
|
+
}
|
|
17560
17895
|
if (!this._screenShareId) {
|
|
17561
17896
|
logger$16.debug("[WebRTCManager] No screen share peer connection found.");
|
|
17562
17897
|
return;
|
|
@@ -17585,7 +17920,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
17585
17920
|
await this.executeVerto(VertoBye({
|
|
17586
17921
|
...causeParams,
|
|
17587
17922
|
dialogParams: this.dialogParams(rtcPeerConnController)
|
|
17588
|
-
}));
|
|
17923
|
+
}), { callID: rtcPeerConnController.id });
|
|
17589
17924
|
} catch (error) {
|
|
17590
17925
|
logger$16.warn("[WebRTCManager] Call might already be disconnected, error sending Verto bye:", error);
|
|
17591
17926
|
throw error;
|
|
@@ -18977,13 +19312,13 @@ var WebRTCCall = class extends Destroyable {
|
|
|
18977
19312
|
get bandwidthConstrained$() {
|
|
18978
19313
|
return this.deferEmission(this._bandwidthConstrained$.asObservable());
|
|
18979
19314
|
}
|
|
18980
|
-
/** Observable that emits when server
|
|
19315
|
+
/** Observable that emits when the server pushes media params. */
|
|
18981
19316
|
get mediaParamsUpdated$() {
|
|
18982
19317
|
return this.deferEmission(this._mediaParamsUpdated$.asObservable());
|
|
18983
19318
|
}
|
|
18984
19319
|
/**
|
|
18985
19320
|
* @internal Emit a media params update event.
|
|
18986
|
-
* Called by the VertoManager when server
|
|
19321
|
+
* Called by the VertoManager when the server pushes media params.
|
|
18987
19322
|
*/
|
|
18988
19323
|
emitMediaParamsUpdated(event) {
|
|
18989
19324
|
this._mediaParamsUpdated$.next(event);
|
|
@@ -19191,6 +19526,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
19191
19526
|
get selfId$() {
|
|
19192
19527
|
return this.vertoManager.selfId$;
|
|
19193
19528
|
}
|
|
19529
|
+
/** @internal Lets call creation bound the media and signalling phases apart. */
|
|
19530
|
+
get localMediaSettled$() {
|
|
19531
|
+
return this.vertoManager.localMediaSettled$;
|
|
19532
|
+
}
|
|
19194
19533
|
/** Local participant's member ID, or `null` if not joined. */
|
|
19195
19534
|
get selfId() {
|
|
19196
19535
|
return this.vertoManager.selfId;
|
|
@@ -19586,6 +19925,9 @@ var WebRTCCall = class extends Destroyable {
|
|
|
19586
19925
|
/**
|
|
19587
19926
|
* Infers the semantic error category from a raw Error thrown by VertoManager
|
|
19588
19927
|
* or an RTCPeerConnection layer.
|
|
19928
|
+
*
|
|
19929
|
+
* Pure function — exported for unit testing.
|
|
19930
|
+
* @internal
|
|
19589
19931
|
*/
|
|
19590
19932
|
function inferCallErrorKind(error) {
|
|
19591
19933
|
if (error instanceof RPCTimeoutError) return "timeout";
|
|
@@ -19604,7 +19946,14 @@ const RECOVERABLE_RPC_CODES = new Set([
|
|
|
19604
19946
|
RPC_ERROR_AUTHENTICATION_FAILED,
|
|
19605
19947
|
RPC_ERROR_INVALID_PARAMS
|
|
19606
19948
|
]);
|
|
19607
|
-
/**
|
|
19949
|
+
/**
|
|
19950
|
+
* A *fallback*: callers knowing which leg failed pass an explicit `fatal` and
|
|
19951
|
+
* never reach here, so the default-fatal branch only sees call- and main-leg
|
|
19952
|
+
* errors. Auxiliary legs go through `WebRTCVertoManager.reportLegError`.
|
|
19953
|
+
*
|
|
19954
|
+
* Pure function — exported for unit testing.
|
|
19955
|
+
* @internal
|
|
19956
|
+
*/
|
|
19608
19957
|
function isFatalError(error) {
|
|
19609
19958
|
if (error instanceof VertoPongError) return false;
|
|
19610
19959
|
if (error instanceof MediaTrackError) return false;
|
|
@@ -19639,7 +19988,9 @@ var CallFactory = class {
|
|
|
19639
19988
|
kind: inferCallErrorKind(error),
|
|
19640
19989
|
fatal: options$1?.fatal ?? isFatalError(error),
|
|
19641
19990
|
error,
|
|
19642
|
-
callId: callInstance.id
|
|
19991
|
+
callId: callInstance.id,
|
|
19992
|
+
...options$1?.leg ? { leg: options$1.leg } : {},
|
|
19993
|
+
...options$1?.legId ? { legId: options$1.legId } : {}
|
|
19643
19994
|
};
|
|
19644
19995
|
callInstance.emitError(callError);
|
|
19645
19996
|
},
|
|
@@ -20111,6 +20462,30 @@ const logger$9 = getLogger();
|
|
|
20111
20462
|
function shouldAbortDial(callError) {
|
|
20112
20463
|
return callError.fatal || !(callError.error instanceof MediaAccessError);
|
|
20113
20464
|
}
|
|
20465
|
+
/**
|
|
20466
|
+
* Wait for a dialed call to be ready, or for the failure that stops it.
|
|
20467
|
+
*
|
|
20468
|
+
* Local media acquisition is deliberately unbounded: a permission prompt or a
|
|
20469
|
+
* device picker is human time, and `getUserMedia` cannot be cancelled anyway.
|
|
20470
|
+
* The clock starts only once acquisition settles, so a slow human never spends
|
|
20471
|
+
* the server's budget.
|
|
20472
|
+
*
|
|
20473
|
+
* `merge` rather than `race`, because the two legs settle asymmetrically. A
|
|
20474
|
+
* fatal acquisition failure reports the error and then destroys the call in the
|
|
20475
|
+
* same synchronous step; `errors$` defers delivery by a microtask while
|
|
20476
|
+
* `localMediaSettled$` completes immediately. Under `race` that bare completion
|
|
20477
|
+
* ended the wait first and `dial()` rejected with an RxJS `EmptyError`, burying
|
|
20478
|
+
* the `NotAllowedError` applications are told to inspect. Under `merge` the
|
|
20479
|
+
* completed leg is simply spent, and the queued error — enqueued before the
|
|
20480
|
+
* completion, so delivered before it — arrives to reject the wait. A dial
|
|
20481
|
+
* abandoned with no error at all still ends both legs, and the resulting
|
|
20482
|
+
* `EmptyError` remains the benign-cancel signal.
|
|
20483
|
+
*
|
|
20484
|
+
* Exported for unit testing.
|
|
20485
|
+
*/
|
|
20486
|
+
async function awaitDialReady(session, signalingTimeoutMs) {
|
|
20487
|
+
return (0, import_cjs$7.firstValueFrom)((0, import_cjs$7.merge)(session.localMediaSettled$.pipe((0, import_cjs$7.take)(1), (0, import_cjs$7.switchMap)(() => session.selfId$.pipe((0, import_cjs$7.filter)((id) => Boolean(id)), (0, import_cjs$7.take)(1), (0, import_cjs$7.timeout)(signalingTimeoutMs)))), session.errors$.pipe((0, import_cjs$7.filter)(shouldAbortDial), (0, import_cjs$7.take)(1), (0, import_cjs$7.switchMap)((callError) => (0, import_cjs$7.throwError)(() => callError.error)))));
|
|
20488
|
+
}
|
|
20114
20489
|
const getAddressSearchURI = (options) => {
|
|
20115
20490
|
const to = options.to?.split("?")[0];
|
|
20116
20491
|
const from$9 = options.from?.startsWith("subscriber://") ? options.from.replace("subscriber://", "") : options.from;
|
|
@@ -20127,7 +20502,6 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20127
20502
|
this.authorizationStateKey = authorizationStateKey;
|
|
20128
20503
|
this.attachManager = attachManager;
|
|
20129
20504
|
this.dpopManager = dpopManager;
|
|
20130
|
-
this.callCreateTimeout = 6e3;
|
|
20131
20505
|
this.agent = `signalwire-js/4.0.0`;
|
|
20132
20506
|
this.eventAcks = true;
|
|
20133
20507
|
this.authorizationState$ = this.createReplaySubject(1);
|
|
@@ -20555,7 +20929,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
20555
20929
|
to: destinationURI,
|
|
20556
20930
|
...options
|
|
20557
20931
|
});
|
|
20558
|
-
await (
|
|
20932
|
+
await awaitDialReady(callSession, DEFAULT_CALL_SIGNALING_TIMEOUT_MS);
|
|
20559
20933
|
this._calls$.next({
|
|
20560
20934
|
[`${callSession.id}`]: callSession,
|
|
20561
20935
|
...this._calls$.value
|
|
@@ -22733,6 +23107,11 @@ var SignalWire = class extends Destroyable {
|
|
|
22733
23107
|
* Returns a {@link Call} in `'ringing'` state. Subscribe to {@link Call.status$}
|
|
22734
23108
|
* to track progression through `'connected'` → `'disconnected'`.
|
|
22735
23109
|
*
|
|
23110
|
+
* Local media acquisition is deliberately unbounded: an unanswered permission
|
|
23111
|
+
* prompt leaves this promise pending indefinitely, so apply your own bound if
|
|
23112
|
+
* your UI needs one. The 12 s signaling budget starts only once acquisition
|
|
23113
|
+
* settles.
|
|
23114
|
+
*
|
|
22736
23115
|
* @param destination - Address URI string (e.g. `'/public/my-room'`) or {@link Address} instance.
|
|
22737
23116
|
* @param options - Media and dial options (audio/video, device constraints). Overrides defaults.
|
|
22738
23117
|
* @returns The created {@link Call} instance.
|
|
@@ -23212,5 +23591,5 @@ emitReadyEvent();
|
|
|
23212
23591
|
if (typeof process === "undefined") globalThis.process = { env: { NODE_ENV: "production" } };
|
|
23213
23592
|
|
|
23214
23593
|
//#endregion
|
|
23215
|
-
export { Address, CallCreateError, CallNotReadyError, ClientPreferences, CollectionFetchError, DPoPInitError, DeviceTokenError, EmbedTokenCredentialProvider, InvalidCredentialsError, MediaAccessError, MediaTrackError, MessageParseError, OverconstrainedFallbackError, Participant, ParticipantNotReadyError, PreflightError, RecoveryError, SelfCapabilities, SelfParticipant, SignalWire, StaticCredentialProvider, TokenRefreshError, UnexpectedError, User, VertoPongError, WebRTCCall, embeddableCall, getLogger, isSelfParticipant, ready, setDebugOptions, setLogLevel, setLogger, version };
|
|
23594
|
+
export { Address, AuxiliaryLegTimeoutError, CallCreateError, CallNotReadyError, ClientPreferences, CollectionFetchError, DPoPInitError, DeviceTokenError, EmbedTokenCredentialProvider, InvalidCredentialsError, MediaAccessError, MediaTrackError, MessageParseError, OverconstrainedFallbackError, Participant, ParticipantNotReadyError, PreflightError, RecoveryError, ScreenShareAlreadyActiveError, SelfCapabilities, SelfParticipant, SignalWire, StaticCredentialProvider, TokenRefreshError, UnexpectedError, User, VertoPongError, WebRTCCall, embeddableCall, getLogger, isSelfParticipant, ready, setDebugOptions, setLogLevel, setLogger, version };
|
|
23216
23595
|
//# sourceMappingURL=browser.mjs.map
|