]> git.vomp.tv Git - vompclient.git/blob - command.cc
Changes in signaloff/on and doreboot, enhance hardware deinitialisation
[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   \r
670   Video* video = Video::getInstance();\r
671   Audio* audio = Audio::getInstance();  \r
672   boxstack->remove(vconnect);\r
673 \r
674   VInfo* vi = new VInfo();\r
675   vi->setSize(400, 200);\r
676   vi->createBuffer();\r
677   if (video->getFormat() == Video::PAL)\r
678     vi->setPosition(170, 200);\r
679   else\r
680     vi->setPosition(160, 150);\r
681   vi->setOneLiner(tr("Connected, loading config"));\r
682   vi->draw();\r
683   boxstack->add(vi);\r
684   boxstack->update(vi);\r
685 \r
686   VDR* vdr = VDR::getInstance();\r
687   char* config;\r
688 \r
689   // See if we're supposed to do network logging\r
690   config = vdr->configLoad("Advanced", "Network logging");\r
691   if (config && !STRCASECMP(config, "On"))\r
692   {\r
693     logger->log("Command", Log::INFO, "Turning on network logging");\r
694     logger->setExternLogger(vdr);\r
695   }  \r
696   else\r
697   {\r
698           logger->unsetExternLogger();\r
699     logger->log("Command", Log::INFO, "Turned off network logging");\r
700   }\r
701   if (config) delete[] config;\r
702 \r
703   // See if config says to override video format (PAL/NTSC)\r
704   config = vdr->configLoad("General", "Override Video Format");\r
705   if (config)\r
706   {\r
707     logger->log("Command", Log::DEBUG, "Override Video Format is present");\r
708 \r
709     if (   (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))\r
710         || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL))  )\r
711     {\r
712       // Oh sheesh, need to switch format. Bye bye TV...\r
713 \r
714       // Take everything down\r
715       boxstack->removeAll();\r
716       boxstack->remove(wallpaper);\r
717       Osd* osd = Osd::getInstance();\r
718 #ifndef __ANDROID__\r
719       osd->shutdown();\r
720 #endif\r
721       video->shutdown();\r
722 \r
723       // Get video and osd back up with the new mode\r
724       if (!strcmp(config, "PAL"))\r
725       {\r
726         logger->log("Command", Log::DEBUG, "Switching to PAL");\r
727         video->init(Video::PAL);\r
728       }\r
729       else if (!strcmp(config, "NTSC"))\r
730       {\r
731         logger->log("Command", Log::DEBUG, "Switching to NTSC");\r
732         video->init(Video::NTSC);\r
733       }\r
734 #ifndef __ANDROID__\r
735       //we do not init twice\r
736       osd->init((char*)("/dev/stbgfx"));\r
737 #endif\r
738 \r
739       // Put the wallpaper back\r
740       doWallpaper();\r
741 \r
742       // Re add the vinfo\r
743       vi = new VInfo();\r
744       vi->setSize(400, 200);\r
745       vi->createBuffer();\r
746       if (video->getFormat() == Video::PAL)\r
747         vi->setPosition(170, 200);\r
748       else\r
749         vi->setPosition(160, 150);\r
750 \r
751       vi->setOneLiner(tr("Connected, loading config"));\r
752       vi->draw();\r
753       boxstack->add(vi);\r
754       boxstack->update(vi);\r
755     }\r
756     else\r
757     {\r
758       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");\r
759     }\r
760   }\r
761   else\r
762   {\r
763     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");\r
764   }\r
765 \r
766   // Power off if first boot and config says so\r
767   if (firstBoot)\r
768   {\r
769     firstBoot = 0;\r
770 \r
771     logger->log("Command", Log::DEBUG, "Load power after boot");\r
772 \r
773     config = vdr->configLoad("General", "Power After Boot");\r
774 \r
775     if (config)\r
776     {\r
777       if (!STRCASECMP(config, "On"))\r
778       {\r
779         logger->log("Command", Log::INFO, "Config says Power After Boot = On");\r
780       }\r
781       else if (!STRCASECMP(config, "Off"))\r
782       {\r
783         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");\r
784         doStandby();\r
785         delete[] config;\r
786         return; // quit here\r
787       }\r
788       else if (!STRCASECMP(config, "Last state"))\r
789       {\r
790         char* lastPowerState = vdr->configLoad("General", "Last Power State");\r
791         if (lastPowerState)\r
792         {\r
793           if (!STRCASECMP(lastPowerState, "On"))\r
794           {\r
795             logger->log("Command", Log::INFO, "Config says Last Power State = On");\r
796           }\r
797           else if (!STRCASECMP(lastPowerState, "Off"))\r
798           {\r
799             logger->log("Command", Log::INFO, "Config says Last Power State = Off");\r
800             doStandby();\r
801             delete[] config;\r
802             return; // quit here\r
803           }\r
804           else\r
805           {\r
806             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");\r
807           }\r
808         }\r
809         else\r
810         {\r
811           logger->log("Command", Log::INFO, "Config General/Last Power State not found");\r
812         }\r
813       }\r
814       else\r
815       {\r
816         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");\r
817       }\r
818       delete[] config;\r
819     }\r
820     else\r
821     {\r
822       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");\r
823     }\r
824   }\r
825 \r
826 \r
827   // Go S-Video if config says so\r
828 \r
829   config = vdr->configLoad("TV", "Connection");\r
830 \r
831   if (config)\r
832   {\r
833     if (!STRCASECMP(config, "S-Video"))\r
834     {\r
835       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);\r
836       video->setConnection(Video::SVIDEO);\r
837     }\r
838     else\r
839     {\r
840       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);\r
841       video->setConnection(Video::COMPOSITERGB);\r
842     }\r
843     delete[] config;\r
844   }\r
845   else\r
846   {\r
847     logger->log("Command", Log::INFO, "Config TV/S-Video not found");\r
848   }\r
849 \r
850   // Set remote type\r
851 \r
852   config = vdr->configLoad("General", "Remote type");\r
853 \r
854   if (config)\r
855   {\r
856     if (!STRCASECMP(config, "New"))\r
857     {\r
858       logger->log("Command", Log::INFO, "Switching to New remote type");\r
859       remote->setRemoteType(Remote::NEWREMOTE);\r
860     }\r
861     else\r
862     {\r
863       logger->log("Command", Log::INFO, "Switching to Old remote type");\r
864       remote->setRemoteType(Remote::OLDREMOTE);\r
865     }\r
866     delete[] config;\r
867   }\r
868   else\r
869   {\r
870     logger->log("Command", Log::INFO, "Config General/Remote type not found");\r
871     remote->setRemoteType(Remote::OLDREMOTE);\r
872   }\r
873 \r
874 \r
875 \r
876 \r
877   // Get TV aspect ratio\r
878 \r
879   config = vdr->configLoad("TV", "Aspect");\r
880   if (config)\r
881   {\r
882     if (!STRCASECMP(config, "16:9"))\r
883     {\r
884       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");\r
885       video->setTVsize(Video::ASPECT16X9);\r
886     }\r
887     else\r
888     {\r
889       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");\r
890       video->setTVsize(Video::ASPECT4X3);\r
891     }\r
892     delete[] config;\r
893   }\r
894   else\r
895   {\r
896     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");\r
897     video->setTVsize(Video::ASPECT4X3);\r
898   }\r
899 \r
900   config = vdr->configLoad("TV", "Widemode");\r
901   if (config)\r
902   {\r
903     if (!STRCASECMP(config, "Letterbox"))\r
904     {\r
905       logger->log("Command", Log::INFO, "Setting letterbox mode");\r
906       video->setMode(Video::LETTERBOX);\r
907     }\r
908     else\r
909     {\r
910       logger->log("Command", Log::INFO, "Setting chop-sides mode");\r
911       video->setMode(Video::NORMAL);\r
912     }\r
913     delete[] config;\r
914   }\r
915   else\r
916   {\r
917 #ifdef __ANDROID__\r
918          logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");\r
919          video->setMode(Video::LETTERBOX);\r
920 #else\r
921     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");\r
922     video->setMode(Video::NORMAL);\r
923 #endif\r
924   }\r
925 \r
926   config = vdr->configLoad("Advanced", "TCP receive window");\r
927   if (config)\r
928   {\r
929     size_t newTCPsize = atoi(config);\r
930     delete[] config;\r
931 \r
932     logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);\r
933     vdr->setReceiveWindow(newTCPsize);\r
934   }\r
935   else\r
936   {\r
937     logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");\r
938     vdr->setReceiveWindow(2048); // Default\r
939   }\r
940 \r
941   config = vdr->configLoad("Advanced", "Disable WOL");\r
942   if (config)\r
943   {\r
944     if (!STRCASECMP(config, "Yes"))\r
945     {\r
946       logger->log("Command", Log::INFO, "Config says disable WOL");\r
947       Wol::getInstance()->setEnabled(false);\r
948     }\r
949     else\r
950     {\r
951       logger->log("Command", Log::INFO, "Config says enable WOL");\r
952       Wol::getInstance()->setEnabled(true);\r
953     }\r
954 \r
955     delete[] config;\r
956   }\r
957   else\r
958   {\r
959     logger->log("Command", Log::INFO, "By default, enable WOL");\r
960     Wol::getInstance()->setEnabled(true);\r
961   }\r
962   /* device dependend config */\r
963   audio->loadOptionsfromServer(vdr);\r
964   video->loadOptionsfromServer(vdr);\r
965   remote->loadOptionsfromServer(vdr);\r
966   // config done\r
967 \r
968   // Save power state = on\r
969 \r
970   vdr->configSave("General", "Last Power State", "On");\r
971 \r
972   // Make sure connection didn't die\r
973   if (!vdr->isConnected())\r
974   {\r
975     Command::getInstance()->connectionLost();\r
976   }\r
977   else\r
978   {\r
979     boxstack->remove(vi);\r
980 \r
981     VWelcome* vw = new VWelcome();\r
982     vw->draw();\r
983     boxstack->add(vw);\r
984     boxstack->update(vw);\r
985 \r
986     // Enter pre-keys here\r
987 //    handleCommand(Remote::OK);\r
988 //    handleCommand(Remote::THREE);\r
989 //    handleCommand(Remote::SIX);\r
990 //    handleCommand(Remote::OK);\r
991 //    handleCommand(Remote::UP);\r
992 //    handleCommand(Remote::PLAY);\r
993 //    handleCommand(Remote::DOWN);\r
994 //    handleCommand(Remote::DOWN);\r
995 //    handleCommand(Remote::DOWN);\r
996  //   handleCommand(Remote::OK);\r
997 //    handleCommand(Remote::RED);\r
998   }\r
999 }\r