36#include <sys/capability.h>
39#include <systemd/sd-daemon.h>
77#define MINCHANNELWAIT 10
78#define ACTIVITYTIMEOUT 60
79#define MEMCLEANUPDELTA 3600
80#define SHUTDOWNWAIT 300
81#define SHUTDOWNRETRY 360
82#define SHUTDOWNFORCEPROMPT 5
83#define SHUTDOWNCANCELPROMPT 5
84#define RESTARTCANCELPROMPT 5
85#define MANUALSTART 600
86#define CHANNELSAVEDELTA 600
87#define DEVICEREADYTIMEOUT 30
88#define MENUTIMEOUT 120
89#define TIMERCHECKDELTA 5
90#define TIMERDEVICETIMEOUT 8
91#define TIMERLOOKAHEADTIME 60
92#define VPSLOOKAHEADTIME 24
93#define VPSUPTODATETIME 3600
95#define EXIT(v) { ShutdownHandler.Exit(v); goto Exit; }
99static bool SetUser(
const char *User,
bool UserDump)
102 struct passwd *user =
isnumber(User) ? getpwuid(atoi(User)) : getpwnam(User);
104 fprintf(stderr,
"vdr: unknown user: '%s'\n", User);
107 if (setgid(user->pw_gid) < 0) {
108 fprintf(stderr,
"vdr: cannot set group id %u: %s\n", (
unsigned int)user->pw_gid, strerror(errno));
111 if (initgroups(user->pw_name, user->pw_gid) < 0) {
112 fprintf(stderr,
"vdr: cannot set supplemental group ids for user %s: %s\n", user->pw_name, strerror(errno));
115 if (setuid(user->pw_uid) < 0) {
116 fprintf(stderr,
"vdr: cannot set user id %u: %s\n", (
unsigned int)user->pw_uid, strerror(errno));
119 if (UserDump && prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0)
120 fprintf(stderr,
"vdr: warning - cannot set dumpable: %s\n", strerror(errno));
121 setenv(
"HOME", user->pw_dir, 1);
122 setenv(
"USER", user->pw_name, 1);
123 setenv(
"LOGNAME", user->pw_name, 1);
124 setenv(
"SHELL", user->pw_shell, 1);
132 cap_t caps_all = cap_get_proc();
134 fprintf(stderr,
"vdr: cap_get_proc failed: %s\n", strerror(errno));
137 cap_flag_value_t cap_flag_value;
138 if (cap_get_flag(caps_all, CAP_SYS_TIME, CAP_PERMITTED , &cap_flag_value)) {
139 fprintf(stderr,
"vdr: cap_get_flag failed: %s\n", strerror(errno));
143 if (cap_flag_value == CAP_SET)
144 caps = cap_from_text(
"= cap_sys_nice,cap_sys_time,cap_net_raw=ep");
146 fprintf(stdout,
"vdr: OS does not support cap_sys_time\n");
147 caps = cap_from_text(
"= cap_sys_nice,cap_net_raw=ep");
150 fprintf(stderr,
"vdr: cap_from_text failed: %s\n", strerror(errno));
153 if (cap_set_proc(caps) == -1) {
154 fprintf(stderr,
"vdr: cap_set_proc failed: %s\n", strerror(errno));
165 if (prctl(PR_SET_KEEPCAPS, On ? 1 : 0, 0, 0, 0) != 0) {
166 fprintf(stderr,
"vdr: prctl failed\n");
188#define EXITWATCHDOG 40
194 static volatile sig_atomic_t PanicLevel = 0;
195 switch (PanicLevel) {
196 case 0: PanicLevel = 1;
199 esyslog(
"PANIC: watchdog timer expired - exit()!");
201 sd_notify(0,
"STOPPING=1\nSTATUS=PANIC");
205 case 1: PanicLevel = 2;
208 esyslog(
"PANIC: watchdog timer expired - _exit()!");
223 static void Check(time_t Now);
229#define SPINUPDISK_TIME 60
239 if (
const cTimer *Timer = Timers->GetNextActiveTimer())
240 Delta = Timer->StartTime() - Now;
252int main(
int argc,
char *argv[])
256 struct termios savedTm;
257 bool HasStdin = (tcgetpgrp(STDIN_FILENO) == getpid() || getppid() != (pid_t)1) && tcgetattr(STDIN_FILENO, &savedTm) == 0;
261 setlocale(LC_ALL,
"");
265#define dd(a, b) (*a ? a : b)
266#define DEFAULTSVDRPPORT 6419
267#define DEFAULTWATCHDOG 0
268#define DEFAULTVIDEODIR VIDEODIR
269#define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory)
270#define DEFAULTARGSDIR dd(ARGSDIR, "/etc/vdr/conf.d")
271#define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory)
272#define DEFAULTRESDIR dd(RESDIR, ConfigDirectory)
273#define DEFAULTPLUGINDIR PLUGINDIR
274#define DEFAULTLOCDIR LOCDIR
275#define DEFAULTEPGDATAFILENAME "epg.data"
277 bool StartedAsRoot =
false;
278 const char *VdrUser = NULL;
279 bool UserDump =
false;
281 const char *AudioCommand = NULL;
283 const char *ConfigDirectory = NULL;
284 const char *CacheDirectory = NULL;
285 const char *ResourceDirectory = NULL;
288 bool DisplayHelp =
false;
289 bool DisplayVersion =
false;
290 bool DaemonMode =
false;
291 int SysLogTarget = LOG_USER;
292 bool MuteAudio =
false;
294 const char *Terminal = NULL;
295 const char *OverrideCharacterTable = NULL;
298 const char *LircDevice = NULL;
299#if !defined(REMOTE_KBD)
302#if defined(REMOTE_LIRC)
303 LircDevice = LIRC_DEVICE;
309 time_t SdWatchdog = 0;
310 int SdWatchdogTimeout = 0;
315 Args =
new cArgs(argv[0]);
325 static struct option long_options[] = {
326 {
"audio", required_argument, NULL,
'a' },
327 {
"cachedir", required_argument, NULL,
'c' | 0x100 },
328 {
"chartab", required_argument, NULL,
'c' | 0x200 },
329 {
"config", required_argument, NULL,
'c' },
330 {
"daemon", no_argument, NULL,
'd' },
331 {
"device", required_argument, NULL,
'D' },
332 {
"dirnames", required_argument, NULL,
'd' | 0x100 },
333 {
"edit", required_argument, NULL,
'e' | 0x100 },
334 {
"epgfile", required_argument, NULL,
'E' },
335 {
"filesize", required_argument, NULL,
'f' | 0x100 },
336 {
"genindex", required_argument, NULL,
'g' | 0x100 },
337 {
"grab", required_argument, NULL,
'g' },
338 {
"help", no_argument, NULL,
'h' },
339 {
"instance", required_argument, NULL,
'i' },
340 {
"lib", required_argument, NULL,
'L' },
341 {
"lirc", optional_argument, NULL,
'l' | 0x100 },
342 {
"localedir",required_argument, NULL,
'l' | 0x200 },
343 {
"log", required_argument, NULL,
'l' },
344 {
"mute", no_argument, NULL,
'm' },
345 {
"no-kbd", no_argument, NULL,
'n' | 0x100 },
346 {
"pes2ts", no_argument, NULL,
'p' | 0x100 },
347 {
"plugin", required_argument, NULL,
'P' },
348 {
"port", required_argument, NULL,
'p' },
349 {
"record", required_argument, NULL,
'r' },
350 {
"resdir", required_argument, NULL,
'r' | 0x100 },
351 {
"showargs", optional_argument, NULL,
's' | 0x200 },
352 {
"shutdown", required_argument, NULL,
's' },
353 {
"split", no_argument, NULL,
's' | 0x100 },
354 {
"terminal", required_argument, NULL,
't' },
355 {
"updindex", required_argument, NULL,
'u' | 0x200 },
356 {
"user", required_argument, NULL,
'u' },
357 {
"userdump", no_argument, NULL,
'u' | 0x100 },
358 {
"version", no_argument, NULL,
'V' },
359 {
"vfat", no_argument, NULL,
'v' | 0x100 },
360 {
"video", required_argument, NULL,
'v' },
361 {
"watchdog", required_argument, NULL,
'w' },
362 { NULL, no_argument, NULL, 0 }
366 while ((c = getopt_long(argc, argv,
"a:c:dD:e:E:g:hi:l:L:mp:P:r:s:t:u:v:Vw:", long_options, NULL)) != -1) {
368 case 'a': AudioCommand = optarg;
371 CacheDirectory = optarg;
374 OverrideCharacterTable = optarg;
376 case 'c': ConfigDirectory = optarg;
378 case 'd': DaemonMode =
true;
380 case 'D':
if (*optarg ==
'-') {
385 int n = atoi(optarg);
391 fprintf(stderr,
"vdr: invalid DVB device number: %s\n", optarg);
396 int n = strtol(s, &s, 10);
397 if (n <= 0 || n >= PATH_MAX) {
398 fprintf(stderr,
"vdr: invalid directory path length: %s\n", optarg);
405 fprintf(stderr,
"vdr: invalid delimiter: %s\n", optarg);
413 int n = strtol(s, &s, 10);
414 if (n <= 0 || n > NAME_MAX) {
415 fprintf(stderr,
"vdr: invalid directory name length: %s\n", optarg);
422 fprintf(stderr,
"vdr: invalid delimiter: %s\n", optarg);
429 int n = strtol(s, &s, 10);
430 if (n != 0 && n != 1) {
431 fprintf(stderr,
"vdr: invalid directory encoding: %s\n", optarg);
436 fprintf(stderr,
"vdr: unexpected data: %s\n", optarg);
443 case 'E': EpgDataFileName = (*optarg !=
'-' ? optarg : NULL);
456 case 'h': DisplayHelp =
true;
463 fprintf(stderr,
"vdr: invalid instance id: %s\n", optarg);
466 char *p = strchr(optarg,
'.');
470 int l = atoi(optarg);
471 if (0 <= l && l <= 3) {
478 if (0 <= l && l <= 7) {
479 int targets[] = { LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7 };
480 SysLogTarget = targets[l];
488 fprintf(stderr,
"vdr: invalid log level: %s\n", optarg);
491 case 'L':
if (access(optarg, R_OK | X_OK) == 0)
494 fprintf(stderr,
"vdr: can't access plugin directory: %s\n", optarg);
499 LircDevice = optarg ? optarg : LIRC_DEVICE;
502 if (access(optarg, R_OK | X_OK) == 0)
503 LocaleDirectory = optarg;
505 fprintf(stderr,
"vdr: can't access locale directory: %s\n", optarg);
509 case 'm': MuteAudio =
true;
515 SVDRPport = atoi(optarg);
517 fprintf(stderr,
"vdr: invalid port number: %s\n", optarg);
522 if (argc - optind >= 2)
523 return Pes2Ts(argv[optind], argv[optind + 1]) ? 0 : 2;
525 fprintf(stderr,
"vdr: --pes2ts requires two arguments\n");
529 case 'P': PluginManager.
AddPlugin(optarg);
534 ResourceDirectory = optarg;
545 fprintf(stderr,
"vdr: can't read arguments from directory: %s\n", ArgsDir);
550 for (
int i = 1; i < c; i++)
551 printf(
"%s\n", v[i]);
554 case 't': Terminal = optarg;
555 if (access(Terminal, R_OK | W_OK) < 0) {
556 fprintf(stderr,
"vdr: can't access terminal: %s\n", Terminal);
560 case 'u':
if (*optarg)
567 fprintf(stderr,
"vdr: option '--updindex' is deprecated, using '--genindex' instead\n");
569 case 'V': DisplayVersion =
true;
576 case 'v': VideoDirectory = optarg;
577 while (optarg && *optarg && optarg[strlen(optarg) - 1] ==
'/')
578 optarg[strlen(optarg) - 1] = 0;
582 int t = atoi(optarg);
588 fprintf(stderr,
"vdr: invalid watchdog timeout: %s\n", optarg);
596 if (DisplayHelp || DisplayVersion) {
601 printf(
"Usage: vdr [OPTIONS]\n\n"
602 " -a CMD, --audio=CMD send Dolby Digital audio to stdin of command CMD\n"
603 " --cachedir=DIR save cache files in DIR (default: %s)\n"
604 " --chartab=CHARACTER_TABLE\n"
605 " set the character table to use for strings in the\n"
606 " DVB data stream that don't begin with a character\n"
607 " table indicator, but don't use the standard default\n"
608 " character table (for instance ISO-8859-9)\n"
609 " -c DIR, --config=DIR read config files from DIR (default: %s)\n"
610 " -d, --daemon run in daemon mode\n"
611 " -D NUM, --device=NUM use only the given DVB device (NUM = 0, 1, 2...)\n"
612 " there may be several -D options (default: all DVB\n"
613 " devices will be used); if -D- is given, no DVB\n"
614 " devices will be used at all, independent of any\n"
615 " other -D options\n"
616 " --dirnames=PATH[,NAME[,ENC]]\n"
617 " set the maximum directory path length to PATH\n"
618 " (default: %d); if NAME is also given, it defines\n"
619 " the maximum directory name length (default: %d);\n"
620 " the optional ENC can be 0 or 1, and controls whether\n"
621 " special characters in directory names are encoded as\n"
622 " hex values (default: 0); if PATH or NAME are left\n"
623 " empty (as in \",,1\" to only set ENC), the defaults\n"
625 " --edit=REC cut recording REC and exit\n"
626 " -E FILE, --epgfile=FILE write the EPG data into the given FILE (default is\n"
627 " '%s' in the cache directory)\n"
628 " '-E-' disables this\n"
629 " if FILE is a directory, the default EPG file will be\n"
630 " created in that directory\n"
631 " --filesize=SIZE limit video files to SIZE bytes (default is %dM)\n"
632 " only useful in conjunction with --edit\n"
633 " --genindex=REC generate index for recording REC and exit\n"
634 " -g DIR, --grab=DIR write images from the SVDRP command GRAB into the\n"
635 " given DIR; DIR must be the full path name of an\n"
636 " existing directory, without any \"..\", double '/'\n"
637 " or symlinks (default: none, same as -g-)\n"
638 " -h, --help print this help and exit\n"
639 " -i ID, --instance=ID use ID as the id of this VDR instance (default: 0)\n"
640 " -l LEVEL, --log=LEVEL set log level (default: 3)\n"
641 " 0 = no logging, 1 = errors only,\n"
642 " 2 = errors and info, 3 = errors, info and debug\n"
643 " if logging should be done to LOG_LOCALn instead of\n"
644 " LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7)\n"
645 " -L DIR, --lib=DIR search for plugins in DIR (default is %s)\n"
646 " --lirc[=PATH] use a LIRC remote control device, attached to PATH\n"
648 " --localedir=DIR search for locale files in DIR (default is\n"
650 " -m, --mute mute audio of the primary DVB device at startup\n"
651 " --no-kbd don't use the keyboard as an input device\n"
652 " --pes2ts convert a PES recording to TS\n"
653 " -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
654 " 0 turns off SVDRP\n"
655 " -P OPT, --plugin=OPT load a plugin defined by the given options\n"
656 " -r CMD, --record=CMD call CMD before and after a recording, and after\n"
657 " a recording has been edited or deleted\n"
658 " --resdir=DIR read resource files from DIR (default: %s)\n"
659 " -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
660 " --split split edited files at the editing marks (only\n"
661 " useful in conjunction with --edit)\n"
662 " --showargs[=DIR] print the arguments read from DIR and exit\n"
664 " -t TTY, --terminal=TTY controlling tty\n"
665 " -u USER, --user=USER run as user USER; only applicable if started as\n"
666 " root; USER can be a user name or a numerical id\n"
667 " --userdump allow coredumps if -u is given (debugging)\n"
668 " -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
669 " -V, --version print version information and exit\n"
670 " --vfat for backwards compatibility (same as\n"
671 " --dirnames=250,40,1)\n"
672 " -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
673 " seconds (default: %d); '0' disables the watchdog\n"
695 printf(
"Plugins: vdr -P\"name [OPTIONS]\"\n\n");
696 for (
int i = 0; ; i++) {
701 if (DisplayHelp && help) {
716 openlog(
"vdr", LOG_CONS, SysLogTarget);
721 if (daemon(1, 0) == -1) {
722 fprintf(stderr,
"vdr: %m\n");
729 stdin = freopen(Terminal,
"r", stdin);
730 stdout = freopen(Terminal,
"w", stdout);
731 stderr = freopen(Terminal,
"w", stderr);
733 tcgetattr(STDIN_FILENO, &savedTm);
738 if (VdrUser && geteuid() == 0) {
739 StartedAsRoot =
true;
740 if (strcmp(VdrUser,
"root") && strcmp(VdrUser,
"0")) {
743 if (!
SetUser(VdrUser, UserDump))
755 fprintf(stderr,
"vdr: can't access video directory %s\n", VideoDirectory);
760 if (StartedAsRoot && VdrUser)
761 isyslog(
"switched to user '%s'", VdrUser);
768 char *CodeSet = NULL;
769 if (setlocale(LC_CTYPE,
""))
770 CodeSet = nl_langinfo(CODESET);
772 char *LangEnv = getenv(
"LANG");
774 CodeSet = strchr(LangEnv,
'.');
781 isyslog(
"codeset is '%s' - %s", CodeSet, known ?
"known" :
"unknown");
784 if (OverrideCharacterTable) {
786 isyslog(
"override character table is '%s' - %s", OverrideCharacterTable, known ?
"known" :
"unknown");
798 int LastTimerChannel = -1;
799 int PreviousChannel[2] = { 1, 1 };
800 int PreviousChannelIndex = 0;
801 time_t LastChannelChanged = time(NULL);
802 time_t LastInteract = 0;
803 int MaxLatencyTime = 0;
804 bool IsInfoMenu =
false;
805 cSkin *CurrentSkin = NULL;
806 int OldPrimaryDVB = 0;
815 if (!ConfigDirectory)
821 if (!ResourceDirectory)
844 const char *msg =
"no fonts available - OSD will not show any text!";
845 fprintf(stderr,
"vdr: %s\n", msg);
855 if (EpgDataFileName) {
856 const char *EpgDirectory = NULL;
858 EpgDirectory = EpgDataFileName;
861 else if (*EpgDataFileName !=
'/' && *EpgDataFileName !=
'.')
862 EpgDirectory = CacheDirectory;
867 EpgDataReader.
Start();
889 isyslog(
"trying device number %d instead", i + 1);
897 const char *msg =
"no primary device found - using first device!";
898 fprintf(stderr,
"vdr: %s\n", msg);
903 const char *msg =
"no primary device found - giving up!";
904 fprintf(stderr,
"vdr: %s\n", msg);
944 if (!DaemonMode && HasStdin && UseKbd)
992 if (signal(SIGHUP,
SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
993 if (signal(SIGINT,
SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN);
994 if (signal(SIGTERM,
SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
995 if (signal(SIGPIPE,
SignalHandler) == SIG_IGN) signal(SIGPIPE, SIG_IGN);
996 if (WatchdogTimeout > 0)
997 if (signal(SIGALRM,
Watchdog) == SIG_IGN) signal(SIGALRM, SIG_IGN);
1001 if (WatchdogTimeout > 0) {
1002 dsyslog(
"setting watchdog timer to %d seconds", WatchdogTimeout);
1003 alarm(WatchdogTimeout);
1007 if (sd_watchdog_enabled(0, NULL) > 0) {
1009 SdWatchdog = time(NULL);
1010 sd_watchdog_enabled(0, &timeout);
1011 SdWatchdogTimeout = (int)timeout/1000000;
1012 dsyslog(
"SD_WATCHDOG enabled with timeout set to %d seconds", SdWatchdogTimeout);
1017 sd_notify(0,
"READY=1\nSTATUS=Ready");
1027#define DELETE_MENU ((IsInfoMenu &= (Menu == NULL)), delete Menu, Menu = NULL)
1030#ifdef DEBUGRINGBUFFERS
1031 cRingBufferLinear::PrintDebugRBL();
1036 time_t Now = time(NULL);
1040 static time_t lastTime = 0;
1045 if (Channel && (Channel->
Vpid() || Channel->
Apid(0) || Channel->
Dpid(0))) {
1048 else if (LastTimerChannel > 0) {
1049 Channel = Channels->GetByNumber(LastTimerChannel);
1055 LastTimerChannel = -1;
1063 static time_t lastOsdSizeUpdate = 0;
1064 if (Now != lastOsdSizeUpdate) {
1066 static int OsdState = 0;
1071 lastOsdSizeUpdate = Now;
1075 if (WatchdogTimeout > 0) {
1076 int LatencyTime = WatchdogTimeout - alarm(WatchdogTimeout);
1077 if (LatencyTime > MaxLatencyTime) {
1078 MaxLatencyTime = LatencyTime;
1079 dsyslog(
"max. latency time %d seconds", MaxLatencyTime);
1084 if (SdWatchdogTimeout && (Now - SdWatchdog) * 2 > SdWatchdogTimeout) {
1085 sd_notify(0,
"WATCHDOG=1");
1094 static time_t ChannelSaveTimeout = 0;
1096 static cStateKey ChannelsStateKey(
true);
1097 static int ChannelsModifiedByUser = 0;
1100 if (ChannelSaveTimeout != 1) {
1103 ChannelSaveTimeout = 1;
1104 else if (!ChannelSaveTimeout)
1108 ChannelSaveTimeout = 1;
1111 ChannelSaveTimeout = 1;
1112 if (Timers && Channels) {
1115 ChannelSaveTimeout = 0;
1118 for (
const cChannel *Channel = Channels->
First(); Channel; Channel = Channels->
Next(Channel)) {
1124 isyslog(
"retuning due to modification of channel %d (%s)", Channel->Number(), Channel->Name());
1125 Channels->
SwitchTo(Channel->Number());
1135 ChannelsStateKey.
Remove();
1138 if (ChannelSaveTimeout == 1) {
1140 ChannelsStateKey.
Reset();
1141 TimersStateKey.
Reset();
1149 LastChannelChanged = Now;
1151 if (Now - LastChannelChanged >=
Setup.
ZapTimeout && LastChannel != PreviousChannel[PreviousChannelIndex])
1152 PreviousChannel[PreviousChannelIndex ^= 1] = LastChannel;
1164 SchedulesStateKey.
Reset();
1165 bool TimersModified =
false;
1170 TimersModified =
true;
1173 TimersModified =
true;
1176 TimersModified =
true;
1178 SchedulesStateKey.
Remove();
1180 TimersStateKey.
Remove(TimersModified);
1185 bool TimersModified =
false;
1187 TimersModified =
true;
1191 Timer->SetPending(
true);
1193 LastTimerChannel = Timer->Channel()->Number();
1194 TimersModified =
true;
1197 static time_t LastTimerCheck = 0;
1199 for (
cTimer *Timer = Timers->
First(); Timer; Timer = Timers->
Next(Timer)) {
1200 if (Timer->Remote() || Timer->IsPatternTimer())
1202 bool InVpsMargin =
false;
1203 bool NeedsTransponder =
false;
1204 if (Timer->HasFlags(
tfActive) && !Timer->Recording()) {
1205 if (Timer->HasFlags(
tfVps)) {
1208 else if (Timer->Event()) {
1210 InVpsMargin = Timer->Event()->StartTime() <= Now && Now < Timer->Event()->EndTime();
1215 const cSchedule *Schedule = Schedules->GetSchedule(Timer->Channel());
1216 InVpsMargin = !Schedule;
1223 if (!Timer->Recording())
1224 Timer->SetInVpsMargin(InVpsMargin);
1225 if (NeedsTransponder || InVpsMargin) {
1240 dsyslog(
"switching device %d to channel %d %s (%s)", Device->
DeviceNumber() + 1, Timer->Channel()->Number(), *Timer->Channel()->GetChannelID().ToString(), Timer->Channel()->Name());
1245 LastTimerChannel = Timer->Channel()->Number();
1251 LastTimerCheck = Now;
1255 TimersModified =
true;
1258 if (MaxPriority >= 0)
1260 TimersStateKey.
Remove(TimersModified);
1274 if (!NeedsFastResponse) {
1299 bool WasOpen = Interact != NULL;
1300 bool WasMenu = Interact && Interact->
IsMenu();
1338 #define DirectMainFunction(function...)\
1342 Menu = new cMenuMain(function);\
1366 esyslog(
"ERROR: unknown plugin '%s'", PluginName);
1458 isyslog(
"Power button pressed");
1485 Interact = Menu ? Menu : Control;
1489 if (state ==
osUnknown && Interact != Control) {
1492 if (state ==
osEnd) {
1533 case osEnd:
if (Interact == Menu)
1553 if (PreviousChannel[PreviousChannelIndex ^ 1] == LastChannel || LastChannel != PreviousChannel[0] && LastChannel != PreviousChannel[1])
1554 PreviousChannelIndex ^= 1;
1556 Channels->SwitchTo(PreviousChannel[PreviousChannelIndex ^= 1]);
1579 case kOk: LastChannel = -1;
break;
1609 if (NewPrimaryDVB != OldPrimaryDVB) {
1616 OldPrimaryDVB = NewPrimaryDVB;
1660 static time_t LastMemoryCleanup = 0;
1663 LastMemoryCleanup = Now;
1677 esyslog(
"emergency exit requested - shutting down");
1682 signal(SIGHUP, SIG_DFL);
1683 signal(SIGINT, SIG_DFL);
1684 signal(SIGTERM, SIG_DFL);
1685 signal(SIGPIPE, SIG_DFL);
1686 signal(SIGALRM, SIG_DFL);
1715 if (WatchdogTimeout > 0)
1716 dsyslog(
"max. latency time %d seconds", MaxLatencyTime);
1725 tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
1728 sd_notify(0,
"STOPPING=1\nSTATUS=Startup failed, exiting");
1730 sd_notify(0,
"STOPPING=1\nSTATUS=Exiting");
#define CHANNELMOD_RETUNE
#define LOCK_CHANNELS_READ
cChannelCamRelations ChannelCamRelations
cCiResourceHandlers CiResourceHandlers
bool CamResponsesLoad(const char *FileName, bool AllowComments, bool MustExist)
char ** GetArgv(void) const
bool ReadDirectory(const char *Directory)
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
void Load(const char *FileName)
bool ModifiedByUser(int &State) const
Returns true if the channels have been modified by the user since the last call to this function with...
static const cChannels * GetChannelsRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for read access.
bool SwitchTo(int Number) const
static bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
static void SetSystemCharacterTable(const char *CharacterTable)
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
static cControl * Control(cMutexLock &MutexLock, bool Hidden=false, bool *LockedOtherwise=NULL)
Returns the current replay control (if any) in case it is currently visible.
static void Shutdown(void)
virtual cOsdObject * GetInfo(void)
Returns an OSD object that displays information about the currently played programme.
static void Launch(cControl *Control)
virtual void Hide(void)=0
bool Update(void)
Update status display of the countdown.
void Start(const char *Message, int Seconds)
Start the 5 minute shutdown warning countdown.
void Cancel(void)
Cancel the 5 minute shutdown warning countdown.
bool Done(void)
Check if countdown timer has run out without canceling.
static bool WaitForAllDevicesReady(int Timeout=0)
Waits until all devices have become ready, or the given Timeout (seconds) has expired.
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise.
static cDevice * PrimaryDevice(void)
Returns the primary device.
static void SetUseDevice(int n)
Sets the 'useDevice' flag of the given device.
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
static void Shutdown(void)
Closes down all devices.
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
bool IsPrimaryDevice(bool CheckDecoder=true) const
static bool SetPrimaryDevice(int n)
Sets the primary device to 'n'.
void StopReplay(void)
Stops the current replay session (if any).
void SetVolume(int Volume, bool Absolute=false)
Sets the volume to the given value, either absolutely or relative to the current volume.
static int NumDevices(void)
Returns the total number of devices.
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
virtual bool HasProgramme(void) const
Returns true if the device is currently showing any programme to the user, either through replaying o...
static int CurrentVolume(void)
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
static cDevice * GetDeviceForTransponder(const cChannel *Channel, int Priority)
Returns a device that is not currently "occupied" and can be tuned to the transponder of the given Ch...
void SetOccupied(int Seconds, int Priority=MINPRIORITY, time_t From=0)
Sets the occupied timeout for this device to the given number of Seconds, This can be used to tune a ...
bool ToggleMute(void)
Turns the volume off or on and returns the new mute state.
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
cDisplayChannel(int Number, bool Switched)
static void Process(eKeys Key)
static cDisplaySubtitleTracks * Create(void)
static cDisplayTracks * Create(void)
static void Process(eKeys Key)
static cDisplayVolume * Create(void)
static void Process(eKeys Key)
bool Load(const char *FileName)
static bool BondDevices(const char *Bondings)
Bonds the devices as defined in the given Bondings string.
static bool useDvbDevices
static bool Initialize(void)
Initializes the DVB devices.
cExternalAudio(const char *Command)
static cString GetFontFileName(const char *FontName)
Returns the actual font file name for the given FontName.
bool Confirm(const char *s, int Seconds=10, bool WaitForTimeout=false)
eKeys GetKey(bool Wait=true)
const cKeyMacro * Get(eKeys Key)
static void NewLircRemote(const char *Name)
void SetSyncStateKey(cStateKey &StateKey)
When making changes to this list (while holding a write lock) that shall not affect some other code t...
void Purge(bool Force=false)
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
const T * Next(const T *Object) const
< Returns the element immediately before Object in this list, or NULL if Object is the first element ...
cMenuMain(eOSState State=osUnknown, bool OpenSubMenus=false)
static cOsdObject * PluginOsdObject(void)
bool Load(const char *FileName)
virtual bool NeedsFastResponse(void)
virtual eOSState ProcessKey(eKeys Key)
static bool OsdSizeChanged(int &State)
Checks if the OSD size has changed and a currently displayed OSD needs to be redrawn.
static void Shutdown(void)
Shuts down the OSD provider facility by deleting the current OSD provider.
static void UpdateOsdSize(bool Force=false)
Inquires the actual size of the video display and adjusts the OSD and font sizes accordingly.
static int IsOpen(void)
Returns true if there is currently a level 0 OSD open.
void MainThreadHook(void)
void SetDirectory(const char *Directory)
bool InitializePlugins(void)
void AddPlugin(const char *Args)
static bool HasPlugins(void)
bool LoadPlugins(bool Log=false)
void Shutdown(bool Log=false)
static cPlugin * GetPlugin(int Index)
virtual const char * CommandLineHelp(void)
virtual const char * Version(void)=0
static void SetCacheDirectory(const char *Dir)
virtual cOsdObject * MainMenuAction(void)
static void SetConfigDirectory(const char *Dir)
static void SetResourceDirectory(const char *Dir)
virtual const char * Description(void)=0
static cPositioner * GetPositioner(void)
Returns a previously created positioner.
static void DestroyPositioner(void)
Destroys a previously created positioner.
static void ChannelDataModified(const cChannel *Channel)
static bool Process(cTimers *Timers, time_t t)
static bool PauseLiveVideo(void)
static void Shutdown(void)
static bool Start(cTimers *Timers, cTimer *Timer, bool Pause=false)
static void SetCommand(const char *Command)
void DelAll(void)
Deletes/terminates all operations.
bool Finished(bool &Error)
Returns true if all operations in the list have been finished.
static void Update(bool Wait=false)
Triggers an update of the list of recordings, which will run as a separate thread if Wait is false.
static bool NeedsUpdate(void)
static const char * GetPlugin(void)
Returns the name of the plugin that was set with a previous call to PutMacro() or CallPlugin().
bool Put(uint64_t Code, bool Repeat=false, bool Release=false)
static bool PutMacro(eKeys Key)
static time_t LastActivity(void)
Absolute time when last key was delivered by Get().
static const char * LastReplayed(void)
static void DelTimeshiftTimer(void)
static const char * NowReplaying(void)
bool PresentSeenWithin(int Seconds) const
static const cSchedules * GetSchedulesRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of schedules for read access.
static void SetEpgDataFileName(const char *FileName)
static void Cleanup(bool Force=false)
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
char OSDTheme[MaxThemeName]
char OSDSkin[MaxSkinName]
bool Load(const char *FileName)
int OpenRecMenuAtLastReplayed
char FontOsd[MAXFONTNAME]
void CheckManualStart(int ManualStart)
Check whether the next timer is in ManualStart time window.
void SetShutdownCommand(const char *ShutdownCommand)
Set the command string for shutdown command.
bool ConfirmShutdown(bool Ask)
Check for background activity that blocks shutdown.
bool EmergencyExitRequested(void)
Returns true if an emergency exit was requested.
void SetRetry(int Seconds)
Set shutdown retry so that VDR will not try to automatically shut down within Seconds.
bool Retry(time_t AtTime=0)
Check whether its time to re-try the shutdown.
bool IsUserInactive(time_t AtTime=0)
Check whether VDR is in interactive mode or non-interactive mode (waiting for shutdown).
bool DoShutdown(bool Force)
Call the shutdown script with data of the next pending timer.
bool ConfirmRestart(bool Ask)
Check for background activity that blocks restart.
void Exit(int ExitCode)
Set VDR exit code and initiate end of VDR main loop.
void SetUserInactiveTimeout(int Seconds=-1, bool Force=false)
Set the time in the future when VDR will switch into non-interactive mode or power down.
bool DoExit(void)
Check if an exit code was set, and VDR should exit.
void SetUserInactive(void)
Set VDR manually into non-interactive mode from now on.
int GetExitCode(void)
Get the currently set exit code of VDR.
bool SetCurrent(const char *Name=NULL)
Sets the current skin to the one indicated by name.
eKeys Message(eMessageType Type, const char *s, int Seconds=0)
Displays the given message, either through a currently visible display object that is capable of doin...
cSkin * Current(void)
Returns a pointer to the current skin.
void ProcessQueuedMessages(void)
Processes the first queued message, if any.
virtual void Clear(void) override
Free up all registered skins.
int QueueMessage(eMessageType Type, const char *s, int Seconds=0, int Timeout=0)
Like Message(), but this function may be called from a background thread.
static time_t lastSpinUpDiskCheck
static void Check(time_t Now)
static cSpinUpDisk spinUpDisk
virtual void Action(void) override
A derived cThread class must implement the code it wants to execute as a separate thread in this func...
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
void Reset(void)
Resets the state of this key, so that the next call to a lock's Lock() function with this key will re...
bool StateChanged(void)
Returns true if this key is used for obtaining a write lock, and the lock's state differs from that o...
static void MsgChannelChange(const cChannel *Channel)
static void SetThemesDirectory(const char *ThemesDirectory)
bool Load(const char *SkinName)
static void SetMainThreadId(void)
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
cThread(const char *Description=NULL, bool LowPriority=false)
Creates a new thread.
bool Active(void)
Checks whether the thread is still alive.
static tThreadId ThreadId(void)
static bool Load(const char *FileName)
int GetMaxPriority(void) const
Returns the maximum priority of all local timers that are currently recording.
static cTimers * GetTimersWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for write access.
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
const cTimer * GetMatch(time_t t) const
bool SpawnPatternTimers(const cSchedules *Schedules)
bool DeleteExpired(bool Force)
bool SetEvents(const cSchedules *Schedules)
bool AdjustSpawnedTimers(void)
static void Destroy(void)
static const char * Name(void)
static void SetName(const char *Name)
cNestedItemList RecordingCommands
bool CutRecording(const char *FileName)
void ReportEpgBugFixStats(bool Force)
#define LOCK_SCHEDULES_READ
void I18nInitialize(const char *LocaleDir)
Detects all available locales and loads the language names and codes.
bool SetSystemCharacterTable(const char *CharacterTable)
bool SetOverrideCharacterTable(const char *CharacterTable)
static bool Error(const char *Fmt,...) __attribute__((format(printf
bool Pes2Ts(const char *PesFileName, const char *TsFileName)
void AssertFreeDiskSpace(int Priority, bool Force)
The special Priority value -1 means that we shall get rid of any deleted recordings faster than norma...
bool GenerateIndex(const char *FileName)
Generates the index of the existing recording with the given FileName.
cDoneRecordings DoneRecordingsPattern
cRecordingsHandler RecordingsHandler
void RemoveDeletedRecordings(void)
#define MAXVIDEOFILESIZEDEFAULT
#define MAXVIDEOFILESIZETS
cShutdownHandler ShutdownHandler
cSourceParams SourceParams
static tChannelID FromString(const char *s)
void StopSVDRPHandler(void)
void SetSVDRPGrabImageDir(const char *GrabImageDir)
void StartSVDRPHandler(void)
void SetSVDRPPorts(int TcpPort, int UdpPort)
cStateKey StateKeySVDRPRemoteTimersPoll
Controls whether a change to the local list of timers needs to result in sending a POLL to the remote...
static bool SetUser(const char *User, bool UserDump)
#define SHUTDOWNFORCEPROMPT
int main(int argc, char *argv[])
#define TIMERLOOKAHEADTIME
#define SHUTDOWNCANCELPROMPT
#define DEFAULTEPGDATAFILENAME
static void SignalHandler(int signum)
static bool SetKeepCaps(bool On)
#define TIMERDEVICETIMEOUT
static bool DropCaps(void)
static void Watchdog(int signum)
#define RESTARTCANCELPROMPT
#define DEVICEREADYTIMEOUT
static volatile sig_atomic_t LastSignal
#define DirectMainFunction(function...)