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