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