diff --git a/src/Recording.vue b/src/Recording.vue index 4082a075f85..a271033e996 100644 --- a/src/Recording.vue +++ b/src/Recording.vue @@ -42,7 +42,7 @@ export default { if (this.$route.name === 'recording') { await this.$store.dispatch('updateToken', this.$route.params.token) - await this.soundsStore.setPlaySounds(false) + await this.soundsStore.setShouldPlaySounds(false) } // This should not be strictly needed, as the recording server is diff --git a/src/components/MediaSettings/MediaDevicesSpeakerTest.vue b/src/components/MediaSettings/MediaDevicesSpeakerTest.vue index 96b22f9e1c8..1a189740d62 100644 --- a/src/components/MediaSettings/MediaDevicesSpeakerTest.vue +++ b/src/components/MediaSettings/MediaDevicesSpeakerTest.vue @@ -69,17 +69,17 @@ export default { methods: { t, + playTestSound() { if (this.isPlayingTestSound) { - this.soundsStore.pauseWaitAudio() + this.soundsStore.pauseAudio('wait') return } this.isPlayingTestSound = true - this.soundsStore.playWaitAudio().then((response) => { - response.addEventListener('ended', () => { - this.isPlayingTestSound = false - }) - }) + this.soundsStore.playAudio('wait') + this.soundsStore.audioObjects.wait.addEventListener('ended', () => { + this.isPlayingTestSound = false + }, { once: true }) }, }, } diff --git a/src/components/SettingsDialog/SettingsDialog.vue b/src/components/SettingsDialog/SettingsDialog.vue index ab2dd4466c6..cc5a6ba5795 100644 --- a/src/components/SettingsDialog/SettingsDialog.vue +++ b/src/components/SettingsDialog/SettingsDialog.vue @@ -73,7 +73,7 @@ :name="t('spreed', 'Sounds')" class="app-settings-section"> spreed/img/myAudio.ogg - * - * @param {string} fileName The name of the file without extension - * @return {string} The full path to the file in the spreed/img directory and adds .ogg/.flac depending on supported codecs + * Get play sounds option (from server for user or from browser storage for guest) + * @param {boolean} value whether sounds should be played */ -const getFullAudioFilepath = function(fileName) { - const tempAudio = new Audio() - - // Prefer the .ogg version of sounds, but fall back to .flac in case .ogg is not supported (Safari) - if (tempAudio.canPlayType('audio/ogg')) { - return generateFilePath('spreed', 'img', fileName + '.ogg') - } else { - return generateFilePath('spreed', 'img', fileName + '.flac') - } -} +const hasUserAccount = Boolean(getCurrentUser()?.uid) +const shouldPlaySounds = hasUserAccount + ? loadState('spreed', 'play_sounds', false) + : BrowserStorage.getItem('play_sounds') !== 'no' /** - * Creates a HTMLAudioElement with the specified filePath and loads it - * - * @param {string} filePath Path to the file - * @return {HTMLAudioElement} The created and loaded HTMLAudioElement + * Preferred version is the .ogg, with .flac fallback if .ogg is not supported (Safari) */ -const createAudioObject = function(filePath) { - const audio = new Audio(filePath) - audio.load() - - return audio -} +const fileExtension = new Audio().canPlayType('audio/ogg') ? '.ogg' : '.flac' export const useSoundsStore = defineStore('sounds', { state: () => ({ - playSoundsUser: loadState('spreed', 'play_sounds', false), - playSoundsGuest: BrowserStorage.getItem('play_sounds') !== 'no', + shouldPlaySounds, audioObjectsCreated: false, - joinAudioObject: null, - leaveAudioObject: null, - waitAudioObject: null, - }), - - getters: { - playSounds: (state) => { - if (getCurrentUser()?.uid) { - return state.playSoundsUser - } - return state.playSoundsGuest + audioObjects: { + join: null, + leave: null, + wait: null, }, - }, + }), actions: { /** - * Sets the join audio object - * - * @param {HTMLAudioElement} audioObject new audio object - */ - setJoinAudioObject(audioObject) { - this.joinAudioObject = audioObject - }, - - /** - * Sets the leave audio object - * - * @param {HTMLAudioElement} audioObject new audio object + * Set play sounds option (on server for user or in browser storage for guest) + * @param {boolean} value whether sounds should be played */ - setLeaveAudioObject(audioObject) { - this.leaveAudioObject = audioObject + async setShouldPlaySounds(value) { + await setPlaySounds(hasUserAccount, value ? 'yes' : 'no') + this.shouldPlaySounds = value }, - /** - * Sets the wait audio object - * - * @param {HTMLAudioElement} audioObject new audio object - */ - setWaitAudioObject(audioObject) { - this.waitAudioObject = audioObject + playAudio(key) { + if (!this.audioObjectsCreated) { + this.initAudioObjects() + } + this.audioObjects[key].play() }, - /** - * Sets a flag that all audio objects were created - */ - setAudioObjectsCreated() { - this.audioObjectsCreated = true + pauseAudio(key) { + if (!this.audioObjectsCreated) { + this.initAudioObjects() + } + this.audioObjects[key].pause() }, /** - * Set play sounds + * Creates a HTMLAudioElement with the specified fileName and loads it * - * @param {boolean} enabled Whether sounds should be played - */ - async setPlaySounds(enabled) { - await setPlaySounds(!this.userId, enabled) - this.playSoundsUser = enabled - this.playSoundsGuest = enabled - }, - - /** - * Plays the join audio file with a volume of 0.75 - */ - playJoinAudio() { - // Make sure the audio objects are really created before playing it - this.createAudioObjects() - - const audio = this.joinAudioObject - audio.load() - audio.volume = 0.75 - audio.play() - }, - - /** - * Plays the leave audio file with a volume of 0.75 - */ - playLeaveAudio() { - // Make sure the audio objects are really created before playing it - this.createAudioObjects() - - const audio = this.leaveAudioObject - audio.load() - audio.volume = 0.75 - audio.play() - }, - - /** - * Plays the wait audio file with a volume of 0.5 + * @param {string} key key of the file at store.audioObjects + * @param {string} fileName name of the file at 'spreed/img/' directory + * @param {number} volume volume of the audio */ - async playWaitAudio() { - // Make sure the audio objects are really created before playing it - this.createAudioObjects() - - const audio = this.waitAudioObject + createAudioObject(key, fileName, volume) { + const filePath = generateFilePath('spreed', 'img', fileName + fileExtension) + const audio = new Audio(filePath) audio.load() - audio.volume = 0.5 - audio.play() - - return audio - }, - - /** - * Pauses the wait audio playback - */ - pauseWaitAudio() { - // Make sure the audio objects are really created before pausing it - this.createAudioObjects() - - const audio = this.waitAudioObject - audio.pause() + audio.volume = volume + Vue.set(this.audioObjects, key, audio) }, /** * If not already created, this creates audio objects for join, leave and wait sounds */ - createAudioObjects() { - // No need to create the audio objects, if they were created already + initAudioObjects() { if (this.audioObjectsCreated) { return } - const joinFilepath = getFullAudioFilepath('join_call') - const joinAudio = createAudioObject(joinFilepath) - this.setJoinAudioObject(joinAudio) - - const leaveFilepath = getFullAudioFilepath('leave_call') - const leaveAudio = createAudioObject(leaveFilepath) - this.setLeaveAudioObject(leaveAudio) - - const waitFilepath = getFullAudioFilepath('LibremPhoneCall') - const waitAudio = createAudioObject(waitFilepath) - this.setWaitAudioObject(waitAudio) - - this.setAudioObjectsCreated() + this.createAudioObject('join', 'join_call', 0.75) + this.createAudioObject('leave', 'leave_call', 0.75) + this.createAudioObject('wait', 'LibremPhoneCall', 0.5) + this.audioObjectsCreated = true }, } }) diff --git a/src/utils/sounds.js b/src/utils/sounds.js index a088f94ff21..65d1e3433b0 100644 --- a/src/utils/sounds.js +++ b/src/utils/sounds.js @@ -17,22 +17,22 @@ export const Sounds = { _stopWaiting() { console.debug('Stop waiting sound') const soundsStore = useSoundsStore() - soundsStore.pauseWaitAudio() + soundsStore.pauseAudio('wait') clearInterval(this.backgroundInterval) }, async playWaiting() { const soundsStore = useSoundsStore() - if (!soundsStore.playSounds) { + if (!soundsStore.shouldPlaySounds) { return } console.debug('Playing waiting sound') - soundsStore.playWaitAudio() + soundsStore.playAudio('wait') this.playedWaiting = 0 this.backgroundInterval = setInterval(() => { - if (!soundsStore.playSounds) { + if (!soundsStore.shouldPlaySounds) { this._stopWaiting() return } @@ -44,7 +44,7 @@ export const Sounds = { } console.debug('Playing waiting sound') - soundsStore.playWaitAudio() + soundsStore.playAudio('wait') this.playedWaiting++ }, 15000) @@ -54,7 +54,7 @@ export const Sounds = { this._stopWaiting() const soundsStore = useSoundsStore() - if (!soundsStore.playSounds) { + if (!soundsStore.shouldPlaySounds) { return } @@ -82,7 +82,7 @@ export const Sounds = { if (playWaitingSound) { await this.playWaiting() } else { - soundsStore.playJoinAudio() + soundsStore.playAudio('join') } }, @@ -90,7 +90,7 @@ export const Sounds = { this._stopWaiting() const soundsStore = useSoundsStore() - if (!soundsStore.playSounds) { + if (!soundsStore.shouldPlaySounds) { return } @@ -114,7 +114,7 @@ export const Sounds = { } this.lastPlayedLeave = currentTime - soundsStore.playLeaveAudio() + soundsStore.playAudio('leave') if (playWaitingSound) { this.playWaiting()