@stream-io/video-client 1.0.0 → 1.0.2
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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +332 -48
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +332 -48
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +332 -48
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/InputMediaDeviceManager.d.ts +4 -5
- package/dist/src/devices/InputMediaDeviceManagerState.d.ts +14 -0
- package/dist/src/events/participant.d.ts +5 -1
- package/dist/src/gen/video/sfu/event/events.d.ts +71 -1
- package/dist/src/gen/video/sfu/models/models.d.ts +70 -0
- package/package.json +1 -1
- package/src/Call.ts +2 -12
- package/src/devices/CameraManager.ts +2 -2
- package/src/devices/InputMediaDeviceManager.ts +58 -36
- package/src/devices/InputMediaDeviceManagerState.ts +25 -0
- package/src/events/__tests__/participant.test.ts +28 -1
- package/src/events/callEventHandlers.ts +2 -0
- package/src/events/participant.ts +12 -0
- package/src/gen/video/sfu/event/events.ts +284 -0
- package/src/gen/video/sfu/models/models.ts +70 -0
- package/src/rtc/Dispatcher.ts +2 -0
- package/src/store/CallState.ts +3 -0
- package/src/store/__tests__/CallState.test.ts +9 -1
package/dist/index.cjs.js
CHANGED
|
@@ -954,6 +954,9 @@ var TrackUnpublishReason;
|
|
|
954
954
|
TrackUnpublishReason[TrackUnpublishReason["MODERATION"] = 3] = "MODERATION";
|
|
955
955
|
})(TrackUnpublishReason || (TrackUnpublishReason = {}));
|
|
956
956
|
/**
|
|
957
|
+
* GoAwayReason represents the reason for the SFU to
|
|
958
|
+
* disconnect the client.
|
|
959
|
+
*
|
|
957
960
|
* @generated from protobuf enum stream.video.sfu.models.GoAwayReason
|
|
958
961
|
*/
|
|
959
962
|
var GoAwayReason;
|
|
@@ -971,6 +974,75 @@ var GoAwayReason;
|
|
|
971
974
|
*/
|
|
972
975
|
GoAwayReason[GoAwayReason["REBALANCE"] = 2] = "REBALANCE";
|
|
973
976
|
})(GoAwayReason || (GoAwayReason = {}));
|
|
977
|
+
/**
|
|
978
|
+
* CallEndedReason represents the reason for the call to end.
|
|
979
|
+
*
|
|
980
|
+
* @generated from protobuf enum stream.video.sfu.models.CallEndedReason
|
|
981
|
+
*/
|
|
982
|
+
var CallEndedReason;
|
|
983
|
+
(function (CallEndedReason) {
|
|
984
|
+
/**
|
|
985
|
+
* @generated from protobuf enum value: CALL_ENDED_REASON_UNSPECIFIED = 0;
|
|
986
|
+
*/
|
|
987
|
+
CallEndedReason[CallEndedReason["UNSPECIFIED"] = 0] = "UNSPECIFIED";
|
|
988
|
+
/**
|
|
989
|
+
* @generated from protobuf enum value: CALL_ENDED_REASON_ENDED = 1;
|
|
990
|
+
*/
|
|
991
|
+
CallEndedReason[CallEndedReason["ENDED"] = 1] = "ENDED";
|
|
992
|
+
/**
|
|
993
|
+
* @generated from protobuf enum value: CALL_ENDED_REASON_LIVE_ENDED = 2;
|
|
994
|
+
*/
|
|
995
|
+
CallEndedReason[CallEndedReason["LIVE_ENDED"] = 2] = "LIVE_ENDED";
|
|
996
|
+
/**
|
|
997
|
+
* @generated from protobuf enum value: CALL_ENDED_REASON_KICKED = 3;
|
|
998
|
+
*/
|
|
999
|
+
CallEndedReason[CallEndedReason["KICKED"] = 3] = "KICKED";
|
|
1000
|
+
})(CallEndedReason || (CallEndedReason = {}));
|
|
1001
|
+
/**
|
|
1002
|
+
* WebsocketReconnectStrategy defines the ws strategies available for handling reconnections.
|
|
1003
|
+
*
|
|
1004
|
+
* @generated from protobuf enum stream.video.sfu.models.WebsocketReconnectStrategy
|
|
1005
|
+
*/
|
|
1006
|
+
var WebsocketReconnectStrategy;
|
|
1007
|
+
(function (WebsocketReconnectStrategy) {
|
|
1008
|
+
/**
|
|
1009
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_UNSPECIFIED = 0;
|
|
1010
|
+
*/
|
|
1011
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["UNSPECIFIED"] = 0] = "UNSPECIFIED";
|
|
1012
|
+
/**
|
|
1013
|
+
* Sent after reaching the maximum reconnection attempts, leading to permanent disconnect.
|
|
1014
|
+
*
|
|
1015
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_DISCONNECT = 1;
|
|
1016
|
+
*/
|
|
1017
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["DISCONNECT"] = 1] = "DISCONNECT";
|
|
1018
|
+
/**
|
|
1019
|
+
* SDK should maintaining existing publisher/subscriber pc instances
|
|
1020
|
+
* and establish a new WebSocket connection.
|
|
1021
|
+
*
|
|
1022
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_FAST = 2;
|
|
1023
|
+
*/
|
|
1024
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["FAST"] = 2] = "FAST";
|
|
1025
|
+
/**
|
|
1026
|
+
* SDK should drop existing pc instances and creates a fresh WebSocket connection,
|
|
1027
|
+
* ensuring a clean state for the reconnection.
|
|
1028
|
+
*
|
|
1029
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_CLEAN = 3;
|
|
1030
|
+
*/
|
|
1031
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["CLEAN"] = 3] = "CLEAN";
|
|
1032
|
+
/**
|
|
1033
|
+
* SDK should obtain new credentials from the coordinator, drops existing pc instances, and initializes
|
|
1034
|
+
* a completely new WebSocket connection, ensuring a comprehensive reset.
|
|
1035
|
+
*
|
|
1036
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_FULL = 4;
|
|
1037
|
+
*/
|
|
1038
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["FULL"] = 4] = "FULL";
|
|
1039
|
+
/**
|
|
1040
|
+
* SDK should migrate to a new SFU instance
|
|
1041
|
+
*
|
|
1042
|
+
* @generated from protobuf enum value: WEBSOCKET_RECONNECT_STRATEGY_MIGRATE = 5;
|
|
1043
|
+
*/
|
|
1044
|
+
WebsocketReconnectStrategy[WebsocketReconnectStrategy["MIGRATE"] = 5] = "MIGRATE";
|
|
1045
|
+
})(WebsocketReconnectStrategy || (WebsocketReconnectStrategy = {}));
|
|
974
1046
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
975
1047
|
class CallState$Type extends runtime.MessageType {
|
|
976
1048
|
constructor() {
|
|
@@ -2433,6 +2505,7 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
2433
2505
|
__proto__: null,
|
|
2434
2506
|
Browser: Browser,
|
|
2435
2507
|
Call: Call$1,
|
|
2508
|
+
get CallEndedReason () { return CallEndedReason; },
|
|
2436
2509
|
CallGrants: CallGrants,
|
|
2437
2510
|
CallState: CallState$1,
|
|
2438
2511
|
ClientDetails: ClientDetails,
|
|
@@ -2456,7 +2529,8 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
2456
2529
|
get TrackUnpublishReason () { return TrackUnpublishReason; },
|
|
2457
2530
|
VideoDimension: VideoDimension,
|
|
2458
2531
|
VideoLayer: VideoLayer,
|
|
2459
|
-
get VideoQuality () { return VideoQuality; }
|
|
2532
|
+
get VideoQuality () { return VideoQuality; },
|
|
2533
|
+
get WebsocketReconnectStrategy () { return WebsocketReconnectStrategy; }
|
|
2460
2534
|
});
|
|
2461
2535
|
|
|
2462
2536
|
/* eslint-disable */
|
|
@@ -3865,6 +3939,20 @@ class SfuEvent$Type extends runtime.MessageType {
|
|
|
3865
3939
|
oneof: 'eventPayload',
|
|
3866
3940
|
T: () => PinsChanged,
|
|
3867
3941
|
},
|
|
3942
|
+
{
|
|
3943
|
+
no: 23,
|
|
3944
|
+
name: 'call_ended',
|
|
3945
|
+
kind: 'message',
|
|
3946
|
+
oneof: 'eventPayload',
|
|
3947
|
+
T: () => CallEnded,
|
|
3948
|
+
},
|
|
3949
|
+
{
|
|
3950
|
+
no: 24,
|
|
3951
|
+
name: 'participant_updated',
|
|
3952
|
+
kind: 'message',
|
|
3953
|
+
oneof: 'eventPayload',
|
|
3954
|
+
T: () => ParticipantUpdated,
|
|
3955
|
+
},
|
|
3868
3956
|
]);
|
|
3869
3957
|
}
|
|
3870
3958
|
create(value) {
|
|
@@ -3987,6 +4075,18 @@ class SfuEvent$Type extends runtime.MessageType {
|
|
|
3987
4075
|
pinsUpdated: PinsChanged.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.pinsUpdated),
|
|
3988
4076
|
};
|
|
3989
4077
|
break;
|
|
4078
|
+
case /* stream.video.sfu.event.CallEnded call_ended */ 23:
|
|
4079
|
+
message.eventPayload = {
|
|
4080
|
+
oneofKind: 'callEnded',
|
|
4081
|
+
callEnded: CallEnded.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.callEnded),
|
|
4082
|
+
};
|
|
4083
|
+
break;
|
|
4084
|
+
case /* stream.video.sfu.event.ParticipantUpdated participant_updated */ 24:
|
|
4085
|
+
message.eventPayload = {
|
|
4086
|
+
oneofKind: 'participantUpdated',
|
|
4087
|
+
participantUpdated: ParticipantUpdated.internalBinaryRead(reader, reader.uint32(), options, message.eventPayload.participantUpdated),
|
|
4088
|
+
};
|
|
4089
|
+
break;
|
|
3990
4090
|
default:
|
|
3991
4091
|
let u = options.readUnknownField;
|
|
3992
4092
|
if (u === 'throw')
|
|
@@ -4053,6 +4153,12 @@ class SfuEvent$Type extends runtime.MessageType {
|
|
|
4053
4153
|
/* stream.video.sfu.event.PinsChanged pins_updated = 22; */
|
|
4054
4154
|
if (message.eventPayload.oneofKind === 'pinsUpdated')
|
|
4055
4155
|
PinsChanged.internalBinaryWrite(message.eventPayload.pinsUpdated, writer.tag(22, runtime.WireType.LengthDelimited).fork(), options).join();
|
|
4156
|
+
/* stream.video.sfu.event.CallEnded call_ended = 23; */
|
|
4157
|
+
if (message.eventPayload.oneofKind === 'callEnded')
|
|
4158
|
+
CallEnded.internalBinaryWrite(message.eventPayload.callEnded, writer.tag(23, runtime.WireType.LengthDelimited).fork(), options).join();
|
|
4159
|
+
/* stream.video.sfu.event.ParticipantUpdated participant_updated = 24; */
|
|
4160
|
+
if (message.eventPayload.oneofKind === 'participantUpdated')
|
|
4161
|
+
ParticipantUpdated.internalBinaryWrite(message.eventPayload.participantUpdated, writer.tag(24, runtime.WireType.LengthDelimited).fork(), options).join();
|
|
4056
4162
|
let u = options.writeUnknownFields;
|
|
4057
4163
|
if (u !== false)
|
|
4058
4164
|
(u == true ? runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -4121,10 +4227,21 @@ class Error$Type extends runtime.MessageType {
|
|
|
4121
4227
|
constructor() {
|
|
4122
4228
|
super('stream.video.sfu.event.Error', [
|
|
4123
4229
|
{ no: 4, name: 'error', kind: 'message', T: () => Error$2 },
|
|
4230
|
+
{
|
|
4231
|
+
no: 5,
|
|
4232
|
+
name: 'reconnect_strategy',
|
|
4233
|
+
kind: 'enum',
|
|
4234
|
+
T: () => [
|
|
4235
|
+
'stream.video.sfu.models.WebsocketReconnectStrategy',
|
|
4236
|
+
WebsocketReconnectStrategy,
|
|
4237
|
+
'WEBSOCKET_RECONNECT_STRATEGY_',
|
|
4238
|
+
],
|
|
4239
|
+
},
|
|
4124
4240
|
]);
|
|
4125
4241
|
}
|
|
4126
4242
|
create(value) {
|
|
4127
4243
|
const message = globalThis.Object.create(this.messagePrototype);
|
|
4244
|
+
message.reconnectStrategy = 0;
|
|
4128
4245
|
if (value !== undefined)
|
|
4129
4246
|
runtime.reflectionMergePartial(this, message, value);
|
|
4130
4247
|
return message;
|
|
@@ -4137,6 +4254,9 @@ class Error$Type extends runtime.MessageType {
|
|
|
4137
4254
|
case /* stream.video.sfu.models.Error error */ 4:
|
|
4138
4255
|
message.error = Error$2.internalBinaryRead(reader, reader.uint32(), options, message.error);
|
|
4139
4256
|
break;
|
|
4257
|
+
case /* stream.video.sfu.models.WebsocketReconnectStrategy reconnect_strategy */ 5:
|
|
4258
|
+
message.reconnectStrategy = reader.int32();
|
|
4259
|
+
break;
|
|
4140
4260
|
default:
|
|
4141
4261
|
let u = options.readUnknownField;
|
|
4142
4262
|
if (u === 'throw')
|
|
@@ -4152,6 +4272,9 @@ class Error$Type extends runtime.MessageType {
|
|
|
4152
4272
|
/* stream.video.sfu.models.Error error = 4; */
|
|
4153
4273
|
if (message.error)
|
|
4154
4274
|
Error$2.internalBinaryWrite(message.error, writer.tag(4, runtime.WireType.LengthDelimited).fork(), options).join();
|
|
4275
|
+
/* stream.video.sfu.models.WebsocketReconnectStrategy reconnect_strategy = 5; */
|
|
4276
|
+
if (message.reconnectStrategy !== 0)
|
|
4277
|
+
writer.tag(5, runtime.WireType.Varint).int32(message.reconnectStrategy);
|
|
4155
4278
|
let u = options.writeUnknownFields;
|
|
4156
4279
|
if (u !== false)
|
|
4157
4280
|
(u == true ? runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
@@ -4945,6 +5068,60 @@ class ParticipantLeft$Type extends runtime.MessageType {
|
|
|
4945
5068
|
*/
|
|
4946
5069
|
const ParticipantLeft = new ParticipantLeft$Type();
|
|
4947
5070
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
5071
|
+
class ParticipantUpdated$Type extends runtime.MessageType {
|
|
5072
|
+
constructor() {
|
|
5073
|
+
super('stream.video.sfu.event.ParticipantUpdated', [
|
|
5074
|
+
{ no: 1, name: 'call_cid', kind: 'scalar', T: 9 /*ScalarType.STRING*/ },
|
|
5075
|
+
{ no: 2, name: 'participant', kind: 'message', T: () => Participant },
|
|
5076
|
+
]);
|
|
5077
|
+
}
|
|
5078
|
+
create(value) {
|
|
5079
|
+
const message = globalThis.Object.create(this.messagePrototype);
|
|
5080
|
+
message.callCid = '';
|
|
5081
|
+
if (value !== undefined)
|
|
5082
|
+
runtime.reflectionMergePartial(this, message, value);
|
|
5083
|
+
return message;
|
|
5084
|
+
}
|
|
5085
|
+
internalBinaryRead(reader, length, options, target) {
|
|
5086
|
+
let message = target ?? this.create(), end = reader.pos + length;
|
|
5087
|
+
while (reader.pos < end) {
|
|
5088
|
+
let [fieldNo, wireType] = reader.tag();
|
|
5089
|
+
switch (fieldNo) {
|
|
5090
|
+
case /* string call_cid */ 1:
|
|
5091
|
+
message.callCid = reader.string();
|
|
5092
|
+
break;
|
|
5093
|
+
case /* stream.video.sfu.models.Participant participant */ 2:
|
|
5094
|
+
message.participant = Participant.internalBinaryRead(reader, reader.uint32(), options, message.participant);
|
|
5095
|
+
break;
|
|
5096
|
+
default:
|
|
5097
|
+
let u = options.readUnknownField;
|
|
5098
|
+
if (u === 'throw')
|
|
5099
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
5100
|
+
let d = reader.skip(wireType);
|
|
5101
|
+
if (u !== false)
|
|
5102
|
+
(u === true ? runtime.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
return message;
|
|
5106
|
+
}
|
|
5107
|
+
internalBinaryWrite(message, writer, options) {
|
|
5108
|
+
/* string call_cid = 1; */
|
|
5109
|
+
if (message.callCid !== '')
|
|
5110
|
+
writer.tag(1, runtime.WireType.LengthDelimited).string(message.callCid);
|
|
5111
|
+
/* stream.video.sfu.models.Participant participant = 2; */
|
|
5112
|
+
if (message.participant)
|
|
5113
|
+
Participant.internalBinaryWrite(message.participant, writer.tag(2, runtime.WireType.LengthDelimited).fork(), options).join();
|
|
5114
|
+
let u = options.writeUnknownFields;
|
|
5115
|
+
if (u !== false)
|
|
5116
|
+
(u == true ? runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
5117
|
+
return writer;
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5120
|
+
/**
|
|
5121
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.ParticipantUpdated
|
|
5122
|
+
*/
|
|
5123
|
+
const ParticipantUpdated = new ParticipantUpdated$Type();
|
|
5124
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
4948
5125
|
class SubscriberOffer$Type extends runtime.MessageType {
|
|
4949
5126
|
constructor() {
|
|
4950
5127
|
super('stream.video.sfu.event.SubscriberOffer', [
|
|
@@ -5895,6 +6072,62 @@ class GoAway$Type extends runtime.MessageType {
|
|
|
5895
6072
|
* @generated MessageType for protobuf message stream.video.sfu.event.GoAway
|
|
5896
6073
|
*/
|
|
5897
6074
|
const GoAway = new GoAway$Type();
|
|
6075
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
6076
|
+
class CallEnded$Type extends runtime.MessageType {
|
|
6077
|
+
constructor() {
|
|
6078
|
+
super('stream.video.sfu.event.CallEnded', [
|
|
6079
|
+
{
|
|
6080
|
+
no: 1,
|
|
6081
|
+
name: 'reason',
|
|
6082
|
+
kind: 'enum',
|
|
6083
|
+
T: () => [
|
|
6084
|
+
'stream.video.sfu.models.CallEndedReason',
|
|
6085
|
+
CallEndedReason,
|
|
6086
|
+
'CALL_ENDED_REASON_',
|
|
6087
|
+
],
|
|
6088
|
+
},
|
|
6089
|
+
]);
|
|
6090
|
+
}
|
|
6091
|
+
create(value) {
|
|
6092
|
+
const message = globalThis.Object.create(this.messagePrototype);
|
|
6093
|
+
message.reason = 0;
|
|
6094
|
+
if (value !== undefined)
|
|
6095
|
+
runtime.reflectionMergePartial(this, message, value);
|
|
6096
|
+
return message;
|
|
6097
|
+
}
|
|
6098
|
+
internalBinaryRead(reader, length, options, target) {
|
|
6099
|
+
let message = target ?? this.create(), end = reader.pos + length;
|
|
6100
|
+
while (reader.pos < end) {
|
|
6101
|
+
let [fieldNo, wireType] = reader.tag();
|
|
6102
|
+
switch (fieldNo) {
|
|
6103
|
+
case /* stream.video.sfu.models.CallEndedReason reason */ 1:
|
|
6104
|
+
message.reason = reader.int32();
|
|
6105
|
+
break;
|
|
6106
|
+
default:
|
|
6107
|
+
let u = options.readUnknownField;
|
|
6108
|
+
if (u === 'throw')
|
|
6109
|
+
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
|
6110
|
+
let d = reader.skip(wireType);
|
|
6111
|
+
if (u !== false)
|
|
6112
|
+
(u === true ? runtime.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
return message;
|
|
6116
|
+
}
|
|
6117
|
+
internalBinaryWrite(message, writer, options) {
|
|
6118
|
+
/* stream.video.sfu.models.CallEndedReason reason = 1; */
|
|
6119
|
+
if (message.reason !== 0)
|
|
6120
|
+
writer.tag(1, runtime.WireType.Varint).int32(message.reason);
|
|
6121
|
+
let u = options.writeUnknownFields;
|
|
6122
|
+
if (u !== false)
|
|
6123
|
+
(u == true ? runtime.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
|
6124
|
+
return writer;
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
6127
|
+
/**
|
|
6128
|
+
* @generated MessageType for protobuf message stream.video.sfu.event.CallEnded
|
|
6129
|
+
*/
|
|
6130
|
+
const CallEnded = new CallEnded$Type();
|
|
5898
6131
|
|
|
5899
6132
|
var events = /*#__PURE__*/Object.freeze({
|
|
5900
6133
|
__proto__: null,
|
|
@@ -5902,6 +6135,7 @@ var events = /*#__PURE__*/Object.freeze({
|
|
|
5902
6135
|
AudioLevelChanged: AudioLevelChanged,
|
|
5903
6136
|
AudioMediaRequest: AudioMediaRequest,
|
|
5904
6137
|
AudioSender: AudioSender,
|
|
6138
|
+
CallEnded: CallEnded,
|
|
5905
6139
|
CallGrantsUpdated: CallGrantsUpdated,
|
|
5906
6140
|
ChangePublishQuality: ChangePublishQuality,
|
|
5907
6141
|
ConnectionQualityChanged: ConnectionQualityChanged,
|
|
@@ -5918,6 +6152,7 @@ var events = /*#__PURE__*/Object.freeze({
|
|
|
5918
6152
|
Migration: Migration,
|
|
5919
6153
|
ParticipantJoined: ParticipantJoined,
|
|
5920
6154
|
ParticipantLeft: ParticipantLeft,
|
|
6155
|
+
ParticipantUpdated: ParticipantUpdated,
|
|
5921
6156
|
PinsChanged: PinsChanged,
|
|
5922
6157
|
PublisherAnswer: PublisherAnswer,
|
|
5923
6158
|
SfuEvent: SfuEvent,
|
|
@@ -6198,6 +6433,8 @@ const sfuEventKinds = {
|
|
|
6198
6433
|
goAway: undefined,
|
|
6199
6434
|
iceRestart: undefined,
|
|
6200
6435
|
pinsUpdated: undefined,
|
|
6436
|
+
callEnded: undefined,
|
|
6437
|
+
participantUpdated: undefined,
|
|
6201
6438
|
};
|
|
6202
6439
|
const isSfuEvent = (eventName) => {
|
|
6203
6440
|
return Object.prototype.hasOwnProperty.call(sfuEventKinds, eventName);
|
|
@@ -7137,9 +7374,11 @@ class CallState {
|
|
|
7137
7374
|
this.setCurrentValue(this.thumbnailsSubject, call.thumbnails);
|
|
7138
7375
|
};
|
|
7139
7376
|
this.updateFromMemberRemoved = (event) => {
|
|
7377
|
+
this.updateFromCallResponse(event.call);
|
|
7140
7378
|
this.setCurrentValue(this.membersSubject, (members) => members.filter((m) => event.members.indexOf(m.user_id) === -1));
|
|
7141
7379
|
};
|
|
7142
7380
|
this.updateFromMemberAdded = (event) => {
|
|
7381
|
+
this.updateFromCallResponse(event.call);
|
|
7143
7382
|
this.setCurrentValue(this.membersSubject, (members) => [
|
|
7144
7383
|
...members,
|
|
7145
7384
|
...event.members,
|
|
@@ -7223,6 +7462,7 @@ class CallState {
|
|
|
7223
7462
|
});
|
|
7224
7463
|
};
|
|
7225
7464
|
this.updateMembers = (event) => {
|
|
7465
|
+
this.updateFromCallResponse(event.call);
|
|
7226
7466
|
this.setCurrentValue(this.membersSubject, (members) => members.map((member) => {
|
|
7227
7467
|
const memberUpdate = event.members.find((m) => m.user_id === member.user_id);
|
|
7228
7468
|
return memberUpdate ? memberUpdate : member;
|
|
@@ -9351,6 +9591,17 @@ const watchParticipantLeft = (state) => {
|
|
|
9351
9591
|
state.setParticipants((participants) => participants.filter((p) => p.sessionId !== participant.sessionId));
|
|
9352
9592
|
};
|
|
9353
9593
|
};
|
|
9594
|
+
/**
|
|
9595
|
+
* An event responder which handles the `participantUpdated` event.
|
|
9596
|
+
*/
|
|
9597
|
+
const watchParticipantUpdated = (state) => {
|
|
9598
|
+
return function onParticipantUpdated(e) {
|
|
9599
|
+
const { participant } = e;
|
|
9600
|
+
if (!participant)
|
|
9601
|
+
return;
|
|
9602
|
+
state.updateParticipant(participant.sessionId, participant);
|
|
9603
|
+
};
|
|
9604
|
+
};
|
|
9354
9605
|
/**
|
|
9355
9606
|
* An event responder which handles the `trackPublished` event.
|
|
9356
9607
|
* The SFU will send this event when a participant publishes a track.
|
|
@@ -9452,6 +9703,7 @@ const registerEventHandlers = (call, state, dispatcher) => {
|
|
|
9452
9703
|
watchParticipantCountChanged(dispatcher, state),
|
|
9453
9704
|
call.on('participantJoined', watchParticipantJoined(state)),
|
|
9454
9705
|
call.on('participantLeft', watchParticipantLeft(state)),
|
|
9706
|
+
call.on('participantUpdated', watchParticipantUpdated(state)),
|
|
9455
9707
|
call.on('trackPublished', watchTrackPublished(state)),
|
|
9456
9708
|
call.on('trackUnpublished', watchTrackUnpublished(state)),
|
|
9457
9709
|
watchAudioLevelChanged(dispatcher, state),
|
|
@@ -10638,18 +10890,27 @@ class InputMediaDeviceManager {
|
|
|
10638
10890
|
* Starts stream.
|
|
10639
10891
|
*/
|
|
10640
10892
|
async enable() {
|
|
10641
|
-
if (this.state.
|
|
10893
|
+
if (this.state.optimisticStatus === 'enabled') {
|
|
10894
|
+
await this.statusChangePromise;
|
|
10642
10895
|
return;
|
|
10643
|
-
this.enablePromise = this.unmuteStream();
|
|
10644
|
-
try {
|
|
10645
|
-
await this.enablePromise;
|
|
10646
|
-
this.state.setStatus('enabled');
|
|
10647
|
-
this.enablePromise = undefined;
|
|
10648
|
-
}
|
|
10649
|
-
catch (error) {
|
|
10650
|
-
this.enablePromise = undefined;
|
|
10651
|
-
throw error;
|
|
10652
10896
|
}
|
|
10897
|
+
const signal = this.nextAbortableStatusChangeRequest('enabled');
|
|
10898
|
+
const doEnable = async () => {
|
|
10899
|
+
if (signal.aborted)
|
|
10900
|
+
return;
|
|
10901
|
+
try {
|
|
10902
|
+
await this.unmuteStream();
|
|
10903
|
+
this.state.setStatus('enabled');
|
|
10904
|
+
}
|
|
10905
|
+
finally {
|
|
10906
|
+
if (!signal.aborted)
|
|
10907
|
+
this.resetStatusChangeRequest();
|
|
10908
|
+
}
|
|
10909
|
+
};
|
|
10910
|
+
this.statusChangePromise = this.statusChangePromise
|
|
10911
|
+
? this.statusChangePromise.then(doEnable)
|
|
10912
|
+
: doEnable();
|
|
10913
|
+
await this.statusChangePromise;
|
|
10653
10914
|
}
|
|
10654
10915
|
/**
|
|
10655
10916
|
* Stops or pauses the stream based on state.disableMode
|
|
@@ -10657,19 +10918,28 @@ class InputMediaDeviceManager {
|
|
|
10657
10918
|
*/
|
|
10658
10919
|
async disable(forceStop = false) {
|
|
10659
10920
|
this.state.prevStatus = this.state.status;
|
|
10660
|
-
if (!forceStop && this.state.
|
|
10921
|
+
if (!forceStop && this.state.optimisticStatus === 'disabled') {
|
|
10922
|
+
await this.statusChangePromise;
|
|
10661
10923
|
return;
|
|
10662
|
-
const stopTracks = forceStop || this.state.disableMode === 'stop-tracks';
|
|
10663
|
-
this.disablePromise = this.muteStream(stopTracks);
|
|
10664
|
-
try {
|
|
10665
|
-
await this.disablePromise;
|
|
10666
|
-
this.state.setStatus('disabled');
|
|
10667
|
-
this.disablePromise = undefined;
|
|
10668
|
-
}
|
|
10669
|
-
catch (error) {
|
|
10670
|
-
this.disablePromise = undefined;
|
|
10671
|
-
throw error;
|
|
10672
10924
|
}
|
|
10925
|
+
const stopTracks = forceStop || this.state.disableMode === 'stop-tracks';
|
|
10926
|
+
const signal = this.nextAbortableStatusChangeRequest('disabled');
|
|
10927
|
+
const doDisable = async () => {
|
|
10928
|
+
if (signal.aborted)
|
|
10929
|
+
return;
|
|
10930
|
+
try {
|
|
10931
|
+
await this.muteStream(stopTracks);
|
|
10932
|
+
this.state.setStatus('disabled');
|
|
10933
|
+
}
|
|
10934
|
+
finally {
|
|
10935
|
+
if (!signal.aborted)
|
|
10936
|
+
this.resetStatusChangeRequest();
|
|
10937
|
+
}
|
|
10938
|
+
};
|
|
10939
|
+
this.statusChangePromise = this.statusChangePromise
|
|
10940
|
+
? this.statusChangePromise.then(doDisable)
|
|
10941
|
+
: doDisable();
|
|
10942
|
+
await this.statusChangePromise;
|
|
10673
10943
|
}
|
|
10674
10944
|
/**
|
|
10675
10945
|
* If status was previously enabled, it will re-enable the device.
|
|
@@ -10685,7 +10955,7 @@ class InputMediaDeviceManager {
|
|
|
10685
10955
|
* else it will disable it.
|
|
10686
10956
|
*/
|
|
10687
10957
|
async toggle() {
|
|
10688
|
-
if (this.state.
|
|
10958
|
+
if (this.state.optimisticStatus === 'enabled') {
|
|
10689
10959
|
return this.disable();
|
|
10690
10960
|
}
|
|
10691
10961
|
else {
|
|
@@ -10872,11 +11142,8 @@ class InputMediaDeviceManager {
|
|
|
10872
11142
|
this.state.setMediaStream(stream, await rootStream);
|
|
10873
11143
|
this.getTracks().forEach((track) => {
|
|
10874
11144
|
track.addEventListener('ended', async () => {
|
|
10875
|
-
if (this.
|
|
10876
|
-
await this.
|
|
10877
|
-
}
|
|
10878
|
-
if (this.disablePromise) {
|
|
10879
|
-
await this.disablePromise;
|
|
11145
|
+
if (this.statusChangePromise) {
|
|
11146
|
+
await this.statusChangePromise;
|
|
10880
11147
|
}
|
|
10881
11148
|
if (this.state.status === 'enabled') {
|
|
10882
11149
|
this.isTrackStoppedDueToTrackEnd = true;
|
|
@@ -10906,11 +11173,8 @@ class InputMediaDeviceManager {
|
|
|
10906
11173
|
if (!deviceId) {
|
|
10907
11174
|
return;
|
|
10908
11175
|
}
|
|
10909
|
-
if (this.
|
|
10910
|
-
await this.
|
|
10911
|
-
}
|
|
10912
|
-
if (this.disablePromise) {
|
|
10913
|
-
await this.disablePromise;
|
|
11176
|
+
if (this.statusChangePromise) {
|
|
11177
|
+
await this.statusChangePromise;
|
|
10914
11178
|
}
|
|
10915
11179
|
let isDeviceDisconnected = false;
|
|
10916
11180
|
let isDeviceReplaced = false;
|
|
@@ -10944,6 +11208,16 @@ class InputMediaDeviceManager {
|
|
|
10944
11208
|
findDeviceInList(devices, deviceId) {
|
|
10945
11209
|
return devices.find((d) => d.deviceId === deviceId && d.kind === this.mediaDeviceKind);
|
|
10946
11210
|
}
|
|
11211
|
+
nextAbortableStatusChangeRequest(status) {
|
|
11212
|
+
this.statusChangeAbortController?.abort();
|
|
11213
|
+
this.statusChangeAbortController = new AbortController();
|
|
11214
|
+
this.state.setPendingStatus(status);
|
|
11215
|
+
return this.statusChangeAbortController.signal;
|
|
11216
|
+
}
|
|
11217
|
+
resetStatusChangeRequest() {
|
|
11218
|
+
this.statusChangePromise = undefined;
|
|
11219
|
+
this.statusChangeAbortController = undefined;
|
|
11220
|
+
}
|
|
10947
11221
|
}
|
|
10948
11222
|
|
|
10949
11223
|
class InputMediaDeviceManagerState {
|
|
@@ -10958,6 +11232,7 @@ class InputMediaDeviceManagerState {
|
|
|
10958
11232
|
this.disableMode = disableMode;
|
|
10959
11233
|
this.permissionName = permissionName;
|
|
10960
11234
|
this.statusSubject = new rxjs.BehaviorSubject(undefined);
|
|
11235
|
+
this.optimisticStatusSubject = new rxjs.BehaviorSubject(undefined);
|
|
10961
11236
|
this.mediaStreamSubject = new rxjs.BehaviorSubject(undefined);
|
|
10962
11237
|
this.selectedDeviceSubject = new rxjs.BehaviorSubject(undefined);
|
|
10963
11238
|
this.defaultConstraintsSubject = new rxjs.BehaviorSubject(undefined);
|
|
@@ -10976,6 +11251,12 @@ class InputMediaDeviceManagerState {
|
|
|
10976
11251
|
* An Observable that emits the device status
|
|
10977
11252
|
*/
|
|
10978
11253
|
this.status$ = this.statusSubject.asObservable().pipe(rxjs.distinctUntilChanged());
|
|
11254
|
+
/**
|
|
11255
|
+
* An Observable the reflects the requested device status. Useful for optimistic UIs
|
|
11256
|
+
*/
|
|
11257
|
+
this.optimisticStatus$ = this.optimisticStatusSubject
|
|
11258
|
+
.asObservable()
|
|
11259
|
+
.pipe(rxjs.distinctUntilChanged());
|
|
10979
11260
|
/**
|
|
10980
11261
|
* The default constraints for the device.
|
|
10981
11262
|
*/
|
|
@@ -11043,6 +11324,12 @@ class InputMediaDeviceManagerState {
|
|
|
11043
11324
|
get status() {
|
|
11044
11325
|
return this.getCurrentValue(this.status$);
|
|
11045
11326
|
}
|
|
11327
|
+
/**
|
|
11328
|
+
* The requested device status. Useful for optimistic UIs
|
|
11329
|
+
*/
|
|
11330
|
+
get optimisticStatus() {
|
|
11331
|
+
return this.getCurrentValue(this.optimisticStatus$);
|
|
11332
|
+
}
|
|
11046
11333
|
/**
|
|
11047
11334
|
* The currently selected device
|
|
11048
11335
|
*/
|
|
@@ -11062,6 +11349,13 @@ class InputMediaDeviceManagerState {
|
|
|
11062
11349
|
setStatus(status) {
|
|
11063
11350
|
this.setCurrentValue(this.statusSubject, status);
|
|
11064
11351
|
}
|
|
11352
|
+
/**
|
|
11353
|
+
* @internal
|
|
11354
|
+
* @param pendingStatus
|
|
11355
|
+
*/
|
|
11356
|
+
setPendingStatus(pendingStatus) {
|
|
11357
|
+
this.setCurrentValue(this.optimisticStatusSubject, pendingStatus);
|
|
11358
|
+
}
|
|
11065
11359
|
/**
|
|
11066
11360
|
* Updates the `mediaStream` state variable.
|
|
11067
11361
|
*
|
|
@@ -11181,9 +11475,9 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
11181
11475
|
async selectTargetResolution(resolution) {
|
|
11182
11476
|
this.targetResolution.height = resolution.height;
|
|
11183
11477
|
this.targetResolution.width = resolution.width;
|
|
11184
|
-
if (this.
|
|
11478
|
+
if (this.statusChangePromise && this.state.optimisticStatus === 'enabled') {
|
|
11185
11479
|
try {
|
|
11186
|
-
await this.
|
|
11480
|
+
await this.statusChangePromise;
|
|
11187
11481
|
}
|
|
11188
11482
|
catch (error) {
|
|
11189
11483
|
// couldn't enable device, target resolution will be applied the next time user attempts to start the device
|
|
@@ -13324,12 +13618,7 @@ class Call {
|
|
|
13324
13618
|
}
|
|
13325
13619
|
async initCamera(options) {
|
|
13326
13620
|
// Wait for any in progress camera operation
|
|
13327
|
-
|
|
13328
|
-
await this.camera.enablePromise;
|
|
13329
|
-
}
|
|
13330
|
-
if (this.camera.disablePromise) {
|
|
13331
|
-
await this.camera.disablePromise;
|
|
13332
|
-
}
|
|
13621
|
+
await this.camera.statusChangePromise;
|
|
13333
13622
|
if (this.state.localParticipant?.videoStream ||
|
|
13334
13623
|
!this.permissionsContext.hasPermission('send-video')) {
|
|
13335
13624
|
return;
|
|
@@ -13366,12 +13655,7 @@ class Call {
|
|
|
13366
13655
|
}
|
|
13367
13656
|
async initMic(options) {
|
|
13368
13657
|
// Wait for any in progress mic operation
|
|
13369
|
-
|
|
13370
|
-
await this.microphone.enablePromise;
|
|
13371
|
-
}
|
|
13372
|
-
if (this.microphone.disablePromise) {
|
|
13373
|
-
await this.microphone.disablePromise;
|
|
13374
|
-
}
|
|
13658
|
+
await this.microphone.statusChangePromise;
|
|
13375
13659
|
if (this.state.localParticipant?.audioStream ||
|
|
13376
13660
|
!this.permissionsContext.hasPermission('send-audio')) {
|
|
13377
13661
|
return;
|
|
@@ -14912,7 +15196,7 @@ class StreamClient {
|
|
|
14912
15196
|
});
|
|
14913
15197
|
};
|
|
14914
15198
|
this.getUserAgent = () => {
|
|
14915
|
-
const version = "1.0.
|
|
15199
|
+
const version = "1.0.2" ;
|
|
14916
15200
|
return (this.userAgent ||
|
|
14917
15201
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14918
15202
|
};
|