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