Merge branch 'feat-audiocontext' into develop

master
Håvar Aambø Fosstveit 2019-03-14 09:36:39 +01:00
commit 23948f09d9
6 changed files with 139 additions and 22 deletions

View File

@ -53,7 +53,7 @@ export default class RoomClient
'constructor() [roomId:"%s", peerName:"%s", displayName:"%s", device:%s]',
roomId, peerName, displayName, device.flag);
const signalingUrl = getSignalingUrl(peerName, roomId);
this._signalingUrl = getSignalingUrl(peerName, roomId);
// window element to external login site
this._loginWindow;
@ -76,18 +76,21 @@ export default class RoomClient
// My peer name.
this._peerName = peerName;
// My display name
this._displayName = peerName;
// Alert sound
this._soundAlert = new Audio('/resources/sounds/notify.mp3');
// AudioContext
this._audioContext;
// Socket.io peer connection
this._signalingSocket = io(signalingUrl);
this._signalingSocket = null;
if (this._device.flag === 'firefox')
ROOM_OPTIONS = Object.assign({ iceTransportPolicy: 'relay' }, ROOM_OPTIONS);
// mediasoup-client Room instance.
this._room = new mediasoupClient.Room(ROOM_OPTIONS);
this._room.roomId = roomId;
// The mediasoup room instance
this._room = null;
this._roomId = roomId;
// Our WebTorrent client
this._webTorrent = this._torrentSupport && new WebTorrent({
@ -102,7 +105,7 @@ export default class RoomClient
this._maxSpotlights = ROOM_OPTIONS.maxSpotlights;
// Manager of spotlight
this._spotlights = new Spotlights(this._maxSpotlights, this._room);
this._spotlights = null;
// Transport for sending.
this._sendTransport = null;
@ -140,7 +143,9 @@ export default class RoomClient
this._startKeyListener();
this._join({ displayName, device });
this._audioContext = null;
this.join();
}
close()
@ -983,8 +988,36 @@ export default class RoomClient
}, 500);
}
_join({ displayName, device })
async resumeAudio()
{
logger.debug('resumeAudio()');
try
{
await this._audioContext.resume();
store.dispatch(
stateActions.setAudioSuspended({ audioSuspended: false }));
}
catch (error)
{
logger.error('resumeAudioJoin() failed: %o', error);
}
}
join()
{
this._signalingSocket = io(this._signalingUrl);
if (this._device.flag === 'firefox')
ROOM_OPTIONS = Object.assign({ iceTransportPolicy: 'relay' }, ROOM_OPTIONS);
// mediasoup-client Room instance.
this._room = new mediasoupClient.Room(ROOM_OPTIONS);
this._room.roomId = this._roomId;
this._spotlights = new Spotlights(this._maxSpotlights, this._room);
store.dispatch(stateActions.setRoomState('connecting'));
this._signalingSocket.on('connect', () =>
@ -996,7 +1029,7 @@ export default class RoomClient
{
logger.debug('signaling Peer "room-ready" event');
this._joinRoom({ displayName, device });
this._joinRoom();
});
this._signalingSocket.on('room-locked', () =>
@ -1180,7 +1213,7 @@ export default class RoomClient
});
}
async _joinRoom({ displayName, device })
async _joinRoom()
{
logger.debug('_joinRoom()');
@ -1236,7 +1269,13 @@ export default class RoomClient
try
{
await this._room.join(this._peerName, { displayName, device });
await this._room.join(
this._peerName,
{
displayName : this._displayName,
device : this._device
}
);
store.dispatch(
stateActions.setFileSharingSupported(this._torrentSupport));
@ -1277,7 +1316,7 @@ export default class RoomClient
if (this._produce)
{
if (this._room.canSend('audio'))
this._setMicProducer();
await this._setMicProducer();
// Add our webcam (unless the cookie says no).
if (this._room.canSend('video'))
@ -1285,7 +1324,7 @@ export default class RoomClient
const devicesCookie = cookiesManager.getDevices();
if (!devicesCookie || devicesCookie.webcamEnabled)
this.enableWebcam();
await this.enableWebcam();
}
}
@ -1462,6 +1501,14 @@ export default class RoomClient
store.dispatch(stateActions.setProducerVolume(producer.id, volume));
}
});
this._audioContext = new AudioContext();
// We need to provoke user interaction to get permission from browser to start audio
if (this._audioContext.state === 'suspended')
{
store.dispatch(stateActions.setAudioSuspended({ audioSuspended: true }));
}
}
catch (error)
{
@ -1472,7 +1519,6 @@ export default class RoomClient
if (producer)
producer.close();
throw error;
}
}

