ws2mpd/commands.js

126 lines
2.6 KiB
JavaScript
Raw Normal View History

2019-03-19 18:13:15 +08:00
const EventEmitter = require("events");
2019-04-12 19:46:27 +08:00
const log = require("./log.js").log;
2019-03-19 18:13:15 +08:00
class Command extends EventEmitter {
constructor(mpd) {
super();
this._mpd = mpd;
this._buffer = Buffer.alloc(0);
this._dataListener = data => this._onData(data);
mpd.on("data", this._dataListener);
}
_onData(data) {
log("<-- mpd", data);
this._buffer = Buffer.concat([this._buffer, data]);
this._processBuffer();
}
_processBuffer() {} // abstract
_done(data) {
this._mpd.off("data", this._dataListener);
2019-03-20 05:10:02 +08:00
this._buffer = null;
2019-03-19 18:13:15 +08:00
this.emit("done", data);
}
_getLine() {
let index = this._buffer.indexOf(0x0a);
if (index == -1) { return null; }
let str = this._buffer.slice(0, index).toString("utf8");
this._buffer = this._buffer.slice(index+1);
return str;
}
}
class Normal extends Command {
constructor(mpd, command) {
super(mpd);
this._lines = [];
log("--> mpd", command);
mpd.write(command + "\n");
}
_processBuffer() {
while (1) {
let line = this._getLine();
if (!line) { break; }
this._lines.push(line);
if (line.startsWith("OK") || line.startsWith("ACK")) { return this._done(this._lines); }
}
}
}
class Welcome extends Command {
_processBuffer() {
let line = this._getLine();
2019-03-20 23:20:09 +08:00
if (line) { this._done([line]); }
2019-03-19 18:13:15 +08:00
}
}
2019-03-20 05:10:02 +08:00
class AlbumArt extends Command {
constructor(mpd, command) {
super(mpd);
this._size = 0;
this._binary = 0;
this._data = null;
this._lines = [];
log("--> mpd", command);
mpd.write(command + "\n");
}
_processBuffer() {
if (!this._size) {
let line = this._getLine();
if (!line) { return; }
this._lines.push(line);
2019-03-20 23:20:09 +08:00
if (line.startsWith("ACK")) { // no art!
this._done(this._lines);
return;
}
2019-03-20 05:10:02 +08:00
this._size = Number(line.split(": ").pop());
log("size", this._size);
}
if (!this._binary) {
let line = this._getLine();
if (!line) { return; }
this._lines.push(line);
this._binary = Number(line.split(": ").pop());
log("binary", this._binary);
}
if (!this._data) {
// binary data has this._binary bytes + 1 newline
if (this._buffer.length >= this._binary+1) {
this._data = this._buffer.slice(0, this._binary);
this._buffer = this._buffer.slice(this._binary+1);
this._lines.push([...this._data]);
log("data", this._data.length);
} else { return; }
}
let line = this._getLine();
if (!line) { return; }
this._lines.push(line);
this._done(this._lines);
}
}
2019-03-19 18:13:15 +08:00
exports.create = function(mpd, command) {
2019-03-20 05:10:02 +08:00
if (command.startsWith("albumart")) {
return new AlbumArt(mpd, command);
} else {
return new Normal(mpd, command);
}
2019-03-19 18:13:15 +08:00
return new Normal(mpd, command);
}
exports.welcome = function(mpd) {
return new Welcome(mpd);
}