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);
144 pthread_mutex_unlock(&masterLock);
146 ReleaseMutex(masterLock);
149 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
150 // something happened, lock and process
153 pthread_mutex_lock(&masterLock);
155 WaitForSingleObject(masterLock, INFINITE );
158 if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
160 if (button != Remote::NA_SIGNAL) handleCommand(button);
161 processMessageQueue();
165 pthread_mutex_unlock(&masterLock);
167 ReleaseMutex(masterLock);
171 void Command::postMessage(Message* m)
173 // This is locked here in case the main loop is not waiting for an event, but is processing one
174 // it could be killed but then not react to it because the signal wouldn't cause
175 // remote->getButtonPress to break
176 // locking the mutex ensures that the master thread is waiting on getButtonPress
180 pthread_mutex_lock(&masterLock);
182 WaitForSingleObject(masterLock, INFINITE );
184 MessageQueue::postMessage(m);
187 kill(mainPid, SIGURG);
188 pthread_mutex_unlock(&masterLock);
190 ((RemoteWin*)Remote::getInstance())->Signal();
191 ReleaseMutex(masterLock);
195 void Command::postMessageNoLock(Message* m)
197 // As above but use this one if this message is being posted because of a button press
198 // the mutex is already locked, locking around postMessage is not needed as the
199 // queue is guaranteed to be run when the button has been processed
200 MessageQueue::postMessage(m);
203 bool Command::postMessageIfNotBusy(Message* m)
205 // This is for the timers module
206 // If the masterlock is locked then the timers module wants to
209 if (pthread_mutex_trylock(&masterLock) != EBUSY)
211 MessageQueue::postMessage(m);
212 kill(mainPid, SIGURG);
213 pthread_mutex_unlock(&masterLock);
221 switch (WaitForSingleObject(masterLock, 0 ))
222 { //FIXME this is not "if not busy" check
223 case WAIT_OBJECT_0: //but with proper argument 0 this did not work
224 // case WAIT_ABANDONED:
225 MessageQueue::postMessage(m);
226 ((RemoteWin*)Remote::getInstance())->Signal();
227 ReleaseMutex(masterLock);
230 case WAIT_ABANDONED: return false;
231 case WAIT_TIMEOUT: return false;
237 void Command::processMessage(Message* m)
239 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
243 case Message::STANDBY:
248 case Message::STOP_PLAYBACK:
250 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
253 case Message::STREAM_END:
255 VVideoLive::getInstance()->streamEnd();
258 case Message::VDR_CONNECTED:
260 doJustConnected((VConnect*)m->from);
265 // FIXME - go to one message queue only - then instead of having
266 // objects deriving from messagequeues, make them derive from
267 // messagereceiver - then one messagequeue can deliver any message to anywhere
271 ((TimerReceiver*)m->to)->timercall(m->parameter);
272 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
273 // run viewman message queue here. FIXME improve this!
276 case Message::SCREENSHOT:
278 Osd::getInstance()->screenShot("/out.jpg");
281 case Message::CONNECTION_LOST:
289 void Command::handleCommand(int button)
291 if (isStandby && (button != Remote::POWER)) return;
293 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
295 // command was not handled
299 case Remote::DF_LEFT:
300 case Remote::DF_RIGHT:
301 case Remote::VOLUMEUP:
302 case Remote::VOLUMEDOWN:
304 VVolume* v = new VVolume();
306 v->handleCommand(button); // this will draw+show
311 VMute* v = new VMute();
314 viewman->updateView(v);
324 if (!connLost) return; // if connLost, handle Remote::OK
334 Message* m = new Message(); // break into master mutex
335 m->message = Message::SCREENSHOT;
341 void Command::doStandby()
345 Video::getInstance()->signalOn();
346 Led::getInstance()->on();
350 VConnect* vconnect = new VConnect();
351 viewman->add(vconnect);
356 viewman->removeAll();
357 Video::getInstance()->signalOff();
358 viewman->updateView(wallpaper);
360 VDR::getInstance()->configSave("General", "Last Power State", "Off");
361 VDR::getInstance()->disconnect();
362 Led::getInstance()->off();
367 void Command::doFromTheTop(bool which)
371 connLost = new VInfo();
372 connLost->create(360, 200);
373 if (Video::getInstance()->getFormat() == Video::PAL)
374 connLost->setScreenPos(190, 170);
376 connLost->setScreenPos(180, 120);
377 connLost->setOneLiner(tr("Connection lost"));
378 connLost->setDropThrough();
379 connLost->setBorderOn(1);
380 connLost->setTitleBarColour(Colour::DANGER);
381 connLost->okButton();
383 viewman->add(connLost);
384 viewman->updateView(connLost);
385 remote->clearBuffer();
389 VDR::getInstance()->disconnect();
390 viewman->removeAll();
391 viewman->updateView(wallpaper);
393 VConnect* vconnect = new VConnect();
394 viewman->add(vconnect);
399 void Command::doReboot()
401 VDR::getInstance()->disconnect();
403 logger->log("Command", Log::NOTICE, "Reboot");
405 reboot(LINUX_REBOOT_CMD_RESTART);
406 #endif //Would we support this on windows?
409 void Command::connectionLost()
411 Message* m = new Message(); // break into master mutex
412 m->message = Message::CONNECTION_LOST;
414 postMessageNoLock(m);
417 void Command::doJustConnected(VConnect* vconnect)
420 Video* video = Video::getInstance();
421 viewman->removeView(vconnect);
423 VInfo* vi = new VInfo();
424 vi->create(400, 200);
425 if (video->getFormat() == Video::PAL)
426 vi->setScreenPos(170, 200);
428 vi->setScreenPos(160, 150);
430 vi->setOneLiner(tr("Connected, loading config"));
433 viewman->updateView(vi);
435 VDR* vdr = VDR::getInstance();
438 // See if config says to override video format (PAL/NTSC)
439 config = vdr->configLoad("General", "Override Video Format");
442 logger->log("Command", Log::DEBUG, "Override Video Format is present");
444 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
445 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
447 // Oh sheesh, need to switch format. Bye bye TV...
449 // Take everything down
450 viewman->removeAll();
451 viewman->removeView(wallpaper);
452 Osd* osd = Osd::getInstance();
456 // Get video and osd back up with the new mode
457 if (!strcmp(config, "PAL"))
459 logger->log("Command", Log::DEBUG, "Switching to PAL");
460 video->init(Video::PAL);
462 else if (!strcmp(config, "NTSC"))
464 logger->log("Command", Log::DEBUG, "Switching to NTSC");
465 video->init(Video::NTSC);
467 osd->init((char*)("/dev/stbgfx"));
469 // Put the wallpaper back
474 vi->create(400, 200);
475 if (video->getFormat() == Video::PAL)
476 vi->setScreenPos(170, 200);
478 vi->setScreenPos(160, 150);
480 vi->setOneLiner(tr("Connected, loading config"));
483 viewman->updateView(vi);
487 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
492 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
495 // Power off if first boot and config says so
500 logger->log("Command", Log::DEBUG, "Load power after boot");
502 config = vdr->configLoad("General", "Power After Boot");
506 if (!STRCASECMP(config, "On"))
508 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
510 else if (!STRCASECMP(config, "Off"))
512 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
517 else if (!STRCASECMP(config, "Last state"))
519 char* lastPowerState = vdr->configLoad("General", "Last Power State");
522 if (!STRCASECMP(lastPowerState, "On"))
524 logger->log("Command", Log::INFO, "Config says Last Power State = On");
526 else if (!STRCASECMP(lastPowerState, "Off"))
528 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
535 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
540 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
545 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
551 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
556 // Go S-Video if config says so
558 config = vdr->configLoad("TV", "Connection");
562 if (!STRCASECMP(config, "S-Video"))
564 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
565 video->setConnection(Video::SVIDEO);
569 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
570 video->setConnection(Video::COMPOSITERGB);
576 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
581 config = vdr->configLoad("General", "Remote type");
585 if (!STRCASECMP(config, "New"))
587 logger->log("Command", Log::INFO, "Switching to New remote type");
588 remote->setRemoteType(Remote::NEWREMOTE);
592 logger->log("Command", Log::INFO, "Switching to Old remote type");
593 remote->setRemoteType(Remote::OLDREMOTE);
599 logger->log("Command", Log::INFO, "Config General/Remote type not found");
600 remote->setRemoteType(Remote::OLDREMOTE);
603 // Get TV aspect ratio
605 config = vdr->configLoad("TV", "Aspect");
608 if (!STRCASECMP(config, "16:9"))
610 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
611 video->setTVsize(Video::ASPECT16X9);
615 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
616 video->setTVsize(Video::ASPECT4X3);
622 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
623 video->setTVsize(Video::ASPECT4X3);
626 config = vdr->configLoad("TV", "Widemode");
629 if (!STRCASECMP(config, "Letterbox"))
631 logger->log("Command", Log::INFO, "Setting letterbox mode");
632 video->setMode(Video::LETTERBOX);
636 logger->log("Command", Log::INFO, "Setting chop-sides mode");
637 video->setMode(Video::NORMAL);
643 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
644 video->setMode(Video::NORMAL);
647 config = vdr->configLoad("Advanced", "TCP receive window");
650 size_t newTCPsize = atoi(config);
653 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
654 vdr->setReceiveWindow(newTCPsize);
658 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
659 vdr->setReceiveWindow(2048); // Default
665 // Save power state = on
667 vdr->configSave("General", "Last Power State", "On");
669 // Make sure connection didn't die
670 if (!vdr->isConnected())
672 Command::getInstance()->connectionLost();
676 viewman->removeView(vi);
678 VWelcome* vw = new VWelcome();
681 viewman->updateView(vw);
683 // Enter pre-keys here
684 // handleCommand(Remote::THREE);
685 // handleCommand(Remote::DOWN);
686 // handleCommand(Remote::OK);
687 // handleCommand(Remote::PLAY);