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()) >>>>> + return 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; >>>> >>>> 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: > 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 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