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