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