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