2017-10-12 10:00:28 +08:00
|
|
|
import Users from '/imports/api/users';
|
2017-04-19 23:01:28 +08:00
|
|
|
import Auth from '/imports/ui/services/auth';
|
2021-01-30 04:58:05 +08:00
|
|
|
import { debounce, throttle } from 'lodash';
|
2017-10-13 03:22:10 +08:00
|
|
|
import AudioManager from '/imports/ui/services/audio-manager';
|
2017-10-12 10:00:28 +08:00
|
|
|
import Meetings from '/imports/api/meetings';
|
2019-07-26 02:41:24 +08:00
|
|
|
import { makeCall } from '/imports/ui/services/api';
|
|
|
|
import VoiceUsers from '/imports/api/voice-users';
|
|
|
|
import logger from '/imports/startup/client/logger';
|
2021-02-12 10:55:34 +08:00
|
|
|
import Storage from '../../services/storage/session';
|
2017-03-28 22:02:23 +08:00
|
|
|
|
2019-06-29 04:52:19 +08:00
|
|
|
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
2021-01-26 09:41:26 +08:00
|
|
|
const TOGGLE_MUTE_THROTTLE_TIME = Meteor.settings.public.media.toggleMuteThrottleTime;
|
2022-04-05 05:09:35 +08:00
|
|
|
const SIMPLIFIED_ECHO_TEST = Meteor.settings.public.media.simplifiedEchoTest;
|
|
|
|
const SHOW_VOLUME_METER = Meteor.settings.public.media.showVolumeMeterInSettings;
|
2019-06-29 04:52:19 +08:00
|
|
|
|
2021-02-12 10:55:34 +08:00
|
|
|
const MUTED_KEY = 'muted';
|
|
|
|
|
|
|
|
const recoverMicState = () => {
|
|
|
|
const muted = Storage.getItem(MUTED_KEY);
|
|
|
|
|
|
|
|
if ((muted === undefined) || (muted === null)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.debug({
|
|
|
|
logCode: 'audio_recover_mic_state',
|
|
|
|
}, `Audio recover previous mic state: muted = ${muted}`);
|
|
|
|
makeCall('toggleVoice', null, muted);
|
|
|
|
};
|
|
|
|
|
|
|
|
const audioEventHandler = (event) => {
|
|
|
|
if (!event) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (event.name) {
|
|
|
|
case 'started':
|
2021-02-27 02:52:11 +08:00
|
|
|
if (!event.isListenOnly) recoverMicState();
|
2021-02-12 10:55:34 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-02-21 05:58:37 +08:00
|
|
|
const init = (messages, intl) => {
|
|
|
|
AudioManager.setAudioMessages(messages, intl);
|
2021-11-10 02:04:10 +08:00
|
|
|
if (AudioManager.initialized) return Promise.resolve(false);
|
2017-10-12 20:50:23 +08:00
|
|
|
const meetingId = Auth.meetingID;
|
2017-04-19 23:01:28 +08:00
|
|
|
const userId = Auth.userID;
|
2018-03-06 04:00:52 +08:00
|
|
|
const { sessionToken } = Auth;
|
2019-08-22 20:05:06 +08:00
|
|
|
const User = Users.findOne({ userId }, { fields: { name: 1 } });
|
2017-07-26 22:31:35 +08:00
|
|
|
const username = User.name;
|
2019-08-22 20:05:06 +08:00
|
|
|
const Meeting = Meetings.findOne({ meetingId: Auth.meetingID }, { fields: { 'voiceProp.voiceConf': 1 } });
|
2017-07-18 22:59:05 +08:00
|
|
|
const voiceBridge = Meeting.voiceProp.voiceConf;
|
2017-04-19 23:01:28 +08:00
|
|
|
|
2017-07-13 02:51:29 +08:00
|
|
|
// FIX ME
|
2017-07-18 22:59:05 +08:00
|
|
|
const microphoneLockEnforced = false;
|
2017-04-19 22:59:57 +08:00
|
|
|
|
2017-04-19 23:01:28 +08:00
|
|
|
const userData = {
|
2017-10-12 20:50:23 +08:00
|
|
|
meetingId,
|
2017-04-19 23:01:28 +08:00
|
|
|
userId,
|
2017-09-29 21:38:10 +08:00
|
|
|
sessionToken,
|
2017-04-19 23:01:28 +08:00
|
|
|
username,
|
|
|
|
voiceBridge,
|
2017-05-04 04:12:47 +08:00
|
|
|
microphoneLockEnforced,
|
2017-04-19 23:01:28 +08:00
|
|
|
};
|
|
|
|
|
2021-11-10 02:04:10 +08:00
|
|
|
return AudioManager.init(userData, audioEventHandler);
|
2017-04-19 23:01:28 +08:00
|
|
|
};
|
2017-04-19 22:59:57 +08:00
|
|
|
|
2019-08-22 20:05:06 +08:00
|
|
|
const isVoiceUser = () => {
|
|
|
|
const voiceUser = VoiceUsers.findOne({ intId: Auth.userID },
|
|
|
|
{ fields: { joined: 1 } });
|
|
|
|
return voiceUser ? voiceUser.joined : false;
|
|
|
|
};
|
2019-03-13 02:28:41 +08:00
|
|
|
|
2021-01-26 09:41:26 +08:00
|
|
|
const toggleMuteMicrophone = throttle(() => {
|
2019-08-20 08:23:20 +08:00
|
|
|
const user = VoiceUsers.findOne({
|
2019-07-26 22:35:20 +08:00
|
|
|
meetingId: Auth.meetingID, intId: Auth.userID,
|
|
|
|
}, { fields: { muted: 1 } });
|
2021-02-12 10:55:34 +08:00
|
|
|
|
|
|
|
Storage.setItem(MUTED_KEY, !user.muted);
|
|
|
|
|
2019-08-20 08:23:20 +08:00
|
|
|
if (user.muted) {
|
2019-07-26 22:35:20 +08:00
|
|
|
logger.info({
|
|
|
|
logCode: 'audiomanager_unmute_audio',
|
|
|
|
extraInfo: { logType: 'user_action' },
|
|
|
|
}, 'microphone unmuted by user');
|
2020-02-14 03:19:29 +08:00
|
|
|
makeCall('toggleVoice');
|
2019-07-26 22:35:20 +08:00
|
|
|
} else {
|
|
|
|
logger.info({
|
|
|
|
logCode: 'audiomanager_mute_audio',
|
|
|
|
extraInfo: { logType: 'user_action' },
|
|
|
|
}, 'microphone muted by user');
|
2020-02-14 03:19:29 +08:00
|
|
|
makeCall('toggleVoice');
|
2019-07-26 02:41:24 +08:00
|
|
|
}
|
2021-01-26 09:41:26 +08:00
|
|
|
}, TOGGLE_MUTE_THROTTLE_TIME);
|
2019-07-26 02:41:24 +08:00
|
|
|
|
2020-02-07 04:20:42 +08:00
|
|
|
|
2017-05-03 01:18:01 +08:00
|
|
|
export default {
|
2017-04-19 22:59:57 +08:00
|
|
|
init,
|
2017-09-20 01:47:57 +08:00
|
|
|
exitAudio: () => AudioManager.exitAudio(),
|
2021-12-03 19:45:07 +08:00
|
|
|
forceExitAudio: () => AudioManager.forceExitAudio(),
|
2017-10-12 20:50:23 +08:00
|
|
|
transferCall: () => AudioManager.transferCall(),
|
2018-03-16 02:57:25 +08:00
|
|
|
joinListenOnly: () => AudioManager.joinListenOnly(),
|
|
|
|
joinMicrophone: () => AudioManager.joinMicrophone(),
|
|
|
|
joinEchoTest: () => AudioManager.joinEchoTest(),
|
2020-02-07 04:20:42 +08:00
|
|
|
toggleMuteMicrophone: debounce(toggleMuteMicrophone, 500, { leading: true, trailing: false }),
|
2017-10-11 02:03:29 +08:00
|
|
|
changeInputDevice: inputDeviceId => AudioManager.changeInputDevice(inputDeviceId),
|
2020-07-28 03:49:26 +08:00
|
|
|
liveChangeInputDevice: inputDeviceId => AudioManager.liveChangeInputDevice(inputDeviceId),
|
2021-03-17 22:30:07 +08:00
|
|
|
changeOutputDevice: (outputDeviceId, isLive) => {
|
2020-03-04 01:22:26 +08:00
|
|
|
if (AudioManager.outputDeviceId !== outputDeviceId) {
|
2021-03-17 22:30:07 +08:00
|
|
|
AudioManager.changeOutputDevice(outputDeviceId, isLive);
|
2020-03-04 01:22:26 +08:00
|
|
|
}
|
|
|
|
},
|
2017-09-20 01:47:57 +08:00
|
|
|
isConnected: () => AudioManager.isConnected,
|
2018-06-20 23:36:26 +08:00
|
|
|
isTalking: () => AudioManager.isTalking,
|
2017-10-27 01:14:56 +08:00
|
|
|
isHangingUp: () => AudioManager.isHangingUp,
|
2018-06-20 23:36:26 +08:00
|
|
|
isUsingAudio: () => AudioManager.isUsingAudio(),
|
2017-11-09 02:41:15 +08:00
|
|
|
isWaitingPermissions: () => AudioManager.isWaitingPermissions,
|
2017-09-20 01:47:57 +08:00
|
|
|
isMuted: () => AudioManager.isMuted,
|
|
|
|
isConnecting: () => AudioManager.isConnecting,
|
|
|
|
isListenOnly: () => AudioManager.isListenOnly,
|
|
|
|
inputDeviceId: () => AudioManager.inputDeviceId,
|
|
|
|
outputDeviceId: () => AudioManager.outputDeviceId,
|
2017-09-29 21:38:10 +08:00
|
|
|
isEchoTest: () => AudioManager.isEchoTest,
|
2017-10-11 20:05:57 +08:00
|
|
|
error: () => AudioManager.error,
|
2019-08-30 00:26:07 +08:00
|
|
|
isUserModerator: () => Users.findOne({ userId: Auth.userID },
|
|
|
|
{ fields: { role: 1 } }).role === ROLE_MODERATOR,
|
2019-08-22 20:05:06 +08:00
|
|
|
isVoiceUser,
|
2019-08-03 05:32:42 +08:00
|
|
|
autoplayBlocked: () => AudioManager.autoplayBlocked,
|
|
|
|
handleAllowAutoplay: () => AudioManager.handleAllowAutoplay(),
|
Correctly set audio input/output devices
When refusing ("thumbs down" button) echo test, user is able to select a different input device. This should work fine for chrome, firefox and safari (once user grants permission when asked by html5client).
For output devices, we depend on setSinkId function, which is enabled by default on current chrome release (2020) but not in Firefox (user needs to enable "setSinkId in about:config page). This implementation is listed as (?) in MDN.
In other words, output device selection should work out of the box for chrome, only.
When selecting an outputDevice, all alert sounds (hangup, screenshare , polling, etc) also goes to the same output device.
This solves #10592
2020-10-07 07:37:55 +08:00
|
|
|
playAlertSound: url => AudioManager.playAlertSound(url),
|
2021-01-23 03:30:42 +08:00
|
|
|
updateAudioConstraints:
|
|
|
|
constraints => AudioManager.updateAudioConstraints(constraints),
|
2021-02-26 02:36:11 +08:00
|
|
|
recoverMicState,
|
2021-02-27 02:05:17 +08:00
|
|
|
isReconnecting: () => AudioManager.isReconnecting,
|
2021-03-08 02:01:12 +08:00
|
|
|
setBreakoutAudioTransferStatus: status => AudioManager
|
|
|
|
.setBreakoutAudioTransferStatus(status),
|
2021-03-07 09:09:43 +08:00
|
|
|
getBreakoutAudioTransferStatus: () => AudioManager
|
|
|
|
.getBreakoutAudioTransferStatus(),
|
2021-08-13 03:39:04 +08:00
|
|
|
getStats: () => AudioManager.getStats(),
|
2022-04-05 05:09:35 +08:00
|
|
|
simplifiedEchoTestEnabled: SIMPLIFIED_ECHO_TEST,
|
|
|
|
showVolumeMeter: SHOW_VOLUME_METER,
|
2017-09-29 21:42:08 +08:00
|
|
|
};
|