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 Command* Command::instance = NULL;
40 Command* Command::getInstance()
47 if (initted) return 0;
50 logger = Log::getInstance();
51 viewman = ViewMan::getInstance();
52 remote = Remote::getInstance();
54 if (!logger || !viewman || !remote)
60 pthread_mutex_init(&masterLock, NULL);
65 int Command::shutdown()
67 if (!initted) return 0;
74 // VDR::getInstance()->cancelFindingServer();
78 void Command::doWallpaper()
80 Video* video = Video::getInstance();
84 v->create(video->getScreenWidth(), video->getScreenHeight());
85 v->setBackgroundColour(Colour::VIDEOBLUE);
88 viewman->updateView(v);
89 viewman->removeView(v);
92 wallpaper = new VWallpaper();
93 if (video->getFormat() == Video::PAL)
95 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
96 wallpaper->init("/wallpaperPAL.jpg");
100 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
101 wallpaper->init("/wallpaperNTSC.jpg");
104 viewman->add(wallpaper);
105 viewman->updateView(wallpaper);
110 if (!initted) return;
116 Video::getInstance()->signalOn();
117 Led::getInstance()->on();
121 // End of startup. Lock the mutex and put the first view up
123 pthread_mutex_lock(&masterLock);
126 VConnect* vconnect = new VConnect();
127 viewman->add(vconnect);
135 pthread_mutex_unlock(&masterLock);
137 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
138 // something happened, lock and process
140 pthread_mutex_lock(&masterLock);
142 if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
144 if (button != Remote::NA_SIGNAL) handleCommand(button);
145 processMessageQueue();
148 pthread_mutex_unlock(&masterLock);
151 void Command::postMessage(Message* m)
153 // This is locked here in case the main loop is not waiting for an event, but is processing one
154 // it could be killed but then not react to it because the signal wouldn't cause
155 // remote->getButtonPress to break
156 // locking the mutex ensures that the master thread is waiting on getButtonPress
159 pthread_mutex_lock(&masterLock);
160 MessageQueue::postMessage(m);
161 kill(mainPid, SIGURG);
162 pthread_mutex_unlock(&masterLock);
165 void Command::postMessageNoLock(Message* m)
167 // As above but use this one if this message is being posted because of a button press
168 // the mutex is already locked, locking around postMessage is not needed as the
169 // queue is guaranteed to be run when the button has been processed
170 MessageQueue::postMessage(m);
173 bool Command::postMessageIfNotBusy(Message* m)
175 // This is for the timers module
176 // If the masterlock is locked then the timers module wants to
179 if (pthread_mutex_trylock(&masterLock) != EBUSY)
181 MessageQueue::postMessage(m);
182 kill(mainPid, SIGURG);
183 pthread_mutex_unlock(&masterLock);
192 void Command::processMessage(Message* m)
194 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
198 case Message::STANDBY:
203 case Message::STOP_PLAYBACK:
205 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
208 case Message::STREAM_END:
210 VVideoLive::getInstance()->streamEnd();
213 case Message::VDR_CONNECTED:
215 doJustConnected((VConnect*)m->from);
220 // FIXME - go to one message queue only - then instead of having
221 // objects deriving from messagequeues, make them derive from
222 // messagereceiver - then one messagequeue can deliver any message to anywhere
226 ((TimerReceiver*)m->to)->timercall(m->parameter);
227 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
228 // run viewman message queue here. FIXME improve this!
231 case Message::SCREENSHOT:
233 Osd::getInstance()->screenShot("/out.jpg");
236 case Message::CONNECTION_LOST:
244 void Command::handleCommand(int button)
246 if (isStandby && (button != Remote::POWER)) return;
248 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
250 // command was not handled
254 case Remote::DF_LEFT:
255 case Remote::DF_RIGHT:
256 case Remote::VOLUMEUP:
257 case Remote::VOLUMEDOWN:
259 VVolume* v = new VVolume();
261 v->handleCommand(button); // this will draw+show
266 VMute* v = new VMute();
269 viewman->updateView(v);
279 if (!connLost) return; // if connLost, handle Remote::OK
289 Message* m = new Message(); // break into master mutex
290 m->message = Message::SCREENSHOT;
296 void Command::doStandby()
300 Video::getInstance()->signalOn();
301 Led::getInstance()->on();
305 VConnect* vconnect = new VConnect();
306 viewman->add(vconnect);
311 viewman->removeAll();
312 Video::getInstance()->signalOff();
313 viewman->updateView(wallpaper);
315 VDR::getInstance()->configSave("General", "Last Power State", "Off");
316 VDR::getInstance()->disconnect();
317 Led::getInstance()->off();
322 void Command::doFromTheTop(bool which)
326 connLost = new VInfo();
327 connLost->create(360, 200);
328 if (Video::getInstance()->getFormat() == Video::PAL)
329 connLost->setScreenPos(190, 170);
331 connLost->setScreenPos(180, 120);
332 connLost->setOneLiner(tr("Connection lost"));
333 connLost->setDropThrough();
334 connLost->setBorderOn(1);
335 connLost->setTitleBarColour(Colour::DANGER);
336 connLost->okButton();
338 viewman->add(connLost);
339 viewman->updateView(connLost);
340 remote->clearBuffer();
344 VDR::getInstance()->disconnect();
345 viewman->removeAll();
346 viewman->updateView(wallpaper);
348 VConnect* vconnect = new VConnect();
349 viewman->add(vconnect);
354 void Command::doReboot()
356 VDR::getInstance()->disconnect();
358 logger->log("Command", Log::NOTICE, "Reboot");
359 reboot(LINUX_REBOOT_CMD_RESTART);
362 void Command::connectionLost()
364 Message* m = new Message(); // break into master mutex
365 m->message = Message::CONNECTION_LOST;
367 postMessageNoLock(m);
370 void Command::doJustConnected(VConnect* vconnect)
373 Video* video = Video::getInstance();
374 viewman->removeView(vconnect);
376 VInfo* vi = new VInfo();
377 vi->create(400, 200);
378 if (video->getFormat() == Video::PAL)
379 vi->setScreenPos(170, 200);
381 vi->setScreenPos(160, 150);
383 vi->setOneLiner(tr("Connected, loading config"));
386 viewman->updateView(vi);
388 VDR* vdr = VDR::getInstance();
391 // See if config says to override video format (PAL/NTSC)
392 config = vdr->configLoad("General", "Override Video Format");
395 logger->log("Command", Log::DEBUG, "Override Video Format is present");
397 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
398 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
400 // Oh sheesh, need to switch format. Bye bye TV...
402 // Take everything down
403 viewman->removeAll();
404 viewman->removeView(wallpaper);
405 Osd* osd = Osd::getInstance();
409 // Get video and osd back up with the new mode
410 if (!strcmp(config, "PAL"))
412 logger->log("Command", Log::DEBUG, "Switching to PAL");
413 video->init(Video::PAL);
415 else if (!strcmp(config, "NTSC"))
417 logger->log("Command", Log::DEBUG, "Switching to NTSC");
418 video->init(Video::NTSC);
420 osd->init("/dev/stbgfx");
422 // Put the wallpaper back
427 vi->create(400, 200);
428 if (video->getFormat() == Video::PAL)
429 vi->setScreenPos(170, 200);
431 vi->setScreenPos(160, 150);
433 vi->setOneLiner(tr("Connected, loading config"));
436 viewman->updateView(vi);
440 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
445 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
448 // Power off if first boot and config says so
453 logger->log("Command", Log::DEBUG, "Load power after boot");
455 config = vdr->configLoad("General", "Power After Boot");
459 if (!STRCASECMP(config, "On"))
461 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
463 else if (!STRCASECMP(config, "Off"))
465 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
470 else if (!STRCASECMP(config, "Last state"))
472 char* lastPowerState = vdr->configLoad("General", "Last Power State");
475 if (!STRCASECMP(lastPowerState, "On"))
477 logger->log("Command", Log::INFO, "Config says Last Power State = On");
479 else if (!STRCASECMP(lastPowerState, "Off"))
481 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
488 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
493 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
498 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
504 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
509 // Go S-Video if config says so
511 config = vdr->configLoad("TV", "Connection");
515 if (!STRCASECMP(config, "S-Video"))
517 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
518 video->setConnection(Video::SVIDEO);
522 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
523 video->setConnection(Video::COMPOSITERGB);
529 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
534 config = vdr->configLoad("General", "Remote type");
538 if (!STRCASECMP(config, "New"))
540 logger->log("Command", Log::INFO, "Switching to New remote type");
541 remote->setRemoteType(Remote::NEWREMOTE);
545 logger->log("Command", Log::INFO, "Switching to Old remote type");
546 remote->setRemoteType(Remote::OLDREMOTE);
552 logger->log("Command", Log::INFO, "Config General/Remote type not found");
553 remote->setRemoteType(Remote::OLDREMOTE);
556 // Get TV aspect ratio
558 config = vdr->configLoad("TV", "Aspect");
561 if (!STRCASECMP(config, "16:9"))
563 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
564 video->setTVsize(Video::ASPECT16X9);
568 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
569 video->setTVsize(Video::ASPECT4X3);
575 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
576 video->setTVsize(Video::ASPECT4X3);
579 config = vdr->configLoad("TV", "Widemode");
582 if (!STRCASECMP(config, "Letterbox"))
584 logger->log("Command", Log::INFO, "Setting letterbox mode");
585 video->setMode(Video::LETTERBOX);
589 logger->log("Command", Log::INFO, "Setting chop-sides mode");
590 video->setMode(Video::NORMAL);
596 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
597 video->setMode(Video::NORMAL);
600 config = vdr->configLoad("Advanced", "TCP receive window");
603 size_t newTCPsize = atoi(config);
606 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
607 vdr->setReceiveWindow(newTCPsize);
611 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
612 vdr->setReceiveWindow(2048); // Default
618 // Save power state = on
620 vdr->configSave("General", "Last Power State", "On");
622 // Make sure connection didn't die
623 if (!vdr->isConnected())
625 Command::getInstance()->connectionLost();
629 viewman->removeView(vi);
631 VWelcome* vw = new VWelcome();
634 viewman->updateView(vw);
636 // Enter pre-keys here
637 // handleCommand(Remote::THREE);
638 // handleCommand(Remote::DOWN);
639 // handleCommand(Remote::OK);
640 // handleCommand(Remote::PLAY);