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