maybe better stuff to avoid browser-side caching
[enigma2-plugins.git] / webinterface / src / web-data / tools.js
1 //$Header$
2 var DBG = true;
3 DBG = false;
4
5 var templates = {};
6 var loadedChannellist = {};
7
8 var epgListData = {};
9 var signalPanelData = {};
10
11 var mediaPlayerStarted = false; 
12 var popUpBlockerHinted = false;
13
14 var settings = null;
15 var parentControlList = null;
16
17 var requestcounter = 0;
18
19 var debugWin = '';
20 var signalWin = '';
21 var webRemoteWin = '';
22 var EPGListWin = '';
23
24 var currentBouquet = bouquetsTv;
25
26 var updateBouquetItemsPoller = '';
27 var updateCurrentPoller = '';
28 var signalPanelUpdatePoller = '';
29
30 var hideNotifierTimeout = '';
31
32 var isActive = {};
33 isActive.getCurrent = false;
34
35 var currentLocation = "/hdd/movie";
36 var locationsList = [];
37 var tagsList = [];
38
39 var boxtype = "";
40
41 function startUpdateCurrentPoller(){
42         updateCurrentPoller = setInterval(updateItems, 10000);
43 }
44
45 function stopUpdateCurrentPoller(){
46         clearInterval(updateCurrentPoller);
47 }
48
49 function getXML(request){
50         var xmlDoc = "";
51
52         if(window.ActiveXObject){ // we're on IE
53                 xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
54                 xmlDoc.async="false";
55                 xmlDoc.loadXML(request.responseText);
56         } else { //we're not on IE
57                 if (!window.google || !google.gears){
58                         xmlDoc = request.responseXML;
59                 } else { //no responseXML on gears
60                         xmlDoc = (new DOMParser()).parseFromString(request.responseText, "text/xml");
61                 }
62         }
63
64         return xmlDoc;
65 }
66 /*
67 * Set boxtype Variable for being able of determining model specific stuff correctly (like WebRemote)
68 */
69 function incomingDeviceInfoBoxtype(request){
70         debug("[incomingAboutBoxtype] returned");
71         boxtype = getXML(request).getElementsByTagName("e2devicename").item(0).firstChild.data;
72
73         debug("[incomingAboutBoxtype] Boxtype: " + boxtype);
74 }
75
76
77 function getBoxtype(){
78         doRequest(URL.deviceinfo, incomingDeviceInfoBoxtype, false);
79 }
80
81 function toggleStandby(){
82         sendPowerState(0);
83 }
84
85 function incomingPowerState(request){
86         var standby = getXML(request).getElementsByTagName("e2instandby").item(0).firstChild.data;
87         
88         var signal = $('openSignalPanel');
89         var signalImg = $('openSignalPanelImg');
90         
91         if(standby.strip() == "false"){
92                 signal.stopObserving('click', openSignalPanel);
93                 signal.observe('click', openSignalPanel);
94                 
95                 signalImg.src = "/web-data/img/signal.png";
96                 signalImg.title = "Show Signal Panel";
97                 
98         } else {
99                 signal.stopObserving('click', openSignalPanel);         
100                 
101                 signalImg.src = "/web-data/img/signal_off.png";
102                 signalImg.title = "Please disable standby first";
103         }
104 }
105
106 function getPowerState(){
107         doRequest(URL.powerstate, incomingPowerState);  
108 }
109
110 function set(element, value){
111         element = parent.$(element);
112         if (element){
113                 element.innerHTML = value;
114         }
115 }
116
117 function hideNotifier(){
118         $('notification').fade({duration : 0.5 });
119 }
120
121 function notify(text, state){
122         notif = $('notification');
123
124         if(notif !== null){
125                 //clear possibly existing hideNotifier timeout of a previous notfication
126                 clearTimeout(hideNotifierTimeout);
127                 if(state === false){
128                         notif.style.background = "#C00";
129                 } else {
130                         notif.style.background = "#85C247";
131                 }                               
132
133                 set('notification', "<div>"+text+"</div>");
134                 notif.appear({duration : 0.5, to: 0.9 });
135                 hideNotifierTimeout = setTimeout(hideNotifier, 7500);
136         }
137 }
138
139
140 function simpleResultHandler(simpleResult){
141         notify(simpleResult.statetext, simpleResult.state);
142 }
143
144
145 function startUpdateBouquetItemsPoller(){
146         debug("[startUpdateBouquetItemsPoller] called");
147         updateBouquetItemsPoller = setInterval(updateItemsLazy, 60000);
148 }
149
150
151 function stopUpdateBouquetItemsPoller(){
152         debug("[stopUpdateBouquetItemsPoller] called");
153         clearInterval(updateBouquetItemsPoller);
154 }
155
156
157 //General Helpers
158 function parseNr(num) {
159         if(isNaN(num)){
160                 return 0;
161         } else {
162                 return Number(num);
163         }
164 }
165
166
167 function dec2hex(nr, len){
168
169         var hex = parseInt(nr, 10).toString(16).toUpperCase();
170         if(len > 0){
171                 try{
172                         while(hex.length < len){
173                                 hex = "0"+hex;
174                         }
175                 } 
176                 catch(e){
177                         //something went wrong, return -1
178                         hex = -1;
179                 }
180         } 
181         return hex;
182 }
183
184
185 function quotes2html(txt) {
186         if(typeof(txt) != "undefined"){
187                 return txt.replace(/'/g, "\\'").replace(/"/g, '&quot;');
188         } else {
189                 return "";
190         }
191 }
192
193 function addLeadingZero(nr){
194         if(nr < 10){
195                 return '0' + nr;
196         }
197         return nr;
198 }
199
200 function dateToString(date){
201
202         var dateString = "";
203
204         dateString += date.getFullYear();
205         dateString += "-" + addLeadingZero(date.getMonth()+1);
206         dateString += "-" + addLeadingZero(date.getDate());
207         dateString += " " + addLeadingZero(date.getHours());
208         dateString += ":" + addLeadingZero(date.getMinutes());
209
210         return dateString;
211 }
212
213
214 function showhide(id){
215         var s = $(id).style;
216         s.display = (s.display!="none")? "none":"";
217 }
218
219
220 function show(id){
221         try{
222                 $(id).style.display = "";
223         } catch(e) {
224 //              debug("[show] Could not show element with id: " + id);
225         }
226 }
227
228
229 function hide(id){
230         try{
231                 $(id).style.display = "none";
232         } catch(e) {
233 //              debug("[hide] Could not hide element with id: " + id);
234         }
235 }
236
237
238 /*
239 * Sets the Loading Notification to the given HTML Element
240 * @param targetElement - The element the Ajax-Loader should be set in
241 */
242 function setAjaxLoad(targetElement){
243         $(targetElement).innerHTML = getAjaxLoad();
244 }
245
246
247 //Ajax Request Helpers
248 //requestindikator
249
250 function requestIndicatorUpdate(){
251         /*debug(requestcounter+" open requests");
252         if(requestcounter>=1){
253                 $('RequestIndicator').style.display = "inline";
254         }else{
255                 $('RequestIndicator').style.display = "none";
256         }*/
257 }
258
259 function requestStarted(){
260         requestcounter +=1;
261         requestIndicatorUpdate();
262 }
263
264 function requestFinished(){
265         requestcounter -= 1;
266         requestIndicatorUpdate();
267 }
268
269 //Popup And Messagebox Helpers
270 function messageBox(m){
271         alert(m);
272 }
273
274
275 function popUpBlockerHint(){
276         if(!popUpBlockerHinted){
277                 popUpBlockerHinted = true;
278                 messageBox("Please disable your Popup-Blocker for enigma2 WebControl to work flawlessly!");
279
280         }
281 }
282
283 function setWindowContent(window, html){
284         window.document.write(html);
285         window.document.close();
286 }
287
288 function openPopup(title, html, width, height, x, y){
289         try {
290                 var popup = window.open('about:blank',title,'scrollbars=yes, width='+width+',height='+height);          
291                 setWindowContent(popup, html);
292                 return popup;
293         } catch(e){
294                 popUpBlockerHint();
295                 return "";
296         }
297 }
298
299 function openPopupPage(title, uri, width, height, x, y){
300         try {
301                 var popup = window.open(uri,title,'scrollbars=yes, width='+width+',height='+height);
302                 return popup;
303         } catch(e){
304                 popUpBlockerHint();
305                 return "";
306         }
307 }
308
309 function debug(text){
310         if(DBG){
311                 try{
312                         if(!debugWin.closed && debugWin.location){
313                                 var inner = debugWin.document.getElementById('debugContent').innerHTML;
314                                 debugWin.document.getElementById('debugContent').innerHTML = new Date().toLocaleString() + ": "+text+"<br>" + inner;
315                         }
316                 } catch (Exception) {
317                         popUpBlockerHint();
318                 }
319
320         }
321 }
322
323
324 //Template Helpers
325 function saveTpl(request, tplName){
326         debug("[saveTpl] saving template: " + tplName);
327         templates[tplName] = request.responseText;
328 }
329
330
331 function renderTpl(tpl, data, domElement) {     
332         var result = tpl.process(data);
333
334         try{
335                 $(domElement).innerHTML = result;
336         }catch(ex){
337                 //              debug("[renderTpl] exception: " + ex);
338         }
339 }
340
341
342 function fetchTpl(tplName, callback){
343         if(typeof(templates[tplName]) == "undefined") {
344                 var url = URL.tpl+tplName+".htm";
345
346                 doRequest(
347                                 url, 
348                                 function(transport){
349                                         saveTpl(transport, tplName);
350                                         if(typeof(callback) == 'function'){
351                                                 callback();
352                                         }
353                                 }
354                 );
355         } else {
356                 if(typeof(callback) == 'function'){
357                         callback();
358                 }
359         }
360 }
361
362 function incomingProcessTpl(request, data, domElement, callback){
363         if(request.readyState == 4){
364                 renderTpl(request.responseText, data, domElement);
365                 if(typeof(callback) == 'function') {
366                         callback();
367                 }
368         }
369 }
370
371 function processTpl(tplName, data, domElement, callback){
372         var url = URL.tpl+tplName+".htm";
373
374         doRequest(url, 
375                         function(transport){
376                 incomingProcessTpl(transport, data, domElement, callback);
377         }
378         );
379 }
380
381 //Debugging Window
382
383
384 function openDebug(){
385         var uri = URL.tpl+'tplDebug.htm';
386         debugWin = openPopupPage("Debug", uri, 500, 300);
387 }
388
389 function doRequest(url, readyFunction){
390         requestStarted();
391         var request = '';
392         // gears or not that's the question here
393         if (!window.google || !google.gears){ //no gears, how sad
394 //              debug("NO GEARS!!");            
395                 try{
396                         request = new Ajax.Request(url,
397                                         {
398                                 asynchronous: true,
399                                 method: 'GET',
400                                 requestHeaders: ['Pragma', 'no-cache', 'Cache-Control', 'no-cache', 'Cache-Control', 'no-store', 'Expires', '0'],
401                                 onException: function(o,e){ throw(e); },                                
402                                 onSuccess: function (transport, json) {                                         
403                                         if(typeof(readyFunction) != "undefined"){
404                                                 readyFunction(transport);
405                                         }
406                                 },
407                                 onComplete: requestFinished 
408                                         });
409                 } catch(e) {}
410         } else { //we're on gears!
411                 try{
412                         request = google.gears.factory.create('beta.httprequest');
413                         request.open('GET', url);
414
415                         if( typeof(readyFunction) != "undefined" ){
416                                 request.onreadystatechange = function(){                                
417                                         if(request.readyState == 4){
418                                                 if(request.status == 200){                      
419                                                         readyFunction(request);
420                                                 } else {
421                                                         //we COULD do some error handling here
422                                                 }
423                                         }
424                                 };
425                         }
426                         request.send();
427                 } catch(e) {}
428         }
429 }
430
431 //Parental Control
432 function incomingParentControl(request) {
433         if(request.readyState == 4){
434                 parentControlList = new ServiceList(getXML(request)).getArray();
435                 debug("[incomingParentControl] Got "+parentControlList.length + " services");
436         }
437 }
438
439 function getParentControl() {
440         doRequest(URL.parentcontrol, incomingParentControl, false);
441 }
442
443
444 function getParentControlByRef(txt) {
445         debug("[getParentControlByRef] ("+txt+")");
446         for(var i = 0; i < parentControlList.length; i++) {
447                 debug( "[getParentControlByRef] "+parentControlList[i].getClearServiceReference() );
448                 if(String(parentControlList[i].getClearServiceReference()) == String(txt)) {
449                         return parentControlList[i].getClearServiceReference();
450                 } 
451         }
452         return "";
453 }
454
455
456 //Settings
457 function getSettingByName(txt) {
458         debug("[getSettingByName] (" + txt + ")");
459         for(var i = 0; i < settings.length; i++) {
460                 debug("("+settings[i].getSettingName()+") (" +settings[i].getSettingValue()+")");
461                 if(String(settings[i].getSettingName()) == String(txt)) {
462                         return settings[i].getSettingValue().toLowerCase();
463                 } 
464         }
465         return "";
466 }
467
468 function parentPin(servicereference) {
469         debug("[parentPin] parentControlList");
470         servicereference = decodeURIComponent(servicereference);
471         if(parentControlList === null || String(getSettingByName("config.ParentalControl.configured")) != "true") {
472                 return true;
473         }
474         //debug("parentPin " + parentControlList.length);
475         if(getParentControlByRef(servicereference) == servicereference) {
476                 if(String(getSettingByName("config.ParentalControl.type.value")) == "whitelist") {
477                         debug("[parentPin] Channel in whitelist");
478                         return true;
479                 }
480         } else {
481                 debug("[parentPin] sRef differs ");
482                 return true;
483         }
484         debug("[parentPin] Asking for PIN");
485
486         var userInput = prompt('Parental Control is enabled!<br> Please enter the Parental Control PIN','PIN');
487         if (userInput !== '' && userInput !== null) {
488                 if(String(userInput) == String(getSettingByName("config.ParentalControl.servicepin.0")) ) {
489                         return true;
490                 } else {
491                         return parentPin(servicereference);
492                 }
493         } else {
494                 return false;
495         }
496 }
497
498
499 function incomingGetDreamboxSettings(request){
500         if(request.readyState == 4){
501                 settings = new Settings(getXML(request)).getArray();
502
503                 debug("[incomingGetDreamboxSettings] config.ParentalControl.configured="+ getSettingByName("config.ParentalControl.configured"));
504
505                 if(String(getSettingByName("config.ParentalControl.configured")) == "true") {
506                         getParentControl();
507                 }
508         }
509
510
511
512 }
513
514
515 function getDreamboxSettings(){
516         doRequest(URL.settings, incomingGetDreamboxSettings, false);
517 }
518
519
520 //Subservices
521 function incomingSubServiceRequest(request){
522         if(request.readyState == 4){
523                 var services = new ServiceList(getXML(request)).getArray();
524                 debug("[incomingSubServiceRequest] Got " + services.length + " SubServices");
525
526                 if(services.length > 1) {
527
528                         var first = services[0];
529
530                         // we already have the main service in our servicelist so we'll
531                         // start with the second element                        
532                         services.shift();
533                         
534                         var data = { subservices : services };
535                         
536
537                         var id = 'SUB'+first.servicereference;
538                         show('tr' + id);
539                         processTpl('tplSubServices', data, id);
540                 }
541         }
542 }
543
544
545 function getSubServices(bouquet) {
546         doRequest(URL.subservices, incomingSubServiceRequest, false);
547 }
548
549
550 function delayedGetSubservices(){
551         setTimeout(getSubServices, 5000);
552 }
553
554 //zap zap
555 function zap(servicereference){
556         doRequest("/web/zap?sRef=" + servicereference); 
557         setTimeout(updateItemsLazy, 7000); //reload epg and subservices
558         setTimeout(updateItems, 3000);
559 }
560
561 //SignalPanel
562
563 function updateSignalPanel(){   
564         var html = templates.tplSignalPanel.process(signalPanelData);
565
566         if (!signalWin.closed && signalWin.location) {
567                 setWindowContent(signalWin, html);
568         } else {
569                 clearInterval(signalPanelUpdatePoller);
570                 signalPanelUpdatePoller = '';
571         }
572 }
573
574 function incomingSignalPanel(request){
575         var namespace = {};
576
577         if (request.readyState == 4){
578                 var xml = getXML(request).getElementsByTagName("e2frontendstatus").item(0);
579                 namespace = {
580                                 snrdb : xml.getElementsByTagName('e2snrdb').item(0).firstChild.data,
581                                 snr : xml.getElementsByTagName('e2snr').item(0).firstChild.data,
582                                 ber : xml.getElementsByTagName('e2ber').item(0).firstChild.data,
583                                 acg : xml.getElementsByTagName('e2acg').item(0).firstChild.data
584                 };
585         }
586
587         signalPanelData = { signal : namespace };
588         fetchTpl('tplSignalPanel', updateSignalPanel);  
589 }
590
591 function reloadSignalPanel(){
592         doRequest(URL.signal, incomingSignalPanel, false);
593 }
594
595 function openSignalPanel(){
596         if (!(!signalWin.closed && signalWin.location)){
597                 signalWin = openPopup('SignalPanel', '', 220, 120);
598                 if(signalPanelUpdatePoller === ''){
599                         signalPanelUpdatePoller = setInterval(reloadSignalPanel, 5000);
600                 }
601         }
602         reloadSignalPanel();
603 }
604
605 //EPG functions
606
607
608 function showEpgList(){
609         var html = templates.tplEpgList.process(epgListData);
610
611         if (!EPGListWin.closed && EPGListWin.location) {
612                 setWindowContent(EPGListWin, html);
613         } else {
614                 EPGListWin = openPopup("EPG", html, 900, 500);
615         }
616 }
617
618 function incomingEPGrequest(request){
619         debug("[incomingEPGrequest] readyState" +request.readyState);           
620         if (request.readyState == 4){
621                 var EPGItems = new EPGList(getXML(request)).getArray(true);
622                 debug("[incomingEPGrequest] got "+EPGItems.length+" e2events");
623
624                 if( EPGItems.length > 0){
625                         epgListData = {epg : EPGItems};
626                         fetchTpl('tplEpgList', showEpgList);
627                 } else {
628                         messageBox('No Items found!', 'Sorry but I could not find any EPG Content containing your search value');
629                 }
630         }
631 }
632
633 function loadEPGBySearchString(string){
634         doRequest(URL.epgsearch+escape(string),incomingEPGrequest, false);
635 }
636
637 function loadEPGByServiceReference(servicereference){
638         doRequest(URL.epgservice+servicereference,incomingEPGrequest, false);
639 }
640
641 function buildServiceListEPGItem(epgevent, type){
642         var data = {epg : epgevent};
643         // e.innerHTML = RND(tplServiceListEPGItem, namespace);
644
645         var id = type + epgevent.servicereference;
646
647         show('tr' + id);
648
649         if(typeof(templates.tplServiceListEPGItem) != "undefined"){
650                 renderTpl(templates.tplServiceListEPGItem, data, id, true);
651         } else {
652                 debug("[buildServiceListEPGItem] tplServiceListEPGItem N/A");
653         }
654 }
655
656 function incomingServiceEPGNowNext(request, type){
657         if(request.readyState == 4){
658                 var epgevents = getXML(request).getElementsByTagName("e2eventlist").item(0).getElementsByTagName("e2event");
659                 for (var c = 0; c < epgevents.length; c++){
660                         try{
661                                 var epgEvt = new EPGEvent(epgevents.item(c), c).toJSON();
662                         } catch (e){
663                                 debug("[incomingServiceEPGNowNext]" + e);
664                         }
665
666                         if (epgEvt.eventid != ''){
667                                 buildServiceListEPGItem(epgEvt, type);
668                         }
669                 }
670         }
671 }
672
673 function incomingServiceEPGNow(request){
674         incomingServiceEPGNowNext(request, 'NOW');
675 }
676
677 function incomingServiceEPGNext(request){
678         incomingServiceEPGNowNext(request, 'NEXT');
679 }
680
681 function loadServiceEPGNowNext(servicereference, next){
682         var url = URL.epgnow+servicereference;
683
684         if(typeof(next) == 'undefined'){
685                 doRequest(url, incomingServiceEPGNow, false);
686         } else {
687                 url = URL.epgnext+servicereference;
688                 doRequest(url, incomingServiceEPGNext, false);
689         }
690 }
691
692
693 function getBouquetEpg(){
694         loadServiceEPGNowNext(currentBouquet);
695         loadServiceEPGNowNext(currentBouquet, true);
696 }
697
698
699 function recordNowPopup(){
700         var result = confirm(   
701                         "OK: Record current event\n" +
702                         "Cancel: Start infinite recording"
703         );
704
705         if( result === true || result === false){
706                 recordNowDecision(result);
707         }
708 }
709
710
711 //+++++++++++++++++++++++++++++++++++++++++++++++++++++
712 //+++++++++++++++++++++++++++++++++++++++++++++++++++++
713 //++++ volume functions ++++
714 //+++++++++++++++++++++++++++++++++++++++++++++++++++++
715 //+++++++++++++++++++++++++++++++++++++++++++++++++++++
716 function handleVolumeRequest(request){
717         if (request.readyState == 4) {
718                 var b = getXML(request).getElementsByTagName("e2volume");
719                 var newvalue = b.item(0).getElementsByTagName('e2current').item(0).firstChild.data;
720                 var mute = b.item(0).getElementsByTagName('e2ismuted').item(0).firstChild.data;
721                 debug("[handleVolumeRequest] Volume " + newvalue + " | Mute: " + mute);
722
723                 for (var i = 1; i <= 10; i++)           {
724                         if ( (newvalue/10)>=i){
725                                 $("volume"+i).src = "/web-data/img/led_on.png";
726                         }else{
727                                 $("volume"+i).src = "/web-data/img/led_off.png";
728                         }
729                 }
730                 if (mute == "False"){
731                         $("speaker").src = "/web-data/img/speak_on.png";
732                 }else{
733                         $("speaker").src = "/web-data/img/speak_off.png";
734                 }
735         }       
736 }
737
738
739 function getVolume(){
740         doRequest(URL.getvolume, handleVolumeRequest, false);
741 }
742
743 function volumeSet(val){
744         doRequest(URL.setvolume+val, handleVolumeRequest, false);
745 }
746
747 function volumeUp(){
748         doRequest(URL.volumeup, handleVolumeRequest, false);
749 }
750
751 function volumeDown(){
752         doRequest(URL.volumedown, handleVolumeRequest, false);
753 }
754
755 function volumeMute(){
756         doRequest(URL.volumemute, handleVolumeRequest, false);
757 }
758
759 function initVolumePanel(){
760         getVolume(); 
761 }
762
763
764
765 //Channels and Bouquets
766
767 function incomingChannellist(request){
768         var serviceList = null;
769         if(typeof(loadedChannellist[currentBouquet]) != "undefined"){
770                 serviceList = loadedChannellist[currentBouquet];
771         } else if(request.readyState == 4) {
772                 serviceList = new ServiceList(getXML(request)).getArray();
773                 debug("[incomingChannellist] got "+serviceList.length+" Services");
774         }
775         if(serviceList !== null) {              
776                 var data = { services : serviceList };
777
778                 processTpl('tplServiceList', data, 'contentMain', getBouquetEpg);
779                 delayedGetSubservices();
780         } else {
781                 debug("[incomingChannellist] services is null");
782         }
783 }
784
785
786 function loadBouquet(servicereference, name){ 
787         debug("[loadBouquet] called");
788
789         currentBouquet = servicereference;
790
791         setContentHd(name);
792         setAjaxLoad('contentMain');
793
794         startUpdateBouquetItemsPoller();
795
796         doRequest(URL.getservices+servicereference, incomingChannellist, true);
797 }
798
799
800 function incomingBouquetListInitial(request){
801         if (request.readyState == 4) {
802                 var bouquetList = new ServiceList(getXML(request)).getArray();
803                 debug("[incomingBouquetListInitial] Got " + bouquetList.length + " TV Bouquets!");      
804
805                 // loading first entry of TV Favorites as default for ServiceList
806                 loadBouquet(bouquetList[0].servicereference, bouquetList[0].servicename);
807         }
808 }
809
810
811 function incomingBouquetList(request){
812         if (request.readyState == 4) {
813                 var bouquetList = new ServiceList(getXML(request)).getArray();
814                 debug("[incomingBouquetList] got " + bouquetList.length + " TV Bouquets!");     
815                 
816                 var data = { services : bouquetList };
817
818                 processTpl('tplBouquetList', data, 'contentMain');
819         }
820 }
821
822
823 function initChannelList(){
824         var url = URL.getservices+encodeURIComponent(bouquetsTv);
825         currentBouquet = bouquetsTv;
826
827         doRequest(url, incomingBouquetListInitial, true);
828 }
829
830
831
832 //Movies
833 function initMovieList(){
834         // get videodirs, last_videodir, and all tags
835         doRequest(URL.getcurrlocation, incomingMovieListCurrentLocation, false);
836 }
837
838 function incomingMovieListCurrentLocation(request){
839         if(request.readyState == 4){
840                 result  = new SimpleXMLList(getXML(request), "e2location");
841                 currentLocation = result.getList()[0];
842                 debug("[incomingMovieListCurrentLocation].currentLocation" + currentLocation);
843                 doRequest(URL.getlocations, incomingMovieListLocations, false);
844         }
845 }
846
847 function incomingMovieListLocations(request){
848         if(request.readyState == 4){
849                 result  = new SimpleXMLList(getXML(request), "e2location");
850                 locationsList = result.getList();
851
852                 if (locationsList.length === 0) {
853                         locationsList = ["/hdd/movie"];
854                 }
855                 doRequest(URL.gettags, incomingMovieListTags, false);
856         }
857 }
858
859 function incomingMovieListTags(request){
860         if(request.readyState == 4){
861                 result  = new SimpleXMLList(getXML(request), "e2tag");
862                 tagsList = result.getList();
863         }
864 }
865
866 function createOptionListSimple(lst, selected) {
867         var namespace = Array();
868         var i = 0;
869         var found = false;
870
871         for (i = 0; i < lst.length; i++) {
872                 if (lst[i] == selected) {
873                         found = true;
874                 }
875         }
876
877         if (!found) {
878                 lst = [ selected ].concat(lst);
879         }
880
881         for (i = 0; i < lst.length; i++) {
882                 namespace[i] = {
883                                 'value': lst[i],
884                                 'txt': lst[i],
885                                 'selected': (lst[i] == selected ? "selected" : " ")};
886         }
887
888         return namespace;
889 }
890
891 function loadMovieNav(){
892         // fill in menus
893         var data = {
894                         dirname: createOptionListSimple(locationsList, currentLocation),
895                         tags: createOptionListSimple(tagsList, "")
896         };
897
898         processTpl('tplNavMovies', data, 'navContent');
899 }
900
901 function incomingMovieList(request){
902         if(request.readyState == 4){
903
904                 var movieList = new MovieList(getXML(request)).getArray();
905                 debug("[incomingMovieList] Got "+movieList.length+" movies");
906
907                 var data = { movies : movieList };
908                 processTpl('tplMovieList', data, 'contentMain');
909         }               
910 }
911
912 function loadMovieList(loc, tag){
913         if(typeof(loc) == 'undefined'){
914                 loc = currentLocation;
915         }
916         if(typeof(tag) == 'undefined'){
917                 tag = '';
918         }
919         debug("[loadMovieList] Loading movies in location '"+loc+"' with tag '"+tag+"'");
920         doRequest(URL.movielist+"?dirname="+loc+"&tag="+tag, incomingMovieList, false);
921 }
922
923
924 function incomingDelMovieResult(request) {
925         debug("[incomingDelMovieResult] called");
926         if(request.readyState == 4){
927                 var result = new SimpleXMLResult(getXML(request));
928                 if(result.getState()){                  
929                         loadMovieList();
930                 }
931                 simpleResultHandler(result);
932         }               
933 }
934
935
936 function delMovie(sref ,servicename, title, description) {
937         debug("[delMovie] File(" + unescape(sref) + "), servicename(" + servicename + ")," +
938                         "title(" + unescape(title) + "), description(" + description + ")");
939
940         result = confirm( "Are you sure want to delete the Movie?\n" +
941                         "Servicename: " + servicename + "\n" +
942                         "Title: " + unescape(title) + "\n" + 
943                         "Description: " + description + "\n");
944
945         if(result){
946                 debug("[delMovie] ok confirm panel"); 
947                 doRequest(URL.moviedelete+"?sRef="+unescape(sref), incomingDelMovieResult, false); 
948                 return true;
949         }
950         else{
951                 debug("[delMovie] cancel confirm panel");
952                 return false;
953         }
954 }
955
956 //Send Messages and Receive the Answer
957
958
959 function incomingMessageResult(request){
960         if(request.readyState== 4){
961                 var result = new SimpleXMLResult(getXML(request));
962                 simpleResultHandler(result);
963         }
964 }
965
966 function getMessageAnswer() {
967         doRequest(URL.messageanswer, incomingMessageResult, false);
968 }
969
970 function sendMessage(messagetext, messagetype, messagetimeout){
971         if(!messagetext){
972                 messagetext = $('MessageSendFormText').value;
973         }       
974         if(!messagetimeout){
975                 messagetimeout = $('MessageSendFormTimeout').value;
976         }       
977         if(!messagetype){
978                 var index = $('MessageSendFormType').selectedIndex;
979                 messagetype = $('MessageSendFormType').options[index].value;
980         }       
981         if(parseNr(messagetype) === 0){
982                 doRequest(URL.message+'?text='+messagetext+'&type='+messagetype+'&timeout='+messagetimeout);
983                 setTimeout(getMessageAnswer, parseNr(messagetimeout)*1000);
984         } else {
985                 doRequest(URL.message+'?text='+messagetext+'&type='+messagetype+'&timeout='+messagetimeout, incomingMessageResult, false);
986         }
987 }
988
989
990 //Screenshots
991 function getScreenShot(what) {
992         debug("[getScreenShot] called");
993
994         var buffer = new Image();
995         var downloadStart;
996         var data = {};
997
998         buffer.onload = function () { 
999                 debug("[getScreenShot] image assigned");
1000
1001                 data = { img : { src : buffer.src } };  
1002                 processTpl('tplGrab', data, 'contentMain');
1003
1004                 return true;
1005         };
1006
1007         buffer.onerror = function (meldung) { 
1008                 debug("[getScreenShot] Loading image failed"); 
1009                 return true;
1010         };
1011
1012         switch(what){
1013         case "o":
1014                 what = "&o=&n=";
1015                 break;
1016         case "v":
1017                 what = "&v=";
1018                 break;
1019         default:
1020                 what = "";
1021         break;
1022         }
1023
1024         downloadStart = new Date().getTime();
1025         buffer.src = '/grab?format=jpg&r=720&' + what + '&filename=/tmp/' + downloadStart;
1026 }
1027
1028 function getVideoShot() {
1029         getScreenShot("v");
1030 }
1031
1032 function getOsdShot(){
1033         getScreenShot("o");
1034 }
1035
1036 //RemoteControl Code
1037
1038 function incomingRemoteControlResult(request){
1039 //      if(request.readyState == 4){
1040 //              var b = getXML(request).getElementsByTagName("e2remotecontrol");
1041 //              var result = b.item(0).getElementsByTagName('e2result').item(0).firstChild.data;
1042 //              var resulttext = b.item(0).getElementsByTagName('e2resulttext').item(0).firstChild.data;
1043 //      }
1044 }
1045
1046 function openWebRemote(){
1047         var template = templates.tplWebRemoteOld;
1048
1049         if(boxtype == "dm8000"){
1050                 template = templates.tplWebRemote;
1051         }
1052
1053
1054         if (!webRemoteWin.closed && webRemoteWin.location) {
1055                 setWindowContent(webRemoteWin, template);
1056         } else {
1057                 webRemoteWin = openPopup('WebRemote', template, 250, 600);
1058         }
1059
1060 }
1061
1062
1063 function loadAndOpenWebRemote(){
1064         if(boxtype == "dm8000"){
1065                 fetchTpl('tplWebRemote', openWebRemote);
1066                 
1067         } else {
1068                 fetchTpl('tplWebRemoteOld', openWebRemote);
1069         }
1070 }
1071
1072
1073 function sendRemoteControlRequest(command){
1074         doRequest(URL.remotecontrol+'?command='+command, incomingRemoteControlResult, false);
1075         if(webRemoteWin.document.getElementById('getScreen').checked) {
1076                 if(webRemoteWin.document.getElementById('getVideo').checked){
1077                         getScreenShot();
1078                 } else {
1079                         getScreenShot("o");
1080                 }
1081         }
1082 }
1083
1084
1085 // Array.insert( index, value ) - Insert value at index, without overwriting existing keys
1086 Array.prototype.insert = function( j, v ) {
1087         if( j>=0 ) {
1088                 var a = this.slice(), b = a.splice( j );
1089                 a[j] = v;
1090                 return a.concat( b );
1091         }
1092 };
1093
1094 //Array.splice() - Remove or replace several elements and return any deleted
1095 //elements
1096 if( typeof Array.prototype.splice==='undefined' ) {
1097         Array.prototype.splice = function( a, c ) {
1098                 var e = arguments, d = this.copy(), f = a, l = this.length;
1099
1100                 if( !c ) { 
1101                         c = l - a; 
1102                 }
1103
1104                 for( var i = 0; i < e.length - 2; i++ ) { 
1105                         this[a + i] = e[i + 2]; 
1106                 }
1107
1108
1109                 for( var j = a; j < l - c; j++ ) { 
1110                         this[j + e.length - 2] = d[j - c]; 
1111                 }
1112                 this.length -= c - e.length + 2;
1113
1114                 return d.slice( f, f + c );
1115         };
1116 }
1117
1118 function ifChecked(rObj) {
1119         if(rObj.checked) {
1120                 return rObj.value;
1121         } else {
1122                 return "";
1123         }
1124 }
1125
1126 //Device Info
1127 /*
1128  * Handles an incoming request for /web/deviceinfo Parses the Data, and calls
1129  * everything needed to render the Template using the parsed data and set the
1130  * result into contentMain @param request - the XHR
1131  */
1132 function incomingDeviceInfo(request) {
1133         if(request.readyState == 4){
1134                 debug("[incomingDeviceInfo] called");
1135                 var deviceInfo = new DeviceInfo(getXML(request));
1136
1137                 processTpl('tplDeviceInfo', deviceInfo, 'contentMain');
1138         }
1139 }
1140
1141
1142 /*
1143  * Show Device Info Information in contentMain
1144  */
1145 function showDeviceInfo() {
1146         doRequest(URL.deviceinfo, incomingDeviceInfo, false);
1147 }
1148
1149 function showGears(){
1150         var enabled = false;
1151         
1152         if (window.google && google.gears){
1153                 enabled = gearsEnabled();
1154         }
1155         
1156         data = { 'useGears' : enabled };
1157         processTpl('tplGears', data, 'contentMain');
1158 }
1159  
1160  
1161 // Spezial functions, mostly for testing purpose
1162 function openHiddenFunctions(){
1163         openPopup("Extra Hidden Functions",tplExtraHiddenFunctions,300,100,920,0);
1164 }
1165
1166
1167 function startDebugWindow() {
1168         DBG = true;
1169         debugWin = openPopup("DEBUG", "", 300, 300,920,140, "debugWindow");
1170 }
1171
1172
1173 function restartTwisted() {
1174         doRequest( "/web/restarttwisted" );
1175 }
1176
1177
1178 //MediaPlayer
1179 function sendMediaPlayer(command) {
1180         debug("[sendMediaPlayer] called");
1181         doRequest( URL.mediaplayercmd+command );
1182 }
1183
1184
1185 function incomingMediaPlayer(request){
1186         if(request.readyState == 4){
1187                 var files = new FileList(getXML(request)).getArray();
1188
1189                 debug("[loadMediaPlayer] Got "+files.length+" entries in mediaplayer filelist");
1190                 // listerHtml = tplMediaPlayerHeader;
1191
1192                 var namespace = {};
1193
1194                 var root = files[0].getRoot();
1195                 if (root != "playlist") {
1196                         namespace = {'root': root};
1197                         if(root != '/') {
1198                                 var re = new RegExp(/(.*)\/(.*)\/$/);
1199                                 re.exec(root);
1200                                 var newroot = RegExp.$1+'/';
1201                                 if(newroot == '//') {
1202                                         newroot = '/';
1203                                 }
1204                                 namespace = {
1205                                                 'root': root,
1206                                                 'servicereference': newroot,
1207                                                 'exec': 'loadMediaPlayer',
1208                                                 'exec_description': 'Change to directory ../',
1209                                                 'color': '000000',
1210                                                 'newroot': newroot,
1211                                                 'name': '..'
1212                                 };      
1213                         }
1214                 }
1215
1216                 var itemnamespace = Array();
1217                 for ( var i = 0; i <files.length; i++){
1218                         var file = files[i];
1219                         if(file.getNameOnly() == '') {
1220                                 continue;
1221                         }
1222                         var exec = 'loadMediaPlayer';
1223                         var exec_description = 'Change to directory' + file.getServiceReference();
1224                         var color = '000000';                   
1225                         var isdir = 'true';
1226
1227                         if (file.getIsDirectory() == "False") {
1228                                 exec = 'playFile';
1229                                 exec_description = 'play file';
1230                                 color = '00BCBC';
1231                                 isdir = 'false';
1232                         }
1233
1234                         itemnamespace[i] = {
1235                                         'isdir' : isdir,
1236                                         'servicereference': file.getServiceReference(),
1237                                         'exec': exec,
1238                                         'exec_description': exec_description,
1239                                         'color': color,                                                 
1240                                         'root': file.getRoot(),
1241                                         'name': file.getNameOnly()
1242                         };
1243
1244                 }
1245                 /*
1246                 if (root == "playlist") {
1247                         listerHtml += tplMediaPlayerFooterPlaylist;
1248                 }
1249                  */
1250
1251                 var data = { mp : namespace,
1252                                 items: itemnamespace
1253                 };
1254
1255                 processTpl('tplMediaPlayer', data, 'contentMain');
1256                 var sendMediaPlayerTMP = sendMediaPlayer;
1257                 sendMediaPlayer = false;
1258                 // setBodyMainContent('BodyContent');
1259                 sendMediaPlayer = sendMediaPlayerTMP;
1260         }               
1261 }
1262
1263
1264 function loadMediaPlayer(directory){
1265         debug("[loadMediaPlayer] called");
1266         if(typeof(directory) == 'undefined') directory = 'Filesystems';
1267         doRequest(URL.mediaplayerlist+directory, incomingMediaPlayer, false);
1268 }
1269
1270
1271 function playFile(file,root) {
1272         debug("[playFile] called");
1273         mediaPlayerStarted = true;
1274         doRequest( URL.mediaplayerplay+file+"&root="+root );
1275 }
1276
1277
1278 function deleteFile(sref) {
1279         debug("[deleteFile] called");
1280         mediaPlayerStarted = true;
1281         doRequest( URL.mediaplayerremove+sref );
1282 }
1283
1284
1285 function openMediaPlayerPlaylist() {
1286         debug("[openMediaPlayerPlaylist] called");
1287         doRequest(URL.mediaplayerlist+"playlist", incomingMediaPlayer, false);
1288 }
1289
1290
1291 function writePlaylist() {
1292         debug("[writePlaylist] called");
1293         var filename = '';
1294         filename = prompt("Please enter a name for the playlist", "");
1295
1296         if(filename !== "") {
1297                 doRequest( URL.mediaplayerwrite+filename );
1298         }
1299 }
1300
1301
1302 //Powerstate
1303 /*
1304  * Sets the Powerstate @param newState - the new Powerstate Possible Values
1305  * (also see WebComponents/Sources/PowerState.py) #-1: get current state # 0:
1306  * toggle standby # 1: poweroff/deepstandby # 2: rebootdreambox # 3:
1307  * rebootenigma
1308  */
1309 function sendPowerState(newState){
1310         doRequest( URL.powerstate+'?newstate='+newState, incomingPowerState);
1311 }
1312
1313
1314 //Currently Running Service
1315 function incomingCurrent(request){
1316         //      debug("[incomingCurrent called]");
1317         if(request.readyState == 4){
1318                 try{
1319                         var xml = getXML(request).getElementsByTagName("e2currentserviceinformation").item(0);
1320                         
1321                         var duration = parseInt( (xml.getElementsByTagName('e2eventduration').item(0).firstChild.data / 60), 10 );
1322                         var remaining = parseInt( (xml.getElementsByTagName('e2eventremaining').item(0).firstChild.data / 60), 10 );
1323
1324                         namespace = {
1325                                         "servicereference" : encodeURIComponent(xml.getElementsByTagName('e2servicereference').item(0).firstChild.data),
1326                                         "servicename" : xml.getElementsByTagName('e2servicename').item(0).firstChild.data,
1327                                         "eventname" : xml.getElementsByTagName('e2eventname').item(0).firstChild.data,
1328                                         "remaining" : remaining,
1329                                         "duration" : duration
1330                         };
1331
1332                         var data = { current : namespace };
1333
1334                         if(typeof(templates.tplCurrent) != "undefined"){
1335                                 renderTpl(templates.tplCurrent, data, "currentContent");
1336                         } else {
1337                                 debug("[incomingCurrent] tplCurrent N/A");
1338                         }
1339
1340                 } catch (e){}
1341                 isActive.getCurrent = false;
1342         }
1343 }
1344
1345
1346 function getCurrent(){
1347         if(!isActive.getCurrent){
1348                 isActive.getCurrent = true;
1349                 doRequest(URL.getcurrent, incomingCurrent, false);
1350         }
1351 }
1352
1353
1354 //Navigation and Content Helper Functions
1355
1356 /*
1357  * Loads all Bouquets for the given enigma2 servicereference and sets the
1358  * according contentHeader @param sRef - the Servicereference for the bouquet to
1359  * load
1360  */
1361 function getBouquets(sRef){     
1362         var url = URL.getservices+encodeURIComponent(sRef);
1363         doRequest(url, incomingBouquetList, true);
1364 }
1365
1366 /*
1367  * Loads another navigation template and sets the navigation header
1368  * @param template - The name of the template
1369  * @param title - The title to set for the navigation
1370  */
1371 function reloadNav(template, title){
1372         setAjaxLoad('navContent');
1373         processTpl(template, null, 'navContent');
1374         setNavHd(title);
1375 }
1376
1377 function reloadNavDynamic(fnc, title){
1378         setAjaxLoad('navContent');
1379         setNavHd(title);
1380         fnc();
1381 }
1382
1383 function getBouquetsTv(){
1384         getBouquets(bouquetsTv);
1385 }
1386
1387 function getProviderTv(){
1388         getBouquets(providerTv);
1389 }
1390
1391 function getSatellitesTv(){
1392         getBouquets(satellitesTv);
1393 }
1394
1395 function getAllTv(){
1396         loadBouquet(allTv, "All (TV)");
1397 }
1398
1399
1400 function getBouquetsRadio(){
1401         getBouquets(bouquetsRadio);
1402 }
1403
1404 function getProviderRadio(){
1405         getBouquets(providerRadio);
1406 }
1407
1408 function getSatellitesRadio(){
1409         getBouquets(satellitesRadio);
1410 }
1411
1412 function getAllRadio(){
1413         loadBouquet(allRadio, "All (Radio)");
1414 }
1415
1416
1417
1418 /*
1419  * Loads dynamic content to $(contentMain) by calling a execution function
1420  * @param fnc - The function used to load the content
1421  * @param title - The Title to set on the contentpanel
1422  */
1423 function loadContentDynamic(fnc, title){
1424         setAjaxLoad('contentMain');
1425         setContentHd(title);
1426         stopUpdateBouquetItemsPoller();
1427
1428         fnc();
1429 }
1430
1431 /*
1432  * like loadContentDynamic but without the AjaxLoaderAnimation being shown
1433  */
1434 function reloadContentDynamic(fnc, title){
1435         setContentHd(title);
1436         fnc();
1437 }
1438
1439 /*
1440  * Loads a static template to $(contentMain)
1441  * @param template - Name of the Template
1442  * @param title - The Title to set on the Content-Panel
1443  */
1444 function loadContentStatic(template, title){
1445         setAjaxLoad('contentMain');
1446         setContentHd(title);
1447         stopUpdateBouquetItemsPoller();
1448         processTpl(template, null, 'contentMain');
1449 }
1450
1451
1452 /*
1453  * Opens the given Control
1454  * @param control - Control Page as String
1455  * Possible Values: power, extras, message, screenshot, videoshot, osdshot
1456  */
1457 function loadControl(control){
1458         switch(control){
1459         case "power":
1460                 loadContentStatic('tplPower', 'PowerControl');
1461                 break;
1462
1463         case "message":
1464                 loadContentStatic('tplSendMessage', 'Send a Message');
1465                 break;
1466
1467         case "remote":
1468                 loadAndOpenWebRemote();
1469                 break;
1470
1471         case "screenshot":
1472                 loadContentDynamic(getScreenShot, 'Screenshot');
1473                 break;
1474
1475         case "videoshot":
1476                 loadContentDynamic(getVideoShot, 'Videoshot');
1477                 break;
1478
1479         case "osdshot":
1480                 loadContentDynamic(getOsdShot, 'OSDshot');
1481                 break;
1482
1483         default:
1484                 break;
1485         }
1486 }
1487
1488
1489 function loadDeviceInfo(){
1490         loadContentDynamic(showDeviceInfo, 'Device Information');
1491 }
1492
1493 function loadAbout(){
1494         loadContentStatic('tplAbout', 'About');
1495 }
1496
1497 function loadGearsInfo(){
1498         loadContentDynamic(showGears, 'Google Gears');
1499 }
1500
1501 function reloadGearsInfo(){
1502         loadContentDynamic(showGears, 'Google Gears');
1503 }
1504
1505
1506 /*
1507  * Switches Navigation Modes
1508  * @param mode - The Navigation Mode you want to switch to
1509  * Possible Values: TV, Radio, Movies, Timer, Extras
1510  */
1511 function switchMode(mode){
1512         switch(mode){
1513         case "TV":
1514                 reloadNav('tplNavTv', 'TeleVision');
1515                 break;
1516
1517         case "Radio":
1518                 reloadNav('tplNavRadio', 'Radio');
1519                 break;
1520
1521         case "Movies":
1522                 //The Navigation
1523                 reloadNavDynamic(loadMovieNav, 'Movies');
1524
1525                 // The Movie list
1526                 loadContentDynamic(loadMovieList, 'Movies');
1527                 break;
1528
1529         case "Timer":
1530                 //The Navigation
1531                 reloadNav('tplNavTimer', 'Timer');
1532
1533                 // The Timerlist
1534                 loadContentDynamic(loadTimerList, 'Timer');
1535                 break;
1536
1537         case "MediaPlayer":
1538                 loadContentDynamic(loadMediaPlayer, 'MediaPlayer');
1539                 break;
1540
1541         case "BoxControl":
1542                 reloadNav('tplNavBoxControl', 'BoxControl');
1543                 break;
1544
1545         case "Extras":
1546                 reloadNav('tplNavExtras', 'Extras');
1547                 break;
1548                 
1549         default:
1550                 break;
1551         }
1552 }
1553
1554 function openWebTV(){
1555         window.open('/web-data/streaminterface.html', 'WebTV', 'scrollbars=no, width=800, height=730');
1556 }
1557
1558
1559
1560 function updateItems(){
1561         getCurrent();
1562         getPowerState();
1563 }
1564
1565 function updateItemsLazy(bouquet){
1566         getSubServices();
1567         getBouquetEpg();
1568 }
1569
1570 /*
1571  * Does the everything required on initial pageload
1572  */
1573
1574 function init(){
1575         if(DBG){
1576                 openDebug();
1577         }
1578
1579         if (typeof document.body.style.maxHeight == "undefined") {
1580                 alert("Due to the tremendous amount of work needed to get everthing to " +
1581                 "work properly, there is (for now) no support for Internet Explorer Versions below 7");
1582         }
1583
1584         getBoxtype();
1585
1586         setAjaxLoad('navContent');
1587         setAjaxLoad('contentMain');
1588
1589         fetchTpl('tplServiceListEPGItem');
1590         fetchTpl('tplCurrent'); 
1591         reloadNav('tplNavTv', 'TeleVision');
1592
1593         initChannelList();
1594         initVolumePanel();
1595         initMovieList();
1596
1597         updateItems();
1598         startUpdateCurrentPoller();
1599 }