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();
85 void Command::doWallpaper()
87 Video* video = Video::getInstance();
91 v->create(video->getScreenWidth(), video->getScreenHeight());
92 v->setBackgroundColour(Colour::VIDEOBLUE);
95 viewman->updateView(v);
96 viewman->removeView(v);
99 wallpaper = new VWallpaper();
100 if (video->getFormat() == Video::PAL)
102 logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
103 wallpaper->init("/wallpaperPAL.jpg");
107 logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
108 wallpaper->init("/wallpaperNTSC.jpg");
111 viewman->add(wallpaper);
112 viewman->updateView(wallpaper);
117 if (!initted) return;
124 Video::getInstance()->signalOn();
125 Led::getInstance()->on();
129 // End of startup. Lock the mutex and put the first view up
131 pthread_mutex_lock(&masterLock);
133 WaitForSingleObject(masterLock, INFINITE );
135 VConnect* vconnect = new VConnect();
136 viewman->add(vconnect);
139 // Start method 2 of getting commands in...
147 pthread_mutex_unlock(&masterLock);
149 ReleaseMutex(masterLock);
151 button = remote->getButtonPress(2); // FIXME why is this set to 2 and not 0? so it can quit
152 // something happened, lock and process
155 pthread_mutex_lock(&masterLock);
157 WaitForSingleObject(masterLock, INFINITE );
160 if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
162 if (button != Remote::NA_SIGNAL) handleCommand(button);
163 processMessageQueue();
167 pthread_mutex_unlock(&masterLock);
169 ReleaseMutex(masterLock);
173 void Command::postMessage(Message* m)
175 // This is locked here in case the main loop is not waiting for an event, but is processing one
176 // it could be killed but then not react to it because the signal wouldn't cause
177 // remote->getButtonPress to break
178 // locking the mutex ensures that the master thread is waiting on getButtonPress
182 pthread_mutex_lock(&masterLock);
184 WaitForSingleObject(masterLock, INFINITE );
186 MessageQueue::postMessage(m);
189 kill(mainPid, SIGURG);
190 pthread_mutex_unlock(&masterLock);
192 ((RemoteWin*)Remote::getInstance())->Signal();
193 ReleaseMutex(masterLock);
197 void Command::postMessageNoLock(Message* m)
199 // As above but use this one if this message is being posted because of a button press
200 // the mutex is already locked, locking around postMessage is not needed as the
201 // queue is guaranteed to be run when the button has been processed
202 MessageQueue::postMessage(m);
205 bool Command::postMessageIfNotBusy(Message* m)
207 // This is for the timers module
208 // If the masterlock is locked then the timers module wants to
211 if (pthread_mutex_trylock(&masterLock) != EBUSY)
213 MessageQueue::postMessage(m);
214 kill(mainPid, SIGURG);
215 pthread_mutex_unlock(&masterLock);
223 switch (WaitForSingleObject(masterLock, 0 ))
224 { //FIXME this is not "if not busy" check
225 case WAIT_OBJECT_0: //but with proper argument 0 this did not work
226 // case WAIT_ABANDONED:
227 MessageQueue::postMessage(m);
228 ((RemoteWin*)Remote::getInstance())->Signal();
229 ReleaseMutex(masterLock);
232 case WAIT_ABANDONED: return false;
233 case WAIT_TIMEOUT: return false;
239 void Command::processMessage(Message* m)
241 logger->log("Command", Log::DEBUG, "processing message %i", m->message);
243 // Timer handling is very weird at the mo. Take them out here and convert
244 if (m->message == Message::TIMER)
246 // FIXME - go to one message queue only - then instead of having
247 // objects deriving from messagequeues, make them derive from
248 // messagereceiver - then one messagequeue can deliver any message to anywhere
252 logger->log("Command", Log::DEBUG, "sending timer");
253 ((TimerReceiver*)m->to)->timercall(m->parameter);
254 // handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
255 // // run viewman message queue here. FIXME improve this!
258 else if (m->to == this)
262 case Message::STANDBY:
270 case Message::STOP_PLAYBACK:
272 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
275 case Message::STREAM_END:
277 VVideoLive::getInstance()->streamEnd();
281 // Also connection_lost comes from player - anywhere else?
285 case Message::VDR_CONNECTED:
287 doJustConnected((VConnect*)m->from);
290 case Message::SCREENSHOT:
292 Osd::getInstance()->screenShot("/out.jpg");
295 case Message::CONNECTION_LOST:
300 case Message::UDP_BUTTON:
302 handleCommand(m->parameter);
309 logger->log("Command", Log::DEBUG, "Sending message to viewman");
310 viewman->processMessage(m);
314 void Command::handleCommand(int button)
316 if (isStandby && (button != Remote::POWER)) return;
318 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
320 // command was not handled
324 case Remote::DF_LEFT:
325 case Remote::DF_RIGHT:
326 case Remote::VOLUMEUP:
327 case Remote::VOLUMEDOWN:
329 VVolume* v = new VVolume();
331 v->handleCommand(button); // this will draw+show
336 VMute* v = new VMute();
339 viewman->updateView(v);
349 if (!connLost) return; // if connLost, handle Remote::OK
359 Message* m = new Message(); // break into master mutex
360 m->message = Message::SCREENSHOT;
366 void Command::doStandby()
370 Video::getInstance()->signalOn();
371 Led::getInstance()->on();
375 VConnect* vconnect = new VConnect();
376 viewman->add(vconnect);
381 viewman->removeAll();
382 Video::getInstance()->signalOff();
383 viewman->updateView(wallpaper);
385 VDR::getInstance()->configSave("General", "Last Power State", "Off");
386 VDR::getInstance()->disconnect();
387 Led::getInstance()->off();
390 stop(); //different behavoiur on windows, we exit
395 void Command::doFromTheTop(bool which)
399 connLost = new VInfo();
400 connLost->create(360, 200);
401 if (Video::getInstance()->getFormat() == Video::PAL)
402 connLost->setScreenPos(190, 170);
404 connLost->setScreenPos(180, 120);
405 connLost->setOneLiner(tr("Connection lost"));
406 connLost->setDropThrough();
407 connLost->setBorderOn(1);
408 connLost->setTitleBarColour(Colour::DANGER);
409 connLost->okButton();
411 viewman->add(connLost);
412 viewman->updateView(connLost);
413 remote->clearBuffer();
417 VDR::getInstance()->disconnect();
418 viewman->removeAll();
419 viewman->updateView(wallpaper);
421 VConnect* vconnect = new VConnect();
422 viewman->add(vconnect);
427 void Command::doReboot()
429 VDR::getInstance()->disconnect();
431 logger->log("Command", Log::NOTICE, "Reboot");
433 reboot(LINUX_REBOOT_CMD_RESTART);
434 #endif //Would we support this on windows?
437 void Command::connectionLost()
439 Message* m = new Message(); // break into master mutex
440 m->message = Message::CONNECTION_LOST;
442 postMessageNoLock(m);
445 void Command::doJustConnected(VConnect* vconnect)
448 Video* video = Video::getInstance();
449 viewman->removeView(vconnect);
451 VInfo* vi = new VInfo();
452 vi->create(400, 200);
453 if (video->getFormat() == Video::PAL)
454 vi->setScreenPos(170, 200);
456 vi->setScreenPos(160, 150);
458 vi->setOneLiner(tr("Connected, loading config"));
461 viewman->updateView(vi);
463 VDR* vdr = VDR::getInstance();
466 // See if config says to override video format (PAL/NTSC)
467 config = vdr->configLoad("General", "Override Video Format");
470 logger->log("Command", Log::DEBUG, "Override Video Format is present");
472 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
473 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
475 // Oh sheesh, need to switch format. Bye bye TV...
477 // Take everything down
478 viewman->removeAll();
479 viewman->removeView(wallpaper);
480 Osd* osd = Osd::getInstance();
484 // Get video and osd back up with the new mode
485 if (!strcmp(config, "PAL"))
487 logger->log("Command", Log::DEBUG, "Switching to PAL");
488 video->init(Video::PAL);
490 else if (!strcmp(config, "NTSC"))
492 logger->log("Command", Log::DEBUG, "Switching to NTSC");
493 video->init(Video::NTSC);
495 osd->init((char*)("/dev/stbgfx"));
497 // Put the wallpaper back
502 vi->create(400, 200);
503 if (video->getFormat() == Video::PAL)
504 vi->setScreenPos(170, 200);
506 vi->setScreenPos(160, 150);
508 vi->setOneLiner(tr("Connected, loading config"));
511 viewman->updateView(vi);
515 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
520 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
523 // Power off if first boot and config says so
528 logger->log("Command", Log::DEBUG, "Load power after boot");
530 config = vdr->configLoad("General", "Power After Boot");
534 if (!STRCASECMP(config, "On"))
536 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
538 else if (!STRCASECMP(config, "Off"))
540 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
545 else if (!STRCASECMP(config, "Last state"))
547 char* lastPowerState = vdr->configLoad("General", "Last Power State");
550 if (!STRCASECMP(lastPowerState, "On"))
552 logger->log("Command", Log::INFO, "Config says Last Power State = On");
554 else if (!STRCASECMP(lastPowerState, "Off"))
556 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
563 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
568 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
573 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
579 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
584 // Go S-Video if config says so
586 config = vdr->configLoad("TV", "Connection");
590 if (!STRCASECMP(config, "S-Video"))
592 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
593 video->setConnection(Video::SVIDEO);
597 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
598 video->setConnection(Video::COMPOSITERGB);
604 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
609 config = vdr->configLoad("General", "Remote type");
613 if (!STRCASECMP(config, "New"))
615 logger->log("Command", Log::INFO, "Switching to New remote type");
616 remote->setRemoteType(Remote::NEWREMOTE);
620 logger->log("Command", Log::INFO, "Switching to Old remote type");
621 remote->setRemoteType(Remote::OLDREMOTE);
627 logger->log("Command", Log::INFO, "Config General/Remote type not found");
628 remote->setRemoteType(Remote::OLDREMOTE);
631 // Get TV aspect ratio
633 config = vdr->configLoad("TV", "Aspect");
636 if (!STRCASECMP(config, "16:9"))
638 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
639 video->setTVsize(Video::ASPECT16X9);
643 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
644 video->setTVsize(Video::ASPECT4X3);
650 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
651 video->setTVsize(Video::ASPECT4X3);
654 config = vdr->configLoad("TV", "Widemode");
657 if (!STRCASECMP(config, "Letterbox"))
659 logger->log("Command", Log::INFO, "Setting letterbox mode");
660 video->setMode(Video::LETTERBOX);
664 logger->log("Command", Log::INFO, "Setting chop-sides mode");
665 video->setMode(Video::NORMAL);
671 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
672 video->setMode(Video::NORMAL);
675 config = vdr->configLoad("Advanced", "TCP receive window");
678 size_t newTCPsize = atoi(config);
681 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
682 vdr->setReceiveWindow(newTCPsize);
686 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
687 vdr->setReceiveWindow(2048); // Default
693 // Save power state = on
695 vdr->configSave("General", "Last Power State", "On");
697 // Make sure connection didn't die
698 if (!vdr->isConnected())
700 Command::getInstance()->connectionLost();
704 viewman->removeView(vi);
706 VWelcome* vw = new VWelcome();
709 viewman->updateView(vw);
711 // Enter pre-keys here
712 // handleCommand(Remote::THREE);
713 // handleCommand(Remote::SKIPFORWARD);
714 // handleCommand(Remote::OK);
715 // handleCommand(Remote::PLAY);
716 // handleCommand(Remote::OK);
717 // handleCommand(Remote::DOWN);
718 // handleCommand(Remote::DOWN);
719 // handleCommand(Remote::DOWN);
720 // handleCommand(Remote::OK);