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();
365 void Command::doFromTheTop(bool which)
369 connLost = new VInfo();
370 connLost->create(360, 200);
371 if (Video::getInstance()->getFormat() == Video::PAL)
372 connLost->setScreenPos(190, 170);
374 connLost->setScreenPos(180, 120);
375 connLost->setOneLiner(tr("Connection lost"));
376 connLost->setDropThrough();
377 connLost->setBorderOn(1);
378 connLost->setTitleBarColour(Colour::DANGER);
379 connLost->okButton();
381 viewman->add(connLost);
382 viewman->updateView(connLost);
383 remote->clearBuffer();
387 VDR::getInstance()->disconnect();
388 viewman->removeAll();
389 viewman->updateView(wallpaper);
391 VConnect* vconnect = new VConnect();
392 viewman->add(vconnect);
397 void Command::doReboot()
399 VDR::getInstance()->disconnect();
401 logger->log("Command", Log::NOTICE, "Reboot");
403 reboot(LINUX_REBOOT_CMD_RESTART);
404 #endif //Would we support this on windows?
407 void Command::connectionLost()
409 Message* m = new Message(); // break into master mutex
410 m->message = Message::CONNECTION_LOST;
412 postMessageNoLock(m);
415 void Command::doJustConnected(VConnect* vconnect)
418 Video* video = Video::getInstance();
419 viewman->removeView(vconnect);
421 VInfo* vi = new VInfo();
422 vi->create(400, 200);
423 if (video->getFormat() == Video::PAL)
424 vi->setScreenPos(170, 200);
426 vi->setScreenPos(160, 150);
428 vi->setOneLiner(tr("Connected, loading config"));
431 viewman->updateView(vi);
433 VDR* vdr = VDR::getInstance();
436 // See if config says to override video format (PAL/NTSC)
437 config = vdr->configLoad("General", "Override Video Format");
440 logger->log("Command", Log::DEBUG, "Override Video Format is present");
442 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
443 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
445 // Oh sheesh, need to switch format. Bye bye TV...
447 // Take everything down
448 viewman->removeAll();
449 viewman->removeView(wallpaper);
450 Osd* osd = Osd::getInstance();
454 // Get video and osd back up with the new mode
455 if (!strcmp(config, "PAL"))
457 logger->log("Command", Log::DEBUG, "Switching to PAL");
458 video->init(Video::PAL);
460 else if (!strcmp(config, "NTSC"))
462 logger->log("Command", Log::DEBUG, "Switching to NTSC");
463 video->init(Video::NTSC);
465 osd->init((char*)("/dev/stbgfx"));
467 // Put the wallpaper back
472 vi->create(400, 200);
473 if (video->getFormat() == Video::PAL)
474 vi->setScreenPos(170, 200);
476 vi->setScreenPos(160, 150);
478 vi->setOneLiner(tr("Connected, loading config"));
481 viewman->updateView(vi);
485 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
490 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
493 // Power off if first boot and config says so
498 logger->log("Command", Log::DEBUG, "Load power after boot");
500 config = vdr->configLoad("General", "Power After Boot");
504 if (!STRCASECMP(config, "On"))
506 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
508 else if (!STRCASECMP(config, "Off"))
510 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
515 else if (!STRCASECMP(config, "Last state"))
517 char* lastPowerState = vdr->configLoad("General", "Last Power State");
520 if (!STRCASECMP(lastPowerState, "On"))
522 logger->log("Command", Log::INFO, "Config says Last Power State = On");
524 else if (!STRCASECMP(lastPowerState, "Off"))
526 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
533 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
538 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
543 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
549 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
554 // Go S-Video if config says so
556 config = vdr->configLoad("TV", "Connection");
560 if (!STRCASECMP(config, "S-Video"))
562 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
563 video->setConnection(Video::SVIDEO);
567 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
568 video->setConnection(Video::COMPOSITERGB);
574 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
579 config = vdr->configLoad("General", "Remote type");
583 if (!STRCASECMP(config, "New"))
585 logger->log("Command", Log::INFO, "Switching to New remote type");
586 remote->setRemoteType(Remote::NEWREMOTE);
590 logger->log("Command", Log::INFO, "Switching to Old remote type");
591 remote->setRemoteType(Remote::OLDREMOTE);
597 logger->log("Command", Log::INFO, "Config General/Remote type not found");
598 remote->setRemoteType(Remote::OLDREMOTE);
601 // Get TV aspect ratio
603 config = vdr->configLoad("TV", "Aspect");
606 if (!STRCASECMP(config, "16:9"))
608 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
609 video->setTVsize(Video::ASPECT16X9);
613 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
614 video->setTVsize(Video::ASPECT4X3);
620 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
621 video->setTVsize(Video::ASPECT4X3);
624 config = vdr->configLoad("TV", "Widemode");
627 if (!STRCASECMP(config, "Letterbox"))
629 logger->log("Command", Log::INFO, "Setting letterbox mode");
630 video->setMode(Video::LETTERBOX);
634 logger->log("Command", Log::INFO, "Setting chop-sides mode");
635 video->setMode(Video::NORMAL);
641 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
642 video->setMode(Video::NORMAL);
645 config = vdr->configLoad("Advanced", "TCP receive window");
648 size_t newTCPsize = atoi(config);
651 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
652 vdr->setReceiveWindow(newTCPsize);
656 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
657 vdr->setReceiveWindow(2048); // Default
663 // Save power state = on
665 vdr->configSave("General", "Last Power State", "On");
667 // Make sure connection didn't die
668 if (!vdr->isConnected())
670 Command::getInstance()->connectionLost();
674 viewman->removeView(vi);
676 VWelcome* vw = new VWelcome();
679 viewman->updateView(vw);
681 // Enter pre-keys here
682 // handleCommand(Remote::THREE);
683 // handleCommand(Remote::SKIPFORWARD);
684 // handleCommand(Remote::OK);
685 // handleCommand(Remote::PLAY);
686 // handleCommand(Remote::OK);
687 // handleCommand(Remote::DOWN);
688 // handleCommand(Remote::DOWN);
689 // handleCommand(Remote::DOWN);
690 // handleCommand(Remote::OK);