vdr  2.4.0
vdr.c
Go to the documentation of this file.
1 /*
2  * vdr.c: Video Disk Recorder main program
3  *
4  * Copyright (C) 2000-2018 Klaus Schmidinger
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program 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 this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  *
21  * The author can be reached at vdr@tvdr.de
22  *
23  * The project's page is at http://www.tvdr.de
24  *
25  * $Id: vdr.c 4.25 2018/04/10 13:24:43 kls Exp $
26  */
27 
28 #include <getopt.h>
29 #include <grp.h>
30 #include <langinfo.h>
31 #include <locale.h>
32 #include <pwd.h>
33 #include <signal.h>
34 #include <stdlib.h>
35 #include <sys/capability.h>
36 #include <sys/prctl.h>
37 #ifdef SDNOTIFY
38 #include <systemd/sd-daemon.h>
39 #endif
40 #include <termios.h>
41 #include <unistd.h>
42 #include "args.h"
43 #include "audio.h"
44 #include "channels.h"
45 #include "config.h"
46 #include "cutter.h"
47 #include "device.h"
48 #include "diseqc.h"
49 #include "dvbdevice.h"
50 #include "eitscan.h"
51 #include "epg.h"
52 #include "i18n.h"
53 #include "interface.h"
54 #include "keys.h"
55 #include "libsi/si.h"
56 #include "lirc.h"
57 #include "menu.h"
58 #include "osdbase.h"
59 #include "plugin.h"
60 #include "recording.h"
61 #include "shutdown.h"
62 #include "skinclassic.h"
63 #include "skinlcars.h"
64 #include "skinsttng.h"
65 #include "sourceparams.h"
66 #include "sources.h"
67 #include "status.h"
68 #include "svdrp.h"
69 #include "themes.h"
70 #include "timers.h"
71 #include "tools.h"
72 #include "transfer.h"
73 #include "videodir.h"
74 
75 #define MINCHANNELWAIT 10 // seconds to wait between failed channel switchings
76 #define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping
77 #define SHUTDOWNWAIT 300 // seconds to wait in user prompt before automatic shutdown
78 #define SHUTDOWNRETRY 360 // seconds before trying again to shut down
79 #define SHUTDOWNFORCEPROMPT 5 // seconds to wait in user prompt to allow forcing shutdown
80 #define SHUTDOWNCANCELPROMPT 5 // seconds to wait in user prompt to allow canceling shutdown
81 #define RESTARTCANCELPROMPT 5 // seconds to wait in user prompt before restarting on SIGHUP
82 #define MANUALSTART 600 // seconds the next timer must be in the future to assume manual start
83 #define CHANNELSAVEDELTA 600 // seconds before saving channels.conf after automatic modifications
84 #define DEVICEREADYTIMEOUT 30 // seconds to wait until all devices are ready
85 #define MENUTIMEOUT 120 // seconds of user inactivity after which an OSD display is closed
86 #define TIMERCHECKDELTA 10 // seconds between checks for timers that need to see their channel
87 #define TIMERDEVICETIMEOUT 8 // seconds before a device used for timer check may be reused
88 #define TIMERLOOKAHEADTIME 60 // seconds before a non-VPS timer starts and the channel is switched if possible
89 #define VPSLOOKAHEADTIME 24 // hours within which VPS timers will make sure their events are up to date
90 #define VPSUPTODATETIME 3600 // seconds before the event or schedule of a VPS timer needs to be refreshed
91 
92 #define EXIT(v) { ShutdownHandler.Exit(v); goto Exit; }
93 
94 static int LastSignal = 0;
95 
96 static bool SetUser(const char *User, bool UserDump)
97 {
98  if (User) {
99  struct passwd *user = isnumber(User) ? getpwuid(atoi(User)) : getpwnam(User);
100  if (!user) {
101  fprintf(stderr, "vdr: unknown user: '%s'\n", User);
102  return false;
103  }
104  if (setgid(user->pw_gid) < 0) {
105  fprintf(stderr, "vdr: cannot set group id %u: %s\n", (unsigned int)user->pw_gid, strerror(errno));
106  return false;
107  }
108  if (initgroups(user->pw_name, user->pw_gid) < 0) {
109  fprintf(stderr, "vdr: cannot set supplemental group ids for user %s: %s\n", user->pw_name, strerror(errno));
110  return false;
111  }
112  if (setuid(user->pw_uid) < 0) {
113  fprintf(stderr, "vdr: cannot set user id %u: %s\n", (unsigned int)user->pw_uid, strerror(errno));
114  return false;
115  }
116  if (UserDump && prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0)
117  fprintf(stderr, "vdr: warning - cannot set dumpable: %s\n", strerror(errno));
118  setenv("HOME", user->pw_dir, 1);
119  setenv("USER", user->pw_name, 1);
120  setenv("LOGNAME", user->pw_name, 1);
121  setenv("SHELL", user->pw_shell, 1);
122  }
123  return true;
124 }
125 
126 static bool DropCaps(void)
127 {
128  // drop all capabilities except selected ones
129  cap_t caps = cap_from_text("= cap_sys_nice,cap_sys_time,cap_net_raw=ep");
130  if (!caps) {
131  fprintf(stderr, "vdr: cap_from_text failed: %s\n", strerror(errno));
132  return false;
133  }
134  if (cap_set_proc(caps) == -1) {
135  fprintf(stderr, "vdr: cap_set_proc failed: %s\n", strerror(errno));
136  cap_free(caps);
137  return false;
138  }
139  cap_free(caps);
140  return true;
141 }
142 
143 static bool SetKeepCaps(bool On)
144 {
145  // set keeping capabilities during setuid() on/off
146  if (prctl(PR_SET_KEEPCAPS, On ? 1 : 0, 0, 0, 0) != 0) {
147  fprintf(stderr, "vdr: prctl failed\n");
148  return false;
149  }
150  return true;
151 }
152 
153 static void SignalHandler(int signum)
154 {
155  switch (signum) {
156  case SIGPIPE:
157  break;
158  case SIGHUP:
159  LastSignal = signum;
160  break;
161  default:
162  LastSignal = signum;
163  Interface->Interrupt();
165  }
166  signal(signum, SignalHandler);
167 }
168 
169 static void Watchdog(int signum)
170 {
171  // Something terrible must have happened that prevented the 'alarm()' from
172  // being called in time, so let's get out of here:
173  esyslog("PANIC: watchdog timer expired - exiting!");
174 #ifdef SDNOTIFY
175  sd_notify(0, "STOPPING=1\nSTATUS=PANIC");
176 #endif
177  exit(1);
178 }
179 
180 int main(int argc, char *argv[])
181 {
182  // Save terminal settings:
183 
184  struct termios savedTm;
185  bool HasStdin = (tcgetpgrp(STDIN_FILENO) == getpid() || getppid() != (pid_t)1) && tcgetattr(STDIN_FILENO, &savedTm) == 0;
186 
187  // Initiate locale:
188 
189  setlocale(LC_ALL, "");
190 
191  // Command line options:
192 
193 #define dd(a, b) (*a ? a : b)
194 #define DEFAULTSVDRPPORT 6419
195 #define DEFAULTWATCHDOG 0 // seconds
196 #define DEFAULTVIDEODIR VIDEODIR
197 #define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory)
198 #define DEFAULTARGSDIR dd(ARGSDIR, "/etc/vdr/conf.d")
199 #define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory)
200 #define DEFAULTRESDIR dd(RESDIR, ConfigDirectory)
201 #define DEFAULTPLUGINDIR PLUGINDIR
202 #define DEFAULTLOCDIR LOCDIR
203 #define DEFAULTEPGDATAFILENAME "epg.data"
204 
205  bool StartedAsRoot = false;
206  const char *VdrUser = NULL;
207  bool UserDump = false;
208  int SVDRPport = DEFAULTSVDRPPORT;
209  const char *AudioCommand = NULL;
210  const char *VideoDirectory = DEFAULTVIDEODIR;
211  const char *ConfigDirectory = NULL;
212  const char *CacheDirectory = NULL;
213  const char *ResourceDirectory = NULL;
214  const char *LocaleDirectory = DEFAULTLOCDIR;
215  const char *EpgDataFileName = DEFAULTEPGDATAFILENAME;
216  bool DisplayHelp = false;
217  bool DisplayVersion = false;
218  bool DaemonMode = false;
219  int SysLogTarget = LOG_USER;
220  bool MuteAudio = false;
221  int WatchdogTimeout = DEFAULTWATCHDOG;
222  const char *Terminal = NULL;
223  const char *OverrideCharacterTable = NULL;
224 #ifndef DEPRECATED_VDR_CHARSET_OVERRIDE
225 #define DEPRECATED_VDR_CHARSET_OVERRIDE 0
226 #endif
227 #if DEPRECATED_VDR_CHARSET_OVERRIDE
228  OverrideCharacterTable = getenv("VDR_CHARSET_OVERRIDE");
229  const char *DeprecatedVdrCharsetOverride = OverrideCharacterTable;
230 #endif
231 
232  bool UseKbd = true;
233  const char *LircDevice = NULL;
234 #if !defined(REMOTE_KBD)
235  UseKbd = false;
236 #endif
237 #if defined(REMOTE_LIRC)
238  LircDevice = LIRC_DEVICE;
239 #endif
240 #if defined(VDR_USER)
241  VdrUser = VDR_USER;
242 #endif
243 #ifdef SDNOTIFY
244  time_t SdWatchdog = 0;
245  int SdWatchdogTimeout = 0;
246 #endif
247 
248  cArgs *Args = NULL;
249  if (argc == 1) {
250  Args = new cArgs(argv[0]);
251  if (Args->ReadDirectory(DEFAULTARGSDIR)) {
252  argc = Args->GetArgc();
253  argv = Args->GetArgv();
254  }
255  }
256 
257  cVideoDirectory::SetName(VideoDirectory);
258  cPluginManager PluginManager(DEFAULTPLUGINDIR);
259 
260  static struct option long_options[] = {
261  { "audio", required_argument, NULL, 'a' },
262  { "cachedir", required_argument, NULL, 'c' | 0x100 },
263  { "chartab", required_argument, NULL, 'c' | 0x200 },
264  { "config", required_argument, NULL, 'c' },
265  { "daemon", no_argument, NULL, 'd' },
266  { "device", required_argument, NULL, 'D' },
267  { "dirnames", required_argument, NULL, 'd' | 0x100 },
268  { "edit", required_argument, NULL, 'e' | 0x100 },
269  { "epgfile", required_argument, NULL, 'E' },
270  { "filesize", required_argument, NULL, 'f' | 0x100 },
271  { "genindex", required_argument, NULL, 'g' | 0x100 },
272  { "grab", required_argument, NULL, 'g' },
273  { "help", no_argument, NULL, 'h' },
274  { "instance", required_argument, NULL, 'i' },
275  { "lib", required_argument, NULL, 'L' },
276  { "lirc", optional_argument, NULL, 'l' | 0x100 },
277  { "localedir",required_argument, NULL, 'l' | 0x200 },
278  { "log", required_argument, NULL, 'l' },
279  { "mute", no_argument, NULL, 'm' },
280  { "no-kbd", no_argument, NULL, 'n' | 0x100 },
281  { "plugin", required_argument, NULL, 'P' },
282  { "port", required_argument, NULL, 'p' },
283  { "record", required_argument, NULL, 'r' },
284  { "resdir", required_argument, NULL, 'r' | 0x100 },
285  { "showargs", optional_argument, NULL, 's' | 0x200 },
286  { "shutdown", required_argument, NULL, 's' },
287  { "split", no_argument, NULL, 's' | 0x100 },
288  { "terminal", required_argument, NULL, 't' },
289  { "updindex", required_argument, NULL, 'u' | 0x200 },
290  { "user", required_argument, NULL, 'u' },
291  { "userdump", no_argument, NULL, 'u' | 0x100 },
292  { "version", no_argument, NULL, 'V' },
293  { "vfat", no_argument, NULL, 'v' | 0x100 },
294  { "video", required_argument, NULL, 'v' },
295  { "watchdog", required_argument, NULL, 'w' },
296  { NULL, no_argument, NULL, 0 }
297  };
298 
299  int c;
300  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) {
301  switch (c) {
302  case 'a': AudioCommand = optarg;
303  break;
304  case 'c' | 0x100:
305  CacheDirectory = optarg;
306  break;
307  case 'c' | 0x200:
308  OverrideCharacterTable = optarg;
309  break;
310  case 'c': ConfigDirectory = optarg;
311  break;
312  case 'd': DaemonMode = true;
313  break;
314  case 'D': if (*optarg == '-') {
316  break;
317  }
318  if (isnumber(optarg)) {
319  int n = atoi(optarg);
320  if (0 <= n && n < MAXDEVICES) {
322  break;
323  }
324  }
325  fprintf(stderr, "vdr: invalid DVB device number: %s\n", optarg);
326  return 2;
327  case 'd' | 0x100: {
328  char *s = optarg;
329  if (*s != ',') {
330  int n = strtol(s, &s, 10);
331  if (n <= 0 || n >= PATH_MAX) { // PATH_MAX includes the terminating 0
332  fprintf(stderr, "vdr: invalid directory path length: %s\n", optarg);
333  return 2;
334  }
335  DirectoryPathMax = n;
336  if (!*s)
337  break;
338  if (*s != ',') {
339  fprintf(stderr, "vdr: invalid delimiter: %s\n", optarg);
340  return 2;
341  }
342  }
343  s++;
344  if (!*s)
345  break;
346  if (*s != ',') {
347  int n = strtol(s, &s, 10);
348  if (n <= 0 || n > NAME_MAX) { // NAME_MAX excludes the terminating 0
349  fprintf(stderr, "vdr: invalid directory name length: %s\n", optarg);
350  return 2;
351  }
352  DirectoryNameMax = n;
353  if (!*s)
354  break;
355  if (*s != ',') {
356  fprintf(stderr, "vdr: invalid delimiter: %s\n", optarg);
357  return 2;
358  }
359  }
360  s++;
361  if (!*s)
362  break;
363  int n = strtol(s, &s, 10);
364  if (n != 0 && n != 1) {
365  fprintf(stderr, "vdr: invalid directory encoding: %s\n", optarg);
366  return 2;
367  }
368  DirectoryEncoding = n;
369  if (*s) {
370  fprintf(stderr, "vdr: unexpected data: %s\n", optarg);
371  return 2;
372  }
373  }
374  break;
375  case 'e' | 0x100:
376  return CutRecording(optarg) ? 0 : 2;
377  case 'E': EpgDataFileName = (*optarg != '-' ? optarg : NULL);
378  break;
379  case 'f' | 0x100:
380  Setup.MaxVideoFileSize = StrToNum(optarg) / MEGABYTE(1);
385  break;
386  case 'g' | 0x100:
387  return GenerateIndex(optarg) ? 0 : 2;
388  case 'g': SetSVDRPGrabImageDir(*optarg != '-' ? optarg : NULL);
389  break;
390  case 'h': DisplayHelp = true;
391  break;
392  case 'i': if (isnumber(optarg)) {
393  InstanceId = atoi(optarg);
394  if (InstanceId >= 0)
395  break;
396  }
397  fprintf(stderr, "vdr: invalid instance id: %s\n", optarg);
398  return 2;
399  case 'l': {
400  char *p = strchr(optarg, '.');
401  if (p)
402  *p = 0;
403  if (isnumber(optarg)) {
404  int l = atoi(optarg);
405  if (0 <= l && l <= 3) {
406  SysLogLevel = l;
407  if (!p)
408  break;
409  if (isnumber(p + 1)) {
410  int l = atoi(p + 1);
411  if (0 <= l && l <= 7) {
412  int targets[] = { LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7 };
413  SysLogTarget = targets[l];
414  break;
415  }
416  }
417  }
418  }
419  if (p)
420  *p = '.';
421  fprintf(stderr, "vdr: invalid log level: %s\n", optarg);
422  return 2;
423  }
424  case 'L': if (access(optarg, R_OK | X_OK) == 0)
425  PluginManager.SetDirectory(optarg);
426  else {
427  fprintf(stderr, "vdr: can't access plugin directory: %s\n", optarg);
428  return 2;
429  }
430  break;
431  case 'l' | 0x100:
432  LircDevice = optarg ? optarg : LIRC_DEVICE;
433  break;
434  case 'l' | 0x200:
435  if (access(optarg, R_OK | X_OK) == 0)
436  LocaleDirectory = optarg;
437  else {
438  fprintf(stderr, "vdr: can't access locale directory: %s\n", optarg);
439  return 2;
440  }
441  break;
442  case 'm': MuteAudio = true;
443  break;
444  case 'n' | 0x100:
445  UseKbd = false;
446  break;
447  case 'p': if (isnumber(optarg))
448  SVDRPport = atoi(optarg);
449  else {
450  fprintf(stderr, "vdr: invalid port number: %s\n", optarg);
451  return 2;
452  }
453  break;
454  case 'P': PluginManager.AddPlugin(optarg);
455  break;
456  case 'r': cRecordingUserCommand::SetCommand(optarg);
457  break;
458  case 'r' | 0x100:
459  ResourceDirectory = optarg;
460  break;
461  case 's': ShutdownHandler.SetShutdownCommand(optarg);
462  break;
463  case 's' | 0x100:
465  break;
466  case 's' | 0x200: {
467  const char *ArgsDir = optarg ? optarg : DEFAULTARGSDIR;
468  cArgs Args(argv[0]);
469  if (!Args.ReadDirectory(ArgsDir)) {
470  fprintf(stderr, "vdr: can't read arguments from directory: %s\n", ArgsDir);
471  return 2;
472  }
473  int c = Args.GetArgc();
474  char **v = Args.GetArgv();
475  for (int i = 1; i < c; i++)
476  printf("%s\n", v[i]);
477  return 0;
478  }
479  case 't': Terminal = optarg;
480  if (access(Terminal, R_OK | W_OK) < 0) {
481  fprintf(stderr, "vdr: can't access terminal: %s\n", Terminal);
482  return 2;
483  }
484  break;
485  case 'u': if (*optarg)
486  VdrUser = optarg;
487  break;
488  case 'u' | 0x100:
489  UserDump = true;
490  break;
491  case 'u' | 0x200:
492  return GenerateIndex(optarg, true) ? 0 : 2;
493  case 'V': DisplayVersion = true;
494  break;
495  case 'v' | 0x100:
496  DirectoryPathMax = 250;
497  DirectoryNameMax = 40;
498  DirectoryEncoding = true;
499  break;
500  case 'v': VideoDirectory = optarg;
501  while (optarg && *optarg && optarg[strlen(optarg) - 1] == '/')
502  optarg[strlen(optarg) - 1] = 0;
503  cVideoDirectory::SetName(VideoDirectory);
504  break;
505  case 'w': if (isnumber(optarg)) {
506  int t = atoi(optarg);
507  if (t >= 0) {
508  WatchdogTimeout = t;
509  break;
510  }
511  }
512  fprintf(stderr, "vdr: invalid watchdog timeout: %s\n", optarg);
513  return 2;
514  default: return 2;
515  }
516  }
517 
518  // Set user id in case we were started as root:
519 
520  if (VdrUser && geteuid() == 0) {
521  StartedAsRoot = true;
522  if (strcmp(VdrUser, "root") && strcmp(VdrUser, "0")) {
523  if (!SetKeepCaps(true))
524  return 2;
525  if (!SetUser(VdrUser, UserDump))
526  return 2;
527  if (!SetKeepCaps(false))
528  return 2;
529  if (!DropCaps())
530  return 2;
531  }
532  }
533 
534  // Help and version info:
535 
536  if (DisplayHelp || DisplayVersion) {
537  if (!PluginManager.HasPlugins())
538  PluginManager.AddPlugin("*"); // adds all available plugins
539  PluginManager.LoadPlugins();
540  if (DisplayHelp) {
541  printf("Usage: vdr [OPTIONS]\n\n" // for easier orientation, this is column 80|
542  " -a CMD, --audio=CMD send Dolby Digital audio to stdin of command CMD\n"
543  " --cachedir=DIR save cache files in DIR (default: %s)\n"
544  " --chartab=CHARACTER_TABLE\n"
545  " set the character table to use for strings in the\n"
546  " DVB data stream that don't begin with a character\n"
547  " table indicator, but don't use the standard default\n"
548  " character table (for instance ISO-8859-9)\n"
549  " -c DIR, --config=DIR read config files from DIR (default: %s)\n"
550  " -d, --daemon run in daemon mode\n"
551  " -D NUM, --device=NUM use only the given DVB device (NUM = 0, 1, 2...)\n"
552  " there may be several -D options (default: all DVB\n"
553  " devices will be used); if -D- is given, no DVB\n"
554  " devices will be used at all, independent of any\n"
555  " other -D options\n"
556  " --dirnames=PATH[,NAME[,ENC]]\n"
557  " set the maximum directory path length to PATH\n"
558  " (default: %d); if NAME is also given, it defines\n"
559  " the maximum directory name length (default: %d);\n"
560  " the optional ENC can be 0 or 1, and controls whether\n"
561  " special characters in directory names are encoded as\n"
562  " hex values (default: 0); if PATH or NAME are left\n"
563  " empty (as in \",,1\" to only set ENC), the defaults\n"
564  " apply\n"
565  " --edit=REC cut recording REC and exit\n"
566  " -E FILE, --epgfile=FILE write the EPG data into the given FILE (default is\n"
567  " '%s' in the cache directory)\n"
568  " '-E-' disables this\n"
569  " if FILE is a directory, the default EPG file will be\n"
570  " created in that directory\n"
571  " --filesize=SIZE limit video files to SIZE bytes (default is %dM)\n"
572  " only useful in conjunction with --edit\n"
573  " --genindex=REC generate index for recording REC and exit\n"
574  " -g DIR, --grab=DIR write images from the SVDRP command GRAB into the\n"
575  " given DIR; DIR must be the full path name of an\n"
576  " existing directory, without any \"..\", double '/'\n"
577  " or symlinks (default: none, same as -g-)\n"
578  " -h, --help print this help and exit\n"
579  " -i ID, --instance=ID use ID as the id of this VDR instance (default: 0)\n"
580  " -l LEVEL, --log=LEVEL set log level (default: 3)\n"
581  " 0 = no logging, 1 = errors only,\n"
582  " 2 = errors and info, 3 = errors, info and debug\n"
583  " if logging should be done to LOG_LOCALn instead of\n"
584  " LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7)\n"
585  " -L DIR, --lib=DIR search for plugins in DIR (default is %s)\n"
586  " --lirc[=PATH] use a LIRC remote control device, attached to PATH\n"
587  " (default: %s)\n"
588  " --localedir=DIR search for locale files in DIR (default is\n"
589  " %s)\n"
590  " -m, --mute mute audio of the primary DVB device at startup\n"
591  " --no-kbd don't use the keyboard as an input device\n"
592  " -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
593  " 0 turns off SVDRP\n"
594  " -P OPT, --plugin=OPT load a plugin defined by the given options\n"
595  " -r CMD, --record=CMD call CMD before and after a recording, and after\n"
596  " a recording has been edited or deleted\n"
597  " --resdir=DIR read resource files from DIR (default: %s)\n"
598  " -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
599  " --split split edited files at the editing marks (only\n"
600  " useful in conjunction with --edit)\n"
601  " --showargs[=DIR] print the arguments read from DIR and exit\n"
602  " (default: %s)\n"
603  " -t TTY, --terminal=TTY controlling tty\n"
604  " -u USER, --user=USER run as user USER; only applicable if started as\n"
605  " root; USER can be a user name or a numerical id\n"
606  " --updindex=REC update index for recording REC and exit\n"
607  " --userdump allow coredumps if -u is given (debugging)\n"
608  " -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
609  " -V, --version print version information and exit\n"
610  " --vfat for backwards compatibility (same as\n"
611  " --dirnames=250,40,1)\n"
612  " -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
613  " seconds (default: %d); '0' disables the watchdog\n"
614  "\n",
617  PATH_MAX - 1,
618  NAME_MAX,
622  LIRC_DEVICE,
629  );
630  }
631  if (DisplayVersion)
632  printf("vdr (%s/%s) - The Video Disk Recorder\n", VDRVERSION, APIVERSION);
633  if (PluginManager.HasPlugins()) {
634  if (DisplayHelp)
635  printf("Plugins: vdr -P\"name [OPTIONS]\"\n\n");
636  for (int i = 0; ; i++) {
637  cPlugin *p = PluginManager.GetPlugin(i);
638  if (p) {
639  const char *help = p->CommandLineHelp();
640  printf("%s (%s) - %s\n", p->Name(), p->Version(), p->Description());
641  if (DisplayHelp && help) {
642  printf("\n");
643  puts(help);
644  }
645  }
646  else
647  break;
648  }
649  }
650  return 0;
651  }
652 
653  // Log file:
654 
655  if (SysLogLevel > 0)
656  openlog("vdr", LOG_CONS, SysLogTarget); // LOG_PID doesn't work as expected under NPTL
657 
658  // Check the video directory:
659 
660  if (!DirectoryOk(VideoDirectory, true)) {
661  fprintf(stderr, "vdr: can't access video directory %s\n", VideoDirectory);
662  return 2;
663  }
664 
665  // Daemon mode:
666 
667  if (DaemonMode) {
668  if (daemon(1, 0) == -1) {
669  fprintf(stderr, "vdr: %m\n");
670  esyslog("ERROR: %m");
671  return 2;
672  }
673  }
674  else if (Terminal) {
675  // Claim new controlling terminal
676  stdin = freopen(Terminal, "r", stdin);
677  stdout = freopen(Terminal, "w", stdout);
678  stderr = freopen(Terminal, "w", stderr);
679  HasStdin = true;
680  tcgetattr(STDIN_FILENO, &savedTm);
681  }
682 
683  isyslog("VDR version %s started", VDRVERSION);
684  if (StartedAsRoot && VdrUser)
685  isyslog("switched to user '%s'", VdrUser);
686  if (DaemonMode)
687  dsyslog("running as daemon (tid=%d)", cThread::ThreadId());
689 
690  // Set the system character table:
691 
692  char *CodeSet = NULL;
693  if (setlocale(LC_CTYPE, ""))
694  CodeSet = nl_langinfo(CODESET);
695  else {
696  char *LangEnv = getenv("LANG"); // last resort in case locale stuff isn't installed
697  if (LangEnv) {
698  CodeSet = strchr(LangEnv, '.');
699  if (CodeSet)
700  CodeSet++; // skip the dot
701  }
702  }
703  if (CodeSet) {
704  bool known = SI::SetSystemCharacterTable(CodeSet);
705  isyslog("codeset is '%s' - %s", CodeSet, known ? "known" : "unknown");
707  }
708 #if DEPRECATED_VDR_CHARSET_OVERRIDE
709  if (DeprecatedVdrCharsetOverride)
710  isyslog("use of environment variable VDR_CHARSET_OVERRIDE (%s) is deprecated!", DeprecatedVdrCharsetOverride);
711 #endif
712  if (OverrideCharacterTable) {
713  isyslog("override character table is '%s'", OverrideCharacterTable);
714  SI::SetOverrideCharacterTable(OverrideCharacterTable);
715  }
716 
717  // Initialize internationalization:
718 
719  I18nInitialize(LocaleDirectory);
720 
721  // Main program loop variables - need to be here to have them initialized before any EXIT():
722 
723  cEpgDataReader EpgDataReader;
724  cOsdObject *Menu = NULL;
725  int LastChannel = 0;
726  int LastTimerChannel = -1;
727  int PreviousChannel[2] = { 1, 1 };
728  int PreviousChannelIndex = 0;
729  time_t LastChannelChanged = time(NULL);
730  time_t LastInteract = 0;
731  int MaxLatencyTime = 0;
732  bool InhibitEpgScan = false;
733  bool IsInfoMenu = false;
734  cSkin *CurrentSkin = NULL;
735  int OldPrimaryDVB = 0;
736 
737  // Load plugins:
738 
739  if (!PluginManager.LoadPlugins(true))
740  EXIT(2);
741 
742  // Directories:
743 
744  if (!ConfigDirectory)
745  ConfigDirectory = DEFAULTCONFDIR;
746  cPlugin::SetConfigDirectory(ConfigDirectory);
747  if (!CacheDirectory)
748  CacheDirectory = DEFAULTCACHEDIR;
749  cPlugin::SetCacheDirectory(CacheDirectory);
750  if (!ResourceDirectory)
751  ResourceDirectory = DEFAULTRESDIR;
752  cPlugin::SetResourceDirectory(ResourceDirectory);
753  cThemes::SetThemesDirectory("/var/lib/vdr/data/themes");
754 
755  // Configuration data:
756 
757  Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
758  Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true, true);
759  Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
760  Scrs.Load(AddDirectory(ConfigDirectory, "scr.conf"), true);
761  cChannels::Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
762  cTimers::Load(AddDirectory(ConfigDirectory, "timers.conf"));
763  Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
764  RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"));
765  SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
766  Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
767  KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);
768  Folders.Load(AddDirectory(ConfigDirectory, "folders.conf"));
769  CamResponsesLoad(AddDirectory(ConfigDirectory, "camresponses.conf"), true);
770 
772  const char *msg = "no fonts available - OSD will not show any text!";
773  fprintf(stderr, "vdr: %s\n", msg);
774  esyslog("ERROR: %s", msg);
775  }
776 
777  // Recordings:
778 
780 
781  // EPG data:
782 
783  if (EpgDataFileName) {
784  const char *EpgDirectory = NULL;
785  if (DirectoryOk(EpgDataFileName)) {
786  EpgDirectory = EpgDataFileName;
787  EpgDataFileName = DEFAULTEPGDATAFILENAME;
788  }
789  else if (*EpgDataFileName != '/' && *EpgDataFileName != '.')
790  EpgDirectory = CacheDirectory;
791  if (EpgDirectory)
792  cSchedules::SetEpgDataFileName(AddDirectory(EpgDirectory, EpgDataFileName));
793  else
794  cSchedules::SetEpgDataFileName(EpgDataFileName);
795  EpgDataReader.Start();
796  }
797 
798  // DVB interfaces:
799 
802 
803  // Initialize plugins:
804 
805  if (!PluginManager.InitializePlugins())
806  EXIT(2);
807 
808  // Primary device:
809 
811  if (!cDevice::PrimaryDevice() || !cDevice::PrimaryDevice()->HasDecoder()) {
812  if (cDevice::PrimaryDevice() && !cDevice::PrimaryDevice()->HasDecoder())
813  isyslog("device %d has no MPEG decoder", cDevice::PrimaryDevice()->DeviceNumber() + 1);
814  for (int i = 0; i < cDevice::NumDevices(); i++) {
815  cDevice *d = cDevice::GetDevice(i);
816  if (d && d->HasDecoder()) {
817  isyslog("trying device number %d instead", i + 1);
818  if (cDevice::SetPrimaryDevice(i + 1)) {
819  Setup.PrimaryDVB = i + 1;
820  break;
821  }
822  }
823  }
824  if (!cDevice::PrimaryDevice()) {
825  const char *msg = "no primary device found - using first device!";
826  fprintf(stderr, "vdr: %s\n", msg);
827  esyslog("ERROR: %s", msg);
829  EXIT(2);
830  if (!cDevice::PrimaryDevice()) {
831  const char *msg = "no primary device found - giving up!";
832  fprintf(stderr, "vdr: %s\n", msg);
833  esyslog("ERROR: %s", msg);
834  EXIT(2);
835  }
836  }
837  }
838  OldPrimaryDVB = Setup.PrimaryDVB;
839 
840  // Check for timers in automatic start time window:
841 
843 
844  // User interface:
845 
846  Interface = new cInterface;
847 
848  // Default skins:
849 
850  new cSkinLCARS;
851  new cSkinSTTNG;
852  new cSkinClassic;
855  CurrentSkin = Skins.Current();
856 
857  // Start plugins:
858 
859  if (!PluginManager.StartPlugins())
860  EXIT(2);
861 
862  // Set skin and theme in case they're implemented by a plugin:
863 
864  if (!CurrentSkin || CurrentSkin == Skins.Current() && strcmp(Skins.Current()->Name(), Setup.OSDSkin) != 0) {
867  }
868 
869  // Remote Controls:
870  if (LircDevice)
871  new cLircRemote(LircDevice);
872  if (!DaemonMode && HasStdin && UseKbd)
873  new cKbdRemote;
874  Interface->LearnKeys();
875 
876  // External audio:
877 
878  if (AudioCommand)
879  new cExternalAudio(AudioCommand);
880 
881  // Positioner:
882 
883  if (!cPositioner::GetPositioner()) // no plugin has created a positioner
884  new cDiseqcPositioner;
885 
886  // CAM data:
887 
888  ChannelCamRelations.Load(AddDirectory(CacheDirectory, "cam.data"));
889 
890  // Channel:
891 
893  dsyslog("not all devices ready after %d seconds", DEVICEREADYTIMEOUT);
895  dsyslog("not all CAM slots ready after %d seconds", DEVICEREADYTIMEOUT);
896  if (*Setup.InitialChannel) {
898  if (isnumber(Setup.InitialChannel)) { // for compatibility with old setup.conf files
899  if (const cChannel *Channel = Channels->GetByNumber(atoi(Setup.InitialChannel)))
900  Setup.InitialChannel = Channel->GetChannelID().ToString();
901  }
902  if (const cChannel *Channel = Channels->GetByChannelID(tChannelID::FromString(Setup.InitialChannel)))
903  Setup.CurrentChannel = Channel->Number();
904  }
905  if (Setup.InitialVolume >= 0)
907  {
909  Channels->SwitchTo(Setup.CurrentChannel);
910  }
911  if (MuteAudio)
913  else
915 
916  // Signal handlers:
917 
918  if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
919  if (signal(SIGINT, SignalHandler) == SIG_IGN) signal(SIGINT, SIG_IGN);
920  if (signal(SIGTERM, SignalHandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);
921  if (signal(SIGPIPE, SignalHandler) == SIG_IGN) signal(SIGPIPE, SIG_IGN);
922  if (WatchdogTimeout > 0)
923  if (signal(SIGALRM, Watchdog) == SIG_IGN) signal(SIGALRM, SIG_IGN);
924 
925  // Watchdog:
926 
927  if (WatchdogTimeout > 0) {
928  dsyslog("setting watchdog timer to %d seconds", WatchdogTimeout);
929  alarm(WatchdogTimeout); // Initial watchdog timer start
930  }
931 
932 #ifdef SDNOTIFY
933  if (sd_watchdog_enabled(0, NULL) > 0) {
934  uint64_t timeout;
935  SdWatchdog = time(NULL);
936  sd_watchdog_enabled(0, &timeout);
937  SdWatchdogTimeout = (int)timeout/1000000;
938  dsyslog("SD_WATCHDOG enabled with timeout set to %d seconds", SdWatchdogTimeout);
939  }
940 
941  // Startup notification:
942 
943  sd_notify(0, "READY=1\nSTATUS=Ready");
944 #endif
945 
946  // SVDRP:
947 
948  SetSVDRPPorts(SVDRPport, DEFAULTSVDRPPORT);
950 
951  // Main program loop:
952 
953 #define DELETE_MENU ((IsInfoMenu &= (Menu == NULL)), delete Menu, Menu = NULL)
954 
955  while (!ShutdownHandler.DoExit()) {
956 #ifdef DEBUGRINGBUFFERS
957  cRingBufferLinear::PrintDebugRBL();
958 #endif
959  // Attach launched player control:
961 
962  time_t Now = time(NULL);
963 
964  // Make sure we have a visible programme in case device usage has changed:
966  static time_t lastTime = 0;
968  if (!CamMenuActive() && Now - lastTime > MINCHANNELWAIT) { // !CamMenuActive() to avoid interfering with the CAM if a CAM menu is open
970  const cChannel *Channel = Channels->GetByNumber(cDevice::CurrentChannel());
971  if (Channel && (Channel->Vpid() || Channel->Apid(0) || Channel->Dpid(0))) {
972  if (cDevice::GetDeviceForTransponder(Channel, LIVEPRIORITY) && Channels->SwitchTo(Channel->Number())) // try to switch to the original channel...
973  ;
974  else if (LastTimerChannel > 0) {
975  Channel = Channels->GetByNumber(LastTimerChannel);
976  if (Channel && cDevice::GetDeviceForTransponder(Channel, LIVEPRIORITY) && Channels->SwitchTo(LastTimerChannel)) // ...or the one used by the last timer
977  ;
978  }
979  }
980  lastTime = Now; // don't do this too often
981  LastTimerChannel = -1;
982  }
983  }
984  else
985  lastTime = 0; // makes sure we immediately try again next time
986  }
987  // Update the OSD size:
988  {
989  static time_t lastOsdSizeUpdate = 0;
990  if (Now != lastOsdSizeUpdate) { // once per second
992  static int OsdState = 0;
993  if (cOsdProvider::OsdSizeChanged(OsdState)) {
994  if (cOsdMenu *OsdMenu = dynamic_cast<cOsdMenu *>(Menu))
995  OsdMenu->Display();
996  }
997  lastOsdSizeUpdate = Now;
998  }
999  }
1000  // Restart the Watchdog timer:
1001  if (WatchdogTimeout > 0) {
1002  int LatencyTime = WatchdogTimeout - alarm(WatchdogTimeout);
1003  if (LatencyTime > MaxLatencyTime) {
1004  MaxLatencyTime = LatencyTime;
1005  dsyslog("max. latency time %d seconds", MaxLatencyTime);
1006  }
1007  }
1008 #ifdef SDNOTIFY
1009  // Ping systemd watchdog when half the timeout is elapsed:
1010  if (SdWatchdogTimeout && (Now - SdWatchdog) * 2 > SdWatchdogTimeout) {
1011  sd_notify(0, "WATCHDOG=1");
1012  SdWatchdog = Now;
1013  dsyslog("SD_WATCHDOG ping");
1014  }
1015 #endif
1016  // Handle channel and timer modifications:
1017  static bool ChannelsRenumber = false;
1018  {
1019  // Channels and timers need to be stored in a consistent manner,
1020  // therefore if one of them is changed, we save both.
1021  static time_t ChannelSaveTimeout = 0;
1022  static cStateKey TimersStateKey(true);
1023  static cStateKey ChannelsStateKey(true);
1024  static int ChannelsModifiedByUser = 0;
1025  const cTimers *Timers = cTimers::GetTimersRead(TimersStateKey);
1026  const cChannels *Channels = cChannels::GetChannelsRead(ChannelsStateKey);
1027  if (ChannelSaveTimeout != 1) {
1028  if (Channels) {
1029  if (Channels->ModifiedByUser(ChannelsModifiedByUser))
1030  ChannelSaveTimeout = 1; // triggers an immediate save
1031  else if (!ChannelSaveTimeout)
1032  ChannelSaveTimeout = Now + CHANNELSAVEDELTA;
1033  }
1034  if (Timers)
1035  ChannelSaveTimeout = 1; // triggers an immediate save
1036  }
1037  if (ChannelSaveTimeout && Now > ChannelSaveTimeout && !cRecordControls::Active())
1038  ChannelSaveTimeout = 1; // triggers an immediate save
1039  if (Timers && Channels) {
1040  Channels->Save();
1041  Timers->Save();
1042  ChannelSaveTimeout = 0;
1043  }
1044  if (Channels) {
1045  for (const cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
1046  int ChannelModification = Channel->Modification(CHANNELMOD_ALL);
1047  if (ChannelModification & CHANNELMOD_TRANSP)
1048  ChannelsRenumber = true;
1049  if (ChannelModification & CHANNELMOD_RETUNE) {
1051  if (Channel->Number() == cDevice::CurrentChannel() && cDevice::PrimaryDevice()->HasDecoder()) {
1053  if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
1054  isyslog("retuning due to modification of channel %d (%s)", Channel->Number(), Channel->Name());
1055  Channels->SwitchTo(Channel->Number());
1056  }
1057  }
1058  }
1059  cStatus::MsgChannelChange(Channel);
1060  }
1061  }
1062  }
1063  // State keys are removed in reverse order!
1064  if (Channels)
1065  ChannelsStateKey.Remove();
1066  if (Timers)
1067  TimersStateKey.Remove();
1068  if (ChannelSaveTimeout == 1) {
1069  // Only one of them was modified, so we reset the state keys to handle them both in the next turn:
1070  ChannelsStateKey.Reset();
1071  TimersStateKey.Reset();
1072  }
1073  }
1074  // Channel display:
1075  if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
1076  if (!Menu)
1077  Menu = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel >= 0);
1078  LastChannel = cDevice::CurrentChannel();
1079  LastChannelChanged = Now;
1080  }
1081  if (Now - LastChannelChanged >= Setup.ZapTimeout && LastChannel != PreviousChannel[PreviousChannelIndex])
1082  PreviousChannel[PreviousChannelIndex ^= 1] = LastChannel;
1083  {
1084  // Timers and Recordings:
1085  static cStateKey TimersStateKey;
1086  cTimers *Timers = cTimers::GetTimersWrite(TimersStateKey);
1087  {
1088  // Assign events to timers:
1089  static cStateKey SchedulesStateKey;
1090  if (TimersStateKey.StateChanged())
1091  SchedulesStateKey.Reset(); // we assign events if either the Timers or the Schedules have changed
1092  bool TimersModified = false;
1093  if (const cSchedules *Schedules = cSchedules::GetSchedulesRead(SchedulesStateKey)) {
1095  if (Timers->SetEvents(Schedules))
1096  TimersModified = true;
1097  SchedulesStateKey.Remove();
1098  }
1099  TimersStateKey.Remove(TimersModified); // we need to remove the key here, so that syncing StateKeySVDRPRemoteTimersPoll takes effect!
1100  }
1101  // Must do all following calls with the exact same time!
1102  // Process ongoing recordings:
1103  Timers = cTimers::GetTimersWrite(TimersStateKey);
1104  bool TimersModified = false;
1105  if (cRecordControls::Process(Timers, Now))
1106  TimersModified = true;
1107  // Start new recordings:
1108  if (cTimer *Timer = Timers->GetMatch(Now)) {
1109  if (!cRecordControls::Start(Timers, Timer))
1110  Timer->SetPending(true);
1111  else
1112  LastTimerChannel = Timer->Channel()->Number();
1113  TimersModified = true;
1114  }
1115  // Make sure timers "see" their channel early enough:
1116  static time_t LastTimerCheck = 0;
1117  if (Now - LastTimerCheck > TIMERCHECKDELTA) { // don't do this too often
1118  InhibitEpgScan = false;
1119  for (cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
1120  if (Timer->Remote())
1121  continue;
1122  bool InVpsMargin = false;
1123  bool NeedsTransponder = false;
1124  if (Timer->HasFlags(tfActive) && !Timer->Recording()) {
1125  if (Timer->HasFlags(tfVps)) {
1126  if (Timer->Matches(Now, true, Setup.VpsMargin)) {
1127  InVpsMargin = true;
1128  Timer->SetInVpsMargin(InVpsMargin);
1129  }
1130  else if (Timer->Event()) {
1131  InVpsMargin = Timer->Event()->StartTime() <= Now && Now < Timer->Event()->EndTime();
1132  NeedsTransponder = Timer->Event()->StartTime() - Now < VPSLOOKAHEADTIME * 3600 && !Timer->Event()->SeenWithin(VPSUPTODATETIME);
1133  }
1134  else {
1136  const cSchedule *Schedule = Schedules->GetSchedule(Timer->Channel());
1137  InVpsMargin = !Schedule; // we must make sure we have the schedule
1138  NeedsTransponder = Schedule && !Schedule->PresentSeenWithin(VPSUPTODATETIME);
1139  }
1140  InhibitEpgScan |= InVpsMargin | NeedsTransponder;
1141  }
1142  else
1143  NeedsTransponder = Timer->Matches(Now, true, TIMERLOOKAHEADTIME);
1144  }
1145  if (NeedsTransponder || InVpsMargin) {
1146  // Find a device that provides the required transponder:
1147  cDevice *Device = cDevice::GetDeviceForTransponder(Timer->Channel(), MINPRIORITY);
1148  if (!Device && InVpsMargin)
1149  Device = cDevice::GetDeviceForTransponder(Timer->Channel(), LIVEPRIORITY);
1150  // Switch the device to the transponder:
1151  if (Device) {
1152  bool HadProgramme = cDevice::PrimaryDevice()->HasProgramme();
1153  if (!Device->IsTunedToTransponder(Timer->Channel())) {
1154  if (Device == cDevice::ActualDevice() && !Device->IsPrimaryDevice())
1155  cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
1156  dsyslog("switching device %d to channel %d %s (%s)", Device->DeviceNumber() + 1, Timer->Channel()->Number(), *Timer->Channel()->GetChannelID().ToString(), Timer->Channel()->Name());
1157  if (Device->SwitchChannel(Timer->Channel(), false))
1159  }
1160  if (cDevice::PrimaryDevice()->HasDecoder() && HadProgramme && !cDevice::PrimaryDevice()->HasProgramme())
1161  Skins.QueueMessage(mtInfo, tr("Upcoming recording!")); // the previous SwitchChannel() has switched away the current live channel
1162  }
1163  }
1164  }
1165  LastTimerCheck = Now;
1166  }
1167  // Delete expired timers:
1168  if (Timers->DeleteExpired())
1169  TimersModified = true;
1170  // Make sure there is enough free disk space for ongoing recordings:
1172  TimersStateKey.Remove(TimersModified);
1173  }
1174  // Renumber channels on LCN update
1175  if (ChannelsRenumber) {
1177  Channels->ReNumber();
1178  ChannelsRenumber = false;
1179  }
1180  // Recordings:
1181  if (!Menu) {
1184  }
1185  // CAM control:
1186  if (!Menu && !cOsd::IsOpen())
1187  Menu = CamControl();
1188  // Queued messages:
1189  if (!Skins.IsOpen())
1191  // User Input:
1192  cOsdObject *Interact = Menu ? Menu : cControl::Control();
1193  eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
1194  if (ISREALKEY(key)) {
1195  EITScanner.Activity();
1196  // Cancel shutdown countdown:
1199  // Set user active for MinUserInactivity time in the future:
1201  }
1202  // Keys that must work independent of any interactive mode:
1203  switch (int(key)) {
1204  // Menu control:
1205  case kMenu: {
1206  key = kNone; // nobody else needs to see this key
1207  bool WasOpen = Interact != NULL;
1208  bool WasMenu = Interact && Interact->IsMenu();
1209  if (Menu)
1210  DELETE_MENU;
1211  else if (cControl::Control()) {
1212  if (cOsd::IsOpen())
1213  cControl::Control()->Hide();
1214  else
1215  WasOpen = false;
1216  }
1217  if (!WasOpen || !WasMenu && !Setup.MenuKeyCloses)
1218  Menu = new cMenuMain;
1219  }
1220  break;
1221  // Info:
1222  case kInfo: {
1223  if (IsInfoMenu) {
1224  key = kNone; // nobody else needs to see this key
1225  DELETE_MENU;
1226  }
1227  else if (!Menu) {
1228  IsInfoMenu = true;
1229  if (cControl::Control()) {
1230  cControl::Control()->Hide();
1231  Menu = cControl::Control()->GetInfo();
1232  if (Menu)
1233  Menu->Show();
1234  else
1235  IsInfoMenu = false;
1236  }
1237  else {
1238  cRemote::Put(kOk, true);
1239  cRemote::Put(kSchedule, true);
1240  }
1241  key = kNone; // nobody else needs to see this key
1242  }
1243  }
1244  break;
1245  // Direct main menu functions:
1246  #define DirectMainFunction(function)\
1247  { DELETE_MENU;\
1248  if (cControl::Control())\
1249  cControl::Control()->Hide();\
1250  Menu = new cMenuMain(function);\
1251  key = kNone; } // nobody else needs to see this key
1252  case kSchedule: DirectMainFunction(osSchedule); break;
1253  case kChannels: DirectMainFunction(osChannels); break;
1254  case kTimers: DirectMainFunction(osTimers); break;
1256  case kSetup: DirectMainFunction(osSetup); break;
1257  case kCommands: DirectMainFunction(osCommands); break;
1258  case kUser0 ... kUser9: cRemote::PutMacro(key); key = kNone; break;
1259  case k_Plugin: {
1260  const char *PluginName = cRemote::GetPlugin();
1261  if (PluginName) {
1262  DELETE_MENU;
1263  if (cControl::Control())
1264  cControl::Control()->Hide();
1265  cPlugin *plugin = cPluginManager::GetPlugin(PluginName);
1266  if (plugin) {
1267  Menu = plugin->MainMenuAction();
1268  if (Menu)
1269  Menu->Show();
1270  }
1271  else
1272  esyslog("ERROR: unknown plugin '%s'", PluginName);
1273  }
1274  key = kNone; // nobody else needs to see these keys
1275  }
1276  break;
1277  // Channel up/down:
1278  case kChanUp|k_Repeat:
1279  case kChanUp:
1280  case kChanDn|k_Repeat:
1281  case kChanDn:
1282  if (!Interact) {
1283  Menu = new cDisplayChannel(NORMALKEY(key));
1284  continue;
1285  }
1286  else if (cDisplayChannel::IsOpen() || cControl::Control()) {
1287  Interact->ProcessKey(key);
1288  continue;
1289  }
1290  else
1291  cDevice::SwitchChannel(NORMALKEY(key) == kChanUp ? 1 : -1);
1292  break;
1293  // Volume control:
1294  case kVolUp|k_Repeat:
1295  case kVolUp:
1296  case kVolDn|k_Repeat:
1297  case kVolDn:
1298  case kMute:
1299  if (key == kMute) {
1300  if (!cDevice::PrimaryDevice()->ToggleMute() && !Menu) {
1301  key = kNone; // nobody else needs to see these keys
1302  break; // no need to display "mute off"
1303  }
1304  }
1305  else
1307  if (!Menu && !cOsd::IsOpen())
1308  Menu = cDisplayVolume::Create();
1310  key = kNone; // nobody else needs to see these keys
1311  break;
1312  // Audio track control:
1313  case kAudio:
1314  if (cControl::Control())
1315  cControl::Control()->Hide();
1316  if (!cDisplayTracks::IsOpen()) {
1317  DELETE_MENU;
1318  Menu = cDisplayTracks::Create();
1319  }
1320  else
1322  key = kNone;
1323  break;
1324  // Subtitle track control:
1325  case kSubtitles:
1326  if (cControl::Control())
1327  cControl::Control()->Hide();
1329  DELETE_MENU;
1331  }
1332  else
1334  key = kNone;
1335  break;
1336  // Pausing live video:
1337  case kPlayPause:
1338  case kPause:
1339  if (!cControl::Control()) {
1340  DELETE_MENU;
1341  if (Setup.PauseKeyHandling) {
1342  if (Setup.PauseKeyHandling > 1 || Interface->Confirm(tr("Pause live video?"))) {
1344  Skins.QueueMessage(mtError, tr("No free DVB device to record!"));
1345  }
1346  }
1347  key = kNone; // nobody else needs to see this key
1348  }
1349  break;
1350  // Instant recording:
1351  case kRecord:
1352  if (!cControl::Control()) {
1353  if (Setup.RecordKeyHandling) {
1354  if (Setup.RecordKeyHandling > 1 || Interface->Confirm(tr("Start recording?"))) {
1355  if (cRecordControls::Start())
1356  Skins.QueueMessage(mtInfo, tr("Recording started"));
1357  }
1358  }
1359  key = kNone; // nobody else needs to see this key
1360  }
1361  break;
1362  // Power off:
1363  case kPower:
1364  isyslog("Power button pressed");
1365  DELETE_MENU;
1366  // Check for activity, request power button again if active:
1367  if (!ShutdownHandler.ConfirmShutdown(false) && Skins.Message(mtWarning, tr("VDR will shut down later - press Power to force"), SHUTDOWNFORCEPROMPT) != kPower) {
1368  // Not pressed power - set VDR to be non-interactive and power down later:
1370  break;
1371  }
1372  // No activity or power button pressed twice - ask for confirmation:
1373  if (!ShutdownHandler.ConfirmShutdown(true)) {
1374  // Non-confirmed background activity - set VDR to be non-interactive and power down later:
1376  break;
1377  }
1378  // Ask the final question:
1379  if (!Interface->Confirm(tr("Press any key to cancel shutdown"), SHUTDOWNCANCELPROMPT, true))
1380  // If final question was canceled, continue to be active:
1381  break;
1382  // Ok, now call the shutdown script:
1384  // Set VDR to be non-interactive and power down again later:
1386  // Do not attempt to automatically shut down for a while:
1388  break;
1389  default: break;
1390  }
1391  Interact = Menu ? Menu : cControl::Control(); // might have been closed in the mean time
1392  if (Interact) {
1393  LastInteract = Now;
1394  eOSState state = Interact->ProcessKey(key);
1395  if (state == osUnknown && Interact != cControl::Control()) {
1396  if (ISMODELESSKEY(key) && cControl::Control()) {
1397  state = cControl::Control()->ProcessKey(key);
1398  if (state == osEnd) {
1399  // let's not close a menu when replay ends:
1401  continue;
1402  }
1403  }
1404  else if (Now - cRemote::LastActivity() > MENUTIMEOUT)
1405  state = osEnd;
1406  }
1407  switch (state) {
1408  case osPause: DELETE_MENU;
1410  Skins.QueueMessage(mtError, tr("No free DVB device to record!"));
1411  break;
1412  case osRecord: DELETE_MENU;
1413  if (cRecordControls::Start())
1414  Skins.QueueMessage(mtInfo, tr("Recording started"));
1415  break;
1416  case osRecordings:
1417  DELETE_MENU;
1419  Menu = new cMenuMain(osRecordings, true);
1420  break;
1421  case osReplay: DELETE_MENU;
1424  break;
1425  case osStopReplay:
1426  DELETE_MENU;
1428  break;
1429  case osPlugin: DELETE_MENU;
1430  Menu = cMenuMain::PluginOsdObject();
1431  if (Menu)
1432  Menu->Show();
1433  break;
1434  case osBack:
1435  case osEnd: if (Interact == Menu)
1436  DELETE_MENU;
1437  else
1439  break;
1440  default: ;
1441  }
1442  }
1443  else {
1444  // Key functions in "normal" viewing mode:
1445  if (key != kNone && KeyMacros.Get(key)) {
1446  cRemote::PutMacro(key);
1447  key = kNone;
1448  }
1449  switch (int(key)) {
1450  // Toggle channels:
1451  case kChanPrev:
1452  case k0: {
1453  if (PreviousChannel[PreviousChannelIndex ^ 1] == LastChannel || LastChannel != PreviousChannel[0] && LastChannel != PreviousChannel[1])
1454  PreviousChannelIndex ^= 1;
1456  Channels->SwitchTo(PreviousChannel[PreviousChannelIndex ^= 1]);
1457  break;
1458  }
1459  // Direct Channel Select:
1460  case k1 ... k9:
1461  // Left/Right rotates through channel groups:
1462  case kLeft|k_Repeat:
1463  case kLeft:
1464  case kRight|k_Repeat:
1465  case kRight:
1466  // Previous/Next rotates through channel groups:
1467  case kPrev|k_Repeat:
1468  case kPrev:
1469  case kNext|k_Repeat:
1470  case kNext:
1471  // Up/Down Channel Select:
1472  case kUp|k_Repeat:
1473  case kUp:
1474  case kDown|k_Repeat:
1475  case kDown:
1476  Menu = new cDisplayChannel(NORMALKEY(key));
1477  break;
1478  // Viewing Control:
1479  case kOk: LastChannel = -1; break; // forces channel display
1480  // Instant resume of the last viewed recording:
1481  case kPlay:
1485  }
1486  else
1487  DirectMainFunction(osRecordings); // no last viewed recording, so enter the Recordings menu
1488  break;
1489  default: break;
1490  }
1491  }
1492  if (!Menu) {
1493  if (!InhibitEpgScan)
1494  EITScanner.Process();
1495  bool Error = false;
1496  if (RecordingsHandler.Finished(Error)) {
1497  if (Error)
1498  Skins.Message(mtError, tr("Editing process failed!"));
1499  else
1500  Skins.Message(mtInfo, tr("Editing process finished"));
1501  }
1502  }
1503 
1504  // Change primary device:
1505  int NewPrimaryDVB = Setup.PrimaryDVB;
1506  if (NewPrimaryDVB != OldPrimaryDVB) {
1507  DELETE_MENU;
1509  Skins.QueueMessage(mtInfo, tr("Switching primary DVB..."));
1511  cDevice::SetPrimaryDevice(NewPrimaryDVB);
1512  OldPrimaryDVB = NewPrimaryDVB;
1513  }
1514 
1515  // SIGHUP shall cause a restart:
1516  if (LastSignal == SIGHUP) {
1517  if (ShutdownHandler.ConfirmRestart(true) && Interface->Confirm(tr("Press any key to cancel restart"), RESTARTCANCELPROMPT, true))
1518  EXIT(1);
1519  LastSignal = 0;
1520  }
1521 
1522  // Update the shutdown countdown:
1524  if (!ShutdownHandler.ConfirmShutdown(false))
1526  }
1527 
1528  if ((Now - LastInteract) > ACTIVITYTIMEOUT && !cRecordControls::Active() && !RecordingsHandler.Active() && (Now - cRemote::LastActivity()) > ACTIVITYTIMEOUT) {
1529  // Handle housekeeping tasks
1530 
1531  // Shutdown:
1532  // Check whether VDR will be ready for shutdown in SHUTDOWNWAIT seconds:
1533  time_t Soon = Now + SHUTDOWNWAIT;
1535  if (ShutdownHandler.ConfirmShutdown(false))
1536  // Time to shut down - start final countdown:
1537  ShutdownHandler.countdown.Start(tr("VDR will shut down in %s minutes"), SHUTDOWNWAIT); // the placeholder is really %s!
1538  // Dont try to shut down again for a while:
1540  }
1541  // Countdown run down to 0?
1542  if (ShutdownHandler.countdown.Done()) {
1543  // Timed out, now do a final check:
1545  ShutdownHandler.DoShutdown(false);
1546  // Do this again a bit later:
1548  }
1549 
1550  // Disk housekeeping:
1554  // Plugins housekeeping:
1555  PluginManager.Housekeeping();
1556  }
1557 
1559 
1560  // Main thread hooks of plugins:
1561  PluginManager.MainThreadHook();
1562  }
1563 
1565  esyslog("emergency exit requested - shutting down");
1566 
1567 Exit:
1568 
1569  // Reset all signal handlers to default before Interface gets deleted:
1570  signal(SIGHUP, SIG_DFL);
1571  signal(SIGINT, SIG_DFL);
1572  signal(SIGTERM, SIG_DFL);
1573  signal(SIGPIPE, SIG_DFL);
1574  signal(SIGALRM, SIG_DFL);
1575 
1576  StopSVDRPHandler();
1579  PluginManager.StopPlugins();
1581  delete Menu;
1583  delete Interface;
1585  Remotes.Clear();
1586  Audios.Clear();
1587  Skins.Clear();
1588  SourceParams.Clear();
1589  if (ShutdownHandler.GetExitCode() != 2) {
1592  Setup.Save();
1593  }
1597  EpgHandlers.Clear();
1598  cSchedules::Cleanup(true);
1601  PluginManager.Shutdown(true);
1602  ReportEpgBugFixStats(true);
1603  if (WatchdogTimeout > 0)
1604  dsyslog("max. latency time %d seconds", MaxLatencyTime);
1605  if (LastSignal)
1606  isyslog("caught signal %d", LastSignal);
1608  esyslog("emergency exit!");
1609  isyslog("exiting, exit code %d", ShutdownHandler.GetExitCode());
1610  if (SysLogLevel > 0)
1611  closelog();
1612  if (HasStdin)
1613  tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
1614 #ifdef SDNOTIFY
1615  if (ShutdownHandler.GetExitCode() == 2)
1616  sd_notify(0, "STOPPING=1\nSTATUS=Startup failed, exiting");
1617  else
1618  sd_notify(0, "STOPPING=1\nSTATUS=Exiting");
1619 #endif
1620  return ShutdownHandler.GetExitCode();
1621 }
const cTimer * GetMatch(time_t t) const
Definition: timers.c:779
Definition: keys.h:29
cDiseqcs Diseqcs
Definition: diseqc.c:439
static void Watchdog(int signum)
Definition: vdr.c:169
void Purge(bool Force=false)
Definition: tools.c:2111
bool Replaying(void) const
Returns true if we are currently replaying.
Definition: device.c:1307
int DeviceNumber(void) const
Returns the number of this device (0 ... numDevices - 1).
Definition: device.c:160
#define MENUTIMEOUT
Definition: vdr.c:85
void SetSVDRPPorts(int TcpPort, int UdpPort)
Definition: svdrp.c:2724
static const cChannels * GetChannelsRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for read access.
Definition: channels.c:850
bool DirectoryEncoding
Definition: recording.c:78
int Vpid(void) const
Definition: channels.h:154
int Number(void) const
Definition: channels.h:179
void SetOccupied(int Seconds)
Sets the occupied timeout for this device to the given number of Seconds, This can be used to tune a ...
Definition: device.c:934
cString DeviceBondings
Definition: config.h:369
Definition: keys.h:37
int CurrentChannel
Definition: config.h:358
static void SetThemesDirectory(const char *ThemesDirectory)
Definition: themes.c:295
static tChannelID FromString(const char *s)
Definition: channels.c:24
bool ToggleMute(void)
Turns the volume off or on and returns the new mute state.
Definition: device.c:981
void CheckManualStart(int ManualStart)
Check whether the next timer is in ManualStart time window.
Definition: shutdown.c:104
#define dsyslog(a...)
Definition: tools.h:37
cString AddDirectory(const char *DirName, const char *FileName)
Definition: tools.c:384
#define TIMERDEVICETIMEOUT
Definition: vdr.c:87
bool isnumber(const char *s)
Definition: tools.c:346
#define SHUTDOWNFORCEPROMPT
Definition: vdr.c:79
Definition: keys.h:34
bool Confirm(const char *s, int Seconds=10, bool WaitForTimeout=false)
Definition: interface.c:59
bool IsUserInactive(time_t AtTime=0)
Check whether VDR is in interactive mode or non-interactive mode (waiting for shutdown).
Definition: shutdown.h:72
cEpgHandlers EpgHandlers
Definition: epg.c:1384
static const cSchedules * GetSchedulesRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of schedules for read access.
Definition: epg.c:1231
static bool Initialize(void)
Initializes the DVB devices.
Definition: dvbdevice.c:1689
Definition: keys.h:23
bool LoadPlugins(bool Log=false)
Definition: plugin.c:354
#define CHANNELSAVEDELTA
Definition: vdr.c:83
bool Load(const char *SkinName)
Definition: themes.c:239
Definition: keys.h:19
virtual cOsdObject * GetInfo(void)
Returns an OSD object that displays information about the currently played programme.
Definition: player.c:58
cEITScanner EITScanner
Definition: eitscan.c:90
const char * Name(void)
Definition: plugin.h:34
void Shutdown(bool Log=false)
Definition: plugin.c:512
#define DEFAULTVIDEODIR
#define ISMODELESSKEY(k)
Definition: keys.h:80
bool DirectoryOk(const char *DirName, bool LogErrors)
Definition: tools.c:463
#define VPSLOOKAHEADTIME
Definition: vdr.c:89
Definition: keys.h:43
static void Shutdown(void)
Definition: menu.c:5594
virtual const char * Version(void)=0
int Dpid(int i) const
Definition: channels.h:161
Definition: keys.h:39
static bool DropCaps(void)
Definition: vdr.c:126
Definition: keys.h:46
#define RESTARTCANCELPROMPT
Definition: vdr.c:81
bool Save(void) const
Definition: config.h:167
cCiResourceHandlers CiResourceHandlers
Definition: ci.c:1738
int ZapTimeout
Definition: config.h:298
#define CHANNELMOD_TRANSP
Definition: channels.h:27
int DirectoryNameMax
Definition: recording.c:77
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.
Definition: skins.c:293
void ReportEpgBugFixStats(bool Force)
Definition: epg.c:611
virtual cOsdObject * MainMenuAction(void)
Definition: plugin.c:95
#define DEFAULTRESDIR
#define APIVERSION
Definition: config.h:30
static cDisplayVolume * Create(void)
Definition: menu.c:5017
void ProcessQueuedMessages(void)
Processes the first queued message, if any.
Definition: skins.c:349
Definition: plugin.h:20
Definition: keys.h:17
Definition: args.h:17
Definition: keys.h:61
#define MAXDEVICES
Definition: device.h:29
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition: thread.c:859
#define esyslog(a...)
Definition: tools.h:35
#define TIMERCHECKDELTA
Definition: vdr.c:86
cNestedItemList Commands
Definition: config.c:275
void SetUserInactive(void)
Set VDR manually into non-interactive mode from now on.
Definition: shutdown.h:86
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition: device.c:223
static cControl * Control(bool Hidden=false)
Returns the current replay control (if any) in case it is currently visible.
Definition: player.c:73
#define ISREALKEY(k)
Definition: keys.h:81
bool Save(void)
Definition: config.c:736
bool Load(const char *FileName=NULL, bool AllowComments=false, bool MustExist=false)
Definition: config.h:120
Definition: keys.h:49
static void Process(eKeys Key)
Definition: menu.c:5236
bool Update(void)
Update status display of the countdown.
Definition: shutdown.c:64
#define DEFAULTCACHEDIR
#define VDRVERSION
Definition: config.h:25
bool EmergencyExitRequested(void)
Returns true if an emergency exit was requested.
Definition: shutdown.h:61
static int NumDevices(void)
Returns the total number of devices.
Definition: device.h:127
bool DoShutdown(bool Force)
Call the shutdown script with data of the next pending timer.
Definition: shutdown.c:233
void Exit(int ExitCode)
Set VDR exit code and initiate end of VDR main loop.
Definition: shutdown.h:54
#define MINPRIORITY
Definition: config.h:40
bool InitializePlugins(void)
Definition: plugin.c:363
const char * Name(void)
Definition: skins.h:421
int MenuKeyCloses
Definition: config.h:266
bool IsMenu(void) const
Definition: osdbase.h:80
static bool OsdSizeChanged(int &State)
Checks if the OSD size has changed and a currently displayed OSD needs to be redrawn.
Definition: osd.c:2064
cRemotes Remotes
Definition: remote.c:211
#define NORMALKEY(k)
Definition: keys.h:79
#define LOCK_CHANNELS_WRITE
Definition: channels.h:268
void MainThreadHook(void)
Definition: plugin.c:406
static bool SetKeepCaps(bool On)
Definition: vdr.c:143
#define DEFAULTSVDRPPORT
static void SetEpgDataFileName(const char *FileName)
Definition: epg.c:1241
bool PresentSeenWithin(int Seconds) const
Definition: epg.h:166
void Reset(void)
Resets the state of this key, so that the next call to a lock&#39;s Lock() function with this key will re...
Definition: thread.c:854
void SetSyncStateKey(cStateKey &StateKey)
When making changes to this list (while holding a write lock) that shall not affect some other code t...
Definition: tools.h:562
static void SetCommand(const char *Command)
Definition: recording.h:431
#define MINCHANNELWAIT
Definition: vdr.c:75
void StopSVDRPHandler(void)
Definition: svdrp.c:2828
int SysLogLevel
Definition: tools.c:31
int GetMaxPriority(void) const
Returns the maximum priority of all local timers that are currently recording.
Definition: timers.c:820
cCountdown countdown
Definition: shutdown.h:51
Definition: keys.h:38
static bool IsOpen(void)
Definition: menu.h:172
cNestedItemList RecordingCommands
Definition: config.c:276
#define MAXVIDEOFILESIZEDEFAULT
Definition: recording.h:446
static bool Load(const char *FileName)
Definition: timers.c:735
static cTimers * GetTimersWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for write access.
Definition: timers.c:848
virtual void Clear(void)
Definition: tools.c:2229
static bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
Definition: channels.c:879
static cPositioner * GetPositioner(void)
Returns a previously created positioner.
Definition: positioner.c:133
static int CurrentVolume(void)
Definition: device.h:622
void Interrupt(void)
Definition: interface.h:24
Definition: keys.h:55
bool IsPrimaryDevice(void) const
Definition: device.h:213
Definition: keys.h:58
Definition: timers.h:27
#define CHANNELMOD_ALL
Definition: channels.h:21
#define TIMERLOOKAHEADTIME
Definition: vdr.c:88
virtual const char * Description(void)=0
bool DeleteExpired(void)
Definition: timers.c:890
#define SHUTDOWNWAIT
Definition: vdr.c:77
virtual const char * CommandLineHelp(void)
Definition: plugin.c:48
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition: device.c:1312
eOSState
Definition: osdbase.h:18
static void Destroy(void)
Definition: videodir.c:50
void Start(const char *Message, int Seconds)
Start the 5 minute shutdown warning countdown.
Definition: shutdown.c:37
bool Active(void)
Definition: eitscan.h:33
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
Definition: device.h:350
cSVDRPhosts SVDRPhosts
Definition: config.c:280
static bool PutMacro(eKeys Key)
Definition: remote.c:110
int InitialVolume
Definition: config.h:363
void Activity(void)
Definition: eitscan.c:118
Definition: keys.h:54
static bool BondDevices(const char *Bondings)
Bonds the devices as defined in the given Bondings string.
Definition: dvbdevice.c:1831
Definition: keys.h:40
Definition: osdbase.h:34
cAudios Audios
Definition: audio.c:27
cTheme * Theme(void)
Definition: skins.h:422
void SetVolume(int Volume, bool Absolute=false)
Sets the volume to the given value, either absolutely or relative to the current volume.
Definition: device.c:1010
int GetExitCode(void)
Get the currently set exit code of VDR.
Definition: shutdown.h:59
cStateKey StateKeySVDRPRemoteTimersPoll
Controls whether a change to the local list of timers needs to result in sending a POLL to the remote...
void StartSVDRPHandler(void)
Definition: svdrp.c:2812
Definition: keys.h:44
static char * OverrideCharacterTable
Definition: si.c:322
virtual void Clear(void)
Free up all registered skins.
Definition: skins.c:397
cListGarbageCollector ListGarbageCollector
Definition: tools.c:2088
bool SwitchChannel(const cChannel *Channel, bool LiveView)
Switches the device to the given Channel, initiating transfer mode if necessary.
Definition: device.c:785
#define LOCK_CHANNELS_READ
Definition: channels.h:267
Definition: keys.h:48
#define SHUTDOWNRETRY
Definition: vdr.c:78
char FontOsd[MAXFONTNAME]
Definition: config.h:328
#define DEFAULTPLUGINDIR
void RemoveDeletedRecordings(void)
Definition: recording.c:131
Definition: keys.h:54
bool DoExit(void)
Check if an exit code was set, and VDR should exit.
Definition: shutdown.h:57
cSources Sources
Definition: sources.c:117
bool ModifiedByUser(int &State) const
Returns true if the channels have been modified by the user since the last call to this function with...
Definition: channels.c:1106
void SetSVDRPGrabImageDir(const char *GrabImageDir)
Definition: svdrp.c:2730
int GetArgc(void) const
Definition: args.h:30
static void SetName(const char *Name)
Definition: videodir.c:65
const cKeyMacro * Get(eKeys Key)
Definition: keys.c:269
Definition: keys.h:18
bool StateChanged(void)
Returns true if this key is used for obtaining a write lock, and the lock&#39;s state differs from that o...
Definition: thread.c:869
void Process(void)
Definition: eitscan.c:128
cKeys Keys
Definition: keys.c:156
int RecordKeyHandling
Definition: config.h:303
void bool Start(void)
Sets the description of this thread, which will be used when logging starting or stopping of the thre...
Definition: thread.c:304
Definition: keys.h:50
static void UpdateOsdSize(bool Force=false)
Inquires the actual size of the video display and adjusts the OSD and font sizes accordingly.
Definition: osd.c:2037
char ** GetArgv(void) const
Definition: args.h:31
#define DEFAULTLOCDIR
cSourceParams SourceParams
Definition: sourceparams.c:34
#define ACTIVITYTIMEOUT
Definition: vdr.c:76
Definition: keys.h:52
bool Finished(bool &Error)
Returns true if all operations in the list have been finished.
Definition: recording.c:2066
static bool Process(cTimers *Timers, time_t t)
Definition: menu.c:5553
Definition: keys.h:28
Definition: skins.h:37
virtual bool HasProgramme(void) const
Returns true if the device is currently showing any programme to the user, either through replaying o...
Definition: device.c:950
bool GenerateIndex(const char *FileName, bool Update)
Generates the index of the existing recording with the given FileName.
Definition: recording.c:2847
static bool Active(void)
Definition: menu.c:5585
bool ConfirmShutdown(bool Ask)
Check for background activity that blocks shutdown.
Definition: shutdown.c:157
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
Definition: diseqc.c:441
cSetup Setup
Definition: config.c:372
int PauseKeyHandling
Definition: config.h:304
void Load(const char *FileName)
Definition: ci.c:2960
bool Put(uint64_t Code, bool Repeat=false, bool Release=false)
Definition: remote.c:124
Definition: keys.h:20
bool ReadDirectory(const char *Directory)
Definition: args.c:39
static void Cleanup(bool Force=false)
Definition: epg.c:1248
const T * Next(const T *Object) const
&lt; Returns the element immediately before Object in this list, or NULL if Object is the first element ...
Definition: tools.h:613
cShutdownHandler ShutdownHandler
Definition: shutdown.c:27
static int IsOpen(void)
Returns true if there is currently a level 0 OSD open.
Definition: osd.h:814
static const char * GetPlugin(void)
Returns the name of the plugin that was set with a previous call to PutMacro() or CallPlugin()...
Definition: remote.c:162
static void SetSystemCharacterTable(const char *CharacterTable)
Definition: tools.c:968
int SplitEditedFiles
Definition: config.h:338
static bool WaitForAllDevicesReady(int Timeout=0)
Waits until all devices have become ready, or the given Timeout (seconds) has expired.
Definition: device.c:126
static tThreadId ThreadId(void)
Definition: thread.c:372
int InstanceId
Definition: recording.c:79
static cDisplaySubtitleTracks * Create(void)
Definition: menu.c:5225
cRecordingsHandler RecordingsHandler
Definition: recording.c:1961
Definition: keys.h:45
#define MINVIDEOFILESIZE
Definition: recording.h:445
Definition: skins.h:402
#define DEVICEREADYTIMEOUT
Definition: vdr.c:84
bool IsOpen(void)
Returns true if there is currently a skin display object active.
Definition: skins.h:470
bool SwitchTo(int Number) const
Definition: channels.c:1070
static void Launch(cControl *Control)
Definition: player.c:79
virtual bool ProvidesTransponder(const cChannel *Channel) const
Returns true if this device can provide the transponder of the given Channel (which implies that it c...
Definition: device.c:721
static const char * LastReplayed(void)
Definition: menu.c:5747
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...
Definition: skins.c:250
virtual void Show(void)
Definition: osdbase.c:70
bool SetSystemCharacterTable(const char *CharacterTable)
Definition: si.c:330
int MaxVideoFileSize
Definition: config.h:337
#define DEFAULTWATCHDOG
cNestedItemList Folders
Definition: config.c:274
bool CamResponsesLoad(const char *FileName, bool AllowComments, bool MustExist)
Definition: ci.c:447
static bool useDvbDevices
Definition: dvbdevice.h:180
static bool HasPlugins(void)
Definition: plugin.c:452
static cDevice * GetDeviceForTransponder(const cChannel *Channel, int Priority)
Returns a device that is not currently &quot;occupied&quot; and can be tuned to the transponder of the given Ch...
Definition: device.c:415
int PrimaryDVB
Definition: config.h:261
virtual eOSState ProcessKey(eKeys Key)
Definition: osdbase.h:82
Definition: skins.h:37
int64_t StrToNum(const char *s)
Converts the given string to a number.
Definition: tools.c:357
int DirectoryPathMax
Definition: recording.c:76
int VpsMargin
Definition: config.h:308
void Housekeeping(void)
Definition: plugin.c:390
#define MEGABYTE(n)
Definition: tools.h:45
static void SetMainThreadId(void)
Definition: thread.c:377
#define DEFAULTEPGDATAFILENAME
bool WaitForAllCamSlotsReady(int Timeout=0)
Waits until all CAM slots have become ready, or the given Timeout (seconds) has expired.
Definition: ci.c:2767
#define CHANNELMOD_RETUNE
Definition: channels.h:29
static time_t LastActivity(void)
Absolute time when last key was delivered by Get().
Definition: remote.h:68
static void Attach(void)
Definition: player.c:87
static void Process(eKeys Key)
Definition: menu.c:5024
#define MANUALSTART
Definition: vdr.c:82
void DelAll(void)
Deletes/terminates all operations.
Definition: recording.c:2051
static void SetCacheDirectory(const char *Dir)
Definition: plugin.c:149
static void Process(eKeys Key)
Definition: menu.c:5118
static cString GetFontFileName(const char *FontName)
Returns the actual font file name for the given FontName.
Definition: font.c:479
bool CutRecording(const char *FileName)
Definition: cutter.c:726
eKeys GetKey(bool Wait=true)
Definition: interface.c:31
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...
Definition: recording.c:1514
static cDevice * PrimaryDevice(void)
Returns the primary device.
Definition: device.h:146
static bool IsOpen(void)
Definition: menu.h:190
bool Load(const char *FileName)
Definition: config.c:543
bool Active(void)
Checks whether the thread is still alive.
Definition: thread.c:329
static int LastSignal
Definition: vdr.c:94
Definition: epg.h:150
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...
Definition: shutdown.c:141
cKeyMacros KeyMacros
Definition: keys.c:267
Definition: timers.h:21
void AddPlugin(const char *Args)
Definition: plugin.c:318
static bool NeedsUpdate(void)
Definition: recording.c:1506
#define DELETE_MENU
static bool SetPrimaryDevice(int n)
Sets the primary device to &#39;n&#39;.
Definition: device.c:187
static cDisplayTracks * Create(void)
Definition: menu.c:5107
void StopReplay(void)
Stops the current replay session (if any).
Definition: device.c:1355
int Apid(int i) const
Definition: channels.h:160
#define tr(s)
Definition: i18n.h:85
cScrs Scrs
Definition: diseqc.c:182
cChannelCamRelations ChannelCamRelations
Definition: ci.c:2864
virtual bool NeedsFastResponse(void)
Definition: osdbase.h:79
bool Retry(time_t AtTime=0)
Check whether its time to re-try the shutdown.
Definition: shutdown.h:88
bool ConfirmRestart(bool Ask)
Check for background activity that blocks restart.
Definition: shutdown.c:209
static bool SetUser(const char *User, bool UserDump)
Definition: vdr.c:96
void SetDirectory(const char *Directory)
Definition: plugin.c:312
#define isyslog(a...)
Definition: tools.h:36
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel&#39;s transponder.
Definition: device.c:775
void AssertFreeDiskSpace(int Priority, bool Force)
The special Priority value -1 means that we shall get rid of any deleted recordings faster than norma...
Definition: recording.c:148
Definition: keys.h:42
static void SignalHandler(int signum)
Definition: vdr.c:153
static cPlugin * GetPlugin(int Index)
Definition: plugin.c:457
int CurrentVolume
Definition: config.h:359
static void Shutdown(void)
Closes down all devices.
Definition: device.c:446
Definition: keys.h:32
static cDevice * ActualDevice(void)
Returns the actual receiving device in case of Transfer Mode, or the primary device otherwise...
Definition: device.c:215
int main(int argc, char *argv[])
Definition: runvdr.c:550
Definition: keys.h:31
#define DEFAULTCONFDIR
Definition: keys.h:28
#define VPSUPTODATETIME
Definition: vdr.c:90
static cOsdObject * PluginOsdObject(void)
Definition: menu.c:4456
#define SHUTDOWNCANCELPROMPT
Definition: vdr.c:80
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
Definition: device.c:205
bool Load(const char *FileName)
Definition: config.c:234
bool StartPlugins(void)
Definition: plugin.c:376
static void MsgChannelChange(const cChannel *Channel)
Definition: status.c:26
Definition: osdbase.h:33
void Save(void)
Definition: ci.c:2994
bool SetEvents(const cSchedules *Schedules)
Definition: timers.c:882
#define EXIT(v)
Definition: vdr.c:92
static bool Start(cTimers *Timers, cTimer *Timer, bool Pause=false)
Definition: menu.c:5416
const T * First(void) const
Returns the first element in this list, or NULL if the list is empty.
Definition: tools.h:606
cInterface * Interface
Definition: interface.c:20
bool Load(const char *FileName, bool AllowComments=false, bool MustExist=false)
Definition: diseqc.c:184
void SetRetry(int Seconds)
Set shutdown retry so that VDR will not try to automatically shut down within Seconds.
Definition: shutdown.h:93
#define LOCK_SCHEDULES_READ
Definition: epg.h:224
char OSDTheme[MaxThemeName]
Definition: config.h:260
void SetShutdownCommand(const char *ShutdownCommand)
Set the command string for shutdown command.
Definition: shutdown.c:121
cString InitialChannel
Definition: config.h:368
#define MAXVIDEOFILESIZETS
Definition: recording.h:443
char OSDSkin[MaxSkinName]
Definition: config.h:259
#define LIVEPRIORITY
Definition: config.h:41
void StopPlugins(void)
Definition: plugin.c:500
static bool PauseLiveVideo(void)
Definition: menu.c:5505
cSkin * Current(void)
Returns a pointer to the current skin.
Definition: skins.h:468
Definition: keys.h:28
static const cTimers * GetTimersRead(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of timers for read access.
Definition: timers.c:843
static void SetResourceDirectory(const char *Dir)
Definition: plugin.c:163
Definition: keys.h:53
static bool IsOpen(void)
Definition: menu.h:143
bool SetCurrent(const char *Name=NULL)
Sets the current skin to the one indicated by name.
Definition: skins.c:231
static void Shutdown(void)
Definition: player.c:100
static void ChannelDataModified(const cChannel *Channel)
Definition: menu.c:5568
#define VOLUMEDELTA
Definition: device.h:33
#define DirectMainFunction(function)
eKeys
Definition: keys.h:16
void SetOverrideCharacterTable(const char *CharacterTable)
Definition: si.c:324
static void SetUseDevice(int n)
Sets the &#39;useDevice&#39; flag of the given device.
Definition: device.c:142
cCamSlots CamSlots
Definition: ci.c:2755
void I18nInitialize(const char *LocaleDir)
Detects all available locales and loads the language names and codes.
Definition: i18n.c:103
static void Shutdown(void)
Shuts down the OSD provider facility by deleting the current OSD provider.
Definition: osd.c:2124
Definition: keys.h:41
static void DestroyPositioner(void)
Destroys a previously created positioner.
Definition: positioner.c:138
void Cancel(void)
Cancel the 5 minute shutdown warning countdown.
Definition: shutdown.c:46
static void SetConfigDirectory(const char *Dir)
Definition: plugin.c:135
virtual void Hide(void)=0
bool Done(void)
Check if countdown timer has run out without canceling.
Definition: shutdown.c:55
#define DEFAULTARGSDIR
void LearnKeys(void)
Definition: interface.c:147
Definition: keys.h:22
cSkins Skins
Definition: skins.c:219
int DiSEqC
Definition: config.h:273