Skip to content

Commit

Permalink
Merge branch 'v2.2.x-release' of github.com:bigbluebutton/bigbluebutt…
Browse files Browse the repository at this point in the history
…on into pres-url-on-page-convert
  • Loading branch information
ritzalam committed Feb 28, 2020
2 parents c0372e3 + cd62e7f commit a1ea899
Show file tree
Hide file tree
Showing 17 changed files with 340 additions and 58 deletions.
69 changes: 39 additions & 30 deletions bigbluebutton-html5/imports/api/audio/client/bridge/sip.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import {
analyzeSdp,
logSelectedCandidate,
} from '/imports/utils/sdpUtils';
import { Tracker } from 'meteor/tracker';
import VoiceCallStates from '/imports/api/voice-call-states';
import CallStateOptions from '/imports/api/voice-call-states/utils/callStates';
import Auth from '/imports/ui/services/auth';

const MEDIA = Meteor.settings.public.media;
const MEDIA_TAG = MEDIA.mediaTag;
Expand Down Expand Up @@ -47,14 +51,6 @@ class SIPSession {
this.reconnectAttempt = reconnectAttempt;
}

static parseDTMF(message) {
const parse = message.match(/Signal=(.)/);
if (parse && parse.length === 2) {
return parse[1];
}
return '';
}

