]> git.vomp.tv Git - vompclient.git/blob - control.cc
Log conversion
[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   irun = true;
389
390   // just in case
391   Video::getInstance()->signalOn();
392   Led::getInstance()->on();
393
394   doWallpaper();
395
396   if (crashed)
397   {
398     buildCrashedBox();
399   }
400   else
401   {
402     VConnect* vconnect = new VConnect();
403     boxstack->add(vconnect);
404     vconnect->run();
405   }
406
407
408   // FIXME Input::NA_SIGNAL is possibly obsolete now
409
410   std::unique_lock<std::mutex> lockWrapper(messageQueueMutex);  // locks. unlocks on out-of-scope
411
412   inputMan->start();
413
414   while(irun)
415   {
416     messageQueueCond.wait(lockWrapper, [&] { return !irun || !messages.empty(); });
417     logger->debug(TAG, "woke");
418
419     if (!irun) break;
420
421     while(!messages.empty())
422     {
423       Message* m = messages.front();
424       messages.pop_front();
425
426       lockWrapper.unlock();
427
428       processMessage(m);
429       delete m;
430
431       lockWrapper.lock();
432     }
433   }
434
435   inputMan->stop();
436
437   boxstack->removeAllExceptWallpaper();
438   boxstack->remove(wallpaper);
439   delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
440 }
441
442 void Control::processMessage(Message* m)
443 {
444     // FIXME - a slight modification - how if messagereceivers were to register
445     // themselves as receivers to avoid the calling-a-deleted-object problem
446     // then only deliver/register/unregister would have to be protected
447
448   logger->debug(TAG, "processing message {}", m->message);
449
450
451   if ((m->p_to == Message::CONTROL) || (m->to == this)) // Maybe don't check m->to here? Always use predefined?
452   {
453     switch(m->message)
454     {
455       case Message::SHUTDOWN:
456       {
457         irun = false;
458         break;
459       }
460       // << FIXME OBSELETE
461       case Message::STOP_PLAYBACK:
462       {
463         handleCommand(Input::STOP); // an odd way of doing it, but so simple
464         break;
465       }
466       // Also connection_lost comes from player - anywhere else?
467       // FIXME OBSELETE >>
468
469
470       case Message::VDR_CONNECTED:
471       {
472         doJustConnected(static_cast<VConnect*>(m->from));
473         break;
474       }
475       case Message::SCREENSHOT:
476       {
477         logger->info(TAG, "Screenshot Message arrived");
478         Osd::getInstance()->screenShot("out.jpg");
479         break;
480       }
481       case Message::CONNECTION_LOST:
482       {
483         doFromTheTop(true);
484         break;
485       }
486       case Message::INPUT_EVENT:
487       {
488         logger->info(TAG, "INPUT_EVENT {}", m->parameter);
489
490         handleCommand(m->parameter);
491         break;
492       }
493       case Message::CHANGE_LANGUAGE:
494       {
495         boxstack->removeAllExceptWallpaper();
496         boxstack->update(wallpaper);
497         I18n::initialize();
498         if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
499         VWelcome* vw = new VWelcome();
500         vw->draw();
501         boxstack->add(vw);
502         boxstack->update(vw);
503         break;
504       }
505       case Message::LAST_VIEW_CLOSE:
506       {
507         // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
508         if (crashed)
509         {
510           crashed = false;
511           doFromTheTop(false);        
512         }
513       
514 //        VWelcome* vw = new VWelcome();
515 //        vw->draw();
516 //        boxstack->add(vw);
517 //        boxstack->update(vw);
518
519         break;
520       }
521       case Message::NEW_PICTURE:
522       {
523         //Log::getInstance()->log("Control", Log::DEBUG, "TVMedia NEW_PICTURE");
524         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
525         if (osdv) osdv->informPicture(m->tag, reinterpret_cast<ImageIndex>(m->data));
526         break;
527       }
528       case Message::NEW_PICTURE_STATIC:
529       {
530         //Log::getInstance()->log("Control", Log::DEBUG, "TVMedia NEW_PICTURE %x %x",m->tag,m->parameter);
531         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
532         if (osdv) osdv->informPicture(static_cast<unsigned long long>(m->tag) << 32LL, reinterpret_cast<ImageIndex>(m->data));
533         break;
534       }
535     }
536   }
537   else
538   {
539     /* FIXME
540     
541     Instead of sending through the boxstack, implement a more generic MessageReceiver interface
542     and have potential receivers register with something
543     When a message needs to be delivered, check if the receiver is still registered, if so, deliver the message
544     This could all be done using the existing big control mutex to keep it simple
545     */
546   
547     logger->debug(TAG, "Sending message to boxstack");
548     boxstack->processMessage(m);
549   }
550 }
551
552 void Control::handleCommand(int button)
553 {
554   if (isStandby && (button != Input::POWER)
555                 && (button != Input::POWERON)
556                 && (button != Input::POWEROFF))  return;
557
558   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
559
560   // command was not handled
561
562   switch(button)
563   {
564     case Input::VOLUMEUP:
565     case Input::VOLUMEDOWN:
566     {
567       if (inputMan->handlesVolume()) // CEC volume handler?
568       {
569         if (button == Input::VOLUMEDOWN)
570           inputMan->volumeDown();
571         else
572           inputMan->volumeUp();
573       }
574       else
575       {
576         VVolume* v = new VVolume();
577         boxstack->add(v);
578         v->handleCommand(button); // this will draw+show
579       }
580       return;
581     }
582     case Input::MUTE:
583     {
584       if (inputMan->handlesVolume())
585       {
586         inputMan->volumeMute();
587       }
588       else
589       {
590         VMute* v = new VMute();
591         v->draw();
592         boxstack->add(v);
593         boxstack->update(v);
594       }
595       return;
596     }
597     case Input::POWER:
598     {
599       doStandby();
600       return;
601     }
602     case Input::POWERON:
603     {
604       doPowerOn();
605       return;
606     }
607     case Input::POWEROFF:
608     {
609       doPowerOff();
610       return;
611     }
612     case Input::OK:
613     {
614       // FIXME
615       if (!connLost) return; // if connLost, handle Input::OK
616       doFromTheTop(false);
617       return;
618     }
619     case Input::GO:
620     {
621       logger->debug(TAG, "Handling sleeptimer go");
622       sleepTimer->go();
623       return;
624     }
625   }
626 }
627
628 /*
629 void Control::sig1()
630 {
631 #ifdef DEV
632   Message* m = new Message(); // break into master mutex
633   m->message = Message::SCREENSHOT;
634   m->to = this;
635   postMessage(m);
636 #endif
637 }
638 */
639
640 void Control::doStandby()
641 {
642   if (isStandby)
643   {
644     doPowerOn();
645   }
646   else
647   {
648     doPowerOff();
649   }
650 }
651
652
653 void Control::doPowerOn()
654 {
655   if (isStandby)
656   {
657     Video::getInstance()->signalOn();
658     Led::getInstance()->on();
659     InputMan::getInstance()->changePowerState(true);
660     isStandby = false;
661
662     VConnect* vconnect = new VConnect();
663     boxstack->add(vconnect);
664     vconnect->run();
665   }
666 }
667
668 void Control::doPowerOff()
669 {
670   if (!isStandby)
671   {
672     VDR::getInstance()->shutdownVDR();
673     boxstack->removeAllExceptWallpaper();
674     Video::getInstance()->signalOff();
675     boxstack->update(wallpaper);
676
677     VDR::getInstance()->configSave("General", "Last Power State", "Off");
678     logger->unsetExternLogger();
679     VDR::getInstance()->disconnect();
680     Led::getInstance()->off();
681     InputMan::getInstance()->changePowerState(false);
682     isStandby = true;
683     sleepTimer->shutdown();
684   }
685 }
686
687 void Control::doFromTheTop(bool which)
688 {
689   if (isStandby) return;
690   if (which)
691   {
692     if (connLost)
693     {
694       logger->info(TAG, "Connection lost dialog already present");
695       return;
696     }
697   
698     logger->info(TAG, "Doing connection lost dialog");
699     connLost = new VInfo();
700     connLost->setSize(360, 200);
701     connLost->createBuffer();
702     if (Video::getInstance()->getFormat() == Video::PAL)
703       connLost->setPosition(190, 170);
704     else
705       connLost->setPosition(180, 120);
706     connLost->setOneLiner(tr("Connection lost"));
707     connLost->setDropThrough();
708     connLost->setBorderOn(1);
709     connLost->setTitleBarColour(DrawStyle::DANGER);
710     connLost->okButton();
711     connLost->draw();
712     boxstack->add(connLost);
713     boxstack->update(connLost);
714
715     clearMQInputEvents();
716   }
717   else
718   {
719     logger->unsetExternLogger();
720     VDR::getInstance()->disconnect();
721     boxstack->removeAllExceptWallpaper();
722     boxstack->update(wallpaper);
723     connLost = NULL;
724     
725     flushMessageQueue();
726     
727     // at this point, everything should be reset to first-go
728     
729     VConnect* vconnect = new VConnect();
730     boxstack->add(vconnect);
731     vconnect->run();
732   }
733 }
734
735 void Control::clearMQInputEvents()
736 {
737   std::lock_guard<std::mutex> lg(messageQueueMutex); // Get the lock
738
739   MQueueI i = messages.begin();
740   while(i != messages.end())
741   {
742     Message* m = *i;
743     if (m->message == Message::INPUT_EVENT)
744     {
745       delete m;
746       i = messages.erase(i);
747     }
748     else
749     {
750       ++i;
751     }
752   }
753 }
754
755 void Control::doReboot()
756 {
757
758   logger->unsetExternLogger();
759   VDR::getInstance()->disconnect();
760   // just kill it...
761   logger->info(TAG, "Reboot");
762 #ifndef WIN32
763 #ifndef VOMP_HAS_EXIT
764   // some plattforms, want a proper deinitialisation of their hardware before reboot
765   Osd::getInstance()->shutdown();
766   Audio::getInstance()->shutdown();
767   Video::getInstance()->shutdown();
768   InputMan::getInstance()->shutdown();
769
770   reboot(LINUX_REBOOT_CMD_RESTART);
771   // if  reboot is not allowed -> stop
772   stop();
773
774
775 #else
776   stop();
777
778 #ifdef __ANDROID__
779   exit(0);
780 #endif
781
782 #endif
783 #endif //Would we support this on windows?
784 }
785
786 void Control::connectionLost()
787 {
788   logger->unsetExternLogger();
789   Message* m = new Message(); // break into master mutex
790   m->message = Message::CONNECTION_LOST;
791   m->p_to = Message::CONTROL;
792   postMessage(m);
793 }
794
795 void Control::buildCrashedBox()
796 {
797   VInfo* crash = new VInfo();
798   crash->setSize(360, 250);
799   crash->createBuffer();
800   if (Video::getInstance()->getFormat() == Video::PAL)
801     crash->setPosition(190, 146);
802   else
803     crash->setPosition(180, 96);
804   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.");
805   crash->setBorderOn(1);
806   crash->setTitleBarColour(DrawStyle::DANGER);
807   crash->okButton();
808   crash->setExitable();
809   crash->draw();
810   boxstack->add(crash);
811   boxstack->update(crash);
812 }
813
814 int Control::getLangPref(bool subtitle, const char* langcode)
815 {
816   std::vector<struct ASLPref>::iterator itty=langcodes.begin();
817   char templangcode[4];
818   templangcode[0] = langcode[0];
819   templangcode[1] = langcode[1];
820   templangcode[2] = langcode[2];
821   templangcode[3] = '\0';
822   int langpos = 0;
823   while (itty != langcodes.end())
824   {
825     size_t pos = (*itty).langcode.find(templangcode);
826     if (pos != std::string::npos)
827     {
828       //vector<struct ASLPref>::iterator itty2=langcodes.begin();
829       for (unsigned int i = 0; i < langcodes.size(); i++)
830       {
831         int pref = 0;
832         if (subtitle)
833           pref = langcodes[i].subtitlepref;
834         else
835           pref = langcodes[i].audiopref;
836         if (pref < 0) break;
837
838         if (subtitle)
839         {
840           if (langcodes[i].subtitlepref==langpos) return i;
841         }
842         else
843         {
844           if (langcodes[i].audiopref==langpos) return i;
845         }
846       }
847       break;
848     }
849     itty++;
850     langpos++;
851   }
852   return langcodes.size(); //neutral
853 }
854
855 void Control::doJustConnected(VConnect* vconnect)
856 {
857   I18n::initialize();
858   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
859   logger->info(TAG, "Entering doJustConnected");
860   
861   boxstack->remove(vconnect);
862
863   VInfo* vi = new VInfo();
864   vi->setSize(400, 200);
865   vi->createBuffer();
866   if (video->getFormat() == Video::PAL)
867     vi->setPosition(170, 200);
868   else
869     vi->setPosition(160, 150);
870   vi->setOneLiner(tr("Connected, loading config"));
871   vi->draw();
872   boxstack->add(vi);
873   boxstack->update(vi);
874
875   // FIXME make config system
876
877   char* config;
878
879   // See if we're supposed to do network logging
880   config = vdr->configLoad("Advanced", "Network logging");
881   if (config && !STRCASECMP(config, "On"))
882   {
883     logger->info(TAG, "Turning on network logging");
884     logger->setExternLogger(vdr);
885   }  
886   else
887   {
888           logger->unsetExternLogger();
889     logger->info(TAG, "Turned off network logging");
890   }
891   if (config) delete[] config;
892
893   config = vdr->configLoad("Advanced", "Skin Name");
894   if (config)
895   {
896     const char **skinnames=SkinFactory::getSkinNames();
897     for (int i=0;i<SkinFactory::getNumberofSkins();i++)
898     {
899       if (!STRCASECMP(config, skinnames[i]))
900       {
901         SkinFactory::InitSkin(i);
902         break;
903       }
904     }
905     delete[] config;
906
907     if (wallpaper && wallpaper_pict)
908     {
909       if (DrawStyle::WALLPAPER.alpha)
910         wallpaper_pict->setVisible(true);
911       else
912         wallpaper_pict->setVisible(false);
913
914       wallpaper->draw();
915       boxstack->update(wallpaper);
916     }
917   }
918   else
919   {
920     SkinFactory::InitSkin(0);
921   }
922
923   // See if config says to override video format (PAL/NTSC)
924   config = vdr->configLoad("General", "Override Video Format");
925   if (config)
926   {
927     logger->debug(TAG, "Override Video Format is present");
928
929     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
930         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
931         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
932         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
933         )
934     {
935       // Oh sheesh, need to switch format. Bye bye TV...
936
937       // Take everything down
938       boxstack->removeAllExceptWallpaper();
939       boxstack->remove(wallpaper);
940       delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
941
942 #ifndef __ANDROID__
943       osd->shutdown();
944 #endif
945       video->shutdown();
946
947       inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
948       inputMan->init(); // FIXME this breaks badly now
949
950       // Get video and osd back up with the new mode
951       if (!strcmp(config, "PAL"))
952       {
953         logger->debug(TAG, "Switching to PAL");
954         video->init(Video::PAL);
955       }
956       else if (!strcmp(config, "NTSC"))
957       {
958         logger->debug(TAG, "Switching to NTSC");
959         video->init(Video::NTSC);
960       } else if (!strcmp(config, "PAL_M"))
961       {
962         logger->debug(TAG, "Switching to PAL_M");
963         video->init(Video::PAL_M);
964       } else if (!strcmp(config, "NTSC_J"))
965       {
966         logger->debug(TAG, "Switching to NTSC_J");
967         video->init(Video::NTSC_J);
968       }
969       delete[] config;
970
971 #ifndef __ANDROID__
972       //we do not init twice
973       osd->init();
974 #endif
975
976       // Put the wallpaper back
977       doWallpaper();
978
979       // Re add the vinfo
980       vi = new VInfo();
981       vi->setSize(400, 200);
982       vi->createBuffer();
983       if (video->getFormat() == Video::PAL)
984         vi->setPosition(170, 200);
985       else
986         vi->setPosition(160, 150);
987
988       vi->setOneLiner(tr("Connected, loading config"));
989       vi->draw();
990       boxstack->add(vi);
991       boxstack->update(vi);
992     }
993     else
994     {
995       logger->debug(TAG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
996     }
997   }
998   else
999   {
1000     logger->debug(TAG, "Phew, no dangerous on-the-fly mode switching to do!");
1001   }
1002
1003   // Power off if first boot and config says so
1004   if (firstBoot)
1005   {
1006     firstBoot = false;
1007
1008     logger->debug(TAG, "Load power after boot");
1009
1010     config = vdr->configLoad("General", "Power After Boot");
1011
1012     if (config)
1013     {
1014       if (!STRCASECMP(config, "On"))
1015       {
1016         logger->info(TAG, "Config says Power After Boot = On");
1017       }
1018       else if (!STRCASECMP(config, "Off"))
1019       {
1020         logger->info(TAG, "Config says Power After Boot = Off");
1021         doStandby();
1022         delete[] config;
1023         return; // quit here
1024       }
1025       else if (!STRCASECMP(config, "Last state"))
1026       {
1027         char* lastPowerState = vdr->configLoad("General", "Last Power State");
1028         if (lastPowerState)
1029         {
1030           if (!STRCASECMP(lastPowerState, "On"))
1031           {
1032             logger->info(TAG, "Config says Last Power State = On");
1033           }
1034           else if (!STRCASECMP(lastPowerState, "Off"))
1035           {
1036             logger->info(TAG, "Config says Last Power State = Off");
1037             doStandby();
1038             delete[] config;
1039             return; // quit here
1040           }
1041           else
1042           {
1043             logger->info(TAG, "Config General/Last Power State not understood");
1044           }
1045         }
1046         else
1047         {
1048           logger->info(TAG, "Config General/Last Power State not found");
1049         }
1050       }
1051       else
1052       {
1053         logger->info(TAG, "Config/Power After Boot not understood");
1054       }
1055       delete[] config;
1056     }
1057     else
1058     {
1059       logger->info(TAG, "Config General/Power After Boot not found");
1060     }
1061   }
1062
1063
1064   // Go S-Video if config says so
1065
1066   config = vdr->configLoad("TV", "Connection");
1067
1068   if (config)
1069   {
1070     if (!STRCASECMP(config, "S-Video"))
1071     {
1072       logger->info(TAG, "Switching to S-Video as Connection=%s", config);
1073       video->setConnection(Video::SVIDEO);
1074     } else  if (!STRCASECMP(config, "HDMI"))
1075     {
1076       logger->info(TAG, "Switching to HDMI as Connection=%s", config);
1077       video->setConnection(Video::HDMI);
1078     } else  if (!STRCASECMP(config, "HDMI3D"))
1079     {
1080       logger->info(TAG, "Switching to HDMI3D as Connection=%s", config);
1081       video->setConnection(Video::HDMI3D);
1082     }
1083     else
1084     {
1085       logger->info(TAG, "Switching to RGB/Composite as Connection=%s", config);
1086       video->setConnection(Video::COMPOSITERGB);
1087     }
1088     delete[] config;
1089   }
1090   else
1091   {
1092     logger->info(TAG, "Config TV/S-Video not found");
1093   }
1094
1095   // Set to shutdown VDR if config says
1096   
1097   config = vdr->configLoad("General", "VDR shutdown");
1098   if (config)
1099   {
1100     if (!STRCASECMP(config, "On"))
1101     {
1102       logger->info(TAG, "Shutdown VDR when shutting down vomp");
1103       vdr->setVDRShutdown(true);
1104     }
1105     else if (!STRCASECMP(config, "Off"))
1106     {
1107       logger->info(TAG, "Shutdown only vomp");
1108       vdr->setVDRShutdown(false);
1109     }
1110   }
1111   else
1112   {
1113     logger->info(TAG, "Default shutdown only vomp");
1114     vdr->setVDRShutdown(false); // Default
1115   }
1116           
1117   // Get TV aspect ratio
1118
1119   config = vdr->configLoad("TV", "Aspect");
1120   if (config)
1121   {
1122     if (!STRCASECMP(config, "16:9"))
1123     {
1124       logger->info(TAG, "/// Switching to TV aspect 16:9");
1125       video->setTVsize(Video::ASPECT16X9);
1126     }
1127     else
1128     {
1129       logger->info(TAG, "/// Switching to TV aspect 4:3");
1130       video->setTVsize(Video::ASPECT4X3);
1131     }
1132     delete[] config;
1133   }
1134   else
1135   {
1136     logger->info(TAG, "Config TV/Aspect type not found, going 4:3");
1137     video->setTVsize(Video::ASPECT4X3);
1138   }
1139
1140   config = vdr->configLoad("TV", "Widemode");
1141   if (config)
1142   {
1143     if (!STRCASECMP(config, "Letterbox"))
1144     {
1145       logger->info(TAG, "Setting letterbox mode");
1146       video->setMode(Video::LETTERBOX);
1147     }
1148     else
1149     {
1150       logger->info(TAG, "Setting chop-sides mode");
1151       video->setMode(Video::NORMAL);
1152     }
1153     delete[] config;
1154   }
1155   else
1156   {
1157 #ifdef __ANDROID__
1158          logger->info(TAG, "Config TV/Widemode not found, Setting letterbox mode");
1159          video->setMode(Video::LETTERBOX);
1160 #else
1161     logger->info(TAG, "Config TV/Widemode not found, Setting chop-sides mode");
1162     video->setMode(Video::NORMAL);
1163 #endif
1164   }
1165
1166   config = vdr->configLoad("Advanced", "TCP receive window");
1167   if (config)
1168   {
1169     size_t newTCPsize = atoi(config);
1170     delete[] config;
1171
1172     logger->info(TAG, "Setting TCP window size %i", newTCPsize);
1173     vdr->setReceiveWindow(newTCPsize);
1174   }
1175   else
1176   {
1177     logger->info(TAG, "TCP window size not found, setting 2048");
1178     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1179   }
1180
1181   config = vdr->configLoad("Advanced", "Font Name");
1182   if (config)
1183   {
1184         Osd::getInstance()->setFont(config);
1185     logger->info(TAG, "Setting Font to %s", config);
1186     delete[] config;
1187
1188   }
1189
1190
1191   // Set recording list type
1192
1193 #ifdef ADVANCED_MENUES
1194   config = vdr->configLoad("Advanced", "Menu type");
1195
1196   if (config)
1197   {
1198     if (!STRCASECMP(config, "Advanced"))
1199     {
1200       logger->info(TAG, "Switching to Advanced menu");
1201       advMenus = true;
1202     }
1203     else
1204     {
1205       logger->info(TAG, "Switching to Classic menu");
1206       advMenus = false;
1207     }
1208     delete[] config;
1209   }
1210   else
1211   {
1212     logger->info(TAG, "Config General/menu type not found");
1213     advMenus = true;
1214   }
1215 #endif
1216
1217   config = vdr->configLoad("Advanced", "Disable WOL");
1218   if (config)
1219   {
1220     if (!STRCASECMP(config, "Yes"))
1221     {
1222       logger->info(TAG, "Config says disable WOL");
1223       Wol::getInstance()->setEnabled(false);
1224     }
1225     else
1226     {
1227       logger->info(TAG, "Config says enable WOL");
1228       Wol::getInstance()->setEnabled(true);
1229     }
1230
1231     delete[] config;
1232   }
1233   else
1234   {
1235     logger->info(TAG, "By default, enable WOL");
1236     Wol::getInstance()->setEnabled(true);
1237   }
1238   /* device dependend config */
1239   audio->loadOptionsFromServer(vdr);
1240   video->loadOptionsFromServer(vdr);
1241   inputMan->loadOptionsFromServer(vdr);
1242
1243   video->executePendingModeChanges();
1244   // config done
1245
1246   // Save power state = on
1247
1248   vdr->configSave("General", "Last Power State", "On");
1249
1250   // Make sure connection didn't die
1251   if (!vdr->isConnected())
1252   {
1253     Control::getInstance()->connectionLost();
1254   }
1255   else
1256   {
1257     boxstack->remove(vi);
1258
1259     VWelcome* vw = new VWelcome();
1260     vw->draw();
1261     boxstack->add(vw);
1262     boxstack->update(vw);
1263
1264     // Enter pre-keys here
1265 //    handleCommand(Input::OK);
1266 //    handleCommand(Input::THREE);
1267 //    handleCommand(Input::SIX);
1268 //    handleCommand(Input::OK);
1269 //    handleCommand(Input::UP);
1270 //    handleCommand(Input::PLAY);
1271 //    handleCommand(Input::DOWN);
1272 //    handleCommand(Input::DOWN);
1273 //    handleCommand(Input::DOWN);
1274 //    handleCommand(Input::RIGHT);
1275 //    handleCommand(Input::RED);
1276   }
1277 }