Add a not yet complete audio out selection.

auto_join_3.3
Mészáros Mihály 2020-04-18 23:20:58 +02:00
parent bb9c07de3b
commit e98d80ed57
7 changed files with 164 additions and 5 deletions

View File

@ -244,6 +244,8 @@ export default class RoomClient
this._audioDevices = {}; this._audioDevices = {};
this._audioOutputDevices = {};
// mediasoup Consumers. // mediasoup Consumers.
// @type {Map<String, mediasoupClient.Consumer>} // @type {Map<String, mediasoupClient.Consumer>}
this._consumers = new Map(); this._consumers = new Map();
@ -1107,6 +1109,50 @@ export default class RoomClient
meActions.setAudioInProgress(false)); meActions.setAudioInProgress(false));
} }
async changeAudioOutputDevice(deviceId)
{
logger.debug('changeAudioOutputDevice() [deviceId: %s]', deviceId);
store.dispatch(
meActions.setAudioOutputInProgress(true));
try
{
const device = this._audioOutputDevices[deviceId];
if (!device)
throw new Error('Selected audio output device no longer avaibale');
logger.debug(
'changeAudioOutputDevice() | new selected [audio output device:%o]',
device);
const audioElements = document.getElementById("audio");
for( let i=0; i<audioElements; i++){
if (typeof audioElements[0].setSinkId === 'function'){
if (i === 0) logger.debug('changeAudioOutputDevice()');
await audioElements[i].setSinkId(deviceId);
} else {
logger.debug('changeAudioOutputDevice() | setSinkId not implemented');
break;
}
};
store.dispatch(settingsActions.setSelectedAudioOutputDevice(deviceId));
await this._updateAudioOutputDevices();
}
catch (error)
{
logger.error('changeAudioOutputDevice() failed: %o', error);
}
store.dispatch(
meActions.setAudioOutputInProgress(false));
}
async changeVideoResolution(resolution) async changeVideoResolution(resolution)
{ {
logger.debug('changeVideoResolution() [resolution: %s]', resolution); logger.debug('changeVideoResolution() [resolution: %s]', resolution);
@ -2642,6 +2688,8 @@ export default class RoomClient
if (joinVideo && this._mediasoupDevice.canProduce('video')) if (joinVideo && this._mediasoupDevice.canProduce('video'))
this.enableWebcam(); this.enableWebcam();
} }
this._updateAudioOutputDevices();
store.dispatch(roomActions.setRoomState('connected')); store.dispatch(roomActions.setRoomState('connected'));
@ -3441,4 +3489,35 @@ export default class RoomClient
logger.error('_getWebcamDeviceId() failed:%o', error); logger.error('_getWebcamDeviceId() failed:%o', error);
} }
} }
async _updateAudioOutputDevices()
{
logger.debug('_updateAudioOutputDevices()');
// Reset the list.
this._audioOutputDevices = {};
try
{
logger.debug('_updateAudioOutputDevices() | calling enumerateDevices()');
const devices = await navigator.mediaDevices.enumerateDevices();
for (const device of devices)
{
if (device.kind !== 'audiooutput')
continue;
this._audioOutputDevices[device.deviceId] = device;
}
store.dispatch(
meActions.setAudioOutputDevices(this._audioOutputDevices));
}
catch (error)
{
logger.error('_updateAudioOutputDevices() failed:%o', error);
}
}
} }

View File

