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