From 5a3835184ed6c31bff97e716f172abaeae93f100 Mon Sep 17 00:00:00 2001 From: Florrie Date: Tue, 4 Feb 2020 22:03:56 -0400 Subject: remove mkfifo; use socat instead --- package-lock.json | 27 +++++++-------------------- package.json | 1 - players.js | 54 ++++++++++++++++++++++++++++++++++-------------------- socat.js | 41 +++++++++++++++++++++++++++++++++++++++++ test-socat.txt | 0 todo.txt | 9 +++++++++ 6 files changed, 91 insertions(+), 41 deletions(-) create mode 100644 socat.js create mode 100644 test-socat.txt diff --git a/package-lock.json b/package-lock.json index 99afaa1..325ce96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,24 +27,11 @@ "clone": "^1.0.2" } }, - "es6-error": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-3.2.0.tgz", - "integrity": "sha1-5WfP3LMk1OeuWSKjcAraXeh5oMo=" - }, "expand-home-dir": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/expand-home-dir/-/expand-home-dir-0.0.3.tgz", "integrity": "sha1-ct6KBIbMKKO71wRjU5iCW1tign0=" }, - "fifo-js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fifo-js/-/fifo-js-2.1.0.tgz", - "integrity": "sha1-iEBfId6gZzYlWBieegdlXcD+FL4=", - "requires": { - "es6-error": "^3.0.1" - } - }, "is-wsl": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", @@ -121,17 +108,17 @@ } }, "tui-text-editor": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/tui-text-editor/-/tui-text-editor-0.2.0.tgz", - "integrity": "sha512-XnqfBQ3EGqABUf6Xdyxl47byRUR1q+mxDJ4tFBDpezi9ui7Loub4t7LTnsb8fwxJkeMiemF4gpVnEC5JkV5Iqw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tui-text-editor/-/tui-text-editor-0.3.1.tgz", + "integrity": "sha512-ySLdKfUHwxt6W1hub7Qt7smtuwujRHWxMIwdnO+IOzhd2B9naIg07JDr2LISZ3X+SZg0mvBNcGGeTf+L8bcSpw==", "requires": { - "tui-lib": "^0.1.0" + "tui-lib": "^0.1.1" }, "dependencies": { "tui-lib": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/tui-lib/-/tui-lib-0.1.0.tgz", - "integrity": "sha512-pSq5gn4/8MDlG4B0qbz2u1G5YeuF4xFvqfVLmC0hDAlv90r3yj7pErilDg4Sk7pAE5LEPrxIPsklKbaIXYTEaw==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/tui-lib/-/tui-lib-0.1.1.tgz", + "integrity": "sha512-QAE4axNCJ42IZSNnc2pLOkFtzHqYFgenDyw88JHHRNd8PXTVO8+JIpJArpgAguopd4MmoYaJbreze0BHoWMXfA==", "requires": { "wcwidth": "^1.0.1", "word-wrap": "^1.2.3" diff --git a/package.json b/package.json index 81fb70a..6f8e447 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "dependencies": { "command-exists": "^1.2.6", "expand-home-dir": "0.0.3", - "fifo-js": "^2.1.0", "mkdirp": "^0.5.1", "node-fetch": "^2.1.2", "node-natural-sort": "^0.8.6", diff --git a/players.js b/players.js index 651b519..07b711c 100644 --- a/players.js +++ b/players.js @@ -1,9 +1,9 @@ // stolen from http-music const { spawn } = require('child_process') -const FIFO = require('fifo-js') -const EventEmitter = require('events') const { commandExists, killProcess, getTimeStrings } = require('./general-util') +const EventEmitter = require('events') +const Socat = require('./socat') class Player extends EventEmitter { constructor() { @@ -116,27 +116,43 @@ module.exports.MPVPlayer = class extends Player { module.exports.ControllableMPVPlayer = class extends module.exports.MPVPlayer { getMPVOptions(file) { - return ['--input-file=' + this.fifo.path, ...super.getMPVOptions(file)] + return ['--input-ipc-server=' + this.socat.path, ...super.getMPVOptions(file)] } playFile(file) { - this.fifo = new FIFO() + let path + do { + path = '/tmp/mtui-socket-' + Math.floor(Math.random() * 10000) + } while (this.existsSync(path)) + + this.socat = new Socat(path) + + const mpv = super.playFile(file) - return super.playFile(file) + return mpv } - sendCommand(command) { - if (this.fifo) { - this.fifo.write(command) + existsSync(path) { + try { + fs.statSync(path) + return true + } catch (error) { + return false + } + } + + sendCommand(...command) { + if (this.socat) { + this.socat.send(JSON.stringify({command})) } } seekAhead(secs) { - this.sendCommand(`seek +${parseFloat(secs)}`) + this.sendCommand('seek', secs) } seekBack(secs) { - this.sendCommand(`seek -${parseFloat(secs)}`) + this.sendCommand('seek', -secs) } volUp(amount) { @@ -151,35 +167,33 @@ module.exports.ControllableMPVPlayer = class extends module.exports.MPVPlayer { this.volume = value this.volume = Math.max(0, this.volume) this.volume = Math.min(100, this.volume) - this.sendCommand(`set volume ${this.volume}`) + this.sendCommand('set', 'volume', this.volue) } togglePause() { this.isPaused = !this.isPaused - this.sendCommand('cycle pause') + this.sendCommand('cycle', 'pause') } toggleLoop() { this.isLooping = !this.isLooping - this.sendCommand('cycle loop') + this.sendCommand('cycle', 'loop') } setPause(val) { this.isPaused = !!val - this.sendCommand('set pause ' + (val ? 'yes' : 'no')) + this.sendCommand('set', 'pause', this.isPaused) } setLoop(val) { this.isLooping = !!val - this.sendCommand('set loop ' + (val ? 'yes' : 'no')) + this.sendCommand('set', 'loop', this.isLooping) } kill() { - if (this.fifo) { - this.fifo.close() - delete this.fifo + if (this.socat) { + this.socat.stop() } - return super.kill() } } @@ -246,7 +260,7 @@ module.exports.SoXPlayer = class extends Player { module.exports.getPlayer = async function() { if (await commandExists('mpv')) { - if (await commandExists('mkfifo')) { + if (await commandExists('socat')) { return new module.exports.ControllableMPVPlayer() } else { return new module.exports.MPVPlayer() diff --git a/socat.js b/socat.js new file mode 100644 index 0000000..ca317ea --- /dev/null +++ b/socat.js @@ -0,0 +1,41 @@ +// Simple interface for making a socat process and interacting with it. +// Assumes access to the `socat` command as a child process. + +const EventEmitter = require('events') +const { spawn } = require('child_process') +const { killProcess } = require('./general-util') + +module.exports = class Socat extends EventEmitter { + constructor(path) { + super() + this.setPath(path) + } + + setPath(path) { + this.stop() + this.path = path + } + + start() { + this.stop() + this.subprocess = spawn('socat', ['-', this.path]) + this.subprocess.stdout.on('data', data => this.emit('data', data)) + this.subprocess.on('close', () => { + this.subprocess = null + }) + } + + stop() { + if (this.subprocess) { + killProcess(this.subprocess) + this.subprocess = null + } + } + + send(message) { + if (!this.subprocess) { + this.start() + } + this.subprocess.stdin.write(message + '\r\n') + } +} diff --git a/test-socat.txt b/test-socat.txt new file mode 100644 index 0000000..e69de29 diff --git a/todo.txt b/todo.txt index 0db2382..5e1fe65 100644 --- a/todo.txt +++ b/todo.txt @@ -463,3 +463,12 @@ TODO: Only count *consistently* formatted text, across all tracks in a group, it is the only track in the group which is formatted '## # '. It does follow the formatting '## ' as all other tracks do, so only the first digits, and following whitespace, should be removed. + +TODO: Related to the above - always keep at least one word. See CANSLP's new + release "untitled folder", with tracks named "01 1", "02 2", etc. + +TODO: Update to work with IPC server mpv (and socat). + (Done!) + +TODO: Look into testing ^that on Windows. Remove mkfifo, since it's probably + no longer necessary! -- cgit 1.3.0-6-gf8a5