diff -u -N -r vdr_1.4.5_orig/device.c vdr_1.4.5_eddi_v2/device.c --- vdr_1.4.5_orig/device.c 2006-09-03 12:13:25.000000000 +0200 +++ vdr_1.4.5_eddi_v2/device.c 2007-02-10 03:02:54.000000000 +0100 @@ -18,6 +18,7 @@ #include "receiver.h" #include "status.h" #include "transfer.h" +#include "dvbdevice.h" // --- cPesAssembler --------------------------------------------------------- @@ -143,13 +144,21 @@ int cDevice::numDevices = 0; int cDevice::useDevice = 0; int cDevice::nextCardIndex = 0; +int cDevice::forceCardIndex = -1; +int cDevice::numFrontends = 0; +int cDevice::curFrontends = 0; int cDevice::currentChannel = 1; cDevice *cDevice::device[MAXDEVICES] = { NULL }; cDevice *cDevice::primaryDevice = NULL; cDevice::cDevice(void) { - cardIndex = nextCardIndex++; + esyslog("cDevice Constructor"); + + if (forceCardIndex >=0) + cardIndex = forceCardIndex; + else + cardIndex = nextCardIndex++; SetDescription("receiver on device %d", CardIndex() + 1); @@ -174,14 +183,22 @@ for (int i = 0; i < MAXRECEIVERS; i++) receiver[i] = NULL; - if (numDevices < MAXDEVICES) - device[numDevices++] = this; - else - esyslog("ERROR: too many devices!"); + if (forceCardIndex >=0) + device[cardIndex] = this; + else { + if (numDevices < MAXDEVICES) + device[numDevices++] = this; + else + esyslog("ERROR: too many devices!"); + } + esyslog("cDevice Constructor: cardIndex=%d", cardIndex); + if (forceCardIndex >=0) + forceCardIndex = -1; } cDevice::~cDevice() { + esyslog("cDevice Destructor"); Detach(player); for (int i = 0; i < MAXRECEIVERS; i++) Detach(receiver[i]); @@ -192,6 +209,7 @@ delete eitFilter; delete sectionHandler; delete pesAssembler; + esyslog("cDevice Destructor: cardIndex=%d", cardIndex); } bool cDevice::WaitForAllDevicesReady(int Timeout) @@ -282,9 +300,50 @@ { cDevice *d = NULL; uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact + + int frontend = 0, maxfrontends = 0; + + for (int i = 0; i < numDevices; i++) { bool ndr; + + maxfrontends = device[i]->GetNumFrontends(); + + +while (!d && frontend <= maxfrontends) { + esyslog("debug frontend %d numfrontend %d", frontend, maxfrontends); + + + + + if (frontend != device[i]->GetCurFrontends()) { +// esyslog("cDvbDevice::ProvidesChannel stub: stop and restart frontend adapter/frontend %d/%d", adapter, frontend); + +// esyslog("cDvbDevice::ProvidesChannel ForceCardIndex(%d)",adapter); +// ForceCardIndex(adapter); +// esyslog("cDvbDevice::ProvidesChannel delete dvbDevice[%d]",adapter); +// delete dvbDevice[adapter]; +// esyslog("cDvbDevice::ProvidesChannel dvbDevice[%d] = NULL",adapter); +// dvbDevice[adapter] = NULL; +// esyslog("cDvbDevice::ProvidesChannel new cDvbDevice(%d,%d)",adapter, frontend); +// dvbDevice[adapter] = new cDvbDevice(adapter, frontend); +// esyslog("cDvbDevice::ProvidesChannel dvbDevice[%d]->SetCurFrontends(%d);",adapter, frontend); +// dvbDevice[adapter]->SetCurFrontends(frontend); +// esyslog("cDvbDevice::ProvidesChannel ForceCardIndex(-1)"); +// ForceCardIndex(-1); + + //device[i]->ForceCardIndex(i); + esyslog("*cDevice::GetDevice delete device[%d]",i); + device[i]->ForceCardIndex(i); + delete device[i]; + new cDvbDevice(i, frontend, 1); //,true + device[i]->ForceCardIndex(-1); + } + + + if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job + esyslog("This frontend provides the channel"); // Put together an integer number that reflects the "impact" using // this device would have on the overall system. Each condition is represented // by one bit in the number (or several bits, if the condition is actually @@ -307,7 +366,10 @@ *NeedsDetachReceivers = ndr; } } + frontend++; } + } + return d; } diff -u -N -r vdr_1.4.5_orig/device.h vdr_1.4.5_eddi_v2/device.h --- vdr_1.4.5_orig/device.h 2006-06-15 11:32:48.000000000 +0200 +++ vdr_1.4.5_eddi_v2/device.h 2007-02-10 02:43:06.000000000 +0100 @@ -139,6 +139,8 @@ ///< Must be called at the end of the program. private: static int nextCardIndex; + static int forceCardIndex; + static int numFrontends, curFrontends; int cardIndex; protected: cDevice(void); @@ -165,10 +167,15 @@ ///< anything the device needs to set up when it becomes the primary ///< device (On = true) or to shut down when it no longer is the primary ///< device (On = false), it should do so in this function. + static void ForceCardIndex(int n) { forceCardIndex = n; } public: bool IsPrimaryDevice(void) const { return this == primaryDevice; } int CardIndex(void) const { return cardIndex; } ///< Returns the card index of this device (0 ... MAXDEVICES - 1). + void SetNumFrontends(int n) { numFrontends = n; esyslog("SetNumFrontends: %d", numFrontends); } + int GetNumFrontends(void) const { esyslog("GetNumFrontends: %d", numFrontends); return numFrontends; } + void SetCurFrontends(int n) { curFrontends = n; esyslog("SetCurFrontends: %d", curFrontends); } + int GetCurFrontends(void) const { esyslog("GetCurFrontends: %d", curFrontends); return curFrontends; } int DeviceNumber(void) const; ///< Returns the number of this device (0 ... numDevices). virtual int ProvidesCa(const cChannel *Channel) const; diff -u -N -r vdr_1.4.5_orig/dvbdevice.c vdr_1.4.5_eddi_v2/dvbdevice.c --- vdr_1.4.5_orig/dvbdevice.c 2006-08-14 11:38:32.000000000 +0200 +++ vdr_1.4.5_eddi_v2/dvbdevice.c 2007-02-10 03:16:41.000000000 +0100 @@ -28,7 +28,6 @@ #define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1 #define DO_MULTIPLE_RECORDINGS 1 -//#define DO_MULTIPLE_CA_CHANNELS #define DEV_VIDEO "/dev/video" #define DEV_DVB_ADAPTER "/dev/dvb/adapter" @@ -47,22 +46,25 @@ #define DVBT_TUNE_TIMEOUT 9000 //ms #define DVBT_LOCK_TIMEOUT 2000 //ms +cDvbDevice *dvbDevice; + class cDvbName { private: char buffer[PATH_MAX]; public: - cDvbName(const char *Name, int n) { - snprintf(buffer, sizeof(buffer), "%s%d/%s%d", DEV_DVB_ADAPTER, n, Name, 0); + cDvbName(const char *Name, int adapter, int frontend) { + snprintf(buffer, sizeof(buffer), "%s%d/%s%d", DEV_DVB_ADAPTER, adapter, Name, frontend); } const char *operator*() { return buffer; } }; -static int DvbOpen(const char *Name, int n, int Mode, bool ReportError = false) +static int DvbOpen(const char *Name, int adapter, int frontend, int Mode, bool ReportError = false) { - const char *FileName = *cDvbName(Name, n); + const char *FileName = *cDvbName(Name, adapter, frontend); int fd = open(FileName, Mode); if (fd < 0 && ReportError) LOG_ERROR_STR(FileName); + esyslog("DvbOpen: %s", FileName); return fd; } @@ -358,24 +360,30 @@ int cDvbDevice::devVideoOffset = -1; int cDvbDevice::setTransferModeForDolbyDigital = 1; -cDvbDevice::cDvbDevice(int n) +cDvbDevice::cDvbDevice(int adapter, int frontend, int force) { + +switch (force) { + case 0: esyslog("SetNumFrontends force %d adapter %d frontend %d", force, adapter,frontend); SetNumFrontends(frontend); //Da usare in fase di scansione se busy + break; + case 1: // esyslog("SetNumFrontends force %d adapter %d frontend %d", force, adapter,frontend); SetNumFrontends(frontend); //Da usare in fase di scansione + case 2: esyslog("SetCurfrontends force %d adapter %d frontend %d", force, adapter,frontend); SetCurFrontends(frontend); //Normale + dvbTuner = NULL; frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN spuDecoder = NULL; digitalAudio = false; playMode = pmNone; - // Devices that are present on all card types: - int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK); + fd_frontend = DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK); // Devices that are only present on cards with decoders: - fd_osd = DvbOpen(DEV_DVB_OSD, n, O_RDWR); - fd_video = DvbOpen(DEV_DVB_VIDEO, n, O_RDWR | O_NONBLOCK); - fd_audio = DvbOpen(DEV_DVB_AUDIO, n, O_RDWR | O_NONBLOCK); - fd_stc = DvbOpen(DEV_DVB_DEMUX, n, O_RDWR); + fd_osd = DvbOpen(DEV_DVB_OSD, adapter, frontend, O_RDWR); + fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK); + fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK); + fd_stc = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR); // The DVR device (will be opened and closed as needed): @@ -420,59 +428,95 @@ dvb_frontend_info feinfo; if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) { frontendType = feinfo.type; - ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, n)); + ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, adapter, frontend)); + esyslog("cDvbDevice: CardIndex=%d", CardIndex()); dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler); } else LOG_ERROR; } else - esyslog("ERROR: can't open DVB device %d", n); + esyslog("ERROR: can't open DVB adapter %d - frontend %d", adapter, frontend); StartSectionHandler(); + } + } cDvbDevice::~cDvbDevice() { + esyslog("~cDvbDevice()"); delete spuDecoder; delete dvbTuner; + close(fd_stc); + close(fd_audio); + close(fd_video); + close(fd_osd); + close(fd_frontend); + Cancel(1); // We're not explicitly closing any device files here, since this sometimes // caused segfaults. Besides, the program is about to terminate anyway... } -bool cDvbDevice::Probe(const char *FileName) +int cDvbDevice::Probe(const char *FileName) { if (access(FileName, F_OK) == 0) { dsyslog("probing %s", FileName); int f = open(FileName, O_RDONLY); if (f >= 0) { close(f); - return true; } else if (errno != ENODEV && errno != EINVAL) LOG_ERROR_STR(FileName); } else if (errno != ENOENT) LOG_ERROR_STR(FileName); - return false; + return errno; } bool cDvbDevice::Initialize(void) { int found = 0; - int i; + int i, j, rc = 0; for (i = 0; i < MAXDVBDEVICES; i++) { + dvbDevice = NULL; + j = 0; + while (rc != ENOENT) { if (UseDevice(NextCardIndex())) { - if (Probe(*cDvbName(DEV_DVB_FRONTEND, i))) { - new cDvbDevice(i); - found++; - } - else - break; + rc = Probe(*cDvbName(DEV_DVB_FRONTEND, i ,j)); + switch (rc) { + case 0: +//dvbDevice[i] = +// new cDvbDevice(i,j); + dvbDevice = new cDvbDevice(i,j,2); +// dvbDevice[i]->SetNumFrontends(j); +// dvbDevice[i]->SetCurFrontends(j); + found++; + break; + case EBUSY: // we have a frontend that can't work in shared mode + + if (dvbDevice) + dvbDevice->SetNumFrontends(j); +// ForceCardIndex(); +// new cDvbDevice(i,j,0); +// ForceCardIndex(-1); + esyslog("cDvbDevice::Initialize: WARNING %d - Device or resource busy", rc); + // we have a frontend that can't work in shared mode + break; + case ENOENT: esyslog("cDvbDevice::Initialize: Device %d have %d frontends", i, j); + break; + default: +//dvbDevice[i] = NULL; + esyslog("cDvbDevice::Initialize: %d", rc); + break; } + } else NextCardIndex(1); // skips this one - } + j++; + } + } + NextCardIndex(MAXDVBDEVICES - i); // skips the rest if (found > 0) isyslog("found %d video device%s", found, found > 1 ? "s" : ""); @@ -668,7 +712,9 @@ memset(&pesFilterParams, 0, sizeof(pesFilterParams)); if (On) { if (Handle->handle < 0) { - Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), O_RDWR | O_NONBLOCK, true); + esyslog("SetPid: CardIndex=%d", CardIndex()); +// Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK, true); + Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK, true); if (Handle->handle < 0) { LOG_ERROR; return false; @@ -705,7 +751,8 @@ int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) { - const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex()); +// const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends()); + const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex(), GetCurFrontends()); int f = open(FileName, O_RDWR | O_NONBLOCK); if (f >= 0) { dmx_sct_filter_params sctFilterParams; @@ -798,6 +845,7 @@ } if (NeedsDetachReceivers) *NeedsDetachReceivers = needsDetachReceivers; + return result; } @@ -834,8 +882,6 @@ if (TurnOffLivePIDs) TurnOffLiveMode(LiveView); - // Set the tuner: - dvbTuner->Set(Channel, DoTune); // If this channel switch was requested by the EITScanner we don't wait for @@ -954,8 +1000,10 @@ { if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) { // reopen the devices - fd_video = DvbOpen(DEV_DVB_VIDEO, CardIndex(), O_RDWR | O_NONBLOCK); - fd_audio = DvbOpen(DEV_DVB_AUDIO, CardIndex(), O_RDWR | O_NONBLOCK); +// fd_video = DvbOpen(DEV_DVB_VIDEO, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK); +// fd_audio = DvbOpen(DEV_DVB_AUDIO, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK); + fd_video = DvbOpen(DEV_DVB_VIDEO, CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK); + fd_audio = DvbOpen(DEV_DVB_AUDIO, CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK); SetVideoFormat(Setup.VideoFormat); } @@ -1183,7 +1231,8 @@ bool cDvbDevice::OpenDvr(void) { CloseDvr(); - fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), O_RDONLY | O_NONBLOCK, true); +// fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDONLY | O_NONBLOCK, true); + fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), GetCurFrontends(), O_RDONLY | O_NONBLOCK, true); if (fd_dvr >= 0) tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1); return fd_dvr >= 0; diff -u -N -r vdr_1.4.5_orig/dvbdevice.h vdr_1.4.5_eddi_v2/dvbdevice.h --- vdr_1.4.5_orig/dvbdevice.h 2006-05-28 17:05:19.000000000 +0200 +++ vdr_1.4.5_eddi_v2/dvbdevice.h 2007-02-09 23:10:44.000000000 +0100 @@ -20,6 +20,7 @@ #endif #define MAXDVBDEVICES 4 +//#define MAXDVBFRONTENDS 4 class cDvbTuner; @@ -27,7 +28,7 @@ class cDvbDevice : public cDevice { private: - static bool Probe(const char *FileName); + static int Probe(const char *FileName); ///< Probes for existing DVB devices. public: static bool Initialize(void); @@ -36,11 +37,11 @@ ///< \return True if any devices are available. private: fe_type_t frontendType; - int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc; + int fd_frontend, fd_osd, fd_audio, fd_video, fd_dvr, fd_stc; protected: virtual void MakePrimaryDevice(bool On); public: - cDvbDevice(int n); + cDvbDevice(int adapter, int frontend, int force); virtual ~cDvbDevice(); virtual bool Ready(void); virtual int ProvidesCa(const cChannel *Channel) const;