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