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