mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented automatic shutdown
This commit is contained in:
parent
a92b585c1e
commit
a8f8de9dc9
6
HISTORY
6
HISTORY
@ -676,3 +676,9 @@ Video Disk Recorder Revision History
|
||||
- Timers are now sorted in the "Timers" menu, showing the sequence in which
|
||||
they will be recording. This can be disabled in the "Setup" menu. Note
|
||||
that the "Mark" button doesn't work if timers are displayed sorted.
|
||||
|
||||
2001-09-01: Version 0.9.4
|
||||
|
||||
- Changed version number notation.
|
||||
- Implemented automatic shutdown (see INSTALL and MANUAL for details).
|
||||
|
||||
|
42
INSTALL
42
INSTALL
@ -98,6 +98,48 @@ call to the VDR program, be sure to NOT use the '-d' option! Otherwise
|
||||
VDR will go into 'deamon' mode and the initial program call will return
|
||||
immediately!
|
||||
|
||||
Automatic shutdown:
|
||||
-------------------
|
||||
|
||||
If you define a shutdown command via the '-s' command line option, VDR
|
||||
will call the given command if there is currently no recording or replay
|
||||
active, the user has been inactive for at least MinUserInactivity minutes
|
||||
and the next timer event is at least MinEventTimeout minutes in the future
|
||||
(see the Setup parameters in MANUAL).
|
||||
|
||||
The command given in the '-s' option will be called with two parameters.
|
||||
The first one is the time (in UTC) of the next timer event (as a time_t
|
||||
type number), and the second one is the number of seconds from the current
|
||||
time until the next timer event. Your program can choose which one to use
|
||||
for programming some sort of hardware device that makes sure the computer
|
||||
will be restarted in time before the next timer event. Your program must
|
||||
also initiate the actual shutdown procedure of the computer. After this
|
||||
your program should return to VDR. VDR will not automatically exit after
|
||||
calling the shutdown program, but will rather continue normally untit it
|
||||
receives a SIGTERM when the computer is actually shut down. So in case
|
||||
the shutdown fails, or the shutdown program for some reason decides not to
|
||||
perform a shutdown, VDR will stay up and running.
|
||||
|
||||
Before the shutdown program is called, the user will be prompted to inform
|
||||
him that the system is about to shut down. If any remote control key is
|
||||
pressed while this prompt is visible, the shutdown will be cancelled (and
|
||||
tried again after another MinUserInactivity minutes). The shutdown prompt
|
||||
will be displayed for 5 minutes, which should be enough time for the user
|
||||
to react.
|
||||
|
||||
A sample shell script to be used with the '-s' option might look like this:
|
||||
|
||||
#!/bin/sh
|
||||
setRTCwakeup $(($1 - 300))
|
||||
sudo halt
|
||||
|
||||
Here 'setRTCwakeup' would be some program that uses the first parameter
|
||||
(which is the absolute time of the next timer event) to set the Real Time
|
||||
Clock so that it wakes up the computer 5 minutes (i.e. 300 seconds) before
|
||||
that event. The 'sudo halt' command then shuts down the computer.
|
||||
You will have to substitute both commands with whatever applies to your
|
||||
particular hard- and software environment.
|
||||
|
||||
Command line options:
|
||||
---------------------
|
||||
|
||||
|
9
MANUAL
9
MANUAL
@ -417,6 +417,15 @@ Video Disk Recorder User's Manual
|
||||
you may want to use smaller values if you are planning
|
||||
on archiving a recording to CD.
|
||||
|
||||
MinEventTimeout=120 If the command line option '-s' has been set, VDR will
|
||||
MinUserInactivity=120 automatically shutdown the computer if the next timer
|
||||
event is at least MinEventTimeout minutes in the future,
|
||||
and the user has been inactive for at least
|
||||
MinUserInactivity minutes. Setting MinUserInactivity
|
||||
to 0 disables the automatic shutdown, while still
|
||||
retaining the possibility to manually shutdown the
|
||||
computer.
|
||||
|
||||
* Executing system commands
|
||||
|
||||
The "Main" menu option "Commands" allows you to execute any system commands
|
||||
|
8
config.c
8
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.59 2001/08/26 14:46:43 kls Exp $
|
||||
* $Id: config.c 1.60 2001/08/31 13:46:26 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -820,6 +820,8 @@ cSetup::cSetup(void)
|
||||
OSDwidth = 52;
|
||||
OSDheight = 18;
|
||||
MaxVideoFileSize = MAXVIDEOFILESIZE;
|
||||
MinEventTimeout = 120;
|
||||
MinUserInactivity = 120;
|
||||
CurrentChannel = -1;
|
||||
}
|
||||
|
||||
@ -853,6 +855,8 @@ bool cSetup::Parse(char *s)
|
||||
else if (!strcasecmp(Name, "OSDwidth")) OSDwidth = atoi(Value);
|
||||
else if (!strcasecmp(Name, "OSDheight")) OSDheight = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
|
||||
else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value);
|
||||
else
|
||||
return false;
|
||||
@ -921,6 +925,8 @@ bool cSetup::Save(const char *FileName)
|
||||
fprintf(f, "OSDwidth = %d\n", OSDwidth);
|
||||
fprintf(f, "OSDheight = %d\n", OSDheight);
|
||||
fprintf(f, "MaxVideoFileSize = %d\n", MaxVideoFileSize);
|
||||
fprintf(f, "MinEventTimeout = %d\n", MinEventTimeout);
|
||||
fprintf(f, "MinUserInactivity = %d\n", MinUserInactivity);
|
||||
fprintf(f, "CurrentChannel = %d\n", CurrentChannel);
|
||||
f.Close();
|
||||
isyslog(LOG_INFO, "saved setup to %s", FileName);
|
||||
|
5
config.h
5
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.66 2001/08/26 14:46:53 kls Exp $
|
||||
* $Id: config.h 1.67 2001/09/01 07:15:26 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,7 +19,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "0.93"
|
||||
#define VDRVERSION "0.9.4"
|
||||
|
||||
#define MaxBuffer 10000
|
||||
|
||||
@ -295,6 +295,7 @@ public:
|
||||
int ChannelInfoPos;
|
||||
int OSDwidth, OSDheight;
|
||||
int MaxVideoFileSize;
|
||||
int MinEventTimeout, MinUserInactivity;
|
||||
int CurrentChannel;
|
||||
cSetup(void);
|
||||
bool Load(const char *FileName);
|
||||
|
29
i18n.c
29
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.35 2001/08/26 13:45:10 kls Exp $
|
||||
* $Id: i18n.c 1.36 2001/08/31 15:37:05 kls Exp $
|
||||
*
|
||||
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
|
||||
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
|
||||
@ -385,6 +385,15 @@ const tPhrase Phrases[] = {
|
||||
"Annuler les modifications?",
|
||||
"Avbryte redigering",
|
||||
},
|
||||
{ "Press any key to cancel shutdown",
|
||||
"Taste drücken um Shutdown abzubrechen",
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
},
|
||||
// Channel parameters:
|
||||
{ "Name",
|
||||
"Name",
|
||||
@ -875,6 +884,24 @@ const tPhrase Phrases[] = {
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
},
|
||||
{ "MinEventTimeout",
|
||||
"Mindest Event Pause",
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
},
|
||||
{ "MinUserInactivity",
|
||||
"Mindest User Inaktivität",
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
},
|
||||
// The days of the week:
|
||||
{ "MTWTFSS",
|
||||
"MDMDFSS",
|
||||
|
11
interface.c
11
interface.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.c 1.41 2001/08/25 13:15:00 kls Exp $
|
||||
* $Id: interface.c 1.42 2001/09/01 07:30:37 kls Exp $
|
||||
*/
|
||||
|
||||
#include "interface.h"
|
||||
@ -20,6 +20,7 @@ cInterface::cInterface(int SVDRPport)
|
||||
cols[0] = 0;
|
||||
width = height = 0;
|
||||
keyFromWait = kNone;
|
||||
interrupted = false;
|
||||
rcIo = NULL;
|
||||
SVDRP = NULL;
|
||||
#if defined(REMOTE_RCU)
|
||||
@ -110,11 +111,12 @@ eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
time_t timeout = time(NULL) + Seconds;
|
||||
for (;;) {
|
||||
Key = GetKey();
|
||||
if ((Key != kNone && (RAWKEY(Key) != kOk || RAWKEY(Key) == Key)) || time(NULL) > timeout)
|
||||
if ((Key != kNone && (RAWKEY(Key) != kOk || RAWKEY(Key) == Key)) || time(NULL) > timeout || interrupted)
|
||||
break;
|
||||
}
|
||||
if (KeepChar && ISRAWKEY(Key))
|
||||
keyFromWait = Key;
|
||||
interrupted = false;
|
||||
return Key;
|
||||
}
|
||||
|
||||
@ -312,12 +314,13 @@ void cInterface::Error(const char *s)
|
||||
Close();
|
||||
}
|
||||
|
||||
bool cInterface::Confirm(const char *s)
|
||||
bool cInterface::Confirm(const char *s, int Seconds, bool WaitForTimeout)
|
||||
{
|
||||
Open();
|
||||
isyslog(LOG_INFO, "confirm: %s", s);
|
||||
Status(s, clrBlack, clrYellow);
|
||||
bool result = Wait(10) == kOk;
|
||||
eKeys k = Wait(Seconds);
|
||||
bool result = WaitForTimeout ? k == kNone : k == kOk;
|
||||
Status(NULL);
|
||||
Close();
|
||||
isyslog(LOG_INFO, "%sconfirmed", result ? "" : "not ");
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.22 2001/07/27 11:38:01 kls Exp $
|
||||
* $Id: interface.h 1.23 2001/09/01 07:29:24 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
@ -23,6 +23,7 @@ private:
|
||||
int open;
|
||||
int cols[MaxCols];
|
||||
eKeys keyFromWait;
|
||||
bool interrupted;
|
||||
cSVDRP *SVDRP;
|
||||
cRcIoBase *rcIo;
|
||||
unsigned int GetCh(bool Wait = true, bool *Repeat = NULL, bool *Release = NULL);
|
||||
@ -34,6 +35,7 @@ public:
|
||||
~cInterface();
|
||||
void Open(int NumCols = 0, int NumLines = 0);
|
||||
void Close(void);
|
||||
void Interrupt(void) { interrupted = true; }
|
||||
int Width(void) { return width; }
|
||||
int Height(void) { return height; }
|
||||
eKeys GetKey(bool Wait = true);
|
||||
@ -52,7 +54,7 @@ public:
|
||||
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
||||
void Info(const char *s);
|
||||
void Error(const char *s);
|
||||
bool Confirm(const char *s);
|
||||
bool Confirm(const char *s, int Seconds = 10, bool WaitForTimeout = false);
|
||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
void LearnKeys(void);
|
||||
void DisplayChannelNumber(int Number);
|
||||
|
4
menu.c
4
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.109 2001/08/26 14:03:27 kls Exp $
|
||||
* $Id: menu.c 1.110 2001/08/31 13:47:28 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -1731,6 +1731,8 @@ void cMenuSetup::Set(void)
|
||||
Add(new cMenuEditIntItem( tr("OSDwidth"), &data.OSDwidth, MINOSDWIDTH, MAXOSDWIDTH));
|
||||
Add(new cMenuEditIntItem( tr("OSDheight"), &data.OSDheight, MINOSDHEIGHT, MAXOSDHEIGHT));
|
||||
Add(new cMenuEditIntItem( tr("MaxVideoFileSize"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZE));
|
||||
Add(new cMenuEditIntItem( tr("MinEventTimeout"), &data.MinEventTimeout));
|
||||
Add(new cMenuEditIntItem( tr("MinUserInactivity"), &data.MinUserInactivity));
|
||||
}
|
||||
|
||||
eOSState cMenuSetup::ProcessKey(eKeys Key)
|
||||
|
64
vdr.c
64
vdr.c
@ -22,9 +22,10 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.64 2001/08/26 15:02:00 kls Exp $
|
||||
* $Id: vdr.c 1.65 2001/09/01 08:57:11 kls Exp $
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
@ -48,13 +49,16 @@
|
||||
#endif
|
||||
|
||||
#define ACTIVITYTIMEOUT 60 // seconds before starting housekeeping
|
||||
#define SHUTDOWNWAIT 300 // seconds to wait in user prompt before automatic shutdown
|
||||
|
||||
static int Interrupted = 0;
|
||||
|
||||
static void SignalHandler(int signum)
|
||||
{
|
||||
if (signum != SIGPIPE)
|
||||
if (signum != SIGPIPE) {
|
||||
Interrupted = signum;
|
||||
Interface->Interrupt();
|
||||
}
|
||||
signal(signum, SignalHandler);
|
||||
}
|
||||
|
||||
@ -77,7 +81,8 @@ int main(int argc, char *argv[])
|
||||
const char *ConfigDirectory = NULL;
|
||||
bool DaemonMode = false;
|
||||
int WatchdogTimeout = DEFAULTWATCHDOG;
|
||||
char *Terminal = NULL;
|
||||
const char *Terminal = NULL;
|
||||
const char *Shutdown = NULL;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "audio", required_argument, NULL, 'a' },
|
||||
@ -88,16 +93,17 @@ int main(int argc, char *argv[])
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "log", required_argument, NULL, 'l' },
|
||||
{ "port", required_argument, NULL, 'p' },
|
||||
{ "shutdown", required_argument, NULL, 's' },
|
||||
{ "terminal", required_argument, NULL, 't' },
|
||||
{ "video", required_argument, NULL, 'v' },
|
||||
{ "dvd", required_argument, NULL, 'V' },
|
||||
{ "watchdog", required_argument, NULL, 'w' },
|
||||
{ "terminal", required_argument, NULL, 't' },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
int c;
|
||||
int option_index = 0;
|
||||
while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:p:t:v:V:w:", long_options, &option_index)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:p:s:t:v:V:w:", long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'a': cDvbApi::SetAudioCommand(optarg);
|
||||
break;
|
||||
@ -134,6 +140,7 @@ int main(int argc, char *argv[])
|
||||
" 2 = errors and info, 3 = errors, info and debug\n"
|
||||
" -p PORT, --port=PORT use PORT for SVDRP (default: %d)\n"
|
||||
" 0 turns off SVDRP\n"
|
||||
" -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
|
||||
" -t TTY, --terminal=TTY controlling tty\n"
|
||||
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
|
||||
" -V DEV, --dvd=DEV use DEV as the DVD device (default: %s)\n"
|
||||
@ -170,6 +177,8 @@ int main(int argc, char *argv[])
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 's': Shutdown = optarg;
|
||||
break;
|
||||
case 't': Terminal = optarg;
|
||||
break;
|
||||
case 'v': VideoDirectory = optarg;
|
||||
@ -292,7 +301,7 @@ int main(int argc, char *argv[])
|
||||
cReplayControl *ReplayControl = NULL;
|
||||
int LastChannel = -1;
|
||||
int PreviousChannel = cDvbApi::CurrentChannel();
|
||||
time_t LastActivity = time(NULL);
|
||||
time_t LastActivity = 0;
|
||||
int MaxLatencyTime = 0;
|
||||
|
||||
if (WatchdogTimeout > 0) {
|
||||
@ -333,8 +342,10 @@ int main(int argc, char *argv[])
|
||||
// User Input:
|
||||
cOsdBase **Interact = Menu ? &Menu : (cOsdBase **)&ReplayControl;
|
||||
eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
|
||||
if (NORMALKEY(key) != kNone)
|
||||
if (NORMALKEY(key) != kNone) {
|
||||
EITScanner.Activity();
|
||||
LastActivity = time(NULL);
|
||||
}
|
||||
if (*Interact) {
|
||||
switch ((*Interact)->ProcessKey(key)) {
|
||||
case osMenu: DELETENULL(Menu);
|
||||
@ -424,13 +435,44 @@ int main(int argc, char *argv[])
|
||||
cVideoCutter::Active();
|
||||
}
|
||||
if (!*Interact && !cRecordControls::Active()) {
|
||||
if (time(NULL) - LastActivity > ACTIVITYTIMEOUT) {
|
||||
time_t Now = time(NULL);
|
||||
if (Now - LastActivity > ACTIVITYTIMEOUT) {
|
||||
// Shutdown:
|
||||
if (Shutdown && Setup.MinUserInactivity && Now - LastActivity > Setup.MinUserInactivity * 60) {
|
||||
cTimer *timer = Timers.GetNextActiveTimer();
|
||||
if (timer) {
|
||||
time_t Next = timer->StartTime();
|
||||
time_t Delta = Next - Now;
|
||||
dsyslog(LOG_INFO, "next timer event at %s", ctime(&Next));
|
||||
if (Delta > Setup.MinEventTimeout * 60) {
|
||||
if (!LastActivity) {
|
||||
// Apparently the user started VDR manually
|
||||
dsyslog(LOG_INFO, "assuming manual start of VDR");
|
||||
LastActivity = Now;
|
||||
continue;
|
||||
}
|
||||
if (WatchdogTimeout > 0)
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
if (Interface->Confirm(tr("Press any key to cancel shutdown"), SHUTDOWNWAIT, true)) {
|
||||
char *cmd;
|
||||
asprintf(&cmd, "%s %ld %ld", Shutdown, Next, Delta);
|
||||
isyslog(LOG_INFO, "executing '%s'", cmd);
|
||||
system(cmd);
|
||||
delete cmd;
|
||||
}
|
||||
else if (WatchdogTimeout > 0) {
|
||||
alarm(WatchdogTimeout);
|
||||
if (signal(SIGALRM, Watchdog) == SIG_IGN)
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
}
|
||||
LastActivity = Now; // don't try again too soon
|
||||
}
|
||||
}
|
||||
}
|
||||
// Disk housekeeping:
|
||||
RemoveDeletedRecordings();
|
||||
LastActivity = time(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
LastActivity = time(NULL);
|
||||
}
|
||||
if (Interrupted)
|
||||
isyslog(LOG_INFO, "caught signal %d", Interrupted);
|
||||
|
Loading…
Reference in New Issue
Block a user