]> git.vomp.tv Git - vompclient.git/blob - command.cc
20 CWFs, fix some snprintf calls
[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 "timerreceiver.h"
45 #include "timers.h"
46 #include "wol.h"
47 #include "vconnect.h"
48 #include "message.h"
49 #include "inputman.h"
50 #include "input.h"
51 #include "vinfo.h"
52 #include "boxx.h"
53 #include "boxstack.h"
54 #include "log.h"
55 #include "vsleeptimer.h"
56 #include "wjpeg.h"
57 #include "osdvector.h"
58
59
60 Command* Command::instance = NULL;
61
62 Command::Command()
63 {
64   if (instance) return;
65   instance = this;
66 }
67
68 Command::~Command()
69 {
70   flushMessageQueue();
71   instance = NULL;
72 }
73
74 Command* Command::getInstance()
75 {
76   return instance;
77 }
78
79 int Command::init(bool tcrashed, char* tServer)
80 {
81   if (initted) return 0;
82   initted = true;
83   crashed = tcrashed;
84   server = tServer;
85
86   logger = Log::getInstance();
87   boxstack = BoxStack::getInstance();
88   inputMan = InputMan::getInstance();
89   
90   if (!logger || !boxstack || !inputMan)
91   {
92     initted = false;
93     return 0;
94   }
95
96   SkinFactory::InitSkin(0);
97
98   return 1;
99 }
100
101 int Command::shutdown()
102 {
103   if (!initted) return 0;
104   initted = false;
105   return 1;
106 }
107
108 void Command::stop()
109 {
110   logger->log("Command", Log::NOTICE, "Request stop");
111
112   Message* m = new Message(); // break master loop
113   m->message = Message::SHUTDOWN;
114   m->to = this;
115   postMessage(m);
116 }
117
118 void Command::doWallpaper()
119 {
120   Video* video = Video::getInstance();
121
122   // Blue background
123   Boxx* bbg = new Boxx();
124   bbg->setSize(video->getScreenWidth(), video->getScreenHeight());
125   bbg->createBuffer();
126   bbg->fillColour(DrawStyle::WALLPAPER);
127   boxstack->add(bbg);
128   boxstack->update(bbg);
129   boxstack->remove(bbg);
130
131   // Wallpaper
132   wallpaper = new Boxx();
133   wallpaper->setSize(video->getScreenWidth(), video->getScreenHeight());
134   wallpaper->createBuffer();
135   wallpaper->setBackgroundColour(DrawStyle::WALLPAPER);
136
137   wallpaper_pict = new WJpegTYPE();
138   wallpaper_pict->setSize(video->getScreenWidth(), video->getScreenHeight());
139
140   if (video->getFormat() == Video::PAL)
141   {
142     logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
143 #ifndef _MIPS_ARCH    
144     wallpaper_pict->init("/wallpaperPAL.jpg");
145 #else
146     wallpaper_pict->init("wallpaperPAL.jpg");
147 #endif
148   }
149   else
150   {
151     logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
152     wallpaper_pict->init("/wallpaperNTSC.jpg");
153   }
154
155   if (DrawStyle::WALLPAPER.alpha)
156     wallpaper_pict->setVisible(true);
157   else
158     wallpaper_pict->setVisible(false);
159
160   wallpaper->add(wallpaper_pict);
161   wallpaper->draw();
162
163   boxstack->add(wallpaper);
164   boxstack->update(wallpaper);
165
166   OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
167   if (osdv) osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
168 }
169
170 void Command::run()
171 {
172   if (!initted) return;
173   irun = true;
174
175   // just in case
176   Video::getInstance()->signalOn();
177   Led::getInstance()->on();
178
179   doWallpaper();
180
181   if (crashed)
182   {
183     buildCrashedBox();
184   }
185   else
186   {
187     VConnect* vconnect = new VConnect(server);
188     boxstack->add(vconnect);
189     vconnect->run();
190   }
191
192
193   // FIXME Input::NA_SIGNAL is possibly obsolete now
194
195   std::unique_lock<std::mutex> lockWrapper(messageQueueMutex);  // locks. unlocks on out-of-scope
196
197   inputMan->start();
198
199   while(irun)
200   {
201     messageQueueCond.wait(lockWrapper, [&] { return !irun || !messages.empty(); });
202     logger->log("Command", Log::DEBUG, "woke");
203
204     if (!irun) break;
205
206     while(!messages.empty())
207     {
208       Message* m = messages.front();
209       messages.pop_front();
210
211       lockWrapper.unlock();
212
213       processMessage(m);
214       delete m;
215
216       lockWrapper.lock();
217     }
218   }
219
220   inputMan->stop();
221
222   boxstack->removeAllExceptWallpaper();
223   boxstack->remove(wallpaper);
224   delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
225 }
226
227 void Command::processMessage(Message* m)
228 {
229     // FIXME - a slight modification - how if messagereceivers were to register
230     // themselves as receivers to avoid the calling-a-deleted-object problem
231     // then only deliver/register/unregister would have to be protected
232
233   logger->log("Command", Log::DEBUG, "processing message %i", m->message);
234
235
236   if (m->to == this)
237   {
238     switch(m->message)
239     {
240       case Message::SHUTDOWN:
241       {
242         irun = false;
243         break;
244       }
245       // << FIXME OBSELETE
246       case Message::STOP_PLAYBACK:
247       {
248         handleCommand(Input::STOP); // an odd way of doing it, but so simple
249         break;
250       }
251       // Also connection_lost comes from player - anywhere else?
252       // FIXME OBSELETE >>
253
254
255       case Message::VDR_CONNECTED:
256       {
257         doJustConnected(static_cast<VConnect*>(m->from));
258         break;
259       }
260       case Message::SCREENSHOT:
261       {
262         logger->log("Osd", Log::NOTICE, "Screenshot Message arrived");
263         Osd::getInstance()->screenShot("out.jpg");
264         break;
265       }
266       case Message::CONNECTION_LOST:
267       {
268         doFromTheTop(true);
269         break;
270       }
271       case Message::INPUT_EVENT:
272       {
273         logger->log("Command", Log::NOTICE, "INPUT_EVENT %i", m->parameter);
274
275         handleCommand(m->parameter);
276         break;
277       }
278       case Message::CHANGE_LANGUAGE:
279       {
280         boxstack->removeAllExceptWallpaper();
281         boxstack->update(wallpaper);
282         I18n::initialize();
283         if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
284         VWelcome* vw = new VWelcome();
285         vw->draw();
286         boxstack->add(vw);
287         boxstack->update(vw);
288         break;
289       }
290       case Message::LAST_VIEW_CLOSE:
291       {
292         // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
293         if (crashed)
294         {
295           crashed = false;
296           doFromTheTop(false);        
297         }
298       
299 //        VWelcome* vw = new VWelcome();
300 //        vw->draw();
301 //        boxstack->add(vw);
302 //        boxstack->update(vw);
303
304         break;
305       }
306       case Message::NEW_PICTURE:
307       {
308         //Log::getInstance()->log("Command", Log::DEBUG, "TVMedia NEW_PICTURE");
309         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
310         if (osdv) osdv->informPicture(m->tag, reinterpret_cast<ImageIndex>(m->data));
311         break;
312       }
313       case Message::NEW_PICTURE_STATIC:
314       {
315         //Log::getInstance()->log("Command", Log::DEBUG, "TVMedia NEW_PICTURE %x %x",m->tag,m->parameter);
316         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
317         if (osdv) osdv->informPicture(static_cast<unsigned long long>(m->tag) << 32LL, reinterpret_cast<ImageIndex>(m->data));
318         break;
319       }
320     }
321   }
322   else
323   {
324     /* FIXME
325     
326     Instead of sending through the boxstack, implement a more generic MessageReceiver interface
327     and have potential receivers register with something
328     When a message needs to be delivered, check if the receiver is still registered, if so, deliver the message
329     This could all be done using the existing big command mutex to keep it simple
330     */
331   
332     logger->log("Command", Log::DEBUG, "Sending message to boxstack");
333     boxstack->processMessage(m);
334   }
335 }
336
337 void Command::handleCommand(int button)
338 {
339   if (isStandby && (button != Input::POWER)
340                 && (button != Input::POWERON)
341                 && (button != Input::POWEROFF))  return;
342
343   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
344
345   // command was not handled
346
347   switch(button)
348   {
349     case Input::VOLUMEUP:
350     case Input::VOLUMEDOWN:
351     {
352       if (inputMan->handlesVolume()) // CEC volume handler?
353       {
354         if (button == Input::VOLUMEDOWN)
355           inputMan->volumeDown();
356         else
357           inputMan->volumeUp();
358       }
359       else
360       {
361         VVolume* v = new VVolume();
362         boxstack->add(v);
363         v->handleCommand(button); // this will draw+show
364       }
365       return;
366     }
367     case Input::MUTE:
368     {
369       if (inputMan->handlesVolume())
370       {
371         inputMan->volumeMute();
372       }
373       else
374       {
375         VMute* v = new VMute();
376         v->draw();
377         boxstack->add(v);
378         boxstack->update(v);
379       }
380       return;
381     }
382     case Input::POWER:
383     {
384       doStandby();
385       return;
386     }
387     case Input::POWERON:
388     {
389       doPowerOn();
390       return;
391     }
392     case Input::POWEROFF:
393     {
394       doPowerOff();
395       return;
396     }
397     case Input::OK:
398     {
399       // FIXME
400       if (!connLost) return; // if connLost, handle Input::OK
401       doFromTheTop(false);
402       return;
403     }
404     case Input::GO:
405     {
406       VSleeptimer* sleep = new VSleeptimer();
407       boxstack->add(sleep);
408       sleep->handleCommand(button); // this will draw+show
409       return;
410     }
411   }
412 }
413
414 void Command::sig1()
415 {
416 #ifdef DEV
417   Message* m = new Message(); // break into master mutex
418   m->message = Message::SCREENSHOT;
419   m->to = this;
420   postMessage(m);
421 #endif
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(server);
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(server);
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->to = this;
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   VDR* vdr = VDR::getInstance();
662   char* config;
663
664   // See if we're supposed to do network logging
665   config = vdr->configLoad("Advanced", "Network logging");
666   if (config && !STRCASECMP(config, "On"))
667   {
668     logger->log("Command", Log::INFO, "Turning on network logging");
669     logger->setExternLogger(vdr);
670   }  
671   else
672   {
673           logger->unsetExternLogger();
674     logger->log("Command", Log::INFO, "Turned off network logging");
675   }
676   if (config) delete[] config;
677
678   config = vdr->configLoad("Advanced", "Skin Name");
679   if (config)
680   {
681     const char **skinnames=SkinFactory::getSkinNames();
682     for (int i=0;i<SkinFactory::getNumberofSkins();i++)
683     {
684       if (!STRCASECMP(config, skinnames[i]))
685       {
686         SkinFactory::InitSkin(i);
687         break;
688       }
689     }
690     delete[] config;
691
692     if (wallpaper && wallpaper_pict)
693     {
694       if (DrawStyle::WALLPAPER.alpha)
695         wallpaper_pict->setVisible(true);
696       else
697         wallpaper_pict->setVisible(false);
698
699       wallpaper->draw();
700       boxstack->update(wallpaper);
701     }
702   }
703   else
704   {
705     SkinFactory::InitSkin(0);
706   }
707
708   // See if config says to override video format (PAL/NTSC)
709   config = vdr->configLoad("General", "Override Video Format");
710   if (config)
711   {
712     logger->log("Command", Log::DEBUG, "Override Video Format is present");
713
714     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
715         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
716         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
717         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
718         )
719     {
720       // Oh sheesh, need to switch format. Bye bye TV...
721
722       // Take everything down
723       boxstack->removeAllExceptWallpaper();
724       boxstack->remove(wallpaper);
725       delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
726
727       Osd* osd = Osd::getInstance();
728 #ifndef __ANDROID__
729       osd->shutdown();
730 #endif
731       video->shutdown();
732
733       inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
734       inputMan->init(); // FIXME this breaks badly now
735
736       // Get video and osd back up with the new mode
737       if (!strcmp(config, "PAL"))
738       {
739         logger->log("Command", Log::DEBUG, "Switching to PAL");
740         video->init(Video::PAL);
741       }
742       else if (!strcmp(config, "NTSC"))
743       {
744         logger->log("Command", Log::DEBUG, "Switching to NTSC");
745         video->init(Video::NTSC);
746       } else if (!strcmp(config, "PAL_M"))
747       {
748         logger->log("Command", Log::DEBUG, "Switching to PAL_M");
749         video->init(Video::PAL_M);
750       } else if (!strcmp(config, "NTSC_J"))
751       {
752         logger->log("Command", Log::DEBUG, "Switching to NTSC_J");
753         video->init(Video::NTSC_J);
754       }
755       delete[] config;
756
757 #ifndef __ANDROID__
758       //we do not init twice
759       osd->init();
760 #endif
761
762       // Put the wallpaper back
763       doWallpaper();
764
765       // Re add the vinfo
766       vi = new VInfo();
767       vi->setSize(400, 200);
768       vi->createBuffer();
769       if (video->getFormat() == Video::PAL)
770         vi->setPosition(170, 200);
771       else
772         vi->setPosition(160, 150);
773
774       vi->setOneLiner(tr("Connected, loading config"));
775       vi->draw();
776       boxstack->add(vi);
777       boxstack->update(vi);
778     }
779     else
780     {
781       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
782     }
783   }
784   else
785   {
786     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
787   }
788
789   // Power off if first boot and config says so
790   if (firstBoot)
791   {
792     firstBoot = false;
793
794     logger->log("Command", Log::DEBUG, "Load power after boot");
795
796     config = vdr->configLoad("General", "Power After Boot");
797
798     if (config)
799     {
800       if (!STRCASECMP(config, "On"))
801       {
802         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
803       }
804       else if (!STRCASECMP(config, "Off"))
805       {
806         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
807         doStandby();
808         delete[] config;
809         return; // quit here
810       }
811       else if (!STRCASECMP(config, "Last state"))
812       {
813         char* lastPowerState = vdr->configLoad("General", "Last Power State");
814         if (lastPowerState)
815         {
816           if (!STRCASECMP(lastPowerState, "On"))
817           {
818             logger->log("Command", Log::INFO, "Config says Last Power State = On");
819           }
820           else if (!STRCASECMP(lastPowerState, "Off"))
821           {
822             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
823             doStandby();
824             delete[] config;
825             return; // quit here
826           }
827           else
828           {
829             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
830           }
831         }
832         else
833         {
834           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
835         }
836       }
837       else
838       {
839         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
840       }
841       delete[] config;
842     }
843     else
844     {
845       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
846     }
847   }
848
849
850   // Go S-Video if config says so
851
852   config = vdr->configLoad("TV", "Connection");
853
854   if (config)
855   {
856     if (!STRCASECMP(config, "S-Video"))
857     {
858       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
859       video->setConnection(Video::SVIDEO);
860     } else  if (!STRCASECMP(config, "HDMI"))
861     {
862       logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config);
863       video->setConnection(Video::HDMI);
864     } else  if (!STRCASECMP(config, "HDMI3D"))
865     {
866       logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
867       video->setConnection(Video::HDMI3D);
868     }
869     else
870     {
871       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
872       video->setConnection(Video::COMPOSITERGB);
873     }
874     delete[] config;
875   }
876   else
877   {
878     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
879   }
880
881   // Set to shutdown VDR if config says
882   
883   config = vdr->configLoad("General", "VDR shutdown");
884   if (config)
885   {
886     if (!STRCASECMP(config, "On"))
887     {
888       logger->log("Command", Log::INFO, "Shutdown VDR when shutting down vomp");
889       vdr->setVDRShutdown(true);
890     }
891     else if (!STRCASECMP(config, "Off"))
892     {
893       logger->log("Command", Log::INFO, "Shutdown only vomp");
894       vdr->setVDRShutdown(false);
895     }
896   }
897   else
898   {
899     logger->log("Command", Log::INFO, "Default shutdown only vomp");
900     vdr->setVDRShutdown(false); // Default
901   }
902           
903   // Get TV aspect ratio
904
905   config = vdr->configLoad("TV", "Aspect");
906   if (config)
907   {
908     if (!STRCASECMP(config, "16:9"))
909     {
910       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
911       video->setTVsize(Video::ASPECT16X9);
912     }
913     else
914     {
915       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
916       video->setTVsize(Video::ASPECT4X3);
917     }
918     delete[] config;
919   }
920   else
921   {
922     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
923     video->setTVsize(Video::ASPECT4X3);
924   }
925
926   config = vdr->configLoad("TV", "Widemode");
927   if (config)
928   {
929     if (!STRCASECMP(config, "Letterbox"))
930     {
931       logger->log("Command", Log::INFO, "Setting letterbox mode");
932       video->setMode(Video::LETTERBOX);
933     }
934     else
935     {
936       logger->log("Command", Log::INFO, "Setting chop-sides mode");
937       video->setMode(Video::NORMAL);
938     }
939     delete[] config;
940   }
941   else
942   {
943 #ifdef __ANDROID__
944          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
945          video->setMode(Video::LETTERBOX);
946 #else
947     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
948     video->setMode(Video::NORMAL);
949 #endif
950   }
951
952   config = vdr->configLoad("Advanced", "TCP receive window");
953   if (config)
954   {
955     size_t newTCPsize = atoi(config);
956     delete[] config;
957
958     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
959     vdr->setReceiveWindow(newTCPsize);
960   }
961   else
962   {
963     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
964     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
965   }
966
967   config = vdr->configLoad("Advanced", "Font Name");
968   if (config)
969   {
970         Osd::getInstance()->setFont(config);
971     logger->log("Command", Log::INFO, "Setting Font to %s", config);
972     delete[] config;
973
974   }
975
976
977   // Set recording list type
978
979 #ifdef ADVANCED_MENUES
980   config = vdr->configLoad("Advanced", "Menu type");
981
982   if (config)
983   {
984     if (!STRCASECMP(config, "Advanced"))
985     {
986       logger->log("Command", Log::INFO, "Switching to Advanced menu");
987       advMenus = true;
988     }
989     else
990     {
991       logger->log("Command", Log::INFO, "Switching to Classic menu");
992       advMenus = false;
993     }
994     delete[] config;
995   }
996   else
997   {
998     logger->log("Command", Log::INFO, "Config General/menu type not found");
999     advMenus = true;
1000   }
1001 #endif
1002
1003   config = vdr->configLoad("Advanced", "Disable WOL");
1004   if (config)
1005   {
1006     if (!STRCASECMP(config, "Yes"))
1007     {
1008       logger->log("Command", Log::INFO, "Config says disable WOL");
1009       Wol::getInstance()->setEnabled(false);
1010     }
1011     else
1012     {
1013       logger->log("Command", Log::INFO, "Config says enable WOL");
1014       Wol::getInstance()->setEnabled(true);
1015     }
1016
1017     delete[] config;
1018   }
1019   else
1020   {
1021     logger->log("Command", Log::INFO, "By default, enable WOL");
1022     Wol::getInstance()->setEnabled(true);
1023   }
1024   /* device dependend config */
1025   audio->loadOptionsFromServer(vdr);
1026   video->loadOptionsFromServer(vdr);
1027   inputMan->loadOptionsFromServer(vdr);
1028
1029   video->executePendingModeChanges();
1030   // config done
1031
1032   // Save power state = on
1033
1034   vdr->configSave("General", "Last Power State", "On");
1035
1036   // Make sure connection didn't die
1037   if (!vdr->isConnected())
1038   {
1039     Command::getInstance()->connectionLost();
1040   }
1041   else
1042   {
1043     boxstack->remove(vi);
1044
1045     VWelcome* vw = new VWelcome();
1046     vw->draw();
1047     boxstack->add(vw);
1048     boxstack->update(vw);
1049
1050     // Enter pre-keys here
1051 //    handleCommand(Input::OK);
1052 //    handleCommand(Input::THREE);
1053 //    handleCommand(Input::SIX);
1054 //    handleCommand(Input::OK);
1055 //    handleCommand(Input::UP);
1056 //    handleCommand(Input::PLAY);
1057 //    handleCommand(Input::DOWN);
1058 //    handleCommand(Input::DOWN);
1059 //    handleCommand(Input::DOWN);
1060 //    handleCommand(Input::RIGHT);
1061 //    handleCommand(Input::RED);
1062   }
1063 }