webrtc config electron
init on LoggedInView mounting configurable via UserSettings new class: CallMediaHandler Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/21833/head
							parent
							
								
									0e880f7971
								
							
						
					
					
						commit
						c6262d62a6
					
				|  | @ -0,0 +1,63 @@ | |||
| /* | ||||
|  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 = {}; | ||||
| 
 | ||||
|             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); | ||||
|     }, | ||||
| }; | ||||
|  | @ -21,6 +21,7 @@ import React from 'react'; | |||
| import KeyCode from '../../KeyCode'; | ||||
| import Notifier from '../../Notifier'; | ||||
| import PageTypes from '../../PageTypes'; | ||||
| import CallMediaHandler from '../../CallMediaHandler'; | ||||
| import sdk from '../../index'; | ||||
| import dis from '../../dispatcher'; | ||||
| 
 | ||||
|  | @ -71,6 +72,10 @@ export default React.createClass({ | |||
|         // RoomView.getScrollState()
 | ||||
|         this._scrollStateMap = {}; | ||||
| 
 | ||||
|         // Only run these in electron, at least until a better mechanism for perms exists
 | ||||
|         // https://w3c.github.io/permissions/#dom-permissionname-device-info
 | ||||
|         if (window && window.process && window.process.type) CallMediaHandler.loadDevices(); | ||||
| 
 | ||||
|         document.addEventListener('keydown', this._onKeyDown); | ||||
|     }, | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ var dis = require("../../dispatcher"); | |||
| var q = require('q'); | ||||
| var package_json = require('../../../package.json'); | ||||
| var UserSettingsStore = require('../../UserSettingsStore'); | ||||
| var CallMediaHandler = require('../../CallMediaHandler'); | ||||
| var GeminiScrollbar = require('react-gemini-scrollbar'); | ||||
| var Email = require('../../email'); | ||||
| var AddThreepid = require('../../AddThreepid'); | ||||
|  | @ -109,7 +110,6 @@ const THEMES = [ | |||
|     } | ||||
| ]; | ||||
| 
 | ||||
| 
 | ||||
| module.exports = React.createClass({ | ||||
|     displayName: 'UserSettings', | ||||
| 
 | ||||
|  | @ -147,6 +147,7 @@ module.exports = React.createClass({ | |||
|             email_add_pending: false, | ||||
|             vectorVersion: null, | ||||
|             rejectingInvites: false, | ||||
|             mediaDevices: null, | ||||
|         }; | ||||
|     }, | ||||
| 
 | ||||
|  | @ -167,6 +168,18 @@ module.exports = React.createClass({ | |||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         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', | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         // 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
 | ||||
|  | @ -187,6 +200,8 @@ module.exports = React.createClass({ | |||
|         this._syncedSettings = syncedSettings; | ||||
| 
 | ||||
|         this._localSettings = UserSettingsStore.getLocalSettings(); | ||||
|         this._setAudioInput = this._setAudioInput.bind(this); | ||||
|         this._setVideoInput = this._setVideoInput.bind(this); | ||||
|     }, | ||||
| 
 | ||||
|     componentDidMount: function() { | ||||
|  | @ -775,6 +790,66 @@ 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); | ||||
|     }, | ||||
| 
 | ||||
|     _renderWebRtcSettings: function() { | ||||
|         if (!(window && window.process && window.process.type) | ||||
|          || !this.state.mediaDevices) return; | ||||
| 
 | ||||
|         const Dropdown = sdk.getComponent('elements.Dropdown'); | ||||
| 
 | ||||
|         let microphoneDropdown = <h5>No Microphones detected</h5>; | ||||
|         let webcamDropdown = <h5>No Webcams detected</h5>; | ||||
| 
 | ||||
|         const audioInputs = this.state.mediaDevices.audioinput; | ||||
|         if ('default' in audioInputs) { | ||||
|             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) { | ||||
|             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> | ||||
|             <div className="mx_UserSettings_section"> | ||||
|                 {microphoneDropdown} | ||||
|                 {webcamDropdown} | ||||
|             </div> | ||||
|         </div>; | ||||
|     }, | ||||
| 
 | ||||
|     _showSpoiler: function(event) { | ||||
|         const target = event.target; | ||||
|         const hidden = target.getAttribute('data-spoiler'); | ||||
|  | @ -973,6 +1048,7 @@ module.exports = React.createClass({ | |||
| 
 | ||||
|                 {this._renderUserInterfaceSettings()} | ||||
|                 {this._renderLabs()} | ||||
|                 {this._renderWebRtcSettings()} | ||||
|                 {this._renderDevicesPanel()} | ||||
|                 {this._renderCryptoInfo()} | ||||
|                 {this._renderBulkOptions()} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Telatynski
						Michael Telatynski