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