-
-
Notifications
You must be signed in to change notification settings - Fork 828
webrtc config electron #850
Changes from 6 commits
c6262d6
110ca22
b944fff
a4b2bac
09d0ab7
8158ec6
04b86e5
dbba1de
0c36778
aa90d6b
dd4480f
4e36c10
0f2c89d
beedeec
3eb519b
46a9326
4976cbb
0bafd64
6b4daf0
f4db83a
b1973d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com> | ||
|
||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
|
||
http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
import UserSettingsStore from './UserSettingsStore'; | ||
import * as Matrix from 'matrix-js-sdk'; | ||
import q from 'q'; | ||
|
||
export default { | ||
getDevices: function() { | ||
// Only needed for Electron atm, though should work in modern browsers | ||
// once permission has been granted to the webapp | ||
return navigator.mediaDevices.enumerateDevices().then(function(devices) { | ||
const audioIn = {}; | ||
const videoIn = {}; | ||
|
||
if (devices.some((device) => !device.label)) return false; | ||
|
||
devices.forEach((device) => { | ||
switch (device.kind) { | ||
case 'audioinput': audioIn[device.deviceId] = device.label; break; | ||
case 'videoinput': videoIn[device.deviceId] = device.label; break; | ||
} | ||
}); | ||
|
||
// console.log("Loaded WebRTC Devices", mediaDevices); | ||
return { | ||
audioinput: audioIn, | ||
videoinput: videoIn, | ||
}; | ||
}, (error) => { console.log('Unable to refresh WebRTC Devices: ', error); }); | ||
}, | ||
|
||
loadDevices: function() { | ||
// this.getDevices().then((devices) => { | ||
const localSettings = UserSettingsStore.getLocalSettings(); | ||
// // if deviceId is not found, automatic fallback is in spec | ||
// // recall previously stored inputs if any | ||
Matrix.setMatrixCallAudioInput(localSettings['webrtc_audioinput']); | ||
Matrix.setMatrixCallVideoInput(localSettings['webrtc_videoinput']); | ||
// }); | ||
}, | ||
|
||
setAudioInput: function(deviceId) { | ||
UserSettingsStore.setLocalSetting('webrtc_audioinput', deviceId); | ||
Matrix.setMatrixCallAudioInput(deviceId); | ||
}, | ||
|
||
setVideoInput: function(deviceId) { | ||
UserSettingsStore.setLocalSetting('webrtc_videoinput', deviceId); | ||
Matrix.setMatrixCallVideoInput(deviceId); | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ const dis = require("../../dispatcher"); | |
const q = require('q'); | ||
const packageJson = require('../../../package.json'); | ||
const UserSettingsStore = require('../../UserSettingsStore'); | ||
const CallMediaHandler = require('../../CallMediaHandler'); | ||
const GeminiScrollbar = require('react-gemini-scrollbar'); | ||
const Email = require('../../email'); | ||
const AddThreepid = require('../../AddThreepid'); | ||
|
@@ -119,7 +120,6 @@ const THEMES = [ | |
}, | ||
]; | ||
|
||
|
||
module.exports = React.createClass({ | ||
displayName: 'UserSettings', | ||
|
||
|
@@ -157,6 +157,7 @@ module.exports = React.createClass({ | |
email_add_pending: false, | ||
vectorVersion: undefined, | ||
rejectingInvites: false, | ||
mediaDevices: null, | ||
}; | ||
}, | ||
|
||
|
@@ -177,6 +178,8 @@ module.exports = React.createClass({ | |
}); | ||
} | ||
|
||
this._refreshMediaDevices(); | ||
|
||
// Bulk rejecting invites: | ||
// /sync won't have had time to return when UserSettings re-renders from state changes, so getRooms() | ||
// will still return rooms with invites. To get around this, add a listener for | ||
|
@@ -218,6 +221,20 @@ module.exports = React.createClass({ | |
} | ||
}, | ||
|
||
_refreshMediaDevices: function() { | ||
q().then(() => { | ||
return CallMediaHandler.getDevices(); | ||
}).then((mediaDevices) => { | ||
// console.log("got mediaDevices", mediaDevices, this._unmounted); | ||
if (this._unmounted) return; | ||
this.setState({ | ||
mediaDevices, | ||
activeAudioInput: this._localSettings['webrtc_audioinput'] || 'default', | ||
activeVideoInput: this._localSettings['webrtc_videoinput'] || 'default', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do these need changing also? |
||
}); | ||
}); | ||
}, | ||
|
||
_refreshFromServer: function() { | ||
const self = this; | ||
q.all([ | ||
|
@@ -787,6 +804,93 @@ module.exports = React.createClass({ | |
</div>; | ||
}, | ||
|
||
_mapWebRtcDevicesToSpans: function(devices) { | ||
return Object.keys(devices).map( | ||
(deviceId) => <span key={deviceId}>{devices[deviceId]}</span> | ||
); | ||
}, | ||
|
||
_setAudioInput: function(deviceId) { | ||
this.setState({activeAudioInput: deviceId}); | ||
CallMediaHandler.setAudioInput(deviceId); | ||
}, | ||
|
||
_setVideoInput: function(deviceId) { | ||
this.setState({activeVideoInput: deviceId}); | ||
CallMediaHandler.setVideoInput(deviceId); | ||
}, | ||
|
||
_requestMediaPermissions: function(event) { | ||
const getUserMedia = ( | ||
window.navigator.getUserMedia || window.navigator.webkitGetUserMedia || window.navigator.mozGetUserMedia | ||
); | ||
if (getUserMedia) { | ||
return getUserMedia.apply(window.navigator, [ | ||
{ video: true, audio: true }, | ||
this._refreshMediaDevices, | ||
function() { | ||
const ErrorDialog = sdk.getComponent('dialogs.ErrorDialog'); | ||
Modal.createDialog(ErrorDialog, { | ||
title: "No media permissions", | ||
description: "You may need to manually permit Riot to access your microphone/webcam", | ||
}); | ||
}, | ||
]); | ||
} | ||
}, | ||
|
||
_renderWebRtcSettings: function() { | ||
if (this.state.mediaDevices === false) { | ||
return <div> | ||
<h3>WebRTC</h3> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's call it VoIP. needs i18n |
||
<div className="mx_UserSettings_section"> | ||
<p className="mx_UserSettings_link" onClick={this._requestMediaPermissions}> | ||
Missing Media Permissions, click here to request. | ||
</p> | ||
</div> | ||
</div>; | ||
} else if (!this.state.mediaDevices) return; | ||
|
||
const Dropdown = sdk.getComponent('elements.Dropdown'); | ||
|
||
let microphoneDropdown = <p>No Microphones detected</p>; | ||
let webcamDropdown = <p>No Webcams detected</p>; | ||
|
||
const audioInputs = this.state.mediaDevices.audioinput; | ||
if ('default' in audioInputs) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needs |
||
microphoneDropdown = <div> | ||
<h4>Microphone</h4> | ||
<Dropdown | ||
className="mx_UserSettings_webRtcDevices_dropdown" | ||
value={this.state.activeAudioInput} | ||
onOptionChange={this._setAudioInput}> | ||
{this._mapWebRtcDevicesToSpans(audioInputs)} | ||
</Dropdown> | ||
</div>; | ||
} | ||
|
||
const videoInputs = this.state.mediaDevices.videoinput; | ||
if ('default' in videoInputs) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needs |
||
webcamDropdown = <div> | ||
<h4>Cameras</h4> | ||
<Dropdown | ||
className="mx_UserSettings_webRtcDevices_dropdown" | ||
value={this.state.activeVideoInput} | ||
onOptionChange={this._setVideoInput}> | ||
{this._mapWebRtcDevicesToSpans(videoInputs)} | ||
</Dropdown> | ||
</div>; | ||
} | ||
|
||
return <div> | ||
<h3>WebRTC</h3> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's call it VoIP, and i18n please |
||
<div className="mx_UserSettings_section"> | ||
{microphoneDropdown} | ||
{webcamDropdown} | ||
</div> | ||
</div>; | ||
}, | ||
|
||
_showSpoiler: function(event) { | ||
const target = event.target; | ||
target.innerHTML = target.getAttribute('data-spoiler'); | ||
|
@@ -983,6 +1087,7 @@ module.exports = React.createClass({ | |
|
||
{this._renderUserInterfaceSettings()} | ||
{this._renderLabs()} | ||
{this._renderWebRtcSettings()} | ||
{this._renderDevicesPanel()} | ||
{this._renderCryptoInfo()} | ||
{this._renderBulkOptions()} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels a bit weird - shouldn't this be operating on a MatrixClient rather than importing the whole js-sdk as
Matrix
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ara4n it's in the same class as createNewMatrixCall is in, which looking at VectorConferenceHandler is used in the same manner. Just following the patterns I see. The other way to do it would be to pass the devices when initiating/answering a call, would you prefer this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, ok. i guess this is ok