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