]> git.vomp.tv Git - vompclient.git/blob - command.cc
Add recording option to VEpgSummary
[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::NEW_PICTURE:
449       {
450           Log::getInstance()->log("Command", Log::DEBUG, "TVMedia NEW_PICTURE");
451           OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
452           if (osdv) {
453                   osdv->informPicture(m->tag,m->parameter);
454           }
455
456       } break;
457       case Message::NEW_PICTURE_STATIC:
458       {
459           OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
460           if (osdv) {
461                   osdv->informPicture(((long long)m->tag)<<32LL,m->parameter);
462           }
463
464       } break;
465     }
466   }
467   else
468   {
469     /* FIXME
470     
471     Instead of sending through the boxstack, implement a more generic MessageReceiver interface
472     and have potential receivers register with something
473     When a message needs to be delivered, check if the receiver is still registered, if so, deliver the message
474     This could all be done using the existing big command mutex to keep it simple
475     */
476   
477     logger->log("Command", Log::DEBUG, "Sending message to boxstack");
478     boxstack->processMessage(m);
479   }
480 }
481
482 void Command::handleCommand(int button)
483 {
484   if (isStandby && (button != Remote::POWER) 
485       && (button != Remote::POWERON) && (button != Remote::POWEROFF))  return;
486   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
487
488   // command was not handled
489
490   switch(button)
491   {
492     case Remote::DF_LEFT:
493     case Remote::DF_RIGHT:
494     case Remote::VOLUMEUP:
495     case Remote::VOLUMEDOWN:
496     {
497         if (remote->handlesVolume()) {
498                 if (button==Remote::DF_LEFT || button==Remote::VOLUMEDOWN)
499                         remote->volumeDown();
500                 else remote->volumeUp();
501         } else {
502                 VVolume* v = new VVolume();
503                 boxstack->add(v);
504                 v->handleCommand(button); // this will draw+show
505         }
506       return;
507     }
508     case Remote::MUTE:
509     {
510         if (remote->handlesVolume()) {
511                 remote->volumeMute();
512         } else {
513                 VMute* v = new VMute();
514                 v->draw();
515                 boxstack->add(v);
516                 boxstack->update(v);
517         }
518       return;
519     }
520     case Remote::POWER:
521     {
522       doStandby();
523       return;
524     }
525     case Remote::POWERON:
526     {
527       doPowerOn();
528       return;
529     }
530     case Remote::POWEROFF:
531     {
532       doPowerOff();
533       return;
534     }
535     case Remote::OK:
536     {
537       // FIXME
538       if (!connLost) return; // if connLost, handle Remote::OK
539       doFromTheTop(false);
540       return;
541     }
542     case Remote::GO:
543     {
544       VSleeptimer* sleep = new VSleeptimer();
545       boxstack->add(sleep);
546       sleep->handleCommand(button); // this will draw+show
547       return;
548     }
549   }
550 }
551
552 void Command::sig1()
553 {
554 #ifdef DEV
555   Message* m = new Message(); // break into master mutex
556   m->message = Message::SCREENSHOT;
557   m->to = this;
558   postMessage(m);
559 #endif
560 }
561
562 void Command::doStandby()
563 {
564   if (isStandby)
565   {
566     doPowerOn();
567   }
568   else
569   {
570    doPowerOff();
571   }
572 }
573
574
575 void Command::doPowerOn()
576 {
577   if (isStandby)
578   {
579     Video::getInstance()->signalOn();
580     Led::getInstance()->on();
581     Remote::getInstance()->changePowerState(true);
582     isStandby = 0;
583
584
585     VConnect* vconnect = new VConnect(server);
586     boxstack->add(vconnect);
587     vconnect->run();
588   }
589 }
590
591 void Command::doPowerOff()
592 {
593   if (!isStandby)
594   {
595     VDR::getInstance()->shutdownVDR();
596     boxstack->removeAll();
597     Video::getInstance()->signalOff();
598     boxstack->update(wallpaper);
599
600     VDR::getInstance()->configSave("General", "Last Power State", "Off");
601     logger->unsetExternLogger();
602     VDR::getInstance()->disconnect();
603     Led::getInstance()->off();
604     Remote::getInstance()->changePowerState(false);
605     isStandby = 1;
606     Sleeptimer::getInstance()->shutdown();
607 #ifdef WIN32
608     stop(); //different behavoiur on windows, we exit
609 #endif
610   }
611 }
612
613 void Command::doFromTheTop(bool which)
614 {
615   if (isStandby) return;
616   if (which)
617   {
618     if (connLost)
619     {
620       logger->log("Command", Log::NOTICE, "Connection lost dialog already present");
621       return;
622     }
623   
624     logger->log("Command", Log::NOTICE, "Doing connection lost dialog");
625     connLost = new VInfo();
626     connLost->setSize(360, 200);
627     connLost->createBuffer();
628     if (Video::getInstance()->getFormat() == Video::PAL)
629       connLost->setPosition(190, 170);
630     else
631       connLost->setPosition(180, 120);
632     connLost->setOneLiner(tr("Connection lost"));
633     connLost->setDropThrough();
634     connLost->setBorderOn(1);
635     connLost->setTitleBarColour(DrawStyle::DANGER);
636     connLost->okButton();
637     connLost->draw();
638     boxstack->add(connLost);
639     boxstack->update(connLost);
640     remote->clearBuffer();
641   }
642   else
643   {
644     logger->unsetExternLogger();
645     VDR::getInstance()->disconnect();
646     boxstack->removeAll();
647     boxstack->update(wallpaper);
648     connLost = NULL;
649     
650     flushMessageQueue();
651     remote->clearBuffer();
652     
653     // at this point, everything should be reset to first-go
654     
655     VConnect* vconnect = new VConnect(server);
656     boxstack->add(vconnect);
657     vconnect->run();
658   }
659 }
660
661 void Command::doReboot()
662 {
663
664   logger->unsetExternLogger();
665   VDR::getInstance()->disconnect();
666   // just kill it...
667   logger->log("Command", Log::NOTICE, "Reboot");
668 #ifndef WIN32
669 #ifndef VOMP_HAS_EXIT
670   // some plattforms, want a proper deinitialisation of their hardware before reboot
671   Osd::getInstance()->shutdown();
672   Audio::getInstance()->shutdown();
673   Video::getInstance()->shutdown();
674   Remote::getInstance()->shutdown();
675
676   reboot(LINUX_REBOOT_CMD_RESTART);
677   // if  reboot is not allowed -> stop
678   stop();
679
680
681 #else
682   stop();
683
684 #ifdef __ANDROID__
685   exit(0);
686 #endif
687
688 #endif
689 #endif //Would we support this on windows?
690 }
691
692 void Command::connectionLost()
693 {
694   logger->unsetExternLogger();
695   Message* m = new Message(); // break into master mutex
696   m->message = Message::CONNECTION_LOST;
697   m->to = this;
698   postMessageFromOuterSpace(m);
699 }
700
701 void Command::buildCrashedBox()
702 {
703   VInfo* crash = new VInfo();
704   crash->setSize(360, 250);
705   crash->createBuffer();
706   if (Video::getInstance()->getFormat() == Video::PAL)
707     crash->setPosition(190, 146);
708   else
709     crash->setPosition(180, 96);
710   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.");
711   crash->setBorderOn(1);
712   crash->setTitleBarColour(DrawStyle::DANGER);
713   crash->okButton();
714   crash->setExitable();
715   crash->draw();
716   boxstack->add(crash);
717   boxstack->update(crash);
718 }
719
720 void Command::doJustConnected(VConnect* vconnect)
721 {
722   I18n::initialize();
723   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
724   logger->log("Command", Log::INFO, "Entering doJustConnected");
725   
726   Video* video = Video::getInstance();
727   Audio* audio = Audio::getInstance();  
728   boxstack->remove(vconnect);
729
730   VInfo* vi = new VInfo();
731   vi->setSize(400, 200);
732   vi->createBuffer();
733   if (video->getFormat() == Video::PAL)
734     vi->setPosition(170, 200);
735   else
736     vi->setPosition(160, 150);
737   vi->setOneLiner(tr("Connected, loading config"));
738   vi->draw();
739   boxstack->add(vi);
740   boxstack->update(vi);
741
742   VDR* vdr = VDR::getInstance();
743   char* config;
744
745   // See if we're supposed to do network logging
746   config = vdr->configLoad("Advanced", "Network logging");
747   if (config && !STRCASECMP(config, "On"))
748   {
749     logger->log("Command", Log::INFO, "Turning on network logging");
750     logger->setExternLogger(vdr);
751   }  
752   else
753   {
754           logger->unsetExternLogger();
755     logger->log("Command", Log::INFO, "Turned off network logging");
756   }
757   if (config) delete[] config;
758
759   // See if config says to override video format (PAL/NTSC)
760   config = vdr->configLoad("General", "Override Video Format");
761   if (config)
762   {
763     logger->log("Command", Log::DEBUG, "Override Video Format is present");
764
765     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
766         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
767         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
768         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
769         )
770     {
771       // Oh sheesh, need to switch format. Bye bye TV...
772
773       // Take everything down
774       boxstack->removeAll();
775       boxstack->remove(wallpaper);
776       Osd* osd = Osd::getInstance();
777 #ifndef __ANDROID__
778       osd->shutdown();
779 #endif
780       video->shutdown();
781
782       remote->shutdown(); // need on raspberry shut not do any harm, hopefully
783       remote->init(RemoteStartDev);
784
785       // Get video and osd back up with the new mode
786       if (!strcmp(config, "PAL"))
787       {
788         logger->log("Command", Log::DEBUG, "Switching to PAL");
789         video->init(Video::PAL);
790       }
791       else if (!strcmp(config, "NTSC"))
792       {
793         logger->log("Command", Log::DEBUG, "Switching to NTSC");
794         video->init(Video::NTSC);
795       } else if (!strcmp(config, "PAL_M"))
796       {
797         logger->log("Command", Log::DEBUG, "Switching to PAL_M");
798         video->init(Video::PAL_M);
799       } else if (!strcmp(config, "NTSC_J"))
800       {
801         logger->log("Command", Log::DEBUG, "Switching to NTSC_J");
802         video->init(Video::NTSC_J);
803       }
804 #ifndef __ANDROID__
805       //we do not init twice
806       osd->init((char*)("/dev/stbgfx"));
807 #endif
808
809       // Put the wallpaper back
810       doWallpaper();
811
812       // Re add the vinfo
813       vi = new VInfo();
814       vi->setSize(400, 200);
815       vi->createBuffer();
816       if (video->getFormat() == Video::PAL)
817         vi->setPosition(170, 200);
818       else
819         vi->setPosition(160, 150);
820
821       vi->setOneLiner(tr("Connected, loading config"));
822       vi->draw();
823       boxstack->add(vi);
824       boxstack->update(vi);
825     }
826     else
827     {
828       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
829     }
830   }
831   else
832   {
833     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
834   }
835
836   // Power off if first boot and config says so
837   if (firstBoot)
838   {
839     firstBoot = 0;
840
841     logger->log("Command", Log::DEBUG, "Load power after boot");
842
843     config = vdr->configLoad("General", "Power After Boot");
844
845     if (config)
846     {
847       if (!STRCASECMP(config, "On"))
848       {
849         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
850       }
851       else if (!STRCASECMP(config, "Off"))
852       {
853         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
854         doStandby();
855         delete[] config;
856         return; // quit here
857       }
858       else if (!STRCASECMP(config, "Last state"))
859       {
860         char* lastPowerState = vdr->configLoad("General", "Last Power State");
861         if (lastPowerState)
862         {
863           if (!STRCASECMP(lastPowerState, "On"))
864           {
865             logger->log("Command", Log::INFO, "Config says Last Power State = On");
866           }
867           else if (!STRCASECMP(lastPowerState, "Off"))
868           {
869             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
870             doStandby();
871             delete[] config;
872             return; // quit here
873           }
874           else
875           {
876             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
877           }
878         }
879         else
880         {
881           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
882         }
883       }
884       else
885       {
886         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
887       }
888       delete[] config;
889     }
890     else
891     {
892       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
893     }
894   }
895
896
897   // Go S-Video if config says so
898
899   config = vdr->configLoad("TV", "Connection");
900
901   if (config)
902   {
903     if (!STRCASECMP(config, "S-Video"))
904     {
905       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
906       video->setConnection(Video::SVIDEO);
907     } else  if (!STRCASECMP(config, "HDMI"))
908     {
909       logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config);
910       video->setConnection(Video::HDMI);
911     } else  if (!STRCASECMP(config, "HDMI3D"))
912     {
913       logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
914       video->setConnection(Video::HDMI3D);
915     }
916     else
917     {
918       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
919       video->setConnection(Video::COMPOSITERGB);
920     }
921     delete[] config;
922   }
923   else
924   {
925     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
926   }
927
928   // Set to shutdown VDR if config says
929   
930   config = vdr->configLoad("General", "VDR shutdown");
931   if (config)
932   {
933     if (!STRCASECMP(config, "On"))
934     {
935       logger->log("Command", Log::INFO, "Shutdown VDR when  shutting down vomp");
936       vdr->setVDRShutdown(true);
937     }
938     else if (!STRCASECMP(config, "Off"))
939     {
940       logger->log("Command", Log::INFO, "Shutdown only vomp");
941       vdr->setVDRShutdown(false);
942     }
943   }
944   else
945   {
946     logger->log("Command", Log::INFO, "Default shutdown only vomp");
947     vdr->setVDRShutdown(false); // Default
948   }
949           
950   // Set remote type
951
952   config = vdr->configLoad("General", "Remote type");
953
954   if (config)
955   {
956     if (!STRCASECMP(config, "New"))
957     {
958       logger->log("Command", Log::INFO, "Switching to New remote type");
959       remote->setRemoteType(Remote::NEWREMOTE);
960     }
961     else
962     {
963       logger->log("Command", Log::INFO, "Switching to Old remote type");
964       remote->setRemoteType(Remote::OLDREMOTE);
965     }
966     delete[] config;
967   }
968   else
969   {
970     logger->log("Command", Log::INFO, "Config General/Remote type not found");
971     remote->setRemoteType(Remote::OLDREMOTE);
972   }
973
974
975
976   // Get TV aspect ratio
977
978   config = vdr->configLoad("TV", "Aspect");
979   if (config)
980   {
981     if (!STRCASECMP(config, "16:9"))
982     {
983       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
984       video->setTVsize(Video::ASPECT16X9);
985     }
986     else
987     {
988       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
989       video->setTVsize(Video::ASPECT4X3);
990     }
991     delete[] config;
992   }
993   else
994   {
995     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
996     video->setTVsize(Video::ASPECT4X3);
997   }
998
999   config = vdr->configLoad("TV", "Widemode");
1000   if (config)
1001   {
1002     if (!STRCASECMP(config, "Letterbox"))
1003     {
1004       logger->log("Command", Log::INFO, "Setting letterbox mode");
1005       video->setMode(Video::LETTERBOX);
1006     }
1007     else
1008     {
1009       logger->log("Command", Log::INFO, "Setting chop-sides mode");
1010       video->setMode(Video::NORMAL);
1011     }
1012     delete[] config;
1013   }
1014   else
1015   {
1016 #ifdef __ANDROID__
1017          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
1018          video->setMode(Video::LETTERBOX);
1019 #else
1020     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
1021     video->setMode(Video::NORMAL);
1022 #endif
1023   }
1024
1025   config = vdr->configLoad("Advanced", "TCP receive window");
1026   if (config)
1027   {
1028     size_t newTCPsize = atoi(config);
1029     delete[] config;
1030
1031     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
1032     vdr->setReceiveWindow(newTCPsize);
1033   }
1034   else
1035   {
1036     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
1037     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1038   }
1039
1040   config = vdr->configLoad("Advanced", "Font Name");
1041   if (config)
1042   {
1043         Osd::getInstance()->setFont(config);
1044     logger->log("Command", Log::INFO, "Setting Font to %s", config);
1045     delete[] config;
1046
1047   }
1048
1049
1050   // Set recording list type
1051
1052   advmenues=false;
1053 #ifdef    ADVANCED_MENUES
1054   config = vdr->configLoad("Advanced", "Menu type");
1055
1056   if (config)
1057   {
1058           if (!STRCASECMP(config, "Advanced"))
1059           {
1060                   logger->log("Command", Log::INFO, "Switching to Advanced menu");
1061                   advmenues=true;
1062
1063           }
1064           else
1065           {
1066                   logger->log("Command", Log::INFO, "Switching to Classic menu");
1067                   advmenues=false;
1068           }
1069           delete[] config;
1070   }
1071   else
1072   {
1073           logger->log("Command", Log::INFO, "Config General/menu type not found");
1074           advmenues=true;
1075   }
1076 #endif
1077
1078   config = vdr->configLoad("Advanced", "Disable WOL");
1079   if (config)
1080   {
1081     if (!STRCASECMP(config, "Yes"))
1082     {
1083       logger->log("Command", Log::INFO, "Config says disable WOL");
1084       Wol::getInstance()->setEnabled(false);
1085     }
1086     else
1087     {
1088       logger->log("Command", Log::INFO, "Config says enable WOL");
1089       Wol::getInstance()->setEnabled(true);
1090     }
1091
1092     delete[] config;
1093   }
1094   else
1095   {
1096     logger->log("Command", Log::INFO, "By default, enable WOL");
1097     Wol::getInstance()->setEnabled(true);
1098   }
1099   /* device dependend config */
1100   audio->loadOptionsfromServer(vdr);
1101   video->loadOptionsfromServer(vdr);
1102   remote->loadOptionsfromServer(vdr);
1103
1104   video->executePendingModeChanges();
1105   // config done
1106
1107   // Save power state = on
1108
1109   vdr->configSave("General", "Last Power State", "On");
1110
1111   // Make sure connection didn't die
1112   if (!vdr->isConnected())
1113   {
1114     Command::getInstance()->connectionLost();
1115   }
1116   else
1117   {
1118     boxstack->remove(vi);
1119
1120     VWelcome* vw = new VWelcome();
1121     vw->draw();
1122     boxstack->add(vw);
1123     boxstack->update(vw);
1124
1125     // Enter pre-keys here
1126 //    handleCommand(Remote::OK);
1127 //    handleCommand(Remote::THREE);
1128 //    handleCommand(Remote::SIX);
1129 //    handleCommand(Remote::OK);
1130 //    handleCommand(Remote::UP);
1131 //    handleCommand(Remote::PLAY);
1132 //    handleCommand(Remote::DOWN);
1133 //    handleCommand(Remote::DOWN);
1134 //    handleCommand(Remote::DOWN);
1135  //   handleCommand(Remote::OK);
1136 //    handleCommand(Remote::RED);
1137   }
1138 }