@signalwire/js 4.0.0-beta.7 → 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.mjs
CHANGED
|
@@ -3107,7 +3107,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3107
3107
|
exports.throwError = void 0;
|
|
3108
3108
|
var Observable_1$18 = require_Observable();
|
|
3109
3109
|
var isFunction_1$14 = require_isFunction();
|
|
3110
|
-
function throwError(errorOrErrorFactory, scheduler) {
|
|
3110
|
+
function throwError$1(errorOrErrorFactory, scheduler) {
|
|
3111
3111
|
var errorFactory = isFunction_1$14.isFunction(errorOrErrorFactory) ? errorOrErrorFactory : function() {
|
|
3112
3112
|
return errorOrErrorFactory;
|
|
3113
3113
|
};
|
|
@@ -3118,7 +3118,7 @@ var require_throwError = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
3118
3118
|
return scheduler.schedule(init, 0, subscriber);
|
|
3119
3119
|
} : init);
|
|
3120
3120
|
}
|
|
3121
|
-
exports.throwError = throwError;
|
|
3121
|
+
exports.throwError = throwError$1;
|
|
3122
3122
|
}));
|
|
3123
3123
|
|
|
3124
3124
|
//#endregion
|
|
@@ -4327,13 +4327,13 @@ var require_race$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4327
4327
|
var innerFrom_1$28 = require_innerFrom();
|
|
4328
4328
|
var argsOrArgArray_1$4 = require_argsOrArgArray();
|
|
4329
4329
|
var OperatorSubscriber_1$48 = require_OperatorSubscriber();
|
|
4330
|
-
function race$
|
|
4330
|
+
function race$4() {
|
|
4331
4331
|
var sources = [];
|
|
4332
4332
|
for (var _i = 0; _i < arguments.length; _i++) sources[_i] = arguments[_i];
|
|
4333
4333
|
sources = argsOrArgArray_1$4.argsOrArgArray(sources);
|
|
4334
4334
|
return sources.length === 1 ? innerFrom_1$28.innerFrom(sources[0]) : new Observable_1$6.Observable(raceInit(sources));
|
|
4335
4335
|
}
|
|
4336
|
-
exports.race = race$
|
|
4336
|
+
exports.race = race$4;
|
|
4337
4337
|
function raceInit(sources) {
|
|
4338
4338
|
return function(subscriber) {
|
|
4339
4339
|
var subscriptions = [];
|
|
@@ -5470,7 +5470,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
5470
5470
|
var identity_1$10 = require_identity();
|
|
5471
5471
|
var lift_1$42 = require_lift();
|
|
5472
5472
|
var OperatorSubscriber_1$31 = require_OperatorSubscriber();
|
|
5473
|
-
function distinctUntilChanged$
|
|
5473
|
+
function distinctUntilChanged$6(comparator, keySelector) {
|
|
5474
5474
|
if (keySelector === void 0) keySelector = identity_1$10.identity;
|
|
5475
5475
|
comparator = comparator !== null && comparator !== void 0 ? comparator : defaultCompare;
|
|
5476
5476
|
return lift_1$42.operate(function(source, subscriber) {
|
|
@@ -5486,7 +5486,7 @@ var require_distinctUntilChanged = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
5486
5486
|
}));
|
|
5487
5487
|
});
|
|
5488
5488
|
}
|
|
5489
|
-
exports.distinctUntilChanged = distinctUntilChanged$
|
|
5489
|
+
exports.distinctUntilChanged = distinctUntilChanged$6;
|
|
5490
5490
|
function defaultCompare(a, b) {
|
|
5491
5491
|
return a === b;
|
|
5492
5492
|
}
|
|
@@ -6915,7 +6915,7 @@ var require_startWith = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6915
6915
|
var concat_1$2 = require_concat$1();
|
|
6916
6916
|
var args_1$2 = require_args();
|
|
6917
6917
|
var lift_1$14 = require_lift();
|
|
6918
|
-
function startWith() {
|
|
6918
|
+
function startWith$1() {
|
|
6919
6919
|
var values = [];
|
|
6920
6920
|
for (var _i = 0; _i < arguments.length; _i++) values[_i] = arguments[_i];
|
|
6921
6921
|
var scheduler = args_1$2.popScheduler(values);
|
|
@@ -6923,7 +6923,7 @@ var require_startWith = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6923
6923
|
(scheduler ? concat_1$2.concat(values, source, scheduler) : concat_1$2.concat(values, source)).subscribe(subscriber);
|
|
6924
6924
|
});
|
|
6925
6925
|
}
|
|
6926
|
-
exports.startWith = startWith;
|
|
6926
|
+
exports.startWith = startWith$1;
|
|
6927
6927
|
}));
|
|
6928
6928
|
|
|
6929
6929
|
//#endregion
|
|
@@ -6934,7 +6934,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6934
6934
|
var innerFrom_1$6 = require_innerFrom();
|
|
6935
6935
|
var lift_1$13 = require_lift();
|
|
6936
6936
|
var OperatorSubscriber_1$11 = require_OperatorSubscriber();
|
|
6937
|
-
function switchMap$
|
|
6937
|
+
function switchMap$4(project, resultSelector) {
|
|
6938
6938
|
return lift_1$13.operate(function(source, subscriber) {
|
|
6939
6939
|
var innerSubscriber = null;
|
|
6940
6940
|
var index = 0;
|
|
@@ -6958,7 +6958,7 @@ var require_switchMap = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
6958
6958
|
}));
|
|
6959
6959
|
});
|
|
6960
6960
|
}
|
|
6961
|
-
exports.switchMap = switchMap$
|
|
6961
|
+
exports.switchMap = switchMap$4;
|
|
6962
6962
|
}));
|
|
6963
6963
|
|
|
6964
6964
|
//#endregion
|
|
@@ -9104,13 +9104,14 @@ var DependencyError = class extends Error {
|
|
|
9104
9104
|
}
|
|
9105
9105
|
};
|
|
9106
9106
|
var CallCreateError = class extends Error {
|
|
9107
|
-
constructor(message, error = null, options) {
|
|
9107
|
+
constructor(message, error = null, direction = "outbound", options) {
|
|
9108
9108
|
super(message, {
|
|
9109
9109
|
...options,
|
|
9110
9110
|
cause: options?.cause ?? (error instanceof Error ? error : void 0)
|
|
9111
9111
|
});
|
|
9112
9112
|
this.message = message;
|
|
9113
9113
|
this.error = error;
|
|
9114
|
+
this.direction = direction;
|
|
9114
9115
|
this.name = "CallCreateError";
|
|
9115
9116
|
}
|
|
9116
9117
|
};
|
|
@@ -9122,6 +9123,15 @@ var JSONRPCError = class extends Error {
|
|
|
9122
9123
|
this.name = "JSONRPCError";
|
|
9123
9124
|
}
|
|
9124
9125
|
};
|
|
9126
|
+
var RPCError = class extends Error {
|
|
9127
|
+
constructor(code, requestId, message, data, options) {
|
|
9128
|
+
super(message, options);
|
|
9129
|
+
this.code = code;
|
|
9130
|
+
this.requestId = requestId;
|
|
9131
|
+
this.data = data;
|
|
9132
|
+
this.name = "RPCError";
|
|
9133
|
+
}
|
|
9134
|
+
};
|
|
9125
9135
|
var InvalidParams = class extends Error {
|
|
9126
9136
|
constructor(message, options) {
|
|
9127
9137
|
super(message, options);
|
|
@@ -9660,7 +9670,7 @@ var PreferencesContainer = class PreferencesContainer {
|
|
|
9660
9670
|
skipDeviceMonitoring: false,
|
|
9661
9671
|
savePreferences: false
|
|
9662
9672
|
};
|
|
9663
|
-
this.receiveVideo =
|
|
9673
|
+
this.receiveVideo = false;
|
|
9664
9674
|
this.receiveAudio = true;
|
|
9665
9675
|
this.preferredAudioInput = null;
|
|
9666
9676
|
this.preferredAudioOutput = null;
|
|
@@ -9973,7 +9983,7 @@ var NavigatorDeviceController = class extends Destroyable {
|
|
|
9973
9983
|
};
|
|
9974
9984
|
this._devicesState$ = this.createBehaviorSubject(initialDevicesState);
|
|
9975
9985
|
this._selectedDevicesState$ = this.createBehaviorSubject(initialSelectedDevicesState);
|
|
9976
|
-
this._errors$ = this.
|
|
9986
|
+
this._errors$ = this.createReplaySubject(1);
|
|
9977
9987
|
this.init();
|
|
9978
9988
|
}
|
|
9979
9989
|
get selectedAudioInputDeviceConstraints() {
|
|
@@ -10500,7 +10510,7 @@ const RPCExecute = ({ method, params }) => {
|
|
|
10500
10510
|
|
|
10501
10511
|
//#endregion
|
|
10502
10512
|
//#region src/core/RPCMessages/VertoMessages.ts
|
|
10503
|
-
const
|
|
10513
|
+
const SDK_TO_VERTO_FIELD_MAP = {
|
|
10504
10514
|
id: "callID",
|
|
10505
10515
|
destinationNumber: "destination_number",
|
|
10506
10516
|
remoteCallerName: "remote_caller_id_name",
|
|
@@ -10509,19 +10519,31 @@ const tmpMap = {
|
|
|
10509
10519
|
callerNumber: "caller_id_number",
|
|
10510
10520
|
fromCallAddressId: "from_fabric_address_id"
|
|
10511
10521
|
};
|
|
10522
|
+
const EXCLUDED_DIALOG_PARAMS = new Set([
|
|
10523
|
+
"remoteSdp",
|
|
10524
|
+
"localStream",
|
|
10525
|
+
"remoteStream"
|
|
10526
|
+
]);
|
|
10512
10527
|
/**
|
|
10513
|
-
* Translate SDK fields into verto variables
|
|
10528
|
+
* Translate SDK fields into verto variables.
|
|
10529
|
+
* Returns a new object — the input is never mutated.
|
|
10514
10530
|
*/
|
|
10531
|
+
/** @internal Exported for testing only. */
|
|
10515
10532
|
const filterVertoParams = (params) => {
|
|
10516
|
-
if (Object.prototype.hasOwnProperty.call(params, "dialogParams"))
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10533
|
+
if (!Object.prototype.hasOwnProperty.call(params, "dialogParams")) return params;
|
|
10534
|
+
const sourceDialogParams = params.dialogParams;
|
|
10535
|
+
const filteredDialogParams = Object.entries(sourceDialogParams).reduce((acc, [key, value]) => {
|
|
10536
|
+
if (EXCLUDED_DIALOG_PARAMS.has(key)) return acc;
|
|
10537
|
+
const mappedKey = SDK_TO_VERTO_FIELD_MAP[key] ?? key;
|
|
10538
|
+
return {
|
|
10539
|
+
...acc,
|
|
10540
|
+
[mappedKey]: value
|
|
10541
|
+
};
|
|
10542
|
+
}, {});
|
|
10543
|
+
return {
|
|
10544
|
+
...params,
|
|
10545
|
+
dialogParams: filteredDialogParams
|
|
10546
|
+
};
|
|
10525
10547
|
};
|
|
10526
10548
|
const buildVertoRPCMessage = (method) => {
|
|
10527
10549
|
return (params = {}) => {
|
|
@@ -10703,12 +10725,12 @@ var require_race = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
10703
10725
|
exports.race = void 0;
|
|
10704
10726
|
var argsOrArgArray_1 = require_argsOrArgArray();
|
|
10705
10727
|
var raceWith_1$1 = require_raceWith();
|
|
10706
|
-
function race$
|
|
10728
|
+
function race$3() {
|
|
10707
10729
|
var args = [];
|
|
10708
10730
|
for (var _i = 0; _i < arguments.length; _i++) args[_i] = arguments[_i];
|
|
10709
10731
|
return raceWith_1$1.raceWith.apply(void 0, __spreadArray([], __read(argsOrArgArray_1.argsOrArgArray(args))));
|
|
10710
10732
|
}
|
|
10711
|
-
exports.race = race$
|
|
10733
|
+
exports.race = race$3;
|
|
10712
10734
|
}));
|
|
10713
10735
|
|
|
10714
10736
|
//#endregion
|
|
@@ -12042,7 +12064,13 @@ var Participant = class extends Destroyable {
|
|
|
12042
12064
|
}
|
|
12043
12065
|
/** Removes this participant from the call. */
|
|
12044
12066
|
async remove() {
|
|
12045
|
-
|
|
12067
|
+
const state = this._state$.value;
|
|
12068
|
+
const target = {
|
|
12069
|
+
member_id: this.id,
|
|
12070
|
+
call_id: state.call_id ?? "",
|
|
12071
|
+
node_id: state.node_id ?? ""
|
|
12072
|
+
};
|
|
12073
|
+
await this.executeMethod(target, "call.member.remove", {});
|
|
12046
12074
|
}
|
|
12047
12075
|
/** Ends the call for this participant. */
|
|
12048
12076
|
async end() {
|
|
@@ -12401,7 +12429,6 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12401
12429
|
this.options = options;
|
|
12402
12430
|
this.callIds = /* @__PURE__ */ new Set();
|
|
12403
12431
|
this.roomSessionIds = /* @__PURE__ */ new Set();
|
|
12404
|
-
this._status$ = this.createBehaviorSubject("trying");
|
|
12405
12432
|
this._participants$ = this.createBehaviorSubject({});
|
|
12406
12433
|
this._self$ = this.createBehaviorSubject(null);
|
|
12407
12434
|
this._sessionState$ = this.createBehaviorSubject(initialSessionState);
|
|
@@ -12410,15 +12437,12 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12410
12437
|
get participants$() {
|
|
12411
12438
|
return this.cachedObservable("participants$", () => this._participants$.asObservable().pipe((0, import_cjs$14.map)((participantsRecord) => Object.values(participantsRecord))));
|
|
12412
12439
|
}
|
|
12440
|
+
get participants() {
|
|
12441
|
+
return Object.values(this._participants$.value);
|
|
12442
|
+
}
|
|
12413
12443
|
get self$() {
|
|
12414
12444
|
return this.cachedObservable("self$", () => this._self$.asObservable().pipe(filterNull()));
|
|
12415
12445
|
}
|
|
12416
|
-
get status$() {
|
|
12417
|
-
return this._status$.asObservable();
|
|
12418
|
-
}
|
|
12419
|
-
get status() {
|
|
12420
|
-
return this._status$.value;
|
|
12421
|
-
}
|
|
12422
12446
|
isRoomSessionIdValid(roomSessionId) {
|
|
12423
12447
|
return this.roomSessionIds.has(roomSessionId);
|
|
12424
12448
|
}
|
|
@@ -12503,7 +12527,6 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12503
12527
|
callId: callJoinedEvent.call_id,
|
|
12504
12528
|
roomSessionId: callJoinedEvent.room_session_id
|
|
12505
12529
|
});
|
|
12506
|
-
this._status$.next("connected");
|
|
12507
12530
|
const sessionState = callJoinedEvent.room_session;
|
|
12508
12531
|
const { capabilities } = callJoinedEvent;
|
|
12509
12532
|
this.selfId = this.selfId ?? callJoinedEvent.member_id;
|
|
@@ -12630,12 +12653,53 @@ var CallEventsManager = class extends Destroyable {
|
|
|
12630
12653
|
|
|
12631
12654
|
//#endregion
|
|
12632
12655
|
//#region src/helpers/SDPHelper.ts
|
|
12656
|
+
/** Valid SDP direction attribute values. */
|
|
12657
|
+
const SDP_DIRECTIONS = new Set([
|
|
12658
|
+
"sendrecv",
|
|
12659
|
+
"sendonly",
|
|
12660
|
+
"recvonly",
|
|
12661
|
+
"inactive"
|
|
12662
|
+
]);
|
|
12633
12663
|
/**
|
|
12634
|
-
*
|
|
12664
|
+
* Extracts the media directions (audio/video) from an SDP string.
|
|
12665
|
+
*
|
|
12666
|
+
* Parses each media section (`m=audio` / `m=video`) and reads the `a=` direction
|
|
12667
|
+
* attribute (`sendrecv`, `sendonly`, `recvonly`, `inactive`).
|
|
12668
|
+
* If no explicit direction attribute is found for a media section, defaults to `sendrecv`
|
|
12669
|
+
* per RFC 4566.
|
|
12635
12670
|
*
|
|
12636
|
-
*
|
|
12637
|
-
*
|
|
12671
|
+
* @param sdp - The SDP string to parse
|
|
12672
|
+
* @returns The extracted audio and video directions
|
|
12673
|
+
*
|
|
12674
|
+
* @example
|
|
12675
|
+
* ```typescript
|
|
12676
|
+
* 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`;
|
|
12677
|
+
* extractMediaDirectionsFromSDP(sdp);
|
|
12678
|
+
* // { audio: 'sendrecv', video: 'recvonly' }
|
|
12679
|
+
* ```
|
|
12638
12680
|
*/
|
|
12681
|
+
function extractMediaDirectionsFromSDP(sdp) {
|
|
12682
|
+
const result = {
|
|
12683
|
+
audio: "inactive",
|
|
12684
|
+
video: "inactive"
|
|
12685
|
+
};
|
|
12686
|
+
if (!sdp) return result;
|
|
12687
|
+
const lines = sdp.split(/\r?\n/);
|
|
12688
|
+
let currentMediaKind = null;
|
|
12689
|
+
let currentDirection = null;
|
|
12690
|
+
for (const line of lines) if (line.startsWith("m=")) {
|
|
12691
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
12692
|
+
if (line.startsWith("m=audio")) currentMediaKind = "audio";
|
|
12693
|
+
else if (line.startsWith("m=video")) currentMediaKind = "video";
|
|
12694
|
+
else currentMediaKind = null;
|
|
12695
|
+
currentDirection = null;
|
|
12696
|
+
} else if (currentMediaKind && line.startsWith("a=")) {
|
|
12697
|
+
const attr = line.substring(2).trim();
|
|
12698
|
+
if (SDP_DIRECTIONS.has(attr)) currentDirection = attr;
|
|
12699
|
+
}
|
|
12700
|
+
if (currentMediaKind) result[currentMediaKind] = currentDirection ?? "sendrecv";
|
|
12701
|
+
return result;
|
|
12702
|
+
}
|
|
12639
12703
|
/**
|
|
12640
12704
|
* Validates that an SDP string has at least one non-host ICE candidate
|
|
12641
12705
|
* for each media section (m= line).
|
|
@@ -12938,6 +13002,15 @@ var LocalStreamController = class extends Destroyable {
|
|
|
12938
13002
|
track.addEventListener("ended", this.mediaTrackEndedHandler);
|
|
12939
13003
|
}
|
|
12940
13004
|
/**
|
|
13005
|
+
* Update the controller options (e.g., when media overrides are applied).
|
|
13006
|
+
*/
|
|
13007
|
+
updateOptions(options) {
|
|
13008
|
+
this.options = {
|
|
13009
|
+
...this.options,
|
|
13010
|
+
...options
|
|
13011
|
+
};
|
|
13012
|
+
}
|
|
13013
|
+
/**
|
|
12941
13014
|
* Stop all local tracks and clean up.
|
|
12942
13015
|
*/
|
|
12943
13016
|
stopAllTracks() {
|
|
@@ -13276,11 +13349,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13276
13349
|
this._connectionState$ = this.createReplaySubject(1);
|
|
13277
13350
|
this._signalingState$ = this.createReplaySubject(1);
|
|
13278
13351
|
this._iceGatheringState$ = this.createReplaySubject(1);
|
|
13279
|
-
this._errors$ = this.
|
|
13352
|
+
this._errors$ = this.createReplaySubject(1);
|
|
13280
13353
|
this._iceCandidates$ = this.createReplaySubject(1);
|
|
13281
13354
|
this._initialized$ = this.createReplaySubject(1);
|
|
13282
13355
|
this._remoteDescription$ = this.createReplaySubject(1);
|
|
13283
13356
|
this._remoteStream$ = this.createBehaviorSubject(null);
|
|
13357
|
+
this._remoteOfferMediaDirections = null;
|
|
13284
13358
|
this.deviceController = deviceController ?? {};
|
|
13285
13359
|
this.id = options.callId ?? v4_default();
|
|
13286
13360
|
this._type = remoteSessionDescription ? "answer" : "offer";
|
|
@@ -13288,10 +13362,19 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13288
13362
|
type: "offer",
|
|
13289
13363
|
sdp: remoteSessionDescription
|
|
13290
13364
|
} : void 0;
|
|
13365
|
+
this._remoteOfferMediaDirections = remoteSessionDescription ? extractMediaDirectionsFromSDP(remoteSessionDescription) : null;
|
|
13366
|
+
const offerDefaults = this._remoteOfferMediaDirections ? {
|
|
13367
|
+
audio: this._remoteOfferMediaDirections.audio.includes("recv"),
|
|
13368
|
+
video: this._remoteOfferMediaDirections.video.includes("recv"),
|
|
13369
|
+
receiveAudio: this._remoteOfferMediaDirections.audio.includes("send"),
|
|
13370
|
+
receiveVideo: this._remoteOfferMediaDirections.video.includes("send")
|
|
13371
|
+
} : {};
|
|
13291
13372
|
this.options = {
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13373
|
+
...options,
|
|
13374
|
+
audio: options.audio ?? offerDefaults.audio,
|
|
13375
|
+
video: options.video ?? offerDefaults.video,
|
|
13376
|
+
receiveAudio: options.receiveAudio ?? offerDefaults.receiveAudio ?? PreferencesContainer.instance.receiveAudio,
|
|
13377
|
+
receiveVideo: options.receiveVideo ?? offerDefaults.receiveVideo ?? PreferencesContainer.instance.receiveVideo
|
|
13295
13378
|
};
|
|
13296
13379
|
this.localStreamController = new LocalStreamController({
|
|
13297
13380
|
propose: this.propose,
|
|
@@ -13436,7 +13519,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13436
13519
|
};
|
|
13437
13520
|
}
|
|
13438
13521
|
get inputVideoDeviceConstraints() {
|
|
13439
|
-
if (this.options.video
|
|
13522
|
+
if (!this.options.video && !this.options.inputVideoDeviceConstraints) return false;
|
|
13440
13523
|
return {
|
|
13441
13524
|
...this.options.inputVideoDeviceConstraints,
|
|
13442
13525
|
...this.deviceController.selectedVideoInputDeviceConstraints
|
|
@@ -13458,12 +13541,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13458
13541
|
default: return {
|
|
13459
13542
|
...options,
|
|
13460
13543
|
offerToReceiveAudio: true,
|
|
13461
|
-
offerToReceiveVideo: Boolean(this.inputVideoDeviceConstraints)
|
|
13544
|
+
offerToReceiveVideo: this.options.receiveVideo ?? Boolean(this.inputVideoDeviceConstraints)
|
|
13462
13545
|
};
|
|
13463
13546
|
}
|
|
13464
13547
|
}
|
|
13465
13548
|
get answerOptions() {
|
|
13466
|
-
return {};
|
|
13549
|
+
return { iceRestart: this.firstSDPExchangeCompleted ? true : void 0 };
|
|
13467
13550
|
}
|
|
13468
13551
|
/**
|
|
13469
13552
|
* Initialize the RTCPeerConnection and setup event listeners.
|
|
@@ -13498,11 +13581,15 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13498
13581
|
});
|
|
13499
13582
|
await this.updateSelectedInputDevice(kind, deviceInfo);
|
|
13500
13583
|
});
|
|
13501
|
-
await this.setupTrackHandling();
|
|
13502
|
-
this._initialized$.next(true);
|
|
13503
13584
|
if (this.type === "answer" && this.sdpInit) {
|
|
13585
|
+
await this.setupRemoteTracks();
|
|
13586
|
+
this._initialized$.next(true);
|
|
13504
13587
|
this.setupEventListeners();
|
|
13505
|
-
|
|
13588
|
+
this._isNegotiating$.next(true);
|
|
13589
|
+
await this._setRemoteDescription(this.sdpInit);
|
|
13590
|
+
} else {
|
|
13591
|
+
await this.setupTrackHandling();
|
|
13592
|
+
this._initialized$.next(true);
|
|
13506
13593
|
}
|
|
13507
13594
|
} catch (error) {
|
|
13508
13595
|
logger$11.error("[RTCPeerConnectionController] Initialization error:", error);
|
|
@@ -13600,6 +13687,35 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13600
13687
|
default:
|
|
13601
13688
|
}
|
|
13602
13689
|
}
|
|
13690
|
+
/**
|
|
13691
|
+
* Accept an inbound call by creating the SDP answer.
|
|
13692
|
+
* Optionally override media options before the answer is generated.
|
|
13693
|
+
* Must be called after initialization for inbound (answer-type) connections.
|
|
13694
|
+
*/
|
|
13695
|
+
async acceptInbound(mediaOverrides) {
|
|
13696
|
+
if (mediaOverrides) {
|
|
13697
|
+
const { audio, video, receiveAudio, receiveVideo } = mediaOverrides;
|
|
13698
|
+
this.options = {
|
|
13699
|
+
...this.options,
|
|
13700
|
+
...audio !== void 0 ? { audio } : {},
|
|
13701
|
+
...video !== void 0 ? { video } : {},
|
|
13702
|
+
...receiveAudio !== void 0 ? { receiveAudio } : {},
|
|
13703
|
+
...receiveVideo !== void 0 ? { receiveVideo } : {}
|
|
13704
|
+
};
|
|
13705
|
+
this.transceiverController?.updateOptions({
|
|
13706
|
+
receiveAudio: this.receiveAudio,
|
|
13707
|
+
receiveVideo: this.receiveVideo
|
|
13708
|
+
});
|
|
13709
|
+
this.localStreamController.updateOptions({
|
|
13710
|
+
inputAudioDeviceConstraints: this.inputAudioDeviceConstraints,
|
|
13711
|
+
inputVideoDeviceConstraints: this.inputVideoDeviceConstraints
|
|
13712
|
+
});
|
|
13713
|
+
}
|
|
13714
|
+
await this.setupLocalTracks();
|
|
13715
|
+
const { answerOptions } = this;
|
|
13716
|
+
logger$11.debug("[RTCPeerConnectionController] Creating inbound answer with options:", answerOptions);
|
|
13717
|
+
await this.createAnswer(answerOptions);
|
|
13718
|
+
}
|
|
13603
13719
|
async handleOfferReceived() {
|
|
13604
13720
|
if (!this.sdpInit) throw new DependencyError("SDP initialization parameters are not set");
|
|
13605
13721
|
this._isNegotiating$.next(true);
|
|
@@ -13674,37 +13790,29 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13674
13790
|
}
|
|
13675
13791
|
async setupLocalTracks() {
|
|
13676
13792
|
logger$11.debug("[RTCPeerConnectionController] Setting up local tracks/transceivers.");
|
|
13677
|
-
|
|
13678
|
-
if (
|
|
13679
|
-
|
|
13680
|
-
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
if (localStream) {
|
|
13685
|
-
if (this.transceiverController?.useAddStream ?? false) {
|
|
13686
|
-
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
13687
|
-
this.peerConnection?.addStream(localStream);
|
|
13688
|
-
if (!this.isNegotiating) {
|
|
13689
|
-
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
13690
|
-
this.negotiationNeeded$.next();
|
|
13691
|
-
}
|
|
13692
|
-
return;
|
|
13793
|
+
const localStream = this.localStream ?? await this.localStreamController.buildLocalStream();
|
|
13794
|
+
if (this.transceiverController?.useAddStream ?? false) {
|
|
13795
|
+
logger$11.warn("[RTCPeerConnectionController] Using deprecated addStream API to add local stream.");
|
|
13796
|
+
this.peerConnection?.addStream(localStream);
|
|
13797
|
+
if (!this.isNegotiating) {
|
|
13798
|
+
logger$11.debug("[RTCPeerConnectionController] Forcing negotiationneeded after local tracks setup.");
|
|
13799
|
+
this.negotiationNeeded$.next();
|
|
13693
13800
|
}
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
}
|
|
13801
|
+
return;
|
|
13802
|
+
}
|
|
13803
|
+
for (const kind of ["audio", "video"]) {
|
|
13804
|
+
const tracks = (kind === "audio" ? localStream.getAudioTracks() : localStream.getVideoTracks()).map((track, index) => ({
|
|
13805
|
+
index,
|
|
13806
|
+
track
|
|
13807
|
+
}));
|
|
13808
|
+
for (const { index, track } of tracks) {
|
|
13809
|
+
this.localStreamController.addTrackEndedListener(track);
|
|
13810
|
+
if (this.transceiverController?.useAddTransceivers ?? false) {
|
|
13811
|
+
const transceivers = (kind === "audio" ? this.transceiverController?.audioTransceivers : this.transceiverController?.videoTransceivers) ?? [];
|
|
13812
|
+
await this.transceiverController?.setupTransceiverSender(track, localStream, transceivers[index]);
|
|
13813
|
+
} else {
|
|
13814
|
+
logger$11.debug(`[RTCPeerConnectionController] Using addTrack for local ${kind} track:`, track.id);
|
|
13815
|
+
this.peerConnection?.addTrack(track, localStream);
|
|
13708
13816
|
}
|
|
13709
13817
|
}
|
|
13710
13818
|
}
|
|
@@ -13721,7 +13829,12 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13721
13829
|
if (!this.peerConnection) throw new DependencyError("RTCPeerConnection is not initialized");
|
|
13722
13830
|
this.peerConnection.ontrack = (event) => {
|
|
13723
13831
|
logger$11.debug("[RTCPeerConnectionController] Remote track received:", event.track.kind);
|
|
13724
|
-
this._remoteStream$.next(event.streams[0]);
|
|
13832
|
+
if (event.streams[0]) this._remoteStream$.next(event.streams[0]);
|
|
13833
|
+
else {
|
|
13834
|
+
const existingTracks = this._remoteStream$.value?.getTracks() ?? [];
|
|
13835
|
+
const newStream = new MediaStream([...existingTracks, event.track]);
|
|
13836
|
+
this._remoteStream$.next(newStream);
|
|
13837
|
+
}
|
|
13725
13838
|
};
|
|
13726
13839
|
await this.transceiverController?.setupRemoteTransceivers(this.type);
|
|
13727
13840
|
}
|
|
@@ -13820,7 +13933,7 @@ var RTCPeerConnectionController = class extends Destroyable {
|
|
|
13820
13933
|
});
|
|
13821
13934
|
}
|
|
13822
13935
|
get mediaDirections() {
|
|
13823
|
-
return this.transceiverController?.getMediaDirections() ?? {
|
|
13936
|
+
return this.transceiverController?.getMediaDirections() ?? this._remoteOfferMediaDirections ?? {
|
|
13824
13937
|
audio: "inactive",
|
|
13825
13938
|
video: "inactive"
|
|
13826
13939
|
};
|
|
@@ -13980,6 +14093,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
13980
14093
|
});
|
|
13981
14094
|
this.subscribeTo(this.vertoAnswer$, (event) => {
|
|
13982
14095
|
logger$10.debug("[WebRTCManager] Received Verto answer event:", event);
|
|
14096
|
+
this._signalingStatus$.next("connecting");
|
|
13983
14097
|
const { sdp, callID } = event;
|
|
13984
14098
|
this._rtcPeerConnectionsMap.get(callID)?.updateAnswerStatus({
|
|
13985
14099
|
status: "received",
|
|
@@ -14051,13 +14165,13 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14051
14165
|
if (response.error) {
|
|
14052
14166
|
const error = new JSONRPCError(response.error.code, response.error.message, response.error.data);
|
|
14053
14167
|
this.onError?.(error);
|
|
14054
|
-
|
|
14168
|
+
return response;
|
|
14055
14169
|
}
|
|
14056
14170
|
const innerResult = getValueFrom(response, "result.result");
|
|
14057
14171
|
if (innerResult?.error) {
|
|
14058
14172
|
const error = new JSONRPCError(innerResult.error.code, innerResult.error.message, innerResult.error.data);
|
|
14059
14173
|
this.onError?.(error);
|
|
14060
|
-
|
|
14174
|
+
return response;
|
|
14061
14175
|
}
|
|
14062
14176
|
return response;
|
|
14063
14177
|
}
|
|
@@ -14077,7 +14191,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14077
14191
|
}
|
|
14078
14192
|
} catch (error) {
|
|
14079
14193
|
logger$10.error(`[WebRTCManager] Error sending Verto ${vertoMethod}:`, error);
|
|
14080
|
-
|
|
14194
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
14081
14195
|
}
|
|
14082
14196
|
}
|
|
14083
14197
|
async processModifyResponse(response, rtcPeerConnController) {
|
|
@@ -14091,12 +14205,14 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14091
14205
|
});
|
|
14092
14206
|
} catch (error) {
|
|
14093
14207
|
logger$10.warn("[WebRTCManager] Error processing modify response:", error);
|
|
14094
|
-
|
|
14208
|
+
const modifyError = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
14209
|
+
this.onError?.(modifyError);
|
|
14095
14210
|
}
|
|
14096
14211
|
}
|
|
14097
14212
|
}
|
|
14098
14213
|
processInviteResponse(response, rtcPeerConnController) {
|
|
14099
14214
|
if (!response.error && getValueFrom(response, "result.result.result.message") === "CALL CREATED") {
|
|
14215
|
+
this._signalingStatus$.next("trying");
|
|
14100
14216
|
this._nodeId$.next(getValueFrom(response, "result.node_id") ?? null);
|
|
14101
14217
|
const memberId = getValueFrom(response, "result.result.result.memberID") ?? null;
|
|
14102
14218
|
const callId = getValueFrom(response, "result.result.result.callID") ?? null;
|
|
@@ -14151,6 +14267,36 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14151
14267
|
this.subscribeTo(rtcPeerConnController.errors$, (error) => {
|
|
14152
14268
|
this.onError?.(error);
|
|
14153
14269
|
});
|
|
14270
|
+
if (options.initOffer) this.handleInboundAnswer(rtcPeerConnController);
|
|
14271
|
+
}
|
|
14272
|
+
async handleInboundAnswer(rtcPeerConnController) {
|
|
14273
|
+
logger$10.debug("[WebRTCManager] Waiting for inbound call to be accepted or rejected");
|
|
14274
|
+
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);
|
|
14275
|
+
if (vertoByeOrAccepted === null) {
|
|
14276
|
+
logger$10.debug("[WebRTCManager] Inbound answer handler aborted (destroyed).");
|
|
14277
|
+
return;
|
|
14278
|
+
}
|
|
14279
|
+
if (isVertoByeMessage(vertoByeOrAccepted)) {
|
|
14280
|
+
logger$10.info("[WebRTCManager] Inbound call ended by remote before answer.");
|
|
14281
|
+
this.callSession?.destroy();
|
|
14282
|
+
} else if (!vertoByeOrAccepted) {
|
|
14283
|
+
logger$10.info("[WebRTCManager] Inbound call rejected by user.");
|
|
14284
|
+
try {
|
|
14285
|
+
await this.bye("USER_BUSY");
|
|
14286
|
+
} finally {
|
|
14287
|
+
this._signalingStatus$.next("disconnected");
|
|
14288
|
+
this.callSession?.destroy();
|
|
14289
|
+
}
|
|
14290
|
+
} else {
|
|
14291
|
+
logger$10.debug("[WebRTCManager] Inbound call accepted, creating SDP answer");
|
|
14292
|
+
const answerOptions = this.webRtcCallSession.answerMediaOptions;
|
|
14293
|
+
try {
|
|
14294
|
+
await rtcPeerConnController.acceptInbound(answerOptions);
|
|
14295
|
+
} catch (error) {
|
|
14296
|
+
logger$10.error("[WebRTCManager] Error creating inbound answer:", error);
|
|
14297
|
+
this.onError?.(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
14298
|
+
}
|
|
14299
|
+
}
|
|
14154
14300
|
}
|
|
14155
14301
|
setupVertoAttachHandler() {
|
|
14156
14302
|
this.subscribeTo(this.vertoAttach$, async (vertoAttach) => {
|
|
@@ -14168,7 +14314,7 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14168
14314
|
});
|
|
14169
14315
|
}
|
|
14170
14316
|
initObservables(rtcPeerConnController) {
|
|
14171
|
-
this.mediaDirections$ = rtcPeerConnController.connectionState$.pipe((0, import_cjs$10.filter)((state) => state === "connected"), (0, import_cjs$10.
|
|
14317
|
+
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$));
|
|
14172
14318
|
this.localStream$ = rtcPeerConnController.localStream$.pipe(filterNull(), (0, import_cjs$10.takeUntil)(this.destroyed$));
|
|
14173
14319
|
this.remoteStream$ = rtcPeerConnController.remoteStream$.pipe(filterNull(), (0, import_cjs$10.takeUntil)(this.destroyed$));
|
|
14174
14320
|
}
|
|
@@ -14184,7 +14330,6 @@ var WebRTCVertoManager = class extends VertoManager {
|
|
|
14184
14330
|
});
|
|
14185
14331
|
this.sendLocalDescriptionOnceAccepted(vertoMessageRequest, rtcPeerConnController);
|
|
14186
14332
|
} else if (initial) {
|
|
14187
|
-
this._signalingStatus$.next("trying");
|
|
14188
14333
|
const vertoMessageRequest = VertoInvite({
|
|
14189
14334
|
dialogParams,
|
|
14190
14335
|
sdp
|
|
@@ -14491,8 +14636,8 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14491
14636
|
this.clientSession = clientSession;
|
|
14492
14637
|
this.options = options;
|
|
14493
14638
|
this.address = address;
|
|
14494
|
-
this.
|
|
14495
|
-
this.
|
|
14639
|
+
this._errors$ = this.createReplaySubject(1);
|
|
14640
|
+
this._lastMergedStatus = "new";
|
|
14496
14641
|
this._answered$ = this.createReplaySubject();
|
|
14497
14642
|
this._holdState = false;
|
|
14498
14643
|
this._userVariables$ = this.createBehaviorSubject({ ...PreferencesContainer.instance.userVariables });
|
|
@@ -14513,8 +14658,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14513
14658
|
const managers = initialization.initializeManagers(this);
|
|
14514
14659
|
this.vertoManager = managers.vertoManager;
|
|
14515
14660
|
this.callEventsManager = managers.callEventsManager;
|
|
14516
|
-
if (options.initOffer)
|
|
14517
|
-
|
|
14661
|
+
if (options.initOffer) {
|
|
14662
|
+
this._status$ = this.createBehaviorSubject("ringing");
|
|
14663
|
+
this._lastMergedStatus = "ringing";
|
|
14664
|
+
} else this._status$ = this.createBehaviorSubject("new");
|
|
14518
14665
|
const { deviceController } = initialization;
|
|
14519
14666
|
this.participantFactory = new ParticipantFactory(this.executeMethod.bind(this), this.vertoManager, deviceController);
|
|
14520
14667
|
}
|
|
@@ -14522,9 +14669,17 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14522
14669
|
get errors$() {
|
|
14523
14670
|
return this._errors$.asObservable();
|
|
14524
14671
|
}
|
|
14525
|
-
/**
|
|
14526
|
-
|
|
14527
|
-
|
|
14672
|
+
/**
|
|
14673
|
+
* @internal Push an error to the call's error stream.
|
|
14674
|
+
* Fatal errors automatically transition the call to `'failed'` and destroy it.
|
|
14675
|
+
*/
|
|
14676
|
+
emitError(callError) {
|
|
14677
|
+
if (this._status$.value === "destroyed" || this._status$.value === "failed") return;
|
|
14678
|
+
this._errors$.next(callError);
|
|
14679
|
+
if (callError.fatal) {
|
|
14680
|
+
this._status$.next("failed");
|
|
14681
|
+
this.destroy();
|
|
14682
|
+
}
|
|
14528
14683
|
}
|
|
14529
14684
|
/** Whether this call is `'inbound'` or `'outbound'`. */
|
|
14530
14685
|
get direction() {
|
|
@@ -14564,7 +14719,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14564
14719
|
}
|
|
14565
14720
|
/** Current snapshot of all participants in the call. */
|
|
14566
14721
|
get participants() {
|
|
14567
|
-
return
|
|
14722
|
+
return this.callEventsManager.participants;
|
|
14568
14723
|
}
|
|
14569
14724
|
/** The local participant, or `null` if not yet joined. */
|
|
14570
14725
|
get self() {
|
|
@@ -14573,7 +14728,6 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14573
14728
|
async toggleLock() {
|
|
14574
14729
|
const method = this.locked ? "call.unlock" : "call.lock";
|
|
14575
14730
|
await this.executeMethod(this.selfId ?? "", method, {});
|
|
14576
|
-
throw new UnimplementedError();
|
|
14577
14731
|
}
|
|
14578
14732
|
async toggleHold() {
|
|
14579
14733
|
if (this._holdState) await this.vertoManager.unhold();
|
|
@@ -14615,25 +14769,31 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14615
14769
|
}
|
|
14616
14770
|
}
|
|
14617
14771
|
buildMethodParams(target, args) {
|
|
14618
|
-
const
|
|
14619
|
-
node_id: this.nodeId,
|
|
14620
|
-
call_id: this.id
|
|
14772
|
+
const self = {
|
|
14773
|
+
node_id: this.nodeId ?? "",
|
|
14774
|
+
call_id: this.id,
|
|
14775
|
+
member_id: this.vertoManager.selfId ?? ""
|
|
14776
|
+
};
|
|
14777
|
+
if (typeof target === "object") return {
|
|
14778
|
+
...args,
|
|
14779
|
+
self,
|
|
14780
|
+
targets: [target]
|
|
14621
14781
|
};
|
|
14622
14782
|
return {
|
|
14623
14783
|
...args,
|
|
14624
|
-
self
|
|
14625
|
-
...reference,
|
|
14626
|
-
member_id: this.vertoManager.selfId
|
|
14627
|
-
},
|
|
14784
|
+
self,
|
|
14628
14785
|
target: {
|
|
14629
|
-
|
|
14786
|
+
node_id: this.nodeId ?? "",
|
|
14787
|
+
call_id: this.id,
|
|
14630
14788
|
member_id: target
|
|
14631
14789
|
}
|
|
14632
14790
|
};
|
|
14633
14791
|
}
|
|
14634
14792
|
/** Observable of the current call status (e.g. `'ringing'`, `'connected'`). */
|
|
14635
14793
|
get status$() {
|
|
14636
|
-
return this.cachedObservable("status$", () => (0, import_cjs$9.merge)(this._status$.asObservable(), this.vertoManager.signalingStatus$))
|
|
14794
|
+
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) => {
|
|
14795
|
+
this._lastMergedStatus = status;
|
|
14796
|
+
})));
|
|
14637
14797
|
}
|
|
14638
14798
|
/** Observable of the participants list, emits on join/leave/update. */
|
|
14639
14799
|
get participants$() {
|
|
@@ -14673,7 +14833,7 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14673
14833
|
}
|
|
14674
14834
|
/** Current call status. */
|
|
14675
14835
|
get status() {
|
|
14676
|
-
return this.
|
|
14836
|
+
return this._lastMergedStatus;
|
|
14677
14837
|
}
|
|
14678
14838
|
/** Whether the call is currently being recorded. */
|
|
14679
14839
|
get recording() {
|
|
@@ -14850,10 +15010,15 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14850
15010
|
async sendDigits(dtmf) {
|
|
14851
15011
|
return this.vertoManager.sendDigits(dtmf);
|
|
14852
15012
|
}
|
|
14853
|
-
/** Accepts an inbound call. */
|
|
14854
|
-
answer() {
|
|
15013
|
+
/** Accepts an inbound call, optionally overriding media options for the answer. */
|
|
15014
|
+
answer(options) {
|
|
15015
|
+
this._answerMediaOptions = options;
|
|
14855
15016
|
this._answered$.next(true);
|
|
14856
15017
|
}
|
|
15018
|
+
/** Media options provided when answering. Used internally by the VertoManager. */
|
|
15019
|
+
get answerMediaOptions() {
|
|
15020
|
+
return this._answerMediaOptions;
|
|
15021
|
+
}
|
|
14857
15022
|
/** Rejects an inbound call. */
|
|
14858
15023
|
reject() {
|
|
14859
15024
|
this._answered$.next(false);
|
|
@@ -14881,10 +15046,10 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14881
15046
|
}
|
|
14882
15047
|
/** Destroys the call, releasing all resources and subscriptions. */
|
|
14883
15048
|
destroy() {
|
|
15049
|
+
if (this._status$.value === "destroyed") return;
|
|
14884
15050
|
this._status$.next("destroyed");
|
|
14885
15051
|
this.vertoManager.destroy();
|
|
14886
15052
|
this.callEventsManager.destroy();
|
|
14887
|
-
this.participantsMap.clear();
|
|
14888
15053
|
super.destroy();
|
|
14889
15054
|
}
|
|
14890
15055
|
};
|
|
@@ -14892,6 +15057,23 @@ var WebRTCCall = class extends Destroyable {
|
|
|
14892
15057
|
//#endregion
|
|
14893
15058
|
//#region src/managers/CallFactory.ts
|
|
14894
15059
|
/**
|
|
15060
|
+
* Infers the semantic error category from a raw Error thrown by VertoManager
|
|
15061
|
+
* or an RTCPeerConnection layer.
|
|
15062
|
+
*/
|
|
15063
|
+
function inferCallErrorKind(error) {
|
|
15064
|
+
if (error instanceof RPCTimeoutError) return "timeout";
|
|
15065
|
+
if (error instanceof JSONRPCError) return "signaling";
|
|
15066
|
+
if (error instanceof MediaTrackError) return "media";
|
|
15067
|
+
if (error instanceof WebSocketConnectionError || error instanceof TransportConnectionError) return "network";
|
|
15068
|
+
return "internal";
|
|
15069
|
+
}
|
|
15070
|
+
/** Determines whether an error should be fatal (destroy the call). */
|
|
15071
|
+
function isFatalError(error) {
|
|
15072
|
+
if (error instanceof VertoPongError) return false;
|
|
15073
|
+
if (error instanceof MediaTrackError) return false;
|
|
15074
|
+
return true;
|
|
15075
|
+
}
|
|
15076
|
+
/**
|
|
14895
15077
|
* Factory for creating WebRTCCall instances with proper manager wiring.
|
|
14896
15078
|
* Eliminates circular dependencies by centralizing Call and Manager creation.
|
|
14897
15079
|
*/
|
|
@@ -14912,7 +15094,13 @@ var CallFactory = class {
|
|
|
14912
15094
|
vertoManager: new WebRTCVertoManager(callInstance, this.attachManager, this.deviceController, this.webRTCApiProvider, {
|
|
14913
15095
|
nodeId: options.nodeId,
|
|
14914
15096
|
onError: (error) => {
|
|
14915
|
-
|
|
15097
|
+
const callError = {
|
|
15098
|
+
kind: inferCallErrorKind(error),
|
|
15099
|
+
fatal: isFatalError(error),
|
|
15100
|
+
error,
|
|
15101
|
+
callId: callInstance.id
|
|
15102
|
+
};
|
|
15103
|
+
callInstance.emitError(callError);
|
|
14916
15104
|
}
|
|
14917
15105
|
}),
|
|
14918
15106
|
callEventsManager: new CallEventsManager(callInstance)
|
|
@@ -15292,9 +15480,15 @@ var PendingRPC = class PendingRPC {
|
|
|
15292
15480
|
return () => signal.removeEventListener("abort", abortHandler);
|
|
15293
15481
|
}) : import_cjs$6.NEVER).subscribe({
|
|
15294
15482
|
next: (response) => {
|
|
15295
|
-
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
15296
15483
|
isSettled = true;
|
|
15297
|
-
|
|
15484
|
+
if (response.error) {
|
|
15485
|
+
const rpcError = new RPCError(response.error.code, request.id, response.error.message, response.error.data);
|
|
15486
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Rejecting promise with RPC error:`, rpcError);
|
|
15487
|
+
reject(rpcError);
|
|
15488
|
+
} else {
|
|
15489
|
+
logger$7.debug(`[PendingRPC(${this.id}) request:${request.id}] Resolving promise with response:`, response);
|
|
15490
|
+
resolve(response);
|
|
15491
|
+
}
|
|
15298
15492
|
subscription.unsubscribe();
|
|
15299
15493
|
},
|
|
15300
15494
|
error: (error) => {
|
|
@@ -15351,7 +15545,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15351
15545
|
revision: 0
|
|
15352
15546
|
};
|
|
15353
15547
|
this._authorization$ = this.createBehaviorSubject(void 0);
|
|
15354
|
-
this._errors$ = this.
|
|
15548
|
+
this._errors$ = this.createReplaySubject(1);
|
|
15355
15549
|
this._authenticated$ = this.createBehaviorSubject(false);
|
|
15356
15550
|
this._subscriberInfo$ = this.createBehaviorSubject(null);
|
|
15357
15551
|
this._calls$ = this.createBehaviorSubject({});
|
|
@@ -15621,12 +15815,13 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15621
15815
|
}
|
|
15622
15816
|
async createOutboundCall(destination, options = {}) {
|
|
15623
15817
|
const destinationURI = destination instanceof Address ? destination.defaultChannel : destination;
|
|
15818
|
+
let callSession;
|
|
15624
15819
|
try {
|
|
15625
|
-
|
|
15820
|
+
callSession = await this.createCall({
|
|
15626
15821
|
to: destinationURI,
|
|
15627
15822
|
...options
|
|
15628
15823
|
});
|
|
15629
|
-
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)));
|
|
15824
|
+
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)))));
|
|
15630
15825
|
this._calls$.next({
|
|
15631
15826
|
[`${callSession.id}`]: callSession,
|
|
15632
15827
|
...this._calls$.value
|
|
@@ -15634,7 +15829,8 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15634
15829
|
return callSession;
|
|
15635
15830
|
} catch (error) {
|
|
15636
15831
|
logger$6.error("[Session] Error creating outbound call:", error);
|
|
15637
|
-
|
|
15832
|
+
callSession?.destroy();
|
|
15833
|
+
const callError = new CallCreateError(error instanceof import_cjs$5.TimeoutError ? "Call create timeout" : "Call creation failed", error, "outbound");
|
|
15638
15834
|
this._errors$.next(callError);
|
|
15639
15835
|
throw callError;
|
|
15640
15836
|
}
|
|
@@ -15660,7 +15856,7 @@ var ClientSessionManager = class extends Destroyable {
|
|
|
15660
15856
|
return callSession;
|
|
15661
15857
|
} catch (error) {
|
|
15662
15858
|
logger$6.error("[Session] Error creating call session:", error);
|
|
15663
|
-
throw new CallCreateError("Call create error", error);
|
|
15859
|
+
throw new CallCreateError("Call create error", error, options.initOffer ? "inbound" : "outbound");
|
|
15664
15860
|
}
|
|
15665
15861
|
}
|
|
15666
15862
|
destroy() {
|
|
@@ -15909,7 +16105,7 @@ var WebSocketController = class WebSocketController extends Destroyable {
|
|
|
15909
16105
|
this.shouldReconnect = false;
|
|
15910
16106
|
this._status$ = this.createBehaviorSubject("disconnected");
|
|
15911
16107
|
this._incomingMessages$ = this.createSubject();
|
|
15912
|
-
this._errors$ = this.
|
|
16108
|
+
this._errors$ = this.createReplaySubject(1);
|
|
15913
16109
|
this.reconnectDelayMin = options.reconnectDelayMin ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MIN_MS;
|
|
15914
16110
|
this.reconnectDelayMax = options.reconnectDelayMax ?? WebSocketController.DEFAULT_RECONNECT_DELAY_MAX_MS;
|
|
15915
16111
|
this.connectionTimeout = options.connectionTimeout ?? WebSocketController.DEFAULT_CONNECTION_TIMEOUT_MS;
|
|
@@ -16236,7 +16432,8 @@ const buildOptionsFromDestination = (destination) => {
|
|
|
16236
16432
|
const channel = new URLSearchParams(queryString).get("channel");
|
|
16237
16433
|
if (channel === "video") return {
|
|
16238
16434
|
audio: true,
|
|
16239
|
-
video: true
|
|
16435
|
+
video: true,
|
|
16436
|
+
receiveVideo: true
|
|
16240
16437
|
};
|
|
16241
16438
|
else if (channel === "audio") return {
|
|
16242
16439
|
audio: true,
|
|
@@ -16266,7 +16463,7 @@ var SignalWire = class extends Destroyable {
|
|
|
16266
16463
|
this._directory$ = this.createBehaviorSubject(void 0);
|
|
16267
16464
|
this._isConnected$ = this.createBehaviorSubject(false);
|
|
16268
16465
|
this._isRegistered$ = this.createBehaviorSubject(false);
|
|
16269
|
-
this._errors$ = this.
|
|
16466
|
+
this._errors$ = this.createReplaySubject(1);
|
|
16270
16467
|
this._options = {};
|
|
16271
16468
|
this._deps = new DependencyContainer();
|
|
16272
16469
|
this._options = {
|
|
@@ -16343,7 +16540,12 @@ var SignalWire = class extends Destroyable {
|
|
|
16343
16540
|
this._subscriber$.next(new Subscriber(this._deps.http));
|
|
16344
16541
|
if (!this._options.skipConnection) await this.connect();
|
|
16345
16542
|
if (!this._options.reconnectAttachedCalls && this._attachManager) await this._attachManager.flush();
|
|
16346
|
-
if (!this._options.skipRegister)
|
|
16543
|
+
if (!this._options.skipRegister) try {
|
|
16544
|
+
await this.register();
|
|
16545
|
+
} catch (error) {
|
|
16546
|
+
logger$1.error("[SignalWire] Registration failed:", error);
|
|
16547
|
+
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16548
|
+
}
|
|
16347
16549
|
this.handleAttachments();
|
|
16348
16550
|
}
|
|
16349
16551
|
async handleAttachments() {
|
|
@@ -16506,8 +16708,22 @@ var SignalWire = class extends Destroyable {
|
|
|
16506
16708
|
}));
|
|
16507
16709
|
this._isRegistered$.next(true);
|
|
16508
16710
|
} catch (error) {
|
|
16509
|
-
logger$1.
|
|
16711
|
+
logger$1.debug("[SignalWire] Failed to register subscriber, trying reauthentication...");
|
|
16712
|
+
if (this._deps.credential.token) this._clientSession.reauthenticate(this._deps.credential.token).then(async () => {
|
|
16713
|
+
logger$1.debug("[SignalWire] Reauthentication successful, retrying register()");
|
|
16714
|
+
await this._transport.execute(RPCExecute({
|
|
16715
|
+
method: "subscriber.online",
|
|
16716
|
+
params: {}
|
|
16717
|
+
}));
|
|
16718
|
+
this._isRegistered$.next(true);
|
|
16719
|
+
}).catch((reauthError) => {
|
|
16720
|
+
logger$1.error("[SignalWire] Reauthentication failed during register():", reauthError);
|
|
16721
|
+
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 }) });
|
|
16722
|
+
this._errors$.next(registerError);
|
|
16723
|
+
throw registerError;
|
|
16724
|
+
});
|
|
16510
16725
|
this._errors$.next(error instanceof Error ? error : new Error(String(error), { cause: error }));
|
|
16726
|
+
throw error;
|
|
16511
16727
|
}
|
|
16512
16728
|
}
|
|
16513
16729
|
/** Unregisters the subscriber, going offline for inbound calls. */
|