]> git.wh0rd.org - chrome-ext/music-player-client.git/blobdiff - js/mpc.js
images: update screenshot
[chrome-ext/music-player-client.git] / js / mpc.js
index 4860682ade5760e8554fe02a3ce7285a31018cd5..1e3390b27b7d21100dfe22d95837c9c508323efe 100644 (file)
--- 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,69 @@ 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._cb_update_state(this.state);
+               break;
+
        case 'currentsong':
+               this.state.Currentsong = this._parse_result(lines).state;
+               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 +99,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 +115,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 +250,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');