]> git.vomp.tv Git - vompclient.git/blob - control.cc
Control/main/winmain/util reorg
[vompclient.git] / control.cc
1 /*
2     Copyright 2004-2020 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, see <https://www.gnu.org/licenses/>.
18 */
19
20 // FIXME rename to Control and move stuff from main to here
21
22 #ifndef WIN32
23 #include <unistd.h> // for reboot
24 #include <linux/reboot.h>
25 #include <sys/reboot.h>
26 #endif
27
28 #include <time.h>
29
30 #ifdef WIN32
31 #include "inputwin.h"
32 #endif
33
34 #ifdef __ANDROID__
35 #include "inputandroid.h"
36 #endif
37
38 #include "led.h"
39 #include "video.h"
40 #include "audio.h"
41 #include "vdr.h"
42 #include "vvolume.h"
43 #include "vserverselect.h"
44 #include "vwelcome.h"
45 #include "vmute.h"
46 #include "colour.h"
47 #include "osd.h"
48 #include "i18n.h"
49 #include "timers.h"
50 #include "wol.h"
51 #include "vconnect.h"
52 #include "message.h"
53 #include "inputman.h"
54 #include "input.h"
55 #include "vinfo.h"
56 #include "boxx.h"
57 #include "boxstack.h"
58 #include "log.h"
59 #include "vsleeptimer.h"
60 #include "wjpeg.h"
61 #include "osdvector.h"
62
63 #include "control.h"
64
65 Control* Control::instance = NULL;
66
67 Control::Control()
68 {
69   if (instance) return;
70   instance = this;
71 }
72
73 Control::~Control()
74 {
75   flushMessageQueue();
76   instance = NULL;
77 }
78
79 Control* Control::getInstance()
80 {
81   return instance;
82 }
83
84 bool Control::init(bool tcrashed)
85 {
86   if (initted) return false;
87   crashed = tcrashed;
88
89
90   SkinFactory::InitSkin(0);
91
92   logger = Log::getInstance();
93
94
95   try
96   {
97     vdr = new VDR();                           if (!boxstack) throw 1;
98     if (!vdr->init())                          throw 2;
99
100     boxstack = new BoxStack();                if (!boxstack) throw 10;
101     if (!boxstack->init())                    throw 20;
102
103     sleeptimer = new Sleeptimer();            if (!sleeptimer) throw 30;
104
105     wol = new Wol();                          if (!wol) throw 40;
106
107   }
108   catch (int e)
109   {
110     if      (e == 1 ) logger->log("Control", Log::EMERG, "VDR module failed to create");
111     else if (e == 2 ) logger->log("Control", Log::EMERG, "VDR module failed to initialise");
112     else if (e == 10) logger->log("Control", Log::EMERG, "BoxStack module failed to create");
113     else if (e == 20) logger->log("Control", Log::EMERG, "BoxStack module failed to initialise");
114     else if (e == 30) logger->log("Control", Log::EMERG, "SleepTimer module failed to create");
115     else if (e == 40) logger->log("Control", Log::EMERG, "WOL module failed to create");
116
117     switch(e)
118     {
119       case 40:
120         FALLTHROUGH
121       case 30:
122         FALLTHROUGH
123       case 20:
124         delete boxstack;
125         boxstack = NULL;
126         FALLTHROUGH
127       case 10:
128         FALLTHROUGH
129       case 2:
130         delete vdr;
131         vdr = NULL;
132         FALLTHROUGH
133       case 1:
134         FALLTHROUGH
135     }
136
137     return false;
138   }
139
140
141   inputMan = InputMan::getInstance();
142   
143   if (!inputMan)
144   {
145     initted = false;
146     return 0;
147   }
148
149
150
151   initted = true;
152   return true;
153 }
154
155 void Control::shutdown()
156 {
157   if (!initted) return;
158   initted = false;
159
160   if (wol)
161   {
162     delete wol;
163     logger->log("Control", Log::NOTICE, "WOL module shut down");
164   }
165
166   if (sleeptimer)
167   {
168     delete sleeptimer;
169     sleeptimer = NULL;
170     logger->log("Control", Log::NOTICE, "Sleeptimer module shut down");
171   }
172
173   if (boxstack)
174   {
175     boxstack->shutdown();
176     delete boxstack;
177     boxstack = NULL;
178     logger->log("Control", Log::NOTICE, "BoxStack module shut down");
179   }
180
181   if (vdr)
182   {
183     vdr->shutdown();
184     delete vdr;
185     vdr = NULL;
186     logger->log("Control", Log::NOTICE, "VDR module shut down");
187   }
188 }
189
190 void Control::stop()
191 {
192   logger->log("Control", Log::NOTICE, "Request stop");
193
194   Message* m = new Message(); // break master loop
195   m->message = Message::SHUTDOWN;
196   m->p_to = Message::CONTROL;
197   postMessage(m);
198 }
199
200 void Control::doWallpaper()
201 {
202   Video* video = Video::getInstance();
203
204   // Blue background
205   Boxx* bbg = new Boxx();
206   bbg->setSize(video->getScreenWidth(), video->getScreenHeight());
207   bbg->createBuffer();
208   bbg->fillColour(DrawStyle::WALLPAPER);
209   boxstack->add(bbg);
210   boxstack->update(bbg);
211   boxstack->remove(bbg);
212
213   // Wallpaper
214   wallpaper = new Boxx();
215   wallpaper->setSize(video->getScreenWidth(), video->getScreenHeight());
216   wallpaper->createBuffer();
217   wallpaper->setBackgroundColour(DrawStyle::WALLPAPER);
218
219   wallpaper_pict = new WJpegTYPE();
220   wallpaper_pict->setSize(video->getScreenWidth(), video->getScreenHeight());
221
222   if (video->getFormat() == Video::PAL)
223   {
224     logger->log("Control", Log::DEBUG, "PAL wallpaper selected");
225 #ifndef _MIPS_ARCH    
226     wallpaper_pict->init("/wallpaperPAL.jpg");
227 #else
228     wallpaper_pict->init("wallpaperPAL.jpg");
229 #endif
230   }
231   else
232   {
233     logger->log("Control", Log::DEBUG, "NTSC wallpaper selected");
234     wallpaper_pict->init("/wallpaperNTSC.jpg");
235   }
236
237   if (DrawStyle::WALLPAPER.alpha)
238     wallpaper_pict->setVisible(true);
239   else
240     wallpaper_pict->setVisible(false);
241
242   wallpaper->add(wallpaper_pict);
243   wallpaper->draw();
244
245   boxstack->add(wallpaper);
246   boxstack->update(wallpaper);
247
248   OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
249   if (osdv) osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
250 }
251
252 void Control::run()
253 {
254   if (!initted) return;
255   irun = true;
256
257   // just in case
258   Video::getInstance()->signalOn();
259   Led::getInstance()->on();
260
261   doWallpaper();
262
263   if (crashed)
264   {
265     buildCrashedBox();
266   }
267   else
268   {
269     VConnect* vconnect = new VConnect();
270     boxstack->add(vconnect);
271     vconnect->run();
272   }
273
274
275   // FIXME Input::NA_SIGNAL is possibly obsolete now
276
277   std::unique_lock<std::mutex> lockWrapper(messageQueueMutex);  // locks. unlocks on out-of-scope
278
279   inputMan->start();
280
281   while(irun)
282   {
283     messageQueueCond.wait(lockWrapper, [&] { return !irun || !messages.empty(); });
284     logger->log("Control", Log::DEBUG, "woke");
285
286     if (!irun) break;
287
288     while(!messages.empty())
289     {
290       Message* m = messages.front();
291       messages.pop_front();
292
293       lockWrapper.unlock();
294
295       processMessage(m);
296       delete m;
297
298       lockWrapper.lock();
299     }
300   }
301
302   inputMan->stop();
303
304   boxstack->removeAllExceptWallpaper();
305   boxstack->remove(wallpaper);
306   delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
307 }
308
309 void Control::processMessage(Message* m)
310 {
311     // FIXME - a slight modification - how if messagereceivers were to register
312     // themselves as receivers to avoid the calling-a-deleted-object problem
313     // then only deliver/register/unregister would have to be protected
314
315   logger->log("Control", Log::DEBUG, "processing message %i", m->message);
316
317
318   if ((m->p_to == Message::CONTROL) || (m->to == this)) // Maybe don't check m->to here? Always use predefined?
319   {
320     switch(m->message)
321     {
322       case Message::SHUTDOWN:
323       {
324         irun = false;
325         break;
326       }
327       // << FIXME OBSELETE
328       case Message::STOP_PLAYBACK:
329       {
330         handleCommand(Input::STOP); // an odd way of doing it, but so simple
331         break;
332       }
333       // Also connection_lost comes from player - anywhere else?
334       // FIXME OBSELETE >>
335
336
337       case Message::VDR_CONNECTED:
338       {
339         doJustConnected(static_cast<VConnect*>(m->from));
340         break;
341       }
342       case Message::SCREENSHOT:
343       {
344         logger->log("Osd", Log::NOTICE, "Screenshot Message arrived");
345         Osd::getInstance()->screenShot("out.jpg");
346         break;
347       }
348       case Message::CONNECTION_LOST:
349       {
350         doFromTheTop(true);
351         break;
352       }
353       case Message::INPUT_EVENT:
354       {
355         logger->log("Control", Log::NOTICE, "INPUT_EVENT %i", m->parameter);
356
357         handleCommand(m->parameter);
358         break;
359       }
360       case Message::CHANGE_LANGUAGE:
361       {
362         boxstack->removeAllExceptWallpaper();
363         boxstack->update(wallpaper);
364         I18n::initialize();
365         if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
366         VWelcome* vw = new VWelcome();
367         vw->draw();
368         boxstack->add(vw);
369         boxstack->update(vw);
370         break;
371       }
372       case Message::LAST_VIEW_CLOSE:
373       {
374         // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
375         if (crashed)
376         {
377           crashed = false;
378           doFromTheTop(false);        
379         }
380       
381 //        VWelcome* vw = new VWelcome();
382 //        vw->draw();
383 //        boxstack->add(vw);
384 //        boxstack->update(vw);
385
386         break;
387       }
388       case Message::NEW_PICTURE:
389       {
390         //Log::getInstance()->log("Control", Log::DEBUG, "TVMedia NEW_PICTURE");
391         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
392         if (osdv) osdv->informPicture(m->tag, reinterpret_cast<ImageIndex>(m->data));
393         break;
394       }
395       case Message::NEW_PICTURE_STATIC:
396       {
397         //Log::getInstance()->log("Control", Log::DEBUG, "TVMedia NEW_PICTURE %x %x",m->tag,m->parameter);
398         OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
399         if (osdv) osdv->informPicture(static_cast<unsigned long long>(m->tag) << 32LL, reinterpret_cast<ImageIndex>(m->data));
400         break;
401       }
402     }
403   }
404   else
405   {
406     /* FIXME
407     
408     Instead of sending through the boxstack, implement a more generic MessageReceiver interface
409     and have potential receivers register with something
410     When a message needs to be delivered, check if the receiver is still registered, if so, deliver the message
411     This could all be done using the existing big control mutex to keep it simple
412     */
413   
414     logger->log("Control", Log::DEBUG, "Sending message to boxstack");
415     boxstack->processMessage(m);
416   }
417 }
418
419 void Control::handleCommand(int button)
420 {
421   if (isStandby && (button != Input::POWER)
422                 && (button != Input::POWERON)
423                 && (button != Input::POWEROFF))  return;
424
425   if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
426
427   // command was not handled
428
429   switch(button)
430   {
431     case Input::VOLUMEUP:
432     case Input::VOLUMEDOWN:
433     {
434       if (inputMan->handlesVolume()) // CEC volume handler?
435       {
436         if (button == Input::VOLUMEDOWN)
437           inputMan->volumeDown();
438         else
439           inputMan->volumeUp();
440       }
441       else
442       {
443         VVolume* v = new VVolume();
444         boxstack->add(v);
445         v->handleCommand(button); // this will draw+show
446       }
447       return;
448     }
449     case Input::MUTE:
450     {
451       if (inputMan->handlesVolume())
452       {
453         inputMan->volumeMute();
454       }
455       else
456       {
457         VMute* v = new VMute();
458         v->draw();
459         boxstack->add(v);
460         boxstack->update(v);
461       }
462       return;
463     }
464     case Input::POWER:
465     {
466       doStandby();
467       return;
468     }
469     case Input::POWERON:
470     {
471       doPowerOn();
472       return;
473     }
474     case Input::POWEROFF:
475     {
476       doPowerOff();
477       return;
478     }
479     case Input::OK:
480     {
481       // FIXME
482       if (!connLost) return; // if connLost, handle Input::OK
483       doFromTheTop(false);
484       return;
485     }
486     case Input::GO:
487     {
488       VSleeptimer* sleep = new VSleeptimer();
489       boxstack->add(sleep);
490       sleep->handleCommand(button); // this will draw+show
491       return;
492     }
493   }
494 }
495
496 /*
497 void Control::sig1()
498 {
499 #ifdef DEV
500   Message* m = new Message(); // break into master mutex
501   m->message = Message::SCREENSHOT;
502   m->to = this;
503   postMessage(m);
504 #endif
505 }
506 */
507
508 void Control::doStandby()
509 {
510   if (isStandby)
511   {
512     doPowerOn();
513   }
514   else
515   {
516     doPowerOff();
517   }
518 }
519
520
521 void Control::doPowerOn()
522 {
523   if (isStandby)
524   {
525     Video::getInstance()->signalOn();
526     Led::getInstance()->on();
527     InputMan::getInstance()->changePowerState(true);
528     isStandby = false;
529
530     VConnect* vconnect = new VConnect();
531     boxstack->add(vconnect);
532     vconnect->run();
533   }
534 }
535
536 void Control::doPowerOff()
537 {
538   if (!isStandby)
539   {
540     VDR::getInstance()->shutdownVDR();
541     boxstack->removeAllExceptWallpaper();
542     Video::getInstance()->signalOff();
543     boxstack->update(wallpaper);
544
545     VDR::getInstance()->configSave("General", "Last Power State", "Off");
546     logger->unsetExternLogger();
547     VDR::getInstance()->disconnect();
548     Led::getInstance()->off();
549     InputMan::getInstance()->changePowerState(false);
550     isStandby = true;
551     Sleeptimer::getInstance()->shutdown();
552   }
553 }
554
555 void Control::doFromTheTop(bool which)
556 {
557   if (isStandby) return;
558   if (which)
559   {
560     if (connLost)
561     {
562       logger->log("Control", Log::NOTICE, "Connection lost dialog already present");
563       return;
564     }
565   
566     logger->log("Control", Log::NOTICE, "Doing connection lost dialog");
567     connLost = new VInfo();
568     connLost->setSize(360, 200);
569     connLost->createBuffer();
570     if (Video::getInstance()->getFormat() == Video::PAL)
571       connLost->setPosition(190, 170);
572     else
573       connLost->setPosition(180, 120);
574     connLost->setOneLiner(tr("Connection lost"));
575     connLost->setDropThrough();
576     connLost->setBorderOn(1);
577     connLost->setTitleBarColour(DrawStyle::DANGER);
578     connLost->okButton();
579     connLost->draw();
580     boxstack->add(connLost);
581     boxstack->update(connLost);
582
583     clearMQInputEvents();
584   }
585   else
586   {
587     logger->unsetExternLogger();
588     VDR::getInstance()->disconnect();
589     boxstack->removeAllExceptWallpaper();
590     boxstack->update(wallpaper);
591     connLost = NULL;
592     
593     flushMessageQueue();
594     
595     // at this point, everything should be reset to first-go
596     
597     VConnect* vconnect = new VConnect();
598     boxstack->add(vconnect);
599     vconnect->run();
600   }
601 }
602
603 void Control::clearMQInputEvents()
604 {
605   std::lock_guard<std::mutex> lg(messageQueueMutex); // Get the lock
606
607   MQueueI i = messages.begin();
608   while(i != messages.end())
609   {
610     Message* m = *i;
611     if (m->message == Message::INPUT_EVENT)
612     {
613       delete m;
614       i = messages.erase(i);
615     }
616     else
617     {
618       ++i;
619     }
620   }
621 }
622
623 void Control::doReboot()
624 {
625
626   logger->unsetExternLogger();
627   VDR::getInstance()->disconnect();
628   // just kill it...
629   logger->log("Control", Log::NOTICE, "Reboot");
630 #ifndef WIN32
631 #ifndef VOMP_HAS_EXIT
632   // some plattforms, want a proper deinitialisation of their hardware before reboot
633   Osd::getInstance()->shutdown();
634   Audio::getInstance()->shutdown();
635   Video::getInstance()->shutdown();
636   InputMan::getInstance()->shutdown();
637
638   reboot(LINUX_REBOOT_CMD_RESTART);
639   // if  reboot is not allowed -> stop
640   stop();
641
642
643 #else
644   stop();
645
646 #ifdef __ANDROID__
647   exit(0);
648 #endif
649
650 #endif
651 #endif //Would we support this on windows?
652 }
653
654 void Control::connectionLost()
655 {
656   logger->unsetExternLogger();
657   Message* m = new Message(); // break into master mutex
658   m->message = Message::CONNECTION_LOST;
659   m->p_to = Message::CONTROL;
660   postMessage(m);
661 }
662
663 void Control::buildCrashedBox()
664 {
665   VInfo* crash = new VInfo();
666   crash->setSize(360, 250);
667   crash->createBuffer();
668   if (Video::getInstance()->getFormat() == Video::PAL)
669     crash->setPosition(190, 146);
670   else
671     crash->setPosition(180, 96);
672   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.");
673   crash->setBorderOn(1);
674   crash->setTitleBarColour(DrawStyle::DANGER);
675   crash->okButton();
676   crash->setExitable();
677   crash->draw();
678   boxstack->add(crash);
679   boxstack->update(crash);
680 }
681
682 int Control::getLangPref(bool subtitle, const char* langcode)
683 {
684   std::vector<struct ASLPref>::iterator itty=langcodes.begin();
685   char templangcode[4];
686   templangcode[0] = langcode[0];
687   templangcode[1] = langcode[1];
688   templangcode[2] = langcode[2];
689   templangcode[3] = '\0';
690   int langpos = 0;
691   while (itty != langcodes.end())
692   {
693     size_t pos = (*itty).langcode.find(templangcode);
694     if (pos != std::string::npos)
695     {
696       //vector<struct ASLPref>::iterator itty2=langcodes.begin();
697       for (unsigned int i = 0; i < langcodes.size(); i++)
698       {
699         int pref = 0;
700         if (subtitle)
701           pref = langcodes[i].subtitlepref;
702         else
703           pref = langcodes[i].audiopref;
704         if (pref < 0) break;
705
706         if (subtitle)
707         {
708           if (langcodes[i].subtitlepref==langpos) return i;
709         }
710         else
711         {
712           if (langcodes[i].audiopref==langpos) return i;
713         }
714       }
715       break;
716     }
717     itty++;
718     langpos++;
719   }
720   return langcodes.size(); //neutral
721 }
722
723 void Control::doJustConnected(VConnect* vconnect)
724 {
725   I18n::initialize();
726   if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
727   logger->log("Control", Log::INFO, "Entering doJustConnected");
728   
729   Video* video = Video::getInstance();
730   Audio* audio = Audio::getInstance();  
731   boxstack->remove(vconnect);
732
733   VInfo* vi = new VInfo();
734   vi->setSize(400, 200);
735   vi->createBuffer();
736   if (video->getFormat() == Video::PAL)
737     vi->setPosition(170, 200);
738   else
739     vi->setPosition(160, 150);
740   vi->setOneLiner(tr("Connected, loading config"));
741   vi->draw();
742   boxstack->add(vi);
743   boxstack->update(vi);
744
745   // FIXME make config system
746
747   char* config;
748
749   // See if we're supposed to do network logging
750   config = vdr->configLoad("Advanced", "Network logging");
751   if (config && !STRCASECMP(config, "On"))
752   {
753     logger->log("Control", Log::INFO, "Turning on network logging");
754     logger->setExternLogger(vdr);
755   }  
756   else
757   {
758           logger->unsetExternLogger();
759     logger->log("Control", Log::INFO, "Turned off network logging");
760   }
761   if (config) delete[] config;
762
763   config = vdr->configLoad("Advanced", "Skin Name");
764   if (config)
765   {
766     const char **skinnames=SkinFactory::getSkinNames();
767     for (int i=0;i<SkinFactory::getNumberofSkins();i++)
768     {
769       if (!STRCASECMP(config, skinnames[i]))
770       {
771         SkinFactory::InitSkin(i);
772         break;
773       }
774     }
775     delete[] config;
776
777     if (wallpaper && wallpaper_pict)
778     {
779       if (DrawStyle::WALLPAPER.alpha)
780         wallpaper_pict->setVisible(true);
781       else
782         wallpaper_pict->setVisible(false);
783
784       wallpaper->draw();
785       boxstack->update(wallpaper);
786     }
787   }
788   else
789   {
790     SkinFactory::InitSkin(0);
791   }
792
793   // See if config says to override video format (PAL/NTSC)
794   config = vdr->configLoad("General", "Override Video Format");
795   if (config)
796   {
797     logger->log("Control", Log::DEBUG, "Override Video Format is present");
798
799     if (   (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
800         || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
801         || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
802         || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
803         )
804     {
805       // Oh sheesh, need to switch format. Bye bye TV...
806
807       // Take everything down
808       boxstack->removeAllExceptWallpaper();
809       boxstack->remove(wallpaper);
810       delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
811
812       Osd* osd = Osd::getInstance();
813 #ifndef __ANDROID__
814       osd->shutdown();
815 #endif
816       video->shutdown();
817
818       inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
819       inputMan->init(); // FIXME this breaks badly now
820
821       // Get video and osd back up with the new mode
822       if (!strcmp(config, "PAL"))
823       {
824         logger->log("Control", Log::DEBUG, "Switching to PAL");
825         video->init(Video::PAL);
826       }
827       else if (!strcmp(config, "NTSC"))
828       {
829         logger->log("Control", Log::DEBUG, "Switching to NTSC");
830         video->init(Video::NTSC);
831       } else if (!strcmp(config, "PAL_M"))
832       {
833         logger->log("Control", Log::DEBUG, "Switching to PAL_M");
834         video->init(Video::PAL_M);
835       } else if (!strcmp(config, "NTSC_J"))
836       {
837         logger->log("Control", Log::DEBUG, "Switching to NTSC_J");
838         video->init(Video::NTSC_J);
839       }
840       delete[] config;
841
842 #ifndef __ANDROID__
843       //we do not init twice
844       osd->init();
845 #endif
846
847       // Put the wallpaper back
848       doWallpaper();
849
850       // Re add the vinfo
851       vi = new VInfo();
852       vi->setSize(400, 200);
853       vi->createBuffer();
854       if (video->getFormat() == Video::PAL)
855         vi->setPosition(170, 200);
856       else
857         vi->setPosition(160, 150);
858
859       vi->setOneLiner(tr("Connected, loading config"));
860       vi->draw();
861       boxstack->add(vi);
862       boxstack->update(vi);
863     }
864     else
865     {
866       logger->log("Control", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
867     }
868   }
869   else
870   {
871     logger->log("Control", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
872   }
873
874   // Power off if first boot and config says so
875   if (firstBoot)
876   {
877     firstBoot = false;
878
879     logger->log("Control", Log::DEBUG, "Load power after boot");
880
881     config = vdr->configLoad("General", "Power After Boot");
882
883     if (config)
884     {
885       if (!STRCASECMP(config, "On"))
886       {
887         logger->log("Control", Log::INFO, "Config says Power After Boot = On");
888       }
889       else if (!STRCASECMP(config, "Off"))
890       {
891         logger->log("Control", Log::INFO, "Config says Power After Boot = Off");
892         doStandby();
893         delete[] config;
894         return; // quit here
895       }
896       else if (!STRCASECMP(config, "Last state"))
897       {
898         char* lastPowerState = vdr->configLoad("General", "Last Power State");
899         if (lastPowerState)
900         {
901           if (!STRCASECMP(lastPowerState, "On"))
902           {
903             logger->log("Control", Log::INFO, "Config says Last Power State = On");
904           }
905           else if (!STRCASECMP(lastPowerState, "Off"))
906           {
907             logger->log("Control", Log::INFO, "Config says Last Power State = Off");
908             doStandby();
909             delete[] config;
910             return; // quit here
911           }
912           else
913           {
914             logger->log("Control", Log::INFO, "Config General/Last Power State not understood");
915           }
916         }
917         else
918         {
919           logger->log("Control", Log::INFO, "Config General/Last Power State not found");
920         }
921       }
922       else
923       {
924         logger->log("Control", Log::INFO, "Config/Power After Boot not understood");
925       }
926       delete[] config;
927     }
928     else
929     {
930       logger->log("Control", Log::INFO, "Config General/Power After Boot not found");
931     }
932   }
933
934
935   // Go S-Video if config says so
936
937   config = vdr->configLoad("TV", "Connection");
938
939   if (config)
940   {
941     if (!STRCASECMP(config, "S-Video"))
942     {
943       logger->log("Control", Log::INFO, "Switching to S-Video as Connection=%s", config);
944       video->setConnection(Video::SVIDEO);
945     } else  if (!STRCASECMP(config, "HDMI"))
946     {
947       logger->log("Control", Log::INFO, "Switching to HDMI as Connection=%s", config);
948       video->setConnection(Video::HDMI);
949     } else  if (!STRCASECMP(config, "HDMI3D"))
950     {
951       logger->log("Control", Log::INFO, "Switching to HDMI3D as Connection=%s", config);
952       video->setConnection(Video::HDMI3D);
953     }
954     else
955     {
956       logger->log("Control", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
957       video->setConnection(Video::COMPOSITERGB);
958     }
959     delete[] config;
960   }
961   else
962   {
963     logger->log("Control", Log::INFO, "Config TV/S-Video not found");
964   }
965
966   // Set to shutdown VDR if config says
967   
968   config = vdr->configLoad("General", "VDR shutdown");
969   if (config)
970   {
971     if (!STRCASECMP(config, "On"))
972     {
973       logger->log("Control", Log::INFO, "Shutdown VDR when shutting down vomp");
974       vdr->setVDRShutdown(true);
975     }
976     else if (!STRCASECMP(config, "Off"))
977     {
978       logger->log("Control", Log::INFO, "Shutdown only vomp");
979       vdr->setVDRShutdown(false);
980     }
981   }
982   else
983   {
984     logger->log("Control", Log::INFO, "Default shutdown only vomp");
985     vdr->setVDRShutdown(false); // Default
986   }
987           
988   // Get TV aspect ratio
989
990   config = vdr->configLoad("TV", "Aspect");
991   if (config)
992   {
993     if (!STRCASECMP(config, "16:9"))
994     {
995       logger->log("Control", Log::INFO, "/// Switching to TV aspect 16:9");
996       video->setTVsize(Video::ASPECT16X9);
997     }
998     else
999     {
1000       logger->log("Control", Log::INFO, "/// Switching to TV aspect 4:3");
1001       video->setTVsize(Video::ASPECT4X3);
1002     }
1003     delete[] config;
1004   }
1005   else
1006   {
1007     logger->log("Control", Log::INFO, "Config TV/Aspect type not found, going 4:3");
1008     video->setTVsize(Video::ASPECT4X3);
1009   }
1010
1011   config = vdr->configLoad("TV", "Widemode");
1012   if (config)
1013   {
1014     if (!STRCASECMP(config, "Letterbox"))
1015     {
1016       logger->log("Control", Log::INFO, "Setting letterbox mode");
1017       video->setMode(Video::LETTERBOX);
1018     }
1019     else
1020     {
1021       logger->log("Control", Log::INFO, "Setting chop-sides mode");
1022       video->setMode(Video::NORMAL);
1023     }
1024     delete[] config;
1025   }
1026   else
1027   {
1028 #ifdef __ANDROID__
1029          logger->log("Control", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
1030          video->setMode(Video::LETTERBOX);
1031 #else
1032     logger->log("Control", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
1033     video->setMode(Video::NORMAL);
1034 #endif
1035   }
1036
1037   config = vdr->configLoad("Advanced", "TCP receive window");
1038   if (config)
1039   {
1040     size_t newTCPsize = atoi(config);
1041     delete[] config;
1042
1043     logger->log("Control", Log::INFO, "Setting TCP window size %i", newTCPsize);
1044     vdr->setReceiveWindow(newTCPsize);
1045   }
1046   else
1047   {
1048     logger->log("Control", Log::INFO, "TCP window size not found, setting 2048");
1049     if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1050   }
1051
1052   config = vdr->configLoad("Advanced", "Font Name");
1053   if (config)
1054   {
1055         Osd::getInstance()->setFont(config);
1056     logger->log("Control", Log::INFO, "Setting Font to %s", config);
1057     delete[] config;
1058
1059   }
1060
1061
1062   // Set recording list type
1063
1064 #ifdef ADVANCED_MENUES
1065   config = vdr->configLoad("Advanced", "Menu type");
1066
1067   if (config)
1068   {
1069     if (!STRCASECMP(config, "Advanced"))
1070     {
1071       logger->log("Control", Log::INFO, "Switching to Advanced menu");
1072       advMenus = true;
1073     }
1074     else
1075     {
1076       logger->log("Control", Log::INFO, "Switching to Classic menu");
1077       advMenus = false;
1078     }
1079     delete[] config;
1080   }
1081   else
1082   {
1083     logger->log("Control", Log::INFO, "Config General/menu type not found");
1084     advMenus = true;
1085   }
1086 #endif
1087
1088   config = vdr->configLoad("Advanced", "Disable WOL");
1089   if (config)
1090   {
1091     if (!STRCASECMP(config, "Yes"))
1092     {
1093       logger->log("Control", Log::INFO, "Config says disable WOL");
1094       Wol::getInstance()->setEnabled(false);
1095     }
1096     else
1097     {
1098       logger->log("Control", Log::INFO, "Config says enable WOL");
1099       Wol::getInstance()->setEnabled(true);
1100     }
1101
1102     delete[] config;
1103   }
1104   else
1105   {
1106     logger->log("Control", Log::INFO, "By default, enable WOL");
1107     Wol::getInstance()->setEnabled(true);
1108   }
1109   /* device dependend config */
1110   audio->loadOptionsFromServer(vdr);
1111   video->loadOptionsFromServer(vdr);
1112   inputMan->loadOptionsFromServer(vdr);
1113
1114   video->executePendingModeChanges();
1115   // config done
1116
1117   // Save power state = on
1118
1119   vdr->configSave("General", "Last Power State", "On");
1120
1121   // Make sure connection didn't die
1122   if (!vdr->isConnected())
1123   {
1124     Control::getInstance()->connectionLost();
1125   }
1126   else
1127   {
1128     boxstack->remove(vi);
1129
1130     VWelcome* vw = new VWelcome();
1131     vw->draw();
1132     boxstack->add(vw);
1133     boxstack->update(vw);
1134
1135     // Enter pre-keys here
1136 //    handleCommand(Input::OK);
1137 //    handleCommand(Input::THREE);
1138 //    handleCommand(Input::SIX);
1139 //    handleCommand(Input::OK);
1140 //    handleCommand(Input::UP);
1141 //    handleCommand(Input::PLAY);
1142 //    handleCommand(Input::DOWN);
1143 //    handleCommand(Input::DOWN);
1144 //    handleCommand(Input::DOWN);
1145 //    handleCommand(Input::RIGHT);
1146 //    handleCommand(Input::RED);
1147   }
1148 }