UNPKG

node-mpv-2

Version:
172 lines (167 loc) 5.58 kB
'use strict'; const net = require('net'); const controls = { // toggles pause togglePause: function() { return this.cycleProperty('pause'); }, // pause pause: function() { return this.setProperty('pause', true); }, // resume resume: function() { return this.setProperty('pause', false); }, // play play: async function() { const idle = await this.getProperty('idle-active') const playlist_size = await this.getPlaylistSize(); // if mpv is idle but has a playlist, set playlist-pos to 0, // which starts the playback if(idle && playlist_size > 0){ return new Promise(async (resolve, reject) => { // get the filename of the first item in the playlist for error handling purposes const fname = await this.getProperty('playlist/0/filename'); let started = false; // socket to observe if the file is being played back const observeSocket = new net.Socket(); observeSocket.connect({path: this.options.socket}, async () => { // this starts the playback when mpv is idle but songs are queued in the playlist await this.setProperty('playlist-pos', 0); }).on('data', (data) => { // parse the messages from the socket const messages = data.toString('utf-8').split('\n'); // check every message messages.forEach((message) => { // ignore empty messages if(message.length > 0){ message = JSON.parse(message); // look for the file-loaded event to see if the file was loaded and is played if('event' in message){ if(message.event === 'start-file'){ started = true; } // when the file has successfully been loaded resolve the promise else if(message.event === 'file-loaded' && started){ observeSocket.destroy(); // resolve the promise return resolve(); } // when the track has changed we don't need a seek event else if (message.event === 'end-file' && started){ observeSocket.destroy(); return reject(this.errorHandler.errorMessage(0, 'play()', [fname])); } } } }); }); }); } // if mpv is not idle and has files queued just set the pause state to false else{ return this.setProperty('pause', false); } }, // stop stop: function() { return this.command('stop', []); }, // quit quit: function() { // unbind the event listeners this.mpvPlayer.removeAllListeners('close'); this.mpvPlayer.removeAllListeners('error'); this.mpvPlayer.removeAllListeners('message'); clearInterval(this.timepositionListenerId); // send the quit command to mpv this.socket.command("quit"); // quit the socket connection this.socket.quit(); }, // volume control values 0-100 volume: function(value) { return this.setProperty('volume', value); }, adjustVolume: function(value) { return this.addProperty('volume', value); }, // mute // bool set // true mutes // false unmutes // Not setting set toggles the mute state mute: function(set) { return set!=null ? this.setProperty('mute', set) : this.cycleProperty('mute'); }, // relative search seek: async function(seconds, mode = 'relative') { // reject the promise if the mode is not correct if(!['relative', 'absolute', 'append-play'].includes(mode)){ throw ( this.errorHandler.errorMessage(1, 'seek()', mode, null, { 'relative': 'Searches x seconds from the current position', 'absolute': 'Goes to position x seconds of the current track', })); } // perform a seek operation return new Promise((resolve, reject) => { // tracks if the seek event has been emitted let seek_event_started = false; const observeSocket = new net.Socket(); observeSocket.connect({path: this.options.socket}, async () => { try { await this.command('seek', [seconds, mode, 'exact']); } catch (err) { reject(err); } }).on('data', (data) => { // parse the messages from the socket const messages = data.toString('utf-8').split('\n'); // check every message messages.forEach((message) => { // ignore empty messages if(message.length > 0){ message = JSON.parse(message); if('event' in message){ // if the seek event was found set the flag variable to true if(message.event === 'seek') seek_event_started = true; // resolve the promise if the playback-restart event was fired else if (seek_event_started && message.event === 'playback-restart') { observeSocket.destroy(); resolve(); } } } }); }); }); }, // go to position of the song goToPosition: async function(seconds) { return this.seek(seconds, 'absolute'); }, // loop // int/string times // number n - loop n times // 'inf' - loop infinitely often // 'no' - switch loop to off // // if times is not set, this method will toggle the loop state, if any looping is set, either 'inf' or a fixed number it will be switched off loop: async function(times) { // if times was set, use it. Times can be any number > 0, 'inf' and 'no' if (times!=null) { return this.setProperty('loop', times); } // if times was not set, net loop toggle the mute property else { // get the loop status // if any loop status was set, either 'inf' or a fixed number, switch loop to off // if no loop status was set, switch it on to 'inf' const loop_status = await this.getProperty('loop'); return !loop_status ? this.setProperty('loop', 'inf') : this.setProperty('loop', 'no'); } } } module.exports = controls;