Priority of transfer-mode should not be -1

Message ID 446255A9.2010304@gmail.com
State New
Headers

Commit Message

Anssi Hannula May 10, 2006, 9:05 p.m. UTC
  Klaus Schmidinger wrote:
> Anssi Hannula wrote:
> 
>> Klaus Schmidinger wrote:
>>
>>>> Anssi Hannula wrote:
>>>>
>>>>> The transfer-mode uses always priority -1.
>>>>>
>>>>> That presents a problem: If I connect to that vdr using streamdev, it
>>>>> switches the first budget device off from the multiplex transfered to
>>>>> the FF card, although there is a second identical budget
>>>>> device available.
>>>>>

> But then again, it's of course the same problem if you are in Transfer-Mode
> and a recording starts and selects the receiver device, even though an
> other
> device would be free.
> 
> I'll think over this again...

Okay, I finally found some time to solve this problem. You may remember
may previous patch that just changed the priority, the patch which had a
flaw:

Thomas Bergwinkl wrote:
> I think there is a problem with your patch. There is a reason for the
> priority -1. Imagine you have a channel which can only be received by
> one card and this card is used for transfer-mode. When you want to
> switch to this channel, the transfer-mode has, with your patch, e.g
> priority 0. But the new transfer-mode would have the same priority (but
> not a higher), so there would be no free device (channel not available).
> So when searching for a free device, vdr should consider that the
> device, which is used for transfer-mode, could be free, if transfer-mode
> for the current channel has ended.

My new patch has a different approach:

It seems that on cDevice::Priority() there is already a check that if
the device is the primary device, the returned priority is a minimum of
PrimaryLimit-1, which is low enough so that the channel can be switched
if a device is being searched for a new receiver with priority PrimaryLimit.

This patch modifies it to check (ActualDevice() == this) instead, so
that in case of transfer-mode the Priority() returns PrimaryLimit-1 too.

The SetChannel() is also modified to call GetDevice() with priority
PrimaryLimit instead of 0 when searching for an available device for
transfer-mode.

The Receiving(bool CheckAny) is modified so that if it is called on the
transfer-moded device, it returns true if receivers are found with
priority < 0 even if CheckAny == false.

The actual transfer-mode receiver priority is kept as -1.

So, when something (e.g. streamdev) requests a channel with a priority 5
for example, it will use a free device if available, and detaches the
transfer-mode only as a last resort (if the PrimaryLimit is small
enough, of course).

And if e.g. the user switches from transfer-mode DVB-T channel to
another transfer-mode DVB-T channel on a different multiplex, the (this
== ActualDevice()) in Receiving() evaluates to (false) when it is
called, so the old device is still used for the new channel (unless of
course a better suited device is found by GetDevice()).
  

Patch

diff -Nurp -x '*~' vdr-1.4.0/device.c vdr-1.4.0-fix/device.c
--- vdr-1.4.0/device.c	2006-04-14 17:34:43.000000000 +0300
+++ vdr-1.4.0-fix/device.c	2006-05-10 23:13:16.000000000 +0300
@@ -627,7 +627,7 @@  eSetChannelResult cDevice::SetChannel(co
   // use the card that actually can receive it and transfer data from there:
 
   if (NeedsTransferMode) {
-     cDevice *CaDevice = GetDevice(Channel, 0, &NeedsDetachReceivers);
+     cDevice *CaDevice = GetDevice(Channel, Setup.PrimaryLimit, &NeedsDetachReceivers);
      if (CaDevice && CanReplay()) {
         cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
         if (CaDevice->SetChannel(Channel, false) == scrOk) { // calling SetChannel() directly, not SwitchChannel()!
@@ -1158,7 +1158,7 @@  int cDevice::Ca(void) const
 
 int cDevice::Priority(void) const
 {
-  int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
+  int priority = ActualDevice() == this ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
   for (int i = 0; i < MAXRECEIVERS; i++) {
       if (receiver[i])
          priority = max(receiver[i]->priority, priority);
@@ -1183,6 +1183,8 @@  int cDevice::ProvidesCa(const cChannel *
 
 bool cDevice::Receiving(bool CheckAny) const
 {
+  if (this == ActualDevice())
+      CheckAny = true;
   for (int i = 0; i < MAXRECEIVERS; i++) {
       if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) // cReceiver with priority < 0 doesn't count
          return true;