summaryrefslogtreecommitdiffstats
path: root/src/components/MediaDevicesPreview.vue
diff options
context:
space:
mode:
authormarco <marcoambrosini@pm.me>2021-09-09 12:28:33 +0200
committermarco <marcoambrosini@pm.me>2021-10-05 10:37:38 +0200
commit7d4e3c6877d697e3d0136fdfedd0462b709070bd (patch)
tree646b4555efbd795912f1142b30616f606e30e8fe /src/components/MediaDevicesPreview.vue
parent4739f500605af38695add6df34c8535812f1c3ba (diff)
Move device switching logic to a mixin
Signed-off-by: marco <marcoambrosini@pm.me>
Diffstat (limited to 'src/components/MediaDevicesPreview.vue')
-rw-r--r--src/components/MediaDevicesPreview.vue332
1 files changed, 3 insertions, 329 deletions
diff --git a/src/components/MediaDevicesPreview.vue b/src/components/MediaDevicesPreview.vue
index 566d84929..986d50b50 100644
--- a/src/components/MediaDevicesPreview.vue
+++ b/src/components/MediaDevicesPreview.vue
@@ -90,14 +90,12 @@
</template>
<script>
-import attachMediaStream from 'attachmediastream'
-import hark from 'hark'
import AlertCircle from 'vue-material-design-icons/AlertCircle'
import Microphone from 'vue-material-design-icons/Microphone'
import MicrophoneOff from 'vue-material-design-icons/MicrophoneOff'
import VideoOff from 'vue-material-design-icons/VideoOff'
-import { mediaDevicesManager } from '../utils/webrtc/index'
import MediaDevicesSelector from './MediaDevicesSelector'
+import { devices } from '../mixins/devices'
export default {
@@ -111,130 +109,17 @@ export default {
VideoOff,
},
+ mixins: [devices],
+
data() {
return {
mounted: false,
- mediaDevicesManager,
- pendingGetUserMediaAudioCount: 0,
- pendingGetUserMediaVideoCount: 0,
- audioStream: null,
- audioStreamError: null,
- videoStream: null,
- videoStreamError: null,
- hark: null,
currentVolume: -100,
volumeThreshold: -100,
}
},
computed: {
- devices() {
- return mediaDevicesManager.attributes.devices
- },
-
- audioInputId: {
- get() {
- return mediaDevicesManager.attributes.audioInputId
- },
- set(value) {
- mediaDevicesManager.set('audioInputId', value)
- },
- },
-
- videoInputId: {
- get() {
- return mediaDevicesManager.attributes.videoInputId
- },
- set(value) {
- mediaDevicesManager.set('videoInputId', value)
- },
- },
-
- audioStreamInputId() {
- if (!this.audioStream) {
- return null
- }
-
- const audioTracks = this.audioStream.getAudioTracks()
- if (audioTracks.length < 1) {
- return null
- }
-
- return audioTracks[0].getSettings().deviceId
- },
-
- videoStreamInputId() {
- if (!this.videoStream) {
- return null
- }
-
- const videoTracks = this.videoStream.getVideoTracks()
- if (videoTracks.length < 1) {
- return null
- }
-
- return videoTracks[0].getSettings().deviceId
- },
-
- audioPreviewAvailable() {
- return this.audioInputId && this.audioStream
- },
-
- videoPreviewAvailable() {
- return this.videoInputId && this.videoStream
- },
-
- audioStreamErrorMessage() {
- if (!this.audioStreamError) {
- return null
- }
-
- if (this.audioStreamError.name === 'NotSupportedError' && !window.RTCPeerConnection) {
- return t('spreed', 'Calls are not supported in your browser')
- }
-
- // In newer browser versions MediaDevicesManager is not supported in
- // insecure contexts; in older browser versions it is, but getting
- // the user media fails with "NotAllowedError".
- const isInsecureContext = 'isSecureContext' in window && !window.isSecureContext
- const isInsecureContextAccordingToErrorMessage = this.audioStreamError.message && this.audioStreamError.message.indexOf('Only secure origins') !== -1
- if ((this.audioStreamError.name === 'NotSupportedError' && isInsecureContext)
- || (this.audioStreamError.name === 'NotAllowedError' && isInsecureContextAccordingToErrorMessage)) {
- return t('spreed', 'Access to microphone is only possible with HTTPS')
- }
-
- if (this.audioStreamError.name === 'NotAllowedError') {
- return t('spreed', 'Access to microphone was denied')
- }
-
- return t('spreed', 'Error while accessing microphone')
- },
-
- videoStreamErrorMessage() {
- if (!this.videoStreamError) {
- return null
- }
-
- if (this.videoStreamError.name === 'NotSupportedError' && !window.RTCPeerConnection) {
- return t('spreed', 'Calls are not supported in your browser')
- }
-
- // In newer browser versions MediaDevicesManager is not supported in
- // insecure contexts; in older browser versions it is, but getting
- // the user media fails with "NotAllowedError".
- const isInsecureContext = 'isSecureContext' in window && !window.isSecureContext
- const isInsecureContextAccordingToErrorMessage = this.videoStreamError.message && this.videoStreamError.message.indexOf('Only secure origins') !== -1
- if ((this.videoStreamError.name === 'NotSupportedError' && isInsecureContext)
- || (this.videoStreamError.name === 'NotAllowedError' && isInsecureContextAccordingToErrorMessage)) {
- return t('spreed', 'Access to camera is only possible with HTTPS')
- }
-
- if (this.videoStreamError.name === 'NotAllowedError') {
- return t('spreed', 'Access to camera was denied')
- }
-
- return t('spreed', 'Error while accessing camera')
- },
currentVolumeIndicatorHeight() {
// refs can not be accessed on the initial render, only after the
@@ -260,219 +145,8 @@ export default {
},
- watch: {
- audioInputId(audioInputId) {
- this.updateAudioStream()
- },
-
- videoInputId(videoInputId) {
- this.updateVideoStream()
- },
- },
-
mounted() {
this.mounted = true
-
- if (!this.mediaDevicesManager.isSupported()) {
- // DOMException constructor is not supported in Internet Explorer,
- // so a plain object is used instead.
- this.audioStreamError = {
- message: 'MediaDevicesManager is not supported',
- name: 'NotSupportedError',
- }
- this.videoStreamError = {
- message: 'MediaDevicesManager is not supported',
- name: 'NotSupportedError',
- }
- }
-
- this.mediaDevicesManager.enableDeviceEvents()
- this.updateAudioStream()
- this.updateVideoStream()
- },
-
- destroyed() {
- this.stopAudioStream()
- this.stopVideoStream()
-
- this.mediaDevicesManager.disableDeviceEvents()
- },
-
- methods: {
-
- updateAudioStream() {
- if (!this.mediaDevicesManager.isSupported()) {
- return
- }
-
- if (this.audioStreamInputId && this.audioStreamInputId === this.audioInputId) {
- return
- }
-
- if (this.pendingGetUserMediaAudioCount) {
- this.pendingGetUserMediaAudioCount++
-
- return
- }
-
- // When the audio input device changes the previous stream must be
- // stopped before a new one is requested, as for example currently
- // Firefox does not support having two different audio input devices
- // active at the same time:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1468700
- this.stopAudioStream()
-
- this.audioStreamError = null
-
- if (this.audioInputId === null || this.audioInputId === undefined) {
- return
- }
-
- this.pendingGetUserMediaAudioCount = 1
-
- const resetPendingGetUserMediaAudioCount = () => {
- const updateAudioStreamAgain = this.pendingGetUserMediaAudioCount > 1
-
- this.pendingGetUserMediaAudioCount = 0
-
- if (updateAudioStreamAgain) {
- this.updateAudioStream()
- }
- }
-
- this.mediaDevicesManager.getUserMedia({ audio: true })
- .then(stream => {
- this.setAudioStream(stream)
-
- resetPendingGetUserMediaAudioCount()
- })
- .catch(error => {
- console.error('Error getting audio stream: ' + error.name + ': ' + error.message)
- this.audioStreamError = error
- this.setAudioStream(null)
-
- resetPendingGetUserMediaAudioCount()
- })
- },
-
- updateVideoStream() {
- if (!this.mediaDevicesManager.isSupported()) {
- return
- }
-
- if (this.videoStreamInputId && this.videoStreamInputId === this.videoInputId) {
- return
- }
-
- if (this.pendingGetUserMediaVideoCount) {
- this.pendingGetUserMediaVideoCount++
-
- return
- }
-
- // Video stream is stopped too to avoid potential issues similar to
- // the audio ones (see "updateAudioStream").
- this.stopVideoStream()
-
- this.videoStreamError = null
-
- if (this.videoInputId === null || this.videoInputId === undefined) {
- return
- }
-
- this.pendingGetUserMediaVideoCount = 1
-
- const resetPendingGetUserMediaVideoCount = () => {
- const updateVideoStreamAgain = this.pendingGetUserMediaVideoCount > 1
-
- this.pendingGetUserMediaVideoCount = 0
-
- if (updateVideoStreamAgain) {
- this.updateVideoStream()
- }
- }
-
- this.mediaDevicesManager.getUserMedia({ video: true })
- .then(stream => {
- this.setVideoStream(stream)
-
- resetPendingGetUserMediaVideoCount()
- })
- .catch(error => {
- console.error('Error getting video stream: ' + error.name + ': ' + error.message)
- this.videoStreamError = error
- this.setVideoStream(null)
-
- resetPendingGetUserMediaVideoCount()
- })
- },
-
- setAudioStream(audioStream) {
- this.audioStream = audioStream
-
- if (!audioStream) {
- return
- }
-
- this.hark = hark(this.audioStream)
- this.hark.on('volume_change', (volume, volumeThreshold) => {
- this.currentVolume = volume
- this.volumeThreshold = volumeThreshold
- })
- },
-
- setVideoStream(videoStream) {
- this.videoStream = videoStream
-
- if (!this.$refs.video) {
- return
- }
-
- if (!videoStream) {
- return
- }
-
- const options = {
- autoplay: true,
- mirror: true,
- muted: true,
- }
- attachMediaStream(videoStream, this.$refs.video, options)
- },
-
- stopAudioStream() {
- if (!this.audioStream) {
- return
- }
-
- this.audioStream.getTracks().forEach(function(track) {
- track.stop()
- })
-
- this.audioStream = null
-
- if (this.hark) {
- this.hark.stop()
- this.hark.off('volume_change')
- this.hark = null
- }
- },
-
- stopVideoStream() {
- if (!this.videoStream) {
- return
- }
-
- this.videoStream.getTracks().forEach(function(track) {
- track.stop()
- })
-
- this.videoStream = null
-
- if (this.$refs.video) {
- this.$refs.video.srcObject = null
- }
- },
},
}
</script>