Merge pull request #4117 from Klauswk/html5-2x-fix-audio
[HTML5 2.0] Fix join audio on the HTML5 client 2.0
This commit is contained in:
commit
1bdeb248c1
@ -13,18 +13,18 @@ export default class SIPBridge extends BaseAudioBridge {
|
||||
this.userData = userData;
|
||||
}
|
||||
|
||||
joinListenOnly() {
|
||||
joinListenOnly(stunServers, turnServers) {
|
||||
makeCall('listenOnlyToggle', true);
|
||||
this._joinVoiceCallSIP({ isListenOnly: true });
|
||||
this._joinVoiceCallSIP({ isListenOnly: true, stunServers, turnServers });
|
||||
}
|
||||
|
||||
joinMicrophone() {
|
||||
this._joinVoiceCallSIP({ isListenOnly: false });
|
||||
joinMicrophone(stunServers, turnServers) {
|
||||
this._joinVoiceCallSIP({ isListenOnly: false, stunServers, turnServers });
|
||||
}
|
||||
|
||||
// Periodically check the status of the WebRTC call, when a call has been established attempt to
|
||||
// hangup, retry if a call is in progress, send the leave voice conference message to BBB
|
||||
exitAudio(isListenOnly, afterExitCall = () => {}) {
|
||||
exitAudio(isListenOnly, afterExitCall = () => { }) {
|
||||
// To be called when the hangup is confirmed
|
||||
const hangupCallback = function () {
|
||||
console.log(`Exited Voice Conference, listenOnly=${isListenOnly}`);
|
||||
@ -40,7 +40,7 @@ export default class SIPBridge extends BaseAudioBridge {
|
||||
triedHangup = false;
|
||||
|
||||
// function to initiate call
|
||||
const checkToHangupCall = ((context, afterExitCall = () => {}) => {
|
||||
const checkToHangupCall = ((context, afterExitCall = () => { }) => {
|
||||
// if an attempt to hang up the call is made when the current session is not yet finished,
|
||||
// the request has no effect keep track in the session if we haven't tried a hangup
|
||||
if (window.getCallStatus() != null && !triedHangup) {
|
||||
@ -96,8 +96,8 @@ export default class SIPBridge extends BaseAudioBridge {
|
||||
};
|
||||
|
||||
const stunsAndTurns = {
|
||||
stun: this.userData.stuns,
|
||||
turn: this.userData.turns,
|
||||
stun: options.stunServers,
|
||||
turn: options.turnServers,
|
||||
};
|
||||
|
||||
callIntoConference(extension, (audio) => {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import BaseAudioBridge from '../bridge/base';
|
||||
import VertoBridge from '../bridge/verto';
|
||||
import SIPBridge from '../bridge/sip';
|
||||
@ -24,12 +25,42 @@ export default class AudioManager {
|
||||
}
|
||||
|
||||
joinAudio(listenOnly) {
|
||||
if (listenOnly || this.microphoneLockEnforced) {
|
||||
this.isListenOnly = true;
|
||||
this.bridge.joinListenOnly();
|
||||
} else {
|
||||
this.bridge.joinMicrophone();
|
||||
}
|
||||
AudioManager.fetchServers().then(({ error, stunServers, turnServers }) => {
|
||||
if (error) {
|
||||
//We need to alert the user about this problem by some gui message.
|
||||
console.error("Couldn't fetch the stuns/turns servers!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenOnly || this.microphoneLockEnforced) {
|
||||
this.isListenOnly = true;
|
||||
this.bridge.joinListenOnly(stunServers, turnServers);
|
||||
} else {
|
||||
this.bridge.joinMicrophone(stunServers, turnServers);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We use on the SIP an String Array, while in the server, it comes as
|
||||
// an Array of objects, we need to map from Array<Object> to Array<String>
|
||||
static mapToArray({ response, stunServers, turnServers }) {
|
||||
const promise = new Promise((resolve) => {
|
||||
if (response) {
|
||||
resolve({ error: 404, stunServers: [], turnServers: [] });
|
||||
}
|
||||
resolve({
|
||||
stunServers: stunServers.map(server => server.url),
|
||||
turnServers: turnServers.map(server => server.url),
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
static fetchServers() {
|
||||
const url = `/bigbluebutton/api/stuns?sessionToken=${Auth.sessionToken}`;
|
||||
|
||||
return fetch(url)
|
||||
.then(response => response.json())
|
||||
.then(json => AudioManager.mapToArray(json));
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,13 @@ import mapToAcl from '/imports/startup/mapToAcl';
|
||||
import userLogout from './methods/userLogout';
|
||||
import validateAuthToken from './methods/validateAuthToken';
|
||||
import setEmojiStatus from './methods/setEmojiStatus';
|
||||
import listenOnlyToggle from './methods/listenOnlyToggle';
|
||||
|
||||
Meteor.methods(mapToAcl(['methods.userLogout', 'methods.setEmojiStatus',
|
||||
Meteor.methods(mapToAcl(['methods.userLogout', 'methods.setEmojiStatus', 'methods.listenOnlyToggle',
|
||||
], {
|
||||
userLogout,
|
||||
setEmojiStatus,
|
||||
listenOnlyToggle,
|
||||
}));
|
||||
|
||||
Meteor.methods({ validateAuthToken2x: validateAuthToken });
|
||||
|
@ -7,7 +7,7 @@ import Users from '/imports/api/2.0/users';
|
||||
|
||||
export default function listenOnlyToggle(credentials, isJoining = true) {
|
||||
const REDIS_CONFIG = Meteor.settings.redis;
|
||||
const CHANNEL = REDIS_CONFIG.channels.toBBBApps.meeting;
|
||||
const CHANNEL = REDIS_CONFIG.channels.toAkkaApps;
|
||||
|
||||
const { meetingId, requesterUserId } = credentials;
|
||||
|
||||
@ -18,40 +18,36 @@ export default function listenOnlyToggle(credentials, isJoining = true) {
|
||||
let EVENT_NAME;
|
||||
|
||||
if (isJoining) {
|
||||
EVENT_NAME = 'user_connected_to_global_audio';
|
||||
EVENT_NAME = 'UserConnectedToGlobalAudioMsg';
|
||||
} else {
|
||||
EVENT_NAME = 'user_disconnected_from_global_audio';
|
||||
EVENT_NAME = 'UserDisconnectedFromGlobalAudioMsg';
|
||||
}
|
||||
|
||||
const Meeting = Meetings.findOne({ meetingId });
|
||||
if (!Meeting) {
|
||||
throw new Meteor.Error(
|
||||
'meeting-not-found', 'You need a valid meeting to be able to toggle audio');
|
||||
}
|
||||
|
||||
check(Meeting.voiceConf, String);
|
||||
|
||||
const User = Users.findOne({
|
||||
meetingId,
|
||||
userId: requesterUserId,
|
||||
});
|
||||
|
||||
const Meeting = Meetings.findOne({ meetingId });
|
||||
|
||||
if (!User) {
|
||||
throw new Meteor.Error(
|
||||
'user-not-found', 'You need a valid user to be able to toggle audio');
|
||||
}
|
||||
|
||||
check(User.user.name, String);
|
||||
// check(User.user.name, String);
|
||||
|
||||
const header = {
|
||||
name: EVENT_NAME,
|
||||
voiceConf: Meeting.voiceProp.voiceConf,
|
||||
};
|
||||
|
||||
const payload = {
|
||||
userid: requesterUserId,
|
||||
meeting_id: meetingId,
|
||||
voice_conf: Meeting.voiceConf,
|
||||
userId: requesterUserId,
|
||||
name: User.user.name,
|
||||
};
|
||||
|
||||
Logger.verbose(`User '${requesterUserId}' ${isJoining
|
||||
? 'joined' : 'left'} global audio from meeting '${meetingId}'`);
|
||||
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, payload);
|
||||
return RedisPubSub.publish(CHANNEL, EVENT_NAME, meetingId, payload, header);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ export function joinRouteHandler(nextState, replace, callback) {
|
||||
.then((data) => {
|
||||
const { meetingID, internalUserID, authToken, logoutUrl } = data.response;
|
||||
|
||||
Auth.set(meetingID, internalUserID, authToken, logoutUrl);
|
||||
Auth.set(meetingID, internalUserID, authToken, logoutUrl, sessionToken);
|
||||
replace({ pathname: '/' });
|
||||
callback();
|
||||
});
|
||||
|
@ -2,25 +2,23 @@ import Users from '/imports/api/2.0/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
|
||||
import AudioManager from '/imports/api/1.1/audio/client/manager';
|
||||
import Meetings from '/imports/api/2.0/meetings';
|
||||
|
||||
let audioManager;
|
||||
|
||||
const init = () => {
|
||||
const userId = Auth.userID;
|
||||
const User = Users.findOne({ userId });
|
||||
const username = User.user.name;
|
||||
const Meeting = Meetings.findOne({ meetingId: User.meetingId });
|
||||
const voiceBridge = Meeting.voiceProp.voiceConf;
|
||||
|
||||
const turns = [];
|
||||
const stuns = [];
|
||||
// FIX ME
|
||||
const voiceBridge = 'Meeting.voiceConf';
|
||||
// FIX ME
|
||||
const microphoneLockEnforced = 'Meeting.roomLockSettings.disableMic';
|
||||
const microphoneLockEnforced = false;
|
||||
|
||||
const userData = {
|
||||
userId,
|
||||
username,
|
||||
turns,
|
||||
stuns,
|
||||
voiceBridge,
|
||||
microphoneLockEnforced,
|
||||
};
|
||||
|
@ -13,6 +13,7 @@ class Auth {
|
||||
this._meetingID = Storage.getItem('meetingID');
|
||||
this._userID = Storage.getItem('userID');
|
||||
this._authToken = Storage.getItem('authToken');
|
||||
this._sessionToken = Storage.getItem('sessionToken');
|
||||
this._logoutURL = Storage.getItem('logoutURL');
|
||||
this._loggedIn = {
|
||||
value: false,
|
||||
@ -29,6 +30,15 @@ class Auth {
|
||||
Storage.setItem('meetingID', this._meetingID);
|
||||
}
|
||||
|
||||
set sessionToken(sessionToken) {
|
||||
this._sessionToken = sessionToken;
|
||||
Storage.setItem('sessionToken', this._sessionToken);
|
||||
}
|
||||
|
||||
get sessionToken() {
|
||||
return this._sessionToken;
|
||||
}
|
||||
|
||||
get userID() {
|
||||
return this._userID;
|
||||
}
|
||||
@ -72,14 +82,16 @@ class Auth {
|
||||
requesterUserId: this.userID,
|
||||
requesterToken: this.token,
|
||||
logoutURL: this.logoutURL,
|
||||
sessionToken: this.sessionToken,
|
||||
};
|
||||
}
|
||||
|
||||
set(meetingId, requesterUserId, requesterToken, logoutURL) {
|
||||
set(meetingId, requesterUserId, requesterToken, logoutURL, sessionToken) {
|
||||
this.meetingID = meetingId;
|
||||
this.userID = requesterUserId;
|
||||
this.token = requesterToken;
|
||||
this.logoutURL = logoutURL;
|
||||
this.sessionToken = sessionToken;
|
||||
}
|
||||
|
||||
clearCredentials(...args) {
|
||||
@ -88,6 +100,7 @@ class Auth {
|
||||
this.token = null;
|
||||
this.loggedIn = false;
|
||||
this.logoutURL = null;
|
||||
this.sessionToken = null;
|
||||
|
||||
return Promise.resolve(...args);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user