]> git.vomp.tv Git - vompclient.git/blob - command.cc
EPG tweaks, EPG made NTSC compatible
[vompclient.git] / command.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
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.
10
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.
15
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
19 */
20
21 #include "command.h"
22
23 Command* Command::instance = NULL;
24
25 Command::Command()
26 {
27   if (instance) return;
28   instance = this;
29   initted = 0;
30   isStandby = 0;
31   firstBoot = 1;
32 }
33
34 Command::~Command()
35 {
36   instance = NULL;
37 }
38
39 Command* Command::getInstance()
40 {
41   return instance;
42 }
43
44 int Command::init()
45 {
46   if (initted) return 0;
47   initted = 1;
48
49   logger = Log::getInstance();
50   viewman = ViewMan::getInstance();
51   remote = Remote::getInstance();
52
53   if (!logger || !viewman || !remote)
54   {
55     initted = 0;
56     return 0;
57   }
58
59   pthread_mutex_init(&masterLock, NULL);
60
61   return 1;
62 }
63
64 int Command::shutdown()
65 {
66   if (!initted) return 0;
67   initted = 0;
68   return 1;
69 }
70
71 void Command::stop()
72 {
73 //  VDR::getInstance()->cancelFindingServer();
74   irun = 0;
75 }
76
77 void Command::doWallpaper()
78 {
79   Video* video = Video::getInstance();
80
81   // Blue background
82   View* v = new View();
83   v->create(video->getScreenWidth(), video->getScreenHeight());
84   v->setBackgroundColour(Colour::VIDEOBLUE);
85   v->draw();
86   viewman->add(v);
87   viewman->updateView(v);
88   viewman->removeView(v);
89
90   // Wallpaper
91   wallpaper = new VWallpaper();
92   if (video->getFormat() == Video::PAL)
93   {
94     logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
95     wallpaper->init("/wallpaperPAL.jpg");
96   }
97   else
98   {
99     logger->log("Command", Log::DEBUG, "NTSC wallpaper selected");
100     wallpaper->init("/wallpaperNTSC.jpg");
101   }
102   wallpaper->draw();
103   viewman->add(wallpaper);
104   viewman->updateView(wallpaper);
105 }
106
107 void Command::run()
108 {
109   if (!initted) return;
110   irun = 1;
111
112   mainPid = getpid();
113
114   // just in case
115   Video::getInstance()->signalOn();
116   Led::getInstance()->on();
117
118   doWallpaper();
119
120   // End of startup. Lock the mutex and put the first view up
121
122   pthread_mutex_lock(&masterLock);
123
124
125   VConnect* vconnect = new VConnect();
126   viewman->add(vconnect);
127   vconnect->run();
128
129
130   UCHAR button = 0;
131   while(irun)
132   {
133     // unlock and wait
134     pthread_mutex_unlock(&masterLock);
135
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
138
139     pthread_mutex_lock(&masterLock);
140
141     if ((button == Remote::NA_NONE) || (button == Remote::NA_UNKNOWN)) continue;
142
143     if (button != Remote::NA_SIGNAL) handleCommand(button);
144     processMessageQueue();
145   }
146
147   pthread_mutex_unlock(&masterLock);
148 }
149
150 void Command::postMessage(Message* m)
151 {
152   // This is locked here in case the main loop is not waiting for an event, but is processing one
153   // it could be killed but then not react to it because the signal wouldn't cause
154   // remote->getButtonPress to break
155   // locking the mutex ensures that the master thread is waiting on getButtonPress
156
157   pthread_mutex_lock(&masterLock);
158   MessageQueue::postMessage(m);
159   kill(mainPid, SIGURG);
160   pthread_mutex_unlock(&masterLock);
161 }
162
163 bool Command::postMessageIfNotBusy(Message* m)
164 {
165   // This is for the timers module
166   // If the masterlock is locked then the timers module wants to
167   // cancel delivery
168
169   if (pthread_mutex_trylock(&masterLock) != EBUSY)
170   {
171     MessageQueue::postMessage(m);
172     kill(mainPid, SIGURG);
173     pthread_mutex_unlock(&masterLock);
174     return true;
175   }
176   else
177   {
178     return false;
179   }
180 }
181
182 void Command::processMessage(Message* m)
183 {
184   logger->log("Command", Log::DEBUG, "processing message %i", m->message);
185
186   switch(m->message)
187   {
188     case Message::STANDBY:
189     {
190       doStandby();
191       break;
192     }
193     case Message::STOP_PLAYBACK:
194     {
195       handleCommand(Remote::STOP); // an odd way of doing it, but so simple
196       break;
197     }
198     case Message::STREAM_END:
199     {
200       // post a message to ViewMan and then run the viewman message queue
201       Message* m2 = new Message();
202       m2->message = Message::STREAM_END;
203       m2->to = VVideoLive::getInstance();
204       viewman->postMessage(m2);
205       handleCommand(Remote::NA_NONE);
206       break;
207     }
208     case Message::VDR_CONNECTED:
209     {
210       doJustConnected((VConnect*)m->from);
211       break;
212     }
213     case Message::TIMER:
214     {
215       // FIXME - go to one message queue only - then instead of having
216       // objects deriving from messagequeues, make them derive from
217       // messagereceiver - then one messagequeue can deliver any message to anywhere
218
219       // deliver timer
220
221       ((TimerReceiver*)m->to)->timercall(m->parameter);
222       handleCommand(Remote::NA_NONE); // in case any timer has posted messages to viewman,
223                                       // run viewman message queue here. FIXME improve this!
224       break;
225     }
226     case Message::SCREENSHOT:
227     {
228       Osd::getInstance()->screenShot("/out.jpg");
229     }
230   }
231 }
232
233 void Command::handleCommand(int button)
234 {
235   if (isStandby && (button != Remote::POWER)) return;
236
237   if (viewman->handleCommand(button)) return;
238
239   // command was not handled
240
241   switch(button)
242   {
243     case Remote::DF_LEFT:
244     case Remote::DF_RIGHT:
245     case Remote::VOLUMEUP:
246     case Remote::VOLUMEDOWN:
247     {
248       VVolume* v = new VVolume();
249       viewman->add(v);
250       v->handleCommand(button); // this will draw+show
251       return;
252     }
253     case Remote::MUTE:
254     {
255       VMute* v = new VMute();
256       v->draw();
257       viewman->add(v);
258       viewman->updateView(v);
259       return;
260     }
261     case Remote::POWER:
262     {
263       doStandby();
264       return;
265     }
266   }
267 }
268
269 void Command::sig1()
270 {
271 #ifdef DEV
272   Message* m = new Message();
273   m->message = Message::SCREENSHOT;
274   m->to = this;
275   postMessage(m);
276 #endif
277 }
278
279 void Command::doStandby()
280 {
281   if (isStandby)
282   {
283     Video::getInstance()->signalOn();
284     Led::getInstance()->on();
285     isStandby = 0;
286
287
288     VConnect* vconnect = new VConnect();
289     viewman->add(vconnect);
290     vconnect->run();
291   }
292   else
293   {
294     Video::getInstance()->signalOff();
295     viewman->removeAll();
296     viewman->updateView(wallpaper);
297
298     VDR::getInstance()->configSave("General", "Last Power State", "Off");
299     VDR::getInstance()->disconnect();
300     Led::getInstance()->off();
301     isStandby = 1;
302   }
303 }
304
305 void Command::doReboot()
306 {
307   VDR::getInstance()->disconnect();
308   // just kill it...
309   logger->log("Command", Log::NOTICE, "Reboot");
310   reboot(LINUX_REBOOT_CMD_RESTART);
311 }
312
313 void Command::doJustConnected(VConnect* vconnect)
314 {
315   I18n::initialize();
316   Video* video = Video::getInstance();
317   viewman->removeView(vconnect);
318
319   VInfo* vi = new VInfo();
320   vi->create(400, 200);
321   if (video->getFormat() == Video::PAL)
322     vi->setScreenPos(170, 200);
323   else
324     vi->setScreenPos(160, 150);
325
326   vi->setOneLiner(tr("Connected, loading config"));
327   vi->draw();
328   viewman->add(vi);
329   viewman->updateView(vi);
330
331   VDR* vdr = VDR::getInstance();
332   char* config;
333
334   // See if config says to override video format (PAL/NTSC)
335   config = vdr->configLoad("General", "Override Video Format");
336   if (config)
337   {
338     logger->log("Command", Log::DEBUG, "Override Video Format is present");
339
340     if (   (!strcmp(config, "PAL") && (video->getFormat() == Video::NTSC))
341         || (!strcmp(config, "NTSC") && (video->getFormat() == Video::PAL))  )
342     {
343       // Oh sheesh, need to switch format. Bye bye TV...
344
345       // Take everything down
346       viewman->removeAll();
347       viewman->removeView(wallpaper);
348       Osd* osd = Osd::getInstance();
349       osd->shutdown();
350       video->shutdown();
351
352       // Get video and osd back up with the new mode
353       if (!strcmp(config, "PAL"))
354       {
355         logger->log("Command", Log::DEBUG, "Switching to PAL");
356         video->init(Video::PAL);
357       }
358       else if (!strcmp(config, "NTSC"))
359       {
360         logger->log("Command", Log::DEBUG, "Switching to NTSC");
361         video->init(Video::NTSC);
362       }
363       osd->init("/dev/stbgfx");
364
365       // Put the wallpaper back
366       doWallpaper();
367
368       // Re add the vinfo
369       vi = new VInfo();
370       vi->create(400, 200);
371       if (video->getFormat() == Video::PAL)
372         vi->setScreenPos(170, 200);
373       else
374         vi->setScreenPos(160, 150);
375
376       vi->setOneLiner(tr("Connected, loading config"));
377       vi->draw();
378       viewman->add(vi);
379       viewman->updateView(vi);
380     }
381     else
382     {
383       logger->log("Command", Log::DEBUG, "Already in requested mode, or request was not 'PAL' or 'NTSC'");
384     }
385   }
386   else
387   {
388     logger->log("Command", Log::DEBUG, "Phew, no dangerous on-the-fly mode switching to do!");
389   }
390
391   // Power off if first boot and config says so
392   if (firstBoot)
393   {
394     firstBoot = 0;
395
396     logger->log("Command", Log::DEBUG, "Load power after boot");
397
398     config = vdr->configLoad("General", "Power After Boot");
399
400     if (config)
401     {
402       if (!strcasecmp(config, "On"))
403       {
404         logger->log("Command", Log::INFO, "Config says Power After Boot = On");
405       }
406       else if (!strcasecmp(config, "Off"))
407       {
408         logger->log("Command", Log::INFO, "Config says Power After Boot = Off");
409         doStandby();
410         delete[] config;
411         return; // quit here
412       }
413       else if (!strcasecmp(config, "Last state"))
414       {
415         char* lastPowerState = vdr->configLoad("General", "Last Power State");
416         if (lastPowerState)
417         {
418           if (!strcasecmp(lastPowerState, "On"))
419           {
420             logger->log("Command", Log::INFO, "Config says Last Power State = On");
421           }
422           else if (!strcasecmp(lastPowerState, "Off"))
423           {
424             logger->log("Command", Log::INFO, "Config says Last Power State = Off");
425             doStandby();
426             delete[] config;
427             return; // quit here
428           }
429           else
430           {
431             logger->log("Command", Log::INFO, "Config General/Last Power State not understood");
432           }
433         }
434         else
435         {
436           logger->log("Command", Log::INFO, "Config General/Last Power State not found");
437         }
438       }
439       else
440       {
441         logger->log("Command", Log::INFO, "Config/Power After Boot not understood");
442       }
443       delete[] config;
444     }
445     else
446     {
447       logger->log("Command", Log::INFO, "Config General/Power After Boot not found");
448     }
449   }
450
451
452   // Go S-Video if config says so
453
454   config = vdr->configLoad("TV", "Connection");
455
456   if (config)
457   {
458     if (!strcasecmp(config, "S-Video"))
459     {
460       logger->log("Command", Log::INFO, "Switching to S-Video as Connection=%s", config);
461       video->setConnection(Video::SVIDEO);
462     }
463     else
464     {
465       logger->log("Command", Log::INFO, "Switching to RGB/Composite as Connection=%s", config);
466       video->setConnection(Video::COMPOSITERGB);
467     }
468     delete[] config;
469   }
470   else
471   {
472     logger->log("Command", Log::INFO, "Config TV/S-Video not found");
473   }
474
475   // Set remote type
476
477   config = vdr->configLoad("General", "Remote type");
478
479   if (config)
480   {
481     if (!strcasecmp(config, "New"))
482     {
483       logger->log("Command", Log::INFO, "Switching to New remote type");
484       remote->setRemoteType(Remote::NEWREMOTE);
485     }
486     else
487     {
488       logger->log("Command", Log::INFO, "Switching to Old remote type");
489       remote->setRemoteType(Remote::OLDREMOTE);
490     }
491     delete[] config;
492   }
493   else
494   {
495     logger->log("Command", Log::INFO, "Config General/Remote type not found");
496     remote->setRemoteType(Remote::OLDREMOTE);
497   }
498
499   // Get TV aspect ratio
500
501   config = vdr->configLoad("TV", "Aspect");
502   if (config)
503   {
504     if (!strcasecmp(config, "16:9"))
505     {
506       logger->log("Command", Log::INFO, "/// Switching to TV aspect 16:9");
507       video->setTVsize(Video::ASPECT16X9);
508     }
509     else
510     {
511       logger->log("Command", Log::INFO, "/// Switching to TV aspect 4:3");
512       video->setTVsize(Video::ASPECT4X3);
513     }
514     delete[] config;
515   }
516   else
517   {
518     logger->log("Command", Log::INFO, "Config TV/Aspect type not found, going 4:3");
519     video->setTVsize(Video::ASPECT4X3);
520   }
521
522   config = vdr->configLoad("TV", "Widemode");
523   if (config)
524   {
525     if (!strcasecmp(config, "Letterbox"))
526     {
527       logger->log("Command", Log::INFO, "Setting letterbox mode");
528       video->setMode(Video::LETTERBOX);
529     }
530     else
531     {
532       logger->log("Command", Log::INFO, "Setting chop-sides mode");
533       video->setMode(Video::NORMAL);
534     }
535     delete[] config;
536   }
537   else
538   {
539     logger->log("Command", Log::INFO, "Config TV/Widemode not found, Setting chop-sides mode");
540     video->setMode(Video::NORMAL);
541   }
542
543   // config done
544
545   // Save power state = on
546
547   vdr->configSave("General", "Last Power State", "On");
548
549
550   viewman->removeView(vi);
551
552   VWelcome* vw = new VWelcome();
553   vw->draw();
554   viewman->add(vw);
555   viewman->updateView(vw);
556 }