import { history } from 'site/store' 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 }, {}) } has(id) { return ( (id > 0) && (id in this.files) ) } stop(id) { if (this.players[id]) { this.players[id].type = "done" this.players[id].stop() } } done(id) { // console.log('remove', id) delete this.players[id] } toggleMuted(muted) { this.muted = muted Object.keys(this.players).forEach(id => this.players[id].toggleMuted(muted)) } playPage(page) { const { background_audio_id, restart_audio, stop_all_sounds } = page.settings // console.log('playPage', page) if (stop_all_sounds && this.current_background_id !== background_audio_id) { Object.keys(this.players).forEach(id => this.stop(id)) } else 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 (this.has(background_audio_id)) { this.current_background_id = background_audio_id this.playFile({ id: background_audio_id, type: 'background', restart: !!restart_audio, }) } } playTile({ tile, type }) { let id = type === 'click' ? tile.settings.audio_on_click_id : type === 'hover' ? tile.settings.audio_on_hover_id : null if (this.has(id)) { this.playFile({ id, tile, type }) } } playFile({ id, tile, type, restart, loop }) { const item = this.files[id] if (id in this.players) { if (restart) { this.players[id].restart() } if (tile && !this.players[id].tile) { this.players[id].tile = tile this.players[id].type = type } return this.players[id] } else { this.players[id] = new Player({ item, tile, type, done: this.done, }) this.players[id].toggleMuted(this.muted) this.players[id].play() return this.players[id] } } playURL({ id, url }) { this.players[id] = new Player({ item: { id, url }, tile: { settings: {} }, type: "url", done: this.done }) this.players[id].toggleMuted(this.muted) this.players[id].play() return this.players[id] } } class Player { constructor({ item, tile, type, done }) { this.item = item this.tile = tile this.type = type 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 } toggleMuted(muted) { this.audio.muted = muted } release() { if (this.type === 'click' && this.tile && this.tile.settings.navigate_when_audio_finishes) { history.push(this.tile.href) } 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() { if (this.type === 'background') { this.restart() } else { this.release() } } play() { this.audio.play() } restart() { this.audio.currentTime = 0 this.audio.play() } stop() { this.audio.pause() this.release() } }