From b757ca4616178c0192f5e866f54282339626be2a Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Fri, 26 Oct 2018 15:21:35 +0200 Subject: [PATCH] See #272: updated front-end for transcoding and new API results, improved error handling in player --- front/src/components/audio/PlayButton.vue | 10 +++++-- front/src/components/audio/Player.vue | 23 ++++++++++++++-- front/src/components/audio/Track.vue | 32 ++++++++++++++++------ front/src/components/audio/track/Row.vue | 4 +-- front/src/components/library/Track.vue | 27 ++++++++++-------- front/src/store/index.js | 1 + front/src/store/player.js | 21 ++++++++++++-- front/src/store/queue.js | 1 - front/tests/unit/specs/store/queue.spec.js | 3 -- 9 files changed, 87 insertions(+), 35 deletions(-) diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue index dcb1c507e..521a66f87 100644 --- a/front/src/components/audio/PlayButton.vue +++ b/front/src/components/audio/PlayButton.vue @@ -79,10 +79,14 @@ export default { return true } if (this.track) { - return this.track.is_playable + return this.track.uploads && this.track.uploads.length > 0 + } else if (this.artist) { + return this.albums.filter((a) => { + return a.is_playable === true + }).length > 0 } else if (this.tracks) { return this.tracks.filter((t) => { - return t.is_playable + return t.uploads && t.uploads.length > 0 }).length > 0 } return false @@ -139,7 +143,7 @@ export default { self.isLoading = false }, 250) return tracks.filter(e => { - return e.is_playable === true + return e.uploads && e.uploads.length > 0 }) }) }, diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index 1d622f330..80c54bbb2 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -4,6 +4,7 @@ -
+

{{currentTimeFormatted}}

-
+

{{durationFormatted}}

@@ -59,7 +60,18 @@
- +
+
+ We cannot load this track +
+

+ The next track will play automatically in a few seconds... + +

+

+ You may have a connectivity issue. +

