From f1c05d4f427ee8db23cb9493cc7a04e71b94c556 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Mon, 10 Jul 2017 23:04:32 +0200 Subject: [PATCH] More robust audio player and queue in various situations: - Ensure clearing the queue also stop current radio - Will also repopulate a track from radio on track deletion in queue - Clearing the queue then appending tracks would play automatically instead of getting stuck --- front/src/audio/index.js | 2 +- front/src/audio/queue.js | 47 +++++++++++++++++++++++---- front/src/components/audio/Player.vue | 2 +- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/front/src/audio/index.js b/front/src/audio/index.js index 48f61044..7750ee50 100644 --- a/front/src/audio/index.js +++ b/front/src/audio/index.js @@ -124,9 +124,9 @@ class Audio { } play () { - logger.default.info('Playing track') if (this.state.startLoad) { if (!this.state.playing && this.$Audio.readyState >= 2) { + logger.default.info('Playing track') this.$Audio.play() this.state.paused = false this.state.playing = true diff --git a/front/src/audio/queue.js b/front/src/audio/queue.js index efa3dcdf..25b27f00 100644 --- a/front/src/audio/queue.js +++ b/front/src/audio/queue.js @@ -123,6 +123,7 @@ class Queue { this.tracks.splice(index, 0, track) } if (this.ended) { + logger.default.debug('Playing appended track') this.play(this.currentIndex + 1) } this.cache() @@ -152,19 +153,31 @@ class Queue { clean () { this.stop() + radios.stop() this.tracks = [] this.currentIndex = -1 this.currentTrack = null + // so we replay automatically on next track append + this.ended = true } cleanTrack (index) { - if (index === this.currentIndex) { + // are we removing current playin track + let current = index === this.currentIndex + if (current) { this.stop() } if (index < this.currentIndex) { this.currentIndex -= 1 } this.tracks.splice(index, 1) + if (current) { + // we play next track, which now have the same index + this.play(index) + } + if (this.currentIndex === this.tracks.length - 1) { + this.populateFromRadio() + } } stop () { @@ -172,12 +185,17 @@ class Queue { this.audio.destroyed() } play (index) { - if (this.audio.destroyed) { - logger.default.debug('Destroying previous audio...') - this.audio.destroyed() + let self = this + let currentIndex = index + let currentTrack = this.tracks[index] + if (!currentTrack) { + logger.default.debug('No track at index', index) + return } - this.currentIndex = index - this.currentTrack = this.tracks[index] + + this.currentIndex = currentIndex + this.currentTrack = currentTrack + this.ended = false let file = this.currentTrack.files[0] if (!file) { @@ -193,7 +211,11 @@ class Queue { path = url.updateQueryString(path, 'jwt', auth.getAuthToken()) } - this.audio = new Audio(path, { + if (this.audio.destroyed) { + logger.default.debug('Destroying previous audio...', index - 1) + this.audio.destroyed() + } + let audio = new Audio(path, { preload: true, autoplay: true, rate: 1, @@ -201,6 +223,17 @@ class Queue { volume: this.state.volume, onEnded: this.handleAudioEnded.bind(this) }) + this.audio = audio + audio.updateHook('playState', function (e) { + // in some situations, we may have a race condition, for example + // if the user spams the next / previous buttons, with multiple audios + // playing at the same time. To avoid that, we ensure the audio + // still matches de queue current audio + if (audio !== self.audio) { + logger.default.debug('Destroying duplicate audio') + audio.destroyed() + } + }) if (this.currentIndex === this.tracks.length - 1) { this.populateFromRadio() } diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index 466ead0e..b72f37c5 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -24,7 +24,7 @@ </div> </div> </div> - <div class="progress-area"> + <div class="progress-area" v-if="queue.currentTrack"> <div class="ui grid"> <div class="left floated four wide column"> <p class="timer start" @click="queue.audio.setTime(0)">{{queue.audio.state.currentTimeFormat}}</p> -- GitLab