]> git.vomp.tv Git - vompclient.git/blob - command.cc
Add channel status icons
[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 int Command::getLangPref(bool subtitle,const char* langcode)
741 {
742         vector<struct ASLPref>::iterator itty=langcodes.begin();
743         char templangcode[4];
744         templangcode[0]=langcode[0];
745         templangcode[1]=langcode[1];
746         templangcode[2]=langcode[2];
747         templangcode[3]='\0';
748         int langpos =0;
749         while (itty != langcodes.end()) {
750                 size_t pos=(*itty).langcode.find(templangcode);
751                 if (pos != string::npos) {
752                         vector<struct ASLPref>::iterator itty2=langcodes.begin();
753                         for (int i=0; i<langcodes.size();i++) {
754                                 int pref=-1;
755                                 if (subtitle) {
756                                         pref=langcodes[i].subtitlepref;
757                                 } else {
758                                         pref=langcodes[i].audiopref;
759                                 }
760                                 if (pref < -1) break;
761
762                                 if (langcodes[i].audiopref==langpos) {
763                                         return i;
764                                 }
765                         }
766                         break;
767                 }
768                 itty++;
769                 langpos++;
770         }
771         return langcodes.size(); //neutral
772 }
773
774 void Command::doJustConnected(VConnect* vconnect)
775 {
776   I18n::initialize();
777   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
778   logger->log("Command", Log::INFO, "Entering doJustConnected");
779   
780   Video* video = Video::getInstance();
781   Audio* audio = Audio::getInstance();  
782   boxstack->remove(vconnect);
783
784   VInfo* vi = new VInfo();
785   vi->setSize(400, 200);
786   vi->createBuffer();
787   if (video->getFormat() == Video::PAL)
788     vi->setPosition(170, 200);
789   else
790     vi->setPosition(160, 150);
791   vi->setOneLiner(tr("Connected, loading config"));
792   vi->draw();
793   boxstack->add(vi);
794   boxstack->update(vi);
795
796   VDR* vdr = VDR::getInstance();
797   char* config;
798
799   // See if we're supposed to do network logging
800   config = vdr->configLoad("Advanced", "Network logging");
801   if (config && !STRCASECMP(config, "On"))
802   {
803     logger->log("Command", Log::INFO, "Turning on network logging");
804     logger->setExternLogger(vdr);
805   }  
806   else
807   {
808           logger->unsetExternLogger();
809     logger->log("Command", Log::INFO, "Turned off network logging");
810   }
811   if (config) delete[] config;
812
813   config = vdr->configLoad("Advanced", "Skin Name");
814   if (config) {
815           const char **skinnames=SkinFactory::getSkinNames();
816           for (int i=0;i<SkinFactory::getNumberofSkins();i++) {
817                   if (!STRCASECMP(config, skinnames[i])) {
818                           SkinFactory::InitSkin(i);
819                           break;
820                   }
821           }
822           delete[] config;
823           if (wallpaper && wallpaper_pict) {
824                   if (DrawStyle::WALLPAPER.alpha) {
825                           wallpaper_pict->setVisible(true);
826                   } else {
827                           wallpaper_pict->setVisible(false);
828                   }
829                   wallpaper->draw();
830                   boxstack->update(wallpaper);
831           }
832
833   } else {
834           SkinFactory::InitSkin(0);
835   }
836
837   // See if config says to override video format (PAL/NTSC)
838   config = vdr->configLoad("General", "Override Video Format");
839   if (config)
840   {
841     logger->log("Command", Log::DEBUG, "Override Video Format is present");
842
843     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
844         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
845         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
846         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
847         )
848     {
849       // Oh sheesh, need to switch format. Bye bye TV...
850
851       // Take everything down
852       boxstack->removeAll();
853       boxstack->remove(wallpaper);
854       Osd* osd = Osd::getInstance();
855 #ifndef __ANDROID__
856       osd->shutdown();
857 #endif
858       video->shutdown();
859
860       remote->shutdown(); // need on raspberry shut not do any harm, hopefully
861       remote->init(RemoteStartDev);
862
863       // Get video and osd back up with the new mode
864       if (!strcmp(config, "PAL"))
865       {
866         logger->log("Command", Log::DEBUG, "Switching to PAL");
867         video->init(Video::PAL);
868       }
869       else if (!strcmp(config, "NTSC"))
870       {
871         logger->log("Command", Log::DEBUG, "Switching to NTSC");
872         video->init(Video::NTSC);
873       } else if (!strcmp(config, "PAL_M"))
874       {
875         logger->log("Command", Log::DEBUG, "Switching to PAL_M");
876         video->init(Video::PAL_M);
877       } else if (!strcmp(config, "NTSC_J"))
878       {
879         logger->log("Command", Log::DEBUG, "Switching to NTSC_J");
880         video->init(Video::NTSC_J);
881       }
882       delete[] config;
883
884 #ifndef __ANDROID__
885       //we do not init twice
886       osd->init((char*)("/dev/stbgfx"));
887 #endif
888
889       // Put the wallpaper back
890       doWallpaper();
891
892       // Re add the vinfo
893       vi = new VInfo();
894       vi->setSize(400, 200);
895       vi->createBuffer();
896       if (video->getFormat() == Video::PAL)
897         vi->setPosition(170, 200);
898       else
899         vi->setPosition(160, 150);
900
901       vi->setOneLiner(tr("Connected, loading config"));
902       vi->draw();
903       boxstack->add(vi);
904       boxstack->update(vi);
905     }
906     else
907     {
908       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
909     }
910   }
911   else
912   {
913     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
914   }
915
916   // Power off if first boot and config says so
917   if (firstBoot)
918   {
919     firstBoot = 0;
920
921     logger->log("Command", Log::DEBUG, "Load power after boot");
922
923     config = vdr->configLoad("General", "Power After Boot");
924
925     if (config)
926     {
927       if (!STRCASECMP(config, "On"))
928       {
929         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
930       }
931       else if (!STRCASECMP(config, "Off"))
932       {
933         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
934         doStandby();
935         delete[] config;
936         return; // quit here
937       }
938       else if (!STRCASECMP(config, "Last state"))
939       {
940         char* lastPowerState = vdr->configLoad("General", "Last Power State");
941         if (lastPowerState)
942         {
943           if (!STRCASECMP(lastPowerState, "On"))
944           {
945             logger->log("Command", Log::INFO, "Config says Last Power State = On");
946           }
947           else if (!STRCASECMP(lastPowerState, "Off"))
948           {
949             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
950             doStandby();
951             delete[] config;
952             return; // quit here
953           }
954           else
955           {
956             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
957           }
958         }
959         else
960         {
961           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
962         }
963       }
964       else
965       {
966         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
967       }
968       delete[] config;
969     }
970     else
971     {
972       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
973     }
974   }
975
976
977   // Go S-Video if config says so
978
979   config = vdr->configLoad("TV", "Connection");
980
981   if (config)
982   {
983     if (!STRCASECMP(config, "S-Video"))
984     {
985       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
986       video->setConnection(Video::SVIDEO);
987     } else  if (!STRCASECMP(config, "HDMI"))
988     {
989       logger->log("Command", Log::INFO, "Switching to HDMI as Connection=%s", config);
990       video->setConnection(Video::HDMI);
991     } else  if (!STRCASECMP(config, "HDMI3D"))
992     {
993       logger->log("Command", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
994       video->setConnection(Video::HDMI3D);
995     }
996     else
997     {
998       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
999       video->setConnection(Video::COMPOSITERGB);
1000     }
1001     delete[] config;
1002   }
1003   else
1004   {
1005     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
1006   }
1007
1008   // Set to shutdown VDR if config says
1009   
1010   config = vdr->configLoad("General", "VDR shutdown");
1011   if (config)
1012   {
1013     if (!STRCASECMP(config, "On"))
1014     {
1015       logger->log("Command", Log::INFO, "Shutdown VDR when  shutting down vomp");
1016       vdr->setVDRShutdown(true);
1017     }
1018     else if (!STRCASECMP(config, "Off"))
1019     {
1020       logger->log("Command", Log::INFO, "Shutdown only vomp");
1021       vdr->setVDRShutdown(false);
1022     }
1023   }
1024   else
1025   {
1026     logger->log("Command", Log::INFO, "Default shutdown only vomp");
1027     vdr->setVDRShutdown(false); // Default
1028   }
1029           
1030   // Set remote type
1031
1032   config = vdr->configLoad("General", "Remote type");
1033
1034   if (config)
1035   {
1036     if (!STRCASECMP(config, "New"))
1037     {
1038       logger->log("Command", Log::INFO, "Switching to New remote type");
1039       remote->setRemoteType(Remote::NEWREMOTE);
1040     }
1041     else
1042     {
1043       logger->log("Command", Log::INFO, "Switching to Old remote type");
1044       remote->setRemoteType(Remote::OLDREMOTE);
1045     }
1046     delete[] config;
1047   }
1048   else
1049   {
1050     logger->log("Command", Log::INFO, "Config General/Remote type not found");
1051     remote->setRemoteType(Remote::OLDREMOTE);
1052   }
1053
1054
1055
1056   // Get TV aspect ratio
1057
1058   config = vdr->configLoad("TV", "Aspect");
1059   if (config)
1060   {
1061     if (!STRCASECMP(config, "16:9"))
1062     {
1063       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
1064       video->setTVsize(Video::ASPECT16X9);
1065     }
1066     else
1067     {
1068       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
1069       video->setTVsize(Video::ASPECT4X3);
1070     }
1071     delete[] config;
1072   }
1073   else
1074   {
1075     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
1076     video->setTVsize(Video::ASPECT4X3);
1077   }
1078
1079   config = vdr->configLoad("TV", "Widemode");
1080   if (config)
1081   {
1082     if (!STRCASECMP(config, "Letterbox"))
1083     {
1084       logger->log("Command", Log::INFO, "Setting letterbox mode");
1085       video->setMode(Video::LETTERBOX);
1086     }
1087     else
1088     {
1089       logger->log("Command", Log::INFO, "Setting chop-sides mode");
1090       video->setMode(Video::NORMAL);
1091     }
1092     delete[] config;
1093   }
1094   else
1095   {
1096 #ifdef __ANDROID__
1097          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
1098          video->setMode(Video::LETTERBOX);
1099 #else
1100     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
1101     video->setMode(Video::NORMAL);
1102 #endif
1103   }
1104
1105   config = vdr->configLoad("Advanced", "TCP receive window");
1106   if (config)
1107   {
1108     size_t newTCPsize = atoi(config);
1109     delete[] config;
1110
1111     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
1112     vdr->setReceiveWindow(newTCPsize);
1113   }
1114   else
1115   {
1116     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
1117     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1118   }
1119
1120   config = vdr->configLoad("Advanced", "Font Name");
1121   if (config)
1122   {
1123         Osd::getInstance()->setFont(config);
1124     logger->log("Command", Log::INFO, "Setting Font to %s", config);
1125     delete[] config;
1126
1127   }
1128
1129
1130   // Set recording list type
1131
1132   advmenues=false;
1133 #ifdef    ADVANCED_MENUES
1134   config = vdr->configLoad("Advanced", "Menu type");
1135
1136   if (config)
1137   {
1138           if (!STRCASECMP(config, "Advanced"))
1139           {
1140                   logger->log("Command", Log::INFO, "Switching to Advanced menu");
1141                   advmenues=true;
1142
1143           }
1144           else
1145           {
1146                   logger->log("Command", Log::INFO, "Switching to Classic menu");
1147                   advmenues=false;
1148           }
1149           delete[] config;
1150   }
1151   else
1152   {
1153           logger->log("Command", Log::INFO, "Config General/menu type not found");
1154           advmenues=true;
1155   }
1156 #endif
1157
1158   config = vdr->configLoad("Advanced", "Disable WOL");
1159   if (config)
1160   {
1161     if (!STRCASECMP(config, "Yes"))
1162     {
1163       logger->log("Command", Log::INFO, "Config says disable WOL");
1164       Wol::getInstance()->setEnabled(false);
1165     }
1166     else
1167     {
1168       logger->log("Command", Log::INFO, "Config says enable WOL");
1169       Wol::getInstance()->setEnabled(true);
1170     }
1171
1172     delete[] config;
1173   }
1174   else
1175   {
1176     logger->log("Command", Log::INFO, "By default, enable WOL");
1177     Wol::getInstance()->setEnabled(true);
1178   }
1179   /* device dependend config */
1180   audio->loadOptionsfromServer(vdr);
1181   video->loadOptionsfromServer(vdr);
1182   remote->loadOptionsfromServer(vdr);
1183
1184   video->executePendingModeChanges();
1185   // config done
1186
1187   // Save power state = on
1188
1189   vdr->configSave("General", "Last Power State", "On");
1190
1191   // Make sure connection didn't die
1192   if (!vdr->isConnected())
1193   {
1194     Command::getInstance()->connectionLost();
1195   }
1196   else
1197   {
1198     boxstack->remove(vi);
1199
1200     VWelcome* vw = new VWelcome();
1201     vw->draw();
1202     boxstack->add(vw);
1203     boxstack->update(vw);
1204
1205     // Enter pre-keys here
1206 //    handleCommand(Remote::OK);
1207 //    handleCommand(Remote::THREE);
1208 //    handleCommand(Remote::SIX);
1209 //    handleCommand(Remote::OK);
1210 //    handleCommand(Remote::UP);
1211 //    handleCommand(Remote::PLAY);
1212 //    handleCommand(Remote::DOWN);
1213 //    handleCommand(Remote::DOWN);
1214 //    handleCommand(Remote::DOWN);
1215  //   handleCommand(Remote::OK);
1216 //    handleCommand(Remote::RED);
1217   }
1218 }