]> git.vomp.tv Git - vompclient.git/blob - command.cc
Start of new live tv
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "vvideolive.h"
46 #include "vconnect.h"
47 #include "message.h"
48 #include "remote.h"
49 #include "vinfo.h"
50 #include "boxx.h"
51 #include "boxstack.h"
52 #include "log.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       case Message::STANDBY:
357       {
358         doStandby();
359         break;
360       }
361
362
363       // << FIXME OBSELETE
364       case Message::STOP_PLAYBACK:
365       {
366         handleCommand(Remote::STOP); // an odd way of doing it, but so simple
367         break;
368       }
369       case Message::STREAM_END:
370       {
371         VVideoLive::getInstance()->streamEnd();
372         break;
373       }
374       // Also connection_lost comes from player - anywhere else?
375       // FIXME OBSELETE >>
376
377
378       case Message::VDR_CONNECTED:
379       {
380         doJustConnected((VConnect*)m->from);
381         break;
382       }
383       case Message::SCREENSHOT:
384       {
385         Osd::getInstance()->screenShot("/out.jpg");
386         break;
387       }
388       case Message::CONNECTION_LOST:
389       {
390         doFromTheTop(true);
391         break;
392       }
393       case Message::UDP_BUTTON:
394       {
395         handleCommand(m->parameter);
396         break;
397       }
398       case Message::CHANGE_LANGUAGE:
399       {
400         boxstack->removeAll();
401         boxstack->update(wallpaper);
402         I18n::initialize();
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     logger->log("Command", Log::DEBUG, "Sending message to boxstack");
430     boxstack->processMessage(m);
431   }
432 }
433
434 void Command::handleCommand(int button)
435 {
436   if (isStandby && (button != Remote::POWER)) return;
437   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
438
439   // command was not handled
440
441   switch(button)
442   {
443     case Remote::DF_LEFT:
444     case Remote::DF_RIGHT:
445     case Remote::VOLUMEUP:
446     case Remote::VOLUMEDOWN:
447     {
448       VVolume* v = new VVolume();
449       boxstack->add(v);
450       v->handleCommand(button); // this will draw+show
451       return;
452     }
453     case Remote::MUTE:
454     {
455       VMute* v = new VMute();
456       v->draw();
457       boxstack->add(v);
458       boxstack->update(v);
459       return;
460     }
461     case Remote::POWER:
462     {
463       doStandby();
464       return;
465     }
466     case Remote::OK:
467     {
468       // FIXME
469       if (!connLost) return; // if connLost, handle Remote::OK
470       doFromTheTop(false);
471       return;
472     }
473   }
474 }
475
476 void Command::sig1()
477 {
478 #ifdef DEV
479   Message* m = new Message(); // break into master mutex
480   m->message = Message::SCREENSHOT;
481   m->to = this;
482   postMessage(m);
483 #endif
484 }
485
486 void Command::doStandby()
487 {
488   if (isStandby)
489   {
490     Video::getInstance()->signalOn();
491     Led::getInstance()->on();
492     isStandby = 0;
493
494
495     VConnect* vconnect = new VConnect(server);
496     boxstack->add(vconnect);
497     vconnect->run();
498   }
499   else
500   {
501     boxstack->removeAll();
502     Video::getInstance()->signalOff();
503     boxstack->update(wallpaper);
504
505     VDR::getInstance()->configSave("General", "Last Power State", "Off");
506     VDR::getInstance()->disconnect();
507     Led::getInstance()->off();
508     isStandby = 1;
509 #ifdef WIN32
510     stop(); //different behavoiur on windows, we exit
511 #endif
512   }
513 }
514
515 void Command::doFromTheTop(bool which)
516 {
517   if (which)
518   {
519     connLost = new VInfo();
520     connLost->setSize(360, 200);
521     connLost->createBuffer();
522     if (Video::getInstance()->getFormat() == Video::PAL)
523       connLost->setPosition(190, 170);
524     else
525       connLost->setPosition(180, 120);
526     connLost->setOneLiner(tr("Connection lost"));
527     connLost->setDropThrough();
528     connLost->setBorderOn(1);
529     connLost->setTitleBarColour(Colour::DANGER);
530     connLost->okButton();
531     connLost->draw();
532     boxstack->add(connLost);
533     boxstack->update(connLost);
534     remote->clearBuffer();
535   }
536   else
537   {
538     VDR::getInstance()->disconnect();
539     boxstack->removeAll();
540     boxstack->update(wallpaper);
541     connLost = NULL;
542     VConnect* vconnect = new VConnect(server);
543     boxstack->add(vconnect);
544     vconnect->run();
545   }
546 }
547
548 void Command::doReboot()
549 {
550   VDR::getInstance()->disconnect();
551   // just kill it...
552   logger->log("Command", Log::NOTICE, "Reboot");
553 #ifndef WIN32
554   reboot(LINUX_REBOOT_CMD_RESTART);
555 #endif //Would we support this on windows?
556 }
557
558 void Command::connectionLost()
559 {
560   Message* m = new Message(); // break into master mutex
561   m->message = Message::CONNECTION_LOST;
562   m->to = this;
563   postMessageNoLock(m);
564 }
565
566 void Command::buildCrashedBox()
567 {
568   VInfo* crash = new VInfo();
569   crash->setSize(360, 250);
570   crash->createBuffer();
571   if (Video::getInstance()->getFormat() == Video::PAL)
572     crash->setPosition(190, 146);
573   else
574     crash->setPosition(180, 96);
575   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.");
576   crash->setBorderOn(1);
577   crash->setTitleBarColour(Colour::DANGER);
578   crash->okButton();
579   crash->setExitable();
580   crash->draw();
581   boxstack->add(crash);
582   boxstack->update(crash);
583 }
584
585 void Command::doJustConnected(VConnect* vconnect)
586 {
587   I18n::initialize();
588   Video* video = Video::getInstance();
589   Audio* audio = Audio::getInstance();  
590   boxstack->remove(vconnect);
591
592   VInfo* vi = new VInfo();
593   vi->setSize(400, 200);
594   vi->createBuffer();
595   if (video->getFormat() == Video::PAL)
596     vi->setPosition(170, 200);
597   else
598     vi->setPosition(160, 150);
599   vi->setOneLiner(tr("Connected, loading config"));
600   vi->draw();
601   boxstack->add(vi);
602   boxstack->update(vi);
603
604   VDR* vdr = VDR::getInstance();
605   char* config;
606
607   // See if config says to override video format (PAL/NTSC)
608   config = vdr->configLoad("General", "Override Video Format");
609   if (config)
610   {
611     logger->log("Command", Log::DEBUG, "Override Video Format is present");
612
613     if (   (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
614         || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL))  )
615     {
616       // Oh sheesh, need to switch format. Bye bye TV...
617
618       // Take everything down
619       boxstack->removeAll();
620       boxstack->remove(wallpaper);
621       Osd* osd = Osd::getInstance();
622       osd->shutdown();
623       video->shutdown();
624
625       // Get video and osd back up with the new mode
626       if (!strcmp(config, "PAL"))
627       {
628         logger->log("Command", Log::DEBUG, "Switching to PAL");
629         video->init(Video::PAL);
630       }
631       else if (!strcmp(config, "NTSC"))
632       {
633         logger->log("Command", Log::DEBUG, "Switching to NTSC");
634         video->init(Video::NTSC);
635       }
636       osd->init((char*)("/dev/stbgfx"));
637
638       // Put the wallpaper back
639       doWallpaper();
640
641       // Re add the vinfo
642       vi = new VInfo();
643       vi->setSize(400, 200);
644       vi->createBuffer();
645       if (video->getFormat() == Video::PAL)
646         vi->setPosition(170, 200);
647       else
648         vi->setPosition(160, 150);
649
650       vi->setOneLiner(tr("Connected, loading config"));
651       vi->draw();
652       boxstack->add(vi);
653       boxstack->update(vi);
654     }
655     else
656     {
657       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
658     }
659   }
660   else
661   {
662     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
663   }
664
665   // Power off if first boot and config says so
666   if (firstBoot)
667   {
668     firstBoot = 0;
669
670     logger->log("Command", Log::DEBUG, "Load power after boot");
671
672     config = vdr->configLoad("General", "Power After Boot");
673
674     if (config)
675     {
676       if (!STRCASECMP(config, "On"))
677       {
678         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
679       }
680       else if (!STRCASECMP(config, "Off"))
681       {
682         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
683         doStandby();
684         delete[] config;
685         return; // quit here
686       }
687       else if (!STRCASECMP(config, "Last state"))
688       {
689         char* lastPowerState = vdr->configLoad("General", "Last Power State");
690         if (lastPowerState)
691         {
692           if (!STRCASECMP(lastPowerState, "On"))
693           {
694             logger->log("Command", Log::INFO, "Config says Last Power State = On");
695           }
696           else if (!STRCASECMP(lastPowerState, "Off"))
697           {
698             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
699             doStandby();
700             delete[] config;
701             return; // quit here
702           }
703           else
704           {
705             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
706           }
707         }
708         else
709         {
710           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
711         }
712       }
713       else
714       {
715         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
716       }
717       delete[] config;
718     }
719     else
720     {
721       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
722     }
723   }
724
725
726   // Go S-Video if config says so
727
728   config = vdr->configLoad("TV", "Connection");
729
730   if (config)
731   {
732     if (!STRCASECMP(config, "S-Video"))
733     {
734       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
735       video->setConnection(Video::SVIDEO);
736     }
737     else
738     {
739       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
740       video->setConnection(Video::COMPOSITERGB);
741     }
742     delete[] config;
743   }
744   else
745   {
746     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
747   }
748
749   // Set remote type
750
751   config = vdr->configLoad("General", "Remote type");
752
753   if (config)
754   {
755     if (!STRCASECMP(config, "New"))
756     {
757       logger->log("Command", Log::INFO, "Switching to New remote type");
758       remote->setRemoteType(Remote::NEWREMOTE);
759     }
760     else
761     {
762       logger->log("Command", Log::INFO, "Switching to Old remote type");
763       remote->setRemoteType(Remote::OLDREMOTE);
764     }
765     delete[] config;
766   }
767   else
768   {
769     logger->log("Command", Log::INFO, "Config General/Remote type not found");
770     remote->setRemoteType(Remote::OLDREMOTE);
771   }
772
773
774
775
776   // Get TV aspect ratio
777
778   config = vdr->configLoad("TV", "Aspect");
779   if (config)
780   {
781     if (!STRCASECMP(config, "16:9"))
782     {
783       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
784       video->setTVsize(Video::ASPECT16X9);
785     }
786     else
787     {
788       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
789       video->setTVsize(Video::ASPECT4X3);
790     }
791     delete[] config;
792   }
793   else
794   {
795     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
796     video->setTVsize(Video::ASPECT4X3);
797   }
798
799   config = vdr->configLoad("TV", "Widemode");
800   if (config)
801   {
802     if (!STRCASECMP(config, "Letterbox"))
803     {
804       logger->log("Command", Log::INFO, "Setting letterbox mode");
805       video->setMode(Video::LETTERBOX);
806     }
807     else
808     {
809       logger->log("Command", Log::INFO, "Setting chop-sides mode");
810       video->setMode(Video::NORMAL);
811     }
812     delete[] config;
813   }
814   else
815   {
816     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
817     video->setMode(Video::NORMAL);
818   }
819
820   config = vdr->configLoad("Advanced", "TCP receive window");
821   if (config)
822   {
823     size_t newTCPsize = atoi(config);
824     delete[] config;
825
826     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
827     vdr->setReceiveWindow(newTCPsize);
828   }
829   else
830   {
831     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
832     vdr->setReceiveWindow(2048); // Default
833   }
834
835   config = vdr->configLoad("Advanced", "Disable WOL");
836   if (config)
837   {
838     if (!STRCASECMP(config, "Yes"))
839     {
840       logger->log("Command", Log::INFO, "Config says disable WOL");
841       Wol::getInstance()->setEnabled(false);
842     }
843     else
844     {
845       logger->log("Command", Log::INFO, "Config says enable WOL");
846       Wol::getInstance()->setEnabled(true);
847     }
848
849     delete[] config;
850   }
851   else
852   {
853     logger->log("Command", Log::INFO, "By default, enable WOL");
854     Wol::getInstance()->setEnabled(true);
855   }
856   /* device dependend config */
857   audio->loadOptionsfromServer(vdr);
858   video->loadOptionsfromServer(vdr);
859   remote->loadOptionsfromServer(vdr);
860   // config done
861
862   // Save power state = on
863
864   vdr->configSave("General", "Last Power State", "On");
865
866   // Make sure connection didn't die
867   if (!vdr->isConnected())
868   {
869     Command::getInstance()->connectionLost();
870   }
871   else
872   {
873     boxstack->remove(vi);
874
875     VWelcome* vw = new VWelcome();
876     vw->draw();
877     boxstack->add(vw);
878     boxstack->update(vw);
879
880     // Enter pre-keys here
881 //    handleCommand(Remote::THREE);
882 //    handleCommand(Remote::UP);
883 //    handleCommand(Remote::PLAY);
884 //    handleCommand(Remote::DOWN);
885 //    handleCommand(Remote::DOWN);
886 //    handleCommand(Remote::DOWN);
887     handleCommand(Remote::OK);
888     handleCommand(Remote::OK);
889 //    handleCommand(Remote::RED);
890   }
891 }