Parameter --manual-start/--timer-start (was: vdr shutdown handling / streamdev plugin)

Message ID 200612082021.07708.rollercoaster@reel-multimedia.com
State New
Headers

Commit Message

rollercoaster@reel-multimedia.com Dec. 8, 2006, 7:21 p.m. UTC
  Am Samstag, 2. Dezember 2006 16:24 schrieb Matthias Schwarzott:
> To manual start check I have another idea. Perhaps vdr can get a parameter
> for setting explicitly manual-start or start based on timer. Then the
> startskript could check the time that was written into nvram/acpi/wherever
> and tell vdr if start was manual or not.
>
> Matthias

The attached patch does what you suggest, but I don't see any correlation to 
the shutdown behaviour of plugins...

Tim
  

Comments

Marko Mäkelä Dec. 8, 2006, 9:45 p.m. UTC | #1
On Fri, Dec 08, 2006 at 08:21:07PM +0100, Thiemo Gehrke wrote:
> Am Samstag, 2. Dezember 2006 16:24 schrieb Matthias Schwarzott:
> > To manual start check I have another idea. Perhaps vdr can get a parameter
> > for setting explicitly manual-start or start based on timer. Then the
> > startskript could check the time that was written into nvram/acpi/wherever
> > and tell vdr if start was manual or not.
> >
> > Matthias
> 
> The attached patch does what you suggest, but I don't see any correlation to 
> the shutdown behaviour of plugins...

What about a third possibility: the computer is started by Wake-on-LAN
or Wake-on-Ring?  It is kind of manual startup, but there should not be
any output in that case.

I have written a patch for making the Power key suspend the output.
Some softdevice users have found it useful, but I've been told that
the patch does not stop playback on full-featured cards.  You can
access the patch here: http://www.iki.fi/~msmakela/software/vdr/#suspend

Quoting from there:

"The patch introduces three 'Setup/Miscellanous' menu items. The Booleans
'Power button suspends playback' and 'Playback suspended' should be
self-explanatory. The integer, 'Suspend to shutdown timeout (s)', is 0 by
default, meaning that no shutdown will be initiated when playback is
suspended by pressing the Power button. If you would like to use the
Power button as a smart power-off button that works in any context, set
this timeout to a suitable value, e.g., five seconds. Should you only
want to suspend playback and not power the system off, you can press
Power followed by OK. The latter button-press will confirm the 'Press any
key to cancel shutdown prompt' if one is presented. (If any timed
recordings are in progress, the prompt will be presented after they have
finished, unless the shutdown was cancelled by pressing any button.)"

I originally made the patch for vdr 1.3.32, and back then it was too late
to change the shutdown behaviour of 1.4.  I hope that the feature will make
it to 1.5 in some form.

	Marko
  
Udo Richter Dec. 9, 2006, 4:16 p.m. UTC | #2
Marko Mäkelä wrote:
> I have written a patch for making the Power key suspend the output.
> Some softdevice users have found it useful, but I've been told that
> the patch does not stop playback on full-featured cards.  You can
> access the patch here: http://www.iki.fi/~msmakela/software/vdr/#suspend
> 
> I originally made the patch for vdr 1.3.32, and back then it was too late
> to change the shutdown behaviour of 1.4.  I hope that the feature will make
> it to 1.5 in some form.

Since I've taken the job to re-design the shutdown stuff for 1.5.x, I 
probably have to take a look into this too.

I'm not sure whether this will be a core feature of VDR, but maybe we 
can add the needed interfaces so this can be done with a plugin.

I'm not yet sure how exactly the new shutdown code will look like, but 
I'm quite sure there will be a way to detect whether VDR is currently 
interactive (some user is watching) or not (unattended start, timer 
recording, no activity for x hours, power button pressed but not 
confirmed). Based on that, a plugin could probably take over the output 
device and suspend it or show a still. Or softdevice itself could react 
on this.

Cheers,

Udo
  
Marko Mäkelä Dec. 9, 2006, 5:59 p.m. UTC | #3
On Sat, Dec 09, 2006 at 05:16:22PM +0100, Udo Richter wrote:
> Marko Mäkelä wrote:
> >I have written a patch for making the Power key suspend the output.
> >Some softdevice users have found it useful, but I've been told that
> >the patch does not stop playback on full-featured cards.  You can
> >access the patch here: http://www.iki.fi/~msmakela/software/vdr/#suspend
> >
> >I originally made the patch for vdr 1.3.32, and back then it was too late
> >to change the shutdown behaviour of 1.4.  I hope that the feature will make
> >it to 1.5 in some form.
> 
> Since I've taken the job to re-design the shutdown stuff for 1.5.x, I 
> probably have to take a look into this too.

Thank you, I really appreciate that!

> I'm not sure whether this will be a core feature of VDR, but maybe we 
> can add the needed interfaces so this can be done with a plugin.

At the very least, the plugins should be able to receive suspend and
resume events.  I think it would be useful to expose the interface for
generating suspend and resume events as well.

