Hi!
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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
This bug is still present in 1.3.29. Klaus, I know that your day is only 24 hours long and that I'm bringing this patch up the third time, but could this be either applied or replied?
Anssi Hannula 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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
This bug is still present in 1.3.29. Klaus, I know that your day is only 24 hours long and that I'm bringing this patch up the third time, but could this be either applied or replied?
Sorry, your original posting was during my vacation, so I must have overlooked it.
I guess you're right with this and will make it so in the next version.
Klaus
Hi,
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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
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.
Thomas
Thomas Bergwinkl wrote:
Hi,
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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
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.
Oh, I just assumed VDR takes that into account. If not, then of course it either has to be implemented or the patch not applied. I have 3 DVB-T cards in my system, so I can use the patch anyway.
Thomas Bergwinkl wrote:
Hi,
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.
Also, if I had DVB-S FF and only one DVB-T budget and had a DVB-T recording with priority 10 and Primary Limit at 20, live DVB-T video would (wouldn't it?) be severed.
Klaus, shouldn't transfer-mode be also using the Primary Limit value, so that recordings with priority less than Primary Limit couldn't distract the output of primary device?
Patch attached.
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.
Thanks, I didn't think of this when I said I would adopt that change.
Actually, the PrimaryLimit was implemented at a time where the FF DVB cards were unable to record and replay at the same time. In that case, when a timer needed to use the primary device, it was no longer possible to switch to a different channel. These times are long gone, so I would instead tend to remove the PrimaryLimit altogether. It would make things simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
Klaus
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.
Actually, the PrimaryLimit was implemented at a time where the FF DVB cards were unable to record and replay at the same time. In that case, when a timer needed to use the primary device, it was no longer possible to switch to a different channel. These times are long gone, so I would instead tend to remove the PrimaryLimit altogether. It would make things simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
How exactly would that resolve the situation I described above?
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.
Actually, the PrimaryLimit was implemented at a time where the FF DVB cards were unable to record and replay at the same time. In that case, when a timer needed to use the primary device, it was no longer possible to switch to a different channel. These times are long gone, so I would instead tend to remove the PrimaryLimit altogether. It would make things simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
How exactly would that resolve the situation I described above?
Well, it wouldn't. Apparently I overread that this was a streamdev issue. 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...
Klaus
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.
Actually, the PrimaryLimit was implemented at a time where
the FF DVB
cards were unable to record and replay at the same time.
In that case,
when a timer needed to use the primary device, it was no
longer possible
to switch to a different channel. These times are long
gone, so I would
instead tend to remove the PrimaryLimit altogether. It
would make things
simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
How exactly would that resolve the situation I described above?
Well, it wouldn't. Apparently I overread that this was a streamdev issue. 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...
What do you think about the attached patch?
Thomas
Thomas Bergwinkl wrote:
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.
Actually, the PrimaryLimit was implemented at a time where
the FF DVB
cards were unable to record and replay at the same time.
In that case,
when a timer needed to use the primary device, it was no
longer possible
to switch to a different channel. These times are long
gone, so I would
instead tend to remove the PrimaryLimit altogether. It
would make things
simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
How exactly would that resolve the situation I described above?
Well, it wouldn't. Apparently I overread that this was a streamdev issue. 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...
What do you think about the attached patch?
Thomas
@Anssi: have you had a chance to test this patch yet?
Klaus
Klaus Schmidinger wrote:
Thomas Bergwinkl wrote:
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. >
Actually, the PrimaryLimit was implemented at a time where
the FF DVB
cards were unable to record and replay at the same time.
In that case,
when a timer needed to use the primary device, it was no
longer possible
to switch to a different channel. These times are long
gone, so I would
instead tend to remove the PrimaryLimit altogether. It
would make things
simpler instead of more complex ;-)
If somebody has programmed so many timers that all of the DVB cards are needed to record them, so be it.
Comments?
How exactly would that resolve the situation I described above?
Well, it wouldn't. Apparently I overread that this was a streamdev issue. 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...
What do you think about the attached patch?
Thomas
@Anssi: have you had a chance to test this patch yet?
Meanwhile I realised that in cDevice::SetChannel GetDevice is called with priority 0. So the 'Priority >= 0' in the patch is always true (and therefore could be replaced be 'true') . This will lead to a 'sideeffect' if more than one device is able to provide this channel: When zapping through the channels always the other device will be choosen. Another effect with this patch is, that when a recording on the same transponder starts, which currently is received via transfermode, then the receiving device will be prefered for the recording be GetDevice(). So I am not really happy with this patch anymore and think a better solution is neccessary.
Thomas
Thomas Bergwinkl wrote:
Klaus Schmidinger wrote:
Thomas Bergwinkl wrote:
Klaus Schmidinger wrote:
Well, it wouldn't. Apparently I overread that this was a streamdev issue. 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...
What do you think about the attached patch?
Thomas
@Anssi: have you had a chance to test this patch yet?
Oops, sorry I didn't notice this new patch at all. Is this meant to be used with or without my initial patch?
Meanwhile I realised that in cDevice::SetChannel GetDevice is called with priority 0. So the 'Priority >= 0' in the patch is always true (and therefore could be replaced be 'true') . This will lead to a 'sideeffect' if more than one device is able to provide this channel: When zapping through the channels always the other device will be choosen. Another effect with this patch is, that when a recording on the same transponder starts, which currently is received via transfermode, then the receiving device will be prefered for the recording be GetDevice(). So I am not really happy with this patch anymore and think a better solution is neccessary.
Hmm, too complicated for me to understand right now...
BTW, with my original patch, the channel switching in DVB-T seems to be faster. When switching multiplex, VDR also switches to second device. When I switch back to the previous multiplex, I believe the first card (which VDR changes back to) is still tuned to that and retuning is not necessary. However this same thing is the problem also, as Thomas said, because you need always an extra free card for multiplex switching (which is not a problem for me, because number of multiplexes = number of cards).
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()).
Anssi Hannula wrote:
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.
bool cDevice::Receiving(bool CheckAny) const {
- if (this == ActualDevice())
CheckAny = true;
No, what if primary device is not receiving, but has -1 priority receivers? This reports true then, when it shouldn't.
It should be this instead: + if (this == cTransferControl::ReceiverDevice()) + return true;
Attached is a revised patch.
Anssi Hannula wrote:
Anssi Hannula wrote:
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.
bool cDevice::Receiving(bool CheckAny) const {
- if (this == ActualDevice())
CheckAny = true;
No, what if primary device is not receiving, but has -1 priority receivers? This reports true then, when it shouldn't.
It should be this instead:
- if (this == cTransferControl::ReceiverDevice())
return true;
Attached is a revised 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-12 06:31:20.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 == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) // cReceiver with priority < 0 doesn't count return true;return true;
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1 - all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2 - channels 10 and 11 are on the same transponder, channel 12 is on a different one - switch directly to channel 10 -> transfer mode starts - press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Klaus
Klaus Schmidinger wrote:
Anssi Hannula wrote:
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-12 06:31:20.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 == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) //return true;
cReceiver with priority < 0 doesn't count return true;
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default) - SwitchChannel() gets called (device.c line 581) - PrimaryDevice()->ProvidesChannel() returns false (line 591) - GetDevice() is called (line 281) - for the device 1 ProvidesChannel() returns false (line 288) - ProvidesChannel() is called for device 2 (dvbdevice.c line 767) - Priority = 0, this->Priority() = -1, so hasPriority = true - ProvidesChannel() result = true is set in line 785 - ProvidesChannel() return true and ndr = false (device.c line 288) - (device[i]->Receiving() && !ndr) evaluates true (line 290) - pri = 0 so device 2 is selected - SwitchChannel() calls another SwitchChannel (line 601) - SwitchChannel() calls SetChannel (line 568) - and so on
Hopefully I'll have time to test this scenario later today.
BTW, isn't the PrimaryLimit there so that liveview would not be distracted when a recording with (priority < primarylimit) is trying to start? Why is it used for primary device exclusively, then? If the liveview is in transfer-mode, shouldn't that be protected as well?
If you think it should be used for primary device only, only the change in Receiving() in my patch is necessary. If you think it should indeed be used for whatever device the user currently is watching, there are some more places where transfermode-liveview priority is assumed 0, when it should be PrimaryLimit (at least in device.c line 591 call to GetDevice()). Or if you still think the PrimaryLimit adds only complexity for not much of real value, then remove it ;) and assume 0 for it's value everywhere.
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
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-12 06:31:20.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 == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) //return true;
cReceiver with priority < 0 doesn't count return true;
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
BTW, isn't the PrimaryLimit there so that liveview would not be distracted when a recording with (priority < primarylimit) is trying to start? Why is it used for primary device exclusively, then? If the liveview is in transfer-mode, shouldn't that be protected as well?
This parameter was introduced at a time when it was not yet possible to record and replay on the FF cards at the same time, so that a timer wouldn't prevent the user from live viewing.
Now that the FF cards can record and replay at the same time, the primary device actually wouldn't need to be "protected" any more, because if it has to be used for recording (for instance because it is the only device that can provide a certain channel), it could just fetch the live channel from a different device and show it in Transfer Mode.
If you think it should be used for primary device only, only the change in Receiving() in my patch is necessary. If you think it should indeed be used for whatever device the user currently is watching, there are some more places where transfermode-liveview priority is assumed 0, when it should be PrimaryLimit (at least in device.c line 591 call to GetDevice()). Or if you still think the PrimaryLimit adds only complexity for not much of real value, then remove it ;) and assume 0 for it's value everywhere.
I'd really prefer to drop the whole PrimaryLimit thing, because, as we see in this thread, it makes things rather complex.
If users program so many concurrent timers that the system needs all the devices to record them, well, then that's apparently what they wanted.
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right? Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
for (int i = 0; i < numDevices; i++) { if (AvoidActualDevice && device[i] == ActualDevice()) continue; bool ndr; ...
Finally, streamdev would have to be modified so that it sets AvoidActualDevice to 'true' before calling cDevice::GetDevice(), and back to 'false' afterwards.
If this turns out to be feasible, we could change cDevice::GetDevice() in version 1.5.x so that it has an additional parameter for this.
Klaus
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
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-12 06:31:20.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 == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) //return true;
cReceiver with priority < 0 doesn't count return true;
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
Well, I tried it in the following scenario: - two devices, primary is 1 - all channels available on device 2 only - channels 1 and 2 are on the same transponder, 3 and 4 on a different one - manually switch to channel 1 - press up -> vdr switches to 2 - up again -> vdr switches to 3 - up again -> vdr switches to 4
It works ok. Do you have PrimaryLimit != 0? As it turns out, there is indeed a bug in the patch which appears when PrimaryLimit is something else than 0 and affects the channelup & channeldown. If you do, try one of the following: 1. The above patch with only the Receiving() change. 2. The above patch fully and additionally Priority of GetDevice() call in device.c line 591 changed from 0 to Setup.PrimaryLimit. 3. PrimaryLimit = 0
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right?
Yes.
Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
I think it would be much better to fix this bug (VDR doesn't prefer free devices over transfer-moded) rather than add this kind of workaround.
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
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-12 06:31:20.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 == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) //return true;
cReceiver with priority < 0 doesn't count return true;
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
Well, I tried it in the following scenario:
- two devices, primary is 1
- all channels available on device 2 only
- channels 1 and 2 are on the same transponder, 3 and 4 on a different one
- manually switch to channel 1
- press up -> vdr switches to 2
- up again -> vdr switches to 3
- up again -> vdr switches to 4
It works ok. Do you have PrimaryLimit != 0? As it turns out, there is indeed a bug in
Well, I normally have PrimaryLimit=0, but I've set it to 10 for testing. Sorry, forgot to mention that.
the patch which appears when PrimaryLimit is something else than 0 and affects the channelup & channeldown. If you do, try one of the following:
- The above patch with only the Receiving() change.
- The above patch fully and additionally Priority of GetDevice() call
in device.c line 591 changed from 0 to Setup.PrimaryLimit. 3. PrimaryLimit = 0
Sorry, it's late today - but see below, maybe this is all no longer a problem, anyway ;-)
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right?
Yes.
Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
I think it would be much better to fix this bug (VDR doesn't prefer free devices over transfer-moded) rather than add this kind of workaround.
VDR does prefer free devices over ones used for Transfer Mode:
Device *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { ... else if (!device[i]->Receiving() && device[i] != ActualDevice()) pri = 3; // free and not the actual device else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice()) pri = 4; // free and not the primary device ... }
Hmm, come to think of it: could it be that your original problem no longer exists since VDR 1.3.46?
2006-04-09: Version 1.3.46
... - Now avoiding the 'actual' device when starting a recording, so that a Transfer Mode for live tv isn't interrupted.
Klaus
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
Well, I tried it in the following scenario:
- two devices, primary is 1
- all channels available on device 2 only
- channels 1 and 2 are on the same transponder, 3 and 4 on a different
one
- manually switch to channel 1
- press up -> vdr switches to 2
- up again -> vdr switches to 3
- up again -> vdr switches to 4
It works ok. Do you have PrimaryLimit != 0? As it turns out, there is indeed a bug in
Well, I normally have PrimaryLimit=0, but I've set it to 10 for testing. Sorry, forgot to mention that.
the patch which appears when PrimaryLimit is something else than 0 and affects the channelup & channeldown. If you do, try one of the following:
- The above patch with only the Receiving() change.
- The above patch fully and additionally Priority of GetDevice() call
in device.c line 591 changed from 0 to Setup.PrimaryLimit. 3. PrimaryLimit = 0
Sorry, it's late today - but see below, maybe this is all no longer a problem, anyway ;-)
It is, but hopefully not for long :)
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right?
Yes.
Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
I think it would be much better to fix this bug (VDR doesn't prefer free devices over transfer-moded) rather than add this kind of workaround.
VDR does prefer free devices over ones used for Transfer Mode:
No, it doesn't, if the transfer-moded device is a budget card:
Device *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { ... else if (!device[i]->Receiving() && !device[i]->HasDecoder()) pri = 2; // free and not a full featured card
This causes the device to be selected no matter if it is in transfer mode or not.
It seems to me that the above "2" case and the below "3" case should be swapped.
However, Receiving() is supposed to be "Returns true if we are currently receiving." so I think it should still check for transfermode, as it is then definitely receiving. Then the "free and not the actual device" case could be dropped from GetDevice().
else if (!device[i]->Receiving() && device[i] != ActualDevice()) pri = 3; // free and not the actual device else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice()) pri = 4; // free and not the primary device
... }
Hmm, come to think of it: could it be that your original problem no longer exists since VDR 1.3.46?
2006-04-09: Version 1.3.46
...
- Now avoiding the 'actual' device when starting a recording, so that a
Transfer Mode for live tv isn't interrupted.
Nope, I'm running 1.4.0 and I also confirmed the problem still exists with vanilla VDR.
I've now attached two patches. One adds a check for transfer mode in Receiving() and drops the then-useless "free and not the actual device" case from GetDevice(). The other one is optional: it changes the effective transfer-mode receiver priority from fixed 0 to PrimaryLimit, so that the transfer-mode is also "protected" by PrimaryLimit.
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
I'm afraid this patch has a nasty side effect.
Asssume the following scenario:
- two devices, primary is 1
- all channels are available on both devices, except for channels 10, 11 and 12 which can only be received by device 2
- channels 10 and 11 are on the same transponder, channel 12 is on a
different one
- switch directly to channel 10 -> transfer mode starts
- press "Up" to switch to channel 11, but that channel is skipped and it switches to channel 12
So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
Well, I tried it in the following scenario:
- two devices, primary is 1
- all channels available on device 2 only
- channels 1 and 2 are on the same transponder, 3 and 4 on a different
one
- manually switch to channel 1
- press up -> vdr switches to 2
- up again -> vdr switches to 3
- up again -> vdr switches to 4
It works ok. Do you have PrimaryLimit != 0? As it turns out, there is indeed a bug in
Well, I normally have PrimaryLimit=0, but I've set it to 10 for testing. Sorry, forgot to mention that.
the patch which appears when PrimaryLimit is something else than 0 and affects the channelup & channeldown. If you do, try one of the following:
- The above patch with only the Receiving() change.
- The above patch fully and additionally Priority of GetDevice() call
in device.c line 591 changed from 0 to Setup.PrimaryLimit. 3. PrimaryLimit = 0
Sorry, it's late today - but see below, maybe this is all no longer a problem, anyway ;-)
It is, but hopefully not for long :)
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right?
Yes.
Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
I think it would be much better to fix this bug (VDR doesn't prefer free devices over transfer-moded) rather than add this kind of workaround.
VDR does prefer free devices over ones used for Transfer Mode:
No, it doesn't, if the transfer-moded device is a budget card:
Device *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { ... else if (!device[i]->Receiving() && !device[i]->HasDecoder()) pri = 2; // free and not a full featured card
This causes the device to be selected no matter if it is in transfer mode or not.
Ok, you're right about that.
It seems to me that the above "2" case and the below "3" case should be swapped.
However, Receiving() is supposed to be "Returns true if we are currently receiving." so I think it should still check for transfermode, as it is then definitely receiving. Then the "free and not the actual device" case could be dropped from GetDevice().
else if (!device[i]->Receiving() && device[i] != ActualDevice()) pri = 3; // free and not the actual device else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice()) pri = 4; // free and not the primary device
... }
Hmm, come to think of it: could it be that your original problem no longer exists since VDR 1.3.46?
2006-04-09: Version 1.3.46
...
- Now avoiding the 'actual' device when starting a recording, so that a
Transfer Mode for live tv isn't interrupted.
Nope, I'm running 1.4.0 and I also confirmed the problem still exists with vanilla VDR.
I've now attached two patches. One adds a check for transfer mode in Receiving() and drops the then-useless "free and not the actual device" case from GetDevice(). The other one is optional: it changes the effective transfer-mode receiver priority from fixed 0 to PrimaryLimit, so that the transfer-mode is also "protected" by PrimaryLimit.
diff -Nurp -x '*~' vdr-1.4.0/device.c vdr-1.4.0-fix2/device.c --- vdr-1.4.0/device.c 2006-04-14 17:34:43.000000000 +0300 +++ vdr-1.4.0-fix2/device.c 2006-05-14 01:10:25.000000000 +0300 @@ -293,18 +293,16 @@ cDevice *cDevice::GetDevice(const cChann pri = 1; // free and fewer Ca's else if (!device[i]->Receiving() && !device[i]->HasDecoder()) pri = 2; // free and not a full featured card
else if (!device[i]->Receiving() && device[i] != ActualDevice())
pri = 3; // free and not the actual device else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice())
pri = 4; // free and not the primary device
pri = 3; // free and not the primary device else if (!device[i]->Receiving())
pri = 5; // free
pri = 4; // free else if (d && device[i]->Priority() < d->Priority())
pri = 6; // receiving but priority is lower
pri = 5; // receiving but priority is lower else if (d && device[i]->Priority() == d->Priority() && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
pri = 7; // receiving with same priority but fewer Ca's
pri = 6; // receiving with same priority but fewer Ca's else
pri = 8; // all others
pri = 7; // all others if (pri <= select) { select = pri; d = device[i];
@@ -1183,6 +1181,8 @@ int cDevice::ProvidesCa(const cChannel *
bool cDevice::Receiving(bool CheckAny) const {
- if (this == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) // cReceiver with priority < 0 doesn't count return true;return true;
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-14 01:06:32.000000000 +0300 @@ -588,7 +586,7 @@ bool cDevice::SwitchChannel(int Directio cChannel *channel; while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { // try only channels which are currently available
if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0))
if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, Setup.PrimaryLimit)) break; n = channel->Number() + Direction; }
@@ -627,7 +625,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 +1156,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);
I'll need to give this more thought - won't have time for it today.
Klaus
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
Anssi Hannula wrote:
Klaus Schmidinger wrote:
> I'm afraid this patch has a nasty side effect. > > Asssume the following scenario: > > - two devices, primary is 1 > - all channels are available on both devices, except for channels > 10, 11 and 12 which can only be received by device 2 > - channels 10 and 11 are on the same transponder, channel 12 is on a > different one > - switch directly to channel 10 -> transfer mode starts > - press "Up" to switch to channel 11, but that channel is skipped > and > it switches to channel 12 > > So I guess I can't accept this patch.
Thank you for taking a look.
However, I don't see why there is such a problem in the above scenario:
- let's consider PrimaryLimit is 0 (the default)
- SwitchChannel() gets called (device.c line 581)
- PrimaryDevice()->ProvidesChannel() returns false (line 591)
- GetDevice() is called (line 281)
- for the device 1 ProvidesChannel() returns false (line 288)
- ProvidesChannel() is called for device 2 (dvbdevice.c line 767)
- Priority = 0, this->Priority() = -1, so hasPriority = true
- ProvidesChannel() result = true is set in line 785
- ProvidesChannel() return true and ndr = false (device.c line 288)
- (device[i]->Receiving() && !ndr) evaluates true (line 290)
- pri = 0 so device 2 is selected
- SwitchChannel() calls another SwitchChannel (line 601)
- SwitchChannel() calls SetChannel (line 568)
- and so on
Hopefully I'll have time to test this scenario later today.
Well, just try it - it did behave here as described.
Well, I tried it in the following scenario:
- two devices, primary is 1
- all channels available on device 2 only
- channels 1 and 2 are on the same transponder, 3 and 4 on a different
one
- manually switch to channel 1
- press up -> vdr switches to 2
- up again -> vdr switches to 3
- up again -> vdr switches to 4
It works ok. Do you have PrimaryLimit != 0? As it turns out, there is indeed a bug in
Well, I normally have PrimaryLimit=0, but I've set it to 10 for testing. Sorry, forgot to mention that.
the patch which appears when PrimaryLimit is something else than 0 and affects the channelup & channeldown. If you do, try one of the following:
- The above patch with only the Receiving() change.
- The above patch fully and additionally Priority of GetDevice() call
in device.c line 591 changed from 0 to Setup.PrimaryLimit. 3. PrimaryLimit = 0
Sorry, it's late today - but see below, maybe this is all no longer a problem, anyway ;-)
It is, but hopefully not for long :)
Looking back at your original posting, I believe the actual problem that triggered all this was that streamdev would interrupt live viewing in Transfer Mode, right?
Yes.
Well, what if streamdev, when selecting the device to use, could avoid the ActualDevice()?
To test this (without modifying the cDevice API) you could introduce a
bool AvoidActualDevice = false;
right before
cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
and inside that function check that variable, and if it is true and the checked device is the ActualDevice(), continue the 'for' loop:
I think it would be much better to fix this bug (VDR doesn't prefer free devices over transfer-moded) rather than add this kind of workaround.
VDR does prefer free devices over ones used for Transfer Mode:
No, it doesn't, if the transfer-moded device is a budget card:
Device *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { ... else if (!device[i]->Receiving() && !device[i]->HasDecoder()) pri = 2; // free and not a full featured card
This causes the device to be selected no matter if it is in transfer mode or not.
Ok, you're right about that.
It seems to me that the above "2" case and the below "3" case should be swapped.
However, Receiving() is supposed to be "Returns true if we are currently receiving." so I think it should still check for transfermode, as it is then definitely receiving. Then the "free and not the actual device" case could be dropped from GetDevice().
else if (!device[i]->Receiving() && device[i] !=
ActualDevice()) pri = 3; // free and not the actual device else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice()) pri = 4; // free and not the primary device ... }
Hmm, come to think of it: could it be that your original problem no longer exists since VDR 1.3.46?
2006-04-09: Version 1.3.46
...
- Now avoiding the 'actual' device when starting a recording, so that a
Transfer Mode for live tv isn't interrupted.
Nope, I'm running 1.4.0 and I also confirmed the problem still exists with vanilla VDR.
I've now attached two patches. One adds a check for transfer mode in Receiving() and drops the then-useless "free and not the actual device" case from GetDevice(). The other one is optional: it changes the effective transfer-mode receiver priority from fixed 0 to PrimaryLimit, so that the transfer-mode is also "protected" by PrimaryLimit.
diff -Nurp -x '*~' vdr-1.4.0/device.c vdr-1.4.0-fix2/device.c --- vdr-1.4.0/device.c 2006-04-14 17:34:43.000000000 +0300 +++ vdr-1.4.0-fix2/device.c 2006-05-14 01:10:25.000000000 +0300 @@ -293,18 +293,16 @@ cDevice *cDevice::GetDevice(const cChann pri = 1; // free and fewer Ca's else if (!device[i]->Receiving() && !device[i]->HasDecoder()) pri = 2; // free and not a full featured card
else if (!device[i]->Receiving() && device[i] !=
ActualDevice())
pri = 3; // free and not the actual device else if (!device[i]->Receiving() &&
!device[i]->IsPrimaryDevice())
pri = 4; // free and not the primary device
pri = 3; // free and not the primary device else if (!device[i]->Receiving())
pri = 5; // free
pri = 4; // free else if (d && device[i]->Priority() < d->Priority())
pri = 6; // receiving but priority is lower
pri = 5; // receiving but priority is lower else if (d && device[i]->Priority() == d->Priority() &&
device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
pri = 7; // receiving with same priority but fewer Ca's
pri = 6; // receiving with same priority but fewer Ca's else
pri = 8; // all others
pri = 7; // all others if (pri <= select) { select = pri; d = device[i];
@@ -1183,6 +1181,8 @@ int cDevice::ProvidesCa(const cChannel *
bool cDevice::Receiving(bool CheckAny) const {
- if (this == cTransferControl::ReceiverDevice())
for (int i = 0; i < MAXRECEIVERS; i++) { if (receiver[i] && (CheckAny || receiver[i]->priority >= 0)) //return true;
cReceiver with priority < 0 doesn't count return true;
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-14 01:06:32.000000000 +0300 @@ -588,7 +586,7 @@ bool cDevice::SwitchChannel(int Directio cChannel *channel; while ((channel = Channels.GetByNumber(n, Direction)) != NULL) { // try only channels which are currently available
if (PrimaryDevice()->ProvidesChannel(channel,
Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0))
if (PrimaryDevice()->ProvidesChannel(channel,
Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, Setup.PrimaryLimit)) break; n = channel->Number() + Direction; } @@ -627,7 +625,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 +1156,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);
@Anssi: can you please check whether my latest changes to cDevice::GetDevice() have also fixed this problem? See the patch vdr-1.4.0-getdevice-2.diff posted under "RFC: recording strategy on timer conflicts".
Klaus
Anssi Hannula anssi.hannula@gmail.com wrote:
[snip]
I've now attached two patches. One adds a check for transfer mode in Receiving() and drops the then-useless "free and not the actual device" case from GetDevice(). The other one is optional: it changes the effective transfer-mode receiver priority from fixed 0 to PrimaryLimit, so that the transfer-mode is also "protected" by PrimaryLimit.
Seems to work as expected, Thanks !