@signalwire/js 4.0.0-beta.6 → 4.0.0-beta.8
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/base-BxFSgMTI.d.cts +30 -0
- package/dist/{base-A5AZTrAd.d.cts.map → base-BxFSgMTI.d.cts.map} +1 -1
- package/dist/base-DKDZK4Rr.d.mts +30 -0
- package/dist/{base-aVtoG8Wk.d.mts.map → base-DKDZK4Rr.d.mts.map} +1 -1
- package/dist/browser.mjs +337 -121
- package/dist/browser.mjs.map +1 -1
- package/dist/browser.umd.js +337 -121
- package/dist/browser.umd.js.map +1 -1
- package/dist/index.cjs +315 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +276 -153
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +276 -153
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +316 -110
- package/dist/index.mjs.map +1 -1
- package/dist/operators/index.cjs +1 -1
- package/dist/operators/index.d.cts +1 -1
- package/dist/operators/index.d.mts +1 -1
- package/dist/operators/index.mjs +1 -1
- package/dist/{operators-BHQMSEzq.mjs → operators-C8Tqm86j.mjs} +13 -3
- package/dist/operators-C8Tqm86j.mjs.map +1 -0
- package/dist/{operators-DT4UB24-.cjs → operators-CJEML6aa.cjs} +18 -2
- package/dist/operators-CJEML6aa.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/base-A5AZTrAd.d.cts +0 -23
- package/dist/base-aVtoG8Wk.d.mts +0 -23
- package/dist/operators-BHQMSEzq.mjs.map +0 -1
- package/dist/operators-DT4UB24-.cjs.map +0 -1
package/dist/browser.umd.js
CHANGED
|
@@ -3111,7 +3111,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3111
3111
|
exports.throwError = void 0;
|
|
3112
3112
|
var Observable_1$18 = require_Observable();
|
|
3113
3113
|
var isFunction_1$14 = require_isFunction();
|
|
3114
|
-
function throwError(errorOrErrorFactory, scheduler) {
|
|
3114
|
+
function throwError$1(errorOrErrorFactory, scheduler) {
|
|
3115
3115
|
var errorFactory = isFunction_1$14.isFunction(errorOrErrorFactory) ? errorOrErrorFactory : function() {
|
|
3116
3116
|
return errorOrErrorFactory;
|
|
3117
3117
|
};
|
|
@@ -3122,7 +3122,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3122
3122
|
return scheduler.schedule(init, 0, subscriber);
|
|
3123
3123
|
} : init);
|
|
3124
3124
|
}
|
|
3125
|
-
exports.throwError = throwError;
|
|
3125
|
+
exports.throwError = throwError$1;
|
|
3126
3126
|
}));
|
|
3127
3127
|
|
|
3128
3128
|
//#endregion
|
|
@@ -4331,13 +4331,13 @@ var require_race$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4331
4331
|
var innerFrom_1$28 = require_innerFrom();
|
|
4332
4332
|
var argsOrArgArray_1$4 = require_argsOrArgArray();
|
|
4333
4333
|
var OperatorSubscriber_1$48 = require_OperatorSubscriber();
|
|
4334
|
-
function race$
|
|
4334
|
+
function race$4() {
|
|
4335
4335
|
var sources = [];
|
|
4336
4336
|
for (var _i = 0; _i < arguments.length; _i++) sources[_i] = arguments[_i];
|
|
4337
4337
|
sources = argsOrArgArray_1$4.argsOrArgArray(sources);
|
|
4338
4338
|
return sources.length === 1 ? innerFrom_1$28.innerFrom(sources[0]) : new Observable_1$6.Observable(raceInit(sources));
|
|
4339
4339
|
}
|
|
4340
|
-
exports.race = race$
|
|
4340
|
+
exports.race = race$4;
|
|
4341
4341
|
function raceInit(sources) {
|
|
4342
4342
|
return function(subscriber) {
|
|
4343
4343
|
var subscriptions = [];
|
|
@@ -5474,7 +5474,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
5474
5474
|
var identity_1$10 = require_identity();
|
|
5475
5475
|
var lift_1$42 = require_lift();
|
|
5476
5476
|
var OperatorSubscriber_1$31 = require_OperatorSubscriber();
|
|
5477
|
-
function distinctUntilChanged$
|
|
5477
|
+
function distinctUntilChanged$6(comparator, keySelector) {
|
|
5478
5478
|
if (keySelector === void 0) keySelector = identity_1$10.identity;
|
|
5479
5479
|
comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare;
|
|
5480
5480
|
return lift_1$42.operate(function(source, subscriber) {
|
|
@@ -5490,7 +5490,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
5490
5490
|
}));
|
|
5491
5491
|
});
|
|
5492
5492
|
}
|
|
5493
|
-
exports.distinctUntilChanged = distinctUntilChanged$
|
|
5493
|
+
exports.distinctUntilChanged = distinctUntilChanged$6;
|
|
5494
5494
|
function defaultCompare(a, b) {
|
|
5495
5495
|
return a === b;
|
|
5496
5496
|
}
|
|
@@ -6919,7 +6919,7 @@ var require_startWith = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6919
6919
|
var concat_1$2 = require_concat$1();
|
|
6920
6920
|
var args_1$2 = require_args();
|
|
6921
6921
|
var lift_1$14 = require_lift();
|
|
6922
|
-
function startWith() {
|
|
6922
|
+
function startWith$1() {
|
|
6923
6923
|
var values = [];
|
|
6924
6924
|
for (var _i = 0; _i < arguments.length; _i++) values[_i] = arguments[_i];
|
|
6925
6925
|
var scheduler = args_1$2.popScheduler(values);
|
|
@@ -6927,7 +6927,7 @@ var require_startWith = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6927
6927
|
(scheduler ? concat_1$2.concat(values, source, scheduler) : concat_1$2.concat(values, source)).subscribe(subscriber);
|
|
6928
6928
|
});
|
|
6929
6929
|
}
|
|
6930
|
-
exports.startWith = startWith;
|
|
6930
|
+
exports.startWith = startWith$1;
|
|
6931
6931
|
}));
|
|
6932
6932
|
|
|
6933
6933
|
//#endregion
|
|
@@ -6938,7 +6938,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6938
6938
|
var innerFrom_1$6 = require_innerFrom();
|
|
6939
6939
|
var lift_1$13 = require_lift();
|
|
6940
6940
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6941
|
-
function switchMap$
|
|
6941
|
+
function switchMap$4(project, resultSelector) {
|
|
6942
6942
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6943
6943
|
var innerSubscriber = null;
|
|
6944
6944
|
var index = 0;
|
|
@@ -6962,7 +6962,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6962
6962
|
}));
|
|
6963
6963
|
});
|
|
6964
6964
|
}
|
|
6965
|
-
exports.switchMap = switchMap$
|
|
6965
|
+
exports.switchMap = switchMap$4;
|
|
6966
6966
|
}));
|
|
6967
6967
|
|
|
6968
6968
|
//#endregion
|
|
@@ -9108,13 +9108,14 @@ var DependencyError = class extends Error {
|
|
|
9108
9108
|
}
|
|
9109
9109
|
};
|
|
9110
9110
|
var CallCreateError = class extends Error {
|
|
9111
|
-
constructor(message, error = null, options) {
|
|
9111
|
+
constructor(message, error = null, direction = "outbound", options) {
|
|
9112
9112
|
super(message, {
|
|
9113
9113
|
...options,
|
|
9114
9114
|
cause: options?.cause ?? (error instanceof Error ? error : void 0)
|
|
9115
9115
|
});
|
|
9116
9116
|
this.message = message;
|
|
9117
9117
|
this.error = error;
|
|
9118
|
+
this.direction = direction;
|
|
9118
9119
|
this.name = "CallCreateError";
|
|
9119
9120
|
}
|
|
9120
9121
|
};
|
|
@@ -9126,6 +9127,15 @@ var JSONRPCError = class extends Error {
|
|
|
9126
9127
|
this.name = "JSONRPCError";
|
|
9127
9128
|
}
|
|
9128
9129
|
};
|
|
9130
|
+
var RPCError = class extends Error {
|
|
9131
|
+
constructor(code, requestId, message, data, options) {
|
|
9132
|
+
super(message, options);
|
|
9133
|
+
this.code = code;
|
|
9134
|
+
this.requestId = requestId;
|
|
9135
|
+
this.data = data;
|
|
9136
|
+
this.name = "RPCError";
|
|
9137
|
+
}
|
|
9138
|
+
};
|
|
9129
9139
|
var InvalidParams = class extends Error {
|
|
9130
9140
|
constructor(message, options) {
|
|
9131
9141
|
super(message, options);
|
|
@@ -9664,7 +9674,7 @@ var PreferencesContainer = class PreferencesContainer {
|
|
|
9664
9674
|
skipDeviceMonitoring: false,
|
|
9665
9675
|
savePreferences: false
|
|
9666
9676
|
};
|
|
9667
|
-
this.receiveVideo =
|
|
9677
|
+
this.receiveVideo = false;
|
|
9668
9678
|
this.receiveAudio = true;
|
|
9669
9679
|
this.preferredAudioInput = null;
|
|
9670
9680
|
this.preferredAudioOutput = null;
|
|
@@ -9977,7 +9987,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
9977
9987
|
};
|
|
9978
9988
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
9979
9989
|
this._selectedDevicesState$ = this.createBehaviorSubject(initialSelectedDevicesState);
|
|
9980
|
-
this._errors$ = this.
|
|
9990
|
+
this._errors$ = this.createReplaySubject(1);
|
|
9981
9991
|
this.init();
|
|
9982
9992
|
}
|
|
9983
9993
|
get selectedAudioInputDeviceConstraints() {
|
|
@@ -10504,7 +10514,7 @@ const RPCExecute = ({ method, params }) => {
|
|
|
10504
10514
|
|
|
10505
10515
|
//#endregion
|
|
10506
10516
|
//#region src/core/RPCMessages/VertoMessages.ts
|
|
10507
|
-
const
|
|
10517
|
+
const SDK_TO_VERTO_FIELD_MAP = {
|
|
10508
10518
|
id: "callID",
|
|
10509
10519
|
destinationNumber: "destination_number",
|
|
10510
10520
|
remoteCallerName: "remote_caller_id_name",
|
|
@@ -10513,19 +10523,31 @@ const tmpMap = {
|
|
|
10513
10523
|
callerNumber: "caller_id_number",
|
|
10514
10524
|
fromCallAddressId: "from_fabric_address_id"
|
|
10515
10525
|
};
|
|
10526
|
+
const EXCLUDED_DIALOG_PARAMS = new Set([
|
|
10527
|
+
"remoteSdp",
|
|
10528
|
+
"localStream",
|
|
10529
|
+
"remoteStream"
|
|
10530
|
+
]);
|
|
10516
10531
|
/**
|
|
10517
|
-
* Translate SDK fields into verto variables
|
|
10532
|
+
* Translate SDK fields into verto variables.
|
|
10533
|
+
* Returns a new object — the input is never mutated.
|
|
10518
10534
|
*/
|
|
10535
|
+
/** @internal Exported for testing only. */
|
|
10519
10536
|
const filterVertoParams = (params) => {
|
|
10520
|
-
if (Object.prototype.hasOwnProperty.call(params, "dialogParams"))
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10537
|
+
if (!Object.prototype.hasOwnProperty.call(params, "dialogParams")) return params;
|
|
10538
|
+
const sourceDialogParams = params.dialogParams;
|
|
10539
|
+
const filteredDialogParams = Object.entries(sourceDialogParams).reduce((acc, [key, value]) => {
|
|
10540
|
+
if (EXCLUDED_DIALOG_PARAMS.has(key)) return acc;
|
|
10541
|
+
const mappedKey = SDK_TO_VERTO_FIELD_MAP[key] ?? key;
|
|
10542
|
+
return {
|
|
10543
|
+
...acc,
|
|
10544
|
+
[mappedKey]: value
|
|
10545
|
+
};
|
|
10546
|
+
}, {});
|
|
10547
|
+
return {
|
|
10548
|
+
...params,
|
|
10549
|
+
dialogParams: filteredDialogParams
|
|
10550
|
+
};
|
|
10529
10551
|
};
|
|
10530
10552
|
const buildVertoRPCMessage = (method) => {
|
|
10531
10553
|
return (params = {}) => {
|
|
@@ -10707,12 +10729,12 @@ var require_race = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
10707
10729
|
exports.race = void 0;
|
|
10708
10730
|
var argsOrArgArray_1 = require_argsOrArgArray();
|
|
10709
10731
|
var raceWith_1$1 = require_raceWith();
|
|
10710
|
-
function race$
|
|
10732
|
+
function race$3() {
|
|
10711
10733
|
var args = [];
|
|
10712
10734
|
for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
|
|
10713
10735
|
return raceWith_1$1.raceWith.apply(void 0, __spreadArray([], __read(argsOrArgArray_1.argsOrArgArray(args))));
|
|
10714
10736
|
}
|
|
10715
|
-
exports.race = race$
|
|
10737
|
+
exports.race = race$3;
|
|
10716
10738
|
}));
|
|
10717
10739
|
|
|
10718
10740
|
//#endregion
|
|
@@ -12046,7 +12068,13 @@ var Participant = class extends Destroyable {
|
|
|
12046
12068
|
}
|
|
12047
12069
|
/** Removes this participant from the call. */
|
|
12048
12070
|
async remove() {
|
|
12049
|
-
|
|
12071
|
+
const state = this._state$.value;
|
|
12072
|
+
const target = {
|
|
12073
|
+
member_id: this.id,
|
|
12074
|
+
call_id: state.call_id ?? "",
|
|
12075
|
+
node_id: state.node_id ?? ""
|
|
12076
|
+
};
|
|
12077
|
+
await this.executeMethod(target, "call.member.remove", {});
|
|
12050
12078
|
}
|
|
12051
12079
|
/** Ends the call for this participant. */
|
|
12052
12080
|
async end() {
|
|
@@ -12405,7 +12433,6 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12405
12433
|
this.options = options;
|
|
12406
12434
|
this.callIds = /* @__PURE__ */ new Set();
|
|
12407
12435
|
this.roomSessionIds = /* @__PURE__ */ new Set();
|
|
12408
|
-
this._status$ = this.createBehaviorSubject("trying");
|
|
12409
12436
|
this._participants$ = this.createBehaviorSubject({});
|
|
12410
12437
|
this._self$ = this.createBehaviorSubject(null);
|
|
12411
12438
|
this._sessionState$ = this.createBehaviorSubject(initialSessionState);
|
|
@@ -12414,15 +12441,12 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12414
12441
|
get participants$() {
|
|
12415
12442
|
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$14.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
12416
12443
|
}
|
|
12444
|
+
get participants() {
|
|
12445
|
+
return Object.values(this._participants$.value);
|
|
12446
|
+
}
|
|
12417
12447
|
get self$() {
|
|
12418
12448
|
return this.cachedObservable("self$", () => this._self$.asObservable().pipe(filterNull()));
|
|
12419
12449
|
}
|
|
12420
|
-
get status$() {
|
|
12421
|
-
return this._status$.asObservable();
|
|
12422
|
-
}
|
|
12423
|
-
get status() {
|
|
12424
|
-
return this._status$.value;
|
|
12425
|
-
}
|
|
12426
12450
|
isRoomSessionIdValid(roomSessionId) {
|
|
12427
12451
|
return this.roomSessionIds.has(roomSessionId);
|
|
12428
12452
|
}
|
|
@@ -12507,7 +12531,6 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12507
12531
|
callId: callJoinedEvent.call_id,
|
|
12508
12532
|
roomSessionId: callJoinedEvent.room_session_id
|
|
12509
12533
|
});
|
|
12510
|
-
this._status$.next("connected");
|
|
12511
12534
|
const sessionState = callJoinedEvent.room_session;
|
|
12512
12535
|
const { capabilities } = callJoinedEvent;
|
|
12513
12536
|
this.selfId = this.selfId ?? callJoinedEvent.member_id;
|
|
@@ -12634,12 +12657,53 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12634
12657
|
|
|
12635
12658
|
//#endregion
|
|
12636
12659
|
//#region src/helpers/SDPHelper.ts
|
|
12660
|
+
/** Valid SDP direction attribute values. */
|
|
12661
|
+
const SDP_DIRECTIONS = new Set([
|
|
12662
|
+
"sendrecv",
|
|
12663
|
+
"sendonly",
|
|
12664
|
+
"recvonly",
|
|
12665
|
+
"inactive"
|
|
12666
|
+
]);
|
|
12637
12667
|
/**
|
|
12638
|
-
*
|
|
12668
|
+
* Extracts the media directions (audio/video) from an SDP string.
|
|
12669
|
+
*
|
|
12670
|
+
* Parses each media section (`m=audio` / `m=video`) and reads the `a=` direction
|
|
12671
|
+
* attribute (`sendrecv`, `sendonly`, `recvonly`, `inactive`).
|
|
12672
|
+
* If no explicit direction attribute is found for a media section, defaults to `sendrecv`
|
|
12673
|
+
* per RFC 4566.
|
|
12639
12674
|
*
|
|
12640
|
-
*
|
|
12641
|
-
*
|
|
12675
|
+
* @param sdp - The SDP string to parse
|
|
12676
|
+
* @returns The extracted audio and video directions
|
|
12677
|
+
*
|
|
12678
|
+
* @example
|
|
12679
|
+
* ```typescript
|
|
12680
|
+
* const sdp = `v=0\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111\r\na=sendrecv\r\nm=video 9 UDP/TLS/RTP/SAVPF 96\r\na=recvonly`;
|
|
12681
|
+
* extractMediaDirectionsFromSDP(sdp);
|
|
12682
|
+
* // { audio: 'sendrecv', video: 'recvonly' }
|
|
12683
|
+
* ```
|
|
12642
12684
|
*/
|
|
12685
|
+
function extractMediaDirectionsFromSDP(sdp) {
|
|
12686
|
+
const result = {
|
|
12687
|
+
audio: "inactive",
|
|
12688
|
+
video: "inactive"
|
|
12689
|
+
};
|
|
12690
|
+
if (!sdp) return result;
|
|
12691
|
+
const lines = sdp.split(/\r?\n/);
|
|
12692
|
+
let currentMediaKind = null;
|
|
12693
|
+
let currentDirection = null;
|
|
12694
|
+
for (const line of lines) if (line.startsWith("m=")) {
|
|
12695
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
12696
|
+
if (line.startsWith("m=audio")) currentMediaKind = "audio";
|
|
12697
|
+
else if (line.startsWith("m=video")) currentMediaKind = "video";
|
|
12698
|
+
else currentMediaKind = null;
|
|
12699
|
+
currentDirection = null;
|
|
12700
|
+
} else if (currentMediaKind && line.startsWith("a=")) {
|
|
12701
|
+
const attr = line.substring(2).trim();
|
|
12702
|
+
if (SDP_DIRECTIONS.has(attr)) currentDirection = attr;
|
|
12703
|
+
}
|
|
12704
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
12705
|
+
return result;
|
|
12706
|
+
}
|
|
12643
12707
|
/**
|
|
12644
12708
|
* Validates that an SDP string has at least one non-host ICE candidate
|
|
12645
12709
|
* for each media section (m= line).
|
|
@@ -12942,6 +13006,15 @@ var LocalStreamController = class extends Destroyable {
|
|
|
12942
13006
|
track.addEventListener("ended", this.mediaTrackEndedHandler);
|
|
12943
13007
|
}
|
|
12944
13008
|
/**
|
|
13009
|
+
* Update the controller options (e.g., when media overrides are applied).
|
|
13010
|
+
*/
|
|
13011
|
+
updateOptions(options) {
|
|
13012
|
+
this.options = {
|
|
13013
|
+
...this.options,
|
|
13014
|
+
...options
|
|
13015
|
+
};
|
|
13016
|
+
}
|
|
13017
|
+
/**
|
|
12945
13018
|
* Stop all local tracks and clean up.
|
|
12946
13019
|
*/
|
|
12947
13020
|
stopAllTracks() {
|
|
@@ -13280,11 +13353,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13280
13353
|
this._connectionState$ = this.createReplaySubject(1);
|
|
13281
13354
|
this._signalingState$ = this.createReplaySubject(1);
|
|
13282
13355
|
this._iceGatheringState$ = this.createReplaySubject(1);
|
|
13283
|
-
this._errors$ = this.
|
|
13356
|
+
this._errors$ = this.createReplaySubject(1);
|
|
13284
13357
|
this._iceCandidates$ = this.createReplaySubject(1);
|
|
13285
13358
|
this._initialized$ = this.createReplaySubject(1);
|
|
13286
13359
|
this._remoteDescription$ = this.createReplaySubject(1);
|
|
13287
13360
|
this._remoteStream$ = this.createBehaviorSubject(null);
|
|
13361
|
+
this._remoteOfferMediaDirections = null;
|
|
13288
13362
|
this.deviceController = deviceController ?? {};
|
|
13289
13363
|
this.id = options.callId ?? v4_default();
|
|
13290
13364
|
this._type = remoteSessionDescription ? "answer" : "offer";
|
|
@@ -13292,10 +13366,19 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13292
13366
|
type: "offer",
|
|
13293
13367
|
sdp: remoteSessionDescription
|
|
13294
13368
|
} : void 0;
|
|
13369
|
+
this._remoteOfferMediaDirections = remoteSessionDescription ? extractMediaDirectionsFromSDP(remoteSessionDescription) : null;
|
|
13370
|
+
const offerDefaults = this._remoteOfferMediaDirections ? {
|
|
13371
|
+
audio: this._remoteOfferMediaDirections.audio.includes("recv"),
|
|
13372
|
+
video: this._remoteOfferMediaDirections.video.includes("recv"),
|
|
13373
|
+
receiveAudio: this._remoteOfferMediaDirections.audio.includes("send"),
|
|
13374
|
+
receiveVideo: this._remoteOfferMediaDirections.video.includes("send")
|
|
13375
|
+
} : {};
|
|
13295
13376
|
this.options = {
|
|
13296
|
-
|
|
13297
|
-
|
|
13298
|
-
|
|
13377
|
+
...options,
|
|
13378
|
+
audio: options.audio ?? offerDefaults.audio,
|
|
13379
|
+
video: options.video ?? offerDefaults.video,
|
|
13380
|
+
receiveAudio: options.receiveAudio ?? offerDefaults.receiveAudio ?? PreferencesContainer.instance.receiveAudio,
|
|
13381
|
+
receiveVideo: options.receiveVideo ?? offerDefaults.receiveVideo ?? PreferencesContainer.instance.receiveVideo
|
|
13299
13382
|
};
|
|
13300
13383
|
this.localStreamController = new LocalStreamController({
|
|
13301
13384
|
propose: this.propose,
|
|
@@ -13440,7 +13523,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13440
13523
|
};
|
|
13441
13524
|
}
|
|
13442
13525
|
get inputVideoDeviceConstraints() {
|
|
13443
|
-
if (this.options.video
|
|
13526
|
+
if (!this.options.video && !this.options.inputVideoDeviceConstraints) return false;
|
|
13444
13527
|
return {
|
|
13445
13528
|
...this.options.inputVideoDeviceConstraints,
|
|
13446
13529
|
...this.deviceController.selectedVideoInputDeviceConstraints
|
|
@@ -13462,12 +13545,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13462
13545
|
default: return {
|
|
13463
13546
|
...options,
|
|
13464
13547
|
offerToReceiveAudio: true,
|
|
13465
|
-
offerToReceiveVideo: Boolean(this.inputVideoDeviceConstraints)
|
|
13548
|
+
offerToReceiveVideo: this.options.receiveVideo ?? Boolean(this.inputVideoDeviceConstraints)
|
|
13466
13549
|
};
|
|
13467
13550
|
}
|
|
13468
13551
|
}
|
|
13469
13552
|
get answerOptions() {
|
|
13470
|
-
return {};
|
|
13553
|
+
return { iceRestart: this.firstSDPExchangeCompleted ? true : void 0 };
|
|
13471
13554
|
}
|
|
13472
13555
|
/**
|
|
13473
13556
|
* Initialize the RTCPeerConnection and setup event listeners.
|
|
@@ -13502,11 +13585,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13502
13585
|
});
|
|
13503
13586
|
await this.updateSelectedInputDevice(kind, deviceInfo);
|
|
13504
13587
|
});
|
|
13505
|
-
await this.setupTrackHandling();
|
|
13506
|
-
this._initialized$.next(true);
|
|
13507
13588
|
if (this.type === "answer" && this.sdpInit) {
|
|
13589
|
+
await this.setupRemoteTracks();
|
|
13590
|
+
this._initialized$.next(true);
|
|
13508
13591
|
this.setupEventListeners();
|
|
13509
|
-
|
|
13592
|
+
this._isNegotiating$.next(true);
|
|
13593
|
+
await this._setRemoteDescription(this.sdpInit);
|
|
13594
|
+
} else {
|
|
13595
|
+
await this.setupTrackHandling();
|
|
13596
|
+
this._initialized$.next(true);
|
|
13510
13597
|
}
|
|
13511
13598
|
} catch (error) {
|
|
13512
13599
|
logger$11.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
@@ -13604,6 +13691,35 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13604
13691
|
default:
|
|
13605
13692
|
}
|
|
13606
13693
|
}
|
|
13694
|
+
/**
|
|
13695
|
+
* Accept an inbound call by creating the SDP answer.
|
|
13696
|
+
* Optionally override media options before the answer is generated.
|
|
13697
|
+
* Must be called after initialization for inbound (answer-type) connections.
|
|
13698
|
+
*/
|
|
13699
|
+
async acceptInbound(mediaOverrides) {
|
|
13700
|
+
if (mediaOverrides) {
|
|
13701
|
+
const { audio, video, receiveAudio, receiveVideo } = mediaOverrides;
|
|
13702
|
+
this.options = {
|
|
13703
|
+
...this.options,
|
|
13704
|
+
...audio !== void 0 ? { audio } : {},
|
|
13705
|
+
...video !== void 0 ? { video } : {},
|
|
13706
|
+
...receiveAudio !== void 0 ? { receiveAudio } : {},
|
|
13707
|
+
...receiveVideo !== void 0 ? { receiveVideo } : {}
|
|
13708
|
+
};
|
|
13709
|
+
this.transceiverController?.updateOptions({
|
|
13710
|
+
receiveAudio: this.receiveAudio,
|
|
13711
|
+
receiveVideo: this.receiveVideo
|
|
13712
|
+
});
|
|
13713
|
+
this.localStreamController.updateOptions({
|
|
13714
|
+
inputAudioDeviceConstraints: this.inputAudioDeviceConstraints,
|
|
13715
|
+
inputVideoDeviceConstraints: this.inputVideoDeviceConstraints
|
|
13716
|
+
});
|
|
13717
|
+
}
|
|
13718
|
+
await this.setupLocalTracks();
|
|
13719
|
+
const { answerOptions } = this;
|
|
13720
|
+
logger$11.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
13721
|
+
await this.createAnswer(answerOptions);
|
|
13722
|
+
}
|
|
13607
13723
|
async handleOfferReceived() {
|
|
13608
13724
|
if (!this.sdpInit) throw new DependencyError("SDP initialization parameters are not set");
|
|
13609
13725
|
this._isNegotiating$.next(true);
|
|
@@ -13678,37 +13794,29 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13678
13794
|
}
|
|
13679
13795
|
async setupLocalTracks() {
|
|
13680
13796
|
logger$11.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
13681
|
-
|
|
13682
|
-
if (
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
if (localStream) {
|
|
13689
|
-
if (this.transceiverController?.useAddStream ?? false) {
|
|
13690
|
-
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
13691
|
-
this.peerConnection?.addStream(localStream);
|
|
13692
|
-
if (!this.isNegotiating) {
|
|
13693
|
-
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
13694
|
-
this.negotiationNeeded$.next();
|
|
13695
|
-
}
|
|
13696
|
-
return;
|
|
13797
|
+
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
13798
|
+
if (this.transceiverController?.useAddStream ?? false) {
|
|
13799
|
+
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
13800
|
+
this.peerConnection?.addStream(localStream);
|
|
13801
|
+
if (!this.isNegotiating) {
|
|
13802
|
+
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
13803
|
+
this.negotiationNeeded$.next();
|
|
13697
13804
|
}
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
}
|
|
13805
|
+
return;
|
|
13806
|
+
}
|
|
13807
|
+
for (const kind of ["audio", "video"]) {
|
|
13808
|
+
const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
|
|
13809
|
+
index,
|
|
13810
|
+
track
|
|
13811
|
+
}));
|
|
13812
|
+
for (const { index, track } of tracks) {
|
|
13813
|
+
this.localStreamController.addTrackEndedListener(track);
|
|
13814
|
+
if (this.transceiverController?.useAddTransceivers ?? false) {
|
|
13815
|
+
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
13816
|
+
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
13817
|
+
} else {
|
|
13818
|
+
logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
13819
|
+
this.peerConnection?.addTrack(track, localStream);
|
|
13712
13820
|
}
|
|
13713
13821
|
}
|
|
13714
13822
|
}
|
|
@@ -13725,7 +13833,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13725
13833
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
13726
13834
|
this.peerConnection.ontrack = (event) => {
|
|
13727
13835
|
logger$11.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
13728
|
-
this._remoteStream$.next(event.streams[0]);
|
|
13836
|
+
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
13837
|
+
else {
|
|
13838
|
+
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
13839
|
+
const newStream = new MediaStream([...existingTracks, event.track]);
|
|
13840
|
+
this._remoteStream$.next(newStream);
|
|
13841
|
+
}
|
|
13729
13842
|
};
|
|
13730
13843
|
await this.transceiverController?.setupRemoteTransceivers(this.type);
|
|
13731
13844
|
}
|
|
@@ -13824,7 +13937,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13824
13937
|
});
|
|
13825
13938
|
}
|
|
13826
13939
|
get mediaDirections() {
|
|
13827
|
-
return this.transceiverController?.getMediaDirections() ?? {
|
|
13940
|
+
return this.transceiverController?.getMediaDirections() ?? this._remoteOfferMediaDirections ?? {
|
|
13828
13941
|
audio: "inactive",
|
|
13829
13942
|
video: "inactive"
|
|
13830
13943
|
};
|
|
@@ -13984,6 +14097,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
13984
14097
|
});
|
|
13985
14098
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
13986
14099
|
logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
14100
|
+
this._signalingStatus$.next("connecting");
|
|
13987
14101
|
const { sdp, callID } = event;
|
|
13988
14102
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
13989
14103
|
status: "received",
|
|
@@ -14055,13 +14169,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14055
14169
|
if (response.error) {
|
|
14056
14170
|
const error = new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14057
14171
|
this.onError?.(error);
|
|
14058
|
-
|
|
14172
|
+
return response;
|
|
14059
14173
|
}
|
|
14060
14174
|
const innerResult = getValueFrom(response, "result.result");
|
|
14061
14175
|
if (innerResult?.error) {
|
|
14062
14176
|
const error = new JSONRPCError(innerResult.error.code, innerResult.error.message, innerResult.error.data);
|
|
14063
14177
|
this.onError?.(error);
|
|
14064
|
-
|
|
14178
|
+
return response;
|
|
14065
14179
|
}
|
|
14066
14180
|
return response;
|
|
14067
14181
|
}
|
|
@@ -14081,7 +14195,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14081
14195
|
}
|
|
14082
14196
|
} catch (error) {
|
|
14083
14197
|
logger$10.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
14084
|
-
|
|
14198
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
14085
14199
|
}
|
|
14086
14200
|
}
|
|
14087
14201
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -14095,12 +14209,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14095
14209
|
});
|
|
14096
14210
|
} catch (error) {
|
|
14097
14211
|
logger$10.warn("[WebRTCManager] Error processing modify response:", error);
|
|
14098
|
-
|
|
14212
|
+
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
14213
|
+
this.onError?.(modifyError);
|
|
14099
14214
|
}
|
|
14100
14215
|
}
|
|
14101
14216
|
}
|
|
14102
14217
|
processInviteResponse(response, rtcPeerConnController) {
|
|
14103
14218
|
if (!response.error && getValueFrom(response, "result.result.result.message") === "CALL CREATED") {
|
|
14219
|
+
this._signalingStatus$.next("trying");
|
|
14104
14220
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
14105
14221
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
14106
14222
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
@@ -14155,6 +14271,36 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14155
14271
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
14156
14272
|
this.onError?.(error);
|
|
14157
14273
|
});
|
|
14274
|
+
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
14275
|
+
}
|
|
14276
|
+
async handleInboundAnswer(rtcPeerConnController) {
|
|
14277
|
+
logger$10.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
14278
|
+
const vertoByeOrAccepted = await (0, import_cjs$10.firstValueFrom)((0, import_cjs$10.race)(this.vertoBye$, this.webRtcCallSession.answered$).pipe((0, import_cjs$10.takeUntil)(this.destroyed$))).catch(() => null);
|
|
14279
|
+
if (vertoByeOrAccepted === null) {
|
|
14280
|
+
logger$10.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
14281
|
+
return;
|
|
14282
|
+
}
|
|
14283
|
+
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
14284
|
+
logger$10.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
14285
|
+
this.callSession?.destroy();
|
|
14286
|
+
} else if (!vertoByeOrAccepted) {
|
|
14287
|
+
logger$10.info("[WebRTCManager] Inbound call rejected by user.");
|
|
14288
|
+
try {
|
|
14289
|
+
await this.bye("USER_BUSY");
|
|
14290
|
+
} finally {
|
|
14291
|
+
this._signalingStatus$.next("disconnected");
|
|
14292
|
+
this.callSession?.destroy();
|
|
14293
|
+
}
|
|
14294
|
+
} else {
|
|
14295
|
+
logger$10.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
14296
|
+
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
14297
|
+
try {
|
|
14298
|
+
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
14299
|
+
} catch (error) {
|
|
14300
|
+
logger$10.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
14301
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
14302
|
+
}
|
|
14303
|
+
}
|
|
14158
14304
|
}
|
|
14159
14305
|
setupVertoAttachHandler() {
|
|
14160
14306
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
@@ -14172,7 +14318,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14172
14318
|
});
|
|
14173
14319
|
}
|
|
14174
14320
|
initObservables(rtcPeerConnController) {
|
|
14175
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$10.filter)((state) => state === "connected"), (0, import_cjs$10.
|
|
14321
|
+
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$10.filter)((state) => state === "connected"), (0, import_cjs$10.map)(() => rtcPeerConnController.mediaDirections), (0, import_cjs$10.startWith)(rtcPeerConnController.mediaDirections), (0, import_cjs$10.takeUntil)(this.destroyed$));
|
|
14176
14322
|
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$10.takeUntil)(this.destroyed$));
|
|
14177
14323
|
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$10.takeUntil)(this.destroyed$));
|
|
14178
14324
|
}
|
|
@@ -14188,7 +14334,6 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14188
14334
|
});
|
|
14189
14335
|
this.sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnController);
|
|
14190
14336
|
} else if (initial) {
|
|
14191
|
-
this._signalingStatus$.next("trying");
|
|
14192
14337
|
const vertoMessageRequest = VertoInvite({
|
|
14193
14338
|
dialogParams,
|
|
14194
14339
|
sdp
|
|
@@ -14495,8 +14640,8 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14495
14640
|
this.clientSession = clientSession;
|
|
14496
14641
|
this.options = options;
|
|
14497
14642
|
this.address = address;
|
|
14498
|
-
this.
|
|
14499
|
-
this.
|
|
14643
|
+
this._errors$ = this.createReplaySubject(1);
|
|
14644
|
+
this._lastMergedStatus = "new";
|
|
14500
14645
|
this._answered$ = this.createReplaySubject();
|
|
14501
14646
|
this._holdState = false;
|
|
14502
14647
|
this._userVariables$ = this.createBehaviorSubject({ ...PreferencesContainer.instance.userVariables });
|
|
@@ -14517,8 +14662,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14517
14662
|
const managers = initialization.initializeManagers(this);
|
|
14518
14663
|
this.vertoManager = managers.vertoManager;
|
|
14519
14664
|
this.callEventsManager = managers.callEventsManager;
|
|
14520
|
-
if (options.initOffer)
|
|
14521
|
-
|
|
14665
|
+
if (options.initOffer) {
|
|
14666
|
+
this._status$ = this.createBehaviorSubject("ringing");
|
|
14667
|
+
this._lastMergedStatus = "ringing";
|
|
14668
|
+
} else this._status$ = this.createBehaviorSubject("new");
|
|
14522
14669
|
const { deviceController } = initialization;
|
|
14523
14670
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
14524
14671
|
}
|
|
@@ -14526,9 +14673,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14526
14673
|
get errors$() {
|
|
14527
14674
|
return this._errors$.asObservable();
|
|
14528
14675
|
}
|
|
14529
|
-
/**
|
|
14530
|
-
|
|
14531
|
-
|
|
14676
|
+
/**
|
|
14677
|
+
* @internal Push an error to the call's error stream.
|
|
14678
|
+
* Fatal errors automatically transition the call to `'failed'` and destroy it.
|
|
14679
|
+
*/
|
|
14680
|
+
emitError(callError) {
|
|
14681
|
+
if (this._status$.value === "destroyed" || this._status$.value === "failed") return;
|
|
14682
|
+
this._errors$.next(callError);
|
|
14683
|
+
if (callError.fatal) {
|
|
14684
|
+
this._status$.next("failed");
|
|
14685
|
+
this.destroy();
|
|
14686
|
+
}
|
|
14532
14687
|
}
|
|
14533
14688
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
14534
14689
|
get direction() {
|
|
@@ -14568,7 +14723,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14568
14723
|
}
|
|
14569
14724
|
/** Current snapshot of all participants in the call. */
|
|
14570
14725
|
get participants() {
|
|
14571
|
-
return
|
|
14726
|
+
return this.callEventsManager.participants;
|
|
14572
14727
|
}
|
|
14573
14728
|
/** The local participant, or `null` if not yet joined. */
|
|
14574
14729
|
get self() {
|
|
@@ -14577,7 +14732,6 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14577
14732
|
async toggleLock() {
|
|
14578
14733
|
const method = this.locked ? "call.unlock" : "call.lock";
|
|
14579
14734
|
await this.executeMethod(this.selfId ?? "", method, {});
|
|
14580
|
-
throw new UnimplementedError();
|
|
14581
14735
|
}
|
|
14582
14736
|
async toggleHold() {
|
|
14583
14737
|
if (this._holdState) await this.vertoManager.unhold();
|
|
@@ -14619,25 +14773,31 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14619
14773
|
}
|
|
14620
14774
|
}
|
|
14621
14775
|
buildMethodParams(target, args) {
|
|
14622
|
-
const
|
|
14623
|
-
node_id: this.nodeId,
|
|
14624
|
-
call_id: this.id
|
|
14776
|
+
const self = {
|
|
14777
|
+
node_id: this.nodeId ?? "",
|
|
14778
|
+
call_id: this.id,
|
|
14779
|
+
member_id: this.vertoManager.selfId ?? ""
|
|
14780
|
+
};
|
|
14781
|
+
if (typeof target === "object") return {
|
|
14782
|
+
...args,
|
|
14783
|
+
self,
|
|
14784
|
+
targets: [target]
|
|
14625
14785
|
};
|
|
14626
14786
|
return {
|
|
14627
14787
|
...args,
|
|
14628
|
-
self
|
|
14629
|
-
...reference,
|
|
14630
|
-
member_id: this.vertoManager.selfId
|
|
14631
|
-
},
|
|
14788
|
+
self,
|
|
14632
14789
|
target: {
|
|
14633
|
-
|
|
14790
|
+
node_id: this.nodeId ?? "",
|
|
14791
|
+
call_id: this.id,
|
|
14634
14792
|
member_id: target
|
|
14635
14793
|
}
|
|
14636
14794
|
};
|
|
14637
14795
|
}
|
|
14638
14796
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
14639
14797
|
get status$() {
|
|
14640
|
-
return this.cachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$))
|
|
14798
|
+
return this.cachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$).pipe((0, import_cjs$9.distinctUntilChanged)(), (0, import_cjs$9.tap)((status) => {
|
|
14799
|
+
this._lastMergedStatus = status;
|
|
14800
|
+
})));
|
|
14641
14801
|
}
|
|
14642
14802
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
14643
14803
|
get participants$() {
|
|
@@ -14677,7 +14837,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14677
14837
|
}
|
|
14678
14838
|
/** Current call status. */
|
|
14679
14839
|
get status() {
|
|
14680
|
-
return this.
|
|
14840
|
+
return this._lastMergedStatus;
|
|
14681
14841
|
}
|
|
14682
14842
|
/** Whether the call is currently being recorded. */
|
|
14683
14843
|
get recording() {
|
|
@@ -14854,10 +15014,15 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14854
15014
|
async sendDigits(dtmf) {
|
|
14855
15015
|
return this.vertoManager.sendDigits(dtmf);
|
|
14856
15016
|
}
|
|
14857
|
-
/** Accepts an inbound call. */
|
|
14858
|
-
answer() {
|
|
15017
|
+
/** Accepts an inbound call, optionally overriding media options for the answer. */
|
|
15018
|
+
answer(options) {
|
|
15019
|
+
this._answerMediaOptions = options;
|
|
14859
15020
|
this._answered$.next(true);
|
|
14860
15021
|
}
|
|
15022
|
+
/** Media options provided when answering. Used internally by the VertoManager. */
|
|
15023
|
+
get answerMediaOptions() {
|
|
15024
|
+
return this._answerMediaOptions;
|
|
15025
|
+
}
|
|
14861
15026
|
/** Rejects an inbound call. */
|
|
14862
15027
|
reject() {
|
|
14863
15028
|
this._answered$.next(false);
|
|
@@ -14885,10 +15050,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14885
15050
|
}
|
|
14886
15051
|
/** Destroys the call, releasing all resources and subscriptions. */
|
|
14887
15052
|
destroy() {
|
|
15053
|
+
if (this._status$.value === "destroyed") return;
|
|
14888
15054
|
this._status$.next("destroyed");
|
|
14889
15055
|
this.vertoManager.destroy();
|
|
14890
15056
|
this.callEventsManager.destroy();
|
|
14891
|
-
this.participantsMap.clear();
|
|
14892
15057
|
super.destroy();
|
|
14893
15058
|
}
|
|
14894
15059
|
};
|
|
@@ -14896,6 +15061,23 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14896
15061
|
//#endregion
|
|
14897
15062
|
//#region src/managers/CallFactory.ts
|
|
14898
15063
|
/**
|
|
15064
|
+
* Infers the semantic error category from a raw Error thrown by VertoManager
|
|
15065
|
+
* or an RTCPeerConnection layer.
|
|
15066
|
+
*/
|
|
15067
|
+
function inferCallErrorKind(error) {
|
|
15068
|
+
if (error instanceof RPCTimeoutError) return "timeout";
|
|
15069
|
+
if (error instanceof JSONRPCError) return "signaling";
|
|
15070
|
+
if (error instanceof MediaTrackError) return "media";
|
|
15071
|
+
if (error instanceof WebSocketConnectionError || error instanceof TransportConnectionError) return "network";
|
|
15072
|
+
return "internal";
|
|
15073
|
+
}
|
|
15074
|
+
/** Determines whether an error should be fatal (destroy the call). */
|
|
15075
|
+
function isFatalError(error) {
|
|
15076
|
+
if (error instanceof VertoPongError) return false;
|
|
15077
|
+
if (error instanceof MediaTrackError) return false;
|
|
15078
|
+
return true;
|
|
15079
|
+
}
|
|
15080
|
+
/**
|
|
14899
15081
|
* Factory for creating WebRTCCall instances with proper manager wiring.
|
|
14900
15082
|
* Eliminates circular dependencies by centralizing Call and Manager creation.
|
|
14901
15083
|
*/
|
|
@@ -14916,7 +15098,13 @@ var CallFactory = class {
|
|
|
14916
15098
|
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
|
|
14917
15099
|
nodeId: options.nodeId,
|
|
14918
15100
|
onError: (error) => {
|
|
14919
|
-
|
|
15101
|
+
const callError = {
|
|
15102
|
+
kind: inferCallErrorKind(error),
|
|
15103
|
+
fatal: isFatalError(error),
|
|
15104
|
+
error,
|
|
15105
|
+
callId: callInstance.id
|
|
15106
|
+
};
|
|
15107
|
+
callInstance.emitError(callError);
|
|
14920
15108
|
}
|
|
14921
15109
|
}),
|
|
14922
15110
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -15296,9 +15484,15 @@ var PendingRPC = class PendingRPC {
|
|
|
15296
15484
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
15297
15485
|
}) : import_cjs$6.NEVER).subscribe({
|
|
15298
15486
|
next: (response) => {
|
|
15299
|
-
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
15300
15487
|
isSettled = true;
|
|
15301
|
-
|
|
15488
|
+
if (response.error) {
|
|
15489
|
+
const rpcError = new RPCError(response.error.code, request.id, response.error.message, response.error.data);
|
|
15490
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
15491
|
+
reject(rpcError);
|
|
15492
|
+
} else {
|
|
15493
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
15494
|
+
resolve(response);
|
|
15495
|
+
}
|
|
15302
15496
|
subscription.unsubscribe();
|
|
15303
15497
|
},
|
|
15304
15498
|
error: (error) => {
|
|
@@ -15355,7 +15549,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15355
15549
|
revision: 0
|
|
15356
15550
|
};
|
|
15357
15551
|
this._authorization$ = this.createBehaviorSubject(void 0);
|
|
15358
|
-
this._errors$ = this.
|
|
15552
|
+
this._errors$ = this.createReplaySubject(1);
|
|
15359
15553
|
this._authenticated$ = this.createBehaviorSubject(false);
|
|
15360
15554
|
this._subscriberInfo$ = this.createBehaviorSubject(null);
|
|
15361
15555
|
this._calls$ = this.createBehaviorSubject({});
|
|
@@ -15625,12 +15819,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15625
15819
|
}
|
|
15626
15820
|
async createOutboundCall(destination, options = {}) {
|
|
15627
15821
|
const destinationURI = destination instanceof Address ? destination.defaultChannel : destination;
|
|
15822
|
+
let callSession;
|
|
15628
15823
|
try {
|
|
15629
|
-
|
|
15824
|
+
callSession = await this.createCall({
|
|
15630
15825
|
to: destinationURI,
|
|
15631
15826
|
...options
|
|
15632
15827
|
});
|
|
15633
|
-
await (0, import_cjs$5.firstValueFrom)(callSession.selfId$.pipe((0, import_cjs$5.filter)((id) => Boolean(id)), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)(this.callCreateTimeout)));
|
|
15828
|
+
await (0, import_cjs$5.firstValueFrom)((0, import_cjs$5.race)(callSession.selfId$.pipe((0, import_cjs$5.filter)((id) => Boolean(id)), (0, import_cjs$5.take)(1), (0, import_cjs$5.timeout)(this.callCreateTimeout)), callSession.errors$.pipe((0, import_cjs$5.take)(1), (0, import_cjs$5.switchMap)((callError) => (0, import_cjs$5.throwError)(() => callError.error)))));
|
|
15634
15829
|
this._calls$.next({
|
|
15635
15830
|
[`${callSession.id}`]: callSession,
|
|
15636
15831
|
...this._calls$.value
|
|
@@ -15638,7 +15833,8 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15638
15833
|
return callSession;
|
|
15639
15834
|
} catch (error) {
|
|
15640
15835
|
logger$6.error("[Session] Error creating outbound call:", error);
|
|
15641
|
-
|
|
15836
|
+
callSession?.destroy();
|
|
15837
|
+
const callError = new CallCreateError(error instanceof import_cjs$5.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
15642
15838
|
this._errors$.next(callError);
|
|
15643
15839
|
throw callError;
|
|
15644
15840
|
}
|
|
@@ -15664,7 +15860,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15664
15860
|
return callSession;
|
|
15665
15861
|
} catch (error) {
|
|
15666
15862
|
logger$6.error("[Session] Error creating call session:", error);
|
|
15667
|
-
throw new CallCreateError("Call create error", error);
|
|
15863
|
+
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
15668
15864
|
}
|
|
15669
15865
|
}
|
|
15670
15866
|
destroy() {
|
|
@@ -15913,7 +16109,7 @@ var WebSocketController = class WebSocketController extends Destroyable {
|
|
|
15913
16109
|
this.shouldReconnect = false;
|
|
15914
16110
|
this._status$ = this.createBehaviorSubject("disconnected");
|
|
15915
16111
|
this._incomingMessages$ = this.createSubject();
|
|
15916
|
-
this._errors$ = this.
|
|
16112
|
+
this._errors$ = this.createReplaySubject(1);
|
|
15917
16113
|
this.reconnectDelayMin = options.reconnectDelayMin ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MIN_MS;
|
|
15918
16114
|
this.reconnectDelayMax = options.reconnectDelayMax ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MAX_MS;
|
|
15919
16115
|
this.connectionTimeout = options.connectionTimeout ?? WebSocketController.DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
@@ -16240,7 +16436,8 @@ const buildOptionsFromDestination = (destination) => {
|
|
|
16240
16436
|
const channel = new URLSearchParams(queryString).get("channel");
|
|
16241
16437
|
if (channel === "video") return {
|
|
16242
16438
|
audio: true,
|
|
16243
|
-
video: true
|
|
16439
|
+
video: true,
|
|
16440
|
+
receiveVideo: true
|
|
16244
16441
|
};
|
|
16245
16442
|
else if (channel === "audio") return {
|
|
16246
16443
|
audio: true,
|
|
@@ -16270,7 +16467,7 @@ var SignalWire = class extends Destroyable {
|
|
|
16270
16467
|
this._directory$ = this.createBehaviorSubject(void 0);
|
|
16271
16468
|
this._isConnected$ = this.createBehaviorSubject(false);
|
|
16272
16469
|
this._isRegistered$ = this.createBehaviorSubject(false);
|
|
16273
|
-
this._errors$ = this.
|
|
16470
|
+
this._errors$ = this.createReplaySubject(1);
|
|
16274
16471
|
this._options = {};
|
|
16275
16472
|
this._deps = new DependencyContainer();
|
|
16276
16473
|
this._options = {
|
|
@@ -16347,7 +16544,12 @@ var SignalWire = class extends Destroyable {
|
|
|
16347
16544
|
this._subscriber$.next(new Subscriber(this._deps.http));
|
|
16348
16545
|
if (!this._options.skipConnection) await this.connect();
|
|
16349
16546
|
if (!this._options.reconnectAttachedCalls && this._attachManager) await this._attachManager.flush();
|
|
16350
|
-
if (!this._options.skipRegister)
|
|
16547
|
+
if (!this._options.skipRegister) try {
|
|
16548
|
+
await this.register();
|
|
16549
|
+
} catch (error) {
|
|
16550
|
+
logger$1.error("[SignalWire] Registration failed:", error);
|
|
16551
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16552
|
+
}
|
|
16351
16553
|
this.handleAttachments();
|
|
16352
16554
|
}
|
|
16353
16555
|
async handleAttachments() {
|
|
@@ -16510,8 +16712,22 @@ var SignalWire = class extends Destroyable {
|
|
|
16510
16712
|
}));
|
|
16511
16713
|
this._isRegistered$.next(true);
|
|
16512
16714
|
} catch (error) {
|
|
16513
|
-
logger$1.
|
|
16715
|
+
logger$1.debug("[SignalWire] Failed to register subscriber, trying reauthentication...");
|
|
16716
|
+
if (this._deps.credential.token) this._clientSession.reauthenticate(this._deps.credential.token).then(async () => {
|
|
16717
|
+
logger$1.debug("[SignalWire] Reauthentication successful, retrying register()");
|
|
16718
|
+
await this._transport.execute(RPCExecute({
|
|
16719
|
+
method: "subscriber.online",
|
|
16720
|
+
params: {}
|
|
16721
|
+
}));
|
|
16722
|
+
this._isRegistered$.next(true);
|
|
16723
|
+
}).catch((reauthError) => {
|
|
16724
|
+
logger$1.error("[SignalWire] Reauthentication failed during register():", reauthError);
|
|
16725
|
+
const registerError = new InvalidCredentialsError("Failed to register subscriber, and reauthentication attempt also failed. Please check your credentials.", { cause: reauthError instanceof Error ? reauthError : new Error(String(reauthError), { cause: reauthError }) });
|
|
16726
|
+
this._errors$.next(registerError);
|
|
16727
|
+
throw registerError;
|
|
16728
|
+
});
|
|
16514
16729
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16730
|
+
throw error;
|
|
16515
16731
|
}
|
|
16516
16732
|
}
|
|
16517
16733
|
/** Unregisters the subscriber, going offline for inbound calls. */
|