> I'm not yet sure how exactly the new shutdown code will look like, but 
> I'm quite sure there will be a way to detect whether VDR is currently 
> interactive (some user is watching) or not (unattended start, timer 
> recording, no activity for x hours, power button pressed but not 
> confirmed). Based on that, a plugin could probably take over the output 
> device and suspend it or show a still. Or softdevice itself could react 
> on this.

If the suspend and resume events were to be processed in softdevice, then
also the subtitles plugin would have to process the events.  Otherwise,
the subtitles would keep running on the OSD even though video and audio are
suspended.

Regards,

	Marko
  
Udo Richter Dec. 10, 2006, 4 p.m. UTC | #4
Marko Mäkelä wrote:
> At the very least, the plugins should be able to receive suspend and
> resume events.  I think it would be useful to expose the interface for
> generating suspend and resume events as well.

Adding support for a suspended device state is not really part of the 
shutdown, so you'll have to convince Klaus on that. Plus, if you just 
want to disable the video decoder, you can feed it with a dummy signal 
and don't need a special suspended state. It works for streamdev at least.

>> confirmed). Based on that, a plugin could probably take over the output 
>> device and suspend it or show a still. Or softdevice itself could react 
>> on this.
> 
> If the suspend and resume events were to be processed in softdevice, then
> also the subtitles plugin would have to process the events.  Otherwise,
> the subtitles would keep running on the OSD even though video and audio are
> suspended.

If Softdevice knows that there is no current user, then it is free to 
also ignore subtitles together with the video signal. I don't see a 
problem here.

Cheers,

Udo
  
Darren Salt Dec. 10, 2006, 5:39 p.m. UTC | #5
I demand that Udo Richter may or may not have written...

[snip]
> I'm not yet sure how exactly the new shutdown code will look like, but I'm
> quite sure there will be a way to detect whether VDR is currently
> interactive (some user is watching) or not (unattended start, timer
> recording, no activity for x hours, power button pressed but not
> confirmed). Based on that, a plugin could probably take over the output
> device and suspend it or show a still. Or softdevice itself could react on
> this.

It also needs to cope with being shut down by a signal without any
possibility of user intervention. Two levels should be available: stop now,
and stop when inactive.

This helps init scripts when upgrading a packaged-for-$DISTRIBUTION version
of vdr since there's no guarantee that the upgrade won't be scheduled for
when nothing is being recorded.
  
Udo Richter Dec. 10, 2006, 6:33 p.m. UTC | #6
Darren Salt wrote:
> It also needs to cope with being shut down by a signal without any
> possibility of user intervention. Two levels should be available: stop now,
> and stop when inactive.
> 
> This helps init scripts when upgrading a packaged-for-$DISTRIBUTION version
> of vdr since there's no guarantee that the upgrade won't be scheduled for
> when nothing is being recorded.

you mean, a way to kill the VDR process only when there's no background 
activity? Why not just send a power key via SVDRP?

For the purpose of installing updates, I wouldn't like it if the update 
happens when I'm watching live TV either, so we're at the same point 
again: Shut down when no user is active and no background activity is 
going on. Could be done by abusing the existing shutdown script.

Another possibility would be to query the active/inactive state by SVDRP 
commands, either by VDR itself, or by a plugin.

Cheers,

Udo
  
Darren Salt Dec. 10, 2006, 7:28 p.m. UTC | #7
I demand that Udo Richter may or may not have written...

> Darren Salt wrote:
>> It also needs to cope with being shut down by a signal without any
>> possibility of user intervention. Two levels should be available: stop
>> now, and stop when inactive.

>> This helps init scripts when upgrading a packaged-for-$DISTRIBUTION
>> version of vdr since there's no guarantee that the upgrade won't be
>> scheduled for when nothing is being recorded.

> you mean, a way to kill the VDR process only when there's no background
> activity? Why not just send a power key via SVDRP?

That doesn't guarantee that vdr will exit promptly or as soon as it becomes
inactive. A different port may have been chosen, SVDRP may have been
disabled, or the suspend patch may be in use (and my vdr package has this
patch).

There's "restart on becoming inactive" too, but I think that the restart part
of that is best implemented in runvdr since it too may need to be restarted.

> For the purpose of installing updates, I wouldn't like it if the update
> happens when I'm watching live TV either, so we're at the same point again:
> Shut down when no user is active and no background activity is going on.
> Could be done by abusing the existing shutdown script.

Perhaps. You could have a look at my packaging:

http://zap.tartarus.org/~ds/debian/dists/unstable/main/source/vdr_1.4.4-1.ds.diff.gz

> Another possibility would be to query the active/inactive state by SVDRP
> commands, either by VDR itself, or by a plugin.

I still prefer kill(1) and kill(2) - no faffing around with sockets :-)
  

Patch

