2 Copyright 2004-2005 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, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "remotewin.h"
26 Command* Command::instance = NULL;
43 Command* Command::getInstance()
50 if (initted) return 0;
53 logger = Log::getInstance();
54 viewman = ViewMan::getInstance();
55 remote = Remote::getInstance();
57 if (!logger || !viewman || !remote)
63 pthread_mutex_init(&masterLock, NULL);
65 masterLock=CreateMutex(NULL,FALSE,NULL);
71 int Command::shutdown()
73 if (!initted) return 0;
80 // VDR::getInstance()->cancelFindingServer();
84 void Command::doWallpaper()
86 Video* video = Video::getInstance();
90 v->create(video->getScreenWidth(), video->getScreenHeight());
91 v->setBackgroundColour(Colour::VIDEOBLUE);
94 viewman->updateView(v);
95 viewman->removeView(v);
98 wallpaper = new VWallpaper();
99 if (video->getFormat() == Video::PAL)
101 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
102 wallpaper->init("/wallpaperPAL.jpg");
106 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
107 wallpaper->init("/wallpaperNTSC.jpg");
110 viewman->add(wallpaper);
111 viewman->updateView(wallpaper);
116 if (!initted) return;
123 Video::getInstance()->signalOn();
124 Led::getInstance()->on();
128 // End of startup. Lock the mutex and put the first view up
130 pthread_mutex_lock(&masterLock);
132 WaitForSingleObject(masterLock, INFINITE );
134 VConnect* vconnect = new VConnect();
135 viewman->add(vconnect);
143 pthread_mutex_unlock(&masterLock);
145 ReleaseMutex(masterLock);
147 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
148 // something happened, lock and process
151 pthread_mutex_lock(&masterLock);
153 WaitForSingleObject(masterLock, INFINITE );
156 if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
158 if (button != Remote::NA_SIGNAL) handleCommand(button);
159 processMessageQueue();
163 pthread_mutex_unlock(&masterLock);
165 ReleaseMutex(masterLock);
169 void Command::postMessage(Message* m)
171 // This is locked here in case the main loop is not waiting for an event, but is processing one
172 // it could be killed but then not react to it because the signal wouldn't cause
173 // remote->getButtonPress to break
174 // locking the mutex ensures that the master thread is waiting on getButtonPress
178 pthread_mutex_lock(&masterLock);
180 WaitForSingleObject(masterLock, INFINITE );
182 MessageQueue::postMessage(m);
185 kill(mainPid, SIGURG);
186 pthread_mutex_unlock(&masterLock);
188 ((RemoteWin*)Remote::getInstance())->Signal();
189 ReleaseMutex(masterLock);
193 void Command::postMessageNoLock(Message* m)
195 // As above but use this one if this message is being posted because of a button press
196 // the mutex is already locked, locking around postMessage is not needed as the
197 // queue is guaranteed to be run when the button has been processed
198 MessageQueue::postMessage(m);
201 bool Command::postMessageIfNotBusy(Message* m)
203 // This is for the timers module
204 // If the masterlock is locked then the timers module wants to
207 if (pthread_mutex_trylock(&masterLock) != EBUSY)
209 MessageQueue::postMessage(m);
210 kill(mainPid, SIGURG);
211 pthread_mutex_unlock(&masterLock);
219 switch (WaitForSingleObject(masterLock, 0 ))
220 { //FIXME this is not "if not busy" check
221 case WAIT_OBJECT_0: //but with proper argument 0 this did not work
222 // case WAIT_ABANDONED:
223 MessageQueue::postMessage(m);
224 ((RemoteWin*)Remote::getInstance())->Signal();
225 ReleaseMutex(masterLock);
228 case WAIT_ABANDONED: return false;
229 case WAIT_TIMEOUT: return false;
235 void Command::processMessage(Message* m)
237 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
241 case Message::STANDBY:
246 case Message::STOP_PLAYBACK:
248 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
251 case Message::STREAM_END:
253 VVideoLive::getInstance()->streamEnd();
256 case Message::VDR_CONNECTED:
258 doJustConnected((VConnect*)m->from);
263 // FIXME - go to one message queue only - then instead of having
264 // objects deriving from messagequeues, make them derive from
265 // messagereceiver - then one messagequeue can deliver any message to anywhere
269 ((TimerReceiver*)m->to)->timercall(m->parameter);
270 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
271 // run viewman message queue here. FIXME improve this!
274 case Message::SCREENSHOT:
276 Osd::getInstance()->screenShot("/out.jpg");
279 case Message::CONNECTION_LOST:
287 void Command::handleCommand(int button)
289 if (isStandby && (button != Remote::POWER)) return;
291 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
293 // command was not handled
297 case Remote::DF_LEFT:
298 case Remote::DF_RIGHT:
299 case Remote::VOLUMEUP:
300 case Remote::VOLUMEDOWN:
302 VVolume* v = new VVolume();
304 v->handleCommand(button); // this will draw+show
309 VMute* v = new VMute();
312 viewman->updateView(v);
322 if (!connLost) return; // if connLost, handle Remote::OK
332 Message* m = new Message(); // break into master mutex
333 m->message = Message::SCREENSHOT;
339 void Command::doStandby()
343 Video::getInstance()->signalOn();
344 Led::getInstance()->on();
348 VConnect* vconnect = new VConnect();
349 viewman->add(vconnect);
354 viewman->removeAll();
355 Video::getInstance()->signalOff();
356 viewman->updateView(wallpaper);
358 VDR::getInstance()->configSave("General", "Last Power State", "Off");
359 VDR::getInstance()->disconnect();
360 Led::getInstance()->off();
363 stop(); //different behavoiur on windows, we exit
368 void Command::doFromTheTop(bool which)
372 connLost = new VInfo();
373 connLost->create(360, 200);
374 if (Video::getInstance()->getFormat() == Video::PAL)
375 connLost->setScreenPos(190, 170);
377 connLost->setScreenPos(180, 120);
378 connLost->setOneLiner(tr("Connection lost"));
379 connLost->setDropThrough();
380 connLost->setBorderOn(1);
381 connLost->setTitleBarColour(Colour::DANGER);
382 connLost->okButton();
384 viewman->add(connLost);
385 viewman->updateView(connLost);
386 remote->clearBuffer();
390 VDR::getInstance()->disconnect();
391 viewman->removeAll();
392 viewman->updateView(wallpaper);
394 VConnect* vconnect = new VConnect();
395 viewman->add(vconnect);
400 void Command::doReboot()
402 VDR::getInstance()->disconnect();
404 logger->log("Command", Log::NOTICE, "Reboot");
406 reboot(LINUX_REBOOT_CMD_RESTART);
407 #endif //Would we support this on windows?
410 void Command::connectionLost()
412 Message* m = new Message(); // break into master mutex
413 m->message = Message::CONNECTION_LOST;
415 postMessageNoLock(m);
418 void Command::doJustConnected(VConnect* vconnect)
421 Video* video = Video::getInstance();
422 viewman->removeView(vconnect);
424 VInfo* vi = new VInfo();
425 vi->create(400, 200);
426 if (video->getFormat() == Video::PAL)
427 vi->setScreenPos(170, 200);
429 vi->setScreenPos(160, 150);
431 vi->setOneLiner(tr("Connected, loading config"));
434 viewman->updateView(vi);
436 VDR* vdr = VDR::getInstance();
439 // See if config says to override video format (PAL/NTSC)
440 config = vdr->configLoad("General", "Override Video Format");
443 logger->log("Command", Log::DEBUG, "Override Video Format is present");
445 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
446 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
448 // Oh sheesh, need to switch format. Bye bye TV...
450 // Take everything down
451 viewman->removeAll();
452 viewman->removeView(wallpaper);
453 Osd* osd = Osd::getInstance();
457 // Get video and osd back up with the new mode
458 if (!strcmp(config, "PAL"))
460 logger->log("Command", Log::DEBUG, "Switching to PAL");
461 video->init(Video::PAL);
463 else if (!strcmp(config, "NTSC"))
465 logger->log("Command", Log::DEBUG, "Switching to NTSC");
466 video->init(Video::NTSC);
468 osd->init((char*)("/dev/stbgfx"));
470 // Put the wallpaper back
475 vi->create(400, 200);
476 if (video->getFormat() == Video::PAL)
477 vi->setScreenPos(170, 200);
479 vi->setScreenPos(160, 150);
481 vi->setOneLiner(tr("Connected, loading config"));
484 viewman->updateView(vi);
488 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
493 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
496 // Power off if first boot and config says so
501 logger->log("Command", Log::DEBUG, "Load power after boot");
503 config = vdr->configLoad("General", "Power After Boot");
507 if (!STRCASECMP(config, "On"))
509 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
511 else if (!STRCASECMP(config, "Off"))
513 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
518 else if (!STRCASECMP(config, "Last state"))
520 char* lastPowerState = vdr->configLoad("General", "Last Power State");
523 if (!STRCASECMP(lastPowerState, "On"))
525 logger->log("Command", Log::INFO, "Config says Last Power State = On");
527 else if (!STRCASECMP(lastPowerState, "Off"))
529 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
536 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
541 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
546 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
552 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
557 // Go S-Video if config says so
559 config = vdr->configLoad("TV", "Connection");
563 if (!STRCASECMP(config, "S-Video"))
565 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
566 video->setConnection(Video::SVIDEO);
570 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
571 video->setConnection(Video::COMPOSITERGB);
577 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
582 config = vdr->configLoad("General", "Remote type");
586 if (!STRCASECMP(config, "New"))
588 logger->log("Command", Log::INFO, "Switching to New remote type");
589 remote->setRemoteType(Remote::NEWREMOTE);
593 logger->log("Command", Log::INFO, "Switching to Old remote type");
594 remote->setRemoteType(Remote::OLDREMOTE);
600 logger->log("Command", Log::INFO, "Config General/Remote type not found");
601 remote->setRemoteType(Remote::OLDREMOTE);
604 // Get TV aspect ratio
606 config = vdr->configLoad("TV", "Aspect");
609 if (!STRCASECMP(config, "16:9"))
611 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
612 video->setTVsize(Video::ASPECT16X9);
616 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
617 video->setTVsize(Video::ASPECT4X3);
623 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
624 video->setTVsize(Video::ASPECT4X3);
627 config = vdr->configLoad("TV", "Widemode");
630 if (!STRCASECMP(config, "Letterbox"))
632 logger->log("Command", Log::INFO, "Setting letterbox mode");
633 video->setMode(Video::LETTERBOX);
637 logger->log("Command", Log::INFO, "Setting chop-sides mode");
638 video->setMode(Video::NORMAL);
644 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
645 video->setMode(Video::NORMAL);
648 config = vdr->configLoad("Advanced", "TCP receive window");
651 size_t newTCPsize = atoi(config);
654 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
655 vdr->setReceiveWindow(newTCPsize);
659 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
660 vdr->setReceiveWindow(2048); // Default
666 // Save power state = on
668 vdr->configSave("General", "Last Power State", "On");
670 // Make sure connection didn't die
671 if (!vdr->isConnected())
673 Command::getInstance()->connectionLost();
677 viewman->removeView(vi);
679 VWelcome* vw = new VWelcome();
682 viewman->updateView(vw);
684 // Enter pre-keys here
685 // handleCommand(Remote::THREE);
686 // handleCommand(Remote::SKIPFORWARD);
687 // handleCommand(Remote::OK);
688 // handleCommand(Remote::PLAY);
689 // handleCommand(Remote::OK);
690 // handleCommand(Remote::DOWN);
691 // handleCommand(Remote::DOWN);
692 // handleCommand(Remote::DOWN);
693 // handleCommand(Remote::OK);