import { shuffle, orderBy } from 'lodash'; import $ from 'jquery'; import plyr from 'plyr'; import Vue from 'vue'; import { event, loadMainView } from '../utils'; import queueStore from '../stores/queue'; import songStore from '../stores/song'; import artistStore from '../stores/artist'; import preferences from '../stores/preference'; import config from '../config'; export default { player: null, $volumeInput: null, repeatModes: ['NO_REPEAT', 'REPEAT_ALL', 'REPEAT_ONE'], initialized: false, /** * Initialize the playback service for this whole Koel app. * * @param {Vue} app The root Vue component. */ 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 => { 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 = $('