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
This commit is contained in:
Eliot Berriot 2017-07-10 23:04:32 +02:00
parent 6172c0beac
commit f1c05d4f42
3 changed files with 42 additions and 9 deletions

View File

@ -124,9 +124,9 @@ class Audio {
} }
play () { play () {
logger.default.info('Playing track')
if (this.state.startLoad) { if (this.state.startLoad) {
if (!this.state.playing && this.$Audio.readyState >= 2) { if (!this.state.playing && this.$Audio.readyState >= 2) {
logger.default.info('Playing track')
this.$Audio.play() this.$Audio.play()
this.state.paused = false this.state.paused = false
this.state.playing = true this.state.playing = true

View File

@ -123,6 +123,7 @@ class Queue {
this.tracks.splice(index, 0, track) this.tracks.splice(index, 0, track)
} }
if (this.ended) { if (this.ended) {
logger.default.debug('Playing appended track')
this.play(this.currentIndex + 1) this.play(this.currentIndex + 1)
} }
this.cache() this.cache()
@ -152,19 +153,31 @@ class Queue {
clean () { clean () {
this.stop() this.stop()
radios.stop()
this.tracks = [] this.tracks = []
this.currentIndex = -1 this.currentIndex = -1
this.currentTrack = null this.currentTrack = null
// so we replay automatically on next track append
this.ended = true
} }
cleanTrack (index) { cleanTrack (index) {
if (index === this.currentIndex) { // are we removing current playin track
let current = index === this.currentIndex
if (current) {
this.stop() this.stop()
} }
if (index < this.currentIndex) { if (index < this.currentIndex) {
this.currentIndex -= 1 this.currentIndex -= 1
} }
this.tracks.splice(index, 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 () { stop () {
@ -172,12 +185,17 @@ class Queue {
this.audio.destroyed() this.audio.destroyed()
} }
play (index) { play (index) {
if (this.audio.destroyed) { let self = this
logger.default.debug('Destroying previous audio...') let currentIndex = index
this.audio.destroyed() 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 this.ended = false
let file = this.currentTrack.files[0] let file = this.currentTrack.files[0]
if (!file) { if (!file) {
@ -193,7 +211,11 @@ class Queue {
path = url.updateQueryString(path, 'jwt', auth.getAuthToken()) 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, preload: true,
autoplay: true, autoplay: true,
rate: 1, rate: 1,
@ -201,6 +223,17 @@ class Queue {
volume: this.state.volume, volume: this.state.volume,
onEnded: this.handleAudioEnded.bind(this) 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) { if (this.currentIndex === this.tracks.length - 1) {
this.populateFromRadio() this.populateFromRadio()
} }

View File

@ -24,7 +24,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="progress-area"> <div class="progress-area" v-if="queue.currentTrack">
<div class="ui grid"> <div class="ui grid">
<div class="left floated four wide column"> <div class="left floated four wide column">
<p class="timer start" @click="queue.audio.setTime(0)">{{queue.audio.state.currentTimeFormat}}</p> <p class="timer start" @click="queue.audio.setTime(0)">{{queue.audio.state.currentTimeFormat}}</p>