]> Joshua Wise's Git repositories - patchfork.git/blob - std/command.js
Add support for view-only mode.
[patchfork.git] / std / command.js
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
19 var position_txt_node = null;
20 var bitrate_txt_node = null;
21 var ALBUMART_URL = "metadata.php?pic=";
22 var OUTPUT_ID = "output_";
23
24 var DIR_SEPARATOR = "/";
25
26 var STATUS_DEFAULT_TIMEOUT = 10;
27
28 /* todo: put these in an object, no reason for them to be lying around here */
29 var last_update_cmd_id;
30 var problem_update_delay = 5;
31 var last_update = -1; 
32 var pl = new Array();
33 var possliderid = -1;
34 var volsliderid = -1;
35 var playing = new Object();
36 playing.id = -1;
37 playing.pos = -1;
38 playing.length = 0;
39 playing.pl_version = 0;
40 playing.pl_size = 0;
41 playing.size = 0;
42 playing.artist = "";
43 playing.album = "";
44 playing.year = "";
45 playing.title = "";
46 playing.image = "";     // 
47 playing.asin = "";      
48 playing.random = 0;     // random on/off
49 playing.repeat = 0;     // repeat on/off
50 playing.xfade = 0;      // crossfade seconds
51 playing.update = false; // dbupdate
52 playing.show_node = null; // node that is supposed to have playing status
53 playing.is_stream = false; // true if the playing song is a stream
54 playing.error = false;
55 playing.error_time = 0;
56
57 playing.state = "";
58 playing.volume = -1;
59 playing.TIME_ELAPSED = 0; 
60 playing.TIME_REMAINING = 1;
61 playing.TIME_END = 2; 
62 playing.time_dtype = playing.TIME_ELAPSED;
63
64 /* various elements found around the document */
65 playing.disp_info = null;
66 playing.pp_button = null;
67 playing.disp_artist = null;
68 playing.disp_title = null; 
69 playing.disp_album = null;
70 playing.disp_year = null;
71 playing.albumart = null;
72
73 var last_pl_selected = true;
74
75 var output_toggle_id = null;
76
77 var pl_overlay_id = -1;
78 var pl_overlay_write = null;
79
80 var status_bar = null;
81
82 var send_command_rm_status = false;
83 var pl_entry_clone = null;
84
85 var settings_time = 10;
86
87 var need_info_arr = null;
88
89 var init_failed = false;
90
91 var playlist_add_popup = null;
92 var playlist_save_popup = null;
93
94 var pagination = new Object();
95 pagination.max = 0; // max pr. page
96 pagination.page = 0; // what page we currently are on
97 pagination.pages = 0; // number of pages being advertised
98 pagination.need_update = false; // indicates wheter we need an update
99 pagination.list = null; // reference to the displaying area
100 pagination.container = null; // reference to the container
101
102 function 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');
132                 playing.disp_year = document.getElementById('disp_year');
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 */
175 function 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
277 function 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
284 function 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
290 function 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 */
307 function 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 */
315 function 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 (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                         }
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
467 function 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
476 function 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);
482                 if(playing.disp_year)
483                         remove_children(playing.disp_year);
484                 if(playing.albumart)
485                         remove_children(playing.albumart);
486                 playing.artist = "";
487                 playing.title = "";
488                 playing.album = "";
489                 playing.year = "";
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
502 function update_current_song(info) {
503         var artist = info[ "Artist"];
504         var title = info["Title"];
505         var album = info[ "Album"];
506         var year = (info["Year"] == null) ? info["Date"] : info["Year"];
507         var a = playing.disp_artist;
508         var t = playing.disp_title;
509         var alb = playing.disp_album;
510         var y = playing.disp_year;
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 = "";
519         if(typeof(year)=='undefined')
520                 year = "";
521         else
522                 year = "["+year+"]";
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         }
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         }
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
567 function 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
582 function volume_adjust(vol) {
583         send_command("volume=" + parseInt(vol));
584 }
585
586 function position_adjust(pos) {
587         send_command("position=" + parseInt((pos* parseInt(playing.length))/100) + "&id=" + playing.id);
588 }
589
590 function 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
596 function buttons_init() {
597         
598         /* player control */
599         var elem = document.getElementById('pp_button');
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         }
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
685 function 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 }
695 function send_stop_cmd(e) {
696         stop_event(e);
697         send_command("act=stop");
698 }
699 function send_next_song(e) {
700         stop_event(e);
701         send_command("act=next");
702 }
703 function send_previous_song(e) {
704         stop_event(e);
705         send_command("act=previous");
706 }
707
708 function send_update_db_cmd(e) {
709         stop_event(e);
710         send_command("updatedb");
711 }
712
713 function send_clear_error() {
714         send_command("clearerror", false, false, true);
715 }
716
717 function 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
731 function 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
738 function 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
763 function 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
787 function 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
799 function 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
854 function 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
880 function toggle_repeat(e) {
881         send_command("repeat=" + (parseInt(playing.repeat)==0?1:0), toggle_repeat_cb);
882 }
883 function toggle_random(e) {
884         send_command("random=" + (parseInt(playing.random)==0?1:0), toggle_random_cb);
885 }
886 function 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
898 function 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
916 function 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 }
922 function 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 }
928 function 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
943 function send_play_pos(pos) {
944         send_command("act=play&pos=" + pos);
945 }
946
947 function 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
956 function 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 */
964 function 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 */
984 function 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
1000 function 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
1019 function 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.12917 seconds and 4 git commands to generate.