@stream-io/video-client 0.3.13 → 0.3.15
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 +305 -173
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +305 -173
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +305 -173
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/CameraManager.d.ts +1 -2
- package/dist/src/devices/InputMediaDeviceManager.d.ts +10 -3
- package/dist/src/devices/MicrophoneManager.d.ts +1 -2
- package/dist/src/rtc/Publisher.d.ts +22 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +83 -5
- package/src/StreamSfuClient.ts +4 -0
- package/src/coordinator/connection/location.ts +2 -2
- package/src/devices/CameraManager.ts +7 -8
- package/src/devices/InputMediaDeviceManager.ts +58 -12
- package/src/devices/MicrophoneManager.ts +3 -8
- package/src/devices/__tests__/InputMediaDeviceManager.test.ts +5 -12
- package/src/devices/__tests__/mocks.ts +4 -0
- package/src/helpers/__tests__/DynascaleManager.test.ts +3 -0
- package/src/rtc/Publisher.ts +56 -7
- package/src/rtc/__tests__/Publisher.test.ts +1 -0
- package/src/rtc/codecs.ts +0 -2
package/dist/index.es.js
CHANGED
|
@@ -6412,6 +6412,14 @@ class Publisher {
|
|
|
6412
6412
|
[TrackType.SCREEN_SHARE_AUDIO]: undefined,
|
|
6413
6413
|
[TrackType.UNSPECIFIED]: undefined,
|
|
6414
6414
|
};
|
|
6415
|
+
/**
|
|
6416
|
+
* A map keeping track of track types that were published to the SFU.
|
|
6417
|
+
* This map shouldn't be cleared when unpublishing a track, as it is used
|
|
6418
|
+
* to determine whether a track was published before.
|
|
6419
|
+
*
|
|
6420
|
+
* @private
|
|
6421
|
+
*/
|
|
6422
|
+
this.trackTypePublishHistory = new Map();
|
|
6415
6423
|
this.isIceRestarting = false;
|
|
6416
6424
|
this.createPeerConnection = (connectionConfig) => {
|
|
6417
6425
|
const pc = new RTCPeerConnection(connectionConfig);
|
|
@@ -6493,6 +6501,9 @@ class Publisher {
|
|
|
6493
6501
|
// by an external factor as permission revokes, device disconnected, etc.
|
|
6494
6502
|
// keep in mind that `track.stop()` doesn't trigger this event.
|
|
6495
6503
|
track.addEventListener('ended', handleTrackEnded);
|
|
6504
|
+
if (!track.enabled) {
|
|
6505
|
+
track.enabled = true;
|
|
6506
|
+
}
|
|
6496
6507
|
transceiver = this.pc.addTransceiver(track, {
|
|
6497
6508
|
direction: 'sendonly',
|
|
6498
6509
|
streams: trackType === TrackType.VIDEO || trackType === TrackType.SCREEN_SHARE
|
|
@@ -6503,6 +6514,7 @@ class Publisher {
|
|
|
6503
6514
|
logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
6504
6515
|
this.transceiverInitOrder.push(trackType);
|
|
6505
6516
|
this.transceiverRegistry[trackType] = transceiver;
|
|
6517
|
+
this.trackTypePublishHistory.set(trackType, true);
|
|
6506
6518
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
6507
6519
|
logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
6508
6520
|
transceiver.setCodecPreferences(codecPreferences);
|
|
@@ -6530,16 +6542,25 @@ class Publisher {
|
|
|
6530
6542
|
* @param stopTrack specifies whether track should be stopped or just disabled
|
|
6531
6543
|
*/
|
|
6532
6544
|
this.unpublishStream = (trackType, stopTrack) => __awaiter(this, void 0, void 0, function* () {
|
|
6545
|
+
var _b;
|
|
6533
6546
|
const transceiver = this.pc
|
|
6534
6547
|
.getTransceivers()
|
|
6535
6548
|
.find((t) => t === this.transceiverRegistry[trackType] && t.sender.track);
|
|
6536
6549
|
if (transceiver &&
|
|
6537
6550
|
transceiver.sender.track &&
|
|
6538
|
-
|
|
6551
|
+
(stopTrack
|
|
6552
|
+
? transceiver.sender.track.readyState === 'live'
|
|
6553
|
+
: transceiver.sender.track.enabled)) {
|
|
6539
6554
|
stopTrack
|
|
6540
6555
|
? transceiver.sender.track.stop()
|
|
6541
6556
|
: (transceiver.sender.track.enabled = false);
|
|
6542
|
-
|
|
6557
|
+
// We don't need to notify SFU if unpublishing in response to remote soft mute
|
|
6558
|
+
if (!((_b = this.state.localParticipant) === null || _b === void 0 ? void 0 : _b.publishedTracks.includes(trackType))) {
|
|
6559
|
+
return;
|
|
6560
|
+
}
|
|
6561
|
+
else {
|
|
6562
|
+
return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
|
|
6563
|
+
}
|
|
6543
6564
|
}
|
|
6544
6565
|
});
|
|
6545
6566
|
/**
|
|
@@ -6548,6 +6569,32 @@ class Publisher {
|
|
|
6548
6569
|
* @param trackType the track type to check.
|
|
6549
6570
|
*/
|
|
6550
6571
|
this.isPublishing = (trackType) => {
|
|
6572
|
+
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6573
|
+
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6574
|
+
const sender = transceiverForTrackType.sender;
|
|
6575
|
+
return (!!sender.track &&
|
|
6576
|
+
sender.track.readyState === 'live' &&
|
|
6577
|
+
sender.track.enabled);
|
|
6578
|
+
}
|
|
6579
|
+
return false;
|
|
6580
|
+
};
|
|
6581
|
+
/**
|
|
6582
|
+
* Returns true if the given track type was ever published to the SFU.
|
|
6583
|
+
* Contrary to `isPublishing`, this method returns true if a certain
|
|
6584
|
+
* track type was published before, even if it is currently unpublished.
|
|
6585
|
+
*
|
|
6586
|
+
* @param trackType the track type to check.
|
|
6587
|
+
*/
|
|
6588
|
+
this.hasEverPublished = (trackType) => {
|
|
6589
|
+
var _a;
|
|
6590
|
+
return (_a = this.trackTypePublishHistory.get(trackType)) !== null && _a !== void 0 ? _a : false;
|
|
6591
|
+
};
|
|
6592
|
+
/**
|
|
6593
|
+
* Returns true if the given track type is currently live
|
|
6594
|
+
*
|
|
6595
|
+
* @param trackType the track type to check.
|
|
6596
|
+
*/
|
|
6597
|
+
this.isLive = (trackType) => {
|
|
6551
6598
|
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6552
6599
|
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6553
6600
|
const sender = transceiverForTrackType.sender;
|
|
@@ -6588,9 +6635,9 @@ class Publisher {
|
|
|
6588
6635
|
});
|
|
6589
6636
|
};
|
|
6590
6637
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6591
|
-
var
|
|
6638
|
+
var _c;
|
|
6592
6639
|
logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
6593
|
-
const videoSender = (
|
|
6640
|
+
const videoSender = (_c = this.transceiverRegistry[TrackType.VIDEO]) === null || _c === void 0 ? void 0 : _c.sender;
|
|
6594
6641
|
if (!videoSender) {
|
|
6595
6642
|
logger$3('warn', 'Update publish quality, no video sender found.');
|
|
6596
6643
|
return;
|
|
@@ -6688,8 +6735,8 @@ class Publisher {
|
|
|
6688
6735
|
* @param options the optional offer options to use.
|
|
6689
6736
|
*/
|
|
6690
6737
|
this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
6691
|
-
var
|
|
6692
|
-
this.isIceRestarting = (
|
|
6738
|
+
var _d;
|
|
6739
|
+
this.isIceRestarting = (_d = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _d !== void 0 ? _d : false;
|
|
6693
6740
|
const offer = yield this.pc.createOffer(options);
|
|
6694
6741
|
offer.sdp = this.mungeCodecs(offer.sdp);
|
|
6695
6742
|
const trackInfos = this.getCurrentTrackInfos(offer.sdp);
|
|
@@ -7477,6 +7524,9 @@ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
7477
7524
|
retryAttempt++;
|
|
7478
7525
|
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
7479
7526
|
retryAttempt < MAX_RETRIES);
|
|
7527
|
+
if (rpcCallResult.response.error) {
|
|
7528
|
+
throw rpcCallResult.response.error;
|
|
7529
|
+
}
|
|
7480
7530
|
return rpcCallResult;
|
|
7481
7531
|
});
|
|
7482
7532
|
|
|
@@ -9800,6 +9850,190 @@ class CameraManagerState extends InputMediaDeviceManagerState {
|
|
|
9800
9850
|
}
|
|
9801
9851
|
}
|
|
9802
9852
|
|
|
9853
|
+
class InputMediaDeviceManager {
|
|
9854
|
+
constructor(call, state, trackType) {
|
|
9855
|
+
this.call = call;
|
|
9856
|
+
this.state = state;
|
|
9857
|
+
this.trackType = trackType;
|
|
9858
|
+
this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
|
|
9859
|
+
}
|
|
9860
|
+
/**
|
|
9861
|
+
* Lists the available audio/video devices
|
|
9862
|
+
*
|
|
9863
|
+
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
9864
|
+
*
|
|
9865
|
+
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
9866
|
+
*/
|
|
9867
|
+
listDevices() {
|
|
9868
|
+
return this.getDevices();
|
|
9869
|
+
}
|
|
9870
|
+
/**
|
|
9871
|
+
* Starts camera/microphone
|
|
9872
|
+
*/
|
|
9873
|
+
enable() {
|
|
9874
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9875
|
+
if (this.state.status === 'enabled') {
|
|
9876
|
+
return;
|
|
9877
|
+
}
|
|
9878
|
+
this.enablePromise = this.unmuteStream();
|
|
9879
|
+
try {
|
|
9880
|
+
yield this.enablePromise;
|
|
9881
|
+
this.state.setStatus('enabled');
|
|
9882
|
+
}
|
|
9883
|
+
catch (error) {
|
|
9884
|
+
this.enablePromise = undefined;
|
|
9885
|
+
throw error;
|
|
9886
|
+
}
|
|
9887
|
+
});
|
|
9888
|
+
}
|
|
9889
|
+
/**
|
|
9890
|
+
* Stops camera/microphone
|
|
9891
|
+
*
|
|
9892
|
+
* @returns
|
|
9893
|
+
*/
|
|
9894
|
+
disable() {
|
|
9895
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9896
|
+
this.state.prevStatus = this.state.status;
|
|
9897
|
+
if (this.state.status === 'disabled') {
|
|
9898
|
+
return;
|
|
9899
|
+
}
|
|
9900
|
+
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
9901
|
+
try {
|
|
9902
|
+
yield this.disablePromise;
|
|
9903
|
+
this.state.setStatus('disabled');
|
|
9904
|
+
this.disablePromise = undefined;
|
|
9905
|
+
}
|
|
9906
|
+
catch (error) {
|
|
9907
|
+
this.disablePromise = undefined;
|
|
9908
|
+
throw error;
|
|
9909
|
+
}
|
|
9910
|
+
});
|
|
9911
|
+
}
|
|
9912
|
+
/**
|
|
9913
|
+
* If status was previously enabled, it will reenable the device.
|
|
9914
|
+
*/
|
|
9915
|
+
resume() {
|
|
9916
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9917
|
+
if (this.state.prevStatus === 'enabled' &&
|
|
9918
|
+
this.state.status === 'disabled') {
|
|
9919
|
+
this.enable();
|
|
9920
|
+
}
|
|
9921
|
+
});
|
|
9922
|
+
}
|
|
9923
|
+
/**
|
|
9924
|
+
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
9925
|
+
*
|
|
9926
|
+
* @returns
|
|
9927
|
+
*/
|
|
9928
|
+
toggle() {
|
|
9929
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9930
|
+
if (this.state.status === 'enabled') {
|
|
9931
|
+
return this.disable();
|
|
9932
|
+
}
|
|
9933
|
+
else {
|
|
9934
|
+
return this.enable();
|
|
9935
|
+
}
|
|
9936
|
+
});
|
|
9937
|
+
}
|
|
9938
|
+
/**
|
|
9939
|
+
* Select device
|
|
9940
|
+
*
|
|
9941
|
+
* Note: this method is not supported in React Native
|
|
9942
|
+
*
|
|
9943
|
+
* @param deviceId
|
|
9944
|
+
*/
|
|
9945
|
+
select(deviceId) {
|
|
9946
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9947
|
+
if (isReactNative()) {
|
|
9948
|
+
throw new Error('This method is not supported in React Native');
|
|
9949
|
+
}
|
|
9950
|
+
if (deviceId === this.state.selectedDevice) {
|
|
9951
|
+
return;
|
|
9952
|
+
}
|
|
9953
|
+
this.state.setDevice(deviceId);
|
|
9954
|
+
yield this.applySettingsToStream();
|
|
9955
|
+
});
|
|
9956
|
+
}
|
|
9957
|
+
applySettingsToStream() {
|
|
9958
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9959
|
+
if (this.state.status === 'enabled') {
|
|
9960
|
+
yield this.muteStream();
|
|
9961
|
+
yield this.unmuteStream();
|
|
9962
|
+
}
|
|
9963
|
+
});
|
|
9964
|
+
}
|
|
9965
|
+
muteStream(stopTracks = true) {
|
|
9966
|
+
var _a;
|
|
9967
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9968
|
+
if (!this.state.mediaStream) {
|
|
9969
|
+
return;
|
|
9970
|
+
}
|
|
9971
|
+
this.logger('debug', `${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
9972
|
+
if (this.call.state.callingState === CallingState.JOINED) {
|
|
9973
|
+
yield this.stopPublishStream(stopTracks);
|
|
9974
|
+
}
|
|
9975
|
+
this.muteLocalStream(stopTracks);
|
|
9976
|
+
if (((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'ended') {
|
|
9977
|
+
// @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
|
|
9978
|
+
if (typeof this.state.mediaStream.release === 'function') {
|
|
9979
|
+
// @ts-expect-error
|
|
9980
|
+
this.state.mediaStream.release();
|
|
9981
|
+
}
|
|
9982
|
+
this.state.setMediaStream(undefined);
|
|
9983
|
+
}
|
|
9984
|
+
});
|
|
9985
|
+
}
|
|
9986
|
+
muteTrack() {
|
|
9987
|
+
const track = this.getTrack();
|
|
9988
|
+
if (!track || !track.enabled) {
|
|
9989
|
+
return;
|
|
9990
|
+
}
|
|
9991
|
+
track.enabled = false;
|
|
9992
|
+
}
|
|
9993
|
+
unmuteTrack() {
|
|
9994
|
+
const track = this.getTrack();
|
|
9995
|
+
if (!track || track.enabled) {
|
|
9996
|
+
return;
|
|
9997
|
+
}
|
|
9998
|
+
track.enabled = true;
|
|
9999
|
+
}
|
|
10000
|
+
stopTrack() {
|
|
10001
|
+
const track = this.getTrack();
|
|
10002
|
+
if (!track || track.readyState === 'ended') {
|
|
10003
|
+
return;
|
|
10004
|
+
}
|
|
10005
|
+
track.stop();
|
|
10006
|
+
}
|
|
10007
|
+
muteLocalStream(stopTracks) {
|
|
10008
|
+
if (!this.state.mediaStream) {
|
|
10009
|
+
return;
|
|
10010
|
+
}
|
|
10011
|
+
stopTracks ? this.stopTrack() : this.muteTrack();
|
|
10012
|
+
}
|
|
10013
|
+
unmuteStream() {
|
|
10014
|
+
var _a;
|
|
10015
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10016
|
+
this.logger('debug', 'Starting stream');
|
|
10017
|
+
let stream;
|
|
10018
|
+
if (this.state.mediaStream && ((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'live') {
|
|
10019
|
+
stream = this.state.mediaStream;
|
|
10020
|
+
this.unmuteTrack();
|
|
10021
|
+
}
|
|
10022
|
+
else {
|
|
10023
|
+
if (this.state.mediaStream) {
|
|
10024
|
+
this.stopTrack();
|
|
10025
|
+
}
|
|
10026
|
+
const constraints = { deviceId: this.state.selectedDevice };
|
|
10027
|
+
stream = yield this.getStream(constraints);
|
|
10028
|
+
}
|
|
10029
|
+
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10030
|
+
yield this.publishStream(stream);
|
|
10031
|
+
}
|
|
10032
|
+
this.state.setMediaStream(stream);
|
|
10033
|
+
});
|
|
10034
|
+
}
|
|
10035
|
+
}
|
|
10036
|
+
|
|
9803
10037
|
const getDevices = (constraints) => {
|
|
9804
10038
|
return new Observable((subscriber) => {
|
|
9805
10039
|
navigator.mediaDevices
|
|
@@ -10048,156 +10282,9 @@ const disposeOfMediaStream = (stream) => {
|
|
|
10048
10282
|
}
|
|
10049
10283
|
};
|
|
10050
10284
|
|
|
10051
|
-
class InputMediaDeviceManager {
|
|
10052
|
-
constructor(call, state) {
|
|
10053
|
-
this.call = call;
|
|
10054
|
-
this.state = state;
|
|
10055
|
-
}
|
|
10056
|
-
/**
|
|
10057
|
-
* Lists the available audio/video devices
|
|
10058
|
-
*
|
|
10059
|
-
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
10060
|
-
*
|
|
10061
|
-
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
10062
|
-
*/
|
|
10063
|
-
listDevices() {
|
|
10064
|
-
return this.getDevices();
|
|
10065
|
-
}
|
|
10066
|
-
/**
|
|
10067
|
-
* Starts camera/microphone
|
|
10068
|
-
*/
|
|
10069
|
-
enable() {
|
|
10070
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10071
|
-
if (this.state.status === 'enabled') {
|
|
10072
|
-
return;
|
|
10073
|
-
}
|
|
10074
|
-
this.enablePromise = this.unmuteStream();
|
|
10075
|
-
try {
|
|
10076
|
-
yield this.enablePromise;
|
|
10077
|
-
this.state.setStatus('enabled');
|
|
10078
|
-
}
|
|
10079
|
-
catch (error) {
|
|
10080
|
-
this.enablePromise = undefined;
|
|
10081
|
-
throw error;
|
|
10082
|
-
}
|
|
10083
|
-
});
|
|
10084
|
-
}
|
|
10085
|
-
/**
|
|
10086
|
-
* Stops camera/microphone
|
|
10087
|
-
*
|
|
10088
|
-
* @returns
|
|
10089
|
-
*/
|
|
10090
|
-
disable() {
|
|
10091
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10092
|
-
this.state.prevStatus = this.state.status;
|
|
10093
|
-
if (this.state.status === 'disabled') {
|
|
10094
|
-
return;
|
|
10095
|
-
}
|
|
10096
|
-
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
10097
|
-
try {
|
|
10098
|
-
yield this.disablePromise;
|
|
10099
|
-
this.state.setStatus('disabled');
|
|
10100
|
-
this.disablePromise = undefined;
|
|
10101
|
-
}
|
|
10102
|
-
catch (error) {
|
|
10103
|
-
this.disablePromise = undefined;
|
|
10104
|
-
throw error;
|
|
10105
|
-
}
|
|
10106
|
-
});
|
|
10107
|
-
}
|
|
10108
|
-
/**
|
|
10109
|
-
* If status was previously enabled, it will reenable the device.
|
|
10110
|
-
*/
|
|
10111
|
-
resume() {
|
|
10112
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10113
|
-
if (this.state.prevStatus === 'enabled' &&
|
|
10114
|
-
this.state.status === 'disabled') {
|
|
10115
|
-
this.enable();
|
|
10116
|
-
}
|
|
10117
|
-
});
|
|
10118
|
-
}
|
|
10119
|
-
/**
|
|
10120
|
-
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
10121
|
-
*
|
|
10122
|
-
* @returns
|
|
10123
|
-
*/
|
|
10124
|
-
toggle() {
|
|
10125
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10126
|
-
if (this.state.status === 'enabled') {
|
|
10127
|
-
return this.disable();
|
|
10128
|
-
}
|
|
10129
|
-
else {
|
|
10130
|
-
return this.enable();
|
|
10131
|
-
}
|
|
10132
|
-
});
|
|
10133
|
-
}
|
|
10134
|
-
/**
|
|
10135
|
-
* Select device
|
|
10136
|
-
*
|
|
10137
|
-
* Note: this method is not supported in React Native
|
|
10138
|
-
*
|
|
10139
|
-
* @param deviceId
|
|
10140
|
-
*/
|
|
10141
|
-
select(deviceId) {
|
|
10142
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10143
|
-
if (isReactNative()) {
|
|
10144
|
-
throw new Error('This method is not supported in React Native');
|
|
10145
|
-
}
|
|
10146
|
-
if (deviceId === this.state.selectedDevice) {
|
|
10147
|
-
return;
|
|
10148
|
-
}
|
|
10149
|
-
this.state.setDevice(deviceId);
|
|
10150
|
-
yield this.applySettingsToStream();
|
|
10151
|
-
});
|
|
10152
|
-
}
|
|
10153
|
-
applySettingsToStream() {
|
|
10154
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10155
|
-
if (this.state.status === 'enabled') {
|
|
10156
|
-
yield this.muteStream();
|
|
10157
|
-
yield this.unmuteStream();
|
|
10158
|
-
}
|
|
10159
|
-
});
|
|
10160
|
-
}
|
|
10161
|
-
muteStream(stopTracks = true) {
|
|
10162
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10163
|
-
if (!this.state.mediaStream) {
|
|
10164
|
-
return;
|
|
10165
|
-
}
|
|
10166
|
-
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10167
|
-
yield this.stopPublishStream(stopTracks);
|
|
10168
|
-
}
|
|
10169
|
-
else if (this.state.mediaStream) {
|
|
10170
|
-
stopTracks
|
|
10171
|
-
? disposeOfMediaStream(this.state.mediaStream)
|
|
10172
|
-
: this.muteTracks();
|
|
10173
|
-
}
|
|
10174
|
-
if (stopTracks) {
|
|
10175
|
-
this.state.setMediaStream(undefined);
|
|
10176
|
-
}
|
|
10177
|
-
});
|
|
10178
|
-
}
|
|
10179
|
-
unmuteStream() {
|
|
10180
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10181
|
-
let stream;
|
|
10182
|
-
if (this.state.mediaStream) {
|
|
10183
|
-
stream = this.state.mediaStream;
|
|
10184
|
-
this.unmuteTracks();
|
|
10185
|
-
}
|
|
10186
|
-
else {
|
|
10187
|
-
const constraints = { deviceId: this.state.selectedDevice };
|
|
10188
|
-
stream = yield this.getStream(constraints);
|
|
10189
|
-
}
|
|
10190
|
-
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10191
|
-
yield this.publishStream(stream);
|
|
10192
|
-
}
|
|
10193
|
-
this.state.setMediaStream(stream);
|
|
10194
|
-
});
|
|
10195
|
-
}
|
|
10196
|
-
}
|
|
10197
|
-
|
|
10198
10285
|
class CameraManager extends InputMediaDeviceManager {
|
|
10199
10286
|
constructor(call) {
|
|
10200
|
-
super(call, new CameraManagerState());
|
|
10287
|
+
super(call, new CameraManagerState(), TrackType.VIDEO);
|
|
10201
10288
|
this.targetResolution = {
|
|
10202
10289
|
width: 1280,
|
|
10203
10290
|
height: 720,
|
|
@@ -10249,6 +10336,7 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10249
10336
|
if (width !== this.targetResolution.width ||
|
|
10250
10337
|
height !== this.targetResolution.height)
|
|
10251
10338
|
yield this.applySettingsToStream();
|
|
10339
|
+
this.logger('debug', `${width}x${height} target resolution applied to media stream`);
|
|
10252
10340
|
}
|
|
10253
10341
|
});
|
|
10254
10342
|
}
|
|
@@ -10272,13 +10360,9 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10272
10360
|
stopPublishStream(stopTracks) {
|
|
10273
10361
|
return this.call.stopPublish(TrackType.VIDEO, stopTracks);
|
|
10274
10362
|
}
|
|
10275
|
-
|
|
10276
|
-
var _a;
|
|
10277
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((t) => (t.enabled = false));
|
|
10278
|
-
}
|
|
10279
|
-
unmuteTracks() {
|
|
10363
|
+
getTrack() {
|
|
10280
10364
|
var _a;
|
|
10281
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()
|
|
10365
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
|
|
10282
10366
|
}
|
|
10283
10367
|
}
|
|
10284
10368
|
|
|
@@ -10294,7 +10378,7 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
|
10294
10378
|
|
|
10295
10379
|
class MicrophoneManager extends InputMediaDeviceManager {
|
|
10296
10380
|
constructor(call) {
|
|
10297
|
-
super(call, new MicrophoneManagerState());
|
|
10381
|
+
super(call, new MicrophoneManagerState(), TrackType.AUDIO);
|
|
10298
10382
|
}
|
|
10299
10383
|
getDevices() {
|
|
10300
10384
|
return getAudioDevices();
|
|
@@ -10308,13 +10392,9 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
10308
10392
|
stopPublishStream(stopTracks) {
|
|
10309
10393
|
return this.call.stopPublish(TrackType.AUDIO, stopTracks);
|
|
10310
10394
|
}
|
|
10311
|
-
|
|
10312
|
-
var _a;
|
|
10313
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((t) => (t.enabled = false));
|
|
10314
|
-
}
|
|
10315
|
-
unmuteTracks() {
|
|
10395
|
+
getTrack() {
|
|
10316
10396
|
var _a;
|
|
10317
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()
|
|
10397
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
10318
10398
|
}
|
|
10319
10399
|
}
|
|
10320
10400
|
|
|
@@ -11000,7 +11080,7 @@ class Call {
|
|
|
11000
11080
|
*/
|
|
11001
11081
|
this.stopPublish = (trackType, stopTrack = true) => __awaiter(this, void 0, void 0, function* () {
|
|
11002
11082
|
var _j;
|
|
11003
|
-
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
11083
|
+
this.logger('info', `stopPublish ${TrackType[trackType]}, stop tracks: ${stopTrack}`);
|
|
11004
11084
|
yield ((_j = this.publisher) === null || _j === void 0 ? void 0 : _j.unpublishStream(trackType, stopTrack));
|
|
11005
11085
|
});
|
|
11006
11086
|
/**
|
|
@@ -11578,6 +11658,40 @@ class Call {
|
|
|
11578
11658
|
this.leaveCallHooks.add(createSubscription(this.trackSubscriptionsSubject.pipe(debounce((v) => timer(v.type)), map$2((v) => v.data)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
|
|
11579
11659
|
this.camera = new CameraManager(this);
|
|
11580
11660
|
this.microphone = new MicrophoneManager(this);
|
|
11661
|
+
// FIXME OL: disable soft-mutes as they are not working properly
|
|
11662
|
+
// this.state.localParticipant$.subscribe(async (p) => {
|
|
11663
|
+
// if (!this.publisher) return;
|
|
11664
|
+
// // Mute via device manager
|
|
11665
|
+
// // If integrator doesn't use device manager, we mute using stopPublish
|
|
11666
|
+
// if (
|
|
11667
|
+
// this.publisher.hasEverPublished(TrackType.VIDEO) &&
|
|
11668
|
+
// this.publisher.isPublishing(TrackType.VIDEO) &&
|
|
11669
|
+
// !p?.publishedTracks.includes(TrackType.VIDEO)
|
|
11670
|
+
// ) {
|
|
11671
|
+
// this.logger(
|
|
11672
|
+
// 'info',
|
|
11673
|
+
// `Local participant's video track is muted remotely`,
|
|
11674
|
+
// );
|
|
11675
|
+
// await this.camera.disable();
|
|
11676
|
+
// if (this.publisher.isPublishing(TrackType.VIDEO)) {
|
|
11677
|
+
// await this.stopPublish(TrackType.VIDEO);
|
|
11678
|
+
// }
|
|
11679
|
+
// }
|
|
11680
|
+
// if (
|
|
11681
|
+
// this.publisher.hasEverPublished(TrackType.AUDIO) &&
|
|
11682
|
+
// this.publisher.isPublishing(TrackType.AUDIO) &&
|
|
11683
|
+
// !p?.publishedTracks.includes(TrackType.AUDIO)
|
|
11684
|
+
// ) {
|
|
11685
|
+
// this.logger(
|
|
11686
|
+
// 'info',
|
|
11687
|
+
// `Local participant's audio track is muted remotely`,
|
|
11688
|
+
// );
|
|
11689
|
+
// await this.microphone.disable();
|
|
11690
|
+
// if (this.publisher.isPublishing(TrackType.AUDIO)) {
|
|
11691
|
+
// await this.stopPublish(TrackType.AUDIO);
|
|
11692
|
+
// }
|
|
11693
|
+
// }
|
|
11694
|
+
// });
|
|
11581
11695
|
this.speaker = new SpeakerManager();
|
|
11582
11696
|
}
|
|
11583
11697
|
registerEffects() {
|
|
@@ -11603,9 +11717,27 @@ class Call {
|
|
|
11603
11717
|
};
|
|
11604
11718
|
for (const [permission, trackType] of Object.entries(permissionToTrackType)) {
|
|
11605
11719
|
const hasPermission = this.permissionsContext.hasPermission(permission);
|
|
11606
|
-
if (!hasPermission &&
|
|
11607
|
-
this.
|
|
11720
|
+
if (!hasPermission &&
|
|
11721
|
+
(this.publisher.isPublishing(trackType) ||
|
|
11722
|
+
this.publisher.isLive(trackType))) {
|
|
11723
|
+
// Stop tracks, then notify device manager
|
|
11724
|
+
this.stopPublish(trackType)
|
|
11725
|
+
.catch((err) => {
|
|
11608
11726
|
this.logger('error', `Error stopping publish ${trackType}`, err);
|
|
11727
|
+
})
|
|
11728
|
+
.then(() => {
|
|
11729
|
+
if (trackType === TrackType.VIDEO &&
|
|
11730
|
+
this.camera.state.status === 'enabled') {
|
|
11731
|
+
this.camera
|
|
11732
|
+
.disable()
|
|
11733
|
+
.catch((err) => this.logger('error', `Error disabling camera after pemission revoked`, err));
|
|
11734
|
+
}
|
|
11735
|
+
if (trackType === TrackType.AUDIO &&
|
|
11736
|
+
this.microphone.state.status === 'enabled') {
|
|
11737
|
+
this.microphone
|
|
11738
|
+
.disable()
|
|
11739
|
+
.catch((err) => this.logger('error', `Error disabling microphone after pemission revoked`, err));
|
|
11740
|
+
}
|
|
11609
11741
|
});
|
|
11610
11742
|
}
|
|
11611
11743
|
}
|
|
@@ -12869,11 +13001,11 @@ class WSConnectionFallback {
|
|
|
12869
13001
|
}
|
|
12870
13002
|
}
|
|
12871
13003
|
|
|
12872
|
-
const version = '0.3.
|
|
13004
|
+
const version = '0.3.15';
|
|
12873
13005
|
|
|
12874
13006
|
const logger = getLogger(['location']);
|
|
12875
13007
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|
|
12876
|
-
const getLocationHint = (hintUrl = HINT_URL, timeout =
|
|
13008
|
+
const getLocationHint = (hintUrl = HINT_URL, timeout = 2000) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12877
13009
|
const abortController = new AbortController();
|
|
12878
13010
|
const timeoutId = setTimeout(() => abortController.abort(), timeout);
|
|
12879
13011
|
try {
|
|
@@ -12886,7 +13018,7 @@ const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0
|
|
|
12886
13018
|
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
12887
13019
|
}
|
|
12888
13020
|
catch (e) {
|
|
12889
|
-
logger('
|
|
13021
|
+
logger('warn', `Failed to get location hint from ${HINT_URL}`, e);
|
|
12890
13022
|
return 'ERR';
|
|
12891
13023
|
}
|
|
12892
13024
|
finally {
|