@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.cjs.js
CHANGED
|
@@ -6432,6 +6432,14 @@ class Publisher {
|
|
|
6432
6432
|
[TrackType.SCREEN_SHARE_AUDIO]: undefined,
|
|
6433
6433
|
[TrackType.UNSPECIFIED]: undefined,
|
|
6434
6434
|
};
|
|
6435
|
+
/**
|
|
6436
|
+
* A map keeping track of track types that were published to the SFU.
|
|
6437
|
+
* This map shouldn't be cleared when unpublishing a track, as it is used
|
|
6438
|
+
* to determine whether a track was published before.
|
|
6439
|
+
*
|
|
6440
|
+
* @private
|
|
6441
|
+
*/
|
|
6442
|
+
this.trackTypePublishHistory = new Map();
|
|
6435
6443
|
this.isIceRestarting = false;
|
|
6436
6444
|
this.createPeerConnection = (connectionConfig) => {
|
|
6437
6445
|
const pc = new RTCPeerConnection(connectionConfig);
|
|
@@ -6513,6 +6521,9 @@ class Publisher {
|
|
|
6513
6521
|
// by an external factor as permission revokes, device disconnected, etc.
|
|
6514
6522
|
// keep in mind that `track.stop()` doesn't trigger this event.
|
|
6515
6523
|
track.addEventListener('ended', handleTrackEnded);
|
|
6524
|
+
if (!track.enabled) {
|
|
6525
|
+
track.enabled = true;
|
|
6526
|
+
}
|
|
6516
6527
|
transceiver = this.pc.addTransceiver(track, {
|
|
6517
6528
|
direction: 'sendonly',
|
|
6518
6529
|
streams: trackType === TrackType.VIDEO || trackType === TrackType.SCREEN_SHARE
|
|
@@ -6523,6 +6534,7 @@ class Publisher {
|
|
|
6523
6534
|
logger$3('debug', `Added ${TrackType[trackType]} transceiver`);
|
|
6524
6535
|
this.transceiverInitOrder.push(trackType);
|
|
6525
6536
|
this.transceiverRegistry[trackType] = transceiver;
|
|
6537
|
+
this.trackTypePublishHistory.set(trackType, true);
|
|
6526
6538
|
if ('setCodecPreferences' in transceiver && codecPreferences) {
|
|
6527
6539
|
logger$3('info', `Setting ${TrackType[trackType]} codec preferences`, codecPreferences);
|
|
6528
6540
|
transceiver.setCodecPreferences(codecPreferences);
|
|
@@ -6550,16 +6562,25 @@ class Publisher {
|
|
|
6550
6562
|
* @param stopTrack specifies whether track should be stopped or just disabled
|
|
6551
6563
|
*/
|
|
6552
6564
|
this.unpublishStream = (trackType, stopTrack) => __awaiter(this, void 0, void 0, function* () {
|
|
6565
|
+
var _b;
|
|
6553
6566
|
const transceiver = this.pc
|
|
6554
6567
|
.getTransceivers()
|
|
6555
6568
|
.find((t) => t === this.transceiverRegistry[trackType] && t.sender.track);
|
|
6556
6569
|
if (transceiver &&
|
|
6557
6570
|
transceiver.sender.track &&
|
|
6558
|
-
|
|
6571
|
+
(stopTrack
|
|
6572
|
+
? transceiver.sender.track.readyState === 'live'
|
|
6573
|
+
: transceiver.sender.track.enabled)) {
|
|
6559
6574
|
stopTrack
|
|
6560
6575
|
? transceiver.sender.track.stop()
|
|
6561
6576
|
: (transceiver.sender.track.enabled = false);
|
|
6562
|
-
|
|
6577
|
+
// We don't need to notify SFU if unpublishing in response to remote soft mute
|
|
6578
|
+
if (!((_b = this.state.localParticipant) === null || _b === void 0 ? void 0 : _b.publishedTracks.includes(trackType))) {
|
|
6579
|
+
return;
|
|
6580
|
+
}
|
|
6581
|
+
else {
|
|
6582
|
+
return this.notifyTrackMuteStateChanged(undefined, transceiver.sender.track, trackType, true);
|
|
6583
|
+
}
|
|
6563
6584
|
}
|
|
6564
6585
|
});
|
|
6565
6586
|
/**
|
|
@@ -6568,6 +6589,32 @@ class Publisher {
|
|
|
6568
6589
|
* @param trackType the track type to check.
|
|
6569
6590
|
*/
|
|
6570
6591
|
this.isPublishing = (trackType) => {
|
|
6592
|
+
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6593
|
+
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6594
|
+
const sender = transceiverForTrackType.sender;
|
|
6595
|
+
return (!!sender.track &&
|
|
6596
|
+
sender.track.readyState === 'live' &&
|
|
6597
|
+
sender.track.enabled);
|
|
6598
|
+
}
|
|
6599
|
+
return false;
|
|
6600
|
+
};
|
|
6601
|
+
/**
|
|
6602
|
+
* Returns true if the given track type was ever published to the SFU.
|
|
6603
|
+
* Contrary to `isPublishing`, this method returns true if a certain
|
|
6604
|
+
* track type was published before, even if it is currently unpublished.
|
|
6605
|
+
*
|
|
6606
|
+
* @param trackType the track type to check.
|
|
6607
|
+
*/
|
|
6608
|
+
this.hasEverPublished = (trackType) => {
|
|
6609
|
+
var _a;
|
|
6610
|
+
return (_a = this.trackTypePublishHistory.get(trackType)) !== null && _a !== void 0 ? _a : false;
|
|
6611
|
+
};
|
|
6612
|
+
/**
|
|
6613
|
+
* Returns true if the given track type is currently live
|
|
6614
|
+
*
|
|
6615
|
+
* @param trackType the track type to check.
|
|
6616
|
+
*/
|
|
6617
|
+
this.isLive = (trackType) => {
|
|
6571
6618
|
const transceiverForTrackType = this.transceiverRegistry[trackType];
|
|
6572
6619
|
if (transceiverForTrackType && transceiverForTrackType.sender) {
|
|
6573
6620
|
const sender = transceiverForTrackType.sender;
|
|
@@ -6608,9 +6655,9 @@ class Publisher {
|
|
|
6608
6655
|
});
|
|
6609
6656
|
};
|
|
6610
6657
|
this.updateVideoPublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
|
|
6611
|
-
var
|
|
6658
|
+
var _c;
|
|
6612
6659
|
logger$3('info', 'Update publish quality, requested rids by SFU:', enabledRids);
|
|
6613
|
-
const videoSender = (
|
|
6660
|
+
const videoSender = (_c = this.transceiverRegistry[TrackType.VIDEO]) === null || _c === void 0 ? void 0 : _c.sender;
|
|
6614
6661
|
if (!videoSender) {
|
|
6615
6662
|
logger$3('warn', 'Update publish quality, no video sender found.');
|
|
6616
6663
|
return;
|
|
@@ -6708,8 +6755,8 @@ class Publisher {
|
|
|
6708
6755
|
* @param options the optional offer options to use.
|
|
6709
6756
|
*/
|
|
6710
6757
|
this.negotiate = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
6711
|
-
var
|
|
6712
|
-
this.isIceRestarting = (
|
|
6758
|
+
var _d;
|
|
6759
|
+
this.isIceRestarting = (_d = options === null || options === void 0 ? void 0 : options.iceRestart) !== null && _d !== void 0 ? _d : false;
|
|
6713
6760
|
const offer = yield this.pc.createOffer(options);
|
|
6714
6761
|
offer.sdp = this.mungeCodecs(offer.sdp);
|
|
6715
6762
|
const trackInfos = this.getCurrentTrackInfos(offer.sdp);
|
|
@@ -7497,6 +7544,9 @@ const retryable = (rpc, logger) => __awaiter(void 0, void 0, void 0, function* (
|
|
|
7497
7544
|
retryAttempt++;
|
|
7498
7545
|
} while (((_a = rpcCallResult.response.error) === null || _a === void 0 ? void 0 : _a.shouldRetry) &&
|
|
7499
7546
|
retryAttempt < MAX_RETRIES);
|
|
7547
|
+
if (rpcCallResult.response.error) {
|
|
7548
|
+
throw rpcCallResult.response.error;
|
|
7549
|
+
}
|
|
7500
7550
|
return rpcCallResult;
|
|
7501
7551
|
});
|
|
7502
7552
|
|
|
@@ -9820,6 +9870,190 @@ class CameraManagerState extends InputMediaDeviceManagerState {
|
|
|
9820
9870
|
}
|
|
9821
9871
|
}
|
|
9822
9872
|
|
|
9873
|
+
class InputMediaDeviceManager {
|
|
9874
|
+
constructor(call, state, trackType) {
|
|
9875
|
+
this.call = call;
|
|
9876
|
+
this.state = state;
|
|
9877
|
+
this.trackType = trackType;
|
|
9878
|
+
this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
|
|
9879
|
+
}
|
|
9880
|
+
/**
|
|
9881
|
+
* Lists the available audio/video devices
|
|
9882
|
+
*
|
|
9883
|
+
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
9884
|
+
*
|
|
9885
|
+
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
9886
|
+
*/
|
|
9887
|
+
listDevices() {
|
|
9888
|
+
return this.getDevices();
|
|
9889
|
+
}
|
|
9890
|
+
/**
|
|
9891
|
+
* Starts camera/microphone
|
|
9892
|
+
*/
|
|
9893
|
+
enable() {
|
|
9894
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9895
|
+
if (this.state.status === 'enabled') {
|
|
9896
|
+
return;
|
|
9897
|
+
}
|
|
9898
|
+
this.enablePromise = this.unmuteStream();
|
|
9899
|
+
try {
|
|
9900
|
+
yield this.enablePromise;
|
|
9901
|
+
this.state.setStatus('enabled');
|
|
9902
|
+
}
|
|
9903
|
+
catch (error) {
|
|
9904
|
+
this.enablePromise = undefined;
|
|
9905
|
+
throw error;
|
|
9906
|
+
}
|
|
9907
|
+
});
|
|
9908
|
+
}
|
|
9909
|
+
/**
|
|
9910
|
+
* Stops camera/microphone
|
|
9911
|
+
*
|
|
9912
|
+
* @returns
|
|
9913
|
+
*/
|
|
9914
|
+
disable() {
|
|
9915
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9916
|
+
this.state.prevStatus = this.state.status;
|
|
9917
|
+
if (this.state.status === 'disabled') {
|
|
9918
|
+
return;
|
|
9919
|
+
}
|
|
9920
|
+
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
9921
|
+
try {
|
|
9922
|
+
yield this.disablePromise;
|
|
9923
|
+
this.state.setStatus('disabled');
|
|
9924
|
+
this.disablePromise = undefined;
|
|
9925
|
+
}
|
|
9926
|
+
catch (error) {
|
|
9927
|
+
this.disablePromise = undefined;
|
|
9928
|
+
throw error;
|
|
9929
|
+
}
|
|
9930
|
+
});
|
|
9931
|
+
}
|
|
9932
|
+
/**
|
|
9933
|
+
* If status was previously enabled, it will reenable the device.
|
|
9934
|
+
*/
|
|
9935
|
+
resume() {
|
|
9936
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9937
|
+
if (this.state.prevStatus === 'enabled' &&
|
|
9938
|
+
this.state.status === 'disabled') {
|
|
9939
|
+
this.enable();
|
|
9940
|
+
}
|
|
9941
|
+
});
|
|
9942
|
+
}
|
|
9943
|
+
/**
|
|
9944
|
+
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
9945
|
+
*
|
|
9946
|
+
* @returns
|
|
9947
|
+
*/
|
|
9948
|
+
toggle() {
|
|
9949
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9950
|
+
if (this.state.status === 'enabled') {
|
|
9951
|
+
return this.disable();
|
|
9952
|
+
}
|
|
9953
|
+
else {
|
|
9954
|
+
return this.enable();
|
|
9955
|
+
}
|
|
9956
|
+
});
|
|
9957
|
+
}
|
|
9958
|
+
/**
|
|
9959
|
+
* Select device
|
|
9960
|
+
*
|
|
9961
|
+
* Note: this method is not supported in React Native
|
|
9962
|
+
*
|
|
9963
|
+
* @param deviceId
|
|
9964
|
+
*/
|
|
9965
|
+
select(deviceId) {
|
|
9966
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9967
|
+
if (isReactNative()) {
|
|
9968
|
+
throw new Error('This method is not supported in React Native');
|
|
9969
|
+
}
|
|
9970
|
+
if (deviceId === this.state.selectedDevice) {
|
|
9971
|
+
return;
|
|
9972
|
+
}
|
|
9973
|
+
this.state.setDevice(deviceId);
|
|
9974
|
+
yield this.applySettingsToStream();
|
|
9975
|
+
});
|
|
9976
|
+
}
|
|
9977
|
+
applySettingsToStream() {
|
|
9978
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9979
|
+
if (this.state.status === 'enabled') {
|
|
9980
|
+
yield this.muteStream();
|
|
9981
|
+
yield this.unmuteStream();
|
|
9982
|
+
}
|
|
9983
|
+
});
|
|
9984
|
+
}
|
|
9985
|
+
muteStream(stopTracks = true) {
|
|
9986
|
+
var _a;
|
|
9987
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9988
|
+
if (!this.state.mediaStream) {
|
|
9989
|
+
return;
|
|
9990
|
+
}
|
|
9991
|
+
this.logger('debug', `${stopTracks ? 'Stopping' : 'Disabling'} stream`);
|
|
9992
|
+
if (this.call.state.callingState === exports.CallingState.JOINED) {
|
|
9993
|
+
yield this.stopPublishStream(stopTracks);
|
|
9994
|
+
}
|
|
9995
|
+
this.muteLocalStream(stopTracks);
|
|
9996
|
+
if (((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'ended') {
|
|
9997
|
+
// @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
|
|
9998
|
+
if (typeof this.state.mediaStream.release === 'function') {
|
|
9999
|
+
// @ts-expect-error
|
|
10000
|
+
this.state.mediaStream.release();
|
|
10001
|
+
}
|
|
10002
|
+
this.state.setMediaStream(undefined);
|
|
10003
|
+
}
|
|
10004
|
+
});
|
|
10005
|
+
}
|
|
10006
|
+
muteTrack() {
|
|
10007
|
+
const track = this.getTrack();
|
|
10008
|
+
if (!track || !track.enabled) {
|
|
10009
|
+
return;
|
|
10010
|
+
}
|
|
10011
|
+
track.enabled = false;
|
|
10012
|
+
}
|
|
10013
|
+
unmuteTrack() {
|
|
10014
|
+
const track = this.getTrack();
|
|
10015
|
+
if (!track || track.enabled) {
|
|
10016
|
+
return;
|
|
10017
|
+
}
|
|
10018
|
+
track.enabled = true;
|
|
10019
|
+
}
|
|
10020
|
+
stopTrack() {
|
|
10021
|
+
const track = this.getTrack();
|
|
10022
|
+
if (!track || track.readyState === 'ended') {
|
|
10023
|
+
return;
|
|
10024
|
+
}
|
|
10025
|
+
track.stop();
|
|
10026
|
+
}
|
|
10027
|
+
muteLocalStream(stopTracks) {
|
|
10028
|
+
if (!this.state.mediaStream) {
|
|
10029
|
+
return;
|
|
10030
|
+
}
|
|
10031
|
+
stopTracks ? this.stopTrack() : this.muteTrack();
|
|
10032
|
+
}
|
|
10033
|
+
unmuteStream() {
|
|
10034
|
+
var _a;
|
|
10035
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10036
|
+
this.logger('debug', 'Starting stream');
|
|
10037
|
+
let stream;
|
|
10038
|
+
if (this.state.mediaStream && ((_a = this.getTrack()) === null || _a === void 0 ? void 0 : _a.readyState) === 'live') {
|
|
10039
|
+
stream = this.state.mediaStream;
|
|
10040
|
+
this.unmuteTrack();
|
|
10041
|
+
}
|
|
10042
|
+
else {
|
|
10043
|
+
if (this.state.mediaStream) {
|
|
10044
|
+
this.stopTrack();
|
|
10045
|
+
}
|
|
10046
|
+
const constraints = { deviceId: this.state.selectedDevice };
|
|
10047
|
+
stream = yield this.getStream(constraints);
|
|
10048
|
+
}
|
|
10049
|
+
if (this.call.state.callingState === exports.CallingState.JOINED) {
|
|
10050
|
+
yield this.publishStream(stream);
|
|
10051
|
+
}
|
|
10052
|
+
this.state.setMediaStream(stream);
|
|
10053
|
+
});
|
|
10054
|
+
}
|
|
10055
|
+
}
|
|
10056
|
+
|
|
9823
10057
|
const getDevices = (constraints) => {
|
|
9824
10058
|
return new rxjs.Observable((subscriber) => {
|
|
9825
10059
|
navigator.mediaDevices
|
|
@@ -10068,156 +10302,9 @@ const disposeOfMediaStream = (stream) => {
|
|
|
10068
10302
|
}
|
|
10069
10303
|
};
|
|
10070
10304
|
|
|
10071
|
-
class InputMediaDeviceManager {
|
|
10072
|
-
constructor(call, state) {
|
|
10073
|
-
this.call = call;
|
|
10074
|
-
this.state = state;
|
|
10075
|
-
}
|
|
10076
|
-
/**
|
|
10077
|
-
* Lists the available audio/video devices
|
|
10078
|
-
*
|
|
10079
|
-
* Note: It prompts the user for a permission to use devices (if not already granted)
|
|
10080
|
-
*
|
|
10081
|
-
* @returns an Observable that will be updated if a device is connected or disconnected
|
|
10082
|
-
*/
|
|
10083
|
-
listDevices() {
|
|
10084
|
-
return this.getDevices();
|
|
10085
|
-
}
|
|
10086
|
-
/**
|
|
10087
|
-
* Starts camera/microphone
|
|
10088
|
-
*/
|
|
10089
|
-
enable() {
|
|
10090
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10091
|
-
if (this.state.status === 'enabled') {
|
|
10092
|
-
return;
|
|
10093
|
-
}
|
|
10094
|
-
this.enablePromise = this.unmuteStream();
|
|
10095
|
-
try {
|
|
10096
|
-
yield this.enablePromise;
|
|
10097
|
-
this.state.setStatus('enabled');
|
|
10098
|
-
}
|
|
10099
|
-
catch (error) {
|
|
10100
|
-
this.enablePromise = undefined;
|
|
10101
|
-
throw error;
|
|
10102
|
-
}
|
|
10103
|
-
});
|
|
10104
|
-
}
|
|
10105
|
-
/**
|
|
10106
|
-
* Stops camera/microphone
|
|
10107
|
-
*
|
|
10108
|
-
* @returns
|
|
10109
|
-
*/
|
|
10110
|
-
disable() {
|
|
10111
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10112
|
-
this.state.prevStatus = this.state.status;
|
|
10113
|
-
if (this.state.status === 'disabled') {
|
|
10114
|
-
return;
|
|
10115
|
-
}
|
|
10116
|
-
this.disablePromise = this.muteStream(this.state.disableMode === 'stop-tracks');
|
|
10117
|
-
try {
|
|
10118
|
-
yield this.disablePromise;
|
|
10119
|
-
this.state.setStatus('disabled');
|
|
10120
|
-
this.disablePromise = undefined;
|
|
10121
|
-
}
|
|
10122
|
-
catch (error) {
|
|
10123
|
-
this.disablePromise = undefined;
|
|
10124
|
-
throw error;
|
|
10125
|
-
}
|
|
10126
|
-
});
|
|
10127
|
-
}
|
|
10128
|
-
/**
|
|
10129
|
-
* If status was previously enabled, it will reenable the device.
|
|
10130
|
-
*/
|
|
10131
|
-
resume() {
|
|
10132
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10133
|
-
if (this.state.prevStatus === 'enabled' &&
|
|
10134
|
-
this.state.status === 'disabled') {
|
|
10135
|
-
this.enable();
|
|
10136
|
-
}
|
|
10137
|
-
});
|
|
10138
|
-
}
|
|
10139
|
-
/**
|
|
10140
|
-
* If current device statis is disabled, it will enable the device, else it will disable it.
|
|
10141
|
-
*
|
|
10142
|
-
* @returns
|
|
10143
|
-
*/
|
|
10144
|
-
toggle() {
|
|
10145
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10146
|
-
if (this.state.status === 'enabled') {
|
|
10147
|
-
return this.disable();
|
|
10148
|
-
}
|
|
10149
|
-
else {
|
|
10150
|
-
return this.enable();
|
|
10151
|
-
}
|
|
10152
|
-
});
|
|
10153
|
-
}
|
|
10154
|
-
/**
|
|
10155
|
-
* Select device
|
|
10156
|
-
*
|
|
10157
|
-
* Note: this method is not supported in React Native
|
|
10158
|
-
*
|
|
10159
|
-
* @param deviceId
|
|
10160
|
-
*/
|
|
10161
|
-
select(deviceId) {
|
|
10162
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10163
|
-
if (isReactNative()) {
|
|
10164
|
-
throw new Error('This method is not supported in React Native');
|
|
10165
|
-
}
|
|
10166
|
-
if (deviceId === this.state.selectedDevice) {
|
|
10167
|
-
return;
|
|
10168
|
-
}
|
|
10169
|
-
this.state.setDevice(deviceId);
|
|
10170
|
-
yield this.applySettingsToStream();
|
|
10171
|
-
});
|
|
10172
|
-
}
|
|
10173
|
-
applySettingsToStream() {
|
|
10174
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10175
|
-
if (this.state.status === 'enabled') {
|
|
10176
|
-
yield this.muteStream();
|
|
10177
|
-
yield this.unmuteStream();
|
|
10178
|
-
}
|
|
10179
|
-
});
|
|
10180
|
-
}
|
|
10181
|
-
muteStream(stopTracks = true) {
|
|
10182
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10183
|
-
if (!this.state.mediaStream) {
|
|
10184
|
-
return;
|
|
10185
|
-
}
|
|
10186
|
-
if (this.call.state.callingState === exports.CallingState.JOINED) {
|
|
10187
|
-
yield this.stopPublishStream(stopTracks);
|
|
10188
|
-
}
|
|
10189
|
-
else if (this.state.mediaStream) {
|
|
10190
|
-
stopTracks
|
|
10191
|
-
? disposeOfMediaStream(this.state.mediaStream)
|
|
10192
|
-
: this.muteTracks();
|
|
10193
|
-
}
|
|
10194
|
-
if (stopTracks) {
|
|
10195
|
-
this.state.setMediaStream(undefined);
|
|
10196
|
-
}
|
|
10197
|
-
});
|
|
10198
|
-
}
|
|
10199
|
-
unmuteStream() {
|
|
10200
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
10201
|
-
let stream;
|
|
10202
|
-
if (this.state.mediaStream) {
|
|
10203
|
-
stream = this.state.mediaStream;
|
|
10204
|
-
this.unmuteTracks();
|
|
10205
|
-
}
|
|
10206
|
-
else {
|
|
10207
|
-
const constraints = { deviceId: this.state.selectedDevice };
|
|
10208
|
-
stream = yield this.getStream(constraints);
|
|
10209
|
-
}
|
|
10210
|
-
if (this.call.state.callingState === exports.CallingState.JOINED) {
|
|
10211
|
-
yield this.publishStream(stream);
|
|
10212
|
-
}
|
|
10213
|
-
this.state.setMediaStream(stream);
|
|
10214
|
-
});
|
|
10215
|
-
}
|
|
10216
|
-
}
|
|
10217
|
-
|
|
10218
10305
|
class CameraManager extends InputMediaDeviceManager {
|
|
10219
10306
|
constructor(call) {
|
|
10220
|
-
super(call, new CameraManagerState());
|
|
10307
|
+
super(call, new CameraManagerState(), TrackType.VIDEO);
|
|
10221
10308
|
this.targetResolution = {
|
|
10222
10309
|
width: 1280,
|
|
10223
10310
|
height: 720,
|
|
@@ -10269,6 +10356,7 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10269
10356
|
if (width !== this.targetResolution.width ||
|
|
10270
10357
|
height !== this.targetResolution.height)
|
|
10271
10358
|
yield this.applySettingsToStream();
|
|
10359
|
+
this.logger('debug', `${width}x${height} target resolution applied to media stream`);
|
|
10272
10360
|
}
|
|
10273
10361
|
});
|
|
10274
10362
|
}
|
|
@@ -10292,13 +10380,9 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
10292
10380
|
stopPublishStream(stopTracks) {
|
|
10293
10381
|
return this.call.stopPublish(TrackType.VIDEO, stopTracks);
|
|
10294
10382
|
}
|
|
10295
|
-
|
|
10296
|
-
var _a;
|
|
10297
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((t) => (t.enabled = false));
|
|
10298
|
-
}
|
|
10299
|
-
unmuteTracks() {
|
|
10383
|
+
getTrack() {
|
|
10300
10384
|
var _a;
|
|
10301
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()
|
|
10385
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks()[0];
|
|
10302
10386
|
}
|
|
10303
10387
|
}
|
|
10304
10388
|
|
|
@@ -10314,7 +10398,7 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
|
10314
10398
|
|
|
10315
10399
|
class MicrophoneManager extends InputMediaDeviceManager {
|
|
10316
10400
|
constructor(call) {
|
|
10317
|
-
super(call, new MicrophoneManagerState());
|
|
10401
|
+
super(call, new MicrophoneManagerState(), TrackType.AUDIO);
|
|
10318
10402
|
}
|
|
10319
10403
|
getDevices() {
|
|
10320
10404
|
return getAudioDevices();
|
|
@@ -10328,13 +10412,9 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
10328
10412
|
stopPublishStream(stopTracks) {
|
|
10329
10413
|
return this.call.stopPublish(TrackType.AUDIO, stopTracks);
|
|
10330
10414
|
}
|
|
10331
|
-
|
|
10332
|
-
var _a;
|
|
10333
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((t) => (t.enabled = false));
|
|
10334
|
-
}
|
|
10335
|
-
unmuteTracks() {
|
|
10415
|
+
getTrack() {
|
|
10336
10416
|
var _a;
|
|
10337
|
-
(_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()
|
|
10417
|
+
return (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks()[0];
|
|
10338
10418
|
}
|
|
10339
10419
|
}
|
|
10340
10420
|
|
|
@@ -11020,7 +11100,7 @@ class Call {
|
|
|
11020
11100
|
*/
|
|
11021
11101
|
this.stopPublish = (trackType, stopTrack = true) => __awaiter(this, void 0, void 0, function* () {
|
|
11022
11102
|
var _j;
|
|
11023
|
-
this.logger('info', `stopPublish ${TrackType[trackType]}`);
|
|
11103
|
+
this.logger('info', `stopPublish ${TrackType[trackType]}, stop tracks: ${stopTrack}`);
|
|
11024
11104
|
yield ((_j = this.publisher) === null || _j === void 0 ? void 0 : _j.unpublishStream(trackType, stopTrack));
|
|
11025
11105
|
});
|
|
11026
11106
|
/**
|
|
@@ -11598,6 +11678,40 @@ class Call {
|
|
|
11598
11678
|
this.leaveCallHooks.add(createSubscription(this.trackSubscriptionsSubject.pipe(rxjs.debounce((v) => rxjs.timer(v.type)), rxjs.map((v) => v.data)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
|
|
11599
11679
|
this.camera = new CameraManager(this);
|
|
11600
11680
|
this.microphone = new MicrophoneManager(this);
|
|
11681
|
+
// FIXME OL: disable soft-mutes as they are not working properly
|
|
11682
|
+
// this.state.localParticipant$.subscribe(async (p) => {
|
|
11683
|
+
// if (!this.publisher) return;
|
|
11684
|
+
// // Mute via device manager
|
|
11685
|
+
// // If integrator doesn't use device manager, we mute using stopPublish
|
|
11686
|
+
// if (
|
|
11687
|
+
// this.publisher.hasEverPublished(TrackType.VIDEO) &&
|
|
11688
|
+
// this.publisher.isPublishing(TrackType.VIDEO) &&
|
|
11689
|
+
// !p?.publishedTracks.includes(TrackType.VIDEO)
|
|
11690
|
+
// ) {
|
|
11691
|
+
// this.logger(
|
|
11692
|
+
// 'info',
|
|
11693
|
+
// `Local participant's video track is muted remotely`,
|
|
11694
|
+
// );
|
|
11695
|
+
// await this.camera.disable();
|
|
11696
|
+
// if (this.publisher.isPublishing(TrackType.VIDEO)) {
|
|
11697
|
+
// await this.stopPublish(TrackType.VIDEO);
|
|
11698
|
+
// }
|
|
11699
|
+
// }
|
|
11700
|
+
// if (
|
|
11701
|
+
// this.publisher.hasEverPublished(TrackType.AUDIO) &&
|
|
11702
|
+
// this.publisher.isPublishing(TrackType.AUDIO) &&
|
|
11703
|
+
// !p?.publishedTracks.includes(TrackType.AUDIO)
|
|
11704
|
+
// ) {
|
|
11705
|
+
// this.logger(
|
|
11706
|
+
// 'info',
|
|
11707
|
+
// `Local participant's audio track is muted remotely`,
|
|
11708
|
+
// );
|
|
11709
|
+
// await this.microphone.disable();
|
|
11710
|
+
// if (this.publisher.isPublishing(TrackType.AUDIO)) {
|
|
11711
|
+
// await this.stopPublish(TrackType.AUDIO);
|
|
11712
|
+
// }
|
|
11713
|
+
// }
|
|
11714
|
+
// });
|
|
11601
11715
|
this.speaker = new SpeakerManager();
|
|
11602
11716
|
}
|
|
11603
11717
|
registerEffects() {
|
|
@@ -11623,9 +11737,27 @@ class Call {
|
|
|
11623
11737
|
};
|
|
11624
11738
|
for (const [permission, trackType] of Object.entries(permissionToTrackType)) {
|
|
11625
11739
|
const hasPermission = this.permissionsContext.hasPermission(permission);
|
|
11626
|
-
if (!hasPermission &&
|
|
11627
|
-
this.
|
|
11740
|
+
if (!hasPermission &&
|
|
11741
|
+
(this.publisher.isPublishing(trackType) ||
|
|
11742
|
+
this.publisher.isLive(trackType))) {
|
|
11743
|
+
// Stop tracks, then notify device manager
|
|
11744
|
+
this.stopPublish(trackType)
|
|
11745
|
+
.catch((err) => {
|
|
11628
11746
|
this.logger('error', `Error stopping publish ${trackType}`, err);
|
|
11747
|
+
})
|
|
11748
|
+
.then(() => {
|
|
11749
|
+
if (trackType === TrackType.VIDEO &&
|
|
11750
|
+
this.camera.state.status === 'enabled') {
|
|
11751
|
+
this.camera
|
|
11752
|
+
.disable()
|
|
11753
|
+
.catch((err) => this.logger('error', `Error disabling camera after pemission revoked`, err));
|
|
11754
|
+
}
|
|
11755
|
+
if (trackType === TrackType.AUDIO &&
|
|
11756
|
+
this.microphone.state.status === 'enabled') {
|
|
11757
|
+
this.microphone
|
|
11758
|
+
.disable()
|
|
11759
|
+
.catch((err) => this.logger('error', `Error disabling microphone after pemission revoked`, err));
|
|
11760
|
+
}
|
|
11629
11761
|
});
|
|
11630
11762
|
}
|
|
11631
11763
|
}
|
|
@@ -12889,11 +13021,11 @@ class WSConnectionFallback {
|
|
|
12889
13021
|
}
|
|
12890
13022
|
}
|
|
12891
13023
|
|
|
12892
|
-
const version = '0.3.
|
|
13024
|
+
const version = '0.3.15';
|
|
12893
13025
|
|
|
12894
13026
|
const logger = getLogger(['location']);
|
|
12895
13027
|
const HINT_URL = `https://hint.stream-io-video.com/`;
|
|
12896
|
-
const getLocationHint = (hintUrl = HINT_URL, timeout =
|
|
13028
|
+
const getLocationHint = (hintUrl = HINT_URL, timeout = 2000) => __awaiter(void 0, void 0, void 0, function* () {
|
|
12897
13029
|
const abortController = new AbortController();
|
|
12898
13030
|
const timeoutId = setTimeout(() => abortController.abort(), timeout);
|
|
12899
13031
|
try {
|
|
@@ -12906,7 +13038,7 @@ const getLocationHint = (hintUrl = HINT_URL, timeout = 1500) => __awaiter(void 0
|
|
|
12906
13038
|
return awsPop.substring(0, 3); // AMS1-P2 -> AMS
|
|
12907
13039
|
}
|
|
12908
13040
|
catch (e) {
|
|
12909
|
-
logger('
|
|
13041
|
+
logger('warn', `Failed to get location hint from ${HINT_URL}`, e);
|
|
12910
13042
|
return 'ERR';
|
|
12911
13043
|
}
|
|
12912
13044
|
finally {
|