]> git.vomp.tv Git - vompclient.git/blob - main.cc
Fix text corruption in channel number display on live tv
[vompclient.git] / main.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <signal.h>
25 #ifndef WIN32
26 #include <unistd.h>
27 #include <endian.h>
28 #endif
29
30 #include "defines.h"
31
32 #ifdef HANDLE_VT_SWITCHING
33 #include <signal.h>
34 #include <sys/ioctl.h>
35 #include <linux/vt.h>
36 #endif
37 #include "log.h"
38 #include "timers.h"
39 #include "vdr.h"
40 #include "boxstack.h"
41 #include "command.h"
42
43
44 #ifdef VOMP_PLATTFORM_MVP
45
46
47 #include "mtdmvp.h"
48 #include "remotemvp.h"
49 #include "ledmvp.h"
50 #include "osdmvp.h"
51 #include "audiomvp.h"
52 #include "videomvp.h"
53
54 extern "C"
55 {
56   int ticonfig_main(int, char**);
57 }
58
59 #endif
60
61 #ifdef VOMP_PLATTFORM_NMT
62
63 #include "mtdnmt.h"
64 #include "remotelirc.h"
65 #include "lednmt.h"
66 #include "osddirectfb.h"
67 #include "audionmt.h"
68 #include "videonmt.h"
69
70 #endif
71
72 #ifdef VOMP_PLATTFORM_RASPBERRY
73
74 #include "mtdraspberry.h"
75 #include "remotelinux.h"
76 #include "ledraspberry.h"
77 #include "osdopenvg.h"
78 #include "audioomx.h"
79 #include "videoomx.h"
80
81 #endif
82
83
84
85
86 #include "wol.h"
87 #include "vsleeptimer.h"
88
89
90 #ifndef WIN32
91 void sighandler(int signalReceived);
92 #endif
93
94 void shutdown(int code);
95
96 // Global variables --------------------------------------------------------------------------------------------------
97 Log* logger;
98 Remote* remote;
99 Mtd* mtd;
100 Led* led;
101 Osd* osd;
102 Timers* timers;
103 BoxStack* boxstack;
104 Command* command;
105 VDR* vdr;
106 Video* video;
107 Audio* audio;
108 Wol* wol;
109 Sleeptimer* sleeptimer;
110
111 #ifdef HANDLE_VT_SWITCHING
112 int fdtty;
113 struct vt_mode old_vtmode;
114 #endif
115
116 // Linux MVP main function and sighandler
117 #ifndef WIN32
118 int main(int argc, char** argv)
119 {
120 #ifdef VOMP_PLATTFORM_MVP
121   if (strstr(argv[0], "ticonfig")) return ticonfig_main(argc, argv);
122 #endif
123
124   bool daemonize = true;
125   bool debugEnabled = false;
126   bool crashed = false;
127   char* setServer = NULL;
128   int c;
129
130   while ((c = getopt(argc, argv, "cdns:")) != -1)
131   {
132     switch (c)
133     {
134       case 'c':
135         crashed = true;
136         break;
137       case 'd':
138         debugEnabled = true; // and...
139       case 'n':
140         daemonize = false;
141         break;
142       case 's':
143         setServer = optarg;
144         break;
145       case '?':
146         printf("Unknown option\n");
147         return 1;
148       default:
149         printf("Option error\n");
150         return 1;
151     }
152   }
153
154   // Init global vars ------------------------------------------------------------------------------------------------
155   logger     = new Log();
156   timers     = new Timers();
157   vdr        = new VDR();
158
159   mtd        = new Mtd_TYPE();
160   remote     = new Remote_TYPE();
161   led        = new Led_TYPE();
162   osd        = new Osd_TYPE();
163   audio      = new Audio_TYPE();
164   video      = new Video_TYPE();
165
166
167
168   boxstack   = new BoxStack();
169   command    = new Command();
170   wol        = new Wol();
171   sleeptimer = new Sleeptimer();
172
173   if (!logger || !remote || !mtd || !led || !osd || !video || !audio || !boxstack || !command || !wol || !sleeptimer)
174   {
175     printf("Could not create objects. Memory problems?\n");
176     shutdown(1);
177   }
178
179   // Get logging module started --------------------------------------------------------------------------------------
180
181   if (!logger->init(Log::DEBUG, "dummy", debugEnabled ? 1 : 0))
182   {
183     printf("Could not initialise log object. Aborting.\n");
184     shutdown(1);
185   }
186
187   logger->log("Core", Log::INFO, "Starting up...");
188
189   // Daemonize if not -d
190
191   if (daemonize)
192   {
193     // Fork away
194     pid_t forkTest = fork();
195     if (forkTest == -1)
196     { printf("Cannot fork (1).\n"); exit(1); }
197     if (forkTest != 0) _exit(0); // PID returned, I am the parent
198     // otherwise, I am the child
199     setsid();
200     forkTest = fork();
201     if (forkTest == -1)
202     { printf("Cannot fork (2).\n"); exit(1); }
203     if (forkTest != 0) _exit(0); // PID returned, I am the parent
204     // otherwise, I am the child
205     close(0);
206     close(1);
207     close(2);
208   }
209
210   // Set up signal handling ------------------------------------------------------------------------------------------
211
212   sighandler_t sigtest;
213
214   sigtest = signal(SIGPIPE, SIG_IGN);
215   if (sigtest == SIG_ERR)
216   {
217     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGPIPE. Aborting.");
218     shutdown(1);
219   }
220   sigtest = signal(SIGINT, sighandler);
221   if (sigtest == SIG_ERR)
222   {
223     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGINT. Aborting.");
224     shutdown(1);
225   }
226   sigtest = signal(SIGTERM, sighandler);
227   if (sigtest == SIG_ERR)
228   {
229     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGTERM. Aborting.");
230     shutdown(1);
231   }
232   sigtest = signal(SIGUSR1, sighandler);
233   if (sigtest == SIG_ERR)
234   {
235     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGUSR1. Aborting.");
236     shutdown(1);
237   }
238   sigtest = signal(SIGUSR2, sighandler);
239   if (sigtest == SIG_ERR)
240   {
241     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGUSR2. Aborting.");
242     shutdown(1);
243   }
244   sigtest = signal(SIGURG, sighandler);
245   if (sigtest == SIG_ERR)
246   {
247     logger->log("Core", Log::EMERG, "Could not set up signal handler for SIGURG. Aborting.");
248     shutdown(1);
249   }
250
251   logger->log("Core", Log::INFO, "Signal handlers set up successfully");
252
253 #ifdef HANDLE_VT_SWITCHING
254   if ((fdtty = open("/dev/tty", O_WRONLY),0) == -1) {
255           logger->log("Core", Log::EMERG, "Could not open /dev/tty. Please change permissions");
256   } else {
257           int free_vt;
258           if (ioctl(fdtty,VT_OPENQRY,&free_vt)==-1 || free_vt==-1){
259                   logger->log("Core", Log::EMERG, "Could not retrieve free virtual console, please change permissions");
260           } else {
261                   ioctl(fdtty,VT_ACTIVATE,free_vt);
262                   ioctl(fdtty,VT_WAITACTIVE,free_vt);
263                   ioctl(fdtty, VT_LOCKSWITCH, 1);
264           }
265   }
266
267 #endif
268
269   // Init modules ----------------------------------------------------------------------------------------------------
270   int success;
271
272   success = remote->init(RemoteStartDev);
273
274   if (success)
275   {
276     logger->log("Core", Log::INFO, "Remote module initialised");
277   }
278   else
279   {
280     logger->log("Core", Log::EMERG, "Remote module failed to initialise");
281     shutdown(1);
282   }
283 #ifdef VOMP_PLATTFORM_MVP
284   success = led->init(((RemoteMVP*)remote)->getDevice());
285 #else
286   success = led->init(-1);
287 #endif
288   if (success)
289   {
290     logger->log("Core", Log::INFO, "LED module initialised");
291   }
292   else
293   {
294     logger->log("Core", Log::EMERG, "LED module failed to initialise");
295     shutdown(1);
296   }
297
298   success = mtd->init();
299   if (success)
300   {
301     logger->log("Core", Log::INFO, "Mtd module initialised");
302   }
303   else
304   {
305     logger->log("Core", Log::EMERG, "Mtd module failed to initialise");
306     shutdown(1);
307   }
308
309   success = timers->init();
310   if (success)
311   {
312     logger->log("Core", Log::INFO, "Timers module initialised");
313   }
314   else
315   {
316     logger->log("Core", Log::EMERG, "Timers module failed to initialise");
317     shutdown(1);
318   }
319
320   UCHAR videoFormat = (UCHAR)mtd->getPALorNTSC();
321   if      (videoFormat == Video::PAL)  logger->log("Core", Log::INFO, "Read from MTD: PAL 720x576");
322   else if (videoFormat == Video::NTSC) logger->log("Core", Log::INFO, "Read from MTD: NTSC 720x480");
323   else                                 logger->log("Core", Log::INFO, "No help from MTD. Assuming NTSC 720x480");
324
325   success = video->init(videoFormat);
326   if (success)
327   {
328     logger->log("Core", Log::INFO, "Video module initialised");
329   }
330   else
331   {
332     logger->log("Core", Log::EMERG, "Video module failed to initialise");
333     shutdown(1);
334   }
335
336   success = osd->init((void*)OsdStartDev);
337   if (success)
338   {
339     logger->log("Core", Log::INFO, "OSD module initialised");
340   }
341   else
342   {
343     logger->log("Core", Log::EMERG, "OSD module failed to initialise");
344     shutdown(1);
345   }
346
347   success = audio->init(Audio::MPEG2_PES);
348   if (success)
349   {
350     logger->log("Core", Log::INFO, "Audio module initialised");
351   }
352   else
353   {
354     logger->log("Core", Log::EMERG, "Audio module failed to initialise");
355     shutdown(1);
356   }
357
358   success = vdr->init(3024);
359   if (success)
360   {
361     logger->log("Core", Log::INFO, "VDR module initialised");
362   }
363   else
364   {
365     logger->log("Core", Log::EMERG, "VDR module failed to initialise");
366     shutdown(1);
367   }
368
369   success = boxstack->init();
370   if (success)
371   {
372     logger->log("Core", Log::INFO, "BoxStack module initialised");
373   }
374   else
375   {
376     logger->log("Core", Log::EMERG, "BoxStack module failed to initialise");
377     shutdown(1);
378   }
379
380   success = command->init(crashed, setServer);
381   if (success)
382   {
383     logger->log("Core", Log::INFO, "Command module initialised");
384   }
385   else
386   {
387     logger->log("Core", Log::EMERG, "Command module failed to initialise");
388     shutdown(1);
389   }
390
391   // Other init ------------------------------------------------------------------------------------------------------
392
393   logger->log("Core", Log::NOTICE, "Startup successful");
394
395   // Run main loop ---------------------------------------------------------------------------------------------------
396
397   // Ok, all major device components and other bits are loaded and ready
398   command->run();
399
400   // When that returns quit ------------------------------------------------------------------------------------------
401   shutdown(0);
402   return 0;
403 }
404
405 // -------------------------------------------------------------------------------------------------------------------
406
407 void sighandler(int signalReceived)
408 {
409   if (command) command->setSignal(signalReceived);
410 }
411
412 #endif
413
414 // -------------------------------------------------------------------------------------------------------------------
415
416 void shutdown(int code)
417 {
418   if (boxstack)
419   {
420     boxstack->shutdown();
421     delete boxstack;
422     logger->log("Core", Log::NOTICE, "BoxStack module shut down");
423   }
424
425   // FIXME, send a del all to boxstack first, then get rid of it after command?
426   if (command) // shut down command here in case views have posted messages
427   {
428     command->shutdown();
429     delete command;
430     command = NULL;
431     logger->log("Core", Log::NOTICE, "Command module shut down");
432   }
433
434   if (vdr)
435   {
436     vdr->shutdown();
437     delete vdr;
438     logger->log("Core", Log::NOTICE, "VDR module shut down");
439   }
440
441   if (osd)
442   {
443     osd->shutdown();
444     delete osd;
445     logger->log("Core", Log::NOTICE, "OSD module shut down");
446   }
447
448   if (audio)
449   {
450     audio->shutdown();
451     delete audio;
452     logger->log("Core", Log::NOTICE, "Audio module shut down");
453   }
454
455   if (video)
456   {
457     video->shutdown();
458     delete video;
459     logger->log("Core", Log::NOTICE, "Video module shut down");
460   }
461
462   if (timers)
463   {
464     timers->shutdown();
465     delete timers;
466     logger->log("Core", Log::NOTICE, "Timers module shut down");
467   }
468
469   if (mtd)
470   {
471     mtd->shutdown();
472     delete mtd;
473     logger->log("Core", Log::NOTICE, "MTD module shut down");
474   }
475
476   if (led)
477   {
478     led->shutdown();
479     delete led;
480     logger->log("Core", Log::NOTICE, "LED module shut down");
481   }
482
483   if (remote)
484   {
485     remote->shutdown();
486     delete remote;
487     logger->log("Core", Log::NOTICE, "Remote module shut down");
488   }
489
490   if (wol)
491   {
492     delete wol;
493     logger->log("Core", Log::NOTICE, "WOL module shut down");
494   }
495
496   if (sleeptimer)
497   {
498     delete sleeptimer;
499     logger->log("Core", Log::NOTICE, "Sleeptimer module shut down");
500   }
501 #ifdef HANDLE_VT_SWITCHING
502   ioctl(fdtty, VT_UNLOCKSWITCH, 1);
503   close(fdtty);
504 #endif
505
506   if (logger)
507   {
508     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");
509     logger->shutdown();
510     delete logger;
511   }
512
513   exit(code);
514 }
515
516 // -------------------------------------------------------------------------------------------------------------------
517
518 ULLONG htonll(ULLONG a)
519 {
520   #if BYTE_ORDER == BIG_ENDIAN
521     return a;
522   #else
523     ULLONG b = 0;
524
525     b = ((a << 56) & 0xFF00000000000000ULL)
526       | ((a << 40) & 0x00FF000000000000ULL)
527       | ((a << 24) & 0x0000FF0000000000ULL)
528       | ((a <<  8) & 0x000000FF00000000ULL)
529       | ((a >>  8) & 0x00000000FF000000ULL)
530       | ((a >> 24) & 0x0000000000FF0000ULL)
531       | ((a >> 40) & 0x000000000000FF00ULL)
532       | ((a >> 56) & 0x00000000000000FFULL) ;
533
534     return b;
535   #endif
536 }
537
538 ULLONG ntohll(ULLONG a)
539 {
540   return htonll(a);
541 }
542
543 void MILLISLEEP(ULONG a)
544 {
545 #ifndef WIN32
546   struct timespec delayTime;
547   delayTime.tv_sec = a / 1000;
548   delayTime.tv_nsec = (a % 1000) * 1000000;
549   nanosleep(&delayTime, NULL);
550 #else
551   Sleep(a);
552 #endif
553 }
554
555 long long getTimeMS() {
556         struct timespec ts;
557         clock_gettime(VOMP_LINUX_CLOCK, &ts);
558         return ts.tv_sec*1000+ts.tv_nsec/1000000LL;
559 }
560
561 int getClockRealTime(struct timespec *tp)
562 {
563         return clock_gettime(CLOCK_REALTIME, tp);
564 }
565
566
567 int min(UINT a, int b)
568 {
569   if (a > b) return b;
570   else return a;
571 }
572
573 int max(int a, int b)
574 {
575   if (a > b) return a;
576   else return b;
577 }
578