]> Joshua Wise's Git repositories - patchfork.git/blame - std/command.js
Add support for view-only mode.
[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;
f8fb3735
JW
418 if (bt) /* we must be in read write mode to show this */ {
419 if(state=="play") {
420 bt.src = IMAGE.BUTTON_PAUSE;
421 if(typeof(window.streaming_try_autoplay)=='function')
422 streaming_try_autoplay();
423 }
424 else {
425 bt.src = IMAGE.BUTTON_PLAY;
426 if(typeof(window.streaming_try_autostop)=='function')
427 streaming_try_autostop();
428 }
964dd0bc
JW
429 }
430 }
431
432 if(typeof info.error != 'undefined' || playing.error) {
433 if(playing.error && get_time() - 10000 > playing.error_time) {
434 playing.error = false;
435 hide_status_bar();
436 send_clear_error();
437 }
438 else if(typeof info.error != 'undefined' && playing.error != info.error) {
439 playing.error = info.error;
440 playing.error_time = get_time();
441 show_status_bar("MPD error: " + playing.error);
442 }
443 }
444
445 var c_play = info.songid;
446 if(typeof(c_play)=='undefined') {
447 playing.id = -1;
448 playing.pos = -1;
449 request_song_info();
450 select_playing_song();
451 }
452 else if(c_play!=playing.id) {
453 playing.id = c_play;
454 playing.pos = parseInt(info.song);
455 select_playing_song();
456 if(pagination_is_following()) {
457 playlist_scroll_to_playing();
458 }
459 /* this is last because it needs the id */
460 request_song_info();
461 }
462 else if(playing.pos!=info.song) {
463 playing.pos = parseInt(info.song);
464 }
465}
466
467function format_playing_time(pos, total) {
468 if(playing.time_dtype==playing.TIME_REMAINING) {
469 return convert_minsec(pos-total) + "/" + convert_minsec(total);
470 }
471 else { // dtype == playing.TIME_ELAPSED || something wrong
472 return convert_minsec(pos) + "/" + convert_minsec(total);
473 }
474}
475
476function request_song_info() {
477 /* clean up */
478 if(playing.id<0) {
479 remove_children(playing.disp_artist);
480 remove_children(playing.disp_title);
481 remove_children(playing.disp_album);
9a6ec85f
JW
482 if(playing.disp_year)
483 remove_children(playing.disp_year);
964dd0bc
JW
484 if(playing.albumart)
485 remove_children(playing.albumart);
486 playing.artist = "";
487 playing.title = "";
488 playing.album = "";
9a6ec85f 489 playing.year = "";
964dd0bc
JW
490 playing.image = "";
491 playing.asin = "";
492 playing.length = "";
493 playing.is_stream = false;
494 set_playing_title();
495 }
496 else {
497 /* or update */
498 send_command("currentsong", update_current_song, false, true);
499 }
500}
501
502function update_current_song(info) {
503 var artist = info[ "Artist"];
504 var title = info["Title"];
505 var album = info[ "Album"];
9a6ec85f 506 var year = (info["Year"] == null) ? info["Date"] : info["Year"];
964dd0bc
JW
507 var a = playing.disp_artist;
508 var t = playing.disp_title;
509 var alb = playing.disp_album;
9a6ec85f 510 var y = playing.disp_year;
964dd0bc
JW
511 var new_thumb = false;
512
513 if(typeof(title)=='undefined')
514 title = "";
515 if(typeof(album)=='undefined')
516 album = "";
517 if(typeof(artist)=='undefined')
518 artist = "";
9a6ec85f
JW
519 if(typeof(year)=='undefined')
520 year = "";
521 else
522 year = "["+year+"]";
964dd0bc
JW
523
524 if(artist!=playing.artist) {
525 playing.artist = artist;
526 new_thumb = true;
527 remove_children(a);
528 a.appendChild(create_txt(artist));
529 }
530 if(playing.album != album) {
531 playing.album = album;
532 new_thumb = true;
533 remove_children(alb);
534 alb.appendChild(create_txt(album));
535 }
9a6ec85f
JW
536 if((playing.year != year) && y) {
537 playing.year = year;
538 new_thumb = true;
539 remove_children(y);
540 y.appendChild(create_txt(year));
541 }
964dd0bc
JW
542
543 if(typeof(info['file'])!='undefined') {
544 var f = info['file'];
545 if(f&&f.indexOf("http://")==0)
546 playing.is_stream = true;
547 else playing.is_stream = false;
548 }
549
550 remove_children(t);
551 playing.title = title;
552
553 if(title==null||title=="") {
554 title = info["file"];
555 if(title)
556 title = title.substring(title.lastIndexOf(DIR_SEPARATOR)+1);
557 }
558 t.appendChild(create_txt(title));
559
560 set_playing_title(artist, title);
561
562 if(new_thumb&&typeof(window.request_thumbnail) == 'function') {
563 setTimeout(request_thumbnail, 1);
564 }
565}
566
567function set_playing_title(artist, title) {
568 if(typeof(artist)=='undefined'||artist==null)
569 artist = "";
570 if(typeof(title)=='undefined'||title==null)
571 title = "";
572
573 var wt = "Pitchfork MPD Client";
574 if(artist.length||title.length) {
575 wt = artist;
576 if(title.length)
577 wt += " - " + title;
578 }
579 document.title = wt;
580}
581
582function volume_adjust(vol) {
583 send_command("volume=" + parseInt(vol));
584}
585
586function position_adjust(pos) {
587 send_command("position=" + parseInt((pos* parseInt(playing.length))/100) + "&id=" + playing.id);
588}
589
590function convert_minsec(sec) {
591 var min = parseInt(sec/60);
592 var s = Math.abs(sec%60);
593 return (sec<0&&min==0?"-" + min:min) + ":" + (s<10?"0" + s:s);
594}
595
596function buttons_init() {
597
598 /* player control */
599 var elem = document.getElementById('pp_button');
f8fb3735
JW
600 if (elem) /* we must be in read write mode to show these buttons */
601 {
602 elem.src = IMAGE.BUTTON_PLAY;
603 add_listener(elem, "click", send_play_pause);
604 if(window.stop_button) {
605 elem = document.getElementById('stop_button');
606 elem.style.display = "";
607 elem.src = IMAGE.BUTTON_STOP;
608 add_listener(elem, "click", send_stop_cmd);
609 elem.parentNode.style.marginLeft = "-15px";
610 }
611
612 elem = document.getElementById("next_button");
613 elem.src = IMAGE.BUTTON_NEXT;
614 add_listener(elem, "click", send_next_song);
615 elem = document.getElementById("previous_button");
616 elem.src = IMAGE.BUTTON_PREVIOUS;
617 add_listener(elem, "click", send_previous_song);
618 }
964dd0bc
JW
619
620 /* left menu buttons */
621 elem = document.getElementById("open_directory_button");
622 elem.src = IMAGE.MENU_ITEM_DIRECTORY;
623 add_listener(elem, "click", open_pl_overlay);
624 elem = document.getElementById("crop_items_button");
625 elem.src = IMAGE.MENU_ITEM_CROP;
626 add_listener(elem, "click", remove_songs_event);
627 elem = document.getElementById("remove_items_button");
628 elem.src = IMAGE.MENU_ITEM_REMOVE;
629 add_listener(elem, "click", remove_songs_event);
630
631 /* server settings */
632 elem = document.getElementById("settings_header");
633 add_listener(elem, "click", open_close_settings);
634 add_listener(elem, "mousedown", stop_event);
635
636 /* playlist */
637 elem = document.getElementById("playlist_add");
638 add_listener(elem, "click", playlist_add_button);
639 elem = document.getElementById("playlist_save");
640 add_listener(elem, "click", playlist_save_button);
641
642 /* status bar */
643 elem = document.getElementById("status_bar_img");
644 elem.src = IMAGE.WORKING;
645
646 /* streaming if applicable */
647 elem = document.getElementById("streaming_open");
648 if(elem) {
649 add_listener(elem, "click", streaming_open);
650 }
651
652 /* time display */
653 elem = get_slider_txt(possliderid);
654 if(elem) {
655 add_listener(elem, "click", change_pos_dtype);
656 }
657
658 // pagination
659 elem = document.getElementById("pagination");
660 if(elem) {
661 add_listener(elem, "click", pagination_change_page);
662 add_listener(elem, "mousemove", pagination_scroll_view);
663 add_listener(elem, "mouseout", pagination_scroll_stop);
664 }
665 elem = document.getElementById("pagination_jump_current");
666 if(elem) {
667 elem.src = IMAGE.JUMP_CURRENT;
668 add_listener(elem, "click", playlist_scroll_to_playing);
669 elem.title = LANG.JUMP_CURRENT;
670 }
671 elem = document.getElementById("pagination_follow_current");
672 if(elem) {
673 add_listener(elem, "click", pagination_toggle_following);
674 }
675
676 elem = document.getElementById("playlist_search_btn");
677 if(elem) {
678 add_listener(elem, "click", plsearch_open);
679 }
680
681 // set it to nothing selected
682 pl_selection_changed(false);
683}
684
685function send_play_pause(e) {
686 stop_event(e);
687 var act = "toggle";
688 if(playing.state=="stop") {
689 act = "play";
690 if(playing.id>=0)
691 act+="&id=" + playing.id;
692 }
693 send_command("act=" + act);
694}
695function send_stop_cmd(e) {
696 stop_event(e);
697 send_command("act=stop");
698}
699function send_next_song(e) {
700 stop_event(e);
701 send_command("act=next");
702}
703function send_previous_song(e) {
704 stop_event(e);
705 send_command("act=previous");
706}
707
708function send_update_db_cmd(e) {
709 stop_event(e);
710 send_command("updatedb");
711}
712
713function send_clear_error() {
714 send_command("clearerror", false, false, true);
715}
716
717function remove_songs_event(e) {
718 var inv = 'crop_items_button'==e.target.id;
719 var sel = get_pl_selection_range(inv);
720 if(!inv) {
721 /* nothing selected if we just removed it,
722 * or at least in theory */
723 pl_selection_changed(false);
724 }
725 if(sel.length==0) {
726 return;
727 }
728 send_command("remove=" + encodeURIComponent(sel), remove_songs_cb, LANG.WAIT_REMOVING);
729}
730
731function remove_songs_cb(response) {
732 if(response!="ok") {
733 show_status_bar(LANG.E_REMOVE);
734 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
735 }
736}
737
738function open_close_settings(e) {
739 var sc = document.getElementById('settings_container');
740 /* close */
741 if(sc.style.display == "block") { /* not perfect but I think there's enough vars at the top */
742 sc.firstChild.style.display = "none";
743 remove_listener(sc, "mousedown", stop_event);
744 remove_listener(sc, "click", settings_click_handler);
745 setTimeout(open_close_settings_timer, settings_time, sc, false, new Array(0, 200));
746 }
747 else {
748 /* open */
749 var dst_height = sc.scrollHeight; // || innerHeight
750 sc.style.height = "50px";
751 sc.style.overflow = "hidden";
752 remove_children(sc.firstChild);
753 sc.firstChild.style.display = "none";
754 sc.firstChild.appendChild(document.createTextNode("Loading.."));
755 sc.style.display = "block";
756 add_listener(sc, "mousedown", stop_event);
757 add_listener(sc, "click", settings_click_handler);
758 setTimeout(open_close_settings_timer, settings_time, sc, true, new Array(0, 200));
759 send_command("outputs", open_settings_cb);
760 }
761}
762
763function open_close_settings_timer(sc, isOpening, heights) {
764 var ad = 50;
765 if(isOpening)
766 heights[0] += ad;
767 else heights[1] -=ad;
768
769 if(heights[0]<heights[1]) {
770 sc.style.height = (isOpening?heights[0]:heights[1]) + "px";
771 setTimeout(open_close_settings_timer, settings_time, sc, isOpening, heights);
772 }
773 else {
774 if(isOpening) {
775 //sc.style.overflow = "auto";
776 sc.firstChild.style.display = "block";
777 sc.style.height = heights[1] + "px";
778 }
779 else {
780 sc.style.display = "none";
781 sc.style.height = heights[0] + "px";
782 }
783 }
784
785}
786
787function create_settings_status_image(stat) {
788 var img = create_node("img");
789 img.className = "server_settings";
790 if(stat==1||stat=="1") {
791 img.src = IMAGE.SERVER_SETTINGS_ENABLED;
792 }
793 else {
794 img.src = IMAGE.SERVER_SETTINGS_DISABLED;
795 }
796 return img;
797}
798
799function open_settings_cb(response) {
800 var txt = document.getElementById('settings_content');
801 remove_children(txt);
802 var img = create_node("img");
803 img.className = "server_settings";
804
805 function add_entry(id, stat, text, no_img) {
806 var span = create_node("span", id);
807 span.className = "server_settings";
808 if(!no_img) {
809 var im = create_settings_status_image(stat);
810 im.id = id + "_img";
811 span.appendChild(im);
812 }
813 span.appendChild(create_txt(" " + text));
814 txt.appendChild(span);
815 txt.appendChild(create_node("br"));
816 return span;
817 }
818
819 add_entry("repeat_toggle", playing.repeat, LANG.REPEAT);
820 add_entry("random_toggle", playing.random, LANG.RANDOM);
821 var xfade = add_entry("xfade_entry", playing.xfade, LANG.XFADE, true);
822 var xe = create_node("img");
823 xe.name = "left";
824 xe.className = "server_settings";
825 xe.src = IMAGE.SERVER_SETTINGS_XFADE_DOWN;
826 xfade.appendChild(xe);
827 var i_right = xe.cloneNode(true);
828 i_right.name = "right";
829 i_right.src = IMAGE.SERVER_SETTINGS_XFADE_UP;
830 xe = create_node("span", "xfade_adjust_txt", " " + playing.xfade + " ");
831 xfade.appendChild(xe);
832 xfade.appendChild(i_right);
833
834 var tmp = create_node("hr");
835 tmp.className = "server_settings";
836 txt.appendChild(tmp);
837 txt.appendChild(create_txt("Outputs:"));
838 txt.appendChild(create_node("br"));
839 try {
840 var outputs = response['outputs'];
841 for(var i in outputs) {
842 var id = outputs[i]["outputid"];
843 var enabled = outputs[i]["outputenabled"];
844 var s = add_entry(OUTPUT_ID + id, enabled, outputs[i]["outputname"]);
845 s.setAttribute("outputenabled", enabled);
846 }
847 }
848 catch(e) {
849 debug(e.message);
850 txt.appendChild(create_txt(LANG.E_NO_OUTPUTS));
851 }
852}
853
854function settings_click_handler(e) {
855 for(var n = e.target; n.parentNode; n=n.parentNode) {
856 if(n.id) {
857 if(n.id.indexOf(OUTPUT_ID)==0&&n.id.indexOf("img")<0) {
858 toggle_output(n);
859 break;
860 }
861 else if(n.id=="repeat_toggle") {
862 toggle_repeat(n);
863 break;
864 }
865 else if(n.id=="random_toggle") {
866 toggle_random(e);
867 break;
868 }
869 else if(n.id=="xfade_entry") {
870 xfade_adjust(n, e);
871 }
872 else if(n.id=="settings_container") {
873 break;
874 }
875 }
876 }
877 stop_event(e);
878}
879
880function toggle_repeat(e) {
881 send_command("repeat=" + (parseInt(playing.repeat)==0?1:0), toggle_repeat_cb);
882}
883function toggle_random(e) {
884 send_command("random=" + (parseInt(playing.random)==0?1:0), toggle_random_cb);
885}
886function toggle_output(e) {
887 target = e;
888 output_toggle_id = target.id;
889 id = target.id.substring(OUTPUT_ID.length);
890 var cmd = "output_";
891 if(target.getAttribute("outputenabled")==1)
892 cmd+="d";
893 else cmd+="e";
894 cmd+="=" + id;
895 send_command(cmd, output_change_cb);
896}
897
898function xfade_adjust(node, ev) {
899 if(!ev.target.name) {
900 return;
901 }
902 var name = ev.target.name;
903 if(name!="left"&&name!="right") {
904 return;
905 }
906 var xfade= parseInt(playing.xfade) + ("left"==name?-1:+1);
907 if(xfade<0)
908 xfade=0;
909 send_command("xfade=" + xfade);
910 var x = document.getElementById("xfade_adjust_txt");
911 if(x.firstChild) {
912 x.firstChild.nodeValue = " " + xfade + " ";
913 }
914}
915
916function toggle_repeat_cb(response) {
917 var n = document.getElementById("repeat_toggle_img");
918 var img = create_settings_status_image(response);
919 replace_node(img, n);
920 img.id = "repeat_toggle_img";
921}
922function toggle_random_cb(response) {
923 var n = document.getElementById("random_toggle_img");
924 var img = create_settings_status_image(response);
925 replace_node(img, n);
926 img.id = "random_toggle_img";
927}
928function output_change_cb(response) {
929 if(output_toggle_id==null)
930 return;
931 var n = document.getElementById(output_toggle_id);
932 if(!n)
933 return;
934 var o_img = document.getElementById(output_toggle_id + "_img");
935 n.setAttribute("outputenabled", response);
936 var img = create_settings_status_image(response);
937 img.id = o_img.id;
938 replace_node(img, o_img);
939 output_toggle_id = null;
940}
941
942
943function send_play_pos(pos) {
944 send_command("act=play&pos=" + pos);
945}
946
947function open_pl_overlay(e) {
948 if(open_overlay_idx<0) {
949 open_overlay_fixed(pl_overlay_id);
950 }
951 else {
952 close_overlay(pl_overlay_id);
953 }
954}
955
956function StatusBar(txt) {
957 this.txt = document.getElementById('status_bar_txt');
958 this.img = document.getElementById('status_bar_img');
959 this.main = document.getElementById('status_bar');
960 this.timer = false;
961}
962
963/* status bar (could be put in toolkit though */
964function show_status_bar(txt, working) {
965 txt = create_txt(txt);
966 remove_children(status_bar.txt);
967 status_bar.txt.appendChild(txt);
968 if(working) {
969 status_bar.img.setAttribute("working", "yeah");
970 }
971 else {
972 if(status_bar.img.hasAttribute("working"))
973 status_bar.img.removeAttribute("working");
974 }
975 status_bar.main.style.display = "block";
976 /* to prevent it from disappearing again if it is showing */
977 if(status_bar.timer) {
978 clearTimeout(status_bar.timer);
979 status_bar.timer = false;
980 }
981}
982
983/* hides status-bar after optional number of seconds */
984function hide_status_bar(time) {
985 if(typeof(time)!='undefined'&&time&&time>0) {
986 status_bar.timer = setTimeout(hide_status_bar, time*1000, false);
987 }
988 else {
989 remove_children(status_bar.txt);
990 if(browser_is_opera()) {
991 opera_quirk_set_display_none(status_bar.main);
992 }
993 else {
994 status_bar.main.style.display = "none";
995 }
996 status_bar.timer = false;
997 }
998}
999
1000function setup_keys() {
1001 keyboard_init();
1002 keyboard_register_listener(send_play_pause, "k", KEYBOARD_NO_KEY, true);
1003 keyboard_register_listener(send_previous_song, "j", KEYBOARD_NO_KEY, true);
1004 keyboard_register_listener(send_next_song, "l", KEYBOARD_NO_KEY, true);
1005 keyboard_register_listener(quickadd_focus, "s", KEYBOARD_CTRL_KEY|KEYBOARD_SHIFT_KEY, true);
1006 /* for browsers where ctrl+shift does something else */
1007 keyboard_register_listener(quickadd_focus, "s", KEYBOARD_CTRL_KEY|KEYBOARD_ALT_KEY, true);
1008 keyboard_register_listener(playlist_scroll_to_playing, " " , KEYBOARD_NO_KEY, true);
1009
1010 var qa = document.getElementById('quickadd');
1011 qa.setAttribute("autocomplete", "off");
1012 add_listener(qa, "keydown", quickadd_keydown_handler); // stop it from getting to the keylisteners!
1013 add_listener(qa, "keyup", quickadd_keyup_handler);
1014 add_listener(qa, "focus", quickadd_focus);
1015 add_listener(qa, "blur", quickadd_blur);
1016 qa.title = LANG.QUICK_ADD + " [Ctrl+Shift+S]";
1017}
1018
1019function change_pos_dtype() {
1020 playing.time_dtype++;
1021 if(playing.time_dtype>=playing.TIME_END) {
1022 playing.time_dtype = 0;
1023 }
1024 setting_set("time_dtype", playing.time_dtype);
1025}
1026
This page took 0.187031 seconds and 4 git commands to generate.