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