import { shuffle, orderBy } from 'lodash' import $ from 'jquery' import plyr from 'plyr' import Vue from 'vue' import { event } from '../utils' import { queueStore, sharedStore, userStore, songStore, preferenceStore as preferences } from '../stores' import config from '../config' import router from '../router' export const playback = { player: null, $volumeInput: null, repeatModes: ['NO_REPEAT', 'REPEAT_ALL', 'REPEAT_ONE'], initialized: false, /** * Initialize the playback service for this whole Koel app. */ init () { // We don't need to init this service twice, or the media events will be duplicated. if (this.initialized) { return } this.player = plyr.setup({ controls: [] })[0] this.audio = $('audio') this.$volumeInput = $('#volumeRange') /** * Listen to 'error' event on the audio player and play the next song if any. */ document.querySelector('.plyr').addEventListener('error', e => { this.playNext() }, true) /** * Listen to 'ended' event on the audio player and play the next song in the queue. */ document.querySelector('.plyr').addEventListener('ended', e => { if (sharedStore.state.useLastfm && userStore.current.preferences.lastfm_session_key) { songStore.scrobble(queueStore.current) } if (preferences.repeatMode === 'REPEAT_ONE') { this.restart() return } this.playNext() }) /** * Attempt to preload the next song if the current song is about to end. */ document.querySelector('.plyr').addEventListener('timeupdate', e => { if (!this.player.media.duration || this.player.media.currentTime + 10 < this.player.media.duration) { return } // The current song has only 10 seconds left to play. const nextSong = queueStore.next if (!nextSong || nextSong.preloaded) { return } const $preloader = $('