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