Add support for displaying the year; put the album in italics. (Feature request...
[patchfork.git] / std / command.js
CommitLineData
964dd0bc
JW
1/*
2 Pitchfork Music Player Daemon Client
3 Copyright (C) 2007 Roger Bystrøm
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17*/
18
19var position_txt_node = null;
20var bitrate_txt_node = null;
21var ALBUMART_URL = "metadata.php?pic=";
22var OUTPUT_ID = "output_";
23
24var DIR_SEPARATOR = "/";
25
26var STATUS_DEFAULT_TIMEOUT = 10;
27
28/* todo: put these in an object, no reason for them to be lying around here */
29var last_update_cmd_id;
30var problem_update_delay = 5;
31var last_update = -1;
32var pl = new Array();
33var possliderid = -1;
34var volsliderid = -1;
35var playing = new Object();
36playing.id = -1;
37playing.pos = -1;
38playing.length = 0;
39playing.pl_version = 0;
40playing.pl_size = 0;
41playing.size = 0;
42playing.artist = "";
43playing.album = "";
9a6ec85f 44playing.year = "";
964dd0bc
JW
45playing.title = "";
46playing.image = ""; //
47playing.asin = "";
48playing.random = 0; // random on/off
49playing.repeat = 0; // repeat on/off
50playing.xfade = 0; // crossfade seconds
51playing.update = false; // dbupdate
52playing.show_node = null; // node that is supposed to have playing status
53playing.is_stream = false; // true if the playing song is a stream
54playing.error = false;
55playing.error_time = 0;
56
57playing.state = "";
58playing.volume = -1;
59playing.TIME_ELAPSED = 0;
60playing.TIME_REMAINING = 1;
61playing.TIME_END = 2;
62playing.time_dtype = playing.TIME_ELAPSED;
63
64/* various elements found around the document */
65playing.disp_info = null;
66playing.pp_button = null;
67playing.disp_artist = null;
68playing.disp_title = null;
69playing.disp_album = null;
9a6ec85f 70playing.disp_year = null;
964dd0bc
JW
71playing.albumart = null;
72
73var last_pl_selected = true;
74
75var output_toggle_id = null;
76
77var pl_overlay_id = -1;
78var pl_overlay_write = null;
79
80var status_bar = null;
81
82var send_command_rm_status = false;
83var pl_entry_clone = null;
84
85var settings_time = 10;
86
87var need_info_arr = null;
88
89var init_failed = false;
90
91var playlist_add_popup = null;
92var playlist_save_popup = null;
93
94var pagination = new Object();
95pagination.max = 0; // max pr. page
96pagination.page = 0; // what page we currently are on
97pagination.pages = 0; // number of pages being advertised
98pagination.need_update = false; // indicates wheter we need an update
99pagination.list = null; // reference to the displaying area
100pagination.container = null; // reference to the container
101
102function init_player() {
103 try {
104 status_bar = new StatusBar();
105
106 if(update_delay) {
107 if(update_delay<0)
108 update_delay = 1;
109 update_delay = update_delay * 1000;
110 }
111 else window.update_delay = 1000;
112
113 possliderid = setup_slider(document.getElementById('posslider'), position_adjust, LANG.POSITION);
114 set_slider_pos(possliderid, 0);
115
116 volsliderid = setup_slider(document.getElementById('volslider'), volume_adjust, LANG.VOLUME);
117 set_slider_pos(volsliderid, 0);
118
119 playlist_element = document.getElementById('playlist')
120
121 var pltmp_id = setup_node_move(playlist_element, playlist_move, playlist_get_move_txt);
122 add_move_doubleclick(pltmp_id, playlist_dblclick);
123 set_selection_change_handler(pltmp_id, pl_selection_changed);
124
125 pl_overlay_id = setup_overlay(playlist_element, new Array(10, 10, 300, 300 ), pl_overlay_open_cb, pl_overlay_close_cb);
126 pl_overlay_write = get_overlay_write_area(pl_overlay_id);
127
128 playing.disp_info = document.getElementById('disp_info');
129 playing.disp_artist = document.getElementById('disp_artist');
130 playing.disp_title = document.getElementById('disp_title');
131 playing.disp_album = document.getElementById('disp_album');
9a6ec85f 132 playing.disp_year = document.getElementById('disp_year');
964dd0bc
JW
133 playing.albumart = document.getElementById("albumart");
134 playing.pp_button = document.getElementById("pp_button");
135
136 pagination.list = document.getElementById('pagination_list');
137 pagination.container = document.getElementById('pagination');
138 pagination.max = pagination_max; // nice :S
139
140 var tmp = setting_get("time_dtype");
141
142 if(tmp==null) {
143 setting_set("time_dtype", playing.time_dtype);
144 }
145 else {
146 if(tmp==playing.TIME_ELAPSED)
147 playing.time_dtype = playing.TIME_ELAPSED;
148 else if(tmp==playing.TIME_REMAINING)
149 playing.time_dtype = playing.TIME_REMAINING;
150 }
151
152 xpath_init();
153 buttons_init();
154 setup_keys();
155 pagination_init();
156 sidebar_init();
157 plsearch_init();
158 streaming_init();
159
160 if(typeof(window.metadata_init)=='function')
161 metadata_init();
162 if(typeof(window.recommend_init)=='function')
163 recommend_init();
164 playlist_init();
165 }
166 catch(e) {
167 init_failed = true;
168 debug(LANG.E_INIT +": " + e.message, true);
169 }
170}
171
172/* arg-list: command to send, command to call when result is return, show status message when working,
173 don't request status update with this sendcommand,
174 post data if we should use that, if it should form-urlencoded content type should be set */
175function send_command(command, result_callback, status_msg, nostatus, do_post, form_urlencoded) {
176 if(init_failed)
177 return;
178
179 var http = new XMLHttpRequest();
180 var url = "command.php?" + command;
181
182 if(!nostatus) {
183 url+="&plchanges=" + playing.pl_version;
184 if(pagination.max>0) {
185 url+="&pmax=" + pagination.max + "&page=" + pagination.page;
186 //debug("pmax: " + pagination.max + ", page: " + pagination.page);
187 }
188 }
189
190 if(send_command_rm_status) {
191 hide_status_bar();
192 send_command_rm_status = false;
193 }
194
195 http.onreadystatechange = function() {
196 if(http.readyState==4) {
197 var resp = null;
198 if(http.responseText&&(resp = evaluate_json(http.responseText))) {
199 if(resp['connection']&&resp['connection']=="failed") {
200 last_update = get_time();
201 show_status_bar(LANG.E_CONNECT);
202 send_command_rm_status = true;
203 try {
204 result_callback("failed");
205 }
206 catch(e) {}
207 return;
208 }
209 }
210 else {
211 show_status_bar(LANG.E_INVALID_RESPONSE);
212 send_command_rm_status = true;
213 last_update = get_time();
214 try {
215 result_callback("failed");
216 }
217 catch(e) {}
218 return;
219 }
220
221 if(http.status==200) {
222 var res = resp['result'];
223 var stat = resp["status"];
224 var plchanges = resp["plchanges"];
225 var has_plchanges = plchanges && stat && playing.pl_version != stat.playlist;
226
227 if(res&&result_callback) {
228 result_callback(res);
229 }
230
231 if(stat) {
232 current_status_handler(stat, has_plchanges);
233 last_update = get_time();
234 }
235
236 if(has_plchanges) {
237 playing.pl_version = stat.playlist;
238 plchanges_handler3(plchanges, stat.playlistlength);
239 /* the currently playing song might have changed if it's a stream */
240 if(playing.is_stream) {
241 request_song_info();
242 }
243 }
244
245 /* don't remove if there's no message or a timer */
246 if(status_msg&&!status_bar.timer)
247 hide_status_bar();
248 }
249 else {
250 if(result_callback) {
251 result_callback("server operation failed");
252 }
253 show_status_bar(LANG.NO_RESPONSE); // maybe add a 10 second delay here and reconnect!
254 send_command_rm_status = true;
255 }
256 }
257 }
258
259 if(status_msg) {
260 show_status_bar(status_msg, true);
261 }
262
263
264 if(do_post) {
265 http.open("POST", url);
266 if(form_urlencoded) {
267 http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
268 }
269 http.send(do_post);
270 }
271 else {
272 http.open("GET", url);
273 http.send(null);
274 }
275}
276
277function update_callback(res) {
278 var time = update_delay;
279 if(res=="failed")
280 time = problem_update_delay*update_delay;
281 last_update_cmd_id = setTimeout(need_update, time);
282}
283
284function reschedule_update_now() {
285 clearTimeout(last_update_cmd_id);
286 // make sure it get's run immidiately
287 last_update_cmd_id = setTimeout(need_update, 0, -update_delay);
288}
289
290function need_update(delay) {
291 if(!delay)
292 delay = 0;
293 var now = get_time();
294 if(now>last_update+update_delay+delay-20) { // giving it a little slack
295 send_command("ping", update_callback);
296 }
297 else {
298 delay = last_update+update_delay-now;
299 if(delay<10)
300 delay = 10;
301
302 last_update_cmd_id = setTimeout(need_update, delay);
303 }
304}
305
306/* stop program */
307function handle_fatal_error(txt) {
308 show_status_bar(txt);
309 clearTimeout(last_update_cmd_id);
310}
311
312/* current status handler, info is stats
313 * if has_plchanges it is assumed the data also carries plchanges
314 * which will handle resizing of the playlist */
315function current_status_handler(info, has_plchanges) {
316 if(!info) {
317 // something is wrong
318 set_slider_pos(possliderid, 0);
319 return;
320 }
321
322 var tmp = info.playlistlength;
323 if((tmp = parseInt(tmp))>=0) {
324 if(playing.pl_size!=tmp) {
325 playing.pl_size = tmp;
326 if(pagination.max>0) {
327 // make sure size fits inside what we have as number of pages
328 var s = pagination.max * (pagination.pages);
329 if(tmp < s-pagination.max || tmp>=s) {
330 pagination_update_list(tmp);
331 }
332 if(!has_plchanges) {
333 playlist_resize(tmp);
334 }
335 }
336 else if(!has_plchanges) { // if it doesn't carry plchanges we have to do it here
337 playlist_resize(tmp);
338 }
339 }
340 }
341
342 tmp = info.updating_db;
343 if(tmp) {
344 tmp = parseInt(tmp);
345 if(playing.update!=tmp) {
346 playing.update = tmp;
347 show_status_bar(LANG.WAIT_UPDATING_DB, true);
348 }
349 }
350 else if(playing.update) {
351 playing.update = false;
352 hide_status_bar();
353 }
354
355 var state = info["state"];
356 var volume = info[ "volume"];
357 if(volume!=null&&volume!=playing.volume) {
358 set_slider_pos(volsliderid, volume);
359 playing.volume = volume;
360 }
361
362 playing.repeat = info.repeat;
363 playing.random = info.random;
364 playing.xfade = info.xfade;
365
366 if(state!="stop") {
367
368 var pos = info["time"].split(":");
369 set_slider_pos(possliderid, (pos[0]*100)/pos[1]);
370 playing.length = pos[1];
371
372 /* complex, but seems to be somewhat better in firefox */
373 var tmp = info.bitrate;
374 if(tmp&&playing.bitrate!=tmp) {
375 var disp_info = playing.disp_info
376 if(bitrate_txt_node==null) {
377 bitrate_txt_node = document.createTextNode(LANG.BITRATE);
378 disp_info.appendChild(bitrate_txt_node);
379 if(disp_info.normalize)
380 disp_info.normalize();
381 bitrate_txt_node = disp_info.firstChild.splitText(LANG.BITRATE.length);
382 }
383 var rep = document.createTextNode(tmp);
384 disp_info.replaceChild(rep, bitrate_txt_node);
385 bitrate_txt_node = rep;
386 playing.bitrate = tmp;
387 }
388
389 var postxt = get_slider_txt(possliderid);
390 if(postxt) {
391 if(position_txt_node==null) {
392 position_txt_node = postxt.firstChild.splitText(LANG.POSITION.length);
393 }
394 var rep = create_txt(format_playing_time(pos[0], pos[1]));
395 postxt.replaceChild(rep, position_txt_node);
396 position_txt_node = rep;
397 }
398 }
399 else if(playing.state!="stop") { // state == stop and last state wasn't stop
400 set_slider_pos(possliderid, 0);
401 var disp_info = playing.disp_info;
402 var rep = document.createTextNode("0");
403 var postxt = get_slider_txt(possliderid);
404 if(bitrate_txt_node&&bitrate_txt_node!=null) {
405 disp_info.replaceChild(rep, bitrate_txt_node);
406 bitrate_txt_node = rep;
407 }
408 playing.bitrate = 0;
409 rep = document.createTextNode("");
410 if(position_txt_node&&position_txt_node!=null) {
411 postxt.replaceChild(rep, position_txt_node);
412 position_txt_node = rep;
413 }
414 }
415 if(state!=playing.state) {
416 playing.state = state;
417 var bt = playing.pp_button;
418 if(state=="play") {
419 bt.src = IMAGE.BUTTON_PAUSE;
420 if(typeof(window.streaming_try_autoplay)=='function')
421 streaming_try_autoplay();
422 }
423 else {
424 bt.src = IMAGE.BUTTON_PLAY;
425 if(typeof(window.streaming_try_autostop)=='function')
426 streaming_try_autostop();
427 }
428 }
429
430 if(typeof info.error != 'undefined' || playing.error) {
431 if(playing.error && get_time() - 10000 > playing.error_time) {
432 playing.error = false;
433 hide_status_bar();
434 send_clear_error();
435 }
436 else if(typeof info.error != 'undefined' && playing.error != info.error) {
437 playing.error = info.error;
438 playing.error_time = get_time();
439 show_status_bar("MPD error: " + playing.error);
440 }
441 }
442
443 var c_play = info.songid;
444 if(typeof(c_play)=='undefined') {
445 playing.id = -1;
446 playing.pos = -1;
447 request_song_info();
448 select_playing_song();
449 }
450 else if(c_play!=playing.id) {
451 playing.id = c_play;
452 playing.pos = parseInt(info.song);
453 select_playing_song();
454 if(pagination_is_following()) {
455 playlist_scroll_to_playing();
456 }
457 /* this is last because it needs the id */
458 request_song_info();
459 }
460 else if(playing.pos!=info.song) {
461 playing.pos = parseInt(info.song);
462 }
463}
464
465function format_playing_time(pos, total) {
466 if(playing.time_dtype==playing.TIME_REMAINING) {
467 return convert_minsec(pos-total) + "/" + convert_minsec(total);
468 }
469 else { // dtype == playing.TIME_ELAPSED || something wrong
470 return convert_minsec(pos) + "/" + convert_minsec(total);
471 }
472}
473
474function request_song_info() {
475 /* clean up */
476 if(playing.id<0) {
477 remove_children(playing.disp_artist);
478 remove_children(playing.disp_title);
479 remove_children(playing.disp_album);
9a6ec85f
JW
480 if(playing.disp_year)
481 remove_children(playing.disp_year);
964dd0bc
JW
482 if(playing.albumart)
483 remove_children(playing.albumart);
484 playing.artist = "";
485 playing.title = "";
486 playing.album = "";
9a6ec85f 487 playing.year = "";
964dd0bc
JW
488 playing.image = "";
489 playing.asin = "";
490 playing.length = "";
491 playing.is_stream = false;
492 set_playing_title();
493 }
494 else {
495 /* or update */
496 send_command("currentsong", update_current_song, false, true);
497 }
498}
499
500function update_current_song(info) {
501 var artist = info[ "Artist"];
502 var title = info["Title"];
503 var album = info[ "Album"];
9a6ec85f 504 var year = (info["Year"] == null) ? info["Date"] : info["Year"];
964dd0bc
JW
505 var a = playing.disp_artist;
506 var t = playing.disp_title;
507 var alb = playing.disp_album;
9a6ec85f 508 var y = playing.disp_year;
964dd0bc
JW
509 var new_thumb = false;
510
511 if(typeof(title)=='undefined')
512 title = "";
513 if(typeof(album)=='undefined')
514 album = "";
515 if(typeof(artist)=='undefined')
516 artist = "";
9a6ec85f
JW
517 if(typeof(year)=='undefined')
518 year = "";
519 else
520 year = "["+year+"]";
964dd0bc
JW
521
522 if(artist!=playing.artist) {
523 playing.artist = artist;
524 new_thumb = true;
525 remove_children(a);
526 a.appendChild(create_txt(artist));
527 }
528 if(playing.album != album) {
529 playing.album = album;
530 new_thumb = true;
531 remove_children(alb);
532 alb.appendChild(create_txt(album));
533 }
9a6ec85f
JW
534 if((playing.year != year) && y) {
535 playing.year = year;
536 new_thumb = true;
537 remove_children(y);
538 y.appendChild(create_txt(year));
539 }
964dd0bc
JW
540
541 if(typeof(info['file'])!='undefined') {
542 var f = info['file'];
543 if(f&&f.indexOf("http://")==0)
544 playing.is_stream = true;
545 else playing.is_stream = false;
546 }
547
548 remove_children(t);
549 playing.title = title;
550
551 if(title==null||title=="") {
552 title = info["file"];
553 if(title)
554 title = title.substring(title.lastIndexOf(DIR_SEPARATOR)+1);
555 }
556 t.appendChild(create_txt(title));
557
558 set_playing_title(artist, title);
559
560 if(new_thumb&&typeof(window.request_thumbnail) == 'function') {
561 setTimeout(request_thumbnail, 1);
562 }
563}
564
565function set_playing_title(artist, title) {
566 if(typeof(artist)=='undefined'||artist==null)
567 artist = "";
568 if(typeof(title)=='undefined'||title==null)
569 title = "";
570
571 var wt = "Pitchfork MPD Client";
572 if(artist.length||title.length) {
573 wt = artist;
574 if(title.length)
575 wt += " - " + title;
576 }
577 document.title = wt;
578}
579
580function volume_adjust(vol) {
581 send_command("volume=" + parseInt(vol));
582}
583
584function position_adjust(pos) {
585 send_command("position=" + parseInt((pos* parseInt(playing.length))/100) + "&id=" + playing.id);
586}
587
588function convert_minsec(sec) {
589 var min = parseInt(sec/60);
590 var s = Math.abs(sec%60);
591 return (sec<0&&min==0?"-" + min:min) + ":" + (s<10?"0" + s:s);
592}
593
594function buttons_init() {
595
596 /* player control */
597 var elem = document.getElementById('pp_button');
598 elem.src = IMAGE.BUTTON_PLAY;
599 add_listener(elem, "click", send_play_pause);
600 if(window.stop_button) {
601 elem = document.getElementById('stop_button');
602 elem.style.display = "";
603 elem.src = IMAGE.BUTTON_STOP;
604 add_listener(elem, "click", send_stop_cmd);
605 elem.parentNode.style.marginLeft = "-15px";
606 }
607
608 elem = document.getElementById("next_button");
609 elem.src = IMAGE.BUTTON_NEXT;
610 add_listener(elem, "click", send_next_song);
611 elem = document.getElementById("previous_button");
612 elem.src = IMAGE.BUTTON_PREVIOUS;
613 add_listener(elem, "click", send_previous_song);
614
615 /* left menu buttons */
616 elem = document.getElementById("open_directory_button");
617 elem.src = IMAGE.MENU_ITEM_DIRECTORY;
618 add_listener(elem, "click", open_pl_overlay);
619 elem = document.getElementById("crop_items_button");
620 elem.src = IMAGE.MENU_ITEM_CROP;
621 add_listener(elem, "click", remove_songs_event);
622 elem = document.getElementById("remove_items_button");
623 elem.src = IMAGE.MENU_ITEM_REMOVE;
624 add_listener(elem, "click", remove_songs_event);
625
626 /* server settings */
627 elem = document.getElementById("settings_header");
628 add_listener(elem, "click", open_close_settings);
629 add_listener(elem, "mousedown", stop_event);
630
631 /* playlist */
632 elem = document.getElementById("playlist_add");
633 add_listener(elem, "click", playlist_add_button);
634 elem = document.getElementById("playlist_save");
635 add_listener(elem, "click", playlist_save_button);
636
637 /* status bar */
638 elem = document.getElementById("status_bar_img");
639 elem.src = IMAGE.WORKING;
640
641 /* streaming if applicable */
642 elem = document.getElementById("streaming_open");
643 if(elem) {
644 add_listener(elem, "click", streaming_open);
645 }
646
647 /* time display */
648 elem = get_slider_txt(possliderid);
649 if(elem) {
650 add_listener(elem, "click", change_pos_dtype);
651 }
652
653 // pagination
654 elem = document.getElementById("pagination");
655 if(elem) {
656 add_listener(elem, "click", pagination_change_page);
657 add_listener(elem, "mousemove", pagination_scroll_view);
658 add_listener(elem, "mouseout", pagination_scroll_stop);
659 }
660 elem = document.getElementById("pagination_jump_current");
661 if(elem) {
662 elem.src = IMAGE.JUMP_CURRENT;
663 add_listener(elem, "click", playlist_scroll_to_playing);
664 elem.title = LANG.JUMP_CURRENT;
665 }
666 elem = document.getElementById("pagination_follow_current");
667 if(elem) {
668 add_listener(elem, "click", pagination_toggle_following);
669 }
670
671 elem = document.getElementById("playlist_search_btn");
672 if(elem) {
673 add_listener(elem, "click", plsearch_open);
674 }
675
676 // set it to nothing selected
677 pl_selection_changed(false);
678}
679
680function send_play_pause(e) {
681 stop_event(e);
682 var act = "toggle";
683 if(playing.state=="stop") {
684 act = "play";
685 if(playing.id>=0)
686 act+="&id=" + playing.id;
687 }
688 send_command("act=" + act);
689}
690function send_stop_cmd(e) {
691 stop_event(e);
692 send_command("act=stop");
693}
694function send_next_song(e) {
695 stop_event(e);
696 send_command("act=next");
697}
698function send_previous_song(e) {
699 stop_event(e);
700 send_command("act=previous");
701}
702
703function send_update_db_cmd(e) {
704 stop_event(e);
705 send_command("updatedb");
706}
707
708function send_clear_error() {
709 send_command("clearerror", false, false, true);
710}
711
712function remove_songs_event(e) {
713 var inv = 'crop_items_button'==e.target.id;
714 var sel = get_pl_selection_range(inv);
715 if(!inv) {
716 /* nothing selected if we just removed it,
717 * or at least in theory */
718 pl_selection_changed(false);
719 }
720 if(sel.length==0) {
721 return;
722 }
723 send_command("remove=" + encodeURIComponent(sel), remove_songs_cb, LANG.WAIT_REMOVING);
724}
725
726function remove_songs_cb(response) {
727 if(response!="ok") {
728 show_status_bar(LANG.E_REMOVE);
729 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
730 }
731}
732
733function open_close_settings(e) {
734 var sc = document.getElementById('settings_container');
735 /* close */
736 if(sc.style.display == "block") { /* not perfect but I think there's enough vars at the top */
737 sc.firstChild.style.display = "none";
738 remove_listener(sc, "mousedown", stop_event);
739 remove_listener(sc, "click", settings_click_handler);
740 setTimeout(open_close_settings_timer, settings_time, sc, false, new Array(0, 200));
741 }
742 else {
743 /* open */
744 var dst_height = sc.scrollHeight; // || innerHeight
745 sc.style.height = "50px";
746 sc.style.overflow = "hidden";
747 remove_children(sc.firstChild);
748 sc.firstChild.style.display = "none";
749 sc.firstChild.appendChild(document.createTextNode("Loading.."));
750 sc.style.display = "block";
751 add_listener(sc, "mousedown", stop_event);
752 add_listener(sc, "click", settings_click_handler);
753 setTimeout(open_close_settings_timer, settings_time, sc, true, new Array(0, 200));
754 send_command("outputs", open_settings_cb);
755 }
756}
757
758function open_close_settings_timer(sc, isOpening, heights) {
759 var ad = 50;
760 if(isOpening)
761 heights[0] += ad;
762 else heights[1] -=ad;
763
764 if(heights[0]<heights[1]) {
765 sc.style.height = (isOpening?heights[0]:heights[1]) + "px";
766 setTimeout(open_close_settings_timer, settings_time, sc, isOpening, heights);
767 }
768 else {
769 if(isOpening) {
770 //sc.style.overflow = "auto";
771 sc.firstChild.style.display = "block";
772 sc.style.height = heights[1] + "px";
773 }
774 else {
775 sc.style.display = "none";
776 sc.style.height = heights[0] + "px";
777 }
778 }
779
780}
781
782function create_settings_status_image(stat) {
783 var img = create_node("img");
784 img.className = "server_settings";
785 if(stat==1||stat=="1") {
786 img.src = IMAGE.SERVER_SETTINGS_ENABLED;
787 }
788 else {
789 img.src = IMAGE.SERVER_SETTINGS_DISABLED;
790 }
791 return img;
792}
793
794function open_settings_cb(response) {
795 var txt = document.getElementById('settings_content');
796 remove_children(txt);
797 var img = create_node("img");
798 img.className = "server_settings";
799
800 function add_entry(id, stat, text, no_img) {
801 var span = create_node("span", id);
802 span.className = "server_settings";
803 if(!no_img) {
804 var im = create_settings_status_image(stat);
805 im.id = id + "_img";
806 span.appendChild(im);
807 }
808 span.appendChild(create_txt(" " + text));
809 txt.appendChild(span);
810 txt.appendChild(create_node("br"));
811 return span;
812 }
813
814 add_entry("repeat_toggle", playing.repeat, LANG.REPEAT);
815 add_entry("random_toggle", playing.random, LANG.RANDOM);
816 var xfade = add_entry("xfade_entry", playing.xfade, LANG.XFADE, true);
817 var xe = create_node("img");
818 xe.name = "left";
819 xe.className = "server_settings";
820 xe.src = IMAGE.SERVER_SETTINGS_XFADE_DOWN;
821 xfade.appendChild(xe);
822 var i_right = xe.cloneNode(true);
823 i_right.name = "right";
824 i_right.src = IMAGE.SERVER_SETTINGS_XFADE_UP;
825 xe = create_node("span", "xfade_adjust_txt", " " + playing.xfade + " ");
826 xfade.appendChild(xe);
827 xfade.appendChild(i_right);
828
829 var tmp = create_node("hr");
830 tmp.className = "server_settings";
831 txt.appendChild(tmp);
832 txt.appendChild(create_txt("Outputs:"));
833 txt.appendChild(create_node("br"));
834 try {
835 var outputs = response['outputs'];
836 for(var i in outputs) {
837 var id = outputs[i]["outputid"];
838 var enabled = outputs[i]["outputenabled"];
839 var s = add_entry(OUTPUT_ID + id, enabled, outputs[i]["outputname"]);
840 s.setAttribute("outputenabled", enabled);
841 }
842 }
843 catch(e) {
844 debug(e.message);
845 txt.appendChild(create_txt(LANG.E_NO_OUTPUTS));
846 }
847}
848
849function settings_click_handler(e) {
850 for(var n = e.target; n.parentNode; n=n.parentNode) {
851 if(n.id) {
852 if(n.id.indexOf(OUTPUT_ID)==0&&n.id.indexOf("img")<0) {
853 toggle_output(n);
854 break;
855 }
856 else if(n.id=="repeat_toggle") {
857 toggle_repeat(n);
858 break;
859 }
860 else if(n.id=="random_toggle") {
861 toggle_random(e);
862 break;
863 }
864 else if(n.id=="xfade_entry") {
865 xfade_adjust(n, e);
866 }
867 else if(n.id=="settings_container") {
868 break;
869 }
870 }
871 }
872 stop_event(e);
873}
874
875function toggle_repeat(e) {
876 send_command("repeat=" + (parseInt(playing.repeat)==0?1:0), toggle_repeat_cb);
877}
878function toggle_random(e) {
879 send_command("random=" + (parseInt(playing.random)==0?1:0), toggle_random_cb);
880}
881function toggle_output(e) {
882 target = e;
883 output_toggle_id = target.id;
884 id = target.id.substring(OUTPUT_ID.length);
885 var cmd = "output_";
886 if(target.getAttribute("outputenabled")==1)
887 cmd+="d";
888 else cmd+="e";
889 cmd+="=" + id;
890 send_command(cmd, output_change_cb);
891}
892
893function xfade_adjust(node, ev) {
894 if(!ev.target.name) {
895 return;
896 }
897 var name = ev.target.name;
898 if(name!="left"&&name!="right") {
899 return;
900 }
901 var xfade= parseInt(playing.xfade) + ("left"==name?-1:+1);
902 if(xfade<0)
903 xfade=0;
904 send_command("xfade=" + xfade);
905 var x = document.getElementById("xfade_adjust_txt");
906 if(x.firstChild) {
907 x.firstChild.nodeValue = " " + xfade + " ";
908 }
909}
910
911function toggle_repeat_cb(response) {
912 var n = document.getElementById("repeat_toggle_img");
913 var img = create_settings_status_image(response);
914 replace_node(img, n);
915 img.id = "repeat_toggle_img";
916}
917function toggle_random_cb(response) {
918 var n = document.getElementById("random_toggle_img");
919 var img = create_settings_status_image(response);
920 replace_node(img, n);
921 img.id = "random_toggle_img";
922}
923function output_change_cb(response) {
924 if(output_toggle_id==null)
925 return;
926 var n = document.getElementById(output_toggle_id);
927 if(!n)
928 return;
929 var o_img = document.getElementById(output_toggle_id + "_img");
930 n.setAttribute("outputenabled", response);
931 var img = create_settings_status_image(response);
932 img.id = o_img.id;
933 replace_node(img, o_img);
934 output_toggle_id = null;
935}
936
937
938function send_play_pos(pos) {
939 send_command("act=play&pos=" + pos);
940}
941
942function open_pl_overlay(e) {
943 if(open_overlay_idx<0) {
944 open_overlay_fixed(pl_overlay_id);
945 }
946 else {
947 close_overlay(pl_overlay_id);
948 }
949}
950
951function StatusBar(txt) {
952 this.txt = document.getElementById('status_bar_txt');
953 this.img = document.getElementById('status_bar_img');
954 this.main = document.getElementById('status_bar');
955 this.timer = false;
956}
957
958/* status bar (could be put in toolkit though */
959function show_status_bar(txt, working) {
960 txt = create_txt(txt);
961 remove_children(status_bar.txt);
962 status_bar.txt.appendChild(txt);
963 if(working) {
964 status_bar.img.setAttribute("working", "yeah");
965 }
966 else {
967 if(status_bar.img.hasAttribute("working"))
968 status_bar.img.removeAttribute("working");
969 }
970 status_bar.main.style.display = "block";
971 /* to prevent it from disappearing again if it is showing */
972 if(status_bar.timer) {
973 clearTimeout(status_bar.timer);
974 status_bar.timer = false;
975 }
976}
977
978/* hides status-bar after optional number of seconds */
979function hide_status_bar(time) {
980 if(typeof(time)!='undefined'&&time&&time>0) {
981 status_bar.timer = setTimeout(hide_status_bar, time*1000, false);
982 }
983 else {
984 remove_children(status_bar.txt);
985 if(browser_is_opera()) {
986 opera_quirk_set_display_none(status_bar.main);
987 }
988 else {
989 status_bar.main.style.display = "none";
990 }
991 status_bar.timer = false;
992 }
993}
994
995function setup_keys() {
996 keyboard_init();
997 keyboard_register_listener(send_play_pause, "k", KEYBOARD_NO_KEY, true);
998 keyboard_register_listener(send_previous_song, "j", KEYBOARD_NO_KEY, true);
999 keyboard_register_listener(send_next_song, "l", KEYBOARD_NO_KEY, true);
1000 keyboard_register_listener(quickadd_focus, "s", KEYBOARD_CTRL_KEY|KEYBOARD_SHIFT_KEY, true);
1001 /* for browsers where ctrl+shift does something else */
1002 keyboard_register_listener(quickadd_focus, "s", KEYBOARD_CTRL_KEY|KEYBOARD_ALT_KEY, true);
1003 keyboard_register_listener(playlist_scroll_to_playing, " " , KEYBOARD_NO_KEY, true);
1004
1005 var qa = document.getElementById('quickadd');
1006 qa.setAttribute("autocomplete", "off");
1007 add_listener(qa, "keydown", quickadd_keydown_handler); // stop it from getting to the keylisteners!
1008 add_listener(qa, "keyup", quickadd_keyup_handler);
1009 add_listener(qa, "focus", quickadd_focus);
1010 add_listener(qa, "blur", quickadd_blur);
1011 qa.title = LANG.QUICK_ADD + " [Ctrl+Shift+S]";
1012}
1013
1014function change_pos_dtype() {
1015 playing.time_dtype++;
1016 if(playing.time_dtype>=playing.TIME_END) {
1017 playing.time_dtype = 0;
1018 }
1019 setting_set("time_dtype", playing.time_dtype);
1020}
1021
This page took 0.100324 seconds and 4 git commands to generate.