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;
39 Command* Command::getInstance()
46 if (initted) return 0;
49 logger = Log::getInstance();
50 viewman = ViewMan::getInstance();
51 remote = Remote::getInstance();
53 if (!logger || !viewman || !remote)
59 pthread_mutex_init(&masterLock, NULL);
64 int Command::shutdown()
66 if (!initted) return 0;
73 // VDR::getInstance()->cancelFindingServer();
84 Video* video = Video::getInstance();
86 UCHAR screenSize = video->getFormat();
88 // moved from startup because surface delete doesn't work
92 Led::getInstance()->on();
96 v->create(video->getScreenWidth(), video->getScreenHeight());
97 v->setBackgroundColour(Colour::VIDEOBLUE);
101 viewman->removeView(v);
104 wallpaper = new VWallpaper();
105 if (screenSize == Video::PAL)
107 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
108 wallpaper->init("/wallpaperPAL.jpg");
112 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
113 wallpaper->init("/wallpaperNTSC.jpg");
117 viewman->add(wallpaper);
119 // End of startup. Lock the mutex and put the first view up
121 pthread_mutex_lock(&masterLock);
124 VConnect* vconnect = new VConnect();
125 viewman->add(vconnect);
133 pthread_mutex_unlock(&masterLock);
134 logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
136 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
137 // something happened, lock and process
139 pthread_mutex_lock(&masterLock);
140 logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
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
158 pthread_mutex_lock(&masterLock);
159 logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
160 MessageQueue::postMessage(m);
161 kill(mainPid, SIGURG);
162 pthread_mutex_unlock(&masterLock);
163 logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
166 bool Command::postMessageIfNotBusy(Message* m)
168 // This is for the timers module
169 // If the masterlock is locked then the timers module wants to
172 if (pthread_mutex_trylock(&masterLock) != EBUSY)
174 logger->log("Command", Log::DEBUG, "LOCKED MASTER MUTEX");
175 MessageQueue::postMessage(m);
176 kill(mainPid, SIGURG);
177 pthread_mutex_unlock(&masterLock);
178 logger->log("Command", Log::DEBUG, "un-LOCKED MASTER MUTEX");
187 void Command::processMessage(Message* m)
189 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
193 case Message::STANDBY:
198 case Message::STOP_PLAYBACK:
200 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
203 case Message::STREAM_END:
205 // post a message to ViewMan and then run the viewman message queue
206 Message* m2 = new Message();
207 m2->message = Message::STREAM_END;
208 m2->to = VVideoLive::getInstance();
209 viewman->postMessage(m2);
210 handleCommand(Remote::NA_NONE);
213 case Message::VDR_CONNECTED:
215 doJustConnected((VConnect*)m->from);
220 // FIXME lock main mutex
221 // FIXME Reply - if messages are being processed then main loop is on processMessageQueue()
222 // -- this means the mutex is locked
224 // FIXME investigate whether timer can have fired, but waits on this mutex,
225 // a view is deleted, then the timer runs on a non-object
227 // FIXME - go to one message queue only - then instead of having
228 // objects deriving from messagequeues, make them derive from
229 // messagereceiver - then one messagequeue can deliver any message to anywhere
234 logger->log("Command", Log::DEBUG, "m = %p", m);
235 logger->log("Command", Log::DEBUG, "m->message = %i", m->message);
236 logger->log("Command", Log::DEBUG, "m->from = %p", m->from);
237 logger->log("Command", Log::DEBUG, "m->to = %p", m->to);
238 logger->log("Command", Log::DEBUG, "m->parameter = %p", m->parameter);
239 ((TimerReceiver*)m->to)->timercall(m->parameter);
240 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
241 // run viewman message queue here. FIXME improve this!
242 // FIXME unlock main mutex
247 void Command::handleCommand(int button)
249 if (isStandby && (button != Remote::POWER)) return;
251 if (viewman->handleCommand(button)) return;
253 // command was not handled
257 case Remote::DF_LEFT:
258 case Remote::DF_RIGHT:
259 case Remote::VOLUMEUP:
260 case Remote::VOLUMEDOWN:
262 VVolume* v = new VVolume();
263 v->handleCommand(button); // this will draw+show
269 VMute* v = new VMute();
283 Osd::getInstance()->screenShot("/out.jpg");
290 void Command::doStandby()
294 Video::getInstance()->signalOn();
295 Led::getInstance()->on();
299 VConnect* vconnect = new VConnect();
300 viewman->add(vconnect);
305 Video::getInstance()->signalOff();
306 viewman->removeAll();
309 VDR::getInstance()->configSave("General", "Last Power State", "Off");
310 VDR::getInstance()->disconnect();
311 Led::getInstance()->off();
316 void Command::doReboot()
318 VDR::getInstance()->disconnect();
320 logger->log("Command", Log::NOTICE, "Reboot");
321 reboot(LINUX_REBOOT_CMD_RESTART);
324 void Command::doJustConnected(VConnect* vconnect)
327 Video* video = Video::getInstance();
328 viewman->removeView(vconnect);
330 VInfo* vi = new VInfo();
331 vi->create(400, 200);
332 if (video->getFormat() == Video::PAL)
333 vi->setScreenPos(170, 200);
335 vi->setScreenPos(160, 150);
337 vi->setOneLiner(tr("Connected, loading config"));
343 VDR* vdr = VDR::getInstance();
346 // Power off if first boot and config says so
351 config = vdr->configLoad("General", "Power After Boot");
355 if (!strcasecmp(config, "On"))
357 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
359 else if (!strcasecmp(config, "Off"))
361 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
366 else if (!strcasecmp(config, "Last state"))
368 char* lastPowerState = vdr->configLoad("General", "Last Power State");
371 if (!strcasecmp(lastPowerState, "On"))
373 logger->log("Command", Log::INFO, "Config says Last Power State = On");
375 else if (!strcasecmp(lastPowerState, "Off"))
377 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
384 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
389 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
394 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
400 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
405 // Go S-Video if config says so
407 config = vdr->configLoad("TV", "Connection");
411 if (!strcasecmp(config, "S-Video"))
413 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
414 video->setConnection(Video::SVIDEO);
418 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
419 video->setConnection(Video::COMPOSITERGB);
425 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
430 config = vdr->configLoad("General", "Remote type");
434 if (!strcasecmp(config, "New"))
436 logger->log("Command", Log::INFO, "Switching to New remote type");
437 remote->setRemoteType(Remote::NEWREMOTE);
441 logger->log("Command", Log::INFO, "Switching to Old remote type");
442 remote->setRemoteType(Remote::OLDREMOTE);
448 logger->log("Command", Log::INFO, "Config General/Remote type not found");
449 remote->setRemoteType(Remote::OLDREMOTE);
452 // Get TV aspect ratio
454 config = vdr->configLoad("TV", "Aspect");
457 if (!strcasecmp(config, "16:9"))
459 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
460 video->setTVsize(Video::ASPECT16X9);
464 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
465 video->setTVsize(Video::ASPECT4X3);
471 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
472 video->setTVsize(Video::ASPECT4X3);
475 config = vdr->configLoad("TV", "Widemode");
478 if (!strcasecmp(config, "Letterbox"))
480 logger->log("Command", Log::INFO, "Setting letterbox mode");
481 video->setMode(Video::LETTERBOX);
485 logger->log("Command", Log::INFO, "Setting chop-sides mode");
486 video->setMode(Video::NORMAL);
492 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
493 video->setMode(Video::NORMAL);
498 // Save power state = on
500 vdr->configSave("General", "Last Power State", "On");
503 viewman->removeView(vi);
505 VWelcome* vw = new VWelcome();