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