Merge pull request #1932 from matrix-org/t3chguy/audio_output

Select audio output for WebRTC
This commit is contained in:
Michael Telatynski 2018-06-14 11:11:53 +01:00 committed by GitHub
commit 3165a99f52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 8 deletions

View File

@ -22,34 +22,44 @@ export default {
// Only needed for Electron atm, though should work in modern browsers // Only needed for Electron atm, though should work in modern browsers
// once permission has been granted to the webapp // once permission has been granted to the webapp
return navigator.mediaDevices.enumerateDevices().then(function(devices) { return navigator.mediaDevices.enumerateDevices().then(function(devices) {
const audioIn = []; const audiooutput = [];
const videoIn = []; const audioinput = [];
const videoinput = [];
if (devices.some((device) => !device.label)) return false; if (devices.some((device) => !device.label)) return false;
devices.forEach((device) => { devices.forEach((device) => {
switch (device.kind) { switch (device.kind) {
case 'audioinput': audioIn.push(device); break; case 'audiooutput': audiooutput.push(device); break;
case 'videoinput': videoIn.push(device); break; case 'audioinput': audioinput.push(device); break;
case 'videoinput': videoinput.push(device); break;
} }
}); });
// console.log("Loaded WebRTC Devices", mediaDevices); // console.log("Loaded WebRTC Devices", mediaDevices);
return { return {
audioinput: audioIn, audiooutput,
videoinput: videoIn, audioinput,
videoinput,
}; };
}, (error) => { console.log('Unable to refresh WebRTC Devices: ', error); }); }, (error) => { console.log('Unable to refresh WebRTC Devices: ', error); });
}, },
loadDevices: function() { loadDevices: function() {
const audioOutDeviceId = SettingsStore.getValue("webrtc_audiooutput");
const audioDeviceId = SettingsStore.getValue("webrtc_audioinput"); const audioDeviceId = SettingsStore.getValue("webrtc_audioinput");
const videoDeviceId = SettingsStore.getValue("webrtc_videoinput"); const videoDeviceId = SettingsStore.getValue("webrtc_videoinput");
Matrix.setMatrixCallAudioOutput(audioOutDeviceId);
Matrix.setMatrixCallAudioInput(audioDeviceId); Matrix.setMatrixCallAudioInput(audioDeviceId);
Matrix.setMatrixCallVideoInput(videoDeviceId); Matrix.setMatrixCallVideoInput(videoDeviceId);
}, },
setAudioOutput: function(deviceId) {
SettingsStore.setValue("webrtc_audiooutput", null, SettingLevel.DEVICE, deviceId);
Matrix.setMatrixCallAudioOutput(deviceId);
},
setAudioInput: function(deviceId) { setAudioInput: function(deviceId) {
SettingsStore.setValue("webrtc_audioinput", null, SettingLevel.DEVICE, deviceId); SettingsStore.setValue("webrtc_audioinput", null, SettingLevel.DEVICE, deviceId);
Matrix.setMatrixCallAudioInput(deviceId); Matrix.setMatrixCallAudioInput(deviceId);

View File

@ -298,6 +298,7 @@ module.exports = React.createClass({
if (this._unmounted) return; if (this._unmounted) return;
this.setState({ this.setState({
mediaDevices, mediaDevices,
activeAudioOutput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_audiooutput'),
activeAudioInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_audioinput'), activeAudioInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_audioinput'),
activeVideoInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_videoinput'), activeVideoInput: SettingsStore.getValueAt(SettingLevel.DEVICE, 'webrtc_videoinput'),
}); });
@ -976,6 +977,11 @@ module.exports = React.createClass({
return devices.map((device) => <span key={device.deviceId}>{ device.label }</span>); return devices.map((device) => <span key={device.deviceId}>{ device.label }</span>);
}, },
_setAudioOutput: function(deviceId) {
this.setState({activeAudioOutput: deviceId});
CallMediaHandler.setAudioOutput(deviceId);
},
_setAudioInput: function(deviceId) { _setAudioInput: function(deviceId) {
this.setState({activeAudioInput: deviceId}); this.setState({activeAudioInput: deviceId});
CallMediaHandler.setAudioInput(deviceId); CallMediaHandler.setAudioInput(deviceId);
@ -1016,6 +1022,7 @@ module.exports = React.createClass({
const Dropdown = sdk.getComponent('elements.Dropdown'); const Dropdown = sdk.getComponent('elements.Dropdown');
let speakerDropdown = <p>{ _t('No Audio Outputs detected') }</p>;
let microphoneDropdown = <p>{ _t('No Microphones detected') }</p>; let microphoneDropdown = <p>{ _t('No Microphones detected') }</p>;
let webcamDropdown = <p>{ _t('No Webcams detected') }</p>; let webcamDropdown = <p>{ _t('No Webcams detected') }</p>;
@ -1024,6 +1031,26 @@ module.exports = React.createClass({
label: _t('Default Device'), label: _t('Default Device'),
}; };
const audioOutputs = this.state.mediaDevices.audiooutput.slice(0);
if (audioOutputs.length > 0) {
let defaultOutput = '';
if (!audioOutputs.some((input) => input.deviceId === 'default')) {
audioOutputs.unshift(defaultOption);
} else {
defaultOutput = 'default';
}
speakerDropdown = <div>
<h4>{ _t('Audio Output') }</h4>
<Dropdown
className="mx_UserSettings_webRtcDevices_dropdown"
value={this.state.activeAudioOutput || defaultOutput}
onOptionChange={this._setAudioOutput}>
{ this._mapWebRtcDevicesToSpans(audioOutputs) }
</Dropdown>
</div>;
}
const audioInputs = this.state.mediaDevices.audioinput.slice(0); const audioInputs = this.state.mediaDevices.audioinput.slice(0);
if (audioInputs.length > 0) { if (audioInputs.length > 0) {
let defaultInput = ''; let defaultInput = '';
@ -1065,6 +1092,7 @@ module.exports = React.createClass({
} }
return <div> return <div>
{ speakerDropdown }
{ microphoneDropdown } { microphoneDropdown }
{ webcamDropdown } { webcamDropdown }
</div>; </div>;

View File

@ -1079,9 +1079,11 @@
"No media permissions": "No media permissions", "No media permissions": "No media permissions",
"You may need to manually permit Riot to access your microphone/webcam": "You may need to manually permit Riot to access your microphone/webcam", "You may need to manually permit Riot to access your microphone/webcam": "You may need to manually permit Riot to access your microphone/webcam",
"Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.", "Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.",
"No Audio Outputs detected": "No Audio Outputs detected",
"No Microphones detected": "No Microphones detected", "No Microphones detected": "No Microphones detected",
"No Webcams detected": "No Webcams detected", "No Webcams detected": "No Webcams detected",
"Default Device": "Default Device", "Default Device": "Default Device",
"Audio Output": "Audio Output",
"Microphone": "Microphone", "Microphone": "Microphone",
"Camera": "Camera", "Camera": "Camera",
"VoIP": "VoIP", "VoIP": "VoIP",

View File

@ -201,6 +201,10 @@ export const SETTINGS = {
displayName: _td('Disable Peer-to-Peer for 1:1 calls'), displayName: _td('Disable Peer-to-Peer for 1:1 calls'),
default: false, default: false,
}, },
"webrtc_audiooutput": {
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
default: null,
},
"webrtc_audioinput": { "webrtc_audioinput": {
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
default: null, default: null,