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