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