Kaynağa Gözat

feat(audio-only): be able to lock a browser into capturing audio only (#2125)

* feat(audio-only): be able to lock a browser into capturing audio only

* squash: try to make string more clear about audio only support

* squash: final strings
master
virtuacoplenny 8 yıl önce
ebeveyn
işleme
5c464a7bda

+ 1
- 7
conference.js Dosyayı Görüntüle

@@ -29,8 +29,7 @@ import {
29 29
     EMAIL_COMMAND,
30 30
     lockStateChanged,
31 31
     p2pStatusChanged,
32
-    sendLocalParticipant,
33
-    toggleAudioOnly
32
+    sendLocalParticipant
34 33
 } from './react/features/base/conference';
35 34
 import { updateDeviceList } from './react/features/base/devices';
36 35
 import {
@@ -554,11 +553,6 @@ export default {
554 553
 
555 554
         let tryCreateLocalTracks;
556 555
 
557
-        // Enable audio only mode
558
-        if (config.startAudioOnly) {
559
-            APP.store.dispatch(toggleAudioOnly());
560
-        }
561
-
562 556
         // FIXME is there any simpler way to rewrite this spaghetti below ?
563 557
         if (options.startScreenSharing) {
564 558
             tryCreateLocalTracks = this._createDesktopTrack()

+ 25
- 2
css/modals/video-quality/_video-quality.scss Dosyayı Görüntüle

@@ -1,5 +1,4 @@
1 1
 .video-quality-dialog {
2
-
3 2
     .hide-warning {
4 3
         height: 0;
5 4
         visibility: hidden;
@@ -27,7 +26,7 @@
27 26
             @mixin sliderTrackStyles() {
28 27
                 height: 15px;
29 28
                 border-radius: 10px;
30
-                background: #0E1624;
29
+                background: rgb(14, 22, 36);
31 30
             }
32 31
 
33 32
             &::-ms-track {
@@ -110,6 +109,30 @@
110 109
             word-spacing: unset;
111 110
         }
112 111
     }
112
+
113
+    &.video-not-supported {
114
+        .video-quality-dialog-labels {
115
+            color: gray;
116
+        }
117
+
118
+        .video-quality-dialog-slider {
119
+            @mixin sliderTrackDisabledStyles() {
120
+                background: rgba(14, 22, 36, 0.1);
121
+            }
122
+
123
+            &::-ms-track {
124
+                @include sliderTrackDisabledStyles();
125
+            }
126
+
127
+            &::-moz-range-track {
128
+                @include sliderTrackDisabledStyles();
129
+            }
130
+
131
+            &::-webkit-slider-runnable-track {
132
+                @include sliderTrackDisabledStyles();
133
+            }
134
+        }
135
+    }
113 136
 }
114 137
 
115 138
 .video-state-indicator {

+ 2
- 0
lang/main.json Dosyayı Görüntüle

@@ -470,6 +470,8 @@
470 470
         "labelTooltipAudioOnly":  "Audio-only mode enabled",
471 471
         "ld": "LD",
472 472
         "lowDefinition": "Low definition",
473
+        "onlyAudioAvailable": "Only audio is available",
474
+        "onlyAudioSupported": "We only support audio in this browser.",
473 475
         "p2pEnabled": "Peer to Peer Enabled",
474 476
         "p2pVideoQualityDescription": "In peer to peer mode, received call quality can only be toggled between high and audio only. Other settings will not be honored until peer to peer is exited.",
475 477
         "recHighDefinitionOnly": "Will prefer high definition.",

+ 13
- 3
react/features/base/media/middleware.js Dosyayı Görüntüle

@@ -3,6 +3,7 @@
3 3
 import { sendAnalyticsEvent } from '../../analytics';
4 4
 import { SET_ROOM, setAudioOnly } from '../conference';
5 5
 import { parseURLParams } from '../config';
6
+import JitsiMeetJS from '../lib-jitsi-meet';
6 7
 import { MiddlewareRegistry } from '../redux';
7 8
 import { setTrackMuted, TRACK_ADDED } from '../tracks';
8 9
 
@@ -108,10 +109,19 @@ function _setRoom({ dispatch, getState }, next, action) {
108 109
     // because it looks like config.startWithAudioMuted and
109 110
     // config.startWithVideoMuted.
110 111
     if (room) {
111
-        let audioOnly = urlParams && urlParams['config.startAudioOnly'];
112
+        let audioOnly;
113
+
114
+        if (JitsiMeetJS.mediaDevices.supportsVideo()) {
115
+            audioOnly = urlParams && urlParams['config.startAudioOnly'];
116
+            typeof audioOnly === 'undefined'
117
+                && (audioOnly = config.startAudioOnly);
118
+            audioOnly = Boolean(audioOnly);
119
+        } else {
120
+            // Always default to being audio only if the current environment
121
+            // does not support sending or receiving video.
122
+            audioOnly = true;
123
+        }
112 124
 
113
-        typeof audioOnly === 'undefined' && (audioOnly = config.startAudioOnly);
114
-        audioOnly = Boolean(audioOnly);
115 125
         sendAnalyticsEvent(
116 126
             `startaudioonly.${audioOnly ? 'enabled' : 'disabled'}`);
117 127
         logger.log(`Start audio only set to ${audioOnly.toString()}`);

+ 4
- 0
react/features/device-selection/components/DeviceSelectionDialogBase.js Dosyayı Görüntüle

@@ -513,6 +513,10 @@ class DeviceSelectionDialogBase extends Component {
513 513
             this._disposeVideoPreview()
514 514
                 .then(() => createLocalTrack('video', deviceId))
515 515
                 .then(jitsiLocalTrack => {
516
+                    if (!jitsiLocalTrack) {
517
+                        return Promise.reject();
518
+                    }
519
+
516 520
                     this.setState({
517 521
                         previewVideoTrack: jitsiLocalTrack,
518 522
                         previewVideoTrackError: null

+ 42
- 6
react/features/video-quality/components/VideoQualityDialog.web.js Dosyayı Görüntüle

@@ -10,6 +10,7 @@ import {
10 10
     VIDEO_QUALITY_LEVELS
11 11
 } from '../../base/conference';
12 12
 import { translate } from '../../base/i18n';
13
+import JitsiMeetJS from '../../base/lib-jitsi-meet';
13 14
 
14 15
 const logger = require('jitsi-meet-logger').getLogger(__filename);
15 16
 
@@ -48,6 +49,12 @@ class VideoQualityDialog extends Component {
48 49
          */
49 50
         _receiveVideoQuality: PropTypes.number,
50 51
 
52
+        /**
53
+         * Whether or not displaying video is supported in the current
54
+         * environment. If false, the slider will be disabled.
55
+         */
56
+        _videoSupported: PropTypes.bool,
57
+
51 58
         /**
52 59
          * Invoked to request toggling of audio only mode.
53 60
          */
@@ -116,17 +123,26 @@ class VideoQualityDialog extends Component {
116 123
      * @returns {ReactElement}
117 124
      */
118 125
     render() {
119
-        const { _audioOnly, _p2p, t } = this.props;
126
+        const { _audioOnly, _p2p, _videoSupported, t } = this.props;
120 127
         const activeSliderOption = this._mapCurrentQualityToSliderValue();
121
-        const showP2PWarning = _p2p && !_audioOnly;
128
+
129
+        let classNames = 'video-quality-dialog';
130
+        let warning = null;
131
+
132
+        if (!_videoSupported) {
133
+            classNames += ' video-not-supported';
134
+            warning = this._renderAudioOnlyLockedMessage();
135
+        } else if (_p2p && !_audioOnly) {
136
+            warning = this._renderP2PMessage();
137
+        }
122 138
 
123 139
         return (
124
-            <div className = 'video-quality-dialog'>
140
+            <div className = { classNames }>
125 141
                 <h3 className = 'video-quality-dialog-title'>
126 142
                     { t('videoStatus.callQuality') }
127 143
                 </h3>
128
-                <div className = { showP2PWarning ? '' : 'hide-warning' }>
129
-                    { this._renderP2PMessage() }
144
+                <div className = { warning ? '' : 'hide-warning' }>
145
+                    { warning }
130 146
                 </div>
131 147
                 <div className = 'video-quality-dialog-contents'>
132 148
                     <div className = 'video-quality-dialog-slider-container'>
@@ -136,6 +152,7 @@ class VideoQualityDialog extends Component {
136 152
                            */ }
137 153
                         <input
138 154
                             className = 'video-quality-dialog-slider'
155
+                            disabled = { !_videoSupported }
139 156
                             max = { this._sliderOptions.length - 1 }
140 157
                             min = '0'
141 158
                             onChange = { this._onSliderChange }
@@ -154,6 +171,24 @@ class VideoQualityDialog extends Component {
154 171
         );
155 172
     }
156 173
 
174
+    /**
175
+     * Creates a React Element for notifying that the browser is in audio only
176
+     * and cannot be changed.
177
+     *
178
+     * @private
179
+     * @returns {ReactElement}
180
+     */
181
+    _renderAudioOnlyLockedMessage() {
182
+        const { t } = this.props;
183
+
184
+        return (
185
+            <InlineMessage
186
+                title = { t('videoStatus.onlyAudioAvailable') }>
187
+                { t('videoStatus.onlyAudioSupported') }
188
+            </InlineMessage>
189
+        );
190
+    }
191
+
157 192
     /**
158 193
      * Creates React Elements for notifying that peer to peer is enabled.
159 194
      *
@@ -330,7 +365,8 @@ function _mapStateToProps(state) {
330 365
     return {
331 366
         _audioOnly: audioOnly,
332 367
         _p2p: p2p,
333
-        _receiveVideoQuality: receiveVideoQuality
368
+        _receiveVideoQuality: receiveVideoQuality,
369
+        _videoSupported: JitsiMeetJS.mediaDevices.supportsVideo()
334 370
     };
335 371
 }
336 372
 

Loading…
İptal
Kaydet