bigbluebutton-Github/bigbluebutton-html5/imports/api/audio/client/bridge/base.js

136 lines
3.8 KiB
JavaScript
Raw Normal View History

import logger from '/imports/startup/client/logger';
import {
getAudioConstraints,
doGUM,
} from '/imports/api/audio/client/bridge/service';
const BASE_BRIDGE_NAME = 'base';
2017-07-24 22:15:46 +08:00
export default class BaseAudioBridge {
2017-10-12 05:04:10 +08:00
constructor(userData) {
this.userData = userData;
this.baseErrorCodes = {
INVALID_TARGET: 'INVALID_TARGET',
CONNECTION_ERROR: 'CONNECTION_ERROR',
REQUEST_TIMEOUT: 'REQUEST_TIMEOUT',
GENERIC_ERROR: 'GENERIC_ERROR',
2017-10-27 01:14:56 +08:00
MEDIA_ERROR: 'MEDIA_ERROR',
2018-06-27 21:56:03 +08:00
WEBRTC_NOT_SUPPORTED: 'WEBRTC_NOT_SUPPORTED',
2018-06-29 02:14:35 +08:00
ICE_NEGOTIATION_FAILED: 'ICE_NEGOTIATION_FAILED',
2017-10-12 05:04:10 +08:00
};
this.baseCallStates = {
started: 'started',
ended: 'ended',
failed: 'failed',
reconnecting: 'reconnecting',
autoplayBlocked: 'autoplayBlocked',
2017-10-12 05:04:10 +08:00
};
this.bridgeName = BASE_BRIDGE_NAME;
2017-07-24 22:15:46 +08:00
}
getPeerConnection() {
console.error('The Bridge must implement getPeerConnection');
}
2017-07-24 22:15:46 +08:00
exitAudio() {
2017-10-12 05:04:10 +08:00
console.error('The Bridge must implement exitAudio');
2017-07-24 22:15:46 +08:00
}
2017-09-29 21:38:10 +08:00
joinAudio() {
2017-10-12 05:04:10 +08:00
console.error('The Bridge must implement joinAudio');
2017-07-24 22:15:46 +08:00
}
changeInputDevice() {
console.error('The Bridge must implement changeInputDevice');
}
setInputStream() {
console.error('The Bridge must implement setInputStream');
}
sendDtmf() {
console.error('The Bridge must implement sendDtmf');
}
set inputDeviceId (deviceId) {
this._inputDeviceId = deviceId;
}
get inputDeviceId () {
return this._inputDeviceId;
}
/**
* 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) {
let newStream;
let backupStream;
try {
const constraints = {
audio: getAudioConstraints({ deviceId }),
};
// Backup stream (current one) in case the switch fails
if (this.inputStream && this.inputStream.active) {
backupStream = this.inputStream ? this.inputStream.clone() : null;
this.inputStream.getAudioTracks().forEach((track) => track.stop());
}
newStream = await doGUM(constraints);
await this.setInputStream(newStream);
if (backupStream && backupStream.active) {
backupStream.getAudioTracks().forEach((track) => track.stop());
backupStream = null;
}
return newStream;
} catch (error) {
// Device change failed. Clean up the tentative new stream to avoid lingering
// stuff, then try to rollback to the previous input stream.
if (newStream && typeof newStream.getAudioTracks === 'function') {
newStream.getAudioTracks().forEach((t) => t.stop());
newStream = null;
}
// Rollback to backup stream
if (backupStream && backupStream.active) {
this.setInputStream(backupStream).catch((rollbackError) => {
logger.error({
logCode: 'audio_changeinputdevice_rollback_failure',
extraInfo: {
bridgeName: this.bridgeName,
deviceId,
errorName: rollbackError.name,
errorMessage: rollbackError.message,
},
}, 'Microphone device change rollback failed - the device may become silent');
backupStream.getAudioTracks().forEach((track) => track.stop());
backupStream = null;
});
}
throw error;
}
}
trackTransferState(transferCallback) {
2024-04-23 10:20:45 +08:00
return new Promise((resolve) => {
transferCallback();
resolve();
});
}
2017-07-24 22:15:46 +08:00
}