summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Müller <marcel-mueller@gmx.de>2023-05-02 11:32:40 +0200
committerbackportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com>2023-08-03 12:40:40 +0000
commit0738a81ca36d5373752d045edc71d7405a56155a (patch)
treebf8790e1637ab26d8dfe907eb1462fd79cf3b913
parentedc585cf7ec7e406119f6afeb0784a447ade7ec5 (diff)
Create audio objects for call sounds as a result of a user interaction
Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
-rw-r--r--src/components/TopBar/CallButton.vue3
-rw-r--r--src/store/soundsStore.js154
-rw-r--r--src/utils/sounds.js30
3 files changed, 162 insertions, 25 deletions
diff --git a/src/components/TopBar/CallButton.vue b/src/components/TopBar/CallButton.vue
index 82fa94d4f..22b3efb2f 100644
--- a/src/components/TopBar/CallButton.vue
+++ b/src/components/TopBar/CallButton.vue
@@ -332,6 +332,9 @@ export default {
},
handleClick() {
+ // Create audio objects as a result of a user interaction to allow playing sounds in Safari
+ this.$store.dispatch('createAudioObjects')
+
const shouldShowMediaSettingsScreen = (BrowserStorage.getItem('showMediaSettings' + this.token) === null
|| BrowserStorage.getItem('showMediaSettings' + this.token) === 'true') && !this.forceJoinCall
console.debug(shouldShowMediaSettingsScreen)
diff --git a/src/store/soundsStore.js b/src/store/soundsStore.js
index c67a27171..75dbf9b17 100644
--- a/src/store/soundsStore.js
+++ b/src/store/soundsStore.js
@@ -21,6 +21,7 @@
*/
import { loadState } from '@nextcloud/initial-state'
+import { generateFilePath } from '@nextcloud/router'
import BrowserStorage from '../services/BrowserStorage.js'
import { setPlaySounds } from '../services/settingsService.js'
@@ -29,6 +30,10 @@ const state = {
userId: undefined,
playSoundsUser: loadState('spreed', 'play_sounds', false),
playSoundsGuest: BrowserStorage.getItem('play_sounds') !== 'no',
+ audioObjectsCreated: false,
+ joinAudioObject: null,
+ leaveAudioObject: null,
+ waitAudioObject: null,
}
const getters = {
@@ -55,6 +60,76 @@ const mutations = {
setUserId(state, userId) {
state.userId = userId
},
+
+ /**
+ * Sets the join audio object
+ *
+ * @param {object} state current store state
+ * @param {HTMLAudioElement} audioObject new audio object
+ */
+ setJoinAudioObject(state, audioObject) {
+ state.joinAudioObject = audioObject
+ },
+
+ /**
+ * Sets the leave audio object
+ *
+ * @param {object} state current store state
+ * @param {HTMLAudioElement} audioObject new audio object
+ */
+ setLeaveAudioObject(state, audioObject) {
+ state.leaveAudioObject = audioObject
+ },
+
+ /**
+ * Sets the wait audio object
+ *
+ * @param {object} state current store state
+ * @param {HTMLAudioElement} audioObject new audio object
+ */
+ setWaitAudioObject(state, audioObject) {
+ state.waitAudioObject = audioObject
+ },
+
+ /**
+ * Sets a flag that all audio objects were created
+ *
+ * @param {object} state current store state
+ */
+ setAudioObjectsCreated(state) {
+ state.audioObjectsCreated = true
+ },
+}
+
+/**
+ * Helper method to get the full file path of an audio file in spreed/img.
+ * Example: getFullAudioFilepath('myAudio') => 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
+ */
+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')
+ }
+}
+
+/**
+ * Creates a HTMLAudioElement with the specified filePath and loads it
+ *
+ * @param {string} filePath Path to the file
+ * @return {HTMLAudioElement} The created and loaded HTMLAudioElement
+ */
+const createAudioObject = function(filePath) {
+ const audio = new Audio(filePath)
+ audio.load()
+
+ return audio
}
const actions = {
@@ -78,6 +153,85 @@ const actions = {
await setPlaySounds(!context.state.userId, enabled)
context.commit('setPlaySounds', enabled)
},
+
+ /**
+ * Plays the join audio file with a volume of 0.75
+ *
+ * @param {object} context default store context
+ */
+ playJoinAudio(context) {
+ // Make sure the audio objects are really created before playing it
+ context.dispatch('createAudioObjects')
+
+ const audio = context.state.joinAudioObject
+ audio.load()
+ audio.volume = 0.75
+ audio.play()
+ },
+
+ /**
+ * Plays the leave audio file with a volume of 0.75
+ *
+ * @param {object} context default store context
+ */
+ playLeaveAudio(context) {
+ // Make sure the audio objects are really created before playing it
+ context.dispatch('createAudioObjects')
+
+ const audio = context.state.leaveAudioObject
+ audio.load()
+ audio.volume = 0.75
+ audio.play()
+ },
+
+ /**
+ * Plays the wait audio file with a volume of 0.5
+ *
+ * @param {object} context default store context
+ */
+ playWaitAudio(context) {
+ // Make sure the audio objects are really created before playing it
+ context.dispatch('createAudioObjects')
+
+ const audio = context.state.waitAudioObject
+ audio.load()
+ audio.volume = 0.5
+ audio.play()
+ },
+
+ /**
+ * Pauses the wait audio playback
+ *
+ * @param {object} context default store context
+ */
+ pauseWaitAudio(context) {
+ const audio = context.state.waitAudioObject
+ audio.pause()
+ },
+
+ /**
+ * If not already created, this creates audio objects for join, leave and wait sounds
+ *
+ * @param {object} context default store context
+ */
+ createAudioObjects(context) {
+ // No need to create the audio objects, if they were created already
+ if (context.state.audioObjectsCreated) {
+ return
+ }
+
+ const joinFilepath = getFullAudioFilepath('join_call')
+ const joinAudio = createAudioObject(joinFilepath)
+ context.commit('setJoinAudioObject', joinAudio)
+
+ const leaveFilepath = getFullAudioFilepath('leave_call')
+ const leaveAudio = createAudioObject(leaveFilepath)
+ context.commit('setLeaveAudioObject', leaveAudio)
+
+ const waitFilepath = getFullAudioFilepath('LibremPhoneCall')
+ const waitAudio = createAudioObject(waitFilepath)
+ context.commit('setWaitAudioObject', waitAudio)
+ },
}
export default { state, mutations, getters, actions }
diff --git a/src/utils/sounds.js b/src/utils/sounds.js
index 35563d670..e712b2866 100644
--- a/src/utils/sounds.js
+++ b/src/utils/sounds.js
@@ -18,8 +18,6 @@
*
*/
-import { generateFilePath } from '@nextcloud/router'
-
import store from '../store/index.js'
export const Sounds = {
@@ -29,22 +27,11 @@ export const Sounds = {
lastPlayedJoin: 0,
lastPlayedLeave: 0,
playedWaiting: 0,
- backgroundAudio: null,
backgroundInterval: null,
- _playSoundOnce(soundFile) {
- const file = generateFilePath('spreed', 'img', soundFile)
- const audio = new Audio(file)
- audio.volume = 0.75
- audio.play()
- },
-
_stopWaiting() {
console.debug('Stop waiting sound')
- if (this.backgroundAudio) {
- this.backgroundAudio.pause()
- this.backgroundAudio = null
- }
+ store.dispatch('pauseWaitAudio')
clearInterval(this.backgroundInterval)
},
@@ -53,15 +40,8 @@ export const Sounds = {
return
}
- if (!this.backgroundAudio) {
- console.debug('Loading waiting sound')
- const file = generateFilePath('spreed', 'img', 'LibremPhoneCall.ogg')
- this.backgroundAudio = new Audio(file)
- this.backgroundAudio.volume = 0.5
- }
-
console.debug('Playing waiting sound')
- this.backgroundAudio.play()
+ store.dispatch('playWaitAudio')
this.playedWaiting = 0
this.backgroundInterval = setInterval(() => {
@@ -77,7 +57,7 @@ export const Sounds = {
}
console.debug('Playing waiting sound')
- this.backgroundAudio.play()
+ store.dispatch('playWaitAudio')
this.playedWaiting++
}, 15000)
@@ -114,7 +94,7 @@ export const Sounds = {
if (playWaitingSound) {
await this.playWaiting()
} else {
- this._playSoundOnce('join_call.ogg')
+ store.dispatch('playJoinAudio')
}
},
@@ -145,7 +125,7 @@ export const Sounds = {
}
this.lastPlayedLeave = currentTime
- this._playSoundOnce('leave_call.ogg')
+ store.dispatch('playLeaveAudio')
if (playWaitingSound) {
this.playWaiting()