1 // Written by Mike Frysinger <vapier@gmail.com>. Released into the public domain. Suck it.
3 function Mpc(socket, cb_update_state, debug_enabled) {
5 this._cb_update_state = cb_update_state;
6 this._debug_enabled = debug_enabled;
7 this._queue = ['init'];
11 Mpc.prototype.log = function(msg, obj) {
12 if (this._debug_enabled)
13 console.log('mpc: ' + msg, obj);
16 Mpc.prototype.set_debug = function(val) {
17 this._debug_enabled = val;
20 Mpc.prototype.send = function(msg) {
22 this._queue.push(msg);
23 this._socket.send(msg, function(x) {
24 _this.log('send: ' + msg + ':', x);
28 Mpc.prototype.recv_msg = function(lines) {
29 curr = this._queue.shift();
30 this.log('recv: [' + curr + ']:', lines.join('\n'));
31 curr = curr.split(' ');
34 // Needs to return a list of dicts (see above for dicts).
35 //case 'playlistinfo':
40 lines.forEach(function(line) {
41 i = line.indexOf(':');
43 return; // Ignores the OK line
44 key = line.substr(0, i);
45 val = line.substr(i + 2);
49 this._cb_update_state(state);
52 this._cb_update_state(lines, curr);
57 Mpc.prototype.recv = function(msg) {
58 /* We can get back a bunch of responses in a row, so parse them out */
59 /* XXX: Do we have to handle partial reads ? like long playlists ... */
60 lines = msg.split('\n');
62 while (i < lines.length) {
63 if (lines[i] == 'OK' || lines[i].substr(0, 3) == 'OK ') {
64 this.recv_msg(lines.splice(0, i + 1));
72 * Command generator helpers.
75 Mpc.__make_send_void = function(cmd) {
76 return function() { this.send(cmd); }
79 Mpc.__make_send_arg1 = function(cmd) {
82 this.log(cmd + ': function requires one argument');
84 this.send(cmd + ' ' + a1);
88 Mpc.__make_send_arg2 = function(cmd) {
89 return function(a1, a2) {
90 if (a1 === undefined || a2 === undefined)
91 this.log(cmd + ': function requires two arguments');
93 this.send(cmd + ' ' + a1 + ' ' + a2);
97 Mpc.__make_send_opt = function(cmd) {
98 return function(arg) {
99 if (arg === undefined)
101 this.send(cmd + ' ' + arg);
105 Mpc.__make_send_range = function(cmd, min, max, def) {
106 return function(arg) {
107 if (arg === undefined)
109 if (arg >= min && arg <= max)
110 this.send(cmd + ' ' + arg);
112 this.log(cmd + ': arg must be [' + min + ',' + max + '] but got "' + arg + '"');
117 * Querying MPD's status
118 * http://www.musicpd.org/doc/protocol/ch03.html#idp118752
122 Mpc.prototype.clearerror = Mpc.__make_send_void('clearerror');
124 Mpc.prototype.currentsong = Mpc.__make_send_void('currentsong');
125 // idle [SUBSYSTEMS...]
128 Mpc.prototype.status = Mpc.__make_send_void('status');
130 Mpc.prototype.stats = Mpc.__make_send_void('stats');
134 * http://www.musicpd.org/doc/protocol/ch03s02.html
138 Mpc.prototype.consume = Mpc.__make_send_range('consume', 0, 1, 1);
139 // crossfade {SECONDS}
140 Mpc.prototype.crossfade = Mpc.__make_send_arg1('crossfade');
141 // mixrampdb {deciBels}
142 Mpc.prototype.mixrampdb = Mpc.__make_send_arg1('mixrampdb');
143 // mixrampdelay {SECONDS|nan}
144 // Note: Probably should handle javascript NaN here.
145 Mpc.prototype.mixrampdelay = Mpc.__make_send_arg1('mixrampdelay');
147 Mpc.prototype.random = Mpc.__make_send_range('random', 0, 1, 1);
149 Mpc.prototype.repeat = Mpc.__make_send_range('repeat', 0, 1, 1);
151 Mpc.prototype.setvol = Mpc.__make_send_range('setvol', 0, 100);
153 Mpc.prototype.single = Mpc.__make_send_range('single', 0, 1, 1);
154 // replay_gain_mode {MODE}
155 Mpc.prototype.replay_gain_mode = Mpc.__make_send_arg1('replay_gain_mode');
156 // replay_gain_status
159 * Controlling playback
160 * http://www.musicpd.org/doc/protocol/ch03s03.html
164 Mpc.prototype.next = Mpc.__make_send_void('next');
166 Mpc.prototype.pause = Mpc.__make_send_range('pause', 0, 1, 1);
168 Mpc.prototype.play = Mpc.__make_send_opt('play');
170 Mpc.prototype.playid = Mpc.__make_send_opt('playid');
172 Mpc.prototype.previous = Mpc.__make_send_void('previous');
173 // seek {SONGPOS} {TIME}
174 Mpc.prototype.seek = Mpc.__make_send_arg2('seek');
175 // seekid {SONGID} {TIME}
176 Mpc.prototype.seekid = Mpc.__make_send_arg2('seekid');
178 Mpc.prototype.seekcur = Mpc.__make_send_arg1('seek');
180 Mpc.prototype.stop = Mpc.__make_send_void('stop');
183 * Connection settings
184 * http://www.musicpd.org/doc/protocol/ch03s08.html
188 Mpc.prototype.close = Mpc.__make_send_void('close');
190 Mpc.prototype.kill = Mpc.__make_send_void('kill');
191 // password {PASSWORD}
192 Mpc.prototype.password = Mpc.__make_send_arg1('password');
194 Mpc.prototype.ping = Mpc.__make_send_void('ping');