#!/bin/sh /usr/share/dpatch/dpatch-run ## sharelnb patch by Matthias Lötzke ## ## downloaded from http://www.xn--ltzke-jua.de/dvb/VDR_LNB_sharing_patch/ ## original filename configurableLNBshare-VDR_1.3.23_v2.patch ## ## Thomas Günther : ## - solved conflict with enAIO-2.1 patch in config.h and config.c ## - adapted to VDR-1.3.24 ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Patch to share one sat connection for several cards. @DPATCH@ diff -u -r vdr-1.3.23-orig/config.c vdr-1.3.23/config.c --- vdr-1.3.23-orig/config.c 2005-02-20 13:52:59.000000000 +0100 +++ vdr-1.3.23/config.c 2005-04-06 22:02:25.000000000 +0200 @@ -299,6 +299,9 @@ ShowReplayMode = 0; ResumeID = 0; CurrentChannel = -1; +//ML + for (int i = 0; i < MAXDEVICES; i++) CardUsesLNBnr[i] = i + 1; +//ML-Ende CurrentVolume = MAXVOLUME; CurrentDolby = 0; } @@ -459,7 +462,22 @@ else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value); else if (!strcasecmp(Name, "CurrentDolby")) CurrentDolby = atoi(Value); else - return false; + +//ML + { + char tmp[20]; + bool result = false; + for (int i = 1; i <= MAXDEVICES; i++) { + sprintf(tmp, "Card%dusesLNBnr", i); + if (!strcasecmp(Name, tmp)) { + CardUsesLNBnr[i - 1] = atoi(Value); + result = true; + } + } + return result; + } +//ML-Ende + return true; } @@ -523,6 +541,16 @@ Store("CurrentVolume", CurrentVolume); Store("CurrentDolby", CurrentDolby); +//ML + char tmp[20]; + if (cDevice::NumDevices() > 1) { + for (int i = 1; i <= cDevice::NumDevices(); i++) { + sprintf(tmp, "Card%dusesLNBnr", i); + Store(tmp, CardUsesLNBnr[i - 1]); + } + } +//ML-Ende + Sort(); if (cConfig::Save()) { diff -u -r vdr-1.3.23-orig/config.h vdr-1.3.23/config.h --- vdr-1.3.23-orig/config.h 2005-03-05 16:44:35.000000000 +0100 +++ vdr-1.3.23/config.h 2005-04-06 22:02:25.000000000 +0200 @@ -253,6 +253,9 @@ int ShowReplayMode; int ResumeID; int CurrentChannel; +//ML + int CardUsesLNBnr[MAXDEVICES]; +//ML-Ende int CurrentVolume; int CurrentDolby; int __EndData__; diff -u -r vdr-1.3.23-orig/device.c vdr-1.3.23/device.c --- vdr-1.3.23-orig/device.c 2005-02-27 14:55:15.000000000 +0100 +++ vdr-1.3.23/device.c 2005-04-06 22:02:25.000000000 +0200 @@ -19,6 +19,10 @@ #include "status.h" #include "transfer.h" +//ML +#include "diseqc.h" +//ML-Ende + // --- cPesAssembler --------------------------------------------------------- class cPesAssembler { @@ -154,6 +158,12 @@ SetVideoFormat(Setup.VideoFormat); +//ML + LNBstate = -1; + LNBnr = Setup.CardUsesLNBnr[cardIndex]; + LNBsource = NULL; +//ML-Ende + active = false; mute = false; @@ -201,6 +211,16 @@ useDevice |= (1 << n); } +//ML +void cDevice::SetLNBnr(void) +{ + for (int i = 0; i < numDevices; i++) { + device[i]->LNBnr = Setup.CardUsesLNBnr[i]; + isyslog("setting device %d to use LNB %d", i, device[i]->LNBnr); + } +} +//ML-Ende + int cDevice::NextCardIndex(int n) { if (n > 0) { @@ -265,14 +285,102 @@ return (0 <= Index && Index < numDevices) ? device[Index] : NULL; } + +//ML +cDevice *cDevice::GetBadDevice(const cChannel *Channel) +{ + if (Setup.DiSEqC) { + cDiseqc *diseqc; + diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()); + + for (int i = 0; i < numDevices; i++) { + if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBsource() != (int*) diseqc) { + return device[i]; + } + } + } else { + char requiredState; + if (Channel->Frequency() >= Setup.LnbSLOF) { + requiredState = 1 ; + } else { + requiredState = 0; + } + if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2; + + for (int i = 0; i < numDevices; i++) { + if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBconf() != requiredState) { + return device[i]; + } + } + } + return NULL; +} + +int cDevice::GetMaxBadPriority(const cChannel *Channel) +{ + bool PrimaryIsBad = false; + int maxBadPriority = -2; + if (Setup.DiSEqC) { + cDiseqc *diseqc; + diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()); + + for (int i = 0; i < numDevices; i++) { + if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBsource() != (int*) diseqc) { + if (device[i]->Receiving() && device[i]->Priority() > maxBadPriority) { + maxBadPriority = device[i]->Priority(); + } + if (device[i]->IsPrimaryDevice()) { + PrimaryIsBad = true; + } + } + } + } else { + char requiredState; + if (Channel->Frequency() >= Setup.LnbSLOF) { + requiredState = 1 ; + } else { + requiredState = 0; + } + if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2; + + for (int i = 0; i < numDevices; i++) { + if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBconf() != requiredState) { + if (device[i]->Receiving() && device[i]->Priority() > maxBadPriority) { + maxBadPriority = device[i]->Priority(); + } + if (device[i]->IsPrimaryDevice()) { + PrimaryIsBad = true; + } + } + } + } + if (PrimaryIsBad && maxBadPriority == -2) { + maxBadPriority = -1; + } + return maxBadPriority; +} +//ML-Ende + cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) { cDevice *d = NULL; - int select = 8, pri; + +//ML + int select = 11, pri, pri2, badPriority; +//ML-Ende for (int i = 0; i < numDevices; i++) { bool ndr; if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job + +//ML + badPriority = device[i]->GetMaxBadPriority(Channel); + if (badPriority >= Priority || (badPriority == -1 && Priority < Setup.PrimaryLimit)) continue; + if (badPriority == -2) pri2 = 0; // not affected by LNB-sharing + else if (badPriority == -1) pri2 = 2; // primary device would need a channel switch + else pri2 = 4; // primary device would need a channel switch and is receiving with lower priority +//ML-Ende + if (device[i]->Receiving() && !ndr) pri = 0; // receiving and allows additional receivers else if (d && !device[i]->Receiving() && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel)) @@ -287,8 +395,12 @@ pri = 6; // receiving with same priority but fewer Ca's else pri = 7; // all others - if (pri < select) { - select = pri; + +//ML + if (pri + pri2 < select) { + select = pri + pri2; +//ML-Ende + d = device[i]; if (NeedsDetachReceivers) *NeedsDetachReceivers = ndr; @@ -504,6 +616,40 @@ bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView) { +//ML + cDevice *tmpDevice; + if (this->GetMaxBadPriority(Channel) >= 0) { + Skins.Message(mtInfo, tr("Channel locked by LNB!")); + return false; + } + while ((tmpDevice = GetBadDevice(Channel)) != NULL) { + if (tmpDevice->IsPrimaryDevice() ) + tmpDevice->SwitchChannelForced(Channel, true); + else + tmpDevice->SwitchChannelForced(Channel, false); + } +//ML-Ende + + if (LiveView) + isyslog("switching to channel %d", Channel->Number()); + for (int i = 3; i--;) { + + switch (SetChannel(Channel, LiveView)) { + case scrOk: return true; + case scrNotAvailable: Skins.Message(mtInfo, tr("Channel not available!")); + return false; + case scrNoTransfer: Skins.Message(mtError, tr("Can't start Transfer Mode!")); + return false; + case scrFailed: break; // loop will retry + } + esyslog("retrying"); + } + return false; +} + +//ML +bool cDevice::SwitchChannelForced(const cChannel *Channel, bool LiveView) +{ if (LiveView) isyslog("switching to channel %d", Channel->Number()); for (int i = 3; i--;) { @@ -519,6 +665,8 @@ } return false; } +//ML-Ende + bool cDevice::SwitchChannel(int Direction) { @@ -530,7 +678,10 @@ 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)) +//ML + if (PrimaryDevice()->GetMaxBadPriority(channel) < 0 && (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0))) +//ML-Ende + break; n = channel->Number() + Direction; } @@ -564,9 +715,34 @@ // If this DVB card can't receive this channel, let's see if we can // use the card that actually can receive it and transfer data from there: +//ML + char requiredState; + if (Channel->Frequency() >= Setup.LnbSLOF) { + requiredState = 1; + } else { + requiredState = 0; + } + if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2; +//ML-Ende + if (NeedsTransferMode) { cDevice *CaDevice = GetDevice(Channel, 0); if (CaDevice && CanReplay()) { + +//ML + if (CaDevice->GetLNBnr() == LNBnr) { + if (LNBstate != requiredState || (Setup.DiSEqC && LNBsource != (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization())) ) { + if (IsPrimaryDevice()) { + SetChannelDevice(Channel, true); + } else { + SetChannelDevice(Channel, false); + } + LNBstate = requiredState; + LNBsource = (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()); + } + } +//ML-Ende + 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()! cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids())); @@ -584,6 +760,12 @@ sectionHandler->SetStatus(false); sectionHandler->SetChannel(NULL); } + +//ML + LNBstate = requiredState; + LNBsource = (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()); +//ML-Ende + if (SetChannelDevice(Channel, LiveView)) { // Start section handling: if (sectionHandler) { diff -u -r vdr-1.3.23-orig/device.h vdr-1.3.23/device.h --- vdr-1.3.23-orig/device.h 2005-02-20 15:06:28.000000000 +0100 +++ vdr-1.3.23/device.h 2005-04-06 22:02:25.000000000 +0200 @@ -127,6 +127,24 @@ ///< given Priority. ///< See ProvidesChannel() for more information on how ///< priorities are handled, and the meaning of NeedsDetachReceivers. + +//ML +private: + char LNBstate; // Frequenzband und Polarisation des DVB-Empfängers +// cDiseqc *LNBsource; // can not #include "diseqc.h". A workaround follows: + int *LNBsource; // [DiSEqC] Empfangsquelle + int LNBnr; // Nummer des genutzten LNB +public: + char GetLNBconf(void) { return LNBstate; } + int *GetLNBsource(void) { return LNBsource; } + int GetLNBnr(void) { return LNBnr; } + static void SetLNBnr(void); + cDevice *GetBadDevice(const cChannel *Channel); + // Gibt ggf. eine DVB-Karte zurück, die sich mit dieser Karte den LNB teilt und deren Konfiguration unverträglich ist. + int GetMaxBadPriority(const cChannel *Channel); + // Gibt die höchte Priorität aller Aufträge/Aufnahmen mit unverträglicher LNB Konfiguration zurück. +//ML-Ende + static void Shutdown(void); ///< Closes down all devices. ///< Must be called at the end of the program. @@ -204,6 +222,13 @@ bool SwitchChannel(const cChannel *Channel, bool LiveView); ///< Switches the device to the given Channel, initiating transfer mode ///< if necessary. + +//ML + bool SwitchChannelForced(const cChannel *Channel, bool LiveView); + ///< Switches the device to the given Channel, initiating transfer mode + ///< if necessary. Forces the switch without taking care of the LNB configuration. +//ML-Ende + static bool SwitchChannel(int Direction); ///< Switches the primary device to the next available channel in the given ///< Direction (only the sign of Direction is evaluated, positive values diff -u -r vdr-1.3.23-orig/eitscan.c vdr-1.3.23/eitscan.c --- vdr-1.3.23-orig/eitscan.c 2004-10-31 17:19:49.000000000 +0100 +++ vdr-1.3.23/eitscan.c 2005-04-06 22:14:46.000000000 +0200 @@ -149,8 +149,12 @@ if (!(Device->Receiving(true) || Device->Replaying())) { const cChannel *Channel = ScanData->GetChannel(); if (Channel) { - if ((!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) && Device->ProvidesTransponder(Channel)) { - if (Device == cDevice::PrimaryDevice() && !currentChannel) { + +//ML + if ((!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) && Device->ProvidesTransponder(Channel) && (Device->GetMaxBadPriority(Channel) == -2 || (Device->GetMaxBadPriority(Channel) == -1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) ) { + if ((Device == cDevice::PrimaryDevice() || Device->GetMaxBadPriority(Channel) == -1) && !currentChannel) { +//ML-Ende + currentChannel = Device->CurrentChannel(); Skins.Message(mtInfo, "Starting EPG scan"); } diff -u -r vdr-1.3.23-orig/i18n.c vdr-1.3.23/i18n.c --- vdr-1.3.23-orig/i18n.c 2005-03-12 11:43:16.000000000 +0100 +++ vdr-1.3.23/i18n.c 2005-04-06 22:02:25.000000000 +0200 @@ -5304,6 +5304,52 @@ "ST:TNG konsool", "ST:TNG konsol", }, + +//ML + { "Channel locked by LNB!", + "Kanal durch LNB gesperrt!", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "Chaîne interdite par la LNB", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + }, + { "Setup.LNB$DVB device %d uses LNB No.", + "DVB-Empfänger %d nutzt LNB Nr.", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "La carte DVB %d utilise la LNB No.", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + }, +//ML + { NULL } }; diff -u -r vdr-1.3.23-orig/menu.c vdr-1.3.23/menu.c --- vdr-1.3.23-orig/menu.c 2005-03-20 16:14:51.000000000 +0100 +++ vdr-1.3.23/menu.c 2005-04-06 22:02:25.000000000 +0200 @@ -2038,6 +2038,16 @@ Clear(); +//ML + char tmp[30]; + if (cDevice::NumDevices() > 1) { + for (int i = 1; i <= cDevice::NumDevices(); i++) { + sprintf( tmp, tr("Setup.LNB$DVB device %d uses LNB No."), i); + Add(new cMenuEditIntItem( tmp, &data.CardUsesLNBnr[i - 1], 1, cDevice::NumDevices() )); + } + } +//ML-Ende + Add(new cMenuEditBoolItem(tr("Setup.LNB$Use DiSEqC"), &data.DiSEqC)); if (!data.DiSEqC) { Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"), &data.LnbSLOF)); @@ -2054,6 +2064,10 @@ int oldDiSEqC = data.DiSEqC; eOSState state = cMenuSetupBase::ProcessKey(Key); +//ML + if (Key == kOk) cDevice::SetLNBnr(); +//ML-Ende + if (Key != kNone && data.DiSEqC != oldDiSEqC) Setup(); return state; @@ -3134,6 +3148,21 @@ int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority; cDevice *device = cDevice::GetDevice(channel, Priority, &NeedsDetachReceivers); if (device) { + +//ML + cDevice *tmpDevice; + while ((tmpDevice = device->GetBadDevice(channel))) { + if (tmpDevice->Replaying() == false) { + Stop(tmpDevice); + if (tmpDevice->IsPrimaryDevice() ) + tmpDevice->SwitchChannelForced(channel, true); + else + tmpDevice->SwitchChannelForced(channel, false); + } else + tmpDevice->SwitchChannelForced(channel, false); + } +//ML-Ende + if (NeedsDetachReceivers) { Stop(device); if (device == cTransferControl::ReceiverDevice())