]> git.vomp.tv Git - vompclient.git/blob - control.cc
Remove deprecated max() function
[vompclient.git] / control.cc
1 /*
2     Copyright 2004-2020 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 // FIXME rename to Control and move stuff from main to here
21
22 #ifndef WIN32
23 #include <unistd.h> // for reboot
24 #include <linux/reboot.h>
25 #include <sys/reboot.h>
26 #endif
27
28 #include <time.h>
29
30 #ifdef WIN32
31 #include "inputwin.h"
32 #endif
33
34 #ifdef __ANDROID__
35 #include "inputandroid.h"
36 #endif
37
38 #include "led.h"
39 #include "video.h"
40 #include "audio.h"
41 #include "vdr.h"
42 #include "vvolume.h"
43 #include "vserverselect.h"
44 #include "vwelcome.h"
45 #include "vmute.h"
46 #include "colour.h"
47 #include "osd.h"
48 #include "i18n.h"
49 #include "timers.h"
50 #include "wol.h"
51 #include "vconnect.h"
52 #include "message.h"
53 #include "inputman.h"
54 #include "input.h"
55 #include "vinfo.h"
56 #include "boxx.h"
57 #include "boxstack.h"
58 #include "log.h"
59 #include "sleeptimer.h"
60 #include "wjpeg.h"
61 #include "osdvector.h"
62
63
64 #ifdef VOMP_PLATFORM_RASPBERRY
65   #include "ledraspberry.h"
66   #include "osdopenvg.h"
67   #include "videoomx.h"
68   #include "audioomx.h"
69 #endif
70
71 #ifdef WIN32
72   #include "windowsosd.h"
73   #ifdef WINDOWS_LEGACY
74     #include "osdwinpixel.h"
75   #else
76     #include "osdwinvector.h"
77   #endif
78
79   #include "ledwin.h"
80   #include "videowin.h"
81   #include "audiowin.h"
82 #endif
83
84 #include "control.h"
85
86 static const char* TAG = "Control";
87
88 Control* Control::instance = NULL;
89
90 Control::Control()
91 {
92   if (instance) return;
93   instance = this;
94 }
95
96 Control::~Control()
97 {
98   flushMessageQueue();
99   instance = NULL;
100 }
101
102 Control* Control::getInstance()
103 {
104   return instance;
105 }
106
107 bool Control::init(bool tcrashed)
108 {
109   if (initted) return false;
110   crashed = tcrashed;
111   logger = LogNT::getInstance();
112
113   SkinFactory::InitSkin(0);
114
115   try
116   {
117     led = new Led_TYPE();                     if (!led) throw 10;
118     if (!led->init(-1))                       throw 11;  // FIXME init(0) on Win32
119
120     timers = new Timers();                    if (!timers) throw 20;
121     if (!timers->init())                      throw 21;
122
123     video = new Video_TYPE();                 if (!video) throw 30;
124     if (!video->init(Video::PAL))             throw 31;
125
126     audio = new Audio_TYPE();                 if (!audio) throw 40;
127     if (!audio->init(Audio::MPEG2_PES))       throw 41;
128
129     osd = new Osd_TYPE();                     if (!osd) throw 50;
130     if (!osd->init())                         throw 51;
131
132     vdr = new VDR();                          if (!vdr) throw 60;
133     if (!vdr->init())                         throw 61;
134
135     boxstack = new BoxStack();                if (!boxstack) throw 70;
136     if (!boxstack->init())                    throw 71;
137
138     sleepTimer = new SleepTimer();            if (!sleepTimer) throw 80;
139
140     wol = new Wol();                          if (!wol) throw 90;
141
142     inputMan = new InputMan();                if (!inputMan) throw 100;
143     if (!inputMan->init())                    throw 101;
144
145   }
146   catch (int e)
147   {
148     if      (e == 10) logger->crit(TAG, "LED module failed to create");
149     else if (e == 11) logger->crit(TAG, "LED module failed to initialise");
150     else if (e == 20) logger->crit(TAG, "Timers module failed to create");
151     else if (e == 21) logger->crit(TAG, "Timers module failed to initialise");
152     else if (e == 30) logger->crit(TAG, "Video module failed to create");
153     else if (e == 31) logger->crit(TAG, "Video module failed to initialise");
154     else if (e == 40) logger->crit(TAG, "Audio module failed to create");
155     else if (e == 41) logger->crit(TAG, "Audio module failed to initialise");
156     else if (e == 50) logger->crit(TAG, "OSD module failed to create");
157     else if (e == 51) logger->crit(TAG, "OSD module failed to initialise");
158     else if (e == 60) logger->crit(TAG, "VDR module failed to create");
159     else if (e == 61) logger->crit(TAG, "VDR module failed to initialise");
160     else if (e == 70) logger->crit(TAG, "BoxStack module failed to create");
161     else if (e == 71) logger->crit(TAG, "BoxStack module failed to initialise");
162     else if (e == 80) logger->crit(TAG, "SleepTimer module failed to create");
163     else if (e == 90) logger->crit(TAG, "WOL module failed to create");
164     else if (e == 100) logger->crit(TAG, "InputMan module failed to create");
165     else if (e == 101) logger->crit(TAG, "InputMan module failed to initialise");
166
167     switch(e)
168     {
169       case 101:
170         delete inputMan;
171         inputMan = NULL;
172         FALLTHROUGH
173       case 100:
174         delete wol;
175         wol = NULL;
176         FALLTHROUGH
177       case 90:
178         delete sleepTimer;
179         sleepTimer = NULL;
180         FALLTHROUGH
181       case 80:
182         boxstack->shutdown();
183         FALLTHROUGH
184       case 71:
185         delete boxstack;
186         boxstack = NULL;
187         FALLTHROUGH
188       case 70:
189         vdr->shutdown();
190         FALLTHROUGH
191       case 61:
192         delete vdr;
193         vdr = NULL;
194         FALLTHROUGH
195       case 60:
196         osd->shutdown();
197         FALLTHROUGH
198       case 51:
199         delete osd;
200         osd = NULL;
201         FALLTHROUGH
202       case 50:
203         audio->shutdown();
204         FALLTHROUGH
205       case 41:
206         delete audio;
207         audio = NULL;
208         FALLTHROUGH
209       case 40:
210         video->shutdown();
211         FALLTHROUGH
212       case 31:
213         delete video;
214         video = NULL;
215         FALLTHROUGH
216       case 30:
217         timers->shutdown();
218         FALLTHROUGH
219       case 21:
220         delete timers;
221         timers = NULL;
222         FALLTHROUGH
223       case 20:
224         led->shutdown();
225         FALLTHROUGH
226       case 11:
227         delete led;
228         led = NULL;
229         FALLTHROUGH
230       case 10:
231         FALLTHROUGH
232         ;
233     }
234
235     return false;
236   }
237
238   initted = true;
239   return true;
240 }
241
242 void Control::shutdown()
243 {
244   if (!initted) return;
245   initted = false;
246
247   if (inputMan)
248   {
249     inputMan->shutdown();
250     delete inputMan;
251     inputMan = NULL;
252     logger->info(TAG, "InputMan module shut down");
253   }
254
255   if (wol)
256   {
257     delete wol;
258     logger->info(TAG, "WOL module shut down");
259   }
260
261   if (sleepTimer)
262   {
263     delete sleepTimer;
264     sleepTimer = NULL;
265     logger->info(TAG, "SleepTimer module shut down");
266   }
267
268   if (boxstack)
269   {
270     boxstack->shutdown();
271     delete boxstack;
272     boxstack = NULL;
273     logger->info(TAG, "BoxStack module shut down");
274   }
275
276   if (vdr)
277   {
278     vdr->shutdown();
279     delete vdr;
280     vdr = NULL;
281     logger->info(TAG, "VDR module shut down");
282   }
283
284   if (osd)
285   {
286     osd->shutdown();
287     delete osd;
288     osd = NULL;
289     logger->info(TAG, "OSD module shut down");
290   }
291
292   if (audio)
293   {
294     audio->shutdown();
295     delete audio;
296     audio = NULL;
297     logger->info(TAG, "Audio module shut down");
298   }
299
300   if (video)
301   {
302     video->shutdown();
303     delete video;
304     video = NULL;
305     logger->info(TAG, "Video module shut down");
306   }
307
308   if (timers)
309   {
310     timers->shutdown();
311     delete timers;
312     timers = NULL;
313     logger->info(TAG, "Timers module shut down");
314   }
315
316   if (led)
317   {
318     led->shutdown();
319     delete led;
320     led = NULL;
321     logger->info(TAG, "LED module shut down");
322   }
323 }
324
325 void Control::stop()
326 {
327   logger->info(TAG, "Request stop");
328
329   Message* m = new Message(); // break master loop
330   m->message = Message::SHUTDOWN;
331   m->p_to = Message::CONTROL;
332   postMessage(m);
333 }
334
335 void Control::doWallpaper()
336 {
337   // Blue background
338   Boxx* bbg = new Boxx();
339   bbg->setSize(video->getScreenWidth(), video->getScreenHeight());
340   bbg->createBuffer();
341   bbg->fillColour(DrawStyle::WALLPAPER);
342   boxstack->add(bbg);
343   boxstack->update(bbg);
344   boxstack->remove(bbg);
345
346   // Wallpaper
347   wallpaper = new Boxx();
348   wallpaper->setSize(video->getScreenWidth(), video->getScreenHeight());
349   wallpaper->createBuffer();
350   wallpaper->setBackgroundColour(DrawStyle::WALLPAPER);
351
352   wallpaper_pict = new WJpegTYPE();
353   wallpaper_pict->setSize(video->getScreenWidth(), video->getScreenHeight());
354
355   if (video->getFormat() == Video::PAL)
356   {
357     logger->debug(TAG, "PAL wallpaper selected");
358 #ifndef _MIPS_ARCH    
359     wallpaper_pict->init("/wallpaperPAL.jpg");
360 #else
361     wallpaper_pict->init("wallpaperPAL.jpg");
362 #endif
363   }
364   else
365   {
366     logger->debug(TAG, "NTSC wallpaper selected");
367     wallpaper_pict->init("/wallpaperNTSC.jpg");
368   }
369
370   if (DrawStyle::WALLPAPER.alpha)
371     wallpaper_pict->setVisible(true);
372   else
373     wallpaper_pict->setVisible(false);
374
375   wallpaper->add(wallpaper_pict);
376   wallpaper->draw();
377
378   boxstack->add(wallpaper);
379   boxstack->update(wallpaper);
380
381   OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
382   if (osdv) osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
383 }
384
385 void Control::run()
386 {
387   if (!initted) return;
388
389   // just in case
390   Video::getInstance()->signalOn();
391   Led::getInstance()->on();
392
393   doWallpaper();
394
395   if (crashed)
396   {
397     buildCrashedBox();
398   }
399   else
400   {
401     VConnect* vconnect = new VConnect(); // Deleted when VConnect messages Control, and is boxstack->remove()'d
402     boxstack->add(vconnect);
403     vconnect->run();
404   }
405
406   inputMan->start();
407
408   messageLoopRun = true;
409   messageLoop();
410
411   inputMan->stop();
412
413   boxstack->removeAllExceptWallpaper();
414   boxstack->remove(wallpaper);
415   delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
416 }
417
418 void Control::dispatchMessage(Message* m)
419 {
420   logger->debug(TAG, "processing message {}", m->message);
421
422   if (m->p_to == Message::CONTROL)
423   {
424     switch(m->message)
425     {
426       case Message::SHUTDOWN:
427       {
428         messageLoopRun = false;
429         break;
430       }
431       case Message::STOP_PLAYBACK:
432       {
433         handleCommand(Input::STOP); // an odd way of doing it, but so simple
434         break;
435       }
436       case Message::VDR_CONNECTED:
437       {
438         doJustConnected(static_cast<VConnect*>(m->from));
439         break;
440       }
441       case Message::SCREENSHOT:
442       {
443         logger->info(TAG, "Screenshot Message arrived");
444         Osd::getInstance()->screenShot("out.jpg");
445         break;
446       }
447       case Message::CONNECTION_LOST:
448       {
449         doFromTheTop(true);
450         break;
451       }
452       case Message::INPUT_EVENT:
453       {
454         logger->info(TAG, "INPUT_EVENT {}", m->parameter);
455
456         handleCommand(m->parameter);
457         break;
458       }
459       case Message::CHANGE_LANGUAGE:
460       {
461         boxstack->removeAllExceptWallpaper();
462         boxstack->update(wallpaper);
463         I18n::initialize();
464         if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
465         VWelcome* vw = new VWelcome();
466         vw->draw();
467         boxstack->add(vw);
468         boxstack->update(vw);
469         break;
470       }
471       case Message::LAST_VIEW_CLOSE:
472       {
473         // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
474         if (crashed)
475         {
476           crashed = false;
477           doFromTheTop(false);        
478         }
479       
480 //        VWelcome* vw = new VWelcome();
481 //        vw->draw();
482 //        boxstack->add(vw);
483 //        boxstack->update(vw);
484
485         break;
486       }
487     }
488   }
489   else if (m->p_to == Message::BOXSTACK)
490   {
491     boxstack->processMessage(m);
492   }
493   else if (m->p_to == Message::MOUSE_RECEIVER)
494   {
495     logger->debug(TAG, "Sending mouse message to boxstack for dispatch");
496     boxstack->processMessage(m);
497   }
498
499   else
500   {
501     m->to->processMessage(m);
502   }
503
504   logger->debug(TAG, "done processing message {}", m->message);
505 }
506
507 void Control::handleCommand(int button)
508 {
509   if (isStandby && (button != Input::POWER)
510                 && (button != Input::POWERON)
511                 && (button != Input::POWEROFF))  return;
512
513   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
514
515   // command was not handled
516
517   switch(button)
518   {
519     case Input::VOLUMEUP:
520     case Input::VOLUMEDOWN:
521     {
522       if (inputMan->handlesVolume()) // CEC volume handler?
523       {
524         if (button == Input::VOLUMEDOWN)
525           inputMan->volumeDown();
526         else
527           inputMan->volumeUp();
528       }
529       else
530       {
531         VVolume* v = new VVolume();
532         boxstack->add(v);
533         v->handleCommand(button); // this will draw+show
534       }
535       return;
536     }
537     case Input::MUTE:
538     {
539       if (inputMan->handlesVolume())
540       {
541         inputMan->volumeMute();
542       }
543       else
544       {
545         VMute* v = new VMute();
546         v->draw();
547         boxstack->add(v);
548         boxstack->update(v);
549       }
550       return;
551     }
552     case Input::POWER:
553     {
554       doStandby();
555       return;
556     }
557     case Input::POWERON:
558     {
559       doPowerOn();
560       return;
561     }
562     case Input::POWEROFF:
563     {
564       doPowerOff();
565       return;
566     }
567     case Input::OK:
568     {
569       // FIXME
570       if (!connLost) return; // if connLost, handle Input::OK
571       doFromTheTop(false);
572       return;
573     }
574     case Input::GO:
575     {
576       logger->debug(TAG, "Handling sleeptimer go");
577       sleepTimer->go();
578       return;
579     }
580   }
581 }
582
583 /*
584 void Control::sig1()
585 {
586 #ifdef DEV
587   Message* m = new Message(); // break into master mutex
588   m->message = Message::SCREENSHOT;
589   m->p_to = Message::CONTROL;
590   postMessage(m);
591 #endif
592 }
593 */
594
595 void Control::doStandby()
596 {
597   if (isStandby)
598   {
599     doPowerOn();
600   }
601   else
602   {
603     doPowerOff();
604   }
605 }
606
607
608 void Control::doPowerOn()
609 {
610   if (isStandby)
611   {
612     Video::getInstance()->signalOn();
613     Led::getInstance()->on();
614     InputMan::getInstance()->changePowerState(true);
615     isStandby = false;
616
617     VConnect* vconnect = new VConnect();
618     boxstack->add(vconnect);
619     vconnect->run();
620   }
621 }
622
623 void Control::doPowerOff()
624 {
625   if (!isStandby)
626   {
627     VDR::getInstance()->shutdownVDR();
628     boxstack->removeAllExceptWallpaper();
629     Video::getInstance()->signalOff();
630     boxstack->update(wallpaper);
631
632     VDR::getInstance()->configSave("General", "Last Power State", "Off");
633     logger->unsetExternLogger();
634     VDR::getInstance()->disconnect();
635     Led::getInstance()->off();
636     InputMan::getInstance()->changePowerState(false);
637     isStandby = true;
638     sleepTimer->shutdown();
639   }
640 }
641
642 void Control::doFromTheTop(bool which)
643 {
644   if (isStandby) return;
645   if (which)
646   {
647     if (connLost)
648     {
649       logger->info(TAG, "Connection lost dialog already present");
650       return;
651     }
652   
653     logger->info(TAG, "Doing connection lost dialog");
654     connLost = new VInfo();
655     connLost->setSize(360, 200);
656     connLost->createBuffer();
657     if (Video::getInstance()->getFormat() == Video::PAL)
658       connLost->setPosition(190, 170);
659     else
660       connLost->setPosition(180, 120);
661     connLost->setOneLiner(tr("Connection lost"));
662     connLost->setDropThrough();
663     connLost->setBorderOn(1);
664     connLost->setTitleBarColour(DrawStyle::DANGER);
665     connLost->okButton();
666     connLost->draw();
667     boxstack->add(connLost);
668     boxstack->update(connLost);
669
670     clearMQInputEvents();
671   }
672   else
673   {
674     logger->unsetExternLogger();
675     VDR::getInstance()->disconnect();
676     boxstack->removeAllExceptWallpaper();
677     boxstack->update(wallpaper);
678     connLost = NULL;
679     
680     flushMessageQueue();
681     
682     // at this point, everything should be reset to first-go
683     
684     VConnect* vconnect = new VConnect(); // deleted eventually in boxstack
685     boxstack->add(vconnect);
686     vconnect->run();
687   }
688 }
689
690 void Control::clearMQInputEvents()
691 {
692   std::lock_guard<std::mutex> lg(messageQueueMutex); // Get the lock
693
694   MQueueI i = messages.begin();
695   while(i != messages.end())
696   {
697     Message* m = *i;
698     if (m->message == Message::INPUT_EVENT)
699     {
700       delete m;
701       i = messages.erase(i);
702     }
703     else
704     {
705       ++i;
706     }
707   }
708 }
709
710 void Control::doReboot()
711 {
712
713   logger->unsetExternLogger();
714   VDR::getInstance()->disconnect();
715   // just kill it...
716   logger->info(TAG, "Reboot");
717 #ifndef WIN32
718 #ifndef VOMP_HAS_EXIT
719   // some plattforms, want a proper deinitialisation of their hardware before reboot
720   Osd::getInstance()->shutdown();
721   Audio::getInstance()->shutdown();
722   Video::getInstance()->shutdown();
723   InputMan::getInstance()->shutdown();
724
725   reboot(LINUX_REBOOT_CMD_RESTART);
726   // if  reboot is not allowed -> stop
727   stop();
728
729
730 #else
731   stop();
732
733 #ifdef __ANDROID__
734   exit(0);
735 #endif
736
737 #endif
738 #endif //Would we support this on windows?
739 }
740
741 void Control::connectionLost()
742 {
743   logger->unsetExternLogger();
744   Message* m = new Message(); // break into master mutex
745   m->message = Message::CONNECTION_LOST;
746   m->p_to = Message::CONTROL;
747   postMessage(m);
748 }
749
750 void Control::buildCrashedBox()
751 {
752   VInfo* crash = new VInfo();
753   crash->setSize(360, 250);
754   crash->createBuffer();
755   if (Video::getInstance()->getFormat() == Video::PAL)
756     crash->setPosition(190, 146);
757   else
758     crash->setPosition(180, 96);
759   crash->setMainText("Oops, vomp crashed.. :(\nPlease report this crash to the author, with as much detail as possible about what you were doing at the time that might have caused the crash.");
760   crash->setBorderOn(1);
761   crash->setTitleBarColour(DrawStyle::DANGER);
762   crash->okButton();
763   crash->setExitable();
764   crash->draw();
765   boxstack->add(crash);
766   boxstack->update(crash);
767 }
768
769 int Control::getLangPref(bool subtitle, const char* langcode)
770 {
771   std::vector<struct ASLPref>::iterator itty=langcodes.begin();
772   char templangcode[4];
773   templangcode[0] = langcode[0];
774   templangcode[1] = langcode[1];
775   templangcode[2] = langcode[2];
776   templangcode[3] = '\0';
777   int langpos = 0;
778   while (itty != langcodes.end())
779   {
780     size_t pos = (*itty).langcode.find(templangcode);
781     if (pos != std::string::npos)
782     {
783       //vector<struct ASLPref>::iterator itty2=langcodes.begin();
784       for (unsigned int i = 0; i < langcodes.size(); i++)
785       {
786         int pref = 0;
787         if (subtitle)
788           pref = langcodes[i].subtitlepref;
789         else
790           pref = langcodes[i].audiopref;
791         if (pref < 0) break;
792
793         if (subtitle)
794         {
795           if (langcodes[i].subtitlepref==langpos) return i;
796         }
797         else
798         {
799           if (langcodes[i].audiopref==langpos) return i;
800         }
801       }
802       break;
803     }
804     itty++;
805     langpos++;
806   }
807   return langcodes.size(); //neutral
808 }
809
810 void Control::doJustConnected(VConnect* vconnect)
811 {
812   I18n::initialize();
813   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
814   logger->info(TAG, "Entering doJustConnected");
815   
816   boxstack->remove(vconnect);
817
818   VInfo* vi = new VInfo();
819   vi->setSize(400, 200);
820   vi->createBuffer();
821   if (video->getFormat() == Video::PAL)
822     vi->setPosition(170, 200);
823   else
824     vi->setPosition(160, 150);
825   vi->setOneLiner(tr("Connected, loading config"));
826   vi->draw();
827   boxstack->add(vi);
828   boxstack->update(vi);
829
830   // FIXME make config system
831
832   char* config;
833
834   // See if we're supposed to do network logging
835   config = vdr->configLoad("Advanced", "Network logging");
836   if (config && !STRCASECMP(config, "On"))
837   {
838     logger->info(TAG, "Turning on network logging");
839     logger->setExternLogger(vdr);
840   }  
841   else
842   {
843           logger->unsetExternLogger();
844     logger->info(TAG, "Turned off network logging");
845   }
846   if (config) delete[] config;
847
848   config = vdr->configLoad("Advanced", "Skin Name");
849   if (config)
850   {
851     const char **skinnames=SkinFactory::getSkinNames();
852     for (int i=0;i<SkinFactory::getNumberofSkins();i++)
853     {
854       if (!STRCASECMP(config, skinnames[i]))
855       {
856         SkinFactory::InitSkin(i);
857         break;
858       }
859     }
860     delete[] config;
861
862     if (wallpaper && wallpaper_pict)
863     {
864       if (DrawStyle::WALLPAPER.alpha)
865         wallpaper_pict->setVisible(true);
866       else
867         wallpaper_pict->setVisible(false);
868
869       wallpaper->draw();
870       boxstack->update(wallpaper);
871     }
872   }
873   else
874   {
875     SkinFactory::InitSkin(0);
876   }
877
878   // See if config says to override video format (PAL/NTSC)
879   config = vdr->configLoad("General", "Override Video Format");
880   if (config)
881   {
882     logger->debug(TAG, "Override Video Format is present");
883
884     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
885         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
886         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
887         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
888         )
889     {
890       // Oh sheesh, need to switch format. Bye bye TV...
891
892       // Take everything down
893       boxstack->removeAllExceptWallpaper();
894       boxstack->remove(wallpaper);
895       delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
896
897 #ifndef __ANDROID__
898       osd->shutdown();
899 #endif
900       video->shutdown();
901
902       inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
903       inputMan->init(); // FIXME this breaks badly now
904
905       // Get video and osd back up with the new mode
906       if (!strcmp(config, "PAL"))
907       {
908         logger->debug(TAG, "Switching to PAL");
909         video->init(Video::PAL);
910       }
911       else if (!strcmp(config, "NTSC"))
912       {
913         logger->debug(TAG, "Switching to NTSC");
914         video->init(Video::NTSC);
915       } else if (!strcmp(config, "PAL_M"))
916       {
917         logger->debug(TAG, "Switching to PAL_M");
918         video->init(Video::PAL_M);
919       } else if (!strcmp(config, "NTSC_J"))
920       {
921         logger->debug(TAG, "Switching to NTSC_J");
922         video->init(Video::NTSC_J);
923       }
924       delete[] config;
925
926 #ifndef __ANDROID__
927       //we do not init twice
928       osd->init();
929 #endif
930
931       // Put the wallpaper back
932       doWallpaper();
933
934       // Re add the vinfo
935       vi = new VInfo();
936       vi->setSize(400, 200);
937       vi->createBuffer();
938       if (video->getFormat() == Video::PAL)
939         vi->setPosition(170, 200);
940       else
941         vi->setPosition(160, 150);
942
943       vi->setOneLiner(tr("Connected, loading config"));
944       vi->draw();
945       boxstack->add(vi);
946       boxstack->update(vi);
947     }
948     else
949     {
950       logger->debug(TAG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
951     }
952   }
953   else
954   {
955     logger->debug(TAG, "Phew, no dangerous on-the-fly mode switching to do!");
956   }
957
958   // Power off if first boot and config says so
959   if (firstBoot)
960   {
961     firstBoot = false;
962
963     logger->debug(TAG, "Load power after boot");
964
965     config = vdr->configLoad("General", "Power After Boot");
966
967     if (config)
968     {
969       if (!STRCASECMP(config, "On"))
970       {
971         logger->info(TAG, "Config says Power After Boot = On");
972       }
973       else if (!STRCASECMP(config, "Off"))
974       {
975         logger->info(TAG, "Config says Power After Boot = Off");
976         doStandby();
977         delete[] config;
978         return; // quit here
979       }
980       else if (!STRCASECMP(config, "Last state"))
981       {
982         char* lastPowerState = vdr->configLoad("General", "Last Power State");
983         if (lastPowerState)
984         {
985           if (!STRCASECMP(lastPowerState, "On"))
986           {
987             logger->info(TAG, "Config says Last Power State = On");
988           }
989           else if (!STRCASECMP(lastPowerState, "Off"))
990           {
991             logger->info(TAG, "Config says Last Power State = Off");
992             doStandby();
993             delete[] config;
994             return; // quit here
995           }
996           else
997           {
998             logger->info(TAG, "Config General/Last Power State not understood");
999           }
1000         }
1001         else
1002         {
1003           logger->info(TAG, "Config General/Last Power State not found");
1004         }
1005       }
1006       else
1007       {
1008         logger->info(TAG, "Config/Power After Boot not understood");
1009       }
1010       delete[] config;
1011     }
1012     else
1013     {
1014       logger->info(TAG, "Config General/Power After Boot not found");
1015     }
1016   }
1017
1018
1019   // Go S-Video if config says so
1020
1021   config = vdr->configLoad("TV", "Connection");
1022
1023   if (config)
1024   {
1025     if (!STRCASECMP(config, "S-Video"))
1026     {
1027       logger->info(TAG, "Switching to S-Video as Connection={}", config);
1028       video->setConnection(Video::SVIDEO);
1029     } else  if (!STRCASECMP(config, "HDMI"))
1030     {
1031       logger->info(TAG, "Switching to HDMI as Connection={}", config);
1032       video->setConnection(Video::HDMI);
1033     } else  if (!STRCASECMP(config, "HDMI3D"))
1034     {
1035       logger->info(TAG, "Switching to HDMI3D as Connection={}", config);
1036       video->setConnection(Video::HDMI3D);
1037     }
1038     else
1039     {
1040       logger->info(TAG, "Switching to RGB/Composite as Connection={}", config);
1041       video->setConnection(Video::COMPOSITERGB);
1042     }
1043     delete[] config;
1044   }
1045   else
1046   {
1047     logger->info(TAG, "Config TV/S-Video not found");
1048   }
1049
1050   // Set to shutdown VDR if config says
1051   
1052   config = vdr->configLoad("General", "VDR shutdown");
1053   if (config)
1054   {
1055     if (!STRCASECMP(config, "On"))
1056     {
1057       logger->info(TAG, "Shutdown VDR when shutting down vomp");
1058       vdr->setVDRShutdown(true);
1059     }
1060     else if (!STRCASECMP(config, "Off"))
1061     {
1062       logger->info(TAG, "Shutdown only vomp");
1063       vdr->setVDRShutdown(false);
1064     }
1065   }
1066   else
1067   {
1068     logger->info(TAG, "Default shutdown only vomp");
1069     vdr->setVDRShutdown(false); // Default
1070   }
1071           
1072   // Get TV aspect ratio
1073
1074   config = vdr->configLoad("TV", "Aspect");
1075   if (config)
1076   {
1077     if (!STRCASECMP(config, "16:9"))
1078     {
1079       logger->info(TAG, "/// Switching to TV aspect 16:9");
1080       video->setTVsize(Video::ASPECT16X9);
1081     }
1082     else
1083     {
1084       logger->info(TAG, "/// Switching to TV aspect 4:3");
1085       video->setTVsize(Video::ASPECT4X3);
1086     }
1087     delete[] config;
1088   }
1089   else
1090   {
1091     logger->info(TAG, "Config TV/Aspect type not found, going 4:3");
1092     video->setTVsize(Video::ASPECT4X3);
1093   }
1094
1095   config = vdr->configLoad("TV", "Widemode");
1096   if (config)
1097   {
1098     if (!STRCASECMP(config, "Letterbox"))
1099     {
1100       logger->info(TAG, "Setting letterbox mode");
1101       video->setMode(Video::LETTERBOX);
1102     }
1103     else
1104     {
1105       logger->info(TAG, "Setting chop-sides mode");
1106       video->setMode(Video::NORMAL);
1107     }
1108     delete[] config;
1109   }
1110   else
1111   {
1112 #ifdef __ANDROID__
1113          logger->info(TAG, "Config TV/Widemode not found, Setting letterbox mode");
1114          video->setMode(Video::LETTERBOX);
1115 #else
1116     logger->info(TAG, "Config TV/Widemode not found, Setting chop-sides mode");
1117     video->setMode(Video::NORMAL);
1118 #endif
1119   }
1120
1121   config = vdr->configLoad("Advanced", "TCP receive window");
1122   if (config)
1123   {
1124     size_t newTCPsize = atoi(config);
1125     delete[] config;
1126
1127     logger->info(TAG, "Setting TCP window size %i", newTCPsize);
1128     vdr->setReceiveWindow(newTCPsize);
1129   }
1130   else
1131   {
1132     logger->info(TAG, "TCP window size not found, setting 2048");
1133     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1134   }
1135
1136   config = vdr->configLoad("Advanced", "Font Name");
1137   if (config)
1138   {
1139         Osd::getInstance()->setFont(config);
1140     logger->info(TAG, "Setting Font to %s", config);
1141     delete[] config;
1142
1143   }
1144
1145
1146   // Set recording list type
1147
1148 #ifdef ADVANCED_MENUES
1149   config = vdr->configLoad("Advanced", "Menu type");
1150
1151   if (config)
1152   {
1153     if (!STRCASECMP(config, "Advanced"))
1154     {
1155       logger->info(TAG, "Switching to Advanced menu");
1156       advMenus = true;
1157     }
1158     else
1159     {
1160       logger->info(TAG, "Switching to Classic menu");
1161       advMenus = false;
1162     }
1163     delete[] config;
1164   }
1165   else
1166   {
1167     logger->info(TAG, "Config General/menu type not found");
1168     advMenus = true;
1169   }
1170 #endif
1171
1172   config = vdr->configLoad("Advanced", "Disable WOL");
1173   if (config)
1174   {
1175     if (!STRCASECMP(config, "Yes"))
1176     {
1177       logger->info(TAG, "Config says disable WOL");
1178       Wol::getInstance()->setEnabled(false);
1179     }
1180     else
1181     {
1182       logger->info(TAG, "Config says enable WOL");
1183       Wol::getInstance()->setEnabled(true);
1184     }
1185
1186     delete[] config;
1187   }
1188   else
1189   {
1190     logger->info(TAG, "By default, enable WOL");
1191     Wol::getInstance()->setEnabled(true);
1192   }
1193   /* device dependend config */
1194   audio->loadOptionsFromServer(vdr);
1195   video->loadOptionsFromServer(vdr);
1196   inputMan->loadOptionsFromServer(vdr);
1197
1198   video->executePendingModeChanges();
1199   // config done
1200
1201   // Save power state = on
1202
1203   vdr->configSave("General", "Last Power State", "On");
1204
1205   // Make sure connection didn't die
1206   if (!vdr->isConnected())
1207   {
1208     Control::getInstance()->connectionLost();
1209   }
1210   else
1211   {
1212     boxstack->remove(vi);
1213
1214     VWelcome* vw = new VWelcome();
1215     vw->draw();
1216     boxstack->add(vw);
1217     boxstack->update(vw);
1218
1219     // Enter pre-keys here
1220 //    handleCommand(Input::OK);
1221 //    handleCommand(Input::THREE);
1222 //    handleCommand(Input::SIX);
1223 //    handleCommand(Input::UP);
1224 //    handleCommand(Input::OK);
1225 //    handleCommand(Input::OK);
1226 //    handleCommand(Input::PLAY);
1227 //    handleCommand(Input::DOWN);
1228 //    handleCommand(Input::DOWN);
1229 //    handleCommand(Input::DOWN);
1230 //    handleCommand(Input::RIGHT);
1231 //    handleCommand(Input::RED);
1232   }
1233 }