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