X-Git-Url: https://git.wh0rd.org/?p=chrome-ext%2Fmusic-player-client.git;a=blobdiff_plain;f=js%2Fmpc.js;h=84eea050a9970ff47ff69ae6e3867dad378f2bef;hp=4860682ade5760e8554fe02a3ce7285a31018cd5;hb=HEAD;hpb=60d8b85a1a317d5226a3537d8a78e91138d6395d diff --git a/js/mpc.js b/js/mpc.js index 4860682..84eea05 100644 --- a/js/mpc.js +++ b/js/mpc.js @@ -5,6 +5,8 @@ function Mpc(socket, cb_update_state, debug_enabled) { this._cb_update_state = cb_update_state; this._debug_enabled = debug_enabled; this._queue = ['init']; + this._recv_buffer = []; + this._recv_buffer_last = 0; this.state = {}; } @@ -26,31 +28,71 @@ Mpc.prototype.send = function(msg) { this._queue.push(msg); this._socket.send(msg, function(x) { _this.log(0x1, 'send: ' + msg + ':', x); + if (x.bytesWritten < 0) { + _this.log(0x1, 'reconnecting...'); + _this._socket.reconnect(); + _this.queue = [msg]; + _this._socket.send(msg); + } }); } +Mpc.prototype._parse_result = function(lines) { + var state = {}; + var keys = []; + var key, val, i; + + lines.forEach(function(line) { + i = line.indexOf(':'); + if (i == -1) + return; // Ignores the OK line + key = line.substr(0, i); + keys.push(key); + val = line.substr(i + 2); + state[key] = val; + }); + + return { + 'state': state, + 'keys': keys, + }; +} + Mpc.prototype.recv_msg = function(lines) { - curr = this._queue.shift(); + var state, keys, ret; + var curr = this._queue.shift(); this.log(0x2, 'recv: [' + curr + ']:', lines.join('\n')); + if (lines[0].substr(0, 4) == 'ACK ') + this.err(curr, lines.join('\n')); curr = curr.split(' '); switch (curr[0]) { - // Needs to return a list of dicts (see above for dicts). - //case 'playlistinfo': + case 'playlistinfo': + var i = 2, playlist = [], song; + while (i < lines.length) { + if (lines[i].substr(0, 5) == 'file:') { + song = this._parse_result(lines.splice(0, i + 1)).state; + playlist = playlist.concat(song); + i = 0; + } else + ++i; + } + this.state.Playlist = playlist; + this.state.Playlist.lastUpdate = (new Date()).getTime(); + this._cb_update_state(this.state); + break; + case 'currentsong': + this.state.Currentsong = this._parse_result(lines).state; + this.state.Currentsong.lastUpdate = (new Date()).getTime(); + this._cb_update_state(this.state); + break; + case 'stats': case 'status': - state = {}; - keys = []; - lines.forEach(function(line) { - i = line.indexOf(':'); - if (i == -1) - return; // Ignores the OK line - key = line.substr(0, i); - keys.push(key); - val = line.substr(i + 2); - state[key] = val; - }); + ret = this._parse_result(lines); + state = ret.state; + keys = ret.keys; // When mpd is stopped, it gives us back crap values for some things. if ('state' in state && state.state == 'stop') { @@ -59,13 +101,14 @@ Mpc.prototype.recv_msg = function(lines) { } // Now merge the current state with the previous one so that we don't // lose information like volume or song position. - curr_state = this.state; + var curr_state = this.state; keys.forEach(function(key) { curr_state[key] = state[key]; }); this._cb_update_state(curr_state); break; + default: this._cb_update_state(lines, curr); break; @@ -74,16 +117,23 @@ Mpc.prototype.recv_msg = function(lines) { Mpc.prototype.recv = function(msg) { /* We can get back a bunch of responses in a row, so parse them out */ - /* XXX: Do we have to handle partial reads ? like long playlists ... */ - lines = msg.split('\n'); + var lines = this._recv_buffer = this._recv_buffer.concat(msg.split('\n')); var i = 0; while (i < lines.length) { - if (lines[i] == 'OK' || lines[i].substr(0, 3) == 'OK ') { + if (lines[i] == 'OK' || lines[i].substr(0, 3) == 'OK ' || + lines[i].substr(0, 4) == 'ACK ') { this.recv_msg(lines.splice(0, i + 1)); i = 0; } else ++i; } + + if (lines.length && this._recv_buffer_last != lines.length) { + // Keep sucking in data so long as more exists. + this._recv_buffer_last = lines.length; + this._socket.poll(); + } else + this._recv_buffer_last = lines.length; } /* @@ -202,7 +252,7 @@ Mpc.prototype.seek = Mpc.__make_send_arg2('seek'); // seekid {SONGID} {TIME} Mpc.prototype.seekid = Mpc.__make_send_arg2('seekid'); // seekcur {TIME} -Mpc.prototype.seekcur = Mpc.__make_send_arg1('seek'); +Mpc.prototype.seekcur = Mpc.__make_send_arg1('seekcur'); // stop Mpc.prototype.stop = Mpc.__make_send_void('stop');