diff -Nur vdr-1.4.0-pl8/vdr.c vdr-1.4.0/vdr.c
--- vdr-1.4.0-pl8/vdr.c	2006-06-07 15:04:35.000000000 +0200
+++ vdr-1.4.0/vdr.c	2006-06-07 16:43:31.000000000 +0200
@@ -188,6 +188,8 @@ 
   int WatchdogTimeout = DEFAULTWATCHDOG;
   const char *Terminal = NULL;
   const char *Shutdown = NULL;
+  bool TimerWakeup = false; 
+  bool AutoShutdown = false;
 
   bool UseKbd = true;
   const char *LircDevice = NULL;
@@ -230,6 +232,7 @@ 
       { "record",   required_argument, NULL, 'r' },
       { "shutdown", required_argument, NULL, 's' },
       { "terminal", required_argument, NULL, 't' },
+      { "timerwakeup", no_argument,    NULL, 'T' },
       { "user",     required_argument, NULL, 'u' },
       { "version",  no_argument,       NULL, 'V' },
       { "vfat",     no_argument,       NULL, 'v' | 0x100 },
@@ -239,7 +242,7 @@ 
     };
 
   int c;
-  while ((c = getopt_long(argc, argv, "a:c:dD:E:g:hk:l:L:mp:P:r:s:t:u:v:Vw:", long_options, NULL)) != -1) {
+  while ((c = getopt_long(argc, argv, "a:c:dD:E:g:hk:l:L:mp:P:r:s:t:Tu:v:Vw:", long_options, NULL)) != -1) {
         switch (c) {
           case 'a': AudioCommand = optarg;
                     break;
@@ -330,6 +333,8 @@ 
           case 'u': if (*optarg)
                        VdrUser = optarg;
                     break;
+          case 'T': TimerWakeup = true;
+                    break;
           case 'V': DisplayVersion = true;
                     break;
           case 'v' | 0x100:
@@ -521,6 +526,7 @@ 
   int LastTimerChannel = -1;
   int PreviousChannel[2] = { 1, 1 };
   int PreviousChannelIndex = 0;
+  time_t vdrStartTime = time(NULL);
   time_t LastChannelChanged = time(NULL);
   time_t LastActivity = 0;
   time_t LastCamMenu = 0;
@@ -772,6 +778,14 @@ 
         if (time(NULL) - LastChannelChanged >= Setup.ZapTimeout && LastChannel != PreviousChannel[PreviousChannelIndex])
            PreviousChannel[PreviousChannelIndex ^= 1] = LastChannel;
         // Timers and Recordings:
+        if (TimerWakeup && Shutdown && time(NULL) - vdrStartTime > SHUTDOWNWAIT) { 
+           if (LastActivity == 0) {
+               LastActivity = 1;
+               AutoShutdown = true;
+           }
+           else if (LastActivity != 1)
+               AutoShutdown = false;
+           }
         if (!Timers.BeingEdited()) {
            // Assign events to timers:
            Timers.SetEvents();
@@ -1037,7 +1051,7 @@ 
                cTimer *timer = Timers.GetNextActiveTimer();
                time_t Next  = timer ? timer->StartTime() : 0;
                time_t Delta = timer ? Next - time(NULL) : 0;
-               if (Next && Delta <= Setup.MinEventTimeout * 60) {
+               if (Next && Delta <= Setup.MinEventTimeout * 60 && !AutoShutdown) {
                   char *buf;
                   asprintf(&buf, tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
                   bool confirm = Interface->Confirm(buf);
@@ -1167,7 +1181,7 @@ 
                  Skins.Message(mtInfo, tr("Editing process finished"));
               }
            }
-        if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && !cPluginManager::Active() && (!Interface->HasSVDRPConnection() || UserShutdown)) || ForceShutdown)) {
+        if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && !cPluginManager::Active() && (!Interface->HasSVDRPConnection() || UserShutdown || AutoShutdown)) || ForceShutdown)) {
            time_t Now = time(NULL);
            if (Now - LastActivity > ACTIVITYTIMEOUT) {
               // Shutdown:
@@ -1185,13 +1199,14 @@ 
                     else
                        LastActivity = 1;
                     }
-                 if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
+                 if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown || (AutoShutdown && Delta > Setup.MinEventTimeout * 60)) {
                     ForceShutdown = false;
+                    AutoShutdown = false;
                     if (timer)
                        dsyslog("next timer event at %s", *TimeToString(Next));
                     if (WatchdogTimeout > 0)
                        signal(SIGALRM, SIG_IGN);
-                    if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 5 : SHUTDOWNWAIT, true)) {
+                    if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 1 : SHUTDOWNWAIT, true)) {
                        cControl::Shutdown();
                        int Channel = timer ? timer->Channel()->Number() : 0;
                        const char *File = timer ? timer->File() : "";
@@ -1202,6 +1217,8 @@ 
                        isyslog("executing '%s'", cmd);
                        SystemExec(cmd);
                        free(cmd);
+                       //UserShutdownActive = true; //by kh
+                       Interrupted=1; // GA
                        LastActivity = time(NULL) - Setup.MinUserInactivity * 60 + SHUTDOWNRETRY; // try again later
                        }
                     else {