View File

@ -1,5 +1,6 @@
import React, { Fragment } from 'react';
import { connect } from 'react-redux';
import { withRoomContext } from '../RoomContext';
import ReactTooltip from 'react-tooltip';
import PropTypes from 'prop-types';
import classnames from 'classnames';
@ -63,6 +64,7 @@ class Room extends React.Component
render()
{
const {
roomClient,
room,
amActiveSpeaker,
onRoomLinkCopy
@ -73,7 +75,31 @@ class Room extends React.Component
democratic : Peers
}[room.mode];
if (room.lockedOut)
if (room.audioSuspended)
{
return (
<Fragment>
<Appear duration={300}>
<div data-component='Room'>
<div className='sound-suspended'>
This webpage required sound and video to play, please click to allow.
<div
onClick={() =>
{
roomClient.notify('Joining.');
roomClient.resumeAudio();
}}
className='button'
>
<span>Allow</span>
</div>
</div>
</div>
</Appear>
</Fragment>
);
}
else if (room.lockedOut)
{
return (
<Fragment>
@ -186,6 +212,7 @@ class Room extends React.Component
Room.propTypes =
{
roomClient : PropTypes.object.isRequired,
room : appPropTypes.Room.isRequired,
me : appPropTypes.Me.isRequired,
amActiveSpeaker : PropTypes.bool.isRequired,
@ -228,9 +255,9 @@ const mapDispatchToProps = (dispatch) =>
};
};
const RoomContainer = connect(
const RoomContainer = withRoomContext(connect(
mapStateToProps,
mapDispatchToProps
)(Room);
)(Room));
export default RoomContainer;

View File

@ -120,7 +120,7 @@ function run()
// TODO: Debugging stuff.
global.CLIENT = roomClient;
setInterval(() =>
/* setInterval(() =>
{
if (!roomClient._room.peers[0])
{
@ -133,7 +133,7 @@ setInterval(() =>
global.CONSUMER = peer.consumers[peer.consumers.length - 1];
}, 2000);
*/
global.sendSdp = function()
{
logger.debug('---------- SEND_TRANSPORT LOCAL SDP OFFER:');

View File

@ -4,6 +4,7 @@ const initialState =
state : 'new', // new/connecting/connected/disconnected/closed,
locked : false,
lockedOut : false,
audioSuspended : false,
activeSpeakerName : null,
torrentSupport : false,
showSettings : false,
@ -52,6 +53,13 @@ const room = (state = initialState, action) =>
return { ...state, lockedOut: true };
}
case 'SET_AUDIO_SUSPENDED':
{
const { audioSuspended } = action.payload;
return { ...state, audioSuspended };
}
case 'SET_ROOM_ACTIVE_SPEAKER':
{
const { peerName } = action.payload;

View File

@ -43,6 +43,14 @@ export const setRoomLockedOut = () =>
};
};
export const setAudioSuspended = ({ audioSuspended }) =>
{
return {
type : 'SET_AUDIO_SUSPENDED',
payload : { audioSuspended }
};
};
export const setMe = ({ peerName, displayName, displayNameSet, device, loginEnabled }) =>
{
return {

View File

@ -15,6 +15,34 @@
padding: 2vmin;
}
> .sound-suspended {
position: fixed;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 30vw;
text-align: center;
font-family: 'Roboto';
font-size: 2.5em;
box-shadow: 0px 5px 12px 2px rgba(17, 17, 17, 0.5);
background-color: #fff;
padding: 2vmin;
> .button {
font-size: 1.5em;
padding: 1.5vmin;
margin: 0.8vmin;
background-color: #38cd8b;
border-radius: 1.8vmin;
color: #fff;
border: 0;
}
> .button:hover {
background-color: #28bd7b;
}
}
> .room-wrapper {
position: absolute;
top: 0;