@ -31,6 +31,8 @@ beforeEach(() =>
me : { me : {
audioDevices : null, audioDevices : null,
audioInProgress : false, audioInProgress : false,
audioOutputDevices : null,
audioOutputInProgress : false,
canSendMic : false, canSendMic : false,
canSendWebcam : false, canSendWebcam : false,
canShareFiles : false, canShareFiles : false,
@ -72,11 +74,12 @@ beforeEach(() =>
windowConsumer : null windowConsumer : null
}, },
settings : { settings : {
advancedMode : true, advancedMode : true,
displayName : 'Jest Tester', displayName : 'Jest Tester',
resolution : 'ultra', resolution : 'ultra',
selectedAudioDevice : 'default', selectedAudioDevice : 'default',
selectedWebcam : 'soifjsiajosjfoi' selectedAudioOutputDevice : 'default',
selectedWebcam : 'soifjsiajosjfoi'
}, },
toolarea : { toolarea : {
currentToolTab : 'chat', currentToolTab : 'chat',

View File

@ -50,6 +50,12 @@ export const setAudioDevices = (devices) =>
payload : { devices } payload : { devices }
}); });
export const setAudioOutputDevices = (devices) =>
({
type : 'SET_AUDIO_OUTPUT_DEVICES',
payload : { devices }
});
export const setWebcamDevices = (devices) => export const setWebcamDevices = (devices) =>
({ ({
type : 'SET_WEBCAM_DEVICES', type : 'SET_WEBCAM_DEVICES',
@ -67,6 +73,12 @@ export const setAudioInProgress = (flag) =>
type : 'SET_AUDIO_IN_PROGRESS', type : 'SET_AUDIO_IN_PROGRESS',
payload : { flag } payload : { flag }
}); });
export const setAudioOutputInProgress = (flag) =>
({
type : 'SET_AUDIO_OUTPUT_IN_PROGRESS',
payload : { flag }
});
export const setWebcamInProgress = (flag) => export const setWebcamInProgress = (flag) =>
({ ({

View File

@ -4,6 +4,12 @@ export const setSelectedAudioDevice = (deviceId) =>
payload : { deviceId } payload : { deviceId }
}); });
export const setSelectedAudioOutputDevice = (deviceId) =>
({
type : 'CHANGE_AUDIO_OUTPUT_DEVICE',
payload : { deviceId }
});
export const setSelectedWebcamDevice = (deviceId) => export const setSelectedWebcamDevice = (deviceId) =>
({ ({
type : 'CHANGE_WEBCAM', type : 'CHANGE_WEBCAM',

View File

@ -130,6 +130,13 @@ const Settings = ({
audioDevices = Object.values(me.audioDevices); audioDevices = Object.values(me.audioDevices);
else else
audioDevices = []; audioDevices = [];
let audioOutputDevices;
if (me.audioOutputDevices)
audioOutputDevices = Object.values(me.audioOutputDevices);
else
audioOutputDevices = [];
return ( return (
<Dialog <Dialog
@ -226,6 +233,46 @@ const Settings = ({
</FormHelperText> </FormHelperText>
</FormControl> </FormControl>
</form> </form>
<form className={classes.setting} autoComplete='off'>
<FormControl className={classes.formControl}>
<Select
value={settings.selectedAudioOutputDevice || ''}
onChange={(event) =>
{
if (event.target.value)
roomClient.changeAudioOutputDevice(event.target.value);
}}
displayEmpty
name={intl.formatMessage({
id : 'settings.audio.output',
defaultMessage : 'Audio output device'
})}
autoWidth
className={classes.selectEmpty}
disabled={audioOutputDevices.length === 0 || me.audioOutputInProgress}
>
{ audioOutputDevices.map((audioOutput, index) =>
{
return (
<MenuItem key={index} value={audioOutput.deviceId}>{audioOutput.label}</MenuItem>
);
})}
</Select>
<FormHelperText>
{ audioOutputDevices.length > 0 ?
intl.formatMessage({
id : 'settings.selectAudio.output',
defaultMessage : 'Select audio output device'
})
:
intl.formatMessage({
id : 'settings.cantSelectAudio.output',
defaultMessage : 'Unable to select audio output device'
})
}
</FormHelperText>
</FormControl>
</form>
<form className={classes.setting} autoComplete='off'> <form className={classes.setting} autoComplete='off'>
<FormControl className={classes.formControl}> <FormControl className={classes.formControl}>
<Select <Select

View File

@ -97,6 +97,13 @@ const me = (state = initialState, action) =>
return { ...state, audioDevices: devices }; return { ...state, audioDevices: devices };
} }
case 'SET_AUDIO_OUTPUT_DEVICES':
{
const { devices } = action.payload;
return { ...state, audioOutputDevices: devices };
}
case 'SET_WEBCAM_DEVICES': case 'SET_WEBCAM_DEVICES':
{ {
const { devices } = action.payload; const { devices } = action.payload;

View File

@ -23,6 +23,11 @@ const settings = (state = initialState, action) =>
return { ...state, selectedAudioDevice: action.payload.deviceId }; return { ...state, selectedAudioDevice: action.payload.deviceId };
} }
case 'CHANGE_AUDIO_OUTPUT_DEVICE':
{
return { ...state, selectedAudioOutputDevice: action.payload.deviceId };
}
case 'SET_DISPLAY_NAME': case 'SET_DISPLAY_NAME':
{ {
const { displayName } = action.payload; const { displayName } = action.payload;