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