From 9f42c33ef6793482a5c2515f9a87c13c0d189c60 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 25 Feb 2007 18:00:00 +0100 Subject: =?UTF-8?q?Version=201.5.1=20-=20Added=20cDevice::HasCi()=20so=20t?= =?UTF-8?q?hat=20devices=20with=20Common=20Interface=20can=20be=20avoided?= =?UTF-8?q?=20=20=20when=20tuning=20to=20an=20FTA=20channel,=20thus=20pres?= =?UTF-8?q?erving=20the=20CAM=20resources=20even=20on=20budget=20=20=20DVB?= =?UTF-8?q?=20cards=20(suggested=20by=20Petri=20Helin).=20-=20Fixed=20i18n?= =?UTF-8?q?=20characters=20for=20the=20Hungarian=20texts=20(thanks=20to=20?= =?UTF-8?q?Thomas=20G=C3=BCnther).=20-=20Now=20using=20cPipe=20instead=20o?= =?UTF-8?q?f=20popen()=20in=20cCommand::Execute()=20to=20avoid=20problems?= =?UTF-8?q?=20=20=20with=20open=20file=20handles=20when=20starting=20backg?= =?UTF-8?q?round=20commands=20(thanks=20to=20Reinhard=20=20=20Nissl).=20-?= =?UTF-8?q?=20Removed=20'assert(0)'=20from=20cDvbSpuDecoder::setTime()=20(?= =?UTF-8?q?thanks=20to=20Marco=20Schl=C3=BC=C3=9Fler).=20-=20Fixed=20a=20p?= =?UTF-8?q?ossible=20crash=20when=20loading=20an=20invalid=20XPM=20file=20?= =?UTF-8?q?(thanks=20to=20Martin=20Wache).=20-=20Updated=20satellite=20nam?= =?UTF-8?q?es=20in=20'sources.conf'=20(thanks=20to=20Thilo=20Wunderlich).?= =?UTF-8?q?=20-=20Adapted=20'libsi'=20to=20DVB-S2=20(thanks=20to=20Marco?= =?UTF-8?q?=20Schl=C3=BC=C3=9Fler).=20-=20Fixed=20handling=20error=20statu?= =?UTF-8?q?s=20in=20cDvbTuner::GetFrontendStatus()=20(thanks=20to=20=20=20?= =?UTF-8?q?Reinhard=20Nissl).=20-=20Shutdown=20handling=20has=20been=20rew?= =?UTF-8?q?ritten=20(thanks=20to=20Udo=20Richter).=20-=20Plugins=20can=20n?= =?UTF-8?q?ow=20implement=20the=20new=20function=20WakeupTime()=20to=20req?= =?UTF-8?q?uest=20VDR=20to=20wake=20=20=20up=20at=20a=20particular=20time?= =?UTF-8?q?=20(thanks=20to=20Udo=20Richter).=20-=20The=20HUP=20signal=20no?= =?UTF-8?q?w=20forces=20a=20restart=20of=20VDR=20(thanks=20to=20Udo=20Rich?= =?UTF-8?q?ter).=20-=20cThread::EmergencyExit()=20has=20been=20replaced=20?= =?UTF-8?q?by=20ShutdownHandler.RequestEmergencyExit().=20-=20Several=20re?= =?UTF-8?q?ferences=20to=20"button"=20in=20a=20remote=20control=20context?= =?UTF-8?q?=20have=20been=20changed=20=20=20to=20"key"=20(based=20on=20a?= =?UTF-8?q?=20report=20from=20Marko=20M=C3=A4kel=C3=A4=20regarding=20the?= =?UTF-8?q?=20"Menu=20button=20closes"=20=20=20text).=20The=20"MenuButtonC?= =?UTF-8?q?loses"=20parameter=20in=20'setup.conf'=20has=20therefore=20been?= =?UTF-8?q?=20=20=20renamed=20to=20"MenuKeyCloses",=20accordingly.=20This?= =?UTF-8?q?=20will=20result=20in=20an=20"unknown=20config=20=20=20paramete?= =?UTF-8?q?r:=20MenuButtonCloses"=20error=20message=20in=20the=20log=20fil?= =?UTF-8?q?e,=20so=20you=20may=20want=20to=20=20=20remove=20that=20entry?= =?UTF-8?q?=20from=20your=20'setup.conf'=20file.=20-=20Simplified=20the=20?= =?UTF-8?q?error=20handling=20in=20cDvbTuner::GetFrontendStatus()=20(based?= =?UTF-8?q?=20on=20a=20=20=20discussion=20with=20Reinhard=20Nissl).=20-=20?= =?UTF-8?q?Updated=20the=20Finnish=20OSD=20texts=20(thanks=20to=20Rolf=20A?= =?UTF-8?q?hrenberg).=20-=20Increased=20the=20maximum=20number=20of=20DVB?= =?UTF-8?q?=20devices=20to=208=20(thanks=20to=20Rolf=20Ahrenberg).=20-=20T?= =?UTF-8?q?he=20new=20Setup=20parameter=20"Channel=20entry=20timeout"=20ca?= =?UTF-8?q?n=20be=20used=20to=20customize=20the=20time=20=20=20since=20the?= =?UTF-8?q?=20last=20keypress=20until=20a=20numerically=20entered=20channe?= =?UTF-8?q?l=20number=20is=20considered=20=20=20complete,=20and=20the=20ch?= =?UTF-8?q?annel=20is=20switched=20(suggested=20by=20Helmut=20Auer).=20Set?= =?UTF-8?q?ting=20this=20=20=20parameter=20to=200=20turns=20off=20the=20au?= =?UTF-8?q?tomatic=20channel=20switching,=20and=20the=20user=20will=20=20?= =?UTF-8?q?=20have=20to=20confirm=20the=20entry=20by=20pressing=20the=20"O?= =?UTF-8?q?k"=20key.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shutdown.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 shutdown.c (limited to 'shutdown.c') diff --git a/shutdown.c b/shutdown.c new file mode 100644 index 0000000..4029a78 --- /dev/null +++ b/shutdown.c @@ -0,0 +1,250 @@ +/* + * shutdown.c: Handling of shutdown and inactivity + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * Original version written by Udo Richter . + * + * $Id: shutdown.c 1.1 2007/02/24 17:24:11 kls Exp $ + */ + +#include "shutdown.h" +#include +#include +#include +#include +#include "channels.h" +#include "config.h" +#include "cutter.h" +#include "i18n.h" +#include "interface.h" +#include "menu.h" +#include "plugin.h" +#include "timers.h" +#include "tools.h" + +cShutdownHandler ShutdownHandler; + +cCountdown::cCountdown(void) +{ + timeout = 0; + counter = 0; + timedOut = false; + message = NULL; +} + +void cCountdown::Start(const char *Message, int Seconds) +{ + timeout = time(NULL) + Seconds; + counter = -1; + timedOut = false; + message = Message; + Update(); +} + +void cCountdown::Cancel(void) +{ + if (timeout) { + timeout = 0; + timedOut = false; + Skins.Message(mtStatus, NULL); + } +} + +bool cCountdown::Done(void) +{ + if (timedOut) { + Cancel(); + return true; + } + return false; +} + +bool cCountdown::Update(void) +{ + if (timeout) { + int NewCounter = (timeout - time(NULL) + 9) / 10; + if (NewCounter <= 0) + timedOut = true; + if (counter != NewCounter) { + counter = NewCounter; + char time[10]; + snprintf(time, sizeof(time), "%d:%d0", counter > 0 ? counter / 6 : 0, counter > 0 ? counter % 6 : 0); + cString Message = cString::sprintf(message, time); + Skins.Message(mtStatus, Message); + return true; + } + } + return false; +} + +cShutdownHandler::cShutdownHandler(void) +{ + activeTimeout = 0; + retry = 0; + shutdownCommand = NULL; + exitCode = -1; + emergencyExitRequested = false; +} + +cShutdownHandler::~cShutdownHandler() +{ + free(shutdownCommand); +} + +void cShutdownHandler::RequestEmergencyExit(void) +{ + esyslog("initiating emergency exit"); + emergencyExitRequested = true; + Exit(1); +} + +void cShutdownHandler::CheckManualStart(int ManualStart) +{ + time_t Delta = Setup.NextWakeupTime ? Setup.NextWakeupTime - time(NULL) : 0; + + if (!Setup.NextWakeupTime || abs(Delta) > ManualStart) { + // Apparently the user started VDR manually + dsyslog("assuming manual start of VDR"); + // Set inactive after MinUserInactivity + SetUserInactiveTimeout(); + } + else + // Set inactive from now on + SetUserInactive(); +} + +void cShutdownHandler::SetShutdownCommand(const char *ShutdownCommand) +{ + free(shutdownCommand); + shutdownCommand = ShutdownCommand ? strdup(ShutdownCommand) : NULL; +} + +void cShutdownHandler::CallShutdownCommand(time_t WakeupTime, int Channel, const char *File, bool UserShutdown) +{ + time_t Delta = WakeupTime ? WakeupTime - time(NULL) : 0; + cString cmd = cString::sprintf("%s %ld %ld %d \"%s\" %d", shutdownCommand, WakeupTime, Delta, Channel, *strescape(File, "\"$"), UserShutdown); + isyslog("executing '%s'", *cmd); + if (SystemExec(cmd, true) == 0) + Setup.NextWakeupTime = WakeupTime; // Remember this wakeup time for comparison on reboot +} + +void cShutdownHandler::SetUserInactiveTimeout(int Seconds, bool Force) +{ + if (!Setup.MinUserInactivity && !Force) { + activeTimeout = 0; + return; + } + if (Seconds < 0) + Seconds = Setup.MinUserInactivity * 60; + activeTimeout = time(NULL) + Seconds; +} + +bool cShutdownHandler::ConfirmShutdown(bool Interactive) +{ + if (!shutdownCommand) { + if (Interactive) + Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!")); + return false; + } + if (cCutter::Active()) { + if (!Interactive || !Interface->Confirm(tr("Editing - shut down anyway?"))) + return false; + } + + cTimer *timer = Timers.GetNextActiveTimer(); + time_t Next = timer ? timer->StartTime() : 0; + time_t Delta = timer ? Next - time(NULL) : 0; + + if (cRecordControls::Active() || (Next && Delta <= 0)) { + // VPS recordings in timer end margin may cause Delta <= 0 + if (!Interactive || !Interface->Confirm(tr("Recording - shut down anyway?"))) + return false; + } + else if (Next && Delta <= Setup.MinEventTimeout * 60) { + // Timer within Min Event Timeout + if (!Interactive) + return false; + cString buf = cString::sprintf(tr("Recording in %ld minutes, shut down anyway?"), Delta / 60); + if (!Interface->Confirm(buf)) + return false; + } + + if (cPluginManager::Active(Interactive ? tr("shut down anyway?") : NULL)) + return false; + + cPlugin *Plugin = cPluginManager::GetNextWakeupPlugin(); + Next = Plugin ? Plugin->WakeupTime() : 0; + Delta = Next ? Next - time(NULL) : 0; + if (Next && Delta <= Setup.MinEventTimeout * 60) { + // Plugin wakeup within Min Event Timeout + if (!Interactive) + return false; + cString buf = cString::sprintf(tr("Plugin %s wakes up in %ld min, continue?"), Plugin->Name(), Delta / 60); + if (!Interface->Confirm(buf)) + return false; + } + + return true; +} + +bool cShutdownHandler::ConfirmRestart(bool Interactive) +{ + if (cCutter::Active()) { + if (!Interactive || !Interface->Confirm(tr("Editing - restart anyway?"))) + return false; + } + + cTimer *timer = Timers.GetNextActiveTimer(); + time_t Next = timer ? timer->StartTime() : 0; + time_t Delta = timer ? Next - time(NULL) : 0; + + if (cRecordControls::Active() || (Next && Delta <= 0)) { + // VPS recordings in timer end margin may cause Delta <= 0 + if (!Interactive || !Interface->Confirm(tr("Recording - restart anyway?"))) + return false; + } + + if (cPluginManager::Active(Interactive ? tr("restart anyway?") : NULL)) + return false; + + return true; +} + +bool cShutdownHandler::DoShutdown(bool Force) +{ + time_t Now = time(NULL); + cTimer *timer = Timers.GetNextActiveTimer(); + cPlugin *Plugin = cPluginManager::GetNextWakeupPlugin(); + + time_t Next = timer ? timer->StartTime() : 0; + time_t NextPlugin = Plugin ? Plugin->WakeupTime() : 0; + if (NextPlugin && (!Next || Next > NextPlugin)) { + Next = NextPlugin; + timer = NULL; + } + time_t Delta = Next ? Next - Now : 0; + + if (Next && Delta < Setup.MinEventTimeout * 60) { + if (!Force) + return false; + Delta = Setup.MinEventTimeout * 60; + Next = Now + Delta; + timer = NULL; + dsyslog("reboot at %s", *TimeToString(Next)); + } + + if (Next && timer) { + dsyslog("next timer event at %s", *TimeToString(Next)); + CallShutdownCommand(Next, timer->Channel()->Number(), timer->File(), Force); + } + else if (Next && Plugin) { + CallShutdownCommand(Next, 0, Plugin->Name(), Force); + dsyslog("next plugin wakeup at %s", *TimeToString(Next)); + } + else + CallShutdownCommand(Next, 0, "", Force); // Next should always be 0 here. Just for safety, pass it. + + return true; +} -- cgit v1.2.3