]>
git.wh0rd.org - chrome-ext/music-player-client.git/blob - main.js
1 // Written by Mike Frysinger <vapier@gmail.com>. Released into the public domain. Suck it.
3 /* Globals to allow easy manipulation via javascript console */
8 function TcpClientSender(tcpclient
) {
9 this.tcpclient
= tcpclient
;
11 TcpClientSender
.prototype.send = function(data
, cb
) {
12 this.tcpclient
.sendMessage(data
, cb
);
14 TcpClientSender
.prototype.poll = function() {
15 this.tcpclient
.poll();
17 TcpClientSender
.prototype.reconnect = function() {
18 this.tcpclient
.disconnect();
19 this.tcpclient
.connect();
22 function tramp_mpc_recv(data
) {
26 function sync_storage(sync
) {
27 return sync
? chrome
.storage
.sync
: chrome
.storage
.local
;
30 window
.onload = function() {
35 'host', 'port', 'refresh',
38 'host': '192.168.0.2',
44 chrome
.storage
.local
.get(local_keys
, function(settings
) {
45 local_keys
.forEach(function(key
) {
47 options
[key
] = settings
[key
]
50 var storage
= sync_storage(options
['sync']);
51 storage
.get(sync_keys
, function(settings
) {
52 sync_keys
.forEach(function(key
) {
54 options
[key
] = settings
[key
];
57 init_ui(local_keys
, sync_keys
, options
);
63 window
.onkeypress = function(e
) {
64 if (e
.target
!= document
.body
) {
65 /* Only allow the shortcuts when the focus is on the body.
66 Otherwise you can't type these numbers into text fields. */
72 show_page('controls');
75 show_page('metadata');
78 show_page('playlist');
86 function mpc_refresh() {
90 function mpc_connect(host
, port
) {
91 if (typeof(host
) != 'string') {
92 host
= window
['opts_host'].value
;
93 port
= parseInt(window
['opts_port'].value
);
96 if (mpc
!= undefined) {
97 console
.log('disconnecting');
98 update_ui('disconnect');
100 tcpclient
.disconnect();
105 tcpclient
= new TcpClient(host
, port
);
106 tcpclient
.connect(function(resultCode
) {
107 if (resultCode
< 0) {
108 update_ui('error', resultCode
);
112 var mpc_sender
= new TcpClientSender(tcpclient
);
113 tcpclient
.addResponseListener(tramp_mpc_recv
);
114 mpc
= new Mpc(mpc_sender
, update_ui
);
115 console
.log('connected to ' + host
+ ':' + port
);
116 console
.log('protip: use the "mpc" object to poke mpd directly.\n' +
117 'you can also do mpc.set_debug(3) to see traffic');
119 update_refresh_timer();
123 function tramp_mpc_consume() {
124 var val
= zo(!getToggleButton(this));
126 setToggleButton(this, val
);
128 function tramp_mpc_deleteid() { mpc
.deleteid(this.title
); }
129 function tramp_mpc_next() { mpc
.next(); }
130 function tramp_mpc_pause() { mpc
.pause(); }
131 function tramp_mpc_play() { mpc
.play(); }
132 function tramp_mpc_previous() { mpc
.previous(); }
133 function tramp_mpc_random() {
134 var val
= zo(!getToggleButton(this));
136 setToggleButton(this, val
);
138 function tramp_mpc_repeat() {
139 var val
= zo(!getToggleButton(this));
141 setToggleButton(this, val
);
143 function tramp_mpc_seekcur() { mpc
.seekcur(this.value
); }
144 function tramp_mpc_setvol() { mpc
.setvol(this.value
); }
145 function tramp_mpc_single() {
146 var val
= zo(!getToggleButton(this));
148 setToggleButton(this, val
);
150 function tramp_mpc_stop() { mpc
.stop(); }
156 return val
== '0' ? 0 : 1;
158 function getToggleButton(btn
) {
159 return btn
.style
.borderStyle
== 'inset';
161 function setToggleButton(btn
, val
) {
162 if (val
=== undefined)
163 val
= !getToggleButton(btn
);
164 btn
.style
.borderStyle
= val
? 'inset' : '';
167 function show_page(page
) {
168 if (typeof(page
) != 'string')
169 page
= this.id
.split('.')[1];
171 // We might not be connected in which case 'mpc' will be undefined.
183 var eles
= document
.getElementsByClassName('main');
184 for (var i
= 0; i
< eles
.length
; ++i
) {
188 if (ele
.id
== 'main.' + page
) {
192 ele
.style
.display
= dis
;
193 document
.getElementById('tab.' + ele
.id
.split('.')[1]).className
= cls
;
197 function do_refresh() {
199 refresh_id
= window
.setTimeout(do_refresh
, window
['opts_refresh'].value
* 1000);
202 function update_refresh_timer() {
203 if (!isNaN(refresh_id
))
204 window
.clearTimeout(refresh_id
);
205 var rate
= window
['opts_refresh'].value
* 1000;
207 refresh_id
= window
.setTimeout(do_refresh
, rate
);
210 function update_local_settings() {
212 setting
[this.id
] = this.checked
;
213 chrome
.storage
.local
.set(setting
);
216 function update_sync_settings() {
218 setting
[this.id
] = this.value
;
219 var storage
= sync_storage(window
['opts_sync'].checked
);
220 storage
.set(setting
);
224 update_refresh_timer();
229 function init_ui(local_keys
, sync_keys
, options
) {
235 'controls', 'metadata', 'playlist', 'options',
236 ].forEach(function(id
) {
237 var ele
= document
.getElementById('tab.' + id
);
238 ele
.onclick
= show_page
;
239 ele
.title
= id
+ ' [' + i
+ ']';
243 /* Setup control tab */
244 ui_mpc_status
= document
.getElementById('status');
246 'consume', 'next', 'pause', 'play', 'previous', 'random', 'repeat',
247 'seekcur', 'setvol', 'single', 'stop',
248 ].forEach(function(id
) {
249 var ele
= window
['ui_mpc_' + id
] = document
.getElementById(id
);
250 ele
.onchange
= ele
.onclick
= window
['tramp_mpc_' + id
];
253 ele
.title
+= ' [' + ele
.accessKey
+ ']'
255 window
['ui_mpc_currtime'] = document
.getElementById('currtime');
257 /* Setup metadata tab */
259 'album', 'artist', 'date', 'file', 'title',
260 ].forEach(function(id
) {
261 window
['ui_mpc_metadata_' + id
] = document
.getElementById('metadata.' + id
);
264 /* Setup playlist tab */
265 window
['ui_mpc_playlist'] = document
.getElementById('playlist');
267 /* Setup options tab */
268 document
.getElementById('connect').onclick
= mpc_connect
;
269 local_keys
.forEach(function(id
) {
270 var ele
= window
['opts_' + id
] = document
.getElementById(id
);
271 ele
.checked
= options
[id
];
272 ele
.onchange
= update_local_settings
;
274 sync_keys
.forEach(function(id
) {
275 var ele
= window
['opts_' + id
] = document
.getElementById(id
);
276 ele
.value
= options
[id
];
277 ele
.oninput
= update_sync_settings
;
281 function pretty_time(time
) {
282 var sec
, min
, hrs
, ret
= '';
283 time
= parseInt(time
);
285 min
= parseInt((time
/ 60) % 60);
286 hrs
= parseInt((time
/ 3600) % 3600);
288 ret
= hrs
+ ':' + ("00" + min
).substr(-2) + ':';
291 return ret
+ ("00" + sec
).substr(-2);
294 function playlist_del() {
295 mpc
.deleteid(this.song_id
);
296 this.parentNode
.remove();
299 function playlist_play() {
300 mpc
.playid(this.song_id
);
301 this.parentNode
.style
.fontWeight
= 'bold';
304 function update_ui(state
, cmd
) {
305 if (typeof(state
) == 'string') {
306 ui_mpc_status
.innerText
= ({
307 'disconnect': 'Disconnecting...',
308 'init': 'Connecting...',
309 'error': 'Connection error ' + cmd
,
314 if (Array
.isArray(state
)) {
327 /* Update the metadata tab only when things have changed. */
329 if ('Currentsong' in state
) {
330 currentsong
= state
.Currentsong
;
331 if (ui_mpc_metadata_file
.lastUpdate
!= state
.Currentsong
.lastUpdate
) {
332 ui_mpc_metadata_album
.innerText
= currentsong
.Album
;
333 ui_mpc_metadata_artist
.innerText
= currentsong
.Artist
;
334 ui_mpc_metadata_title
.innerText
= currentsong
.Title
;
335 ui_mpc_metadata_date
.innerText
= currentsong
.Date
;
336 ui_mpc_metadata_file
.innerText
= currentsong
.file
;
340 /* Update the playlist tab only when things have changed. */
341 if ('Playlist' in state
&& ui_mpc_playlist
.lastUpdate
!= state
.Playlist
.lastUpdate
) {
342 var playlist
= state
.Playlist
;
344 ui_mpc_playlist
.innerHTML
= '';
345 playlist
.forEach(function(song
) {
346 var cell
, row
= ui_mpc_playlist
.insertRow(-1);
347 if (currentsong
&& song
.Pos
== currentsong
.Pos
)
348 row
.style
.fontWeight
= 'bold';
350 cell
= row
.insertCell(-1);
351 cell
.id
= 'playlist_del';
352 cell
.innerHTML
= '¤';
353 cell
.song_id
= song
.Id
;
354 cell
.title
= 'delete';
355 cell
.onclick
= playlist_del
;
357 cell
= row
.insertCell(-1);
358 cell
.innerText
= song
.Pos
;
359 cell
.style
.textAlign
= 'right';
360 cell
.song_id
= song
.Id
;
362 cell
.onclick
= playlist_play
;
364 if ('Artist' in song
) {
365 row
.insertCell(-1).innerText
= song
.Artist
;
366 row
.insertCell(-1).innerText
= song
.Album
;
367 row
.insertCell(-1).innerText
= song
.Title
;
369 cell
= row
.insertCell(-1);
370 cell
.innerText
= song
.file
;
373 row
.insertCell(-1).innerText
= pretty_time(song
.Time
);
376 ui_mpc_playlist
.lastUpdate
= playlist
.lastUpdate
;
379 /* Update the status tab. */
381 if ('time' in state
) {
382 // When stopped, there is no time field at all.
383 time
= state
.time
.split(':');
384 percent
= Math
.floor((0.0 + time
[0]) * 100 / (0.0 + time
[1]));
389 ui_mpc_seekcur
.max
= time
[1];
390 ui_mpc_seekcur
.value
= time
[0];
391 ui_mpc_seekcur
.title
= 'seekcur (' + percent
+ '%)';
392 ui_mpc_currtime
.innerText
= [pretty_time(time
[0]), pretty_time(time
[1]), percent
+ '%'].join(' / ');
394 ui_mpc_setvol
.title
= 'setvol';
395 if ('volume' in state
) {
396 ui_mpc_setvol
.value
= state
.volume
;
397 ui_mpc_setvol
.title
+= ' (' + state
.volume
+ '%)';
401 'consume', 'random', 'repeat', 'single',
402 ].forEach(function(id
) {
403 setToggleButton(window
['ui_mpc_' + id
], szo(state
[id
]));
406 ui_mpc_status
.innerText
= ({