@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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
### [0.3.15](https://github.com/GetStream/stream-video-js/compare/client0.3.14...client0.3.15) (2023-09-11)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* consider prior track publishing state before applying soft mutes ([#1070](https://github.com/GetStream/stream-video-js/issues/1070)) ([f542409](https://github.com/GetStream/stream-video-js/commit/f542409c641417bbbe6f0997d77e34684b881bfb)), closes [#988](https://github.com/GetStream/stream-video-js/issues/988)
|
|
11
|
+
|
|
12
|
+
### [0.3.14](https://github.com/GetStream/stream-video-js/compare/client0.3.13...client0.3.14) (2023-09-05)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* new device api remote mutes ([#988](https://github.com/GetStream/stream-video-js/issues/988)) ([5bbcefb](https://github.com/GetStream/stream-video-js/commit/5bbcefbf0d8be59025fef8111253a8a0baaf6001))
|
|
18
|
+
|
|
5
19
|
### [0.3.13](https://github.com/GetStream/stream-video-js/compare/client0.3.12...client0.3.13) (2023-08-31)
|
|
6
20
|
|
|
7
21
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -6409,6 +6409,14 @@ class Publisher {
|
|
|
6409
6409
|
[TrackType.SCREEN_SHARE_AUDIO]: undefined,
|
|
6410
6410
|
[TrackType.UNSPECIFIED]: undefined,
|
|
6411
6411
|
};
|
|
6412
|
+
/**
|
|
6413
|
+
* A map keeping track of track types that were published to the SFU.
|
|
6414
|
+
* This map shouldn't be cleared when unpublishing a track, as it is used
|
|
6415
|
+
* to determine whether a track was published before.
|
|
6416
|
+
*
|
|
6417
|
+
* @private
|
|
6418
|
+
*/
|
|
6419
|
+
this.trackTypePublishHistory = new Map();
|
|
6412
6420
|
this.isIceRestarting = false;
|
|
6413
6421
|
this.createPeerConnection = (connectionConfig) => {
|
|
6414
6422
|
const pc = new RTCPeerConnection(connectionConfig);
|
|
@@ -6490,6 +6498,9 @@ class Publisher {
|
|
|
6490
6498
|
// by an external factor as permission revokes, device disconnected, etc.
|
|
6491
6499
|
// keep in mind that `track.stop()` doesn't trigger this event.
|
|
6492
6500
|
track.addEventListener('ended', handleTrackEnded);
|
|
6501
|
+
if (!track.enabled) {
|
|
6502
|
+
track.enabled = true;
|
|
6503
|
+
}
|
|
6493
6504
|
transceiver = this.pc.addTransceiver(track, {
|
|
6494
6505
|
direction: 'sendonly',
|
|
6495
6506
|
streams: trackType === TrackType.VIDEO || trackType === TrackType.SCREEN_SHARE
|
|
@@ -6500,6 +6511,7 @@ class Publisher {
|
|
|
6500
6511
|
logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
6501
6512
|
this.transceiverInitOrder.push(trackType);
|
|
6502
6513
|
this.transceiverRegistry[trackType] = transceiver;
|
|
6514
|
+
this.trackTypePublishHistory.set(trackType, true);
|
|
6503
6515
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
6504
6516
|
logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
6505
6517
|
transceiver.setCodecPreferences(codecPreferences);
|
|
@@ -6527,16 +6539,25 @@ class Publisher {
|
|
|
6527
6539
|
* @param stopTrack specifies whether track should be stopped or just disabled
|
|
6528
6540
|
*/
|
|
6529
6541
|
this.unpublishStream = (trackType, stopTrack) => __awaiter(this, void 0, void 0, function* () {
|
|
6542
|
+
var _b;
|
|
6530
6543
|
const transceiver = this.pc
|
|
6531
6544
|
.getTransceivers()
|
|
6532
6545
|
.find((t) => t === this.transceiverRegistry[trackType] && t.sender.track);
|
|
6533
6546
|
if (transceiver &&
|
|
6534
6547
|
transceiver.sender.track &&
|
|
6535
|
-
|
|
6548
|
+
(stopTrack
|
|
6549
|
+
? transceiver.sender.track.readyState === 'live'
|
|
6550
|
+
: transceiver.sender.track.enabled)) {
|
|
6536
6551
|
stopTrack
|
|
6537
6552
|
? transceiver.sender.track.stop()
|
|
6538
6553
|
: (transceiver.sender.track.enabled = false);
|
|
6539
|
-
|
|
6554
|
+
// We don't need to notify SFU if unpublishing in response to remote soft mute
|
|
6555
|
+
if (!((_b = this.state.localParticipant) === null || _b === void 0 ? void 0 : _b.publishedTracks.includes(trackType))) {
|
|
6556
|
+
return;
|
|
6557
|
+
}
|
|
6558
|
+
else {
|
|
6559
|
+
return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
|
|
6560
|
+
}
|
|
6540
6561
|
}
|
|
6541
6562
|
});
|
|
6542
6563
|
/**
|
|
@@ -6545,6 +6566,32 @@ class Publisher {
|
|
|
6545
6566
|
* @param trackType the track type to check.
|
|
6546
6567
|
*/
|
|
6547
6568
|
this.isPublishing = (trackType) => {
|
|
6569
|
+
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6570
|
+
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6571
|
+
const sender = transceiverForTrackType.sender;
|
|
6572
|
+
return (!!sender.track &&
|
|
6573
|
+
sender.track.readyState === 'live' &&
|
|
6574
|
+
sender.track.enabled);
|
|
6575
|
+
}
|
|
6576
|
+
return false;
|
|
6577
|
+
};
|
|
6578
|
+
/**
|
|
6579
|
+
* Returns true if the given track type was ever published to the SFU.
|
|
6580
|
+
* Contrary to `isPublishing`, this method returns true if a certain
|
|
6581
|
+
* track type was published before, even if it is currently unpublished.
|
|
6582
|
+
*
|
|
6583
|
+
* @param trackType the track type to check.
|
|
6584
|
+
*/
|
|
6585
|
+
this.hasEverPublished = (trackType) => {
|
|
6586
|
+
var _a;
|
|
6587
|
+
return (_a = this.trackTypePublishHistory.get(trackType)) !== null && _a !== void 0 ? _a : false;
|
|
6588
|
+
};
|
|
6589
|
+
/**
|
|
6590
|
+
* Returns true if the given track type is currently live
|
|
6591
|
+
*
|
|
6592
|
+
* @param trackType the track type to check.
|
|
6593
|
+
*/
|
|
6594
|
+
this.isLive = (trackType) => {
|
|
6548
6595
|
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6549
6596
|
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6550
6597
|
const sender = transceiverForTrackType.sender;
|
|
@@ -6585,9 +6632,9 @@ class Publisher {
|
|
|
6585
6632
|
});
|
|
6586
6633
|
};
|
|
6587
6634
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6588
|
-
var
|
|
6635
|
+
var _c;
|
|
6589
6636
|
logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
6590
|
-
const videoSender = (
|
|
6637
|
+
const videoSender = (_c = this.transceiverRegistry[TrackType.VIDEO]) === null || _c === void 0 ? void 0 : _c.sender;
|
|
6591
6638
|
if (!videoSender) {
|
|
6592
6639
|
logger$3('warn', 'Update publish quality, no video sender found.');
|
|
6593
6640
|
return;
|
|
@@ -6685,8 +6732,8 @@ class Publisher {
|
|
|
6685
6732
|
* @param options the optional offer options to use.
|
|
6686
6733
|
*/
|
|
6687
6734
|
this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
6688
|
-
var
|
|
6689
|
-
this.isIceRestarting = (
|
|
6735
|
+
var _d;
|
|
6736
|
+
this.isIceRestarting = (_d = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _d !== void 0 ? _d : false;
|
|
6690
6737
|
const offer = yield this.pc.createOffer(options);
|
|
6691
6738
|
offer.sdp = this.mungeCodecs(offer.sdp);
|
|
6692
6739
|
const trackInfos = this.getCurrentTrackInfos(offer.sdp);
|
|
@@ -7474,6 +7521,9 @@ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
7474
7521
|
retryAttempt++;
|
|
7475
7522
|
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
7476
7523
|
retryAttempt < MAX_RETRIES);
|
|
7524
|
+
if (rpcCallResult.response.error) {
|
|
7525
|
+
throw rpcCallResult.response.error;
|
|
7526
|
+
}
|
|
7477
7527
|
return rpcCallResult;
|
|
7478
7528
|
});
|
|
7479
7529
|
|
|
@@ -9797,6 +9847,190 @@ class CameraManagerState extends InputMediaDeviceManagerState {
|
|
|
9797
9847
|
}
|
|
9798
9848
|
}
|
|
9799
9849
|
|
|
9850
|
+
class InputMediaDeviceManager {
|
|
9851
|
+
constructor(call, state, trackType) {
|
|
9852
|
+
this.call = call;
|
|
9853
|
+
this.state = state;
|
|
9854
|
+
this.trackType = trackType;
|
|
9855
|
+
this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
|
|
9856
|
+
}
|
|
9857
|
+
/**
|
|
9858
|
+
* Lists the available audio/video devices
|
|
9859
|
+
*
|
|
9860
|
+
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
9861
|
+
*
|
|
9862
|
+
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
9863
|
+
*/
|
|
9864
|
+
listDevices() {
|
|
9865
|
+
return this.getDevices();
|
|
9866
|
+
}
|
|
9867
|
+
/**
|
|
9868
|
+
* Starts camera/microphone
|
|
9869
|
+
*/
|
|
9870
|
+
enable() {
|
|
9871
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9872
|
+
if (this.state.status === 'enabled') {
|
|
9873
|
+
return;
|
|
9874
|
+
}
|
|
9875
|
+
this.enablePromise = this.unmuteStream();
|
|
9876
|
+
try {
|
|
9877
|
+
yield this.enablePromise;
|
|
9878
|
+
this.state.setStatus('enabled');
|
|
9879
|
+
}
|
|
9880
|
+
catch (error) {
|
|
9881
|
+
this.enablePromise = undefined;
|
|
9882
|
+
throw error;
|
|
9883
|
+
}
|
|
9884
|
+
});
|
|
9885
|
+
}
|
|
9886
|
+
/**
|
|
9887
|
+
* Stops camera/microphone
|
|
9888
|
+
*
|
|
9889
|
+
* @returns
|
|
9890
|
+
*/
|
|
9891
|
+
disable() {
|
|
9892
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9893
|
+
this.state.prevStatus = this.state.status;
|
|
9894
|
+
if (this.state.status === 'disabled') {
|
|
9895
|
+
return;
|
|
9896
|
+
}
|
|
9897
|
+
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
9898
|
+
try {
|
|
9899
|
+
yield this.disablePromise;
|
|
9900
|
+
this.state.setStatus('disabled');
|
|
9901
|
+
this.disablePromise = undefined;
|
|
9902
|
+
}
|
|
9903
|
+
catch (error) {
|
|
9904
|
+
this.disablePromise = undefined;
|
|
9905
|
+
throw error;
|
|
9906
|
+
}
|
|
9907
|
+
});
|
|
9908
|
+
}
|
|
9909
|
+
/**
|
|
9910
|
+
* If status was previously enabled, it will reenable the device.
|
|
9911
|
+
*/
|
|
9912
|
+
resume() {
|
|
9913
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9914
|
+
if (this.state.prevStatus === 'enabled' &&
|
|
9915
|
+
this.state.status === 'disabled') {
|
|
9916
|
+
this.enable();
|
|
9917
|
+
}
|
|
9918
|
+
});
|
|
9919
|
+
}
|
|
9920
|
+
/**
|
|
9921
|
+
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
9922
|
+
*
|
|
9923
|
+
* @returns
|
|
9924
|
+
*/
|
|
9925
|
+
toggle() {
|
|
9926
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9927
|
+
if (this.state.status === 'enabled') {
|
|
9928
|
+
return this.disable();
|
|
9929
|
+
}
|
|
9930
|
+
else {
|
|
9931
|
+
return this.enable();
|
|
9932
|
+
}
|
|
9933
|
+
});
|
|
9934
|
+
}
|
|
9935
|
+
/**
|
|
9936
|
+
* Select device
|
|
9937
|
+
*
|
|
9938
|
+
* Note: this method is not supported in React Native
|
|
9939
|
+
*
|
|
9940
|
+
* @param deviceId
|
|
9941
|
+
*/
|
|
9942
|
+
select(deviceId) {
|
|
9943
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9944
|
+
if (isReactNative()) {
|
|
9945
|
+
throw new Error('This method is not supported in React Native');
|
|
9946
|
+
}
|
|
9947
|
+
if (deviceId === this.state.selectedDevice) {
|
|
9948
|
+
return;
|
|
9949
|
+
}
|
|
9950
|
+
this.state.setDevice(deviceId);
|
|
9951
|
+
yield this.applySettingsToStream();
|
|
9952
|
+
});
|
|
9953
|
+
}
|
|
9954
|
+
applySettingsToStream() {
|
|
9955
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9956
|
+
if (this.state.status === 'enabled') {
|
|
9957
|
+
yield this.muteStream();
|
|
9958
|
+
yield this.unmuteStream();
|
|
9959
|
+
}
|
|
9960
|
+
});
|
|
9961
|
+
}
|
|
9962
|
+
muteStream(stopTracks = true) {
|
|
9963
|
+
var _a;
|
|
9964
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9965
|
+
if (!this.state.mediaStream) {
|
|
9966
|
+
return;
|
|
9967
|
+
}
|
|
9968
|
+
this.logger('debug', `${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
9969
|
+
if (this.call.state.callingState === CallingState.JOINED) {
|
|
9970
|
+
yield this.stopPublishStream(stopTracks);
|
|
9971
|
+
}
|
|
9972
|
+
this.muteLocalStream(stopTracks);
|
|
9973
|
+
if (((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'ended') {
|
|
9974
|
+
// @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
|
|
9975
|
+
if (typeof this.state.mediaStream.release === 'function') {
|
|
9976
|
+
// @ts-expect-error
|
|
9977
|
+
this.state.mediaStream.release();
|
|
9978
|
+
}
|
|
9979
|
+
this.state.setMediaStream(undefined);
|
|
9980
|
+
}
|
|
9981
|
+
});
|
|
9982
|
+
}
|
|
9983
|
+
muteTrack() {
|
|
9984
|
+
const track = this.getTrack();
|
|
9985
|
+
if (!track || !track.enabled) {
|
|
9986
|
+
return;
|
|
9987
|
+
}
|
|
9988
|
+
track.enabled = false;
|
|
9989
|
+
}
|
|
9990
|
+
unmuteTrack() {
|
|
9991
|
+
const track = this.getTrack();
|
|
9992
|
+
if (!track || track.enabled) {
|
|
9993
|
+
return;
|
|
9994
|
+
}
|
|
9995
|
+
track.enabled = true;
|
|
9996
|
+
}
|
|
9997
|
+
stopTrack() {
|
|
9998
|
+
const track = this.getTrack();
|
|
9999
|
+
if (!track || track.readyState === 'ended') {
|
|
10000
|
+
return;
|
|
10001
|
+
}
|
|
10002
|
+
track.stop();
|
|
10003
|
+
}
|
|
10004
|
+
muteLocalStream(stopTracks) {
|
|
10005
|
+
if (!this.state.mediaStream) {
|
|
10006
|
+
return;
|
|
10007
|
+
}
|
|
10008
|
+
stopTracks ? this.stopTrack() : this.muteTrack();
|
|
10009
|
+
}
|
|
10010
|
+
unmuteStream() {
|
|
10011
|
+
var _a;
|
|
10012
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10013
|
+
this.logger('debug', 'Starting stream');
|
|
10014
|
+
let stream;
|
|
10015
|
+
if (this.state.mediaStream && ((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'live') {
|
|
10016
|
+
stream = this.state.mediaStream;
|
|
10017
|
+
this.unmuteTrack();
|
|
10018
|
+
}
|
|
10019
|
+
else {
|
|
10020
|
+
if (this.state.mediaStream) {
|
|
10021
|
+
this.stopTrack();
|
|
10022
|
+
}
|
|
10023
|
+
const constraints = { deviceId: this.state.selectedDevice };
|
|
10024
|
+
stream = yield this.getStream(constraints);
|
|
10025
|
+
}
|
|
10026
|
+
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10027
|
+
yield this.publishStream(stream);
|
|
10028
|
+
}
|
|
10029
|
+
this.state.setMediaStream(stream);
|
|
10030
|
+
});
|
|
10031
|
+
}
|
|
10032
|
+
}
|
|
10033
|
+
|
|
9800
10034
|
const getDevices = (constraints) => {
|
|
9801
10035
|
return new Observable((subscriber) => {
|
|
9802
10036
|
navigator.mediaDevices
|
|
@@ -10045,156 +10279,9 @@ const disposeOfMediaStream = (stream) => {
|
|
|
10045
10279
|
}
|
|
10046
10280
|
};
|
|
10047
10281
|
|
|
10048
|
-
class InputMediaDeviceManager {
|
|
10049
|
-
constructor(call, state) {
|
|
10050
|
-
this.call = call;
|
|
10051
|
-
this.state = state;
|
|
10052
|
-
}
|
|
10053
|
-
/**
|
|
10054
|
-
* Lists the available audio/video devices
|
|
10055
|
-
*
|
|
10056
|
-
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
10057
|
-
*
|
|
10058
|
-
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
10059
|
-
*/
|
|
10060
|
-
listDevices() {
|
|
10061
|
-
return this.getDevices();
|
|
10062
|
-
}
|
|
10063
|
-
/**
|
|
10064
|
-
* Starts camera/microphone
|
|
10065
|
-
*/
|
|
10066
|
-
enable() {
|
|
10067
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10068
|
-
if (this.state.status === 'enabled') {
|
|
10069
|
-
return;
|
|
10070
|
-
}
|
|
10071
|
-
this.enablePromise = this.unmuteStream();
|
|
10072
|
-
try {
|
|
10073
|
-
yield this.enablePromise;
|
|
10074
|
-
this.state.setStatus('enabled');
|
|
10075
|
-
}
|
|
10076
|
-
catch (error) {
|
|
10077
|
-
this.enablePromise = undefined;
|
|
10078
|
-
throw error;
|
|
10079
|
-
}
|
|
10080
|
-
});
|
|
10081
|
-
}
|
|
10082
|
-
/**
|
|
10083
|
-
* Stops camera/microphone
|
|
10084
|
-
*
|
|
10085
|
-
* @returns
|
|
10086
|
-
*/
|
|
10087
|
-
disable() {
|
|
10088
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10089
|
-
this.state.prevStatus = this.state.status;
|
|
10090
|
-
if (this.state.status === 'disabled') {
|
|
10091
|
-
return;
|
|
10092
|
-
}
|
|
10093
|
-
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
10094
|
-
try {
|
|
10095
|
-
yield this.disablePromise;
|
|
10096
|
-
this.state.setStatus('disabled');
|
|
10097
|
-
this.disablePromise = undefined;
|
|
10098
|
-
}
|
|
10099
|
-
catch (error) {
|
|
10100
|
-
this.disablePromise = undefined;
|
|
10101
|
-
throw error;
|
|
10102
|
-
}
|
|
10103
|
-
});
|
|
10104
|
-
}
|
|
10105
|
-
/**
|
|
10106
|
-
* If status was previously enabled, it will reenable the device.
|
|
10107
|
-
*/
|
|
10108
|
-
resume() {
|
|
10109
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10110
|
-
if (this.state.prevStatus === 'enabled' &&
|
|
10111
|
-
this.state.status === 'disabled') {
|
|
10112
|
-
this.enable();
|
|
10113
|
-
}
|
|
10114
|
-
});
|
|
10115
|
-
}
|
|
10116
|
-
/**
|
|
10117
|
-
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
10118
|
-
*
|
|
10119
|
-
* @returns
|
|
10120
|
-
*/
|
|
10121
|
-
toggle() {
|
|
10122
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10123
|
-
if (this.state.status === 'enabled') {
|
|
10124
|
-
return this.disable();
|
|
10125
|
-
}
|
|
10126
|
-
else {
|
|
10127
|
-
return this.enable();
|
|
10128
|
-
}
|
|
10129
|
-
});
|
|
10130
|
-
}
|
|
10131
|
-
/**
|
|
10132
|
-
* Select device
|
|
10133
|
-
*
|
|
10134
|
-
* Note: this method is not supported in React Native
|
|
10135
|
-
*
|
|
10136
|
-
* @param deviceId
|
|
10137
|
-
*/
|
|
10138
|
-
select(deviceId) {
|
|
10139
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10140
|
-
if (isReactNative()) {
|
|
10141
|
-
throw new Error('This method is not supported in React Native');
|
|
10142
|
-
}
|
|
10143
|
-
if (deviceId === this.state.selectedDevice) {
|
|
10144
|
-
return;
|
|
10145
|
-
}
|
|
10146
|
-
this.state.setDevice(deviceId);
|
|
10147
|
-
yield this.applySettingsToStream();
|
|
10148
|
-
});
|
|
10149
|
-
}
|
|
10150
|
-
applySettingsToStream() {
|
|
10151
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10152
|
-
if (this.state.status === 'enabled') {
|
|
10153
|
-
yield this.muteStream();
|
|
10154
|
-
yield this.unmuteStream();
|
|
10155
|
-
}
|
|
10156
|
-
});
|
|
10157
|
-
}
|
|
10158
|
-
muteStream(stopTracks = true) {
|
|
10159
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10160
|
-
if (!this.state.mediaStream) {
|
|
10161
|
-
return;
|
|
10162
|
-
}
|
|
10163
|
-
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10164
|
-
yield this.stopPublishStream(stopTracks);
|
|
10165
|
-
}
|
|
10166
|
-
else if (this.state.mediaStream) {
|
|
10167
|
-
stopTracks
|
|
10168
|
-
? disposeOfMediaStream(this.state.mediaStream)
|
|
10169
|
-
: this.muteTracks();
|
|
10170
|
-
}
|
|
10171
|
-
if (stopTracks) {
|
|
10172
|
-
this.state.setMediaStream(undefined);
|
|
10173
|
-
}
|
|
10174
|
-
});
|
|
10175
|
-
}
|
|
10176
|
-
unmuteStream() {
|
|
10177
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10178
|
-
let stream;
|
|
10179
|
-
if (this.state.mediaStream) {
|
|
10180
|
-
stream = this.state.mediaStream;
|
|
10181
|
-
this.unmuteTracks();
|
|
10182
|
-
}
|
|
10183
|
-
else {
|
|
10184
|
-
const constraints = { deviceId: this.state.selectedDevice };
|
|
10185
|
-
stream = yield this.getStream(constraints);
|
|
10186
|
-
}
|
|
10187
|
-
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10188
|
-
yield this.publishStream(stream);
|
|
10189
|
-
}
|
|
10190
|
-
this.state.setMediaStream(stream);
|
|
10191
|
-
});
|
|
10192
|
-
}
|
|
10193
|
-
}
|
|
10194
|
-
|
|
10195
10282
|
class CameraManager extends InputMediaDeviceManager {
|
|
10196
10283
|
constructor(call) {
|
|
10197
|
-
super(call, new CameraManagerState());
|
|
10284
|
+
super(call, new CameraManagerState(), TrackType.VIDEO);
|
|
10198
10285
|
this.targetResolution = {
|
|
10199
10286
|
width: 1280,
|
|
10200
10287
|
height: 720,
|
|
@@ -10246,6 +10333,7 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10246
10333
|
if (width !== this.targetResolution.width ||
|
|
10247
10334
|
height !== this.targetResolution.height)
|
|
10248
10335
|
yield this.applySettingsToStream();
|
|
10336
|
+
this.logger('debug', `${width}x${height} target resolution applied to media stream`);
|
|
10249
10337
|
}
|
|
10250
10338
|
});
|
|
10251
10339
|
}
|
|
@@ -10269,13 +10357,9 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10269
10357
|
stopPublishStream(stopTracks) {
|
|
10270
10358
|
return this.call.stopPublish(TrackType.VIDEO, stopTracks);
|
|
10271
10359
|
}
|
|
10272
|
-
|
|
10273
|
-
var _a;
|
|
10274
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((t) => (t.enabled = false));
|
|
10275
|
-
}
|
|
10276
|
-
unmuteTracks() {
|
|
10360
|
+
getTrack() {
|
|
10277
10361
|
var _a;
|
|
10278
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()
|
|
10362
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
|
|
10279
10363
|
}
|
|
10280
10364
|
}
|
|
10281
10365
|
|
|
@@ -10291,7 +10375,7 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
|
10291
10375
|
|
|
10292
10376
|
class MicrophoneManager extends InputMediaDeviceManager {
|
|
10293
10377
|
constructor(call) {
|
|
10294
|
-
super(call, new MicrophoneManagerState());
|
|
10378
|
+
super(call, new MicrophoneManagerState(), TrackType.AUDIO);
|
|
10295
10379
|
}
|
|
10296
10380
|
getDevices() {
|
|
10297
10381
|
return getAudioDevices();
|
|
@@ -10305,13 +10389,9 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
10305
10389
|
stopPublishStream(stopTracks) {
|
|
10306
10390
|
return this.call.stopPublish(TrackType.AUDIO, stopTracks);
|
|
10307
10391
|
}
|
|
10308
|
-
|
|
10309
|
-
var _a;
|
|
10310
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((t) => (t.enabled = false));
|
|
10311
|
-
}
|
|
10312
|
-
unmuteTracks() {
|
|
10392
|
+
getTrack() {
|
|
10313
10393
|
var _a;
|
|
10314
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()
|
|
10394
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
10315
10395
|
}
|
|
10316
10396
|
}
|
|
10317
10397
|
|
|
@@ -10997,7 +11077,7 @@ class Call {
|
|
|
10997
11077
|
*/
|
|
10998
11078
|
this.stopPublish = (trackType, stopTrack = true) => __awaiter(this, void 0, void 0, function* () {
|
|
10999
11079
|
var _j;
|
|
11000
|
-
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
11080
|
+
this.logger('info', `stopPublish ${TrackType[trackType]}, stop tracks: ${stopTrack}`);
|
|
11001
11081
|
yield ((_j = this.publisher) === null || _j === void 0 ? void 0 : _j.unpublishStream(trackType, stopTrack));
|
|
11002
11082
|
});
|
|
11003
11083
|
/**
|
|
@@ -11575,6 +11655,40 @@ class Call {
|
|
|
11575
11655
|
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); }));
|
|
11576
11656
|
this.camera = new CameraManager(this);
|
|
11577
11657
|
this.microphone = new MicrophoneManager(this);
|
|
11658
|
+
// FIXME OL: disable soft-mutes as they are not working properly
|
|
11659
|
+
// this.state.localParticipant$.subscribe(async (p) => {
|
|
11660
|
+
// if (!this.publisher) return;
|
|
11661
|
+
// // Mute via device manager
|
|
11662
|
+
// // If integrator doesn't use device manager, we mute using stopPublish
|
|
11663
|
+
// if (
|
|
11664
|
+
// this.publisher.hasEverPublished(TrackType.VIDEO) &&
|
|
11665
|
+
// this.publisher.isPublishing(TrackType.VIDEO) &&
|
|
11666
|
+
// !p?.publishedTracks.includes(TrackType.VIDEO)
|
|
11667
|
+
// ) {
|
|
11668
|
+
// this.logger(
|
|
11669
|
+
// 'info',
|
|
11670
|
+
// `Local participant's video track is muted remotely`,
|
|
11671
|
+
// );
|
|
11672
|
+
// await this.camera.disable();
|
|
11673
|
+
// if (this.publisher.isPublishing(TrackType.VIDEO)) {
|
|
11674
|
+
// await this.stopPublish(TrackType.VIDEO);
|
|
11675
|
+
// }
|
|
11676
|
+
// }
|
|
11677
|
+
// if (
|
|
11678
|
+
// this.publisher.hasEverPublished(TrackType.AUDIO) &&
|
|
11679
|
+
// this.publisher.isPublishing(TrackType.AUDIO) &&
|
|
11680
|
+
// !p?.publishedTracks.includes(TrackType.AUDIO)
|
|
11681
|
+
// ) {
|
|
11682
|
+
// this.logger(
|
|
11683
|
+
// 'info',
|
|
11684
|
+
// `Local participant's audio track is muted remotely`,
|
|
11685
|
+
// );
|
|
11686
|
+
// await this.microphone.disable();
|
|
11687
|
+
// if (this.publisher.isPublishing(TrackType.AUDIO)) {
|
|
11688
|
+
// await this.stopPublish(TrackType.AUDIO);
|
|
11689
|
+
// }
|
|
11690
|
+
// }
|
|
11691
|
+
// });
|
|
11578
11692
|
this.speaker = new SpeakerManager();
|
|
11579
11693
|
}
|
|
11580
11694
|
registerEffects() {
|
|
@@ -11600,9 +11714,27 @@ class Call {
|
|
|
11600
11714
|
};
|
|
11601
11715
|
for (const [permission, trackType] of Object.entries(permissionToTrackType)) {
|
|
11602
11716
|
const hasPermission = this.permissionsContext.hasPermission(permission);
|
|
11603
|
-
if (!hasPermission &&
|
|
11604
|
-
this.
|
|
11717
|
+
if (!hasPermission &&
|
|
11718
|
+
(this.publisher.isPublishing(trackType) ||
|
|
11719
|
+
this.publisher.isLive(trackType))) {
|
|
11720
|
+
// Stop tracks, then notify device manager
|
|
11721
|
+
this.stopPublish(trackType)
|
|
11722
|
+
.catch((err) => {
|
|
11605
11723
|
this.logger('error', `Error stopping publish ${trackType}`, err);
|
|
11724
|
+
})
|
|
11725
|
+
.then(() => {
|
|
11726
|
+
if (trackType === TrackType.VIDEO &&
|
|
11727
|
+
this.camera.state.status === 'enabled') {
|
|
11728
|
+
this.camera
|
|
11729
|
+
.disable()
|
|
11730
|
+
.catch((err) => this.logger('error', `Error disabling camera after pemission revoked`, err));
|
|
11731
|
+
}
|
|
11732
|
+
if (trackType === TrackType.AUDIO &&
|
|
11733
|
+
this.microphone.state.status === 'enabled') {
|
|
11734
|
+
this.microphone
|
|
11735
|
+
.disable()
|
|
11736
|
+
.catch((err) => this.logger('error', `Error disabling microphone after pemission revoked`, err));
|
|
11737
|
+
}
|
|
11606
11738
|
});
|
|
11607
11739
|
}
|
|
11608
11740
|
}
|
|
@@ -12865,11 +12997,11 @@ class WSConnectionFallback {
|
|
|
12865
12997
|
}
|
|
12866
12998
|
}
|
|
12867
12999
|
|
|
12868
|
-
const version = '0.3.
|
|
13000
|
+
const version = '0.3.15';
|
|
12869
13001
|
|
|
12870
13002
|
const logger = getLogger(['location']);
|
|
12871
13003
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|
|
12872
|
-
const getLocationHint = (hintUrl = HINT_URL, timeout =
|
|
13004
|
+
const getLocationHint = (hintUrl = HINT_URL, timeout = 2000) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12873
13005
|
const abortController = new AbortController();
|
|
12874
13006
|
const timeoutId = setTimeout(() => abortController.abort(), timeout);
|
|
12875
13007
|
try {
|
|
@@ -12882,7 +13014,7 @@ const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0
|
|
|
12882
13014
|
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
12883
13015
|
}
|
|
12884
13016
|
catch (e) {
|
|
12885
|
-
logger('
|
|
13017
|
+
logger('warn', `Failed to get location hint from ${HINT_URL}`, e);
|
|
12886
13018
|
return 'ERR';
|
|
12887
13019
|
}
|
|
12888
13020
|
finally {
|