]> git.vomp.tv Git - vompclient.git/blob - main.cc
A much cleaner patch for enabling MVP again
[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
402   shutdown(0);
403   return 0;
404 }
405
406 // -------------------------------------------------------------------------------------------------------------------
407
408 void sighandler(int signalReceived)
409 {
410   if (command) command->setSignal(signalReceived);
411 }
412
413 #endif
414
415 // -------------------------------------------------------------------------------------------------------------------
416
417 void shutdown(int code)
418 {
419   if (boxstack)
420   {
421     boxstack->shutdown();
422     delete boxstack;
423     logger->log("Core", Log::NOTICE, "BoxStack module shut down");
424   }
425
426   // FIXME, send a del all to boxstack first, then get rid of it after command?
427   if (command) // shut down command here in case views have posted messages
428   {
429     command->shutdown();
430     delete command;
431     command = NULL;
432     logger->log("Core", Log::NOTICE, "Command module shut down");
433   }
434
435   if (vdr)
436   {
437     vdr->shutdown();
438     delete vdr;
439     logger->log("Core", Log::NOTICE, "VDR module shut down");
440   }
441
442   if (osd)
443   {
444     osd->shutdown();
445     delete osd;
446     logger->log("Core", Log::NOTICE, "OSD module shut down");
447   }
448
449   if (audio)
450   {
451     audio->shutdown();
452     delete audio;
453     logger->log("Core", Log::NOTICE, "Audio module shut down");
454   }
455
456   if (video)
457   {
458     video->shutdown();
459     delete video;
460     logger->log("Core", Log::NOTICE, "Video module shut down");
461   }
462
463   if (timers)
464   {
465     timers->shutdown();
466     delete timers;
467     logger->log("Core", Log::NOTICE, "Timers module shut down");
468   }
469
470   if (mtd)
471   {
472     mtd->shutdown();
473     delete mtd;
474     logger->log("Core", Log::NOTICE, "MTD module shut down");
475   }
476
477   if (led)
478   {
479     led->shutdown();
480     delete led;
481     logger->log("Core", Log::NOTICE, "LED module shut down");
482   }
483
484   if (remote)
485   {
486     remote->shutdown();
487     delete remote;
488     logger->log("Core", Log::NOTICE, "Remote module shut down");
489   }
490
491   if (wol)
492   {
493     delete wol;
494     logger->log("Core", Log::NOTICE, "WOL module shut down");
495   }
496
497   if (sleeptimer)
498   {
499     delete sleeptimer;
500     logger->log("Core", Log::NOTICE, "Sleeptimer module shut down");
501   }
502 #ifdef HANDLE_VT_SWITCHING
503   ioctl(fdtty, VT_UNLOCKSWITCH, 1);
504   close(fdtty);
505 #endif
506
507   if (logger)
508   {
509     logger->log("Core", Log::NOTICE, "Log module shutting down... bye!\n\n");
510     logger->shutdown();
511     delete logger;
512   }
513
514   exit(code);
515 }
516
517 // -------------------------------------------------------------------------------------------------------------------
518
519 ULLONG htonll(ULLONG a)
520 {
521   #if BYTE_ORDER == BIG_ENDIAN
522     return a;
523   #else
524     ULLONG b = 0;
525
526     b = ((a << 56) & 0xFF00000000000000ULL)
527       | ((a << 40) & 0x00FF000000000000ULL)
528       | ((a << 24) & 0x0000FF0000000000ULL)
529       | ((a <<  8) & 0x000000FF00000000ULL)
530       | ((a >>  8) & 0x00000000FF000000ULL)
531       | ((a >> 24) & 0x0000000000FF0000ULL)
532       | ((a >> 40) & 0x000000000000FF00ULL)
533       | ((a >> 56) & 0x00000000000000FFULL) ;
534
535     return b;
536   #endif
537 }
538
539 ULLONG ntohll(ULLONG a)
540 {
541   return htonll(a);
542 }
543
544 void MILLISLEEP(ULONG a)
545 {
546 #ifndef WIN32
547   struct timespec delayTime;
548   delayTime.tv_sec = a / 1000;
549   delayTime.tv_nsec = (a % 1000) * 1000000;
550   nanosleep(&delayTime, NULL);
551 #else
552   Sleep(a);
553 #endif
554 }
555
556 long long getTimeMS() {
557         struct timespec ts;
558         clock_gettime(VOMP_LINUX_CLOCK, &ts);
559         return ts.tv_sec*1000+ts.tv_nsec/1000000LL;
560 }
561
562 int getClockRealTime(struct timespec *tp)
563 {
564         return clock_gettime(CLOCK_REALTIME, tp);
565 }
566
567
568 int min(UINT a, int b)
569 {
570   if (a > b) return b;
571   else return a;
572 }
573
574 int max(int a, int b)
575 {
576   if (a > b) return a;
577   else return b;
578 }
579