]> git.vomp.tv Git - vompclient.git/blob - command.cc
Fix typing in channel number in radio list
[vompclient.git] / command.cc
1 /*
2     Copyright 2004-2005 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, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #ifndef WIN32
22 #include <linux/errno.h>
23 #endif
24
25 #include "command.h"
26
27 #ifdef WIN32
28 #include "remotewin.h"
29 #endif
30
31 #ifdef __ANDROID__
32 #include "remoteandroid.h"
33 #endif
34
35 #include "led.h"
36 #include "video.h"
37 #include "audio.h"
38 #include "mtd.h"
39 #include "vdr.h"
40 #include "vvolume.h"
41 #include "vserverselect.h"
42 #include "vwelcome.h"
43 #include "vmute.h"
44 #include "colour.h"
45 #include "osd.h"
46 #include "i18n.h"
47 #include "timerreceiver.h"
48 #include "timers.h"
49 #include "wol.h"
50 #include "vconnect.h"
51 #include "message.h"
52 #include "remote.h"
53 #include "vinfo.h"
54 #include "boxx.h"
55 #include "boxstack.h"
56 #include "log.h"
57 #include "vsleeptimer.h"
58
59
60 Command* Command::instance = NULL;
61
62 Command::Command()
63 {
64   if (instance) return;
65   instance = this;
66   initted = 0;
67   isStandby = 0;
68   firstBoot = 1;
69   connLost = NULL;
70   crashed = false;
71   server = NULL;
72 }
73
74 Command::~Command()
75 {
76   instance = NULL;
77 }
78
79 Command* Command::getInstance()
80 {
81   return instance;
82 }
83
84 int Command::init(bool tcrashed, char* tServer)
85 {
86   if (initted) return 0;
87   initted = 1;
88   crashed = tcrashed;
89   server = tServer;
90
91   logger = Log::getInstance();
92   boxstack = BoxStack::getInstance();
93   remote = Remote::getInstance();
94   
95   remote->InitHWCListwithDefaults();
96   
97   if (!logger || !boxstack || !remote)
98   {
99     initted = 0;
100     return 0;
101   }
102 #ifdef GRADIENT_DRAWING
103   SkinFactory::InitEnhancedSkin();
104 #else
105   SkinFactory::InitDefaultSkin();
106 #endif
107
108 #ifndef WIN32
109   pthread_mutex_init(&masterLock, NULL);
110 #else
111   masterLock=CreateMutex(NULL,FALSE,NULL);
112 #endif
113
114   return 1;
115 }
116
117 int Command::shutdown()
118 {
119   if (!initted) return 0;
120   initted = 0;
121   return 1;
122 }
123
124 void Command::stop()
125 {
126 //  VDR::getInstance()->cancelFindingServer();
127         logger->log("Command", Log::NOTICE, "Command stop1...");
128         
129   udp.shutdown();
130   logger->log("Command", Log::NOTICE,  "Command stop2...");
131   irun = 0;
132 }
133
134 void Command::doWallpaper()
135 {
136   Video* video = Video::getInstance();
137
138   // Blue background
139   Boxx* bbg = new Boxx();
140   bbg->setSize(video->getScreenWidth(), video->getScreenHeight());
141   bbg->createBuffer();
142   bbg->fillColour(DrawStyle::VIDEOBLUE);
143   boxstack->add(bbg);
144   boxstack->update(bbg);
145   boxstack->remove(bbg);
146
147   // Wallpaper
148   WJpeg* wallpaperj = new WJpegTYPE();
149   wallpaperj->setSize(video->getScreenWidth(), video->getScreenHeight());
150   wallpaperj->createBuffer();
151
152   if (video->getFormat() == Video::PAL)
153   {
154     logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
155 #ifndef _MIPS_ARCH    
156     wallpaperj->init("/wallpaperPAL.jpg");
157 #else
158     wallpaperj->init("wallpaperPAL.jpg");
159 #endif
160   }
161   else
162   {
163     logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
164     wallpaperj->init("/wallpaperNTSC.jpg");
165   }
166   wallpaperj->draw();
167
168   boxstack->add(wallpaperj);
169   boxstack->update(wallpaperj);
170
171   wallpaper = wallpaperj;
172 }
173
174 void Command::run()
175 {
176   if (!initted) return;
177   irun = 1;
178 #ifndef WIN32
179   mainPid = getpid();
180 #endif
181
182   // just in case
183   Video::getInstance()->signalOn();
184   Led::getInstance()->on();
185
186   doWallpaper();
187
188   // End of startup. Lock the mutex and put the first view up
189 //  logger->log("Command", Log::DEBUG, "WANT LOCK");
190 #ifndef WIN32
191   pthread_mutex_lock(&masterLock);
192 #else
193   WaitForSingleObject(masterLock, INFINITE );
194 #endif
195   //logger->log("Command", Log::DEBUG, "LOCKED");
196
197   if (crashed)
198   {
199     buildCrashedBox();
200   }
201   else
202   {
203     VConnect* vconnect = new VConnect(server);
204     boxstack->add(vconnect);
205     vconnect->run();
206   }
207
208   // Start method 2 of getting commands in...
209   udp.run(this);
210
211   UCHAR button = 0;
212   while(irun)
213   {
214     // unlock and wait
215     //logger->log("Command", Log::DEBUG, "UNLOCK");
216 #ifndef WIN32
217     pthread_mutex_unlock(&masterLock);
218 #else
219     ReleaseMutex(masterLock);
220 #endif
221         
222     button = remote->getButtonPress(2);  // FIXME why is this set to 2 and not 0? so it can quit 
223     // something happened, lock and process
224         
225     //  logger->log("Command", Log::DEBUG, "WANT LOCK");
226 #ifndef WIN32
227     pthread_mutex_lock(&masterLock);
228 #else
229     WaitForSingleObject(masterLock, INFINITE );
230 #endif
231     // logger->log("Command", Log::DEBUG, "LOCK");
232
233     if ((button == Remote::NA_NONE) /*|| (button == Remote::NA_UNKNOWN)*/) continue;
234
235     if (button != Remote::NA_SIGNAL) handleCommand(button);
236     processMessageQueue();
237
238   }
239
240   //logger->log("Command", Log::DEBUG, "UNLOCK");
241 #ifndef WIN32
242   pthread_mutex_unlock(&masterLock);
243 #else
244   ReleaseMutex(masterLock);
245 #endif
246
247
248 }
249
250 void Command::postMessage(Message* m)
251 {
252   // This is locked here in case the main loop is not waiting for an event, but is processing one
253   // it could be killed but then not react to it because the signal wouldn't cause
254   // remote->getButtonPress to break
255   // locking the mutex ensures that the master thread is waiting on getButtonPress
256
257
258   //logger->log("Command", Log::DEBUG, "WANT LOCK");
259 #ifndef WIN32
260   pthread_mutex_lock(&masterLock);
261 #else
262   WaitForSingleObject(masterLock, INFINITE );
263 #endif
264   //logger->log("Command", Log::DEBUG, "LOCK");
265   MessageQueue::postMessage(m);
266
267 #ifndef WIN32
268 #ifndef __ANDROID__
269   kill(mainPid, SIGURG);
270 #else
271   ((RemoteAndroid*)Remote::getInstance())->Signal();
272 #endif
273   pthread_mutex_unlock(&masterLock);
274 #else
275   ((RemoteWin*)Remote::getInstance())->Signal();
276   ReleaseMutex(masterLock);
277 #endif
278   //logger->log("Command", Log::DEBUG, "UNLOCK");
279 }
280
281 void Command::postMessageNoLock(Message* m)
282 {
283   // As above but use this one if this message is being posted because of a button press
284   // the mutex is already locked, locking around postMessage is not needed as the
285   // queue is guaranteed to be run when the button has been processed
286   MessageQueue::postMessage(m);
287 }
288
289 bool Command::postMessageIfNotBusy(Message* m)
290 {
291   // Used for Windows mouse events
292
293   //logger->log("Command", Log::DEBUG, "TRY LOCK");
294 #ifndef WIN32
295   if (pthread_mutex_trylock(&masterLock) != EBUSY)
296   {
297     //logger->log("Command", Log::DEBUG, "LOCK");
298     MessageQueue::postMessage(m);
299 #ifndef __ANDROID__
300     kill(mainPid, SIGURG);
301 #else
302     ((RemoteAndroid*)Remote::getInstance())->Signal();
303 #endif
304     pthread_mutex_unlock(&masterLock);
305     //logger->log("Command", Log::DEBUG, "UNLOCK");
306     return true;
307   }
308   else
309   {
310     return false;
311   }
312 #else
313   switch (WaitForSingleObject(masterLock, 0 ))
314   { //FIXME this is not "if not busy" check
315     case WAIT_OBJECT_0: //but with proper argument 0 this did not work
316     // case WAIT_ABANDONED:
317     MessageQueue::postMessage(m);
318     ((RemoteWin*)Remote::getInstance())->Signal();
319     ReleaseMutex(masterLock);
320     return true;
321
322     case WAIT_ABANDONED: return false;
323     case WAIT_TIMEOUT: return false;
324   }
325     return false;
326 #endif
327 }
328
329 void Command::postMessageFromOuterSpace(Message* m)
330 {
331   /*
332   Yet another way of getting messages into Command. This one is for events that
333   are not standard button presses (or UDP generated buttons). It is also not for
334   events that are generated as a result of other events (events that can safely
335   call postMessageNoLock and be guaranteed that the message will be processed
336   because it is known that the queue is currently being processed).
337   This is for events that come from outer space and can occur when the master
338   mutex is locked or not, they need to be queued and executed but it doesn't
339   matter when.
340   Actually so far it is for events caused by the video stream - aspect ratio
341   changes. These can occur when the master mutex is locked and so postMessage
342   doesn't work. postMessageNoLock doesn't work because if the mutex *isn't*
343   locked at the time then the message could be sat around a while before
344   being noticed.
345   The whole message system was at first supposed to prevent the problem of
346   calling a function on an object that had just been deleted, by ordering
347   messages such that all calls are done before object deletion. However,
348   because of the new centralised messaging system and the fact that BoxStack
349   locates the destination object before calling it, the messaging system now
350   allows the kind of sloppy calls it was supposed to stop. Weird huh. This
351   is mentioned here because the video stream might generate an event just as
352   the user hits stop. The mutex is locked, and by the time the message
353   is examined the vvideorec/live has been deleted. This doesn't matter because
354   boxstack will drop the message if it can't find the matching object to
355   deliver it to.
356   Finally, all this is fine and dandy, except that I'm not 100% sure that
357   this sloppy postMessage and hope a queued signal will force it to be processed
358   thingy will actually work. Hmmm.
359   Lastly <g>, I will consider making the naming system a little more sane
360   if this works.
361   */
362
363   logger->log("Command", Log::DEBUG, "PMFOS called");
364   MessageQueue::postMessage(m);
365
366 #ifndef WIN32
367 #ifndef __ANDROID__
368   kill(mainPid, SIGURG);
369 #else
370   ((RemoteAndroid*)Remote::getInstance())->Signal();
371 #endif
372 #else
373   ((RemoteWin*)Remote::getInstance())->Signal();
374 #endif
375 }
376
377 void Command::processMessage(Message* m)
378 {
379     // FIXME - a slight modification - how if messagereceivers were to register
380     // themselves as receivers to avoid the calling-a-deleted-object problem
381     // then only deliver/register/unregister would have to be protected
382
383   logger->log("Command", Log::DEBUG, "processing message %i", m->message);
384
385
386   if (m->to == this)
387   {
388     switch(m->message)
389     {
390       // << FIXME OBSELETE
391       case Message::STOP_PLAYBACK:
392       {
393         handleCommand(Remote::STOP); // an odd way of doing it, but so simple
394         break;
395       }
396       // Also connection_lost comes from player - anywhere else?
397       // FIXME OBSELETE >>
398
399
400       case Message::VDR_CONNECTED:
401       {
402         doJustConnected((VConnect*)m->from);
403         break;
404       }
405       case Message::SCREENSHOT:
406       {
407         Osd::getInstance()->screenShot("/out.jpg");
408         break;
409       }
410       case Message::CONNECTION_LOST:
411       {
412         doFromTheTop(true);
413         break;
414       }
415       case Message::UDP_BUTTON:
416       {
417         handleCommand(m->parameter);
418         break;
419       }
420       case Message::CHANGE_LANGUAGE:
421       {
422         boxstack->removeAll();
423         boxstack->update(wallpaper);
424         I18n::initialize();
425         if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
426         VWelcome* vw = new VWelcome();
427         vw->draw();
428         boxstack->add(vw);
429         boxstack->update(vw);
430         break;
431       }
432       case Message::LAST_VIEW_CLOSE:
433       {
434         // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
435         if (crashed)
436         {
437           crashed = false;
438           doFromTheTop(false);        
439         }
440       
441 //        VWelcome* vw = new VWelcome();
442 //        vw->draw();
443 //        boxstack->add(vw);
444 //        boxstack->update(vw);
445
446         break;
447       }
448     }
449   }
450   else
451   {
452     /* FIXME
453     
454     Instead of sending through the boxstack, implement a more generic MessageReceiver interface
455     and have potential receivers register with something
456     When a message needs to be delivered, check if the receiver is still registered, if so, deliver the message
457     This could all be done using the existing big command mutex to keep it simple
458     */
459   
460     logger->log("Command", Log::DEBUG, "Sending message to boxstack");
461     boxstack->processMessage(m);
462   }
463 }
464
465 void Command::handleCommand(int button)
466 {
467   if (isStandby && (button != Remote::POWER)) return;
468   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
469
470   // command was not handled
471
472   switch(button)
473   {
474     case Remote::DF_LEFT:
475     case Remote::DF_RIGHT:
476     case Remote::VOLUMEUP:
477     case Remote::VOLUMEDOWN:
478     {
479         if (remote->handlesVolume()) {
480                 if (button==Remote::DF_LEFT || button==Remote::VOLUMEDOWN)
481                         remote->volumeDown();
482                 else remote->volumeUp();
483         } else {
484                 VVolume* v = new VVolume();
485                 boxstack->add(v);
486                 v->handleCommand(button); // this will draw+show
487         }
488       return;
489     }
490     case Remote::MUTE:
491     {
492         if (remote->handlesVolume()) {
493                 remote->volumeMute();
494         } else {
495                 VMute* v = new VMute();
496                 v->draw();
497                 boxstack->add(v);
498                 boxstack->update(v);
499         }
500       return;
501     }
502     case Remote::POWER:
503     {
504       doStandby();
505       return;
506     }
507     case Remote::OK:
508     {
509       // FIXME
510       if (!connLost) return; // if connLost, handle Remote::OK
511       doFromTheTop(false);
512       return;
513     }
514     case Remote::GO:
515     {
516       VSleeptimer* sleep = new VSleeptimer();
517       boxstack->add(sleep);
518       sleep->handleCommand(button); // this will draw+show
519       return;
520     }
521   }
522 }
523
524 void Command::sig1()
525 {
526 #ifdef DEV
527   Message* m = new Message(); // break into master mutex
528   m->message = Message::SCREENSHOT;
529   m->to = this;
530   postMessage(m);
531 #endif
532 }
533
534 void Command::doStandby()
535 {
536   if (isStandby)
537   {
538     Video::getInstance()->signalOn();
539     Led::getInstance()->on();
540     Remote::getInstance()->changePowerState(true);
541     isStandby = 0;
542
543
544     VConnect* vconnect = new VConnect(server);
545     boxstack->add(vconnect);
546     vconnect->run();
547   }
548   else
549   {
550     VDR::getInstance()->shutdownVDR();
551     boxstack->removeAll();
552     Video::getInstance()->signalOff();
553     boxstack->update(wallpaper);
554
555     VDR::getInstance()->configSave("General", "Last Power State", "Off");
556     logger->unsetExternLogger();
557     VDR::getInstance()->disconnect();
558     Led::getInstance()->off();
559     Remote::getInstance()->changePowerState(false);
560     isStandby = 1;
561     Sleeptimer::getInstance()->shutdown();
562 #ifdef WIN32
563     stop(); //different behavoiur on windows, we exit
564 #endif
565   }
566 }
567
568 void Command::doFromTheTop(bool which)
569 {
570   if (which)
571   {
572     if (connLost)
573     {
574       logger->log("Command", Log::NOTICE, "Connection lost dialog already present");
575       return;
576     }
577   
578     logger->log("Command", Log::NOTICE, "Doing connection lost dialog");
579     connLost = new VInfo();
580     connLost->setSize(360, 200);
581     connLost->createBuffer();
582     if (Video::getInstance()->getFormat() == Video::PAL)
583       connLost->setPosition(190, 170);
584     else
585       connLost->setPosition(180, 120);
586     connLost->setOneLiner(tr("Connection lost"));
587     connLost->setDropThrough();
588     connLost->setBorderOn(1);
589     connLost->setTitleBarColour(DrawStyle::DANGER);
590     connLost->okButton();
591     connLost->draw();
592     boxstack->add(connLost);
593     boxstack->update(connLost);
594     remote->clearBuffer();
595   }
596   else
597   {
598     logger->unsetExternLogger();
599     VDR::getInstance()->disconnect();
600     boxstack->removeAll();
601     boxstack->update(wallpaper);
602     connLost = NULL;
603     
604     flushMessageQueue();
605     remote->clearBuffer();
606     
607     // at this point, everything should be reset to first-go
608     
609     VConnect* vconnect = new VConnect(server);
610     boxstack->add(vconnect);
611     vconnect->run();
612   }
613 }
614
615 void Command::doReboot()
616 {
617
618   logger->unsetExternLogger();
619   VDR::getInstance()->disconnect();
620   // just kill it...
621   logger->log("Command", Log::NOTICE, "Reboot");
622 #ifndef WIN32
623 #ifndef VOMP_HAS_EXIT
624   // some plattforms, want a proper deinitialisation of their hardware before reboot
625   Osd::getInstance()->shutdown();
626   Audio::getInstance()->shutdown();
627   Video::getInstance()->shutdown();
628   Remote::getInstance()->shutdown();
629
630   reboot(LINUX_REBOOT_CMD_RESTART);
631   // if  reboot is not allowed -> stop
632   stop();
633
634
635 #else
636   stop();
637
638 #ifdef __ANDROID__
639   exit(0);
640 #endif
641
642 #endif
643 #endif //Would we support this on windows?
644 }
645
646 void Command::connectionLost()
647 {
648   logger->unsetExternLogger();
649   Message* m = new Message(); // break into master mutex
650   m->message = Message::CONNECTION_LOST;
651   m->to = this;
652   postMessageFromOuterSpace(m);
653 }
654
655 void Command::buildCrashedBox()
656 {
657   VInfo* crash = new VInfo();
658   crash->setSize(360, 250);
659   crash->createBuffer();
660   if (Video::getInstance()->getFormat() == Video::PAL)
661     crash->setPosition(190, 146);
662   else
663     crash->setPosition(180, 96);
664   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.");
665   crash->setBorderOn(1);
666   crash->setTitleBarColour(DrawStyle::DANGER);
667   crash->okButton();
668   crash->setExitable();
669   crash->draw();
670   boxstack->add(crash);
671   boxstack->update(crash);
672 }
673
674 void Command::doJustConnected(VConnect* vconnect)
675 {
676   I18n::initialize();
677   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
678   logger->log("Command", Log::INFO, "Entering doJustConnected");
679   
680   Video* video = Video::getInstance();
681   Audio* audio = Audio::getInstance();  
682   boxstack->remove(vconnect);
683
684   VInfo* vi = new VInfo();
685   vi->setSize(400, 200);
686   vi->createBuffer();
687   if (video->getFormat() == Video::PAL)
688     vi->setPosition(170, 200);
689   else
690     vi->setPosition(160, 150);
691   vi->setOneLiner(tr("Connected, loading config"));
692   vi->draw();
693   boxstack->add(vi);
694   boxstack->update(vi);
695
696   VDR* vdr = VDR::getInstance();
697   char* config;
698
699   // See if we're supposed to do network logging
700   config = vdr->configLoad("Advanced", "Network logging");
701   if (config && !STRCASECMP(config, "On"))
702   {
703     logger->log("Command", Log::INFO, "Turning on network logging");
704     logger->setExternLogger(vdr);
705   }  
706   else
707   {
708           logger->unsetExternLogger();
709     logger->log("Command", Log::INFO, "Turned off network logging");
710   }
711   if (config) delete[] config;
712
713   // See if config says to override video format (PAL/NTSC)
714   config = vdr->configLoad("General", "Override Video Format");
715   if (config)
716   {
717     logger->log("Command", Log::DEBUG, "Override Video Format is present");
718
719     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
720         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
721         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
722         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
723         )
724     {
725       // Oh sheesh, need to switch format. Bye bye TV...
726
727       // Take everything down
728       boxstack->removeAll();
729       boxstack->remove(wallpaper);
730       Osd* osd = Osd::getInstance();
731 #ifndef __ANDROID__
732       osd->shutdown();
733 #endif
734       video->shutdown();
735
736       remote->shutdown(); // need on raspberry shut not do any harm, hopefully
737       remote->init(RemoteStartDev);
738
739       // Get video and osd back up with the new mode
740       if (!strcmp(config, "PAL"))
741       {
742         logger->log("Command", Log::DEBUG, "Switching to PAL");
743         video->init(Video::PAL);
744       }
745       else if (!strcmp(config, "NTSC"))
746       {
747         logger->log("Command", Log::DEBUG, "Switching to NTSC");
748         video->init(Video::NTSC);
749       } else if (!strcmp(config, "PAL_M"))
750       {
751         logger->log("Command", Log::DEBUG, "Switching to PAL_M");
752         video->init(Video::PAL_M);
753       } else if (!strcmp(config, "NTSC_J"))
754       {
755         logger->log("Command", Log::DEBUG, "Switching to NTSC_J");
756         video->init(Video::NTSC_J);
757       }
758 #ifndef __ANDROID__
759       //we do not init twice
760       osd->init((char*)("/dev/stbgfx"));
761 #endif
762
763       // Put the wallpaper back
764       doWallpaper();
765
766       // Re add the vinfo
767       vi = new VInfo();
768       vi->setSize(400, 200);
769       vi->createBuffer();
770       if (video->getFormat() == Video::PAL)
771         vi->setPosition(170, 200);
772       else
773         vi->setPosition(160, 150);
774
775       vi->setOneLiner(tr("Connected, loading config"));
776       vi->draw();
777       boxstack->add(vi);
778       boxstack->update(vi);
779     }
780     else
781     {
782       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
783     }
784   }
785   else
786   {
787     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
788   }
789
790   // Power off if first boot and config says so
791   if (firstBoot)
792   {
793     firstBoot = 0;
794
795     logger->log("Command", Log::DEBUG, "Load power after boot");
796
797     config = vdr->configLoad("General", "Power After Boot");
798
799     if (config)
800     {
801       if (!STRCASECMP(config, "On"))
802       {
803         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
804       }
805       else if (!STRCASECMP(config, "Off"))
806       {
807         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
808         doStandby();
809         delete[] config;
810         return; // quit here
811       }
812       else if (!STRCASECMP(config, "Last state"))
813       {
814         char* lastPowerState = vdr->configLoad("General", "Last Power State");
815         if (lastPowerState)
816         {
817           if (!STRCASECMP(lastPowerState, "On"))
818           {
819             logger->log("Command", Log::INFO, "Config says Last Power State = On");
820           }
821           else if (!STRCASECMP(lastPowerState, "Off"))
822           {
823             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
824             doStandby();
825             delete[] config;
826             return; // quit here
827           }
828           else
829           {
830             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
831           }
832         }
833         else
834         {
835           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
836         }
837       }
838       else
839       {
840         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
841       }
842       delete[] config;
843     }
844     else
845     {
846       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
847     }
848   }
849
850
851   // Go S-Video if config says so
852
853   config = vdr->configLoad("TV", "Connection");
854
855   if (config)
856   {
857     if (!STRCASECMP(config, "S-Video"))
858     {
859       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
860       video->setConnection(Video::SVIDEO);
861     } else  if (!STRCASECMP(config, "HDMI"))
862     {
863       logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config);
864       video->setConnection(Video::HDMI);
865     } else  if (!STRCASECMP(config, "HDMI3D"))
866     {
867       logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
868       video->setConnection(Video::HDMI3D);
869     }
870     else
871     {
872       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
873       video->setConnection(Video::COMPOSITERGB);
874     }
875     delete[] config;
876   }
877   else
878   {
879     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
880   }
881
882   // Set to shutdown VDR if config says
883   
884   config = vdr->configLoad("General", "VDR shutdown");
885   if (config)
886   {
887     if (!STRCASECMP(config, "On"))
888     {
889       logger->log("Command", Log::INFO, "Shutdown VDR when  shutting down vomp");
890       vdr->setVDRShutdown(true);
891     }
892     else if (!STRCASECMP(config, "Off"))
893     {
894       logger->log("Command", Log::INFO, "Shutdown only vomp");
895       vdr->setVDRShutdown(false);
896     }
897   }
898   else
899   {
900     logger->log("Command", Log::INFO, "Default shutdown only vomp");
901     vdr->setVDRShutdown(false); // Default
902   }
903           
904   // Set remote type
905
906   config = vdr->configLoad("General", "Remote type");
907
908   if (config)
909   {
910     if (!STRCASECMP(config, "New"))
911     {
912       logger->log("Command", Log::INFO, "Switching to New remote type");
913       remote->setRemoteType(Remote::NEWREMOTE);
914     }
915     else
916     {
917       logger->log("Command", Log::INFO, "Switching to Old remote type");
918       remote->setRemoteType(Remote::OLDREMOTE);
919     }
920     delete[] config;
921   }
922   else
923   {
924     logger->log("Command", Log::INFO, "Config General/Remote type not found");
925     remote->setRemoteType(Remote::OLDREMOTE);
926   }
927
928
929
930
931   // Get TV aspect ratio
932
933   config = vdr->configLoad("TV", "Aspect");
934   if (config)
935   {
936     if (!STRCASECMP(config, "16:9"))
937     {
938       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
939       video->setTVsize(Video::ASPECT16X9);
940     }
941     else
942     {
943       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
944       video->setTVsize(Video::ASPECT4X3);
945     }
946     delete[] config;
947   }
948   else
949   {
950     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
951     video->setTVsize(Video::ASPECT4X3);
952   }
953
954   config = vdr->configLoad("TV", "Widemode");
955   if (config)
956   {
957     if (!STRCASECMP(config, "Letterbox"))
958     {
959       logger->log("Command", Log::INFO, "Setting letterbox mode");
960       video->setMode(Video::LETTERBOX);
961     }
962     else
963     {
964       logger->log("Command", Log::INFO, "Setting chop-sides mode");
965       video->setMode(Video::NORMAL);
966     }
967     delete[] config;
968   }
969   else
970   {
971 #ifdef __ANDROID__
972          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
973          video->setMode(Video::LETTERBOX);
974 #else
975     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
976     video->setMode(Video::NORMAL);
977 #endif
978   }
979
980   config = vdr->configLoad("Advanced", "TCP receive window");
981   if (config)
982   {
983     size_t newTCPsize = atoi(config);
984     delete[] config;
985
986     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
987     vdr->setReceiveWindow(newTCPsize);
988   }
989   else
990   {
991     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
992     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
993   }
994
995   config = vdr->configLoad("Advanced", "Font Name");
996   if (config)
997   {
998         Osd::getInstance()->setFont(config);
999     logger->log("Command", Log::INFO, "Setting Font to %s", config);
1000     delete[] config;
1001
1002   }
1003
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   remote->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(Remote::OK);
1054 //    handleCommand(Remote::THREE);
1055 //    handleCommand(Remote::SIX);
1056 //    handleCommand(Remote::OK);
1057 //    handleCommand(Remote::UP);
1058 //    handleCommand(Remote::PLAY);
1059 //    handleCommand(Remote::DOWN);
1060 //    handleCommand(Remote::DOWN);
1061 //    handleCommand(Remote::DOWN);
1062  //   handleCommand(Remote::OK);
1063 //    handleCommand(Remote::RED);
1064   }
1065 }