]> git.vomp.tv Git - vompclient.git/blob - control.cc
Bitmap and VPictureBanner CWFs
[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 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       logger->log("Control", Log::DEBUG, "Handling sleeptimer go");
620       sleepTimer->go();
621       return;
622     }
623   }
624 }
625
626 /*
627 void Control::sig1()
628 {
629 #ifdef DEV
630   Message* m = new Message(); // break into master mutex
631   m->message = Message::SCREENSHOT;
632   m->to = this;
633   postMessage(m);
634 #endif
635 }
636 */
637
638 void Control::doStandby()
639 {
640   if (isStandby)
641   {
642     doPowerOn();
643   }
644   else
645   {
646     doPowerOff();
647   }
648 }
649
650
651 void Control::doPowerOn()
652 {
653   if (isStandby)
654   {
655     Video::getInstance()->signalOn();
656     Led::getInstance()->on();
657     InputMan::getInstance()->changePowerState(true);
658     isStandby = false;
659
660     VConnect* vconnect = new VConnect();
661     boxstack->add(vconnect);
662     vconnect->run();
663   }
664 }
665
666 void Control::doPowerOff()
667 {
668   if (!isStandby)
669   {
670     VDR::getInstance()->shutdownVDR();
671     boxstack->removeAllExceptWallpaper();
672     Video::getInstance()->signalOff();
673     boxstack->update(wallpaper);
674
675     VDR::getInstance()->configSave("General", "Last Power State", "Off");
676     logger->unsetExternLogger();
677     VDR::getInstance()->disconnect();
678     Led::getInstance()->off();
679     InputMan::getInstance()->changePowerState(false);
680     isStandby = true;
681     sleepTimer->shutdown();
682   }
683 }
684
685 void Control::doFromTheTop(bool which)
686 {
687   if (isStandby) return;
688   if (which)
689   {
690     if (connLost)
691     {
692       logger->log("Control", Log::NOTICE, "Connection lost dialog already present");
693       return;
694     }
695   
696     logger->log("Control", Log::NOTICE, "Doing connection lost dialog");
697     connLost = new VInfo();
698     connLost->setSize(360, 200);
699     connLost->createBuffer();
700     if (Video::getInstance()->getFormat() == Video::PAL)
701       connLost->setPosition(190, 170);
702     else
703       connLost->setPosition(180, 120);
704     connLost->setOneLiner(tr("Connection lost"));
705     connLost->setDropThrough();
706     connLost->setBorderOn(1);
707     connLost->setTitleBarColour(DrawStyle::DANGER);
708     connLost->okButton();
709     connLost->draw();
710     boxstack->add(connLost);
711     boxstack->update(connLost);
712
713     clearMQInputEvents();
714   }
715   else
716   {
717     logger->unsetExternLogger();
718     VDR::getInstance()->disconnect();
719     boxstack->removeAllExceptWallpaper();
720     boxstack->update(wallpaper);
721     connLost = NULL;
722     
723     flushMessageQueue();
724     
725     // at this point, everything should be reset to first-go
726     
727     VConnect* vconnect = new VConnect();
728     boxstack->add(vconnect);
729     vconnect->run();
730   }
731 }
732
733 void Control::clearMQInputEvents()
734 {
735   std::lock_guard<std::mutex> lg(messageQueueMutex); // Get the lock
736
737   MQueueI i = messages.begin();
738   while(i != messages.end())
739   {
740     Message* m = *i;
741     if (m->message == Message::INPUT_EVENT)
742     {
743       delete m;
744       i = messages.erase(i);
745     }
746     else
747     {
748       ++i;
749     }
750   }
751 }
752
753 void Control::doReboot()
754 {
755
756   logger->unsetExternLogger();
757   VDR::getInstance()->disconnect();
758   // just kill it...
759   logger->log("Control", Log::NOTICE, "Reboot");
760 #ifndef WIN32
761 #ifndef VOMP_HAS_EXIT
762   // some plattforms, want a proper deinitialisation of their hardware before reboot
763   Osd::getInstance()->shutdown();
764   Audio::getInstance()->shutdown();
765   Video::getInstance()->shutdown();
766   InputMan::getInstance()->shutdown();
767
768   reboot(LINUX_REBOOT_CMD_RESTART);
769   // if  reboot is not allowed -> stop
770   stop();
771
772
773 #else
774   stop();
775
776 #ifdef __ANDROID__
777   exit(0);
778 #endif
779
780 #endif
781 #endif //Would we support this on windows?
782 }
783
784 void Control::connectionLost()
785 {
786   logger->unsetExternLogger();
787   Message* m = new Message(); // break into master mutex
788   m->message = Message::CONNECTION_LOST;
789   m->p_to = Message::CONTROL;
790   postMessage(m);
791 }
792
793 void Control::buildCrashedBox()
794 {
795   VInfo* crash = new VInfo();
796   crash->setSize(360, 250);
797   crash->createBuffer();
798   if (Video::getInstance()->getFormat() == Video::PAL)
799     crash->setPosition(190, 146);
800   else
801     crash->setPosition(180, 96);
802   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.");
803   crash->setBorderOn(1);
804   crash->setTitleBarColour(DrawStyle::DANGER);
805   crash->okButton();
806   crash->setExitable();
807   crash->draw();
808   boxstack->add(crash);
809   boxstack->update(crash);
810 }
811
812 int Control::getLangPref(bool subtitle, const char* langcode)
813 {
814   std::vector<struct ASLPref>::iterator itty=langcodes.begin();
815   char templangcode[4];
816   templangcode[0] = langcode[0];
817   templangcode[1] = langcode[1];
818   templangcode[2] = langcode[2];
819   templangcode[3] = '\0';
820   int langpos = 0;
821   while (itty != langcodes.end())
822   {
823     size_t pos = (*itty).langcode.find(templangcode);
824     if (pos != std::string::npos)
825     {
826       //vector<struct ASLPref>::iterator itty2=langcodes.begin();
827       for (unsigned int i = 0; i < langcodes.size(); i++)
828       {
829         int pref = 0;
830         if (subtitle)
831           pref = langcodes[i].subtitlepref;
832         else
833           pref = langcodes[i].audiopref;
834         if (pref < 0) break;
835
836         if (subtitle)
837         {
838           if (langcodes[i].subtitlepref==langpos) return i;
839         }
840         else
841         {
842           if (langcodes[i].audiopref==langpos) return i;
843         }
844       }
845       break;
846     }
847     itty++;
848     langpos++;
849   }
850   return langcodes.size(); //neutral
851 }
852
853 void Control::doJustConnected(VConnect* vconnect)
854 {
855   I18n::initialize();
856   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
857   logger->log("Control", Log::INFO, "Entering doJustConnected");
858   
859   boxstack->remove(vconnect);
860
861   VInfo* vi = new VInfo();
862   vi->setSize(400, 200);
863   vi->createBuffer();
864   if (video->getFormat() == Video::PAL)
865     vi->setPosition(170, 200);
866   else
867     vi->setPosition(160, 150);
868   vi->setOneLiner(tr("Connected, loading config"));
869   vi->draw();
870   boxstack->add(vi);
871   boxstack->update(vi);
872
873   // FIXME make config system
874
875   char* config;
876
877   // See if we're supposed to do network logging
878   config = vdr->configLoad("Advanced", "Network logging");
879   if (config && !STRCASECMP(config, "On"))
880   {
881     logger->log("Control", Log::INFO, "Turning on network logging");
882     logger->setExternLogger(vdr);
883   }  
884   else
885   {
886           logger->unsetExternLogger();
887     logger->log("Control", Log::INFO, "Turned off network logging");
888   }
889   if (config) delete[] config;
890
891   config = vdr->configLoad("Advanced", "Skin Name");
892   if (config)
893   {
894     const char **skinnames=SkinFactory::getSkinNames();
895     for (int i=0;i<SkinFactory::getNumberofSkins();i++)
896     {
897       if (!STRCASECMP(config, skinnames[i]))
898       {
899         SkinFactory::InitSkin(i);
900         break;
901       }
902     }
903     delete[] config;
904
905     if (wallpaper && wallpaper_pict)
906     {
907       if (DrawStyle::WALLPAPER.alpha)
908         wallpaper_pict->setVisible(true);
909       else
910         wallpaper_pict->setVisible(false);
911
912       wallpaper->draw();
913       boxstack->update(wallpaper);
914     }
915   }
916   else
917   {
918     SkinFactory::InitSkin(0);
919   }
920
921   // See if config says to override video format (PAL/NTSC)
922   config = vdr->configLoad("General", "Override Video Format");
923   if (config)
924   {
925     logger->log("Control", Log::DEBUG, "Override Video Format is present");
926
927     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
928         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
929         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
930         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
931         )
932     {
933       // Oh sheesh, need to switch format. Bye bye TV...
934
935       // Take everything down
936       boxstack->removeAllExceptWallpaper();
937       boxstack->remove(wallpaper);
938       delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
939
940 #ifndef __ANDROID__
941       osd->shutdown();
942 #endif
943       video->shutdown();
944
945       inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
946       inputMan->init(); // FIXME this breaks badly now
947
948       // Get video and osd back up with the new mode
949       if (!strcmp(config, "PAL"))
950       {
951         logger->log("Control", Log::DEBUG, "Switching to PAL");
952         video->init(Video::PAL);
953       }
954       else if (!strcmp(config, "NTSC"))
955       {
956         logger->log("Control", Log::DEBUG, "Switching to NTSC");
957         video->init(Video::NTSC);
958       } else if (!strcmp(config, "PAL_M"))
959       {
960         logger->log("Control", Log::DEBUG, "Switching to PAL_M");
961         video->init(Video::PAL_M);
962       } else if (!strcmp(config, "NTSC_J"))
963       {
964         logger->log("Control", Log::DEBUG, "Switching to NTSC_J");
965         video->init(Video::NTSC_J);
966       }
967       delete[] config;
968
969 #ifndef __ANDROID__
970       //we do not init twice
971       osd->init();
972 #endif
973
974       // Put the wallpaper back
975       doWallpaper();
976
977       // Re add the vinfo
978       vi = new VInfo();
979       vi->setSize(400, 200);
980       vi->createBuffer();
981       if (video->getFormat() == Video::PAL)
982         vi->setPosition(170, 200);
983       else
984         vi->setPosition(160, 150);
985
986       vi->setOneLiner(tr("Connected, loading config"));
987       vi->draw();
988       boxstack->add(vi);
989       boxstack->update(vi);
990     }
991     else
992     {
993       logger->log("Control", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
994     }
995   }
996   else
997   {
998     logger->log("Control", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
999   }
1000
1001   // Power off if first boot and config says so
1002   if (firstBoot)
1003   {
1004     firstBoot = false;
1005
1006     logger->log("Control", Log::DEBUG, "Load power after boot");
1007
1008     config = vdr->configLoad("General", "Power After Boot");
1009
1010     if (config)
1011     {
1012       if (!STRCASECMP(config, "On"))
1013       {
1014         logger->log("Control", Log::INFO, "Config says Power After Boot = On");
1015       }
1016       else if (!STRCASECMP(config, "Off"))
1017       {
1018         logger->log("Control", Log::INFO, "Config says Power After Boot = Off");
1019         doStandby();
1020         delete[] config;
1021         return; // quit here
1022       }
1023       else if (!STRCASECMP(config, "Last state"))
1024       {
1025         char* lastPowerState = vdr->configLoad("General", "Last Power State");
1026         if (lastPowerState)
1027         {
1028           if (!STRCASECMP(lastPowerState, "On"))
1029           {
1030             logger->log("Control", Log::INFO, "Config says Last Power State = On");
1031           }
1032           else if (!STRCASECMP(lastPowerState, "Off"))
1033           {
1034             logger->log("Control", Log::INFO, "Config says Last Power State = Off");
1035             doStandby();
1036             delete[] config;
1037             return; // quit here
1038           }
1039           else
1040           {
1041             logger->log("Control", Log::INFO, "Config General/Last Power State not understood");
1042           }
1043         }
1044         else
1045         {
1046           logger->log("Control", Log::INFO, "Config General/Last Power State not found");
1047         }
1048       }
1049       else
1050       {
1051         logger->log("Control", Log::INFO, "Config/Power After Boot not understood");
1052       }
1053       delete[] config;
1054     }
1055     else
1056     {
1057       logger->log("Control", Log::INFO, "Config General/Power After Boot not found");
1058     }
1059   }
1060
1061
1062   // Go S-Video if config says so
1063
1064   config = vdr->configLoad("TV", "Connection");
1065
1066   if (config)
1067   {
1068     if (!STRCASECMP(config, "S-Video"))
1069     {
1070       logger->log("Control", Log::INFO, "Switching to S-Video as Connection=%s", config);
1071       video->setConnection(Video::SVIDEO);
1072     } else  if (!STRCASECMP(config, "HDMI"))
1073     {
1074       logger->log("Control", Log::INFO, "Switching to HDMI as Connection=%s", config);
1075       video->setConnection(Video::HDMI);
1076     } else  if (!STRCASECMP(config, "HDMI3D"))
1077     {
1078       logger->log("Control", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
1079       video->setConnection(Video::HDMI3D);
1080     }
1081     else
1082     {
1083       logger->log("Control", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
1084       video->setConnection(Video::COMPOSITERGB);
1085     }
1086     delete[] config;
1087   }
1088   else
1089   {
1090     logger->log("Control", Log::INFO, "Config TV/S-Video not found");
1091   }
1092
1093   // Set to shutdown VDR if config says
1094   
1095   config = vdr->configLoad("General", "VDR shutdown");
1096   if (config)
1097   {
1098     if (!STRCASECMP(config, "On"))
1099     {
1100       logger->log("Control", Log::INFO, "Shutdown VDR when shutting down vomp");
1101       vdr->setVDRShutdown(true);
1102     }
1103     else if (!STRCASECMP(config, "Off"))
1104     {
1105       logger->log("Control", Log::INFO, "Shutdown only vomp");
1106       vdr->setVDRShutdown(false);
1107     }
1108   }
1109   else
1110   {
1111     logger->log("Control", Log::INFO, "Default shutdown only vomp");
1112     vdr->setVDRShutdown(false); // Default
1113   }
1114           
1115   // Get TV aspect ratio
1116
1117   config = vdr->configLoad("TV", "Aspect");
1118   if (config)
1119   {
1120     if (!STRCASECMP(config, "16:9"))
1121     {
1122       logger->log("Control", Log::INFO, "/// Switching to TV aspect 16:9");
1123       video->setTVsize(Video::ASPECT16X9);
1124     }
1125     else
1126     {
1127       logger->log("Control", Log::INFO, "/// Switching to TV aspect 4:3");
1128       video->setTVsize(Video::ASPECT4X3);
1129     }
1130     delete[] config;
1131   }
1132   else
1133   {
1134     logger->log("Control", Log::INFO, "Config TV/Aspect type not found, going 4:3");
1135     video->setTVsize(Video::ASPECT4X3);
1136   }
1137
1138   config = vdr->configLoad("TV", "Widemode");
1139   if (config)
1140   {
1141     if (!STRCASECMP(config, "Letterbox"))
1142     {
1143       logger->log("Control", Log::INFO, "Setting letterbox mode");
1144       video->setMode(Video::LETTERBOX);
1145     }
1146     else
1147     {
1148       logger->log("Control", Log::INFO, "Setting chop-sides mode");
1149       video->setMode(Video::NORMAL);
1150     }
1151     delete[] config;
1152   }
1153   else
1154   {
1155 #ifdef __ANDROID__
1156          logger->log("Control", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
1157          video->setMode(Video::LETTERBOX);
1158 #else
1159     logger->log("Control", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
1160     video->setMode(Video::NORMAL);
1161 #endif
1162   }
1163
1164   config = vdr->configLoad("Advanced", "TCP receive window");
1165   if (config)
1166   {
1167     size_t newTCPsize = atoi(config);
1168     delete[] config;
1169
1170     logger->log("Control", Log::INFO, "Setting TCP window size %i", newTCPsize);
1171     vdr->setReceiveWindow(newTCPsize);
1172   }
1173   else
1174   {
1175     logger->log("Control", Log::INFO, "TCP window size not found, setting 2048");
1176     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1177   }
1178
1179   config = vdr->configLoad("Advanced", "Font Name");
1180   if (config)
1181   {
1182         Osd::getInstance()->setFont(config);
1183     logger->log("Control", Log::INFO, "Setting Font to %s", config);
1184     delete[] config;
1185
1186   }
1187
1188
1189   // Set recording list type
1190
1191 #ifdef ADVANCED_MENUES
1192   config = vdr->configLoad("Advanced", "Menu type");
1193
1194   if (config)
1195   {
1196     if (!STRCASECMP(config, "Advanced"))
1197     {
1198       logger->log("Control", Log::INFO, "Switching to Advanced menu");
1199       advMenus = true;
1200     }
1201     else
1202     {
1203       logger->log("Control", Log::INFO, "Switching to Classic menu");
1204       advMenus = false;
1205     }
1206     delete[] config;
1207   }
1208   else
1209   {
1210     logger->log("Control", Log::INFO, "Config General/menu type not found");
1211     advMenus = true;
1212   }
1213 #endif
1214
1215   config = vdr->configLoad("Advanced", "Disable WOL");
1216   if (config)
1217   {
1218     if (!STRCASECMP(config, "Yes"))
1219     {
1220       logger->log("Control", Log::INFO, "Config says disable WOL");
1221       Wol::getInstance()->setEnabled(false);
1222     }
1223     else
1224     {
1225       logger->log("Control", Log::INFO, "Config says enable WOL");
1226       Wol::getInstance()->setEnabled(true);
1227     }
1228
1229     delete[] config;
1230   }
1231   else
1232   {
1233     logger->log("Control", Log::INFO, "By default, enable WOL");
1234     Wol::getInstance()->setEnabled(true);
1235   }
1236   /* device dependend config */
1237   audio->loadOptionsFromServer(vdr);
1238   video->loadOptionsFromServer(vdr);
1239   inputMan->loadOptionsFromServer(vdr);
1240
1241   video->executePendingModeChanges();
1242   // config done
1243
1244   // Save power state = on
1245
1246   vdr->configSave("General", "Last Power State", "On");
1247
1248   // Make sure connection didn't die
1249   if (!vdr->isConnected())
1250   {
1251     Control::getInstance()->connectionLost();
1252   }
1253   else
1254   {
1255     boxstack->remove(vi);
1256
1257     VWelcome* vw = new VWelcome();
1258     vw->draw();
1259     boxstack->add(vw);
1260     boxstack->update(vw);
1261
1262     // Enter pre-keys here
1263 //    handleCommand(Input::OK);
1264 //    handleCommand(Input::THREE);
1265 //    handleCommand(Input::SIX);
1266 //    handleCommand(Input::OK);
1267 //    handleCommand(Input::UP);
1268 //    handleCommand(Input::PLAY);
1269 //    handleCommand(Input::DOWN);
1270 //    handleCommand(Input::DOWN);
1271 //    handleCommand(Input::DOWN);
1272 //    handleCommand(Input::RIGHT);
1273 //    handleCommand(Input::RED);
1274   }
1275 }