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);
62 masterLock=CreateMutex(NULL,FALSE,NULL);
68 int Command::shutdown()
70 if (!initted) return 0;
77 // VDR::getInstance()->cancelFindingServer();
81 void Command::doWallpaper()
83 Video* video = Video::getInstance();
87 v->create(video->getScreenWidth(), video->getScreenHeight());
88 v->setBackgroundColour(Colour::VIDEOBLUE);
91 viewman->updateView(v);
92 viewman->removeView(v);
95 wallpaper = new VWallpaper();
96 if (video->getFormat() == Video::PAL)
98 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
99 wallpaper->init("/wallpaperPAL.jpg");
103 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
104 wallpaper->init("/wallpaperNTSC.jpg");
107 viewman->add(wallpaper);
108 viewman->updateView(wallpaper);
113 if (!initted) return;
120 Video::getInstance()->signalOn();
121 Led::getInstance()->on();
125 // End of startup. Lock the mutex and put the first view up
127 pthread_mutex_lock(&masterLock);
129 WaitForSingleObject(masterLock, INFINITE );
131 VConnect* vconnect = new VConnect();
132 viewman->add(vconnect);
141 pthread_mutex_unlock(&masterLock);
143 ReleaseMutex(masterLock);
146 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
147 // something happened, lock and process
150 pthread_mutex_lock(&masterLock);
152 WaitForSingleObject(masterLock, INFINITE );
155 if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
157 if (button != Remote::NA_SIGNAL) handleCommand(button);
158 processMessageQueue();
162 pthread_mutex_unlock(&masterLock);
164 ReleaseMutex(masterLock);
168 void Command::postMessage(Message* m)
170 // This is locked here in case the main loop is not waiting for an event, but is processing one
171 // it could be killed but then not react to it because the signal wouldn't cause
172 // remote->getButtonPress to break
173 // locking the mutex ensures that the master thread is waiting on getButtonPress
177 pthread_mutex_lock(&masterLock);
179 WaitForSingleObject(masterLock, INFINITE );
181 MessageQueue::postMessage(m);
184 kill(mainPid, SIGURG);
185 pthread_mutex_unlock(&masterLock);
187 //TODO: send Window Message
188 ReleaseMutex(masterLock);
192 void Command::postMessageNoLock(Message* m)
194 // As above but use this one if this message is being posted because of a button press
195 // the mutex is already locked, locking around postMessage is not needed as the
196 // queue is guaranteed to be run when the button has been processed
197 MessageQueue::postMessage(m);
200 bool Command::postMessageIfNotBusy(Message* m)
202 // This is for the timers module
203 // If the masterlock is locked then the timers module wants to
206 if (pthread_mutex_trylock(&masterLock) != EBUSY)
208 MessageQueue::postMessage(m);
209 kill(mainPid, SIGURG);
210 pthread_mutex_unlock(&masterLock);
218 if (WaitForSingleObject(masterLock, INFINITE ) == WAIT_OBJECT_0)
220 MessageQueue::postMessage(m);
221 //TODO: send Window Message
222 ReleaseMutex(masterLock);
232 void Command::processMessage(Message* m)
234 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
238 case Message::STANDBY:
243 case Message::STOP_PLAYBACK:
245 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
248 case Message::STREAM_END:
250 VVideoLive::getInstance()->streamEnd();
253 case Message::VDR_CONNECTED:
255 doJustConnected((VConnect*)m->from);
260 // FIXME - go to one message queue only - then instead of having
261 // objects deriving from messagequeues, make them derive from
262 // messagereceiver - then one messagequeue can deliver any message to anywhere
266 ((TimerReceiver*)m->to)->timercall(m->parameter);
267 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
268 // run viewman message queue here. FIXME improve this!
271 case Message::SCREENSHOT:
273 Osd::getInstance()->screenShot("/out.jpg");
276 case Message::CONNECTION_LOST:
284 void Command::handleCommand(int button)
286 if (isStandby && (button != Remote::POWER)) return;
288 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
290 // command was not handled
294 case Remote::DF_LEFT:
295 case Remote::DF_RIGHT:
296 case Remote::VOLUMEUP:
297 case Remote::VOLUMEDOWN:
299 VVolume* v = new VVolume();
301 v->handleCommand(button); // this will draw+show
306 VMute* v = new VMute();
309 viewman->updateView(v);
319 if (!connLost) return; // if connLost, handle Remote::OK
329 Message* m = new Message(); // break into master mutex
330 m->message = Message::SCREENSHOT;
336 void Command::doStandby()
340 Video::getInstance()->signalOn();
341 Led::getInstance()->on();
345 VConnect* vconnect = new VConnect();
346 viewman->add(vconnect);
351 viewman->removeAll();
352 Video::getInstance()->signalOff();
353 viewman->updateView(wallpaper);
355 VDR::getInstance()->configSave("General", "Last Power State", "Off");
356 VDR::getInstance()->disconnect();
357 Led::getInstance()->off();
362 void Command::doFromTheTop(bool which)
366 connLost = new VInfo();
367 connLost->create(360, 200);
368 if (Video::getInstance()->getFormat() == Video::PAL)
369 connLost->setScreenPos(190, 170);
371 connLost->setScreenPos(180, 120);
372 connLost->setOneLiner(tr("Connection lost"));
373 connLost->setDropThrough();
374 connLost->setBorderOn(1);
375 connLost->setTitleBarColour(Colour::DANGER);
376 connLost->okButton();
378 viewman->add(connLost);
379 viewman->updateView(connLost);
380 remote->clearBuffer();
384 VDR::getInstance()->disconnect();
385 viewman->removeAll();
386 viewman->updateView(wallpaper);
388 VConnect* vconnect = new VConnect();
389 viewman->add(vconnect);
394 void Command::doReboot()
396 VDR::getInstance()->disconnect();
398 logger->log("Command", Log::NOTICE, "Reboot");
400 reboot(LINUX_REBOOT_CMD_RESTART);
401 #endif //Would we support this on windows?
404 void Command::connectionLost()
406 Message* m = new Message(); // break into master mutex
407 m->message = Message::CONNECTION_LOST;
409 postMessageNoLock(m);
412 void Command::doJustConnected(VConnect* vconnect)
415 Video* video = Video::getInstance();
416 viewman->removeView(vconnect);
418 VInfo* vi = new VInfo();
419 vi->create(400, 200);
420 if (video->getFormat() == Video::PAL)
421 vi->setScreenPos(170, 200);
423 vi->setScreenPos(160, 150);
425 vi->setOneLiner(tr("Connected, loading config"));
428 viewman->updateView(vi);
430 VDR* vdr = VDR::getInstance();
433 // See if config says to override video format (PAL/NTSC)
434 config = vdr->configLoad("General", "Override Video Format");
437 logger->log("Command", Log::DEBUG, "Override Video Format is present");
439 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
440 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
442 // Oh sheesh, need to switch format. Bye bye TV...
444 // Take everything down
445 viewman->removeAll();
446 viewman->removeView(wallpaper);
447 Osd* osd = Osd::getInstance();
451 // Get video and osd back up with the new mode
452 if (!strcmp(config, "PAL"))
454 logger->log("Command", Log::DEBUG, "Switching to PAL");
455 video->init(Video::PAL);
457 else if (!strcmp(config, "NTSC"))
459 logger->log("Command", Log::DEBUG, "Switching to NTSC");
460 video->init(Video::NTSC);
462 osd->init("/dev/stbgfx");
464 // Put the wallpaper back
469 vi->create(400, 200);
470 if (video->getFormat() == Video::PAL)
471 vi->setScreenPos(170, 200);
473 vi->setScreenPos(160, 150);
475 vi->setOneLiner(tr("Connected, loading config"));
478 viewman->updateView(vi);
482 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
487 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
490 // Power off if first boot and config says so
495 logger->log("Command", Log::DEBUG, "Load power after boot");
497 config = vdr->configLoad("General", "Power After Boot");
501 if (!STRCASECMP(config, "On"))
503 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
505 else if (!STRCASECMP(config, "Off"))
507 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
512 else if (!STRCASECMP(config, "Last state"))
514 char* lastPowerState = vdr->configLoad("General", "Last Power State");
517 if (!STRCASECMP(lastPowerState, "On"))
519 logger->log("Command", Log::INFO, "Config says Last Power State = On");
521 else if (!STRCASECMP(lastPowerState, "Off"))
523 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
530 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
535 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
540 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
546 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
551 // Go S-Video if config says so
553 config = vdr->configLoad("TV", "Connection");
557 if (!STRCASECMP(config, "S-Video"))
559 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
560 video->setConnection(Video::SVIDEO);
564 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
565 video->setConnection(Video::COMPOSITERGB);
571 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
576 config = vdr->configLoad("General", "Remote type");
580 if (!STRCASECMP(config, "New"))
582 logger->log("Command", Log::INFO, "Switching to New remote type");
583 remote->setRemoteType(Remote::NEWREMOTE);
587 logger->log("Command", Log::INFO, "Switching to Old remote type");
588 remote->setRemoteType(Remote::OLDREMOTE);
594 logger->log("Command", Log::INFO, "Config General/Remote type not found");
595 remote->setRemoteType(Remote::OLDREMOTE);
598 // Get TV aspect ratio
600 config = vdr->configLoad("TV", "Aspect");
603 if (!STRCASECMP(config, "16:9"))
605 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
606 video->setTVsize(Video::ASPECT16X9);
610 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
611 video->setTVsize(Video::ASPECT4X3);
617 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
618 video->setTVsize(Video::ASPECT4X3);
621 config = vdr->configLoad("TV", "Widemode");
624 if (!STRCASECMP(config, "Letterbox"))
626 logger->log("Command", Log::INFO, "Setting letterbox mode");
627 video->setMode(Video::LETTERBOX);
631 logger->log("Command", Log::INFO, "Setting chop-sides mode");
632 video->setMode(Video::NORMAL);
638 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
639 video->setMode(Video::NORMAL);
642 config = vdr->configLoad("Advanced", "TCP receive window");
645 size_t newTCPsize = atoi(config);
648 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
649 vdr->setReceiveWindow(newTCPsize);
653 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
654 vdr->setReceiveWindow(2048); // Default
660 // Save power state = on
662 vdr->configSave("General", "Last Power State", "On");
664 // Make sure connection didn't die
665 if (!vdr->isConnected())
667 Command::getInstance()->connectionLost();
671 viewman->removeView(vi);
673 VWelcome* vw = new VWelcome();
676 viewman->updateView(vw);
678 // Enter pre-keys here
679 // handleCommand(Remote::THREE);
680 // handleCommand(Remote::DOWN);
681 // handleCommand(Remote::OK);
682 // handleCommand(Remote::PLAY);