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);
245 case Message::STANDBY:
250 case Message::STOP_PLAYBACK:
252 handleCommand(Remote::STOP); // an odd way of doing it, but so simple
255 case Message::STREAM_END:
257 VVideoLive::getInstance()->streamEnd();
260 case Message::VDR_CONNECTED:
262 doJustConnected((VConnect*)m->from);
267 // FIXME - go to one message queue only - then instead of having
268 // objects deriving from messagequeues, make them derive from
269 // messagereceiver - then one messagequeue can deliver any message to anywhere
273 ((TimerReceiver*)m->to)->timercall(m->parameter);
274 handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
275 // run viewman message queue here. FIXME improve this!
278 case Message::SCREENSHOT:
280 Osd::getInstance()->screenShot("/out.jpg");
283 case Message::CONNECTION_LOST:
288 case Message::UDP_BUTTON:
290 handleCommand(m->parameter);
296 void Command::handleCommand(int button)
298 if (isStandby && (button != Remote::POWER)) return;
300 if (!connLost && viewman->handleCommand(button)) return; // don't send to viewman if connLost
302 // command was not handled
306 case Remote::DF_LEFT:
307 case Remote::DF_RIGHT:
308 case Remote::VOLUMEUP:
309 case Remote::VOLUMEDOWN:
311 VVolume* v = new VVolume();
313 v->handleCommand(button); // this will draw+show
318 VMute* v = new VMute();
321 viewman->updateView(v);
331 if (!connLost) return; // if connLost, handle Remote::OK
341 Message* m = new Message(); // break into master mutex
342 m->message = Message::SCREENSHOT;
348 void Command::doStandby()
352 Video::getInstance()->signalOn();
353 Led::getInstance()->on();
357 VConnect* vconnect = new VConnect();
358 viewman->add(vconnect);
363 viewman->removeAll();
364 Video::getInstance()->signalOff();
365 viewman->updateView(wallpaper);
367 VDR::getInstance()->configSave("General", "Last Power State", "Off");
368 VDR::getInstance()->disconnect();
369 Led::getInstance()->off();
372 stop(); //different behavoiur on windows, we exit
377 void Command::doFromTheTop(bool which)
381 connLost = new VInfo();
382 connLost->create(360, 200);
383 if (Video::getInstance()->getFormat() == Video::PAL)
384 connLost->setScreenPos(190, 170);
386 connLost->setScreenPos(180, 120);
387 connLost->setOneLiner(tr("Connection lost"));
388 connLost->setDropThrough();
389 connLost->setBorderOn(1);
390 connLost->setTitleBarColour(Colour::DANGER);
391 connLost->okButton();
393 viewman->add(connLost);
394 viewman->updateView(connLost);
395 remote->clearBuffer();
399 VDR::getInstance()->disconnect();
400 viewman->removeAll();
401 viewman->updateView(wallpaper);
403 VConnect* vconnect = new VConnect();
404 viewman->add(vconnect);
409 void Command::doReboot()
411 VDR::getInstance()->disconnect();
413 logger->log("Command", Log::NOTICE, "Reboot");
415 reboot(LINUX_REBOOT_CMD_RESTART);
416 #endif //Would we support this on windows?
419 void Command::connectionLost()
421 Message* m = new Message(); // break into master mutex
422 m->message = Message::CONNECTION_LOST;
424 postMessageNoLock(m);
427 void Command::doJustConnected(VConnect* vconnect)
430 Video* video = Video::getInstance();
431 viewman->removeView(vconnect);
433 VInfo* vi = new VInfo();
434 vi->create(400, 200);
435 if (video->getFormat() == Video::PAL)
436 vi->setScreenPos(170, 200);
438 vi->setScreenPos(160, 150);
440 vi->setOneLiner(tr("Connected, loading config"));
443 viewman->updateView(vi);
445 VDR* vdr = VDR::getInstance();
448 // See if config says to override video format (PAL/NTSC)
449 config = vdr->configLoad("General", "Override Video Format");
452 logger->log("Command", Log::DEBUG, "Override Video Format is present");
454 if ( (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
455 || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL)) )
457 // Oh sheesh, need to switch format. Bye bye TV...
459 // Take everything down
460 viewman->removeAll();
461 viewman->removeView(wallpaper);
462 Osd* osd = Osd::getInstance();
466 // Get video and osd back up with the new mode
467 if (!strcmp(config, "PAL"))
469 logger->log("Command", Log::DEBUG, "Switching to PAL");
470 video->init(Video::PAL);
472 else if (!strcmp(config, "NTSC"))
474 logger->log("Command", Log::DEBUG, "Switching to NTSC");
475 video->init(Video::NTSC);
477 osd->init((char*)("/dev/stbgfx"));
479 // Put the wallpaper back
484 vi->create(400, 200);
485 if (video->getFormat() == Video::PAL)
486 vi->setScreenPos(170, 200);
488 vi->setScreenPos(160, 150);
490 vi->setOneLiner(tr("Connected, loading config"));
493 viewman->updateView(vi);
497 logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
502 logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
505 // Power off if first boot and config says so
510 logger->log("Command", Log::DEBUG, "Load power after boot");
512 config = vdr->configLoad("General", "Power After Boot");
516 if (!STRCASECMP(config, "On"))
518 logger->log("Command", Log::INFO, "Config says Power After Boot = On");
520 else if (!STRCASECMP(config, "Off"))
522 logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
527 else if (!STRCASECMP(config, "Last state"))
529 char* lastPowerState = vdr->configLoad("General", "Last Power State");
532 if (!STRCASECMP(lastPowerState, "On"))
534 logger->log("Command", Log::INFO, "Config says Last Power State = On");
536 else if (!STRCASECMP(lastPowerState, "Off"))
538 logger->log("Command", Log::INFO, "Config says Last Power State = Off");
545 logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
550 logger->log("Command", Log::INFO, "Config General/Last Power State not found");
555 logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
561 logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
566 // Go S-Video if config says so
568 config = vdr->configLoad("TV", "Connection");
572 if (!STRCASECMP(config, "S-Video"))
574 logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
575 video->setConnection(Video::SVIDEO);
579 logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
580 video->setConnection(Video::COMPOSITERGB);
586 logger->log("Command", Log::INFO, "Config TV/S-Video not found");
591 config = vdr->configLoad("General", "Remote type");
595 if (!STRCASECMP(config, "New"))
597 logger->log("Command", Log::INFO, "Switching to New remote type");
598 remote->setRemoteType(Remote::NEWREMOTE);
602 logger->log("Command", Log::INFO, "Switching to Old remote type");
603 remote->setRemoteType(Remote::OLDREMOTE);
609 logger->log("Command", Log::INFO, "Config General/Remote type not found");
610 remote->setRemoteType(Remote::OLDREMOTE);
613 // Get TV aspect ratio
615 config = vdr->configLoad("TV", "Aspect");
618 if (!STRCASECMP(config, "16:9"))
620 logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
621 video->setTVsize(Video::ASPECT16X9);
625 logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
626 video->setTVsize(Video::ASPECT4X3);
632 logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
633 video->setTVsize(Video::ASPECT4X3);
636 config = vdr->configLoad("TV", "Widemode");
639 if (!STRCASECMP(config, "Letterbox"))
641 logger->log("Command", Log::INFO, "Setting letterbox mode");
642 video->setMode(Video::LETTERBOX);
646 logger->log("Command", Log::INFO, "Setting chop-sides mode");
647 video->setMode(Video::NORMAL);
653 logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
654 video->setMode(Video::NORMAL);
657 config = vdr->configLoad("Advanced", "TCP receive window");
660 size_t newTCPsize = atoi(config);
663 logger->log("Command", Log::INFO, "Setting TCP window size %i", newTCPsize);
664 vdr->setReceiveWindow(newTCPsize);
668 logger->log("Command", Log::INFO, "TCP window size not found, setting 2048");
669 vdr->setReceiveWindow(2048); // Default
675 // Save power state = on
677 vdr->configSave("General", "Last Power State", "On");
679 // Make sure connection didn't die
680 if (!vdr->isConnected())
682 Command::getInstance()->connectionLost();
686 viewman->removeView(vi);
688 VWelcome* vw = new VWelcome();
691 viewman->updateView(vw);
693 // Enter pre-keys here
694 // handleCommand(Remote::THREE);
695 // handleCommand(Remote::SKIPFORWARD);
696 // handleCommand(Remote::OK);
697 // handleCommand(Remote::PLAY);
698 // handleCommand(Remote::OK);
699 // handleCommand(Remote::DOWN);
700 // handleCommand(Remote::DOWN);
701 // handleCommand(Remote::DOWN);
702 // handleCommand(Remote::OK);