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