]> git.vomp.tv Git - vompclient.git/blob - main.cc
Reverting changes in mutex
[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
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       logger->log("Core", Log::NOTICE, "USR1 signal, screenshot...");
433       command->sig1();
434       break;
435     }
436 /*
437     case SIGUSR1:
438     {
439       logger->log("Core", Log::DEBUG, "SIGUSR1 caught");
440       logger->upLogLevel();
441       break;
442     }
443     case SIGUSR2:
444     {
445       logger->log("Core", Log::DEBUG, "SIGUSR2 caught");
446       logger->downLogLevel();
447       break;
448     }
449 */
450     case SIGURG:
451     {
452       logger->log("Core", Log::DEBUG, "SIGURG caught");
453       break;
454     }
455   }
456 }
457 #endif
458
459 // -------------------------------------------------------------------------------------------------------------------
460
461 void shutdown(int code)
462 {
463   if (boxstack)
464   {
465     boxstack->shutdown();
466     delete boxstack;
467     logger->log("Core", Log::NOTICE, "BoxStack module shut down");
468   }
469
470   // FIXME, send a del all to boxstack first, then get rid of it after command?
471   if (command) // shut down command here in case views have posted messages
472   {
473     command->shutdown();
474     delete command;
475     logger->log("Core", Log::NOTICE, "Command module shut down");
476   }
477
478   if (vdr)
479   {
480     vdr->shutdown();
481     delete vdr;
482     logger->log("Core", Log::NOTICE, "VDR module shut down");
483   }
484
485   if (osd)
486   {
487     osd->shutdown();
488     delete osd;
489     logger->log("Core", Log::NOTICE, "OSD module shut down");
490   }
491
492   if (audio)
493   {
494     audio->shutdown();
495     delete audio;
496     logger->log("Core", Log::NOTICE, "Audio module shut down");
497   }
498
499   if (video)
500   {
501     video->shutdown();
502     delete video;
503     logger->log("Core", Log::NOTICE, "Video module shut down");
504   }
505
506   if (timers)
507   {
508     timers->shutdown();
509     delete timers;
510     logger->log("Core", Log::NOTICE, "Timers module shut down");
511   }
512
513   if (mtd)
514   {
515     mtd->shutdown();
516     delete mtd;
517     logger->log("Core", Log::NOTICE, "MTD module shut down");
518   }
519
520   if (led)
521   {
522     led->shutdown();
523     delete led;
524     logger->log("Core", Log::NOTICE, "LED module shut down");
525   }
526
527   if (remote)
528   {
529     remote->shutdown();
530     delete remote;
531     logger->log("Core", Log::NOTICE, "Remote module shut down");
532   }
533
534   if (wol)
535   {
536     delete wol;
537     logger->log("Core", Log::NOTICE, "WOL module shut down");
538   }
539
540   if (sleeptimer)
541   {
542     delete sleeptimer;
543     logger->log("Core", Log::NOTICE, "Sleeptimer module shut down");
544   }
545 #ifdef HANDLE_VT_SWITCHING
546   ioctl(fdtty, VT_UNLOCKSWITCH, 1);
547   close(fdtty);
548 #endif
549
550   if (logger)
551   {
552     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");
553     logger->shutdown();
554     delete logger;
555   }
556
557   exit(code);
558 }
559
560 // -------------------------------------------------------------------------------------------------------------------
561
562 ULLONG htonll(ULLONG a)
563 {
564   #if BYTE_ORDER == BIG_ENDIAN
565     return a;
566   #else
567     ULLONG b = 0;
568
569     b = ((a << 56) & 0xFF00000000000000ULL)
570       | ((a << 40) & 0x00FF000000000000ULL)
571       | ((a << 24) & 0x0000FF0000000000ULL)
572       | ((a <<  8) & 0x000000FF00000000ULL)
573       | ((a >>  8) & 0x00000000FF000000ULL)
574       | ((a >> 24) & 0x0000000000FF0000ULL)
575       | ((a >> 40) & 0x000000000000FF00ULL)
576       | ((a >> 56) & 0x00000000000000FFULL) ;
577
578     return b;
579   #endif
580 }
581
582 ULLONG ntohll(ULLONG a)
583 {
584   return htonll(a);
585 }
586
587 void MILLISLEEP(ULONG a)
588 {
589 #ifndef WIN32
590   struct timespec delayTime;
591   delayTime.tv_sec = a / 1000;
592   delayTime.tv_nsec = (a % 1000) * 1000000;
593   nanosleep(&delayTime, NULL);
594 #else
595   Sleep(a);
596 #endif
597 }
598
599 long long getTimeMS() {
600         struct timespec ts;
601         clock_gettime(VOMP_LINUX_CLOCK, &ts);
602         return ts.tv_sec*1000+ts.tv_nsec/1000000LL;
603 }
604
605 int min(UINT a, int b)
606 {
607   if (a > b) return b;
608   else return a;
609 }
610
611 int max(int a, int b)
612 {
613   if (a > b) return a;
614   else return b;
615 }
616