2 Copyright 2004-2020 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
20 // FIXME rename to Control and move stuff from main to here
23 #include <unistd.h> // for reboot
24 #include <linux/reboot.h>
25 #include <sys/reboot.h>
35 #include "inputandroid.h"
44 #include "vserverselect.h"
60 #include "sleeptimer.h"
62 #include "osdvector.h"
64 #include "vvideolivetv.h"
66 #include "imageloader.h"
69 #ifdef VOMP_PLATFORM_RASPBERRY
70 #include "ledraspberry.h"
71 #include "osdopenvg.h"
77 #include "windowsosd.h"
79 #include "osdwinpixel.h"
81 #include "osdwinvector.h"
91 static const char* TAG = "Control";
93 Control* Control::instance = NULL;
107 Control* Control::getInstance()
112 bool Control::init(bool tcrashed)
114 if (initted) return false;
116 logger = LogNT::getInstance();
120 SkinFactory::InitSkin(0);
122 // FIXME All constructors first which do very little & don't rely on presence of other objects.
123 // Then all inits. Inits retrieve pointers to other objects.
127 led = new Led_TYPE(); if (!led) throw 10;
128 if (!led->init(-1)) throw 11; // FIXME init(0) on Win32
130 timers = new Timers(); if (!timers) throw 20;
131 if (!timers->init()) throw 21;
133 video = new Video_TYPE(); if (!video) throw 30;
134 if (!video->init(Video::PAL)) throw 31;
136 audio = new Audio_TYPE(); if (!audio) throw 40;
137 if (!audio->init(Audio::MPEG2_PES)) throw 41;
139 imageLoader = new ImageLoader(); if (!imageLoader) throw 50;
140 if (!imageLoader->init()) throw 51;
142 osd = new Osd_TYPE(); if (!osd) throw 60;
143 if (!osd->init()) throw 61;
145 vdr = new VDR(); if (!vdr) throw 70;
146 if (!vdr->init()) throw 71;
148 boxstack = new BoxStack(); if (!boxstack) throw 80;
149 if (!boxstack->init()) throw 81;
151 sleepTimer = new SleepTimer(); if (!sleepTimer) throw 90;
153 wol = new Wol(); if (!wol) throw 100;
155 inputMan = new InputMan(); if (!inputMan) throw 110;
156 if (!inputMan->init()) throw 111;
161 if (e == 10) logger->crit(TAG, "LED module failed to create");
162 else if (e == 11) logger->crit(TAG, "LED module failed to initialise");
163 else if (e == 20) logger->crit(TAG, "Timers module failed to create");
164 else if (e == 21) logger->crit(TAG, "Timers module failed to initialise");
165 else if (e == 30) logger->crit(TAG, "Video module failed to create");
166 else if (e == 31) logger->crit(TAG, "Video module failed to initialise");
167 else if (e == 40) logger->crit(TAG, "Audio module failed to create");
168 else if (e == 41) logger->crit(TAG, "Audio module failed to initialise");
169 else if (e == 50) logger->crit(TAG, "ImageLoader module failed to create");
170 else if (e == 51) logger->crit(TAG, "ImageLoader module failed to initialise");
171 else if (e == 60) logger->crit(TAG, "OSD module failed to create");
172 else if (e == 61) logger->crit(TAG, "OSD module failed to initialise");
173 else if (e == 70) logger->crit(TAG, "VDR module failed to create");
174 else if (e == 71) logger->crit(TAG, "VDR module failed to initialise");
175 else if (e == 80) logger->crit(TAG, "BoxStack module failed to create");
176 else if (e == 81) logger->crit(TAG, "BoxStack module failed to initialise");
177 else if (e == 90) logger->crit(TAG, "SleepTimer module failed to create");
178 else if (e == 100) logger->crit(TAG, "WOL module failed to create");
179 else if (e == 110) logger->crit(TAG, "InputMan module failed to create");
180 else if (e == 111) logger->crit(TAG, "InputMan module failed to initialise");
197 boxstack->shutdown();
218 imageLoader->shutdown();
263 void Control::shutdown()
265 if (!initted) return;
270 inputMan->shutdown();
273 logger->info(TAG, "InputMan module shut down");
279 logger->info(TAG, "WOL module shut down");
286 logger->info(TAG, "SleepTimer module shut down");
291 boxstack->shutdown();
294 logger->info(TAG, "BoxStack module shut down");
302 logger->info(TAG, "VDR module shut down");
310 logger->info(TAG, "OSD module shut down");
315 imageLoader->shutdown();
318 logger->info(TAG, "ImageLoader shut down");
326 logger->info(TAG, "Audio module shut down");
334 logger->info(TAG, "Video module shut down");
342 logger->info(TAG, "Timers module shut down");
350 logger->info(TAG, "LED module shut down");
356 logger->info(TAG, "Request stop");
358 Message* m = new Message(); // break master loop
359 m->message = Message::SHUTDOWN;
360 m->p_to = Message::CONTROL;
364 void Control::doWallpaper()
367 Boxx* bbg = new Boxx();
368 bbg->setSize(video->getScreenWidth(), video->getScreenHeight());
370 bbg->fillColour(DrawStyle::WALLPAPER);
372 boxstack->update(bbg);
373 boxstack->remove(bbg);
376 wallpaper = new Boxx();
377 wallpaper->setSize(video->getScreenWidth(), video->getScreenHeight());
378 wallpaper->createBuffer();
379 wallpaper->setBackgroundColour(DrawStyle::WALLPAPER);
381 wallpaper_pict = new WJpegTYPE();
382 wallpaper_pict->setSize(video->getScreenWidth(), video->getScreenHeight());
384 if (video->getFormat() == Video::PAL)
386 logger->debug(TAG, "PAL wallpaper selected");
388 wallpaper_pict->init("/wallpaperPAL.jpg");
390 wallpaper_pict->init("wallpaperPAL.jpg");
395 logger->debug(TAG, "NTSC wallpaper selected");
396 wallpaper_pict->init("/wallpaperNTSC.jpg");
399 if (DrawStyle::WALLPAPER.alpha)
400 wallpaper_pict->setVisible(true);
402 wallpaper_pict->setVisible(false);
404 wallpaper->add(wallpaper_pict);
407 boxstack->add(wallpaper);
408 boxstack->update(wallpaper);
410 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
411 if (osdv) osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
416 if (!initted) return;
419 Video::getInstance()->signalOn();
420 Led::getInstance()->on();
430 VConnect* vconnect = new VConnect(); // Deleted when VConnect messages Control, and is boxstack->remove()'d
431 boxstack->add(vconnect);
437 //logger->debug(TAG, "Setting log trace only mode");
438 //logger->setTraceOnlyMode(false);
440 messageLoopRun = true;
445 boxstack->removeAllExceptWallpaper();
446 boxstack->remove(wallpaper);
447 delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
450 void Control::dispatchMessage(Message* m)
452 logger->debug(TAG, "processing message {}", m->message);
454 if (m->p_to == Message::CONTROL)
458 case Message::SHUTDOWN:
460 messageLoopRun = false;
463 case Message::STOP_PLAYBACK:
465 handleCommand(Input::STOP); // an odd way of doing it, but so simple
468 case Message::VDR_CONNECTED:
470 doJustConnected(static_cast<VConnect*>(m->from));
473 case Message::SCREENSHOT:
475 logger->info(TAG, "Screenshot Message arrived");
476 Osd::getInstance()->screenShot("out.jpg");
479 case Message::CONNECTION_LOST:
484 case Message::INPUT_EVENT:
486 logger->info(TAG, "INPUT_EVENT {}", m->parameter);
488 handleCommand(m->parameter);
491 case Message::CHANGE_LANGUAGE:
493 boxstack->removeAllExceptWallpaper();
494 boxstack->update(wallpaper);
496 if (!VDR::getInstance()->isConnected()) { connectionLost(); break; }
497 VWelcome* vw = new VWelcome();
500 boxstack->update(vw);
503 case Message::LAST_VIEW_CLOSE:
505 // Shouldn't be done like this. Some generic message pass back from vinfo perhaps
512 // VWelcome* vw = new VWelcome();
514 // boxstack->add(vw);
515 // boxstack->update(vw);
521 else if (m->p_to == Message::BOXSTACK)
523 boxstack->processMessage(m);
525 else if (m->p_to == Message::MOUSE_RECEIVER)
527 logger->debug(TAG, "Sending mouse message to boxstack for dispatch");
528 boxstack->processMessage(m);
533 m->to->processMessage(m);
536 logger->debug(TAG, "done processing message {}", m->message);
539 void Control::handleCommand(int button)
541 if (isStandby && (button != Input::POWER)
542 && (button != Input::POWERON)
543 && (button != Input::POWEROFF)) return;
545 if (!connLost && boxstack->handleCommand(button)) return; // don't send to boxstack if connLost
547 // command was not handled
551 case Input::VOLUMEUP:
552 case Input::VOLUMEDOWN:
554 if (inputMan->handlesVolume()) // CEC volume handler?
556 if (button == Input::VOLUMEDOWN)
557 inputMan->volumeDown();
559 inputMan->volumeUp();
563 VVolume* v = new VVolume();
565 v->handleCommand(button); // this will draw+show
571 if (inputMan->handlesVolume())
573 inputMan->volumeMute();
577 VMute* v = new VMute();
594 case Input::POWEROFF:
602 if (!connLost) return; // if connLost, handle Input::OK
608 logger->debug(TAG, "Handling sleeptimer go");
619 Message* m = new Message(); // break into master mutex
620 m->message = Message::SCREENSHOT;
621 m->p_to = Message::CONTROL;
627 void Control::doStandby()
640 void Control::doPowerOn()
644 Video::getInstance()->signalOn();
645 Led::getInstance()->on();
646 InputMan::getInstance()->changePowerState(true);
649 VConnect* vconnect = new VConnect();
650 boxstack->add(vconnect);
655 void Control::doPowerOff()
659 VDR::getInstance()->shutdownVDR();
660 boxstack->removeAllExceptWallpaper();
661 Video::getInstance()->signalOff();
662 boxstack->update(wallpaper);
664 VDR::getInstance()->configSave("General", "Last Power State", "Off");
665 logger->unsetExternLogger();
666 VDR::getInstance()->disconnect();
667 Led::getInstance()->off();
668 InputMan::getInstance()->changePowerState(false);
670 sleepTimer->shutdown();
674 void Control::doFromTheTop(bool which)
676 if (isStandby) return;
681 logger->info(TAG, "Connection lost dialog already present");
685 logger->info(TAG, "Doing connection lost dialog");
686 connLost = new VInfo();
687 connLost->setSize(360, 200);
688 connLost->createBuffer();
689 if (Video::getInstance()->getFormat() == Video::PAL)
690 connLost->setPosition(190, 170);
692 connLost->setPosition(180, 120);
693 connLost->setOneLiner(tr("Connection lost"));
694 connLost->setDropThrough();
695 connLost->setBorderOn(1);
696 connLost->setTitleBarColour(DrawStyle::DANGER);
697 connLost->okButton();
699 boxstack->add(connLost);
700 boxstack->update(connLost);
702 clearMQInputEvents();
706 logger->unsetExternLogger();
707 VDR::getInstance()->disconnect();
708 boxstack->removeAllExceptWallpaper();
709 boxstack->update(wallpaper);
714 // at this point, everything should be reset to first-go
716 VConnect* vconnect = new VConnect(); // deleted eventually in boxstack
717 boxstack->add(vconnect);
722 void Control::clearMQInputEvents()
724 std::lock_guard<std::mutex> lg(messageQueueMutex); // Get the lock
726 MQueueI i = messages.begin();
727 while(i != messages.end())
730 if (m->message == Message::INPUT_EVENT)
733 i = messages.erase(i);
742 void Control::doReboot()
745 logger->unsetExternLogger();
746 VDR::getInstance()->disconnect();
748 logger->info(TAG, "Reboot");
750 #ifndef VOMP_HAS_EXIT
751 // some plattforms, want a proper deinitialisation of their hardware before reboot
752 Osd::getInstance()->shutdown();
753 Audio::getInstance()->shutdown();
754 Video::getInstance()->shutdown();
755 InputMan::getInstance()->shutdown();
757 reboot(LINUX_REBOOT_CMD_RESTART);
758 // if reboot is not allowed -> stop
770 #endif //Would we support this on windows?
773 void Control::connectionLost()
775 logger->unsetExternLogger();
776 Message* m = new Message(); // break into master mutex
777 m->message = Message::CONNECTION_LOST;
778 m->p_to = Message::CONTROL;
782 void Control::buildCrashedBox()
784 VInfo* crash = new VInfo();
785 crash->setSize(360, 250);
786 crash->createBuffer();
787 if (Video::getInstance()->getFormat() == Video::PAL)
788 crash->setPosition(190, 146);
790 crash->setPosition(180, 96);
791 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.");
792 crash->setBorderOn(1);
793 crash->setTitleBarColour(DrawStyle::DANGER);
795 crash->setExitable();
797 boxstack->add(crash);
798 boxstack->update(crash);
801 int Control::getLangPref(bool subtitle, const char* langcode)
803 std::vector<struct ASLPref>::iterator itty=langcodes.begin();
804 char templangcode[4];
805 templangcode[0] = langcode[0];
806 templangcode[1] = langcode[1];
807 templangcode[2] = langcode[2];
808 templangcode[3] = '\0';
810 while (itty != langcodes.end())
812 size_t pos = (*itty).langcode.find(templangcode);
813 if (pos != std::string::npos)
815 //vector<struct ASLPref>::iterator itty2=langcodes.begin();
816 for (unsigned int i = 0; i < langcodes.size(); i++)
820 pref = langcodes[i].subtitlepref;
822 pref = langcodes[i].audiopref;
827 if (langcodes[i].subtitlepref==langpos) return i;
831 if (langcodes[i].audiopref==langpos) return i;
839 return langcodes.size(); //neutral
842 void Control::doJustConnected(VConnect* vconnect)
845 if (!VDR::getInstance()->isConnected()) { connectionLost(); return; }
846 logger->info(TAG, "Entering doJustConnected");
848 boxstack->remove(vconnect);
850 VInfo* vi = new VInfo();
851 vi->setSize(400, 200);
853 if (video->getFormat() == Video::PAL)
854 vi->setPosition(170, 200);
856 vi->setPosition(160, 150);
857 vi->setOneLiner(tr("Connected, loading config"));
860 boxstack->update(vi);
862 // FIXME make config system
866 // See if we're supposed to do network logging
867 config = vdr->configLoad("Advanced", "Network logging");
868 if (config && !STRCASECMP(config, "On"))
870 logger->info(TAG, "Turning on network logging");
871 logger->setExternLogger(vdr);
875 logger->unsetExternLogger();
876 logger->info(TAG, "Turned off network logging");
878 if (config) delete[] config;
880 config = vdr->configLoad("Advanced", "Skin Name");
883 const char **skinnames=SkinFactory::getSkinNames();
884 for (int i=0;i<SkinFactory::getNumberofSkins();i++)
886 if (!STRCASECMP(config, skinnames[i]))
888 SkinFactory::InitSkin(i);
894 if (wallpaper && wallpaper_pict)
896 if (DrawStyle::WALLPAPER.alpha)
897 wallpaper_pict->setVisible(true);
899 wallpaper_pict->setVisible(false);
902 boxstack->update(wallpaper);
907 SkinFactory::InitSkin(0);
910 // See if config says to override video format (PAL/NTSC)
911 config = vdr->configLoad("General", "Override Video Format");
914 logger->debug(TAG, "Override Video Format is present");
916 if ( (!strcmp(config, "PAL") && (video->getFormat() != Video::PAL))
917 || (!strcmp(config, "NTSC") && (video->getFormat() != Video::NTSC))
918 || (!strcmp(config, "PAL_M") && (video->getFormat() != Video::PAL_M))
919 || (!strcmp(config, "NTSC_J") && (video->getFormat() != Video::NTSC_J))
922 // Oh sheesh, need to switch format. Bye bye TV...
924 // Take everything down
925 boxstack->removeAllExceptWallpaper();
926 boxstack->remove(wallpaper);
927 delete wallpaper_pict; wallpaper_pict = NULL; wallpaper = NULL;
934 // FIXME FIXME FIXME why do this?
935 inputMan->shutdown(); // need on raspberry shut not do any harm, hopefully
938 // Get video and osd back up with the new mode
939 if (!strcmp(config, "PAL"))
941 logger->debug(TAG, "Switching to PAL");
942 video->init(Video::PAL);
944 else if (!strcmp(config, "NTSC"))
946 logger->debug(TAG, "Switching to NTSC");
947 video->init(Video::NTSC);
948 } else if (!strcmp(config, "PAL_M"))
950 logger->debug(TAG, "Switching to PAL_M");
951 video->init(Video::PAL_M);
952 } else if (!strcmp(config, "NTSC_J"))
954 logger->debug(TAG, "Switching to NTSC_J");
955 video->init(Video::NTSC_J);
960 //we do not init twice
964 // Put the wallpaper back
969 vi->setSize(400, 200);
971 if (video->getFormat() == Video::PAL)
972 vi->setPosition(170, 200);
974 vi->setPosition(160, 150);
976 vi->setOneLiner(tr("Connected, loading config"));
979 boxstack->update(vi);
983 logger->debug(TAG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
988 logger->debug(TAG, "Phew, no dangerous on-the-fly mode switching to do!");
991 // Power off if first boot and config says so
996 logger->debug(TAG, "Load power after boot");
998 config = vdr->configLoad("General", "Power After Boot");
1002 if (!STRCASECMP(config, "On"))
1004 logger->info(TAG, "Config says Power After Boot = On");
1006 else if (!STRCASECMP(config, "Off"))
1008 logger->info(TAG, "Config says Power After Boot = Off");
1011 return; // quit here
1013 else if (!STRCASECMP(config, "Last state"))
1015 char* lastPowerState = vdr->configLoad("General", "Last Power State");
1018 if (!STRCASECMP(lastPowerState, "On"))
1020 logger->info(TAG, "Config says Last Power State = On");
1022 else if (!STRCASECMP(lastPowerState, "Off"))
1024 logger->info(TAG, "Config says Last Power State = Off");
1027 return; // quit here
1031 logger->info(TAG, "Config General/Last Power State not understood");
1036 logger->info(TAG, "Config General/Last Power State not found");
1041 logger->info(TAG, "Config/Power After Boot not understood");
1047 logger->info(TAG, "Config General/Power After Boot not found");
1052 // Go S-Video if config says so
1054 config = vdr->configLoad("TV", "Connection");
1058 if (!STRCASECMP(config, "S-Video"))
1060 logger->info(TAG, "Switching to S-Video as Connection={}", config);
1061 video->setConnection(Video::SVIDEO);
1062 } else if (!STRCASECMP(config, "HDMI"))
1064 logger->info(TAG, "Switching to HDMI as Connection={}", config);
1065 video->setConnection(Video::HDMI);
1066 } else if (!STRCASECMP(config, "HDMI3D"))
1068 logger->info(TAG, "Switching to HDMI3D as Connection={}", config);
1069 video->setConnection(Video::HDMI3D);
1073 logger->info(TAG, "Switching to RGB/Composite as Connection={}", config);
1074 video->setConnection(Video::COMPOSITERGB);
1080 logger->info(TAG, "Config TV/S-Video not found");
1083 // Set to shutdown VDR if config says
1085 config = vdr->configLoad("General", "VDR shutdown");
1088 if (!STRCASECMP(config, "On"))
1090 logger->info(TAG, "Shutdown VDR when shutting down vomp");
1091 vdr->setVDRShutdown(true);
1093 else if (!STRCASECMP(config, "Off"))
1095 logger->info(TAG, "Shutdown only vomp");
1096 vdr->setVDRShutdown(false);
1101 logger->info(TAG, "Default shutdown only vomp");
1102 vdr->setVDRShutdown(false); // Default
1105 // Get TV aspect ratio
1107 config = vdr->configLoad("TV", "Aspect");
1110 if (!STRCASECMP(config, "16:9"))
1112 logger->info(TAG, "/// Switching to TV aspect 16:9");
1113 video->setTVsize(Video::ASPECT16X9);
1117 logger->info(TAG, "/// Switching to TV aspect 4:3");
1118 video->setTVsize(Video::ASPECT4X3);
1124 logger->info(TAG, "Config TV/Aspect type not found, going 4:3");
1125 video->setTVsize(Video::ASPECT4X3);
1128 config = vdr->configLoad("TV", "Widemode");
1131 if (!STRCASECMP(config, "Letterbox"))
1133 logger->info(TAG, "Setting letterbox mode");
1134 video->setMode(Video::LETTERBOX);
1138 logger->info(TAG, "Setting chop-sides mode");
1139 video->setMode(Video::NORMAL);
1146 logger->info(TAG, "Config TV/Widemode not found, Setting letterbox mode");
1147 video->setMode(Video::LETTERBOX);
1149 logger->info(TAG, "Config TV/Widemode not found, Setting chop-sides mode");
1150 video->setMode(Video::NORMAL);
1154 config = vdr->configLoad("Advanced", "TCP receive window");
1157 size_t newTCPsize = atoi(config);
1160 logger->info(TAG, "Setting TCP window size %i", newTCPsize);
1161 vdr->setReceiveWindow(newTCPsize);
1165 logger->info(TAG, "TCP window size not found, setting 2048");
1166 if (DEFAULT_TCP_WINDOWSIZE) vdr->setReceiveWindow(2048); // Default
1169 config = vdr->configLoad("Advanced", "Font Name");
1172 Osd::getInstance()->setFont(config);
1173 logger->info(TAG, "Setting Font to %s", config);
1179 // Set recording list type
1181 #ifdef ADVANCED_MENUES
1182 config = vdr->configLoad("Advanced", "Menu type");
1186 if (!STRCASECMP(config, "Advanced"))
1188 logger->info(TAG, "Switching to Advanced menu");
1193 logger->info(TAG, "Switching to Classic menu");
1200 logger->info(TAG, "Config General/menu type not found");
1205 config = vdr->configLoad("Advanced", "Disable WOL");
1208 if (!STRCASECMP(config, "Yes"))
1210 logger->info(TAG, "Config says disable WOL");
1211 Wol::getInstance()->setEnabled(false);
1215 logger->info(TAG, "Config says enable WOL");
1216 Wol::getInstance()->setEnabled(true);
1223 logger->info(TAG, "By default, enable WOL");
1224 Wol::getInstance()->setEnabled(true);
1226 /* device dependend config */
1227 audio->loadOptionsFromServer(vdr);
1228 video->loadOptionsFromServer(vdr);
1229 inputMan->loadOptionsFromServer(vdr);
1231 video->executePendingModeChanges();
1234 // Save power state = on
1236 vdr->configSave("General", "Last Power State", "On");
1238 // Make sure connection didn't die
1239 if (!vdr->isConnected())
1241 Control::getInstance()->connectionLost();
1245 boxstack->remove(vi);
1247 VWelcome* vw = new VWelcome();
1250 // No boxstack->update yet
1252 Config* localConfig = Config::getInstance();
1253 int startToLiveTV{};
1254 localConfig->getInt("main", "start_to_live_tv", startToLiveTV);
1257 std::shared_ptr<ChannelList> chanList = VDR::getInstance()->getChannelsList(VDR::VIDEO);
1258 if (chanList && chanList->size())
1260 Channel* chan = NULL;
1261 for (u4 i = 0; i < chanList->size(); i++)
1263 if ((*chanList)[i]->number == static_cast<u4>(startToLiveTV))
1265 chan = (*chanList)[i];
1271 VVideoLiveTV* v = new VVideoLiveTV(chanList, chan->number, NULL);
1277 // Could not find channel, no VVideoLiveTV was made, update vw instead
1278 boxstack->update(vw);
1283 Control::getInstance()->connectionLost();
1286 else // Not starting to live TV
1288 boxstack->update(vw);
1291 // Enter pre-keys here
1292 // handleCommand(Input::OK);
1293 // handleCommand(Input::THREE);
1294 // handleCommand(Input::SIX);
1295 // handleCommand(Input::UP);
1296 // handleCommand(Input::OK);
1297 // handleCommand(Input::OK);
1298 // handleCommand(Input::PLAY);
1299 // handleCommand(Input::DOWN);
1300 // handleCommand(Input::DOWN);
1301 // handleCommand(Input::DOWN);
1302 // handleCommand(Input::RIGHT);
1303 // handleCommand(Input::RED);