|
@@ -78,7 +78,6 @@ const eventEmitter = new EventEmitter();
|
78
|
78
|
let room;
|
79
|
79
|
let connection;
|
80
|
80
|
let localAudio, localVideo;
|
81
|
|
-let initialAudioMutedState = false;
|
82
|
81
|
|
83
|
82
|
import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
|
84
|
83
|
|
|
@@ -177,11 +176,14 @@ function getDisplayName(id) {
|
177
|
176
|
/**
|
178
|
177
|
* Mute or unmute local audio stream if it exists.
|
179
|
178
|
* @param {boolean} muted - if audio stream should be muted or unmuted.
|
180
|
|
- * @param {boolean} userInteraction - indicates if this local audio mute was a
|
181
|
|
- * result of user interaction
|
|
179
|
+ *
|
|
180
|
+ * @returns {Promise} resolved in case mute/unmute operations succeeds or
|
|
181
|
+ * rejected with an error if something goes wrong. It is expected that often
|
|
182
|
+ * the error will be of the {@link JitsiTrackError} type, but it's not
|
|
183
|
+ * guaranteed.
|
182
|
184
|
*/
|
183
|
185
|
function muteLocalAudio(muted) {
|
184
|
|
- muteLocalMedia(localAudio, muted);
|
|
186
|
+ return muteLocalMedia(localAudio, muted);
|
185
|
187
|
}
|
186
|
188
|
|
187
|
189
|
/**
|
|
@@ -680,7 +682,7 @@ export default {
|
680
|
682
|
});
|
681
|
683
|
}).then(([tracks, con]) => {
|
682
|
684
|
tracks.forEach(track => {
|
683
|
|
- if (track.isAudioTrack() && initialAudioMutedState) {
|
|
685
|
+ if (track.isAudioTrack() && this.audioMuted) {
|
684
|
686
|
track.mute();
|
685
|
687
|
} else if (track.isVideoTrack() && this.videoMuted) {
|
686
|
688
|
track.mute();
|
|
@@ -751,10 +753,46 @@ export default {
|
751
|
753
|
},
|
752
|
754
|
/**
|
753
|
755
|
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
|
754
|
|
- * @param mute true for mute and false for unmute.
|
|
756
|
+ * @param {boolean} mute true for mute and false for unmute.
|
|
757
|
+ * @param {boolean} [showUI] when set to false will not display any error
|
|
758
|
+ * dialogs in case of media permissions error.
|
755
|
759
|
*/
|
756
|
|
- muteAudio(mute) {
|
757
|
|
- muteLocalAudio(mute);
|
|
760
|
+ muteAudio(mute, showUI = true) {
|
|
761
|
+ // Not ready to modify track's state yet
|
|
762
|
+ if (!this._localTracksInitialized) {
|
|
763
|
+ this.audioMuted = mute;
|
|
764
|
+ return;
|
|
765
|
+ } else if (localAudio && localAudio.isMuted() === mute) {
|
|
766
|
+ // NO-OP
|
|
767
|
+ return;
|
|
768
|
+ }
|
|
769
|
+
|
|
770
|
+ const maybeShowErrorDialog = (error) => {
|
|
771
|
+ if (showUI) {
|
|
772
|
+ APP.UI.showDeviceErrorDialog(error, null);
|
|
773
|
+ }
|
|
774
|
+ };
|
|
775
|
+
|
|
776
|
+ if (!localAudio && this.audioMuted && !mute) {
|
|
777
|
+ createLocalTracks({ devices: ['audio'] }, false)
|
|
778
|
+ .then(([audioTrack]) => audioTrack)
|
|
779
|
+ .catch(error => {
|
|
780
|
+ maybeShowErrorDialog(error);
|
|
781
|
+
|
|
782
|
+ // Rollback the audio muted status by using null track
|
|
783
|
+ return null;
|
|
784
|
+ })
|
|
785
|
+ .then(audioTrack => this.useAudioStream(audioTrack));
|
|
786
|
+ } else {
|
|
787
|
+ const oldMutedStatus = this.audioMuted;
|
|
788
|
+
|
|
789
|
+ muteLocalAudio(mute)
|
|
790
|
+ .catch(error => {
|
|
791
|
+ maybeShowErrorDialog(error);
|
|
792
|
+ this.audioMuted = oldMutedStatus;
|
|
793
|
+ APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
|
|
794
|
+ });
|
|
795
|
+ }
|
758
|
796
|
},
|
759
|
797
|
/**
|
760
|
798
|
* Returns whether local audio is muted or not.
|
|
@@ -766,18 +804,11 @@ export default {
|
766
|
804
|
/**
|
767
|
805
|
* Simulates toolbar button click for audio mute. Used by shortcuts
|
768
|
806
|
* and API.
|
769
|
|
- * @param {boolean} force - If the track is not created, the operation
|
770
|
|
- * will be executed after the track is created. Otherwise the operation
|
771
|
|
- * will be ignored.
|
772
|
|
- */
|
773
|
|
- toggleAudioMuted(force = false) {
|
774
|
|
- if(!localAudio && force) {
|
775
|
|
- // NOTE this logic will be adjusted to the same one as for the video
|
776
|
|
- // once 'startWithAudioMuted' option is added.
|
777
|
|
- initialAudioMutedState = !initialAudioMutedState;
|
778
|
|
- return;
|
779
|
|
- }
|
780
|
|
- this.muteAudio(!this.audioMuted);
|
|
807
|
+ * @param {boolean} [showUI] when set to false will not display any error
|
|
808
|
+ * dialogs in case of media permissions error.
|
|
809
|
+ */
|
|
810
|
+ toggleAudioMuted(showUI = true) {
|
|
811
|
+ this.muteAudio(!this.audioMuted, showUI);
|
781
|
812
|
},
|
782
|
813
|
/**
|
783
|
814
|
* Simulates toolbar button click for video mute. Used by shortcuts and API.
|
|
@@ -1213,7 +1244,8 @@ export default {
|
1213
|
1244
|
this.audioMuted = newStream.isMuted();
|
1214
|
1245
|
APP.UI.addLocalStream(newStream);
|
1215
|
1246
|
} else {
|
1216
|
|
- this.audioMuted = false;
|
|
1247
|
+ // No audio is treated the same way as being audio muted
|
|
1248
|
+ this.audioMuted = true;
|
1217
|
1249
|
}
|
1218
|
1250
|
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
|
1219
|
1251
|
});
|
|
@@ -1836,17 +1868,7 @@ export default {
|
1836
|
1868
|
});
|
1837
|
1869
|
|
1838
|
1870
|
APP.UI.addListener(UIEvents.AUDIO_MUTED, muted => {
|
1839
|
|
- if (!localAudio && this.audioMuted && !muted) {
|
1840
|
|
- createLocalTracks({ devices: ['audio'] }, false)
|
1841
|
|
- .then(([audioTrack]) => {
|
1842
|
|
- this.useAudioStream(audioTrack);
|
1843
|
|
- })
|
1844
|
|
- .catch(error => {
|
1845
|
|
- APP.UI.showDeviceErrorDialog(error, null);
|
1846
|
|
- });
|
1847
|
|
- } else {
|
1848
|
|
- muteLocalAudio(muted);
|
1849
|
|
- }
|
|
1871
|
+ this.muteAudio(muted);
|
1850
|
1872
|
});
|
1851
|
1873
|
APP.UI.addListener(UIEvents.VIDEO_MUTED, muted => {
|
1852
|
1874
|
if (this.isAudioOnly() && !muted) {
|