diff --git a/app/src/RoomClient.js b/app/src/RoomClient.js index f6f4764..aea8f94 100644 --- a/app/src/RoomClient.js +++ b/app/src/RoomClient.js @@ -65,10 +65,6 @@ const VIDEO_ENCODINGS = let store; -const AudioContext = window.AudioContext // Default - || window.webkitAudioContext // Safari and old versions of Chrome - || false; - export default class RoomClient { /** @@ -119,11 +115,6 @@ export default class RoomClient // Alert sound this._soundAlert = new Audio('/sounds/notify.mp3'); - if (AudioContext) - { - this._audioContext = new AudioContext(); - } - // Socket.io peer connection this._signalingSocket = null; @@ -661,9 +652,15 @@ export default class RoomClient { logger.debug('muteMic()'); + this._micProducer.pause(); + try { - this._micProducer.pause(); + await this.sendRequest( + 'pauseProducer', { producerId: this._micProducer.id }); + + store.dispatch( + stateActions.setProducerPaused(this._micProducer.id)); } catch (error) { @@ -681,24 +678,32 @@ export default class RoomClient { logger.debug('unmuteMic()'); - try + if (!this._micProducer) { - if (this._micProducer) - this._micProducer.resume(); - else if (this._room.canSend('audio')) - await this.enableMic(); - else - throw new Error('cannot send audio'); + this.enableMic(); } - catch (error) + else { - logger.error('unmuteMic() | failed: %o', error); + this._micProducer.resume(); - store.dispatch(requestActions.notify( - { - type : 'error', - text : 'An error occured while accessing your microphone.' - })); + try + { + await this.sendRequest( + 'resumeProducer', { producerId: this._micProducer.id }); + + store.dispatch( + stateActions.setProducerResumed(this._micProducer.id)); + } + catch (error) + { + logger.error('unmuteMic() | failed: %o', error); + + store.dispatch(requestActions.notify( + { + type : 'error', + text : 'An error occured while accessing your microphone.' + })); + } } } @@ -1056,31 +1061,13 @@ export default class RoomClient stateActions.setMyRaiseHandStateInProgress(false)); } - async resumeAudio() - { - logger.debug('resumeAudio()'); - try - { - await this._audioContext.resume(); - - store.dispatch( - stateActions.setAudioSuspended({ audioSuspended: false })); - - } - catch (error) - { - store.dispatch( - stateActions.setAudioSuspended({ audioSuspended: true })); - logger.error('resumeAudioJoin() failed: %o', error); - } - } - - async join() + async join({ joinVideo }) { this._signalingSocket = io(this._signalingUrl); this._spotlights = new Spotlights(this._maxSpotlights, this._signalingSocket); + store.dispatch(stateActions.toggleJoined()); store.dispatch(stateActions.setRoomState('connecting')); this._signalingSocket.on('connect', () => @@ -1258,7 +1245,7 @@ export default class RoomClient { case 'roomReady': { - await this._joinRoom(); + await this._joinRoom({ joinVideo }); break; } @@ -1514,7 +1501,7 @@ export default class RoomClient }); } - async _joinRoom() + async _joinRoom({ joinVideo }) { logger.debug('_joinRoom()'); @@ -1664,10 +1651,10 @@ export default class RoomClient if (this._produce) { if (this._mediasoupDevice.canProduce('audio')) - await this.enableMic(); + this.enableMic(); - if (this._mediasoupDevice.canProduce('video')) - await this.enableWebcam(); + if (joinVideo && this._mediasoupDevice.canProduce('video')) + this.enableWebcam(); } store.dispatch(stateActions.setRoomState('connected')); @@ -1875,15 +1862,6 @@ export default class RoomClient store.dispatch(stateActions.setPeerVolume(this._peerId, volume)); } }); - - if (this._audioContext) - { - // We need to provoke user interaction to get permission from browser to start audio - if (this._audioContext.state === 'suspended') - { - this.resumeAudio(); - } - } } catch (error) { diff --git a/app/src/actions/stateActions.js b/app/src/actions/stateActions.js index 52ba00d..fda3ceb 100644 --- a/app/src/actions/stateActions.js +++ b/app/src/actions/stateActions.js @@ -43,14 +43,6 @@ export const setRoomLockedOut = () => }; }; -export const setAudioSuspended = ({ audioSuspended }) => -{ - return { - type : 'SET_AUDIO_SUSPENDED', - payload : { audioSuspended } - }; -}; - export const setSettingsOpen = ({ settingsOpen }) => ({ type : 'SET_SETTINGS_OPEN', @@ -568,6 +560,11 @@ export const loggedIn = () => type : 'LOGGED_IN' }); +export const toggleJoined = () => + ({ + type : 'TOGGLE_JOINED' + }); + export const setSelectedPeer = (selectedPeerId) => ({ type : 'SET_SELECTED_PEER', diff --git a/app/src/components/Controls/Sidebar.js b/app/src/components/Controls/Sidebar.js index 79024ea..9ef0583 100644 --- a/app/src/components/Controls/Sidebar.js +++ b/app/src/components/Controls/Sidebar.js @@ -78,11 +78,16 @@ const Sidebar = (props) => let micTip; - if (!me.canSendMic || !micProducer) + if (!me.canSendMic) { micState = 'unsupported'; micTip = 'Audio unsupported'; } + else if (!micProducer) + { + micState = 'off'; + micTip = 'Activate audio'; + } else if (!micProducer.locallyPaused && !micProducer.remotelyPaused) { micState = 'on'; @@ -90,7 +95,7 @@ const Sidebar = (props) => } else { - micState = 'off'; + micState = 'muted'; micTip = 'Unmute audio'; } @@ -152,9 +157,12 @@ const Sidebar = (props) => size={smallScreen ? 'large' : 'medium'} onClick={() => { - micState === 'on' ? - roomClient.disableMic() : + if (micState === 'off') roomClient.enableMic(); + else if (micState === 'on') + roomClient.muteMic(); + else + roomClient.unmuteMic(); }} > { micState === 'on' ? diff --git a/app/src/components/JoinDialog.js b/app/src/components/JoinDialog.js new file mode 100644 index 0000000..5a99b3f --- /dev/null +++ b/app/src/components/JoinDialog.js @@ -0,0 +1,90 @@ +import React from 'react'; +import { withStyles } from '@material-ui/core/styles'; +import { withRoomContext } from '../RoomContext'; +import PropTypes from 'prop-types'; +import Dialog from '@material-ui/core/Dialog'; +import Typography from '@material-ui/core/Typography'; +import DialogActions from '@material-ui/core/DialogActions'; +import Button from '@material-ui/core/Button'; + +const styles = (theme) => + ({ + root : + { + }, + dialogPaper : + { + width : '20vw', + padding : theme.spacing.unit * 2, + [theme.breakpoints.down('lg')] : + { + width : '30vw' + }, + [theme.breakpoints.down('md')] : + { + width : '40vw' + }, + [theme.breakpoints.down('sm')] : + { + width : '60vw' + }, + [theme.breakpoints.down('xs')] : + { + width : '80vw' + } + }, + logo : + { + display : 'block' + } + }); + +const JoinDialog = ({ + roomClient, + classes +}) => +{ + return ( + + ); +}; + +JoinDialog.propTypes = +{ + roomClient : PropTypes.any.isRequired, + classes : PropTypes.object.isRequired +}; + +export default withRoomContext(withStyles(styles)(JoinDialog)); \ No newline at end of file diff --git a/app/src/components/Room.js b/app/src/components/Room.js index 8a503b7..afcc75d 100644 --- a/app/src/components/Room.js +++ b/app/src/components/Room.js @@ -15,7 +15,6 @@ import SwipeableDrawer from '@material-ui/core/SwipeableDrawer'; import Hidden from '@material-ui/core/Hidden'; import Paper from '@material-ui/core/Paper'; import Typography from '@material-ui/core/Typography'; -import Button from '@material-ui/core/Button'; import IconButton from '@material-ui/core/IconButton'; import MenuIcon from '@material-ui/icons/Menu'; import Avatar from '@material-ui/core/Avatar'; @@ -33,6 +32,7 @@ import FullScreenIcon from '@material-ui/icons/Fullscreen'; import FullScreenExitIcon from '@material-ui/icons/FullscreenExit'; import SettingsIcon from '@material-ui/icons/Settings'; import Settings from './Settings/Settings'; +import JoinDialog from './JoinDialog'; const TIMEOUT = 10 * 1000; @@ -176,10 +176,6 @@ class Room extends React.PureComponent componentDidMount() { - const { roomClient } = this.props; - - roomClient.join(); - if (this.fullscreen.fullscreenEnabled) { this.fullscreen.addEventListener('fullscreenchange', this.handleFullscreenChange); @@ -242,29 +238,7 @@ class Room extends React.PureComponent democratic : Democratic }[room.mode]; - if (room.audioSuspended) - { - return ( -