diff --git a/demo/index.html b/demo/index.html
index 4a9679b..4b1c88d 100644
--- a/demo/index.html
+++ b/demo/index.html
@@ -1,6 +1,6 @@
\ No newline at end of file
diff --git a/demo/index.js b/demo/index.js
index c9ae2c4..fa26301 100644
--- a/demo/index.js
+++ b/demo/index.js
@@ -1,4 +1,6 @@
let httpServer = require("http").createServer();
httpServer.listen(8080);
-require("..").ws2mpd(httpServer);
+let mod = require("..");
+mod.logging(true);
+mod.ws2mpd(httpServer);
diff --git a/index.js b/index.js
index 7bf4b8f..fedc959 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,7 @@
#!/usr/bin/env node
-const commands = require("./commands");
const log = require("./log.js").log;
+const Queue = require("./queue").Queue;
function initConnection(request) {
let ws = request.accept();
@@ -16,47 +16,36 @@ function initConnection(request) {
mpd.setTimeout(0);
mpd.connect(port, host);
- let commandQueue = [];
- let command = null;
-
- function waitForCommand(cmd) {
- command = cmd;
- cmd.on("done", data => {
- log("ws <--", data);
- ws.send(JSON.stringify(data));
- command = null;
- processQueue();
- });
- }
-
- function processQueue() {
- if (command || !commandQueue.length) { return; }
- let cmd = commands.create(mpd, commandQueue.shift());
- waitForCommand(cmd);
- }
-
- ws.on("message", message => {
- log("ws -->", message.utf8Data);
- commandQueue.push(message.utf8Data);
- processQueue();
+ // data coming from the response parser
+ let queue = new Queue(mpd);
+ queue.on("response", data => {
+ log("ws <--", data);
+ ws.send(JSON.stringify(data));
});
+ // data going into the response parser
+ ws.on("message", message => {
+ log("ws -->", message.utf8Data);
+ queue.add(message.utf8Data);
+ });
+
+ // client closes
ws.on("close", (reasonCode, description) => {
log(`ws ${ws.remoteAddress} disconnected`);
mpd.end();
});
+ // server closes
mpd.on("close", () => {
log("mpd disconnected");
ws.close();
});
+ // fail to conect
mpd.on("error", () => {
log("mpd connection error");
ws.close();
});
-
- waitForCommand(commands.welcome(mpd));
}
exports.logging = function(enabled) {
diff --git a/package.json b/package.json
index 1906ea5..ad34e33 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ws2mpd",
- "version": "2.1.0",
+ "version": "2.2.0",
"description": "",
"main": "index.js",
"scripts": {
diff --git a/commands.js b/queue.js
similarity index 65%
rename from commands.js
rename to queue.js
index e5e386b..c8113fe 100644
--- a/commands.js
+++ b/queue.js
@@ -1,7 +1,7 @@
const EventEmitter = require("events");
const log = require("./log.js").log;
-class Command extends EventEmitter {
+class Response extends EventEmitter {
constructor(mpd) {
super();
this._mpd = mpd;
@@ -33,12 +33,10 @@ class Command extends EventEmitter {
}
}
-class Normal extends Command {
- constructor(mpd, command) {
+class Normal extends Response {
+ constructor(mpd) {
super(mpd);
this._lines = [];
- log("--> mpd", command);
- mpd.write(command + "\n");
}
_processBuffer() {
@@ -51,23 +49,22 @@ class Normal extends Command {
}
}
-class Welcome extends Command {
+class Idle extends Normal {}
+
+class Welcome extends Response {
_processBuffer() {
let line = this._getLine();
if (line) { this._done([line]); }
}
}
-class AlbumArt extends Command {
- constructor(mpd, command) {
+class Binary extends Response {
+ constructor(mpd) {
super(mpd);
this._size = 0;
this._binary = 0;
this._data = null;
this._lines = [];
-
- log("--> mpd", command);
- mpd.write(command + "\n");
}
_processBuffer() {
@@ -101,25 +98,59 @@ class AlbumArt extends Command {
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);
}
-
}
-exports.create = function(mpd, command) {
- if (command.startsWith("albumart")) {
- return new AlbumArt(mpd, command);
- } else {
- return new Normal(mpd, command);
+
+exports.Queue = class extends EventEmitter {
+ constructor(mpd) {
+ super();
+ this._mpd = mpd;
+ this._waiting = [];
+ this._current = null;
+
+ this._create(Welcome);
+ }
+
+ add(str) {
+ if (str == "noidle" && this._current instanceof Idle) {
+ this._mpd.write(str + "\n");
+ return;
+ }
+ this._waiting.push(str);
+ this._process();
+ }
+
+ _process() {
+ if (this._current || !this._waiting.length) { return; }
+ let str = this._waiting.shift();
+ this._create(getCtor(str));
+ log("--> mpd", str);
+ this._mpd.write(str + "\n");
+ }
+
+ _create(ctor) {
+ let cmd = new ctor(this._mpd);
+ this._current = cmd;
+
+ cmd.on("done", data => {
+ this.emit("response", data);
+ this._current = null;
+ this._process();
+ });
}
- return new Normal(mpd, command);
}
-exports.welcome = function(mpd) {
- return new Welcome(mpd);
+function getCtor(command) {
+ switch (true) {
+ case command.startsWith("idle"): return Idle;
+ case command.startsWith("albumart") || command.startsWith("readpicture"): return Binary;
+ default: return Normal;
+ }
}