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