+
state.player.looping, duration: state => state.player.duration, bufferProgress: state => state.player.bufferProgress, + errored: state => state.player.errored, queue: state => state.queue }), ...mapGetters({ diff --git a/front/src/components/audio/Track.vue b/front/src/components/audio/Track.vue index 32eb62722..c847d4de1 100644 --- a/front/src/components/audio/Track.vue +++ b/front/src/components/audio/Track.vue @@ -46,12 +46,17 @@ export default { onload: function () { self.$store.commit('player/isLoadingAudio', false) self.$store.commit('player/resetErrorCount') + self.$store.commit('player/errored', false) self.$store.commit('player/duration', self.sound.duration()) let node = self.sound._sounds[0]._node; node.addEventListener('progress', () => { self.updateBuffer(node) }) - } + }, + onloaderror: function (sound, error) { + console.log('Error while playing:', sound, error) + self.$emit('errored', {sound, error}) + }, }) if (this.autoplay) { self.$store.commit('player/isLoadingAudio', true) @@ -73,14 +78,23 @@ export default { looping: state => state.player.looping }), srcs: function () { - // let file = this.track.files[0] - // if (!file) { - // this.$store.dispatch('player/trackErrored') - // return [] - // } - let sources = [ - {type: 'mp3', url: this.$store.getters['instance/absoluteUrl'](this.track.listen_url)} - ] + let sources = this.track.uploads.map(u => { + return { + type: u.extension, + url: this.$store.getters['instance/absoluteUrl'](u.listen_url), + } + }) + // We always add a transcoded MP3 src at the end + // because transcoding is expensive, but we want browsers that do + // not support other codecs to be able to play it :) + sources.push({ + type: 'mp3', + url: url.updateQueryString( + this.$store.getters['instance/absoluteUrl'](this.track.listen_url), + 'to', + 'mp3' + ) + }) if (this.$store.state.auth.authenticated) { // we need to send the token directly in url // so authentication can be checked by the backend diff --git a/front/src/components/audio/track/Row.vue b/front/src/components/audio/track/Row.vue index b17cf1170..fd8b2daaf 100644 --- a/front/src/components/audio/track/Row.vue +++ b/front/src/components/audio/track/Row.vue @@ -34,8 +34,8 @@ {{ track.album.title }} - - {{ time.parse(track.duration) }} + + {{ time.parse(track.uploads[0].duration) }} N/A diff --git a/front/src/components/library/Track.vue b/front/src/components/library/Track.vue index 483ff6673..ddccda397 100644 --- a/front/src/components/library/Track.vue +++ b/front/src/components/library/Track.vue @@ -44,13 +44,13 @@ View on MusicBrainz - + Download
-
+

Track information

@@ -58,8 +58,8 @@ - - - -
Duration - {{ time.parse(track.duration) }} + + {{ time.parse(upload.duration) }} N/A @@ -69,8 +69,8 @@ Size - {{ track.size | humanSize }} + + {{ upload.size | humanSize }} N/A @@ -80,8 +80,8 @@ Bitrate - {{ track.bitrate | humanSize }}/s + + {{ upload.bitrate | humanSize }}/s N/A @@ -91,8 +91,8 @@ Type - {{ track.mimetype }} + + {{ upload.extension }} N/A @@ -195,6 +195,11 @@ export default { title: this.$gettext('Track') } }, + upload () { + if (this.track.uploads) { + return this.track.uploads[0] + } + }, wikipediaUrl () { return 'https://en.wikipedia.org/w/index.php?search=' + encodeURI(this.track.title + ' ' + this.track.artist.name) }, @@ -204,7 +209,7 @@ export default { } }, downloadUrl () { - let u = this.$store.getters['instance/absoluteUrl'](this.track.listen_url) + let u = this.$store.getters['instance/absoluteUrl'](this.upload.listen_url) if (this.$store.state.auth.authenticated) { u = url.updateQueryString(u, 'jwt', encodeURI(this.$store.state.auth.token)) } diff --git a/front/src/store/index.js b/front/src/store/index.js index 051e89b39..0b8eb3321 100644 --- a/front/src/store/index.js +++ b/front/src/store/index.js @@ -79,6 +79,7 @@ export default new Vuex.Store({ id: track.id, title: track.title, mbid: track.mbid, + uploads: track.uploads, listen_url: track.listen_url, album: { id: track.album.id, diff --git a/front/src/store/player.js b/front/src/store/player.js index 08492541e..fac17368d 100644 --- a/front/src/store/player.js +++ b/front/src/store/player.js @@ -95,10 +95,19 @@ export default { incrementVolume ({commit, state}, value) { commit('volume', state.volume + value) }, - stop (context) { + stop ({commit}) { + commit('errored', false) + commit('resetErrorCount') }, - togglePlay ({commit, state}) { + togglePlay ({commit, state, dispatch}) { commit('playing', !state.playing) + if (state.errored && state.errorCount < state.maxConsecutiveErrors) { + setTimeout(() => { + if (state.playing) { + dispatch('queue/next', null, {root: true}) + } + }, 3000) + } }, trackListened ({commit, rootState}, track) { if (!rootState.auth.authenticated) { @@ -121,7 +130,13 @@ export default { trackErrored ({commit, dispatch, state}) { commit('errored', true) commit('incrementErrorCount') - dispatch('queue/next', null, {root: true}) + if (state.errorCount < state.maxConsecutiveErrors) { + setTimeout(() => { + if (state.playing) { + dispatch('queue/next', null, {root: true}) + } + }, 3000) + } }, updateProgress ({commit}, t) { commit('currentTime', t) diff --git a/front/src/store/queue.js b/front/src/store/queue.js index b6edb2242..81403b11f 100644 --- a/front/src/store/queue.js +++ b/front/src/store/queue.js @@ -142,7 +142,6 @@ export default { commit('ended', false) commit('player/currentTime', 0, {root: true}) commit('player/playing', true, {root: true}) - commit('player/errored', false, {root: true}) commit('currentIndex', index) if (state.tracks.length - index <= 2 && rootState.radios.running) { dispatch('radios/populateQueue', null, {root: true}) diff --git a/front/tests/unit/specs/store/queue.spec.js b/front/tests/unit/specs/store/queue.spec.js index 373f4938e..282a4f026 100644 --- a/front/tests/unit/specs/store/queue.spec.js +++ b/front/tests/unit/specs/store/queue.spec.js @@ -267,7 +267,6 @@ describe('store/queue', () => { { type: 'ended', payload: false }, { type: 'player/currentTime', payload: 0, options: {root: true} }, { type: 'player/playing', payload: true, options: {root: true} }, - { type: 'player/errored', payload: false, options: {root: true} }, { type: 'currentIndex', payload: 1 } ] }) @@ -281,7 +280,6 @@ describe('store/queue', () => { { type: 'ended', payload: false }, { type: 'player/currentTime', payload: 0, options: {root: true} }, { type: 'player/playing', payload: true, options: {root: true} }, - { type: 'player/errored', payload: false, options: {root: true} }, { type: 'currentIndex', payload: 1 } ] }) @@ -295,7 +293,6 @@ describe('store/queue', () => { { type: 'ended', payload: false }, { type: 'player/currentTime', payload: 0, options: {root: true} }, { type: 'player/playing', payload: true, options: {root: true} }, - { type: 'player/errored', payload: false, options: {root: true} }, { type: 'currentIndex', payload: 1 } ], expectedActions: [