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