Track.vue 3.71 KB
Newer Older
1
2
3
4
5
<template>
  <audio
    ref="audio"
    @error="errored"
    @loadeddata="loaded"
6
    @durationchange="updateDuration"
7
8
9
    @timeupdate="updateProgress"
    @ended="ended"
    preload>
10
11
12
    <source
      @error="sourceErrored"
      v-for="src in srcs"
Eliot Berriot's avatar
Eliot Berriot committed
13
      :src="src.url"
14
      :type="src.type">
15
16
17
18
19
20
  </audio>
</template>

<script>
import {mapState} from 'vuex'
import url from '@/utils/url'
21
import formats from '@/audio/formats'
22
import _ from 'lodash'
23
24
25
26
27
// import logger from '@/logging'

export default {
  props: {
    track: {type: Object},
28
29
30
    isCurrent: {type: Boolean, default: false},
    startTime: {type: Number, default: 0},
    autoplay: {type: Boolean, default: false}
31
  },
32
33
34
35
36
  data () {
    return {
      sourceErrors: 0
    }
  },
37
38
39
40
41
42
43
44
  computed: {
    ...mapState({
      playing: state => state.player.playing,
      currentTime: state => state.player.currentTime,
      duration: state => state.player.duration,
      volume: state => state.player.volume,
      looping: state => state.player.looping
    }),
45
    srcs: function () {
46
47
48
      let file = this.track.files[0]
      if (!file) {
        this.$store.dispatch('player/trackErrored')
49
        return []
50
      }
51
52
53
54
55
56
57
58
59
60
      let sources = [
        {type: file.mimetype, url: file.path}
      ]
      formats.formats.forEach(f => {
        if (f !== file.mimetype) {
          let format = formats.formatsMap[f]
          let url = `/api/v1/trackfiles/transcode/?track_file=${file.id}&to=${format}`
          sources.push({type: f, url: url})
        }
      })
61
      if (this.$store.state.auth.authenticated) {
62
63
64
65
        // we need to send the token directly in url
        // so authentication can be checked by the backend
        // because for audio files we cannot use the regular Authentication
        // header
66
67
68
        sources.forEach(e => {
          e.url = url.updateQueryString(e.url, 'jwt', this.$store.state.auth.token)
        })
69
      }
70
      return sources
71
72
73
74
75
76
    }
  },
  methods: {
    errored: function () {
      this.$store.dispatch('player/trackErrored')
    },
77
78
79
80
81
82
83
    sourceErrored: function () {
      this.sourceErrors += 1
      if (this.sourceErrors >= this.srcs.length) {
        // all sources failed
        this.errored()
      }
    },
84
85
    updateDuration: function (e) {
      this.$store.commit('player/duration', this.$refs.audio.duration)
86
87
    },
    loaded: function () {
88
      this.$refs.audio.volume = this.volume
89
      this.$store.commit('player/resetErrorCount')
90
      if (this.isCurrent) {
91
92
93
94
        this.$store.commit('player/duration', this.$refs.audio.duration)
        if (this.startTime) {
          this.setCurrentTime(this.startTime)
        }
95
96
97
98
        if (this.autoplay) {
          this.$store.commit('player/playing', true)
          this.$refs.audio.play()
        }
99
100
      }
    },
101
    updateProgress: _.throttle(function () {
102
103
104
      if (this.$refs.audio) {
        this.$store.dispatch('player/updateProgress', this.$refs.audio.currentTime)
      }
105
    }, 250),
106
    ended: function () {
107
108
      let onlyTrack = this.$store.state.queue.tracks.length === 1
      if (this.looping === 1 || (onlyTrack && this.looping === 2)) {
109
110
        this.setCurrentTime(0)
        this.$refs.audio.play()
111
112
      } else {
        this.$store.dispatch('player/trackEnded', this.track)
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
      }
    },
    setCurrentTime (t) {
      if (t < 0 | t > this.duration) {
        return
      }
      this.updateProgress(t)
      this.$refs.audio.currentTime = t
    }
  },
  watch: {
    playing: function (newValue) {
      if (newValue === true) {
        this.$refs.audio.play()
      } else {
        this.$refs.audio.pause()
      }
    },
    volume: function (newValue) {
      this.$refs.audio.volume = newValue
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>