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