summaryrefslogtreecommitdiff
path: root/frontend/site/audio/audio.player.js
blob: 42ff53fae5a8a934beed8ed42bd6154aa3b7a24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
export default class AudioPlayer {
  files = {}
  players = {}
  current_background_id = 0

  constructor() {
    this.done = this.done.bind(this)
  }

  load(graph) {
    this.files = graph.uploads
    .filter(upload => upload.tag === 'audio')
    .reduce((accumulator, item) => {
      accumulator[item.id] = item
      return accumulator
    }, {})
  }

  done(id) {
    console.log('remove', id)
    delete this.players[id]
  }

  playPage(page) {
    const { background_audio_id, restart_audio } = page.settings
    console.log('playPage', background_audio_id)
    if (
      this.current_background_id
      && this.current_background_id !== background_audio_id
      && this.current_background_id in this.players
    ) {
      this.players[this.current_background_id].stop()
    }
    if (background_audio_id in this.files) {
      this.current_background_id = background_audio_id
      this.playFile({
        item: this.files[background_audio_id],
        restart: !!restart_audio,
      })
    }
  }

  playFile({ item, restart, loop }) {
    const { id } = item
    if (id in this.players) {
      if (restart) {
        this.players[id].restart()
      }
      return this.players[id]
    } else {
      this.players[id] = new Player(item, this.done)
      this.players[id].play()
      return this.players[id]
    }
  }
}

class Player {
  constructor(item, done) {
    this.item = item
    this.done = done
    this.audio = document.createElement('audio')
    this.handleEnded = this.handleEnded.bind(this)
    this.handleError = this.handleError.bind(this)
    this.release = this.release.bind(this)
    this.audio.addEventListener('ended', this.handleEnded)
    this.audio.addEventListener('error', this.handleError)
    this.audio.src = item.url
  }

  release() {
    this.audio.removeEventListener('ended', this.handleEnded)
    this.audio.removeEventListener('error', this.handleError)
    this.done(this.item.id)
    this.item = null
    this.done = null
    this.audio = null
  }

  handleError(error) {
    console.error(error)
    this.release()
  }

  handleEnded() {
    this.release()
  }

  play() {
    console.log('play', this.item.id)
    this.audio.play()
  }

  restart() {
    console.log('replay', this.item.id)
    this.audio.currentTime = 0
    this.audio.play()
  }

  stop() {
    console.log('stop', this.item.id)
    this.audio.pause()
    this.release()
  }
}