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';
|
2023-03-02 21:25:08 +08:00
|
|
|
import { throttle } from '/imports/utils/throttle';
|
2023-08-10 00:06:57 +08:00
|
|
|
import { debounce } from '/imports/utils/debounce';
|
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 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
|
|
|
|
2024-03-07 01:28:18 +08:00
|
|
|
const ROLE_MODERATOR = window.meetingClientSettings.public.user.role_moderator;
|
|
|
|
const TOGGLE_MUTE_THROTTLE_TIME = window.meetingClientSettings.public.media.toggleMuteThrottleTime;
|
|
|
|
const SHOW_VOLUME_METER = window.meetingClientSettings.public.media.showVolumeMeter;
|
2022-04-12 04:18:43 +08:00
|
|
|
const {
|
|
|
|
enabled: LOCAL_ECHO_TEST_ENABLED,
|
|
|
|
initialHearingState: LOCAL_ECHO_INIT_HEARING_STATE,
|
2024-03-07 01:28:18 +08:00
|
|
|
} = window.meetingClientSettings.public.media.localEchoTest;
|
2019-06-29 04:52:19 +08:00
|
|
|
|
2021-02-12 10:55:34 +08:00
|
|
|
const MUTED_KEY = 'muted';
|
|
|
|
|
2024-01-29 20:49:40 +08:00
|
|
|
const recoverMicState = (toggleVoice) => {
|
2021-02-12 10:55:34 +08:00
|
|
|
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}`);
|
2024-05-10 19:52:01 +08:00
|
|
|
toggleVoice(Auth.userID, muted);
|
2021-02-12 10:55:34 +08:00
|
|
|
};
|
|
|
|
|
2024-01-29 20:49:40 +08:00
|
|
|
const audioEventHandler = (toggleVoice) => (event) => {
|
2021-02-12 10:55:34 +08:00
|
|
|
if (!event) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (event.name) {
|
|
|
|
case 'started':
|
2024-01-29 20:49:40 +08:00
|
|
|
if (!event.isListenOnly) recoverMicState(toggleVoice);
|
2021-02-12 10:55:34 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-04-17 06:39:29 +08:00
|
|
|
const init = (messages, intl, toggleVoice, speechLocale) => {
|
2019-02-21 05:58:37 +08:00
|
|
|
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;
|
2024-03-26 19:57:28 +08:00
|
|
|
const Meeting = Meetings.findOne({ meetingId: Auth.meetingID }, { fields: { 'voiceSettings.voiceConf': 1 } });
|
|
|
|
const voiceBridge = Meeting.voiceSettings.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,
|
2024-04-17 06:39:29 +08:00
|
|
|
speechLocale,
|
2017-04-19 23:01:28 +08:00
|
|
|
};
|
|
|
|
|
2024-01-29 20:49:40 +08:00
|
|
|
return AudioManager.init(userData, audioEventHandler(toggleVoice));
|
2017-04-19 23:01:28 +08:00
|
|
|
};
|
2017-04-19 22:59:57 +08:00
|
|
|
|
2024-01-29 20:49:40 +08:00
|
|
|
const muteMicrophone = (toggleVoice) => {
|
2022-10-14 03:23:54 +08:00
|
|
|
const user = VoiceUsers.findOne({
|
2024-03-08 01:20:11 +08:00
|
|
|
userId: Auth.userID,
|
2022-10-14 03:23:54 +08:00
|
|
|
}, { fields: { muted: 1 } });
|
|
|
|
|
|
|
|
if (!user.muted) {
|
|
|
|
logger.info({
|
|
|
|
logCode: 'audiomanager_mute_audio',
|
|
|
|
extraInfo: { logType: 'user_action' },
|
|
|
|
}, 'User wants to leave conference. Microphone muted');
|
|
|
|
AudioManager.setSenderTrackEnabled(false);
|
2024-05-10 19:52:01 +08:00
|
|
|
toggleVoice(Auth.userID, true);
|
2022-10-14 03:23:54 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-08-22 20:05:06 +08:00
|
|
|
const isVoiceUser = () => {
|
2024-03-07 00:08:32 +08:00
|
|
|
const voiceUser = VoiceUsers.findOne({ userId: Auth.userID },
|
2019-08-22 20:05:06 +08:00
|
|
|
{ fields: { joined: 1 } });
|
|
|
|
return voiceUser ? voiceUser.joined : false;
|
|
|
|
};
|
2019-03-13 02:28:41 +08:00
|
|
|
|
2024-01-29 20:49:40 +08:00
|
|
|
const toggleMuteMicrophone = throttle((toggleVoice) => {
|
2019-08-20 08:23:20 +08:00
|
|
|
const user = VoiceUsers.findOne({
|
2024-03-08 01:20:11 +08:00
|
|
|
userId: Auth.userID,
|
2019-07-26 22:35:20 +08:00
|
|
|
}, { 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');
|
2024-05-10 19:52:01 +08:00
|
|
|
toggleVoice(Auth.userID, false);
|
2019-07-26 22:35:20 +08:00
|
|
|
} else {
|
|
|
|
logger.info({
|
|
|
|
logCode: 'audiomanager_mute_audio',
|
|
|
|
extraInfo: { logType: 'user_action' },
|
|
|
|
}, 'microphone muted by user');
|
2024-05-10 19:52:01 +08:00
|
|
|
toggleVoice(Auth.userID, true);
|
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
|
|
|
|
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(),
|
2023-08-10 00:06:57 +08:00
|
|
|
toggleMuteMicrophone: debounce(toggleMuteMicrophone, 500, { leading: true, trailing: false }),
|
2022-04-19 04:05:26 +08:00
|
|
|
changeInputDevice: (inputDeviceId) => AudioManager.changeInputDevice(inputDeviceId),
|
|
|
|
changeInputStream: (newInputStream) => { AudioManager.inputStream = newInputStream; },
|
|
|
|
liveChangeInputDevice: (inputDeviceId) => AudioManager.liveChangeInputDevice(inputDeviceId),
|
2022-08-20 01:22:42 +08:00
|
|
|
changeOutputDevice: (outputDeviceId, isLive) => AudioManager.changeOutputDevice(outputDeviceId, isLive),
|
2023-07-13 23:40:46 +08:00
|
|
|
isConnectedToBreakout: () => {
|
|
|
|
const transferStatus = AudioManager.getBreakoutAudioTransferStatus();
|
|
|
|
if (transferStatus.status
|
|
|
|
=== AudioManager.BREAKOUT_AUDIO_TRANSFER_STATES.CONNECTED) return true;
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
isConnected: () => {
|
|
|
|
const transferStatus = AudioManager.getBreakoutAudioTransferStatus();
|
|
|
|
if (!!transferStatus.breakoutMeetingId
|
|
|
|
&& transferStatus.breakoutMeetingId !== Auth.meetingID) return false;
|
|
|
|
return 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 },
|
2023-03-15 04:39:06 +08:00
|
|
|
{ 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(),
|
2022-04-19 04:05:26 +08:00
|
|
|
playAlertSound: (url) => AudioManager.playAlertSound(url),
|
2021-01-23 03:30:42 +08:00
|
|
|
updateAudioConstraints:
|
2022-04-19 04:05:26 +08:00
|
|
|
(constraints) => AudioManager.updateAudioConstraints(constraints),
|
2021-02-26 02:36:11 +08:00
|
|
|
recoverMicState,
|
2024-01-29 20:49:40 +08:00
|
|
|
muteMicrophone: (toggleVoice) => muteMicrophone(toggleVoice),
|
2021-02-27 02:05:17 +08:00
|
|
|
isReconnecting: () => AudioManager.isReconnecting,
|
2022-04-19 04:05:26 +08:00
|
|
|
setBreakoutAudioTransferStatus: (status) => AudioManager
|
2021-03-08 02:01:12 +08:00
|
|
|
.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-12 04:18:43 +08:00
|
|
|
localEchoEnabled: LOCAL_ECHO_TEST_ENABLED,
|
|
|
|
localEchoInitHearingState: LOCAL_ECHO_INIT_HEARING_STATE,
|
2022-04-05 05:09:35 +08:00
|
|
|
showVolumeMeter: SHOW_VOLUME_METER,
|
2022-08-20 01:22:42 +08:00
|
|
|
notify: (message, error, icon) => { AudioManager.notify(message, error, icon); },
|
2017-09-29 21:42:08 +08:00
|
|
|
};
|