Merge branch 'feature-ptt' into develop
commit
9cd6efe761
|
|
@ -230,6 +230,9 @@ export default class RoomClient
|
||||||
// Local mic hark
|
// Local mic hark
|
||||||
this._hark = null;
|
this._hark = null;
|
||||||
|
|
||||||
|
// Local MediaStream for hark
|
||||||
|
this._harkStream = null
|
||||||
|
|
||||||
// Local webcam mediasoup Producer.
|
// Local webcam mediasoup Producer.
|
||||||
this._webcamProducer = null;
|
this._webcamProducer = null;
|
||||||
|
|
||||||
|
|
@ -278,8 +281,9 @@ export default class RoomClient
|
||||||
_startKeyListener()
|
_startKeyListener()
|
||||||
{
|
{
|
||||||
// Add keypress event listner on document
|
// Add keypress event listner on document
|
||||||
document.addEventListener('keypress', (event) =>
|
document.addEventListener('keydown', (event) =>
|
||||||
{
|
{
|
||||||
|
if (event.repeat) return;
|
||||||
const key = String.fromCharCode(event.which);
|
const key = String.fromCharCode(event.which);
|
||||||
|
|
||||||
const source = event.target;
|
const source = event.target;
|
||||||
|
|
@ -288,11 +292,11 @@ export default class RoomClient
|
||||||
|
|
||||||
if (exclude.indexOf(source.tagName.toLowerCase()) === -1)
|
if (exclude.indexOf(source.tagName.toLowerCase()) === -1)
|
||||||
{
|
{
|
||||||
logger.debug('keyPress() [key:"%s"]', key);
|
logger.debug('keyDown() [key:"%s"]', key);
|
||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case 'a': // Activate advanced mode
|
case 'A': // Activate advanced mode
|
||||||
{
|
{
|
||||||
store.dispatch(settingsActions.toggleAdvancedMode());
|
store.dispatch(settingsActions.toggleAdvancedMode());
|
||||||
store.dispatch(requestActions.notify(
|
store.dispatch(requestActions.notify(
|
||||||
|
|
@ -331,8 +335,19 @@ export default class RoomClient
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ' ':
|
case ' ': // Push To Talk start
|
||||||
case 'm': // Toggle microphone
|
{
|
||||||
|
if (this._micProducer)
|
||||||
|
{
|
||||||
|
if (this._micProducer.paused)
|
||||||
|
{
|
||||||
|
this.unmuteMic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'M': // Toggle microphone
|
||||||
{
|
{
|
||||||
if (this._micProducer)
|
if (this._micProducer)
|
||||||
{
|
{
|
||||||
|
|
@ -377,7 +392,7 @@ export default class RoomClient
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'v': // Toggle video
|
case 'V': // Toggle video
|
||||||
{
|
{
|
||||||
if (this._webcamProducer)
|
if (this._webcamProducer)
|
||||||
this.disableWebcam();
|
this.disableWebcam();
|
||||||
|
|
@ -394,6 +409,41 @@ export default class RoomClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
document.addEventListener('keyup', (event) =>
|
||||||
|
{
|
||||||
|
const key = String.fromCharCode(event.which);
|
||||||
|
|
||||||
|
const source = event.target;
|
||||||
|
|
||||||
|
const exclude = [ 'input', 'textarea' ];
|
||||||
|
|
||||||
|
if (exclude.indexOf(source.tagName.toLowerCase()) === -1)
|
||||||
|
{
|
||||||
|
logger.debug('keyUp() [key:"%s"]', key);
|
||||||
|
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case ' ': // Push To Talk stop
|
||||||
|
{
|
||||||
|
if (this._micProducer)
|
||||||
|
{
|
||||||
|
if (!this._micProducer.paused)
|
||||||
|
{
|
||||||
|
this.muteMic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_startDevicesListener()
|
_startDevicesListener()
|
||||||
|
|
@ -943,6 +993,16 @@ export default class RoomClient
|
||||||
'changeAudioDevice() | new selected webcam [device:%o]',
|
'changeAudioDevice() | new selected webcam [device:%o]',
|
||||||
device);
|
device);
|
||||||
|
|
||||||
|
if (this._hark != null)
|
||||||
|
this._hark.stop();
|
||||||
|
|
||||||
|
if (this._harkStream != null)
|
||||||
|
{
|
||||||
|
logger.debug('Stopping hark.');
|
||||||
|
this._harkStream.getAudioTracks()[0].stop();
|
||||||
|
this._harkStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (this._micProducer && this._micProducer.track)
|
if (this._micProducer && this._micProducer.track)
|
||||||
this._micProducer.track.stop();
|
this._micProducer.track.stop();
|
||||||
|
|
||||||
|
|
@ -964,17 +1024,15 @@ export default class RoomClient
|
||||||
if (this._micProducer)
|
if (this._micProducer)
|
||||||
this._micProducer.volume = 0;
|
this._micProducer.volume = 0;
|
||||||
|
|
||||||
const harkStream = new MediaStream();
|
this._harkStream = new MediaStream();
|
||||||
|
|
||||||
harkStream.addTrack(track);
|
this._harkStream.addTrack(track.clone());
|
||||||
|
this._harkStream.getAudioTracks()[0].enabled = true;
|
||||||
|
|
||||||
if (!harkStream.getAudioTracks()[0])
|
if (!this._harkStream.getAudioTracks()[0])
|
||||||
throw new Error('changeAudioDevice(): given stream has no audio track');
|
throw new Error('changeAudioDevice(): given stream has no audio track');
|
||||||
|
|
||||||
if (this._hark != null)
|
this._hark = hark(this._harkStream, { play: false });
|
||||||
this._hark.stop();
|
|
||||||
|
|
||||||
this._hark = hark(harkStream, { play: false });
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
this._hark.on('volume_change', (dBs, threshold) =>
|
this._hark.on('volume_change', (dBs, threshold) =>
|
||||||
|
|
@ -998,6 +1056,14 @@ export default class RoomClient
|
||||||
store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume));
|
store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this._hark.on('speaking', function()
|
||||||
|
{
|
||||||
|
store.dispatch(meActions.setIsSpeaking(true));
|
||||||
|
});
|
||||||
|
this._hark.on('stopped_speaking', function()
|
||||||
|
{
|
||||||
|
store.dispatch(meActions.setIsSpeaking(false));
|
||||||
|
});
|
||||||
if (this._micProducer && this._micProducer.id)
|
if (this._micProducer && this._micProducer.id)
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
producerActions.setProducerTrack(this._micProducer.id, track));
|
producerActions.setProducerTrack(this._micProducer.id, track));
|
||||||
|
|
@ -2620,8 +2686,11 @@ export default class RoomClient
|
||||||
track,
|
track,
|
||||||
codecOptions :
|
codecOptions :
|
||||||
{
|
{
|
||||||
opusStereo : 1,
|
opusStereo : false,
|
||||||
opusDtx : 1
|
opusDtx : true,
|
||||||
|
opusFec : true,
|
||||||
|
opusPtime : '3',
|
||||||
|
opusMaxPlaybackRate : 48000
|
||||||
},
|
},
|
||||||
appData :
|
appData :
|
||||||
{ source: 'mic' }
|
{ source: 'mic' }
|
||||||
|
|
@ -2663,17 +2732,20 @@ export default class RoomClient
|
||||||
|
|
||||||
this._micProducer.volume = 0;
|
this._micProducer.volume = 0;
|
||||||
|
|
||||||
const harkStream = new MediaStream();
|
|
||||||
|
|
||||||
harkStream.addTrack(track);
|
|
||||||
|
|
||||||
if (!harkStream.getAudioTracks()[0])
|
|
||||||
throw new Error('enableMic(): given stream has no audio track');
|
|
||||||
|
|
||||||
if (this._hark != null)
|
if (this._hark != null)
|
||||||
this._hark.stop();
|
this._hark.stop();
|
||||||
|
|
||||||
this._hark = hark(harkStream, { play: false });
|
if (this._harkStream != null)
|
||||||
|
this._harkStream.getAudioTracks()[0].stop();
|
||||||
|
|
||||||
|
this._harkStream = new MediaStream();
|
||||||
|
|
||||||
|
this._harkStream.addTrack(track.clone());
|
||||||
|
|
||||||
|
if (!this._harkStream.getAudioTracks()[0])
|
||||||
|
throw new Error('enableMic(): given stream has no audio track');
|
||||||
|
|
||||||
|
this._hark = hark(this._harkStream, { play: false });
|
||||||
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
this._hark.on('volume_change', (dBs, threshold) =>
|
this._hark.on('volume_change', (dBs, threshold) =>
|
||||||
|
|
@ -2697,6 +2769,14 @@ export default class RoomClient
|
||||||
store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume));
|
store.dispatch(peerVolumeActions.setPeerVolume(this._peerId, volume));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this._hark.on('speaking', function()
|
||||||
|
{
|
||||||
|
store.dispatch(meActions.setIsSpeaking(true));
|
||||||
|
});
|
||||||
|
this._hark.on('stopped_speaking', function()
|
||||||
|
{
|
||||||
|
store.dispatch(meActions.setIsSpeaking(false));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (error)
|
catch (error)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -91,3 +91,9 @@ export const setDisplayNameInProgress = (flag) =>
|
||||||
type : 'SET_DISPLAY_NAME_IN_PROGRESS',
|
type : 'SET_DISPLAY_NAME_IN_PROGRESS',
|
||||||
payload : { flag }
|
payload : { flag }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setIsSpeaking = (flag) =>
|
||||||
|
({
|
||||||
|
type : 'SET_IS_SPEAKING',
|
||||||
|
payload : { flag }
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,26 @@ const styles = (theme) =>
|
||||||
fontSize : '7em',
|
fontSize : '7em',
|
||||||
margin : 0
|
margin : 0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
ptt :
|
||||||
|
{
|
||||||
|
position : 'absolute',
|
||||||
|
float : 'left',
|
||||||
|
bottom : '10%',
|
||||||
|
left : '50%',
|
||||||
|
transform : 'translate(-50%, 0%)',
|
||||||
|
color : 'rgba(255, 255, 255, 0.7)',
|
||||||
|
fontSize : '2vs',
|
||||||
|
backgroundColor : 'rgba(255, 0, 0, 0.5)',
|
||||||
|
margin : '4px',
|
||||||
|
padding : '15px',
|
||||||
|
borderRadius : '20px',
|
||||||
|
textAlign : 'center',
|
||||||
|
opacity : 0,
|
||||||
|
'&.enabled' :
|
||||||
|
{
|
||||||
|
opacity : 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -272,7 +292,7 @@ const Me = (props) =>
|
||||||
>
|
>
|
||||||
<div className={classnames(classes.viewContainer)} style={style}>
|
<div className={classnames(classes.viewContainer)} style={style}>
|
||||||
<div
|
<div
|
||||||
className={classnames(classes.controls, hover ? 'hover' : null)}
|
className={classnames(classes.controls, 'hover')}
|
||||||
onMouseOver={() => setHover(true)}
|
onMouseOver={() => setHover(true)}
|
||||||
onMouseOut={() => setHover(false)}
|
onMouseOut={() => setHover(false)}
|
||||||
onTouchStart={() =>
|
onTouchStart={() =>
|
||||||
|
|
@ -293,12 +313,20 @@ const Me = (props) =>
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>
|
<p className={classnames(hover ? 'hover' : null)}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='room.me'
|
id='room.me'
|
||||||
defaultMessage='ME'
|
defaultMessage='ME'
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div className={classnames(classes.ptt, (micState ==='muted' && me.isSpeaking) ? 'enabled' : null)} >
|
||||||
|
<FormattedMessage
|
||||||
|
id='me.mutedPTT'
|
||||||
|
defaultMessage='You are muted: hold SPACE-BAR to speak!'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{ !me.isMobile &&
|
{ !me.isMobile &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Tooltip title={micTip} placement={smallScreen ? 'top' : 'left'}>
|
<Tooltip title={micTip} placement={smallScreen ? 'top' : 'left'}>
|
||||||
|
|
@ -416,7 +444,7 @@ const Me = (props) =>
|
||||||
roomClient.changeDisplayName(displayName);
|
roomClient.changeDisplayName(displayName);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Volume id={me.id} />
|
{ micState === 'muted' ? null : <Volume id={me.id} /> }
|
||||||
</VideoView>
|
</VideoView>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ const initialState =
|
||||||
loginEnabled : false,
|
loginEnabled : false,
|
||||||
raiseHand : false,
|
raiseHand : false,
|
||||||
raiseHandInProgress : false,
|
raiseHandInProgress : false,
|
||||||
loggedIn : false
|
loggedIn : false,
|
||||||
|
isSpeaking : false
|
||||||
};
|
};
|
||||||
|
|
||||||
const me = (state = initialState, action) =>
|
const me = (state = initialState, action) =>
|
||||||
|
|
@ -147,6 +148,13 @@ const me = (state = initialState, action) =>
|
||||||
return { ...state, displayNameInProgress: flag };
|
return { ...state, displayNameInProgress: flag };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'SET_IS_SPEAKING':
|
||||||
|
{
|
||||||
|
const { flag } = action.payload;
|
||||||
|
|
||||||
|
return { ...state, isSpeaking: flag };
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue