]> git.wh0rd.org - chrome-ext/music-player-client.git/blame - js/mpc.js
initial extension
[chrome-ext/music-player-client.git] / js / mpc.js
CommitLineData
50dafc4c
MF
1// Written by Mike Frysinger <vapier@gmail.com>. Released into the public domain. Suck it.
2
3function Mpc(socket, cb_update_state) {
4 this._socket = socket;
5 this._cb_update_state = cb_update_state;
6 this._queue = ['init'];
7 this.state = {};
8}
9
10Mpc.log = function(msg, obj) {
11 console.log('mpc: ' + msg, obj);
12}
13
14Mpc.prototype.send = function(msg) {
15 this._queue.push(msg);
16 this._socket.send(msg, function(x) {
17 Mpc.log('send: ' + msg + ':', x);
18 });
19}
20
21Mpc.prototype.recv_msg = function(lines) {
22 curr = this._queue.shift();
23 Mpc.log('recv: [' + curr + ']:', lines.join('\n'));
24 curr = curr.split(' ');
25
26 switch (curr[0]) {
27 // Needs to return a list of dicts (see above for dicts).
28 //case 'playlistinfo':
29 case 'currentsong':
30 case 'stats':
31 case 'status':
32 state = {};
33 lines.forEach(function(line) {
34 i = line.indexOf(':');
35 if (i == -1)
36 return; // Ignores the OK line
37 key = line.substr(0, i);
38 val = line.substr(i + 2);
39 state[key] = val;
40 });
41 this.state = state;
42 this._cb_update_state(state);
43 break;
44 default:
45 this._cb_update_state(lines, curr);
46 break;
47 }
48}
49
50Mpc.prototype.recv = function(msg) {
51 /* We can get back a bunch of responses in a row, so parse them out */
52 /* XXX: Do we have to handle partial reads ? like long playlists ... */
53 lines = msg.split('\n');
54 var i = 0;
55 while (i < lines.length) {
56 if (lines[i] == 'OK' || lines[i].substr(0, 3) == 'OK ') {
57 this.recv_msg(lines.splice(0, i + 1));
58 i = 0;
59 } else
60 ++i;
61 }
62}
63
64/*
65 * Command generator helpers.
66 */
67
68Mpc.__make_send_void = function(cmd) {
69 return function() { this.send(cmd); }
70}
71
72Mpc.__make_send_arg1 = function(cmd) {
73 return function(a1) {
74 if (a1 === undefined)
75 Mpc.log(cmd + ': function requires one argument');
76 else
77 this.send(cmd + ' ' + a1);
78 }
79}
80
81Mpc.__make_send_arg2 = function(cmd) {
82 return function(a1, a2) {
83 if (a1 === undefined || a2 === undefined)
84 Mpc.log(cmd + ': function requires two arguments');
85 else
86 this.send(cmd + ' ' + a1 + ' ' + a2);
87 }
88}
89
90Mpc.__make_send_opt = function(cmd) {
91 return function(arg) {
92 if (arg === undefined)
93 arg = '';
94 this.send(cmd + ' ' + arg);
95 };
96}
97
98Mpc.__make_send_range = function(cmd, min, max, def) {
99 return function(arg) {
100 if (arg === undefined)
101 arg = def;
102 if (arg >= min && arg <= max)
103 this.send(cmd + ' ' + arg);
104 else
105 Mpc.log(cmd + ': arg must be [' + min + ',' + max + '] but got "' + arg + '"');
106 };
107}
108
109/*
110 * Querying MPD's status
111 * http://www.musicpd.org/doc/protocol/ch03.html#idp118752
112 */
113
114// clearerror
115Mpc.prototype.clearerror = Mpc.__make_send_void('clearerror');
116// currentsong
117Mpc.prototype.currentsong = Mpc.__make_send_void('currentsong');
118// idle [SUBSYSTEMS...]
119// TODO
120// status
121Mpc.prototype.status = Mpc.__make_send_void('status');
122// stats
123Mpc.prototype.stats = Mpc.__make_send_void('stats');
124
125/*
126 * Playback options
127 * http://www.musicpd.org/doc/protocol/ch03s02.html
128 */
129
130// consume {STATE}
131Mpc.prototype.consume = Mpc.__make_send_range('consume', 0, 1, 1);
132// crossfade {SECONDS}
133Mpc.prototype.consume = Mpc.__make_send_arg1('crossfade');
134// mixrampdb {deciBels}
135Mpc.prototype.mixrampdb = Mpc.__make_send_arg1('mixrampdb');
136// mixrampdelay {SECONDS|nan}
137// Note: Probably should handle javascript NaN here.
138Mpc.prototype.mixrampdelay = Mpc.__make_send_arg1('mixrampdelay');
139// random {STATE}
140Mpc.prototype.random = Mpc.__make_send_range('random', 0, 1, 1);
141// repeat {STATE}
142Mpc.prototype.repeat = Mpc.__make_send_range('repeat', 0, 1, 1);
143// setvol {VOL}
144Mpc.prototype.setvol = Mpc.__make_send_range('setvol', 0, 100);
145// single {STATE}
146Mpc.prototype.single = Mpc.__make_send_range('single', 0, 1, 1);
147// replay_gain_mode {MODE}
148Mpc.prototype.replay_gain_mode = Mpc.__make_send_arg1('replay_gain_mode');
149// replay_gain_status
150
151/*
152 * Controlling playback
153 * http://www.musicpd.org/doc/protocol/ch03s03.html
154 */
155
156// next
157Mpc.prototype.next = Mpc.__make_send_void('next');
158// pause {PAUSE}
159Mpc.prototype.pause = Mpc.__make_send_range('pause', 0, 1, 1);
160// play [SONGPOS]
161Mpc.prototype.play = Mpc.__make_send_opt('play');
162// playid [SONGID]
163Mpc.prototype.playid = Mpc.__make_send_opt('playid');
164// previous
165Mpc.prototype.previous = Mpc.__make_send_void('previous');
166// seek {SONGPOS} {TIME}
167Mpc.prototype.seek = Mpc.__make_send_arg2('seek');
168// seekid {SONGID} {TIME}
169Mpc.prototype.seekid = Mpc.__make_send_arg2('seekid');
170// seekcur {TIME}
171Mpc.prototype.seekcur = Mpc.__make_send_arg1('seek');
172// stop
173Mpc.prototype.stop = Mpc.__make_send_void('stop');
174
175/*
176 * Connection settings
177 * http://www.musicpd.org/doc/protocol/ch03s08.html
178 */
179
180// close
181Mpc.prototype.close = Mpc.__make_send_void('close');
182// kill
183Mpc.prototype.kill = Mpc.__make_send_void('kill');
184// password {PASSWORD}
185Mpc.prototype.password = Mpc.__make_send_arg1('password');
186// ping
187Mpc.prototype.ping = Mpc.__make_send_void('ping');