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