2 Copyright 2004-2005 Chris Tallon
\r
4 This file is part of VOMP.
\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
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
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
22 #include <linux/errno.h>
\r
25 #include "command.h"
\r
28 #include "remotewin.h"
\r
32 #include "remoteandroid.h"
\r
39 #include "vvolume.h"
\r
40 #include "vserverselect.h"
\r
41 #include "vwelcome.h"
\r
46 #include "timerreceiver.h"
\r
49 #include "vconnect.h"
\r
50 #include "message.h"
\r
54 #include "boxstack.h"
\r
56 #include "vsleeptimer.h"
\r
59 Command* Command::instance = NULL;
\r
63 if (instance) return;
\r
78 Command* Command::getInstance()
\r
83 int Command::init(bool tcrashed, char* tServer)
\r
85 if (initted) return 0;
\r
90 logger = Log::getInstance();
\r
91 boxstack = BoxStack::getInstance();
\r
92 remote = Remote::getInstance();
\r
94 remote->InitHWCListwithDefaults();
\r
96 if (!logger || !boxstack || !remote)
\r
102 pthread_mutex_init(&masterLock, NULL);
\r
104 masterLock=CreateMutex(NULL,FALSE,NULL);
\r
110 int Command::shutdown()
\r
112 if (!initted) return 0;
\r
117 void Command::stop()
\r
119 // VDR::getInstance()->cancelFindingServer();
\r
120 logger->log("Command", Log::NOTICE, "Command stop1...");
\r
123 logger->log("Command", Log::NOTICE, "Command stop2...");
\r
127 void Command::doWallpaper()
\r
129 Video* video = Video::getInstance();
\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
141 WJpeg* wallpaperj = new WJpegTYPE();
\r
142 wallpaperj->setSize(video->getScreenWidth(), video->getScreenHeight());
\r
143 wallpaperj->createBuffer();
\r
145 if (video->getFormat() == Video::PAL)
\r
147 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
\r
148 #ifndef _MIPS_ARCH
\r
149 wallpaperj->init("/wallpaperPAL.jpg");
\r
151 wallpaperj->init("wallpaperPAL.jpg");
\r
156 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
\r
157 wallpaperj->init("/wallpaperNTSC.jpg");
\r
159 wallpaperj->draw();
\r
161 boxstack->add(wallpaperj);
\r
162 boxstack->update(wallpaperj);
\r
164 wallpaper = wallpaperj;
\r
167 void Command::run()
\r
169 if (!initted) return;
\r
172 mainPid = getpid();
\r
176 Video::getInstance()->signalOn();
\r
177 Led::getInstance()->on();
\r
181 // End of startup. Lock the mutex and put the first view up
\r
182 // logger->log("Command", Log::DEBUG, "WANT LOCK");
\r
184 pthread_mutex_lock(&masterLock);
\r
186 WaitForSingleObject(masterLock, INFINITE );
\r
188 //logger->log("Command", Log::DEBUG, "LOCKED");
\r
196 VConnect* vconnect = new VConnect(server);
\r
197 boxstack->add(vconnect);
\r
201 // Start method 2 of getting commands in...
\r
208 //logger->log("Command", Log::DEBUG, "UNLOCK");
\r
210 pthread_mutex_unlock(&masterLock);
\r
212 ReleaseMutex(masterLock);
\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
218 // logger->log("Command", Log::DEBUG, "WANT LOCK");
\r
220 pthread_mutex_lock(&masterLock);
\r
222 WaitForSingleObject(masterLock, INFINITE );
\r
224 // logger->log("Command", Log::DEBUG, "LOCK");
\r
226 if ((button == Remote::NA_NONE) /*|| (button == Remote::NA_UNKNOWN)*/) continue;
\r
228 if (button != Remote::NA_SIGNAL) handleCommand(button);
\r
229 processMessageQueue();
\r
233 //logger->log("Command", Log::DEBUG, "UNLOCK");
\r
235 pthread_mutex_unlock(&masterLock);
\r
237 ReleaseMutex(masterLock);
\r
243 void Command::postMessage(Message* m)
\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
251 //logger->log("Command", Log::DEBUG, "WANT LOCK");
\r
253 pthread_mutex_lock(&masterLock);
\r
255 WaitForSingleObject(masterLock, INFINITE );
\r
257 //logger->log("Command", Log::DEBUG, "LOCK");
\r
258 MessageQueue::postMessage(m);
\r
261 #ifndef __ANDROID__
\r
262 kill(mainPid, SIGURG);
\r
264 ((RemoteAndroid*)Remote::getInstance())->Signal();
\r
266 pthread_mutex_unlock(&masterLock);
\r
268 ((RemoteWin*)Remote::getInstance())->Signal();
\r
269 ReleaseMutex(masterLock);
\r
271 //logger->log("Command", Log::DEBUG, "UNLOCK");
\r
274 void Command::postMessageNoLock(Message* m)
\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
282 bool Command::postMessageIfNotBusy(Message* m)
\r
284 // Used for Windows mouse events
\r
286 //logger->log("Command", Log::DEBUG, "TRY LOCK");
\r
288 if (pthread_mutex_trylock(&masterLock) != EBUSY)
\r
290 //logger->log("Command", Log::DEBUG, "LOCK");
\r
291 MessageQueue::postMessage(m);
\r
292 #ifndef __ANDROID__
\r
293 kill(mainPid, SIGURG);
\r
295 ((RemoteAndroid*)Remote::getInstance())->Signal();
\r
297 pthread_mutex_unlock(&masterLock);
\r
298 //logger->log("Command", Log::DEBUG, "UNLOCK");
\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
315 case WAIT_ABANDONED: return false;
\r
316 case WAIT_TIMEOUT: return false;
\r
322 void Command::postMessageFromOuterSpace(Message* m)
\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
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
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
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
356 logger->log("Command", Log::DEBUG, "PMFOS called");
\r
357 MessageQueue::postMessage(m);
\r
360 #ifndef __ANDROID__
\r
361 kill(mainPid, SIGURG);
\r
363 ((RemoteAndroid*)Remote::getInstance())->Signal();
\r
366 ((RemoteWin*)Remote::getInstance())->Signal();
\r
370 void Command::processMessage(Message* m)
\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
376 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
\r
383 // << FIXME OBSELETE
\r
384 case Message::STOP_PLAYBACK:
\r
386 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
\r
389 // Also connection_lost comes from player - anywhere else?
\r
390 // FIXME OBSELETE >>
\r
393 case Message::VDR_CONNECTED:
\r
395 doJustConnected((VConnect*)m->from);
\r
398 case Message::SCREENSHOT:
\r
400 Osd::getInstance()->screenShot("/out.jpg");
\r
403 case Message::CONNECTION_LOST:
\r
405 doFromTheTop(true);
\r
408 case Message::UDP_BUTTON:
\r
410 handleCommand(m->parameter);
\r
413 case Message::CHANGE_LANGUAGE:
\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
422 boxstack->update(vw);
\r
425 case Message::LAST_VIEW_CLOSE:
\r
427 // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
\r
431 doFromTheTop(false);
\r
434 // VWelcome* vw = new VWelcome();
\r
436 // boxstack->add(vw);
\r
437 // boxstack->update(vw);
\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
453 logger->log("Command", Log::DEBUG, "Sending message to boxstack");
\r
454 boxstack->processMessage(m);
\r
458 void Command::handleCommand(int button)
\r
460 if (isStandby && (button != Remote::POWER)) return;
\r
461 if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
\r
463 // command was not handled
\r
467 case Remote::DF_LEFT:
\r
468 case Remote::DF_RIGHT:
\r
469 case Remote::VOLUMEUP:
\r
470 case Remote::VOLUMEDOWN:
\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
477 VVolume* v = new VVolume();
\r
479 v->handleCommand(button); // this will draw+show
\r
485 if (remote->handlesVolume()) {
\r
486 remote->volumeMute();
\r
488 VMute* v = new VMute();
\r
491 boxstack->update(v);
\r
495 case Remote::POWER:
\r
503 if (!connLost) return; // if connLost, handle Remote::OK
\r
504 doFromTheTop(false);
\r
509 VSleeptimer* sleep = new VSleeptimer();
\r
510 boxstack->add(sleep);
\r
511 sleep->handleCommand(button); // this will draw+show
\r
517 void Command::sig1()
\r
520 Message* m = new Message(); // break into master mutex
\r
521 m->message = Message::SCREENSHOT;
\r
527 void Command::doStandby()
\r
531 Video::getInstance()->signalOn();
\r
532 Led::getInstance()->on();
\r
536 VConnect* vconnect = new VConnect(server);
\r
537 boxstack->add(vconnect);
\r
542 boxstack->removeAll();
\r
543 Video::getInstance()->signalOff();
\r
544 boxstack->update(wallpaper);
\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
551 Sleeptimer::getInstance()->shutdown();
\r
553 stop(); //different behavoiur on windows, we exit
\r
558 void Command::doFromTheTop(bool which)
\r
564 logger->log("Command", Log::NOTICE, "Connection lost dialog already present");
\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
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
582 boxstack->add(connLost);
\r
583 boxstack->update(connLost);
\r
584 remote->clearBuffer();
\r
588 logger->unsetExternLogger();
\r
589 VDR::getInstance()->disconnect();
\r
590 boxstack->removeAll();
\r
591 boxstack->update(wallpaper);
\r
594 flushMessageQueue();
\r
595 remote->clearBuffer();
\r
597 // at this point, everything should be reset to first-go
\r
599 VConnect* vconnect = new VConnect(server);
\r
600 boxstack->add(vconnect);
\r
605 void Command::doReboot()
\r
608 logger->unsetExternLogger();
\r
609 VDR::getInstance()->disconnect();
\r
611 logger->log("Command", Log::NOTICE, "Reboot");
\r
613 #ifndef VOMP_HAS_EXIT
\r
614 reboot(LINUX_REBOOT_CMD_RESTART);
\r
623 #endif //Would we support this on windows?
\r
626 void Command::connectionLost()
\r
628 logger->unsetExternLogger();
\r
629 Message* m = new Message(); // break into master mutex
\r
630 m->message = Message::CONNECTION_LOST;
\r
632 postMessageFromOuterSpace(m);
\r
635 void Command::buildCrashedBox()
\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
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
648 crash->setExitable();
\r
650 boxstack->add(crash);
\r
651 boxstack->update(crash);
\r
654 void Command::doJustConnected(VConnect* vconnect)
\r
656 I18n::initialize();
\r
657 if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
\r
659 Video* video = Video::getInstance();
\r
660 Audio* audio = Audio::getInstance();
\r
661 boxstack->remove(vconnect);
\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
669 vi->setPosition(160, 150);
\r
670 vi->setOneLiner(tr("Connected, loading config"));
\r
673 boxstack->update(vi);
\r
675 VDR* vdr = VDR::getInstance();
\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
682 logger->log("Command", Log::INFO, "Turning on network logging");
\r
683 logger->setExternLogger(vdr);
\r
687 logger->unsetExternLogger();
\r
688 logger->log("Command", Log::INFO, "Turned off network logging");
\r
690 if (config) delete[] config;
\r
692 // See if config says to override video format (PAL/NTSC)
\r
693 config = vdr->configLoad("General", "Override Video Format");
\r
696 logger->log("Command", Log::DEBUG, "Override Video Format is present");
\r
698 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
\r
699 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
\r
701 // Oh sheesh, need to switch format. Bye bye TV...
\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
712 // Get video and osd back up with the new mode
\r
713 if (!strcmp(config, "PAL"))
\r
715 logger->log("Command", Log::DEBUG, "Switching to PAL");
\r
716 video->init(Video::PAL);
\r
718 else if (!strcmp(config, "NTSC"))
\r
720 logger->log("Command", Log::DEBUG, "Switching to NTSC");
\r
721 video->init(Video::NTSC);
\r
723 #ifndef __ANDROID__
\r
724 //we do not init twice
\r
725 osd->init((char*)("/dev/stbgfx"));
\r
728 // Put the wallpaper back
\r
731 // Re add the 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
738 vi->setPosition(160, 150);
\r
740 vi->setOneLiner(tr("Connected, loading config"));
\r
743 boxstack->update(vi);
\r
747 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
\r
752 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
\r
755 // Power off if first boot and config says so
\r
760 logger->log("Command", Log::DEBUG, "Load power after boot");
\r
762 config = vdr->configLoad("General", "Power After Boot");
\r
766 if (!STRCASECMP(config, "On"))
\r
768 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
\r
770 else if (!STRCASECMP(config, "Off"))
\r
772 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
\r
775 return; // quit here
\r
777 else if (!STRCASECMP(config, "Last state"))
\r
779 char* lastPowerState = vdr->configLoad("General", "Last Power State");
\r
780 if (lastPowerState)
\r
782 if (!STRCASECMP(lastPowerState, "On"))
\r
784 logger->log("Command", Log::INFO, "Config says Last Power State = On");
\r
786 else if (!STRCASECMP(lastPowerState, "Off"))
\r
788 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
\r
791 return; // quit here
\r
795 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
\r
800 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
\r
805 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
\r
811 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
\r
816 // Go S-Video if config says so
\r
818 config = vdr->configLoad("TV", "Connection");
\r
822 if (!STRCASECMP(config, "S-Video"))
\r
824 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
\r
825 video->setConnection(Video::SVIDEO);
\r
829 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
\r
830 video->setConnection(Video::COMPOSITERGB);
\r
836 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
\r
841 config = vdr->configLoad("General", "Remote type");
\r
845 if (!STRCASECMP(config, "New"))
\r
847 logger->log("Command", Log::INFO, "Switching to New remote type");
\r
848 remote->setRemoteType(Remote::NEWREMOTE);
\r
852 logger->log("Command", Log::INFO, "Switching to Old remote type");
\r
853 remote->setRemoteType(Remote::OLDREMOTE);
\r
859 logger->log("Command", Log::INFO, "Config General/Remote type not found");
\r
860 remote->setRemoteType(Remote::OLDREMOTE);
\r
866 // Get TV aspect ratio
\r
868 config = vdr->configLoad("TV", "Aspect");
\r
871 if (!STRCASECMP(config, "16:9"))
\r
873 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
\r
874 video->setTVsize(Video::ASPECT16X9);
\r
878 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
\r
879 video->setTVsize(Video::ASPECT4X3);
\r
885 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
\r
886 video->setTVsize(Video::ASPECT4X3);
\r
889 config = vdr->configLoad("TV", "Widemode");
\r
892 if (!STRCASECMP(config, "Letterbox"))
\r
894 logger->log("Command", Log::INFO, "Setting letterbox mode");
\r
895 video->setMode(Video::LETTERBOX);
\r
899 logger->log("Command", Log::INFO, "Setting chop-sides mode");
\r
900 video->setMode(Video::NORMAL);
\r
907 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting letterbox mode");
\r
908 video->setMode(Video::LETTERBOX);
\r
910 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
\r
911 video->setMode(Video::NORMAL);
\r
915 config = vdr->configLoad("Advanced", "TCP receive window");
\r
918 size_t newTCPsize = atoi(config);
\r
921 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
\r
922 vdr->setReceiveWindow(newTCPsize);
\r
926 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
\r
927 vdr->setReceiveWindow(2048); // Default
\r
930 config = vdr->configLoad("Advanced", "Disable WOL");
\r
933 if (!STRCASECMP(config, "Yes"))
\r
935 logger->log("Command", Log::INFO, "Config says disable WOL");
\r
936 Wol::getInstance()->setEnabled(false);
\r
940 logger->log("Command", Log::INFO, "Config says enable WOL");
\r
941 Wol::getInstance()->setEnabled(true);
\r
948 logger->log("Command", Log::INFO, "By default, enable WOL");
\r
949 Wol::getInstance()->setEnabled(true);
\r
951 /* device dependend config */
\r
952 audio->loadOptionsfromServer(vdr);
\r
953 video->loadOptionsfromServer(vdr);
\r
954 remote->loadOptionsfromServer(vdr);
\r
957 // Save power state = on
\r
959 vdr->configSave("General", "Last Power State", "On");
\r
961 // Make sure connection didn't die
\r
962 if (!vdr->isConnected())
\r
964 Command::getInstance()->connectionLost();
\r
968 boxstack->remove(vi);
\r
970 VWelcome* vw = new VWelcome();
\r
973 boxstack->update(vw);
\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