Fix audio playback

This commit is contained in:
wvffle 2022-07-03 21:36:27 +00:00 committed by Georg Krause
parent cec34d49fa
commit 54a33cd14e
11 changed files with 82 additions and 84 deletions

View File

@ -14,7 +14,7 @@ import { useIntervalFn, useToggle, useWindowSize } from '@vueuse/core'
import { computed, nextTick, onMounted, ref, watchEffect } from 'vue'
import { Track } from '~/types'
import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
import useQueue from '~/composables/useQueue'
import useQueue from '~/composables/audio/useQueue'
import { useStore } from '~/store'
const store = useStore()

View File

@ -9,8 +9,8 @@ import TrackPlaylistIcon from '~/components/playlists/TrackPlaylistIcon.vue'
import Draggable, { } from 'vuedraggable'
import { whenever, useTimeoutFn, useWindowScroll, useWindowSize } from '@vueuse/core'
import { useGettext } from "vue3-gettext"
import useQueue from '~/composables/useQueue'
import usePlayer from '~/composables/usePlayer'
import useQueue from '~/composables/audio/useQueue'
import usePlayer from '~/composables/audio/usePlayer'
const queueModal = ref()

View File

@ -11,8 +11,8 @@ import onKeyboardShortcut from '~/composables/onKeyboardShortcut'
import { ref, computed, watch, onMounted, onBeforeUnmount, watchEffect } from 'vue'
import { useTimeoutFn, useIntervalFn } from '@vueuse/core'
import { useGettext } from 'vue3-gettext'
import useQueue from '~/composables/useQueue'
import usePlayer from '~/composables/usePlayer'
import useQueue from '~/composables/audio/useQueue'
import usePlayer from '~/composables/audio/usePlayer'
import useTrackSources, { TrackSource } from '~/composables/audio/useTrackSources'
import useSoundCache from '~/composables/audio/useSoundCache'
@ -146,11 +146,7 @@ watch(currentTrack, (track, oldValue) => {
})
const observeProgress = ref(false)
useIntervalFn(() => {
if (observeProgress.value) {
updateProgress()
}
}, 1000)
useIntervalFn(() => observeProgress.value && updateProgress(), 1000)
watch(playing, async (isPlaying) => {
if (currentSound.value) {
@ -207,6 +203,7 @@ onMounted(() => {
// TODO (wvffle): Check if it is needed
nextTrackPreloaded.value = false
// Cache sound if we have currentTrack available
if (currentTrack.value) {
getSound(currentTrack.value)
}
@ -249,7 +246,7 @@ const getSound = (trackData: Track) => {
},
onload () {
const node = (sound as any)._sounds[0].node as HTMLAudioElement
const node = (sound as any)._sounds[0]._node as HTMLAudioElement
node.addEventListener('progress', () => {
if (sound !== currentSound.value) {
@ -261,8 +258,8 @@ const getSound = (trackData: Track) => {
},
onplay () {
if (sound !== currentSound.value) {
return sound.stop()
if (this !== currentSound.value) {
return (this as any).stop()
}
const time = currentSound.value.seek()
@ -277,11 +274,16 @@ const getSound = (trackData: Track) => {
store.commit('player/duration', sound.duration())
},
onplayerror (soundId, error) {
console.log('play error', soundId, error)
},
onloaderror (soundId, error) {
console.log('load error', soundId, error)
soundCache.delete(trackData.id)
sound.unload()
if (sound !== currentSound.value) {
if (this !== currentSound.value) {
return
}
@ -298,6 +300,7 @@ const getSound = (trackData: Track) => {
return sound
}
const getTrack = async (trackData: Track) => {
// use previously fetched trackData
if (trackData.uploads.length) {
@ -372,7 +375,8 @@ const loadSound = async (trackData: Track, oldValue?: Track) => {
handleError()
}
currentSound.value = getSound(trackData as Track)
currentSound.value = getSound(trackData)
// TODO (wvffle): #1777
soundId.value = currentSound.value.play()
store.commit('player/isLoadingAudio', true)
@ -576,8 +580,11 @@ const switchTab = () => {
<span
class="start"
@click.stop.prevent="setCurrentTime(0)"
>{{ currentTimeFormatted }}</span>
| <span class="total">{{ durationFormatted }}</span>
>
{{ currentTimeFormatted }}
</span>
|
<span class="total">{{ durationFormatted }}</span>
</template>
</div>
</div>

View File

@ -1,3 +1,41 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useStore } from '~/store'
import { useGettext } from 'vue3-gettext'
import { useTimeoutFn } from '@vueuse/core'
import usePlayer from '~/composables/audio/usePlayer'
const store = useStore()
const { volume, mute, unmute } = usePlayer()
const expanded = ref(false)
const volumeSteps = 100
const sliderVolume = computed({
get: () => volume.value * volumeSteps,
set: (value) => store.commit('player/volume', value / volumeSteps)
})
const { $pgettext } = useGettext()
const labels = computed(() => ({
unmute: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Unmute'),
mute: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Mute'),
slider: $pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Adjust volume')
}))
const { start, stop } = useTimeoutFn(() => (expanded.value = false), 500, { immediate: false })
const handleOver = () => {
stop()
expanded.value = true
}
const handleLeave = () => {
stop()
start()
}
</script>
<template>
<button
class="circular control button"
@ -49,52 +87,3 @@
</div>
</button>
</template>
<script>
import { mapActions } from 'vuex'
export default {
data () {
return {
expanded: false,
timeout: null,
volumeSteps: 100
}
},
computed: {
sliderVolume: {
get () {
return this.$store.state.player.volume * this.volumeSteps
},
set (v) {
this.$store.commit('player/volume', v / this.volumeSteps)
}
},
labels () {
return {
unmute: this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Unmute'),
mute: this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Mute'),
slider: this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Adjust volume')
}
}
},
methods: {
...mapActions({
mute: 'player/mute',
unmute: 'player/unmute',
toggleMute: 'player/toggleMute'
}),
handleOver () {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.expanded = true
},
handleLeave () {
if (this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(() => { this.expanded = false }, 500)
}
}
}
</script>

View File

@ -1,6 +1,6 @@
import { computed, watchEffect } from "vue"
import { Howler } from 'howler'
import useQueue from '~/composables/useQueue'
import useQueue from '~/composables/audio/useQueue'
import toLinearVolumeScale from '~/composables/audio/toLinearVolumeScale'
import store from "~/store"
@ -19,6 +19,10 @@ export default () => {
watchEffect(() => Howler.volume(toLinearVolumeScale(volume.value)))
const mute = () => store.dispatch('player/mute')
const unmute = () => store.dispatch('player/unmute')
const toggleMute = () => store.dispatch('player/toggleMute')
// Time and duration
const duration = computed(() => store.state.player.duration)
const currentTime = computed(() => store.state.player.currentTime)
@ -65,6 +69,9 @@ export default () => {
focused,
volume,
mute,
unmute,
toggleMute,
duration,
currentTime,

View File

@ -19,11 +19,11 @@ export default (maxPreloaded: MaybeRef<number>) => {
if (toRemove > 0 && !cleaningCache.value) {
cleaningCache.value = true
const excess = sortBy(soundCache.values(), [(cached: CachedSound) => cached.date])
// TODO (wvffle): Check if works
.slice(0, toRemove) as unknown as CachedSound[]
const excess = sortBy([...soundCache.values()], [(cached: CachedSound) => cached.date])
.slice(0, toRemove)
for (const cached of excess) {
console.log('Removing cached element:', cached)
soundCache.delete(cached.id)
cached.sound.unload()
}

View File

@ -1,5 +1,5 @@
import { Track } from "~/types"
import { useStore } from '~/store'
import store from '~/store'
import updateQueryString from '~/composables/updateQueryString'
export interface TrackSource {
@ -8,7 +8,6 @@ export interface TrackSource {
}
export default (trackData: Track): TrackSource[] => {
const store = useStore()
const audio = document.createElement('audio')
const allowed = ['probably', 'maybe']

View File

@ -7,11 +7,11 @@ export const install: InitModule = ({ app }) => {
// this is needed to unlock audio playing under some browsers,
// cf https://github.com/goldfire/howler.js#mobilechrome-playback
// but we never actually load those audio files
const dummyAudio = new Howl({
preload: false,
autoplay: false,
src: ['noop.webm', 'noop.mp3']
})
// const dummyAudio = new Howl({
// preload: false,
// autoplay: false,
// src: ['noop.webm', 'noop.mp3']
// })
return dummyAudio
// return dummyAudio
}

View File

@ -1,7 +1,7 @@
import { InitModule } from '~/types'
import { whenever } from '@vueuse/core'
import useQueue from '~/composables/useQueue'
import usePlayer from '~/composables/usePlayer'
import useQueue from '~/composables/audio/useQueue'
import usePlayer from '~/composables/audio/usePlayer'
export const install: InitModule = ({ app }) => {
const { currentTrack, next, previous } = useQueue()

View File

@ -95,10 +95,6 @@ const store: Module<State, RootState> = {
},
getters: {
durationFormatted: state => {
if (state.duration % 1 !== 0) {
return time.parse(0)
}
return time.parse(Math.round(state.duration))
},
currentTimeFormatted: state => {