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