]> git.vomp.tv Git - vompclient-marten.git/blob - command.cc
Improve cec handling in remote linux
[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 #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::POWERON:
508     {
509       doPowerOn();
510       return;
511     }
512     case Remote::POWEROFF:
513     {
514       doPowerOff();
515       return;
516     }
517     case Remote::OK:
518     {
519       // FIXME
520       if (!connLost) return; // if connLost, handle Remote::OK
521       doFromTheTop(false);
522       return;
523     }
524     case Remote::GO:
525     {
526       VSleeptimer* sleep = new VSleeptimer();
527       boxstack->add(sleep);
528       sleep->handleCommand(button); // this will draw+show
529       return;
530     }
531   }
532 }
533
534 void Command::sig1()
535 {
536 #ifdef DEV
537   Message* m = new Message(); // break into master mutex
538   m->message = Message::SCREENSHOT;
539   m->to = this;
540   postMessage(m);
541 #endif
542 }
543
544 void Command::doStandby()
545 {
546   if (isStandby)
547   {
548     doPowerOn();
549   }
550   else
551   {
552    doPowerOff();
553   }
554 }
555
556
557 void Command::doPowerOn()
558 {
559   if (isStandby)
560   {
561     Video::getInstance()->signalOn();
562     Led::getInstance()->on();
563     Remote::getInstance()->changePowerState(true);
564     isStandby = 0;
565
566
567     VConnect* vconnect = new VConnect(server);
568     boxstack->add(vconnect);
569     vconnect->run();
570   }
571 }
572
573 void Command::doPowerOff()
574 {
575   if (!isStandby)
576   {
577     VDR::getInstance()->shutdownVDR();
578     boxstack->removeAll();
579     Video::getInstance()->signalOff();
580     boxstack->update(wallpaper);
581
582     VDR::getInstance()->configSave("General", "Last Power State", "Off");
583     logger->unsetExternLogger();
584     VDR::getInstance()->disconnect();
585     Led::getInstance()->off();
586     Remote::getInstance()->changePowerState(false);
587     isStandby = 1;
588     Sleeptimer::getInstance()->shutdown();
589 #ifdef WIN32
590     stop(); //different behavoiur on windows, we exit
591 #endif
592   }
593 }
594
595 void Command::doFromTheTop(bool which)
596 {
597   if (which)
598   {
599     if (connLost)
600     {
601       logger->log("Command", Log::NOTICE, "Connection lost dialog already present");
602       return;
603     }
604   
605     logger->log("Command", Log::NOTICE, "Doing connection lost dialog");
606     connLost = new VInfo();
607     connLost->setSize(360, 200);
608     connLost->createBuffer();
609     if (Video::getInstance()->getFormat() == Video::PAL)
610       connLost->setPosition(190, 170);
611     else
612       connLost->setPosition(180, 120);
613     connLost->setOneLiner(tr("Connection lost"));
614     connLost->setDropThrough();
615     connLost->setBorderOn(1);
616     connLost->setTitleBarColour(DrawStyle::DANGER);
617     connLost->okButton();
618     connLost->draw();
619     boxstack->add(connLost);
620     boxstack->update(connLost);
621     remote->clearBuffer();
622   }
623   else
624   {
625     logger->unsetExternLogger();
626     VDR::getInstance()->disconnect();
627     boxstack->removeAll();
628     boxstack->update(wallpaper);
629     connLost = NULL;
630     
631     flushMessageQueue();
632     remote->clearBuffer();
633     
634     // at this point, everything should be reset to first-go
635     
636     VConnect* vconnect = new VConnect(server);
637     boxstack->add(vconnect);
638     vconnect->run();
639   }
640 }
641
642 void Command::doReboot()
643 {
644
645   logger->unsetExternLogger();
646   VDR::getInstance()->disconnect();
647   // just kill it...
648   logger->log("Command", Log::NOTICE, "Reboot");
649 #ifndef WIN32
650 #ifndef VOMP_HAS_EXIT
651   // some plattforms, want a proper deinitialisation of their hardware before reboot
652   Osd::getInstance()->shutdown();
653   Audio::getInstance()->shutdown();
654   Video::getInstance()->shutdown();
655   Remote::getInstance()->shutdown();
656
657   reboot(LINUX_REBOOT_CMD_RESTART);
658   // if  reboot is not allowed -> stop
659   stop();
660
661
662 #else
663   stop();
664
665 #ifdef __ANDROID__
666   exit(0);
667 #endif
668
669 #endif
670 #endif //Would we support this on windows?
671 }
672
673 void Command::connectionLost()
674 {
675   logger->unsetExternLogger();
676   Message* m = new Message(); // break into master mutex
677   m->message = Message::CONNECTION_LOST;
678   m->to = this;
679   postMessageFromOuterSpace(m);
680 }
681
682 void Command::buildCrashedBox()
683 {
684   VInfo* crash = new VInfo();
685   crash->setSize(360, 250);
686   crash->createBuffer();
687   if (Video::getInstance()->getFormat() == Video::PAL)
688     crash->setPosition(190, 146);
689   else
690     crash->setPosition(180, 96);
691   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.");
692   crash->setBorderOn(1);
693   crash->setTitleBarColour(DrawStyle::DANGER);
694   crash->okButton();
695   crash->setExitable();
696   crash->draw();
697   boxstack->add(crash);
698   boxstack->update(crash);
699 }
700
701 void Command::doJustConnected(VConnect* vconnect)
702 {
703   I18n::initialize();
704   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
705   logger->log("Command", Log::INFO, "Entering doJustConnected");
706   
707   Video* video = Video::getInstance();
708   Audio* audio = Audio::getInstance();  
709   boxstack->remove(vconnect);
710
711   VInfo* vi = new VInfo();
712   vi->setSize(400, 200);
713   vi->createBuffer();
714   if (video->getFormat() == Video::PAL)
715     vi->setPosition(170, 200);
716   else
717     vi->setPosition(160, 150);
718   vi->setOneLiner(tr("Connected, loading config"));
719   vi->draw();
720   boxstack->add(vi);
721   boxstack->update(vi);
722
723   VDR* vdr = VDR::getInstance();
724   char* config;
725
726   // See if we're supposed to do network logging
727   config = vdr->configLoad("Advanced", "Network logging");
728   if (config && !STRCASECMP(config, "On"))
729   {
730     logger->log("Command", Log::INFO, "Turning on network logging");
731     logger->setExternLogger(vdr);
732   }  
733   else
734   {
735           logger->unsetExternLogger();
736     logger->log("Command", Log::INFO, "Turned off network logging");
737   }
738   if (config) delete[] config;
739
740   // See if config says to override video format (PAL/NTSC)
741   config = vdr->configLoad("General", "Override Video Format");
742   if (config)
743   {
744     logger->log("Command", Log::DEBUG, "Override Video Format is present");
745
746     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
747         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
748         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
749         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
750         )
751     {
752       // Oh sheesh, need to switch format. Bye bye TV...
753
754       // Take everything down
755       boxstack->removeAll();
756       boxstack->remove(wallpaper);
757       Osd* osd = Osd::getInstance();
758 #ifndef __ANDROID__
759       osd->shutdown();
760 #endif
761       video->shutdown();
762
763       remote->shutdown(); // need on raspberry shut not do any harm, hopefully
764       remote->init(RemoteStartDev);
765
766       // Get video and osd back up with the new mode
767       if (!strcmp(config, "PAL"))
768       {
769         logger->log("Command", Log::DEBUG, "Switching to PAL");
770         video->init(Video::PAL);
771       }
772       else if (!strcmp(config, "NTSC"))
773       {
774         logger->log("Command", Log::DEBUG, "Switching to NTSC");
775         video->init(Video::NTSC);
776       } else if (!strcmp(config, "PAL_M"))
777       {
778         logger->log("Command", Log::DEBUG, "Switching to PAL_M");
779         video->init(Video::PAL_M);
780       } else if (!strcmp(config, "NTSC_J"))
781       {
782         logger->log("Command", Log::DEBUG, "Switching to NTSC_J");
783         video->init(Video::NTSC_J);
784       }
785 #ifndef __ANDROID__
786       //we do not init twice
787       osd->init((char*)("/dev/stbgfx"));
788 #endif
789
790       // Put the wallpaper back
791       doWallpaper();
792
793       // Re add the vinfo
794       vi = new VInfo();
795       vi->setSize(400, 200);
796       vi->createBuffer();
797       if (video->getFormat() == Video::PAL)
798         vi->setPosition(170, 200);
799       else
800         vi->setPosition(160, 150);
801
802       vi->setOneLiner(tr("Connected, loading config"));
803       vi->draw();
804       boxstack->add(vi);
805       boxstack->update(vi);
806     }
807     else
808     {
809       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
810     }
811   }
812   else
813   {
814     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
815   }
816
817   // Power off if first boot and config says so
818   if (firstBoot)
819   {
820     firstBoot = 0;
821
822     logger->log("Command", Log::DEBUG, "Load power after boot");
823
824     config = vdr->configLoad("General", "Power After Boot");
825
826     if (config)
827     {
828       if (!STRCASECMP(config, "On"))
829       {
830         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
831       }
832       else if (!STRCASECMP(config, "Off"))
833       {
834         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
835         doStandby();
836         delete[] config;
837         return; // quit here
838       }
839       else if (!STRCASECMP(config, "Last state"))
840       {
841         char* lastPowerState = vdr->configLoad("General", "Last Power State");
842         if (lastPowerState)
843         {
844           if (!STRCASECMP(lastPowerState, "On"))
845           {
846             logger->log("Command", Log::INFO, "Config says Last Power State = On");
847           }
848           else if (!STRCASECMP(lastPowerState, "Off"))
849           {
850             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
851             doStandby();
852             delete[] config;
853             return; // quit here
854           }
855           else
856           {
857             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
858           }
859         }
860         else
861         {
862           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
863         }
864       }
865       else
866       {
867         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
868       }
869       delete[] config;
870     }
871     else
872     {
873       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
874     }
875   }
876
877
878   // Go S-Video if config says so
879
880   config = vdr->configLoad("TV", "Connection");
881
882   if (config)
883   {
884     if (!STRCASECMP(config, "S-Video"))
885     {
886       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
887       video->setConnection(Video::SVIDEO);
888     } else  if (!STRCASECMP(config, "HDMI"))
889     {
890       logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config);
891       video->setConnection(Video::HDMI);
892     } else  if (!STRCASECMP(config, "HDMI3D"))
893     {
894       logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
895       video->setConnection(Video::HDMI3D);
896     }
897     else
898     {
899       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
900       video->setConnection(Video::COMPOSITERGB);
901     }
902     delete[] config;
903   }
904   else
905   {
906     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
907   }
908
909   // Set to shutdown VDR if config says
910   
911   config = vdr->configLoad("General", "VDR shutdown");
912   if (config)
913   {
914     if (!STRCASECMP(config, "On"))
915     {
916       logger->log("Command", Log::INFO, "Shutdown VDR when  shutting down vomp");
917       vdr->setVDRShutdown(true);
918     }
919     else if (!STRCASECMP(config, "Off"))
920     {
921       logger->log("Command", Log::INFO, "Shutdown only vomp");
922       vdr->setVDRShutdown(false);
923     }
924   }
925   else
926   {
927     logger->log("Command", Log::INFO, "Default shutdown only vomp");
928     vdr->setVDRShutdown(false); // Default
929   }
930           
931   // Set remote type
932
933   config = vdr->configLoad("General", "Remote type");
934
935   if (config)
936   {
937     if (!STRCASECMP(config, "New"))
938     {
939       logger->log("Command", Log::INFO, "Switching to New remote type");
940       remote->setRemoteType(Remote::NEWREMOTE);
941     }
942     else
943     {
944       logger->log("Command", Log::INFO, "Switching to Old remote type");
945       remote->setRemoteType(Remote::OLDREMOTE);
946     }
947     delete[] config;
948   }
949   else
950   {
951     logger->log("Command", Log::INFO, "Config General/Remote type not found");
952     remote->setRemoteType(Remote::OLDREMOTE);
953   }
954
955
956
957
958   // Get TV aspect ratio
959
960   config = vdr->configLoad("TV", "Aspect");
961   if (config)
962   {
963     if (!STRCASECMP(config, "16:9"))
964     {
965       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
966       video->setTVsize(Video::ASPECT16X9);
967     }
968     else
969     {
970       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
971       video->setTVsize(Video::ASPECT4X3);
972     }
973     delete[] config;
974   }
975   else
976   {
977     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
978     video->setTVsize(Video::ASPECT4X3);
979   }
980
981   config = vdr->configLoad("TV", "Widemode");
982   if (config)
983   {
984     if (!STRCASECMP(config, "Letterbox"))
985     {
986       logger->log("Command", Log::INFO, "Setting letterbox mode");
987       video->setMode(Video::LETTERBOX);
988     }
989     else
990     {
991       logger->log("Command", Log::INFO, "Setting chop-sides mode");
992       video->setMode(Video::NORMAL);
993     }
994     delete[] config;
995   }
996   else
997   {
998 #ifdef __ANDROID__
999          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
1000          video->setMode(Video::LETTERBOX);
1001 #else
1002     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
1003     video->setMode(Video::NORMAL);
1004 #endif
1005   }
1006
1007   config = vdr->configLoad("Advanced", "TCP receive window");
1008   if (config)
1009   {
1010     size_t newTCPsize = atoi(config);
1011     delete[] config;
1012
1013     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
1014     vdr->setReceiveWindow(newTCPsize);
1015   }
1016   else
1017   {
1018     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
1019     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1020   }
1021
1022   config = vdr->configLoad("Advanced", "Font Name");
1023   if (config)
1024   {
1025         Osd::getInstance()->setFont(config);
1026     logger->log("Command", Log::INFO, "Setting Font to %s", config);
1027     delete[] config;
1028
1029   }
1030
1031
1032   config = vdr->configLoad("Advanced", "Disable WOL");
1033   if (config)
1034   {
1035     if (!STRCASECMP(config, "Yes"))
1036     {
1037       logger->log("Command", Log::INFO, "Config says disable WOL");
1038       Wol::getInstance()->setEnabled(false);
1039     }
1040     else
1041     {
1042       logger->log("Command", Log::INFO, "Config says enable WOL");
1043       Wol::getInstance()->setEnabled(true);
1044     }
1045
1046     delete[] config;
1047   }
1048   else
1049   {
1050     logger->log("Command", Log::INFO, "By default, enable WOL");
1051     Wol::getInstance()->setEnabled(true);
1052   }
1053   /* device dependend config */
1054   audio->loadOptionsfromServer(vdr);
1055   video->loadOptionsfromServer(vdr);
1056   remote->loadOptionsfromServer(vdr);
1057
1058   video->executePendingModeChanges();
1059   // config done
1060
1061   // Save power state = on
1062
1063   vdr->configSave("General", "Last Power State", "On");
1064
1065   // Make sure connection didn't die
1066   if (!vdr->isConnected())
1067   {
1068     Command::getInstance()->connectionLost();
1069   }
1070   else
1071   {
1072     boxstack->remove(vi);
1073
1074     VWelcome* vw = new VWelcome();
1075     vw->draw();
1076     boxstack->add(vw);
1077     boxstack->update(vw);
1078
1079     // Enter pre-keys here
1080 //    handleCommand(Remote::OK);
1081 //    handleCommand(Remote::THREE);
1082 //    handleCommand(Remote::SIX);
1083 //    handleCommand(Remote::OK);
1084 //    handleCommand(Remote::UP);
1085 //    handleCommand(Remote::PLAY);
1086 //    handleCommand(Remote::DOWN);
1087 //    handleCommand(Remote::DOWN);
1088 //    handleCommand(Remote::DOWN);
1089  //   handleCommand(Remote::OK);
1090 //    handleCommand(Remote::RED);
1091   }
1092 }