joinAudio({ isListenOnly, extension, inputStream }, managerCallback) {
return new Promise((resolve, reject) => {
const callExtension = extension ? `${extension}${this.userData.voiceBridge}` : this.userData.voiceBridge;
Expand Down Expand Up @@ -119,8 +115,10 @@ class SIPSession {
return new Promise((resolve, reject) => {
this.inEchoTest = false;

const timeout = setInterval(() => {
clearInterval(timeout);
let trackerControl = null;

const timeout = setTimeout(() => {
trackerControl.stop();
logger.error({ logCode: 'sip_js_transfer_timed_out' }, 'Timeout on transferring from echo test to conference');
this.callback({
status: this.baseCallStates.failed,
Expand All @@ -136,15 +134,22 @@ class SIPSession {
// This is is the call transfer code ask @chadpilkey
this.currentSession.dtmf(1);

this.currentSession.on('dtmf', (event) => {
if (event.body && (typeof event.body === 'string')) {
const key = SIPSession.parseDTMF(event.body);
if (key === '7') {
clearInterval(timeout);
onTransferSuccess();
resolve();
}
}
Tracker.autorun((c) => {
trackerControl = c;
const selector = { meetingId: Auth.meetingID, userId: Auth.userID };
const query = VoiceCallStates.find(selector);

query.observeChanges({
changed: (id, fields) => {
if (fields.callState === CallStateOptions.IN_CONFERENCE) {
clearTimeout(timeout);
onTransferSuccess();

c.stop();
resolve();
}
},
});
});
});
}
Expand Down Expand Up @@ -491,17 +496,21 @@ class SIPSession {
};
['iceConnectionClosed'].forEach(e => mediaHandler.on(e, handleIceConnectionTerminated));

const inEchoDTMF = (event) => {
if (event.body && typeof event.body === 'string') {
const dtmf = SIPSession.parseDTMF(event.body);
if (dtmf === '0') {
fsReady = true;
checkIfCallReady();
}
}
currentSession.off('dtmf', inEchoDTMF);
};
currentSession.on('dtmf', inEchoDTMF);
Tracker.autorun((c) => {
const selector = { meetingId: Auth.meetingID, userId: Auth.userID };
const query = VoiceCallStates.find(selector);

query.observeChanges({
changed: (id, fields) => {
if (fields.callState === CallStateOptions.IN_ECHO_TEST) {
fsReady = true;
checkIfCallReady();

c.stop();
}
},
});
});
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import clearNote from '/imports/api/note/server/modifiers/clearNote';
import clearNetworkInformation from '/imports/api/network-information/server/modifiers/clearNetworkInformation';
import clearLocalSettings from '/imports/api/local-settings/server/modifiers/clearLocalSettings';
import clearRecordMeeting from './clearRecordMeeting';
import clearVoiceCallStates from '/imports/api/voice-call-states/server/modifiers/clearVoiceCallStates';

export default function meetingHasEnded(meetingId) {
removeAnnotationsStreamer(meetingId);
Expand All @@ -40,6 +41,7 @@ export default function meetingHasEnded(meetingId) {
clearNetworkInformation(meetingId);
clearLocalSettings(meetingId);
clearRecordMeeting(meetingId);
clearVoiceCallStates(meetingId);

return Logger.info(`Cleared Meetings with id ${meetingId}`);
});
Expand Down
13 changes: 13 additions & 0 deletions bigbluebutton-html5/imports/api/voice-call-states/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Meteor } from 'meteor/meteor';

const VoiceCallStates = new Mongo.Collection('voiceCallStates');

if (Meteor.isServer) {
// types of queries for the voice users:
// 1. intId
// 2. meetingId, intId

VoiceCallStates._ensureIndex({ meetingId: 1, userId: 1 });
}

export default VoiceCallStates;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import RedisPubSub from '/imports/startup/server/redis';
import handleVoiceCallStateEvent from './handlers/voiceCallStateEvent';

RedisPubSub.on('VoiceCallStateEvtMsg', handleVoiceCallStateEvent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { check } from 'meteor/check';
import VoiceCallState from '/imports/api/voice-call-states';
import Logger from '/imports/startup/server/logger';

// "CALL_STARTED", "IN_ECHO_TEST", "IN_CONFERENCE", "CALL_ENDED"

export default function handleVoiceCallStateEvent({ body }, meetingId) {
const {
voiceConf,
clientSession,
userId,
callerName,
callState,
} = body;

check(meetingId, String);
check(voiceConf, String);
check(clientSession, String);
check(userId, String);
check(callerName, String);
check(callState, String);

const selector = {
meetingId,
userId,
clientSession,
};

const modifier = {
$set: {
meetingId,
userId,
voiceConf,
clientSession,
callState,
},
};

const cb = (err) => {
if (err) {
return Logger.error(`Update voice call state=${userId}: ${err}`);
}

return Logger.debug(`Update voice call state=${userId} meeting=${meetingId} clientSession=${clientSession}`);
};

return VoiceCallState.upsert(selector, modifier, cb);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './eventHandlers';
import './publishers';
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Logger from '/imports/startup/server/logger';
import VoiceCallStates from '/imports/api/voice-users';

export default function clearVoiceCallStates(meetingId) {
if (meetingId) {
return VoiceCallStates.remove({ meetingId }, () => {
Logger.info(`Cleared VoiceCallStates in (${meetingId})`);
});
}

return VoiceCallStates.remove({}, () => {
Logger.info('Cleared VoiceCallStates in all meetings');
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import VoiceCallStates from '/imports/api/voice-call-states';
import { Meteor } from 'meteor/meteor';
import Logger from '/imports/startup/server/logger';
import { extractCredentials } from '/imports/api/common/server/helpers';

function voiceCallStates() {
if (!this.userId) {
return VoiceCallStates.find({ meetingId: '' });
}
const { meetingId, requesterUserId } = extractCredentials(this.userId);

Logger.debug(`Publishing Voice Call States for ${meetingId} ${requesterUserId}`);

return VoiceCallStates.find({ meetingId, userId: requesterUserId });
}

function publish(...args) {
const boundVoiceCallStates = voiceCallStates.bind(this);
return boundVoiceCallStates(...args);
}

Meteor.publish('voice-call-states', publish);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const CallStateOptions = {
CALL_STARTED: 'CALL_STARTED',
IN_ECHO_TEST: 'IN_ECHO_TEST',
IN_CONFERENCE: 'IN_CONFERENCE',
CALL_ENDED: 'CALL_ENDED',
};

export default CallStateOptions;
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ const intlMessages = defineMessages({
id: 'app.presentationUploder.fileToUpload',
description: 'message used in the file selected for upload',
},
genericError: {
id: 'app.presentationUploder.genericError',
description: 'generic error while uploading/converting',
},
rejectedError: {
id: 'app.presentationUploder.rejectedError',
description: 'some files rejected, please check the file mime types',
Expand Down Expand Up @@ -132,10 +128,22 @@ const intlMessages = defineMessages({
id: 'app.presentationUploder.conversion.pageCountExceeded',
description: 'warns the user that the conversion failed because of the page count',
},
PAGE_COUNT_FAILED: {
id: 'app.presentationUploder.conversion.pageCountFailed',
description: '',
},
PDF_HAS_BIG_PAGE: {
id: 'app.presentationUploder.conversion.pdfHasBigPage',
description: 'warns the user that the conversion failed because of the pdf page siz that exceeds the allowed limit',
},
OFFICE_DOC_CONVERSION_INVALID: {
id: 'app.presentationUploder.conversion.officeDocConversionInvalid',
description: '',
},
OFFICE_DOC_CONVERSION_FAILED: {
id: 'app.presentationUploder.conversion.officeDocConversionFailed',
description: '',
},
isDownloadable: {
id: 'app.presentationUploder.isDownloadableLabel',
description: 'presentation is available for downloading by all viewers',
Expand Down Expand Up @@ -249,7 +257,7 @@ class PresentationUploader extends Component {
}

handleConfirm() {
const { mountModal, intl, handleSave } = this.props;
const { mountModal, handleSave } = this.props;
const { disableActions, presentations, oldCurrentId } = this.state;
const presentationsToSave = presentations
.filter(p => !p.upload.error && !p.conversion.error);
Expand Down Expand Up @@ -287,7 +295,6 @@ class PresentationUploader extends Component {
});
})
.catch((error) => {
notify(intl.formatMessage(intlMessages.genericError), 'error');
logger.error({
logCode: 'presentationuploader_component_save_error',
extraInfo: { error },
Expand Down Expand Up @@ -483,6 +490,7 @@ class PresentationUploader extends Component {

renderPresentationItemStatus(item) {
const { intl } = this.props;

if (!item.upload.done && item.upload.progress === 0) {
return intl.formatMessage(intlMessages.fileToUpload);
}
Expand All @@ -494,13 +502,11 @@ class PresentationUploader extends Component {
}

if (item.upload.done && item.upload.error) {
const errorMessage = intlMessages[item.upload.status] || intlMessages.genericError;
return intl.formatMessage(errorMessage);
return intl.formatMessage(intlMessages[item.upload.status]);
}

if (!item.conversion.done && item.conversion.error) {
const errorMessage = intlMessages[item.conversion.status] || intlMessages.genericError;
return intl.formatMessage(errorMessage);
return intl.formatMessage(intlMessages[item.conversion.status]);
}

if (!item.conversion.done && !item.conversion.error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SUBSCRIPTIONS = [
'voiceUsers', 'whiteboard-multi-user', 'screenshare', 'group-chat',
'presentation-pods', 'users-settings', 'guestUser', 'users-infos', 'note', 'meeting-time-remaining',
'network-information', 'ping-pong', 'local-settings', 'users-typing', 'record-meetings', 'video-streams',
'voice-call-states',
];

class Subscriptions extends Component {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
text-align: left;
padding-left: var(--lg-padding-y);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;

[dir="rtl"] & {
text-align: right;
Expand Down
6 changes: 4 additions & 2 deletions bigbluebutton-html5/private/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@
"app.presentationUploder.browseImagesLabel": "or browse/capture for images",
"app.presentationUploder.fileToUpload": "To be uploaded ...",
"app.presentationUploder.currentBadge": "Current",
"app.presentationUploder.genericError": "Ops, something went wrong",
"app.presentationUploder.rejectedError": "The selected file(s) have been rejected. Please check the file type(s).",
"app.presentationUploder.upload.progress": "Uploading ({0}%)",
"app.presentationUploder.upload.413": "File is too large. Please split into multiple files.",
Expand All @@ -177,9 +176,12 @@
"app.presentationUploder.conversion.generatingThumbnail": "Generating thumbnails ...",
"app.presentationUploder.conversion.generatedSlides": "Slides generated ...",
"app.presentationUploder.conversion.generatingSvg": "Generating SVG images ...",
"app.presentationUploder.conversion.pageCountExceeded": "Ops, the page count exceeded the limit of 200 pages",
"app.presentationUploder.conversion.pageCountExceeded": "Number of pages exceeded. Please break file into multiple files.",
"app.presentationUploder.conversion.officeDocConversionInvalid": "Failed to process office document. Please upload a PDF instead.",
"app.presentationUploder.conversion.officeDocConversionFailed": "Failed to process office document. Please upload a PDF instead.",
"app.presentationUploder.conversion.pdfHasBigPage": "We could not convert the PDF file, please try optimizing it",
"app.presentationUploder.conversion.timeout": "Ops, the conversion took too long",
"app.presentationUploder.conversion.pageCountFailed": "Failed to determine the number of pages.",
"app.presentationUploder.isDownloadableLabel": "Do not allow presentation to be downloaded",
"app.presentationUploder.isNotDownloadableLabel": "Allow presentation to be downloaded",
"app.presentationUploder.removePresentationLabel": "Remove presentation",
Expand Down
Loading

0 comments on commit a1ea899

Please sign in to comment.