Merge pull request #12054 from mariogasparoni/fix-12023-and-other-two-fixes

fix: mic selection (firefox/all browsers) and muted alert when mic is changed
This commit is contained in:
Anton Georgiev 2021-04-20 13:40:54 -04:00 committed by GitHub
commit 36b67971ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 27 deletions

View File

@ -24,6 +24,7 @@ module.exports = {
'react/prop-types': 1,
'jsx-a11y/no-access-key': 0,
'react/jsx-props-no-spreading': 'off',
'max-classes-per-file': ['error', 2],
},
globals: {
browser: 'writable',

View File

@ -119,28 +119,69 @@ class SIPSession {
return matchConstraints;
}
setInputStream(stream) {
if (!this.currentSession
|| !this.currentSession.sessionDescriptionHandler
) return;
/**
* Set the input stream for the peer that represents the current session.
* Internally, this will call the sender's replaceTrack function.
* @param {MediaStream} stream The MediaStream object to be used as input
* stream
* @return {Promise} A Promise that is resolved with the
* MediaStream object that was set.
*/
async setInputStream(stream) {
try {
if (!this.currentSession
|| !this.currentSession.sessionDescriptionHandler
) return null;
await this.currentSession.sessionDescriptionHandler
.setLocalMediaStream(stream);
this.currentSession.sessionDescriptionHandler.setLocalMediaStream(stream);
return stream;
} catch (error) {
logger.warn({
logCode: 'sip_js_setinputstream_error',
extraInfo: {
errorCode: error.code,
errorMessage: error.message,
callerIdName: this.user.callerIdName,
},
}, 'Failed to set input stream (mic)');
return null;
}
}
/**
* Change the input device with the given deviceId, without renegotiating
* peer.
* A new MediaStream object is created for the given deviceId. This object
* is returned by the resolved promise.
* @param {String} deviceId The id of the device to be set as input
* @return {Promise} A promise that is resolved with the MediaStream
* object after changing the input device.
*/
async liveChangeInputDevice(deviceId) {
try {
this.inputDeviceId = deviceId;
liveChangeInputDevice(deviceId) {
this.inputDeviceId = deviceId;
const constraints = {
audio: this.getAudioConstraints(),
};
const constraints = {
audio: this.getAudioConstraints(),
};
this.inputStream.getAudioTracks().forEach((t) => t.stop());
this.inputStream.getAudioTracks().forEach(t => t.stop());
return navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
this.setInputStream(stream);
});
return await navigator.mediaDevices.getUserMedia(constraints)
.then(this.setInputStream.bind(this));
} catch (error) {
logger.warn({
logCode: 'sip_js_livechangeinputdevice_error',
extraInfo: {
errorCode: error.code,
errorMessage: error.message,
callerIdName: this.user.callerIdName,
},
}, 'Failed to change input device (mic)');
return null;
}
}
get inputDeviceId() {
@ -149,7 +190,7 @@ class SIPSession {
if (stream) {
const track = stream.getAudioTracks().find(
t => t.getSettings().deviceId,
(t) => t.getSettings().deviceId,
);
if (track && (typeof track.getSettings === 'function')) {

View File

@ -62,17 +62,28 @@ class MutedAlert extends Component {
this._isMounted = false;
if (this.speechEvents) this.speechEvents.stop();
if (this.inputStream) {
this.inputStream.getTracks().forEach(t => t.stop());
this.inputStream.getTracks().forEach((t) => t.stop());
}
this.resetTimer();
}
cloneMediaStream() {
if (this.inputStream) return;
const { inputStream, muted } = this.props;
if (inputStream && !muted) this.inputStream = inputStream.clone();
const { inputStream } = this.props;
if (inputStream) {
this.inputStream = inputStream.clone();
this.enableInputStreamAudioTracks(this.inputStream);
}
}
/* eslint-disable no-param-reassign */
enableInputStreamAudioTracks() {
if (!this.inputStream) return;
this.inputStream.getAudioTracks().forEach((t) => { t.enabled = true; });
}
/* eslint-enable no-param-reassign */
resetTimer() {
if (this.timer) clearTimeout(this.timer);
this.timer = null;

View File

@ -67,6 +67,9 @@ class AudioManager {
this.handlePlayElementFailed = this.handlePlayElementFailed.bind(this);
this.monitor = this.monitor.bind(this);
this._inputStream = null;
this._inputStreamTracker = new Tracker.Dependency();
this.BREAKOUT_AUDIO_TRANSFER_STATES = BREAKOUT_AUDIO_TRANSFER_STATES;
}
@ -335,6 +338,7 @@ class AudioManager {
window.parent.postMessage({ response: 'joinedAudio' }, '*');
this.notify(this.intl.formatMessage(this.messages.info.JOINED_AUDIO));
logger.info({ logCode: 'audio_joined' }, 'Audio Joined');
this.inputStream = (this.bridge ? this.bridge.inputStream : null);
if (STATS.enabled) this.monitor();
this.audioEventHandler({
name: 'started',
@ -357,7 +361,8 @@ class AudioManager {
this.failedMediaElements = [];
if (this.inputStream) {
this.inputStream.getTracks().forEach(track => track.stop());
this.inputStream.getTracks().forEach((track) => track.stop());
this.inputStream = null;
this.inputDevice = { id: 'default' };
}
@ -498,11 +503,13 @@ class AudioManager {
}
liveChangeInputDevice(deviceId) {
const handleChangeInputDeviceSuccess = (inputDevice) => {
this.inputDevice = inputDevice;
return Promise.resolve(inputDevice);
};
this.bridge.liveChangeInputDevice(deviceId).then(handleChangeInputDeviceSuccess);
// we force stream to be null, so MutedAlert will deallocate it and
// a new one will be created for the new stream
this.inputStream = null;
this.bridge.liveChangeInputDevice(deviceId).then((stream) => {
this.setSenderTrackEnabled(!this.isMuted);
this.inputStream = stream;
});
}
async changeOutputDevice(deviceId, isLive) {
@ -517,8 +524,19 @@ class AudioManager {
}
get inputStream() {
this._inputDevice.tracker.depend();
return (this.bridge ? this.bridge.inputStream : null);
this._inputStreamTracker.depend();
return this._inputStream;
}
set inputStream(stream) {
// We store reactive information about input stream
// because mutedalert component needs to track when it changes
// and then update hark with the new value for inputStream
if (this._inputStream !== stream) {
this._inputStreamTracker.changed();
}
this._inputStream = stream;
}
get inputDevice() {