bigbluebutton-Github/bigbluebutton-html5/imports/ui/services/audio-manager/index.js

259 lines
6.2 KiB
JavaScript
Raw Normal View History

import { Tracker } from 'meteor/tracker';
2017-09-29 21:38:10 +08:00
import { makeCall } from '/imports/ui/services/api';
import VertoBridge from '/imports/api/2.0/audio/client/bridge/verto';
import SIPBridge from '/imports/api/2.0/audio/client/bridge/sip';
2017-09-29 21:38:10 +08:00
const USE_SIP = Meteor.settings.public.media.useSIPAudio;
2017-10-05 04:49:11 +08:00
const ERROR_CODES = {
REQUEST_TIMEOUT: {
message: 'Request Timeout',
},
CONNECTION_ERROR: {
message: 'Connection Error',
},
ERROR: {
message: 'An Error Occurred',
},
2017-09-29 21:38:10 +08:00
};
const OUTPUT_TAG = '#remote-media';
const CALL_STATES = {
2017-10-05 04:49:11 +08:00
STARTED: 'started',
ENDED: 'ended',
FAILED: 'failed',
};
class AudioManager {
constructor() {
2017-09-30 04:42:34 +08:00
this._inputDevice = {
tracker: new Tracker.Dependency,
};
2017-10-04 04:42:10 +08:00
navigator.mediaDevices
.getUserMedia({ audio: true })
.then((stream) => {
const deviceLabel = stream.getAudioTracks()[0].label;
navigator.mediaDevices.enumerateDevices().then(devices => {
const device = devices.find(device => device.label === deviceLabel);
this.changeInputDevice(device.deviceId);
})
});
this.defineProperties({
isMuted: false,
isConnected: false,
isConnecting: false,
2017-09-29 21:38:10 +08:00
isListenOnly: false,
isEchoTest: false,
error: null,
outputDeviceId: null,
});
}
defineProperties(obj) {
2017-09-29 21:38:10 +08:00
Object.keys(obj).forEach((key) => {
const privateKey = `_${key}`;
this[privateKey] = {
value: obj[key],
2017-09-29 21:58:13 +08:00
tracker: new Tracker.Dependency,
2017-09-29 21:38:10 +08:00
};
Object.defineProperty(this, key, {
set: (value) => {
2017-09-29 21:38:10 +08:00
this[privateKey].value = value;
this[privateKey].tracker.changed();
},
get: () => {
2017-09-29 21:38:10 +08:00
this[privateKey].tracker.depend();
return this[privateKey].value;
},
});
});
}
2017-09-29 21:38:10 +08:00
joinAudio(options = {}, callbacks = {}) {
const {
isListenOnly,
isEchoTest,
} = options;
console.log('joinAudio', this, isListenOnly);
this.isConnecting = true;
2017-09-29 21:38:10 +08:00
this.isListenOnly = isListenOnly;
this.isEchoTest = isEchoTest;
this.callbacks = callbacks;
const callOptions = {
isListenOnly,
2017-09-30 04:42:34 +08:00
extension: isEchoTest ? '9196' : null,
2017-10-05 04:49:11 +08:00
inputStream: isListenOnly ? this.createListenOnlyStream() : this.inputStream,
2017-09-29 21:58:13 +08:00
}
2017-09-29 21:38:10 +08:00
2017-10-05 04:49:11 +08:00
console.log(callOptions.inputStream);
2017-09-30 04:42:34 +08:00
console.log(this.inputDeviceId);
return this.bridge.joinAudio(callOptions, this.callStateCallback.bind(this));
}
exitAudio() {
console.log('exitAudio', this);
2017-09-29 21:58:13 +08:00
return this.bridge.exitAudio()
}
toggleMuteMicrophone() {
console.log('toggleMuteMicrophone', this);
2017-10-05 04:49:11 +08:00
makeCall('toggleSelfVoice').then((res) => {
console.log(res);
this.onToggleMicrophoneMute();
});
}
2017-09-29 21:38:10 +08:00
callbackToAudioBridge(message) {
console.log('This is the Manager Callback', message);
}
//----------------------------
onAudioJoin() {
2017-09-29 21:38:10 +08:00
if (!this.isEchoTest) {
this.isConnected = true;
}
this.isConnecting = false;
2017-09-29 21:38:10 +08:00
if (this.isListenOnly) {
makeCall('listenOnlyToggle', true);
}
console.log('onAudioJoin', this);
}
onAudioExit() {
this.isConnected = false;
2017-10-05 04:49:11 +08:00
this.isConnecting = false;
2017-09-29 21:38:10 +08:00
if (this.isListenOnly) {
makeCall('listenOnlyToggle', false);
} else if (this.isEchoTest) {
this.isEchoTest = false;
}
console.log('onAudioExit', this);
}
onToggleMicrophoneMute() {
this.isMuted = !this.isMuted;
console.log('onToggleMicrophoneMute', this);
}
//---------------------------
// update(key, value) {
// const query = { _id: this.stateId };
// const modifier = { $set: { [key]: value }};
// collection.update(query, modifier);
// }
2017-09-29 21:38:10 +08:00
2017-10-05 04:49:11 +08:00
callStateCallback(response) {
2017-09-29 21:38:10 +08:00
return new Promise((resolve) => {
const {
2017-10-05 04:49:11 +08:00
STARTED,
ENDED,
FAILED,
} = CALL_STATES;
2017-09-29 21:38:10 +08:00
2017-10-05 04:49:11 +08:00
const {
status,
error,
} = response;
console.log('CALLSTATECALLBACK =====================', response);
if (status === STARTED) {
2017-09-29 21:38:10 +08:00
this.onAudioJoin();
2017-10-05 04:49:11 +08:00
resolve(STARTED);
} else if (status === ENDED) {
console.log('ENDED');
2017-09-29 21:38:10 +08:00
this.onAudioExit();
2017-10-05 04:49:11 +08:00
} else if (status === FAILED) {
console.log('FAILED');
2017-09-29 21:38:10 +08:00
this.onAudioExit();
}
2017-09-29 21:58:13 +08:00
})
2017-09-29 21:38:10 +08:00
}
set userData(value) {
console.log('set user data');
this._userData = value;
this.bridge = USE_SIP ? new SIPBridge(value) : new VertoBridge(value);
}
get userData() {
return this._userData;
}
2017-09-30 04:42:34 +08:00
2017-10-05 04:49:11 +08:00
createListenOnlyStream() {
if (this.listenOnlyAudioContext) {
this.listenOnlyAudioContext.close();
}
this.listenOnlyAudioContext = new window.AudioContext;
return this.listenOnlyAudioContext.createMediaStreamDestination().stream;
}
2017-09-30 04:42:34 +08:00
changeInputDevice(value) {
if(this._inputDevice.audioContext) {
this._inputDevice.audioContext.close().then(() => {
this._inputDevice.audioContext = null;
this._inputDevice.scriptProcessor = null;
this._inputDevice.source = null;
this.changeInputDevice(value);
});
return;
}
console.log(value);
this._inputDevice.id = value;
this._inputDevice.audioContext = new AudioContext();
this._inputDevice.scriptProcessor = this._inputDevice.audioContext.createScriptProcessor(2048, 1, 1);
this._inputDevice.source = null;
const constraints = {
audio: {
deviceId: value,
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
console.log('KAPPA', stream);
this._inputDevice.stream = stream
this._inputDevice.source = this._inputDevice.audioContext.createMediaStreamSource(stream);
this._inputDevice.source.connect(this._inputDevice.scriptProcessor);
2017-10-04 04:42:10 +08:00
this._inputDevice.scriptProcessor.connect(this._inputDevice.audioContext.destination);
this._inputDevice.tracker.changed();
2017-09-30 04:42:34 +08:00
});
}
changeOutputDevice(deviceId) {
this.outputDeviceId = deviceId;
document.querySelector(OUTPUT_TAG).setSinkId(deviceId);
console.log('Change id');
}
2017-09-30 04:42:34 +08:00
get inputStream () {
return this._inputDevice.stream;
}
get inputDeviceId () {
2017-10-04 04:42:10 +08:00
this._inputDevice.tracker.depend();
2017-09-30 04:42:34 +08:00
return this._inputDevice.id;
}
}
const audioManager = new AudioManager();
export default audioManager;