diff --git a/bigbluebutton-html5/imports/api/phone/index.js b/bigbluebutton-html5/imports/api/phone/index.js deleted file mode 100755 index 05101454fb0894b0425e385d99b4d2c7c9dbe8ae..0000000000000000000000000000000000000000 --- a/bigbluebutton-html5/imports/api/phone/index.js +++ /dev/null @@ -1,151 +0,0 @@ -// TODO: This file should be a `service.js` somewhere in the /ui folder -import Users from '/imports/api/users'; -import Meetings from '/imports/api/meetings'; -import Auth from '/imports/ui/services/auth'; -import {callServer} from '/imports/ui/services/api'; -import {vertoExitAudio, vertoJoinListenOnly, vertoJoinMicrophone} from '/imports/api/verto'; - -const APP_CONFIG = Meteor.settings.public.app; -const MEDIA_CONFIG = Meteor.settings.public.media; - -let triedHangup = false; - -function getVoiceBridge() { - return Meetings.findOne({}).voiceConf; -} - -function amIListenOnly() { - const uid = Auth.userID; - return Users.findOne({ userId: uid }).user.listenOnly; -} - -// 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 - -function exitAudio(afterExitCall = () => {}) { - if (!MEDIA_CONFIG.useSIPAudio) { - vertoExitAudio(); - return; - } else { - // To be called when the hangup is initiated - const hangupCallback = function () { - console.log('Exiting Voice Conference'); - }; - - // Checks periodically until a call is established so we can successfully end the call - // clean state - triedHangup = false; - - // function to initiate call - 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) { - console.log('Attempting to hangup on WebRTC call'); - - // notify BBB-apps we are leaving the call call if we are listen only - if (amIListenOnly()) { - callServer('listenOnlyRequestToggle', false); - } - - window.webrtc_hangup(hangupCallback); - - // we have hung up, prevent retries - triedHangup = true; - - if (afterExitCall) { - afterExitCall(this, APP_CONFIG.listenOnly); - } - } else { - console.log('RETRYING hangup on WebRTC call in ' + - `${MEDIA_CONFIG.WebRTCHangupRetryInterval} ms`); - - // try again periodically - setTimeout(checkToHangupCall, MEDIA_CONFIG.WebRTCHangupRetryInterval); - } - }) - - // automatically run function - (this, afterExitCall); - - return false; - }; -} - -// join the conference. If listen only send the request to the server -function joinVoiceCallSIP(options) { - const extension = getVoiceBridge(); - console.log(options); - if (MEDIA_CONFIG.useSIPAudio) { - - // create voice call params - const joinCallback = function (message) { - console.log('Beginning WebRTC Conference Call'); - }; - - window.BBB = {}; - window.BBB.getMyUserInfo = function (callback) { - const uid = Auth.userID; - const result = { - myUserID: uid, - myUsername: Users.findOne({ userId: uid }).user.name, - myInternalUserID: uid, - myAvatarURL: null, - myRole: 'getMyRole', - amIPresenter: 'false', - voiceBridge: extension, - dialNumber: null, - }; - return callback(result); - }; - - const m = Meetings.findOne(); - const st = { - stun: m.stuns, - turn: m.turns, - }; - - callIntoConference(extension, function (audio) { - switch (audio.status) { - case 'failed': - let audioFailed = new CustomEvent('bbb.webrtc.failed', { - status: 'Failed' }); - window.dispatchEvent(audioFailed); - break; - case 'mediafail': - let mediaFailed = new CustomEvent('bbb.webrtc.mediaFailed', { - status: 'MediaFailed' }); - window.dispatchEvent(mediaFailed); - break; - case 'mediasuccess': - case 'started': - let connected = new CustomEvent('bbb.webrtc.connected', { - status: 'started' }); - window.dispatchEvent(connected); - break; - } - }, options.isListenOnly, st); - return; - } -} - -function joinListenOnly() { - callServer('listenOnlyRequestToggle', true); - if (MEDIA_CONFIG.useSIPAudio) { - joinVoiceCallSIP({ isListenOnly: true }); - } else { - vertoJoinListenOnly(); - } -} - -function joinMicrophone() { - if (MEDIA_CONFIG.useSIPAudio) { - joinVoiceCallSIP({ isListenOnly: false }); - } else { - vertoJoinMicrophone(); - } -} - -export { joinListenOnly, joinMicrophone, exitAudio, getVoiceBridge, }; diff --git a/bigbluebutton-html5/imports/api/verto/index.js b/bigbluebutton-html5/imports/api/verto/index.js index 99720b7eca15151bb9eaf5efc410877c5903d072..41bc595a322e223767ed082322f893b3acf98ba3 100755 --- a/bigbluebutton-html5/imports/api/verto/index.js +++ b/bigbluebutton-html5/imports/api/verto/index.js @@ -1,7 +1,7 @@ -import {getInStorage} from '/imports/ui/components/app/service'; +import { getInStorage } from '/imports/ui/components/app/service'; import Users from '/imports/api/users'; import Auth from '/imports/ui/services/auth'; -import { getVoiceBridge } from '/imports/api/phone'; +import { getVoiceBridge } from '/imports/ui/components/audio/service'; function createVertoUserName() { const uid = Auth.userID; diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx index f3d529b46ee21f17e42e08637b83681ead54d126..ad92643f5359440f6682795fcfde4f6956eb2d4f 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import { createContainer } from 'meteor/react-meteor-data'; import ActionsBar from './component'; import Service from './service'; +import { exitAudio, handleJoinAudio } from '../audio/service'; class ActionsBarContainer extends Component { constructor(props) { @@ -20,8 +21,8 @@ class ActionsBarContainer extends Component { export default createContainer(() => { const isPresenter = Service.isUserPresenter(); - const handleExitAudio = () => Service.handleExitAudio(); - const handleOpenJoinAudio = () => Service.handleJoinAudio(); + const handleExitAudio = () => exitAudio(); + const handleOpenJoinAudio = () => handleJoinAudio(); return { isUserPresenter: isPresenter, diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js index ae6381611448dc31b94fbc93c4927e631c675b65..741adaddd5960ce4f896d260a912f5e33682d7ea 100755 --- a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js +++ b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js @@ -1,10 +1,6 @@ import React from 'react'; import AuthSingleton from '/imports/ui/services/auth/index.js'; import Users from '/imports/api/users'; -import { joinListenOnly } from '/imports/api/phone'; -import { showModal } from '/imports/ui/components/app/service'; -import { exitAudio } from '/imports/api/phone'; -import Audio from '/imports/ui/components/audio/audio-modal/component'; let isUserPresenter = () => { @@ -18,17 +14,6 @@ let isUserPresenter = () => { }; }; -const handleExitAudio = () => { - return exitAudio(); -} - -const handleJoinAudio = () => { - const handleJoinListenOnly = () => joinListenOnly(); - return showModal(<Audio handleJoinListenOnly={handleJoinListenOnly} />); -} - export default { isUserPresenter, - handleJoinAudio, - handleExitAudio, }; diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx index d49bd018927f640801dc08bd06139170af7a0ab2..0c01f8f2469e697c5fccc9f604dd6355b6b71800 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-modal/container.jsx @@ -1,7 +1,7 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; import { createContainer } from 'meteor/react-meteor-data'; import Audio from './component'; -import { joinListenOnly } from '/imports/api/phone'; +import { joinListenOnly } from '../service'; export default class AudioModalContainer extends Component { constructor(props) { diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx index 9846dc8cf449e0b0e82e0703227761bf457b824e..104d2e3b4dad90347577a3cd073c33dee6f7699a 100755 --- a/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/audio-settings/component.jsx @@ -6,7 +6,7 @@ import styles from '../audio-modal/styles.scss'; import DeviceSelector from '/imports/ui/components/audio/device-selector/component'; import AudioStreamVolume from '/imports/ui/components/audio/audio-stream-volume/component'; -import EnterAudioContainer from '/imports/ui/components/enter-audio/container'; +import EnterAudioContainer from '/imports/ui/components/audio/enter-audio/container'; import AudioTestContainer from '/imports/ui/components/audio/audio-test/container'; import cx from 'classnames'; diff --git a/bigbluebutton-html5/imports/ui/components/enter-audio/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx similarity index 83% rename from bigbluebutton-html5/imports/ui/components/enter-audio/component.jsx rename to bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx index 231007afc9e95923321a40e8e962874d52e4699d..f1dcb9a6842b0b45a7ec94b926bb4c908c14d346 100755 --- a/bigbluebutton-html5/imports/ui/components/enter-audio/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/component.jsx @@ -1,7 +1,6 @@ import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import Button from '/imports/ui/components/button/component'; -import styles from '../settings/styles.scss'; class EnterAudio extends React.Component { constructor(props) { @@ -14,8 +13,8 @@ class EnterAudio extends React.Component { } = this.props; return ( - <div className={styles.half}> - <Button className={styles.enterBtn} + <div> + <Button label={intl.formatMessage(intlMessages.enterSessionLabel)} size={'md'} color={'primary'} diff --git a/bigbluebutton-html5/imports/ui/components/enter-audio/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx similarity index 81% rename from bigbluebutton-html5/imports/ui/components/enter-audio/container.jsx rename to bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx index 299f254333ce1356f5ea0cccc52ab959e700bf2b..6b3dbdc3df97f2b400fd7db9b2835eb745e5a42b 100755 --- a/bigbluebutton-html5/imports/ui/components/enter-audio/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/audio/enter-audio/container.jsx @@ -1,6 +1,6 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; import { createContainer } from 'meteor/react-meteor-data'; -import {joinListenOnly, joinMicrophone} from '/imports/api/phone'; +import { joinListenOnly, joinMicrophone } from '../service'; import { clearModal } from '/imports/ui/components/app/service'; import EnterAudio from './component'; diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js index fa2f5d09adf7d18bae2e237c41de9c6df53c2506..e802ec2d1b77f9fdec1c87888575d85bb97179f5 100644 --- a/bigbluebutton-html5/imports/ui/components/audio/service.js +++ b/bigbluebutton-html5/imports/ui/components/audio/service.js @@ -1,4 +1,165 @@ import React from 'react'; -export default { +import AudioModal from './audio-modal/component'; +import Auth from '/imports/ui/services/auth'; +import Meetings from '/imports/api/meetings'; +import Users from '/imports/api/users'; + +import { showModal } from '/imports/ui/components/app/service'; +import { callServer } from '/imports/ui/services/api'; +import { vertoExitAudio, vertoJoinListenOnly, vertoJoinMicrophone } from '/imports/api/verto'; + +const handleJoinAudio = () => { + const handleJoinListenOnly = () => joinListenOnly(); + return showModal(<AudioModal handleJoinListenOnly={handleJoinListenOnly} />); +}; + +const APP_CONFIG = Meteor.settings.public.app; +const MEDIA_CONFIG = Meteor.settings.public.media; + +let triedHangup = false; + +function getVoiceBridge() { + return Meetings.findOne({}).voiceConf; +} + +function _amIListenOnly() { + const uid = Auth.userID; + return Users.findOne({ userId: uid }).user.listenOnly; +} + +// 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 +function exitAudio(afterExitCall = () => {}) { + if (!MEDIA_CONFIG.useSIPAudio) { + vertoExitAudio(); + return; + } else { + // To be called when the hangup is initiated + const hangupCallback = function () { + console.log('Exiting Voice Conference'); + }; + + // Checks periodically until a call is established so we can successfully end the call + // clean state + triedHangup = false; + + // function to initiate call + 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) { + console.log('Attempting to hangup on WebRTC call'); + + // notify BBB-apps we are leaving the call call if we are listen only + if (_amIListenOnly()) { + callServer('listenOnlyRequestToggle', false); + } + + window.webrtc_hangup(hangupCallback); + + // we have hung up, prevent retries + triedHangup = true; + + if (afterExitCall) { + afterExitCall(this, APP_CONFIG.listenOnly); + } + } else { + console.log('RETRYING hangup on WebRTC call in ' + + `${MEDIA_CONFIG.WebRTCHangupRetryInterval} ms`); + + // try again periodically + setTimeout(checkToHangupCall, MEDIA_CONFIG.WebRTCHangupRetryInterval); + } + }) + + // automatically run function + (this, afterExitCall); + + return false; + } +} + +// join the conference. If listen only send the request to the server +function _joinVoiceCallSIP(options) { + const extension = getVoiceBridge(); + console.log(options); + if (MEDIA_CONFIG.useSIPAudio) { + + // create voice call params + const joinCallback = function (message) { + console.log('Beginning WebRTC Conference Call'); + }; + + window.BBB = {}; + window.BBB.getMyUserInfo = function (callback) { + const uid = Auth.userID; + const result = { + myUserID: uid, + myUsername: Users.findOne({ userId: uid }).user.name, + myInternalUserID: uid, + myAvatarURL: null, + myRole: 'getMyRole', + amIPresenter: 'false', + voiceBridge: extension, + dialNumber: null, + }; + return callback(result); + }; + + const m = Meetings.findOne(); + const st = { + stun: m.stuns, + turn: m.turns, + }; + + callIntoConference(extension, function (audio) { + switch (audio.status) { + case 'failed': + let audioFailed = new CustomEvent('bbb.webrtc.failed', { + status: 'Failed' }); + window.dispatchEvent(audioFailed); + break; + case 'mediafail': + let mediaFailed = new CustomEvent('bbb.webrtc.mediaFailed', { + status: 'MediaFailed' }); + window.dispatchEvent(mediaFailed); + break; + case 'mediasuccess': + case 'started': + let connected = new CustomEvent('bbb.webrtc.connected', { + status: 'started' }); + window.dispatchEvent(connected); + break; + } + }, options.isListenOnly, st); + return; + } +} + +const joinListenOnly = () => { + callServer('listenOnlyRequestToggle', true); + if (MEDIA_CONFIG.useSIPAudio) { + _joinVoiceCallSIP({ isListenOnly: true }); + } else { + vertoJoinListenOnly(); + } +}; + +const joinMicrophone = () => { + if (MEDIA_CONFIG.useSIPAudio) { + _joinVoiceCallSIP({ isListenOnly: false }); + } else { + vertoJoinMicrophone(); + } +}; + +export { + handleJoinAudio, + getVoiceBridge, + exitAudio, + joinListenOnly, + joinMicrophone, }; diff --git a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx index e23f29fd11ea8fc5a57bde6b32b6e41c04088904..59c10cde061fb3056a9712bc93a9a602008d512b 100644 --- a/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/breakout-join-confirmation/component.jsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { defineMessages, injectIntl } from 'react-intl'; import { clearModal } from '/imports/ui/components/app/service'; -import { exitAudio } from '/imports/api/phone' +import { exitAudio } from '../audio/service' import Modal from '/imports/ui/components/modal/component'; const intlMessages = defineMessages({ diff --git a/bigbluebutton-html5/imports/ui/components/deskshare/service.js b/bigbluebutton-html5/imports/ui/components/deskshare/service.js index 99145dd25837b7492294f2547cccd215a48b5e4b..ea374ea303ed2c6a6a36300943aa2a998b169a71 100755 --- a/bigbluebutton-html5/imports/ui/components/deskshare/service.js +++ b/bigbluebutton-html5/imports/ui/components/deskshare/service.js @@ -1,7 +1,6 @@ import Deskshare from '/imports/api/deskshare'; import {createVertoUserName, watchVertoVideo} from '/imports/api/verto'; import Auth from '/imports/ui/services/auth'; -import {getVoiceBridge} from '/imports/api/phone'; // when the meeting information has been updated check to see if it was // desksharing. If it has changed either trigger a call to receive video