Implemented automatic shutdown

This commit is contained in:
Klaus Schmidinger 2001-09-01 09:04:37 +02:00
parent a92b585c1e
commit a8f8de9dc9
10 changed files with 162 additions and 22 deletions

View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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);

View File

@ -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
View File

@ -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",

View File

@ -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 ");

View File

@ -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
View File

@ -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
View File

@ -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);