2017-09-20 01:47:57 +08:00
|
|
|
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-20 01:47:57 +08:00
|
|
|
|
2017-09-29 21:38:10 +08:00
|
|
|
const USE_SIP = Meteor.settings.public.media.useSIPAudio;
|
2017-09-20 01:47:57 +08:00
|
|
|
|
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
|
|
|
};
|
2017-09-20 01:47:57 +08:00
|
|
|
|
2017-10-10 04:48: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',
|
|
|
|
};
|
2017-09-20 01:47:57 +08:00
|
|
|
|
|
|
|
class AudioManager {
|
|
|
|
constructor() {
|
2017-09-30 04:42:34 +08:00
|
|
|
this._inputDevice = {
|
2017-10-11 02:03:29 +08:00
|
|
|
tracker: new Tracker.Dependency(),
|
2017-09-30 04:42:34 +08:00
|
|
|
};
|
|
|
|
|
2017-10-04 04:42:10 +08:00
|
|
|
navigator.mediaDevices
|
|
|
|
.getUserMedia({ audio: true })
|
|
|
|
.then((stream) => {
|
|
|
|
const deviceLabel = stream.getAudioTracks()[0].label;
|
2017-10-11 02:03:29 +08:00
|
|
|
navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
|
|
const device = devices.find(d => d.label === deviceLabel);
|
2017-10-04 04:42:10 +08:00
|
|
|
this.changeInputDevice(device.deviceId);
|
2017-10-11 02:03:29 +08:00
|
|
|
});
|
2017-10-11 20:05:57 +08:00
|
|
|
}).catch((err) => { this.error = err; });
|
2017-10-04 04:42:10 +08:00
|
|
|
|
2017-10-10 04:48:10 +08:00
|
|
|
|
2017-09-20 01:47:57 +08:00
|
|
|
this.defineProperties({
|
|
|
|
isMuted: false,
|
|
|
|
isConnected: false,
|
|
|
|
isConnecting: false,
|
2017-09-29 21:38:10 +08:00
|
|
|
isListenOnly: false,
|
|
|
|
isEchoTest: false,
|
2017-09-20 01:47:57 +08:00
|
|
|
error: null,
|
2017-10-10 04:48:10 +08:00
|
|
|
outputDeviceId: null,
|
2017-09-20 01:47:57 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
defineProperties(obj) {
|
2017-09-29 21:38:10 +08:00
|
|
|
Object.keys(obj).forEach((key) => {
|
|
|
|
const privateKey = `_${key}`;
|
|
|
|
this[privateKey] = {
|
2017-09-20 01:47:57 +08:00
|
|
|
value: obj[key],
|
2017-10-11 02:03:29 +08:00
|
|
|
tracker: new Tracker.Dependency(),
|
2017-09-29 21:38:10 +08:00
|
|
|
};
|
2017-09-20 01:47:57 +08:00
|
|
|
|
|
|
|
Object.defineProperty(this, key, {
|
|
|
|
set: (value) => {
|
2017-09-29 21:38:10 +08:00
|
|
|
this[privateKey].value = value;
|
|
|
|
this[privateKey].tracker.changed();
|
2017-09-20 01:47:57 +08:00
|
|
|
},
|
|
|
|
get: () => {
|
2017-09-29 21:38:10 +08:00
|
|
|
this[privateKey].tracker.depend();
|
|
|
|
return this[privateKey].value;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
2017-09-20 01:47:57 +08:00
|
|
|
}
|
|
|
|
|
2017-10-11 02:03:29 +08:00
|
|
|
init(userData) {
|
|
|
|
console.log('init', userData);
|
|
|
|
this.bridge = USE_SIP ? new SIPBridge(userData) : new VertoBridge(userData);
|
|
|
|
this.userData = userData;
|
|
|
|
}
|
|
|
|
|
2017-09-29 21:38:10 +08:00
|
|
|
joinAudio(options = {}, callbacks = {}) {
|
|
|
|
const {
|
|
|
|
isListenOnly,
|
|
|
|
isEchoTest,
|
|
|
|
} = options;
|
|
|
|
|
2017-09-20 01:47:57 +08:00
|
|
|
console.log('joinAudio', this, isListenOnly);
|
|
|
|
this.isConnecting = true;
|
2017-10-11 20:05:57 +08:00
|
|
|
this.error = null;
|
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));
|
2017-09-20 01:47:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
exitAudio() {
|
|
|
|
console.log('exitAudio', this);
|
2017-09-29 21:58:13 +08:00
|
|
|
return this.bridge.exitAudio()
|
2017-09-20 01:47:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
toggleMuteMicrophone() {
|
|
|
|
console.log('toggleMuteMicrophone', this);
|
2017-10-05 04:49:11 +08:00
|
|
|
makeCall('toggleSelfVoice').then((res) => {
|
|
|
|
console.log(res);
|
|
|
|
this.onToggleMicrophoneMute();
|
|
|
|
});
|
2017-09-20 01:47:57 +08:00
|
|
|
}
|
|
|
|
|
2017-09-29 21:38:10 +08:00
|
|
|
callbackToAudioBridge(message) {
|
|
|
|
console.log('This is the Manager Callback', message);
|
|
|
|
}
|
|
|
|
|
2017-09-20 01:47:57 +08:00
|
|
|
//----------------------------
|
|
|
|
|
|
|
|
onAudioJoin() {
|
2017-09-29 21:38:10 +08:00
|
|
|
if (!this.isEchoTest) {
|
|
|
|
this.isConnected = true;
|
|
|
|
}
|
2017-09-20 01:47:57 +08:00
|
|
|
this.isConnecting = false;
|
2017-09-29 21:38:10 +08:00
|
|
|
|
|
|
|
if (this.isListenOnly) {
|
|
|
|
makeCall('listenOnlyToggle', true);
|
|
|
|
}
|
|
|
|
|
2017-09-20 01:47:57 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-09-20 01:47:57 +08:00
|
|
|
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) {
|
2017-10-11 20:05:57 +08:00
|
|
|
console.log(error, 'KAAAAPPAAA');
|
|
|
|
this.error = ERROR_CODES[error].message;
|
2017-10-05 04:49:11 +08:00
|
|
|
console.log('FAILED');
|
2017-09-29 21:38:10 +08:00
|
|
|
this.onAudioExit();
|
|
|
|
}
|
2017-10-11 20:05:57 +08:00
|
|
|
});
|
2017-09-29 21:38:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
set userData(value) {
|
|
|
|
this._userData = 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();
|
|
|
|
}
|
|
|
|
|
2017-10-10 05:23:05 +08:00
|
|
|
if ('webkitAudioContext' in window) {
|
|
|
|
this.listenOnlyAudioContext = new window.webkitAudioContext();
|
|
|
|
} else {
|
|
|
|
this.listenOnlyAudioContext = new window.AudioContext();
|
|
|
|
}
|
|
|
|
|
2017-10-05 04:49:11 +08:00
|
|
|
return this.listenOnlyAudioContext.createMediaStreamDestination().stream;
|
|
|
|
}
|
|
|
|
|
2017-09-30 04:42:34 +08:00
|
|
|
changeInputDevice(value) {
|
2017-10-11 02:03:29 +08:00
|
|
|
console.log('changeInputDevice');
|
2017-10-10 05:23:05 +08:00
|
|
|
if (this._inputDevice.audioContext) {
|
2017-09-30 04:42:34 +08:00
|
|
|
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;
|
2017-10-10 05:23:05 +08:00
|
|
|
if ('webkitAudioContext' in window) {
|
|
|
|
this._inputDevice.audioContext = new window.webkitAudioContext();
|
|
|
|
} else {
|
|
|
|
this._inputDevice.audioContext = new AudioContext();
|
|
|
|
}
|
|
|
|
this._inputDevice.scriptProcessor = this._inputDevice.audioContext
|
|
|
|
.createScriptProcessor(2048, 1, 1);
|
2017-09-30 04:42:34 +08:00
|
|
|
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
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-10 04:48:10 +08:00
|
|
|
changeOutputDevice(deviceId) {
|
|
|
|
this.outputDeviceId = deviceId;
|
|
|
|
document.querySelector(OUTPUT_TAG).setSinkId(deviceId);
|
|
|
|
console.log('Change id');
|
|
|
|
}
|
|
|
|
|
2017-10-11 02:03:29 +08:00
|
|
|
get inputStream() {
|
2017-09-30 04:42:34 +08:00
|
|
|
return this._inputDevice.stream;
|
|
|
|
}
|
|
|
|
|
2017-10-11 02:03:29 +08:00
|
|
|
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;
|
|
|
|
}
|
2017-09-20 01:47:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const audioManager = new AudioManager();
|
|
|
|
export default audioManager;
|