summaryrefslogtreecommitdiff
path: root/shutdown.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2007-02-25 18:00:00 +0100
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2007-02-25 18:00:00 +0100
commit9f42c33ef6793482a5c2515f9a87c13c0d189c60 (patch)
tree45025e95c0774761760c9bc6a44f4e69a1baf43b /shutdown.c
parent66ab78a40f5b57e20142a33484e32c785a0c4017 (diff)
downloadvdr-patch-lnbsharing-9f42c33ef6793482a5c2515f9a87c13c0d189c60.tar.gz
vdr-patch-lnbsharing-9f42c33ef6793482a5c2515f9a87c13c0d189c60.tar.bz2
Version 1.5.1vdr-1.5.1
- Added cDevice::HasCi() so that devices with Common Interface can be avoided when tuning to an FTA channel, thus preserving the CAM resources even on budget DVB cards (suggested by Petri Helin). - Fixed i18n characters for the Hungarian texts (thanks to Thomas Günther). - Now using cPipe instead of popen() in cCommand::Execute() to avoid problems with open file handles when starting background commands (thanks to Reinhard Nissl). - Removed 'assert(0)' from cDvbSpuDecoder::setTime() (thanks to Marco Schlüßler). - Fixed a possible crash when loading an invalid XPM file (thanks to Martin Wache). - Updated satellite names in 'sources.conf' (thanks to Thilo Wunderlich). - Adapted 'libsi' to DVB-S2 (thanks to Marco Schlüßler). - Fixed handling error status in cDvbTuner::GetFrontendStatus() (thanks to Reinhard Nissl). - Shutdown handling has been rewritten (thanks to Udo Richter). - Plugins can now implement the new function WakeupTime() to request VDR to wake up at a particular time (thanks to Udo Richter). - The HUP signal now forces a restart of VDR (thanks to Udo Richter). - cThread::EmergencyExit() has been replaced by ShutdownHandler.RequestEmergencyExit(). - Several references to "button" in a remote control context have been changed to "key" (based on a report from Marko Mäkelä regarding the "Menu button closes" text). The "MenuButtonCloses" parameter in 'setup.conf' has therefore been renamed to "MenuKeyCloses", accordingly. This will result in an "unknown config parameter: MenuButtonCloses" error message in the log file, so you may want to remove that entry from your 'setup.conf' file. - Simplified the error handling in cDvbTuner::GetFrontendStatus() (based on a discussion with Reinhard Nissl). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). - Increased the maximum number of DVB devices to 8 (thanks to Rolf Ahrenberg). - The new Setup parameter "Channel entry timeout" can be used to customize the time since the last keypress until a numerically entered channel number is considered complete, and the channel is switched (suggested by Helmut Auer). Setting this parameter to 0 turns off the automatic channel switching, and the user will have to confirm the entry by pressing the "Ok" key.
Diffstat (limited to 'shutdown.c')
-rw-r--r--shutdown.c250
1 files changed, 250 insertions, 0 deletions
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 <udo_richter@gmx.de>.
+ *
+ * $Id: shutdown.c 1.1 2007/02/24 17:24:11 kls Exp $
+ */
+
+#include "shutdown.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#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;
+}