mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
A device is now always kept occupied if a timer is in VPS margin or needs the transponder
This commit is contained in:
parent
51dca45a0c
commit
179d5b87fc
@ -2569,6 +2569,8 @@ Markus Ehrnsperger <markus.ehrnsperger@googlemail.com>
|
||||
a decoder
|
||||
for improving handling present/following data for VPS timers
|
||||
for making logging event status changes also show the previous status
|
||||
for making a device always being kept occupied if a timer is in VPS margin or needs the
|
||||
transponder
|
||||
|
||||
Werner Färber <w.faerber@gmx.de>
|
||||
for reporting a bug in handling the cPluginManager::Active() result when pressing
|
||||
|
4
HISTORY
4
HISTORY
@ -9887,7 +9887,7 @@ Video Disk Recorder Revision History
|
||||
- Fixed possible duplicate component entries in the info of an ongoing recording
|
||||
(reported by Christoph Haubrich).
|
||||
|
||||
2024-03-28:
|
||||
2024-03-29:
|
||||
|
||||
- Fixed the move assignment operator to check for self-assignment (suggested by
|
||||
Stefan Herdler).
|
||||
@ -9916,3 +9916,5 @@ Video Disk Recorder Revision History
|
||||
transponder.
|
||||
- If the current channel is no longer available because of a VPS timer entering the
|
||||
VPS margin, live view now switches to the channel of that timer.
|
||||
- A device is now always kept occupied if a timer is in VPS margin or needs the
|
||||
transponder (thanks to Markus Ehrnsperger).
|
||||
|
41
device.c
41
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 5.12 2024/03/28 13:02:42 kls Exp $
|
||||
* $Id: device.c 5.13 2024/03/29 21:46:50 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -95,7 +95,9 @@ cDevice::cDevice(void)
|
||||
|
||||
camSlot = NULL;
|
||||
|
||||
occupiedFrom = 0;
|
||||
occupiedTimeout = 0;
|
||||
occupiedPriority = MINPRIORITY;
|
||||
|
||||
player = NULL;
|
||||
isPlayingVideo = false;
|
||||
@ -285,7 +287,11 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
if (NumUsableSlots && !HasInternalCam && !CamSlots.Get(j)->Assign(device[i], true))
|
||||
continue; // CAM slot can't be used with this device
|
||||
bool ndr = false;
|
||||
if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
|
||||
bool TunedToTransponder = device[i]->IsTunedToTransponder(Channel);
|
||||
if (TunedToTransponder || device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
|
||||
bool OccupiedOtherTransponder = !TunedToTransponder && device[i]->Occupied();
|
||||
if (OccupiedOtherTransponder)
|
||||
ndr = true;
|
||||
if (NumUsableSlots && !HasInternalCam) {
|
||||
if (cCamSlot *csi = device[i]->CamSlot()) {
|
||||
cCamSlot *csj = CamSlots.Get(j);
|
||||
@ -303,7 +309,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
imp <<= 1; imp |= (LiveView && NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlots.Get(j)->MasterSlotNumber()) || ndr : 0; // prefer CAMs that are known to decrypt this channel for live viewing, if we don't need to detach existing receivers
|
||||
imp <<= 1; imp |= LiveView ? !device[i]->IsPrimaryDevice() || ndr : 0; // prefer the primary device for live viewing if we don't need to detach existing receivers
|
||||
imp <<= 1; imp |= !device[i]->Receiving() && (device[i] != cTransferControl::ReceiverDevice() || device[i]->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode
|
||||
imp <<= 1; imp |= device[i]->Receiving(); // avoid devices that are receiving
|
||||
imp <<= 1; imp |= device[i]->Receiving() || OccupiedOtherTransponder; // avoid devices that are receiving
|
||||
imp <<= 5; imp |= GetClippedNumProvidedSystems(5, device[i]) - 1; // avoid cards which support multiple delivery systems
|
||||
imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
|
||||
imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
|
||||
@ -321,6 +327,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
if (NumUsableSlots && !HasInternalCam)
|
||||
s = CamSlots.Get(j);
|
||||
}
|
||||
//dsyslog("device %d provides channel %d prio %d ndr %d imp %.8X", device[i]->DeviceNumber() + 1, Channel->Number(), Priority, ndr, imp);
|
||||
}
|
||||
}
|
||||
if (!NumUsableSlots)
|
||||
@ -427,7 +434,8 @@ cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
|
||||
if (d->ProvidesTransponder(Channel)) {
|
||||
if (d->MaySwitchTransponder(Channel))
|
||||
return d; // this device may switch to the transponder without disturbing any receiver or live view
|
||||
else if (!d->Occupied() && !d->IsBonded()) { // MaySwitchTransponder() implicitly calls Occupied()
|
||||
else if (!d->Occupied(Priority) && !d->IsBonded() && d->Priority(true) < LIVEPRIORITY) { // MaySwitchTransponder() implicitly calls Occupied()
|
||||
// we select only devices with priority < LIVEPRIORITY, so device can be switched without impact on recordings or live viewing
|
||||
if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority()))
|
||||
Device = d; // use this one only if no other with less impact can be found
|
||||
}
|
||||
@ -801,7 +809,7 @@ bool cDevice::IsTunedToTransponder(const cChannel *Channel) const
|
||||
|
||||
bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
|
||||
{
|
||||
return time(NULL) > occupiedTimeout && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
|
||||
return !Occupied() && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
|
||||
}
|
||||
|
||||
bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
|
||||
@ -959,16 +967,27 @@ void cDevice::ForceTransferMode(void)
|
||||
}
|
||||
}
|
||||
|
||||
int cDevice::Occupied(void) const
|
||||
int cDevice::Occupied(int Priority) const
|
||||
{
|
||||
if (Priority > occupiedPriority)
|
||||
return 0;
|
||||
int Seconds = occupiedTimeout - time(NULL);
|
||||
return Seconds > 0 ? Seconds : 0;
|
||||
}
|
||||
|
||||
void cDevice::SetOccupied(int Seconds)
|
||||
void cDevice::SetOccupied(int Seconds, int Priority, time_t From)
|
||||
{
|
||||
if (Seconds >= 0)
|
||||
occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
|
||||
if (Seconds < 0)
|
||||
return;
|
||||
if (From == 0)
|
||||
From = time(NULL);
|
||||
if (From == occupiedFrom)
|
||||
occupiedPriority = max(Priority, occupiedPriority);
|
||||
else {
|
||||
occupiedPriority = Priority;
|
||||
occupiedFrom = From;
|
||||
}
|
||||
occupiedTimeout = From + min(Seconds, MAXOCCUPIEDTIMEOUT);
|
||||
}
|
||||
|
||||
bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
@ -1660,11 +1679,13 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
|
||||
return Played;
|
||||
}
|
||||
|
||||
int cDevice::Priority(void) const
|
||||
int cDevice::Priority(bool IgnoreOccupied) const
|
||||
{
|
||||
int priority = IDLEPRIORITY;
|
||||
if (IsPrimaryDevice() && !Replaying() && HasProgramme())
|
||||
priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing
|
||||
if (!IgnoreOccupied && time(NULL) <= occupiedTimeout && occupiedPriority > priority)
|
||||
priority = occupiedPriority - 1; // so timers with occupiedPriority can start
|
||||
cMutexLock MutexLock(&mutexReceiver);
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
if (receiver[i])
|
||||
|
21
device.h
21
device.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 5.3 2024/01/22 12:10:30 kls Exp $
|
||||
* $Id: device.h 5.4 2024/03/29 21:46:50 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -178,6 +178,9 @@ public:
|
||||
///< the transponder of the given Channel, without disturbing any receiver
|
||||
///< at priorities higher or equal to Priority.
|
||||
///< If no such device is currently available, NULL will be returned.
|
||||
///< Devices recording (Device->Priority(true) >= LIVEPRIORITY) will not be returned,
|
||||
///< even if Priority >= LIVEPRIORITY. Such higher priorities are only used to
|
||||
///< override occupied.
|
||||
static void Shutdown(void);
|
||||
///< Closes down all devices.
|
||||
///< Must be called at the end of the program.
|
||||
@ -259,7 +262,9 @@ public:
|
||||
|
||||
private:
|
||||
mutable cMutex mutexChannel;
|
||||
time_t occupiedFrom;
|
||||
time_t occupiedTimeout;
|
||||
int occupiedPriority;
|
||||
protected:
|
||||
static int currentChannel;
|
||||
public:
|
||||
@ -369,9 +374,10 @@ public:
|
||||
///< channel number while replaying.
|
||||
void ForceTransferMode(void);
|
||||
///< Forces the device into transfermode for the current channel.
|
||||
int Occupied(void) const;
|
||||
///< Returns the number of seconds this device is still occupied for.
|
||||
void SetOccupied(int Seconds);
|
||||
int Occupied(int Priority = MINPRIORITY) const;
|
||||
///< Returns the number of seconds this device is still occupied for
|
||||
///< with a priority >= Priority.
|
||||
void SetOccupied(int Seconds, int Priority = MINPRIORITY, time_t From = 0);
|
||||
///< Sets the occupied timeout for this device to the given number of
|
||||
///< Seconds, This can be used to tune a device to a particular transponder
|
||||
///< and make sure it will stay there for a certain amount of time, for
|
||||
@ -379,6 +385,10 @@ public:
|
||||
///< after the device has been successfully tuned to the requested transponder.
|
||||
///< Seconds will be silently limited to MAXOCCUPIEDTIMEOUT. Values less than
|
||||
///< 0 will be silently ignored.
|
||||
///< The timeout is counted from the given From time (by default the current time).
|
||||
///< Calling this function several times with the same From time will set the
|
||||
///< priority to the maximum of the given values.
|
||||
///< Priority() may return a value >= Priority until the timeout.
|
||||
virtual bool HasLock(int TimeoutMs = 0) const;
|
||||
///< Returns true if the device has a lock on the requested transponder.
|
||||
///< Default is true, a specific device implementation may return false
|
||||
@ -833,9 +843,10 @@ private:
|
||||
mutable cMutex mutexReceiver;
|
||||
cReceiver *receiver[MAXRECEIVERS];
|
||||
public:
|
||||
int Priority(void) const;
|
||||
int Priority(bool IgnoreOccupied = false) const;
|
||||
///< Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),
|
||||
///< or IDLEPRIORITY if no receiver is currently active.
|
||||
///< If IgnoreOccupied is true, a priority set with SetOccupied() is ignored.
|
||||
protected:
|
||||
virtual bool OpenDvr(void);
|
||||
///< Opens the DVR of this device and prepares it to deliver a Transport
|
||||
|
16
vdr.c
16
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.tvdr.de
|
||||
*
|
||||
* $Id: vdr.c 5.15 2024/03/28 13:21:42 kls Exp $
|
||||
* $Id: vdr.c 5.16 2024/03/29 21:46:50 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -85,7 +85,7 @@
|
||||
#define CHANNELSAVEDELTA 600 // seconds before saving channels.conf after automatic modifications
|
||||
#define DEVICEREADYTIMEOUT 30 // seconds to wait until all devices are ready
|
||||
#define MENUTIMEOUT 120 // seconds of user inactivity after which an OSD display is closed
|
||||
#define TIMERCHECKDELTA 10 // seconds between checks for timers that need to see their channel
|
||||
#define TIMERCHECKDELTA 5 // seconds between checks for timers that need to see their channel
|
||||
#define TIMERDEVICETIMEOUT 8 // seconds before a device used for timer check may be reused
|
||||
#define TIMERLOOKAHEADTIME 60 // seconds before a non-VPS timer starts and the channel is switched if possible
|
||||
#define VPSLOOKAHEADTIME 24 // hours within which VPS timers will make sure their events are up to date
|
||||
@ -1158,8 +1158,12 @@ int main(int argc, char *argv[])
|
||||
if (NeedsTransponder || InVpsMargin) {
|
||||
// Find a device that provides the required transponder:
|
||||
cDevice *Device = cDevice::GetDeviceForTransponder(Timer->Channel(), MINPRIORITY);
|
||||
if (!Device && InVpsMargin)
|
||||
Device = cDevice::GetDeviceForTransponder(Timer->Channel(), LIVEPRIORITY);
|
||||
if (InVpsMargin) {
|
||||
if (!Device)
|
||||
Device = cDevice::GetDeviceForTransponder(Timer->Channel(), Timer->Priority() );
|
||||
if (!Device)
|
||||
Device = cDevice::GetDevice(Timer->Channel(), Timer->Priority(), false, false);
|
||||
}
|
||||
// Switch the device to the transponder:
|
||||
if (Device) {
|
||||
bool HadProgramme = cDevice::PrimaryDevice()->HasProgramme();
|
||||
@ -1167,9 +1171,9 @@ int main(int argc, char *argv[])
|
||||
if (Device == cDevice::ActualDevice() && !Device->IsPrimaryDevice())
|
||||
cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
|
||||
dsyslog("switching device %d to channel %d %s (%s)", Device->DeviceNumber() + 1, Timer->Channel()->Number(), *Timer->Channel()->GetChannelID().ToString(), Timer->Channel()->Name());
|
||||
if (Device->SwitchChannel(Timer->Channel(), false))
|
||||
Device->SetOccupied(TIMERDEVICETIMEOUT);
|
||||
Device->SwitchChannel(Timer->Channel(), false);
|
||||
}
|
||||
Device->SetOccupied(TIMERDEVICETIMEOUT, InVpsMargin ? Timer->Priority() : MINPRIORITY, Now);
|
||||
if (cDevice::PrimaryDevice()->HasDecoder() && HadProgramme && !cDevice::PrimaryDevice()->HasProgramme()) {
|
||||
LastTimerChannel = Timer->Channel()->Number();
|
||||
Skins.QueueMessage(mtInfo, tr("Upcoming recording!")); // the previous SwitchChannel() has switched away the current live channel
|
||||
|
Loading…
x
Reference in New Issue
Block a user