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