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