ose no more used frontends and re-open on demand
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Tue, 6 Dec 2005 22:15:38 +0000 (22:15 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Tue, 6 Dec 2005 22:15:38 +0000 (22:15 +0000)
lib/dvb/dvb.cpp
lib/dvb/dvb.h
lib/dvb/frontend.cpp
lib/dvb/frontend.h
lib/dvb/sec.cpp

index 8feb3c184f4094293bd07c14f4d3d6ec75f686bc..b1e8ad54d96e361de1669d637eede1384d36d139 100644 (file)
@@ -18,12 +18,12 @@ DEFINE_REF(eDVBAllocatedFrontend);
 
 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
 {
 
 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
 {
-       m_fe->m_inuse++;
+       m_fe->inc_use();
 }
 
 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
 {
 }
 
 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
 {
-       --m_fe->m_inuse;
+       m_fe->dec_use();
 }
 
 DEFINE_REF(eDVBAllocatedDemux);
 }
 
 DEFINE_REF(eDVBAllocatedDemux);
@@ -200,8 +200,6 @@ void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
 
                if (!adapter->getFrontend(frontend, i))
                {
 
                if (!adapter->getFrontend(frontend, i))
                {
-                       frontend->setTone(iDVBFrontend::toneOff);
-                       frontend->setVoltage(iDVBFrontend::voltageOff);
                        frontend->setSEC(m_sec);
                        m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
                }
                        frontend->setSEC(m_sec);
                        m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
                }
index ac5946cd6d9dcd0a91eeedd4d94957e4a7fa44ec..71c6a6c1b5e6e391934ba4ab57a26ff5da81d456 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __dvb_dvb_h
 #define __dvb_dvb_h
 
 #ifndef __dvb_dvb_h
 #define __dvb_dvb_h
 
+#include <lib/base/ebase.h>
 #include <lib/dvb/idvb.h>
 #include <lib/dvb/demux.h>
 #include <lib/dvb/frontend.h>
 #include <lib/dvb/idvb.h>
 #include <lib/dvb/demux.h>
 #include <lib/dvb/frontend.h>
@@ -14,14 +15,35 @@ class eDVBChannel;
           (and how to deallocate it). */
 class iDVBAdapter;
 
           (and how to deallocate it). */
 class iDVBAdapter;
 
-class eDVBRegisteredFrontend: public iObject
+class eDVBRegisteredFrontend: public iObject, public Object
 {
 {
-DECLARE_REF(eDVBRegisteredFrontend);
+       DECLARE_REF(eDVBRegisteredFrontend);
+       eTimer *disable;
+       void closeFrontend()
+       {
+               if (!m_inuse)
+                       m_frontend->closeFrontend();
+       }
 public:
 public:
+       eDVBRegisteredFrontend(eDVBFrontend *fe, iDVBAdapter *adap)
+               :disable(new eTimer(eApp)), m_adapter(adap), m_frontend(fe), m_inuse(0)
+       {
+               disable = new eTimer(eApp);
+               CONNECT(disable->timeout, eDVBRegisteredFrontend::closeFrontend);
+       }
+       void dec_use()
+       {
+               if (!--m_inuse)
+                       disable->start(3000, true);
+       }
+       void inc_use()
+       {
+               if (++m_inuse == 1)
+                       m_frontend->openFrontend();
+       }
        iDVBAdapter *m_adapter;
        ePtr<eDVBFrontend> m_frontend;
        int m_inuse;
        iDVBAdapter *m_adapter;
        ePtr<eDVBFrontend> m_frontend;
        int m_inuse;
-       eDVBRegisteredFrontend(eDVBFrontend *fe, iDVBAdapter *adap): m_adapter(adap), m_frontend(fe), m_inuse(0) { }
 };
 
 struct eDVBRegisteredDemux
 };
 
 struct eDVBRegisteredDemux
index a26f6bd85b36dffacf0246b57c34ba91f40230ac..1cafcec40fc2aa6809aa7df1c74c6859f967968e 100644 (file)
@@ -208,102 +208,149 @@ RESULT eDVBFrontendParameters::getHash(unsigned long &hash) const
 
 DEFINE_REF(eDVBFrontend);
 
 
 DEFINE_REF(eDVBFrontend);
 
-eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok): m_type(-1), m_fe(fe), m_curVoltage(-1)
+eDVBFrontend::eDVBFrontend(int adap, int fe, int &ok)
+       :m_type(-1), m_fe(fe), m_timeout(0), m_tuneTimer(0), m_fd(-1)
+#if HAVE_DVB_API_VERSION < 3
+       ,m_secfd(-1)
+#endif
 {
 #if HAVE_DVB_API_VERSION < 3
 {
 #if HAVE_DVB_API_VERSION < 3
-       char sec_filename[128];
+       sprintf(m_sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
 #endif
 #endif
-       char filename[128];
+       sprintf(m_filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
+
+       m_timeout = new eTimer(eApp);
+       CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
+
+       m_tuneTimer = new eTimer(eApp);
+       CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
+
+       int entries = sizeof(m_data) / sizeof(int);
+       for (int i=0; i<entries; ++i)
+               m_data[i] = -1;
 
 
-       int result;
+       ok = !openFrontend();
+       closeFrontend();
+}
+
+int eDVBFrontend::openFrontend()
+{
+       if (m_fd >= 0)
+               return -1;  // already opened
 
 
-       m_sn = 0;
-       m_timeout = 0;
+       m_state=0;
+       m_curVoltage=voltageOff;
+       m_tuning=0;
 
 #if HAVE_DVB_API_VERSION < 3
 
 #if HAVE_DVB_API_VERSION < 3
-       sprintf(sec_filename, "/dev/dvb/card%d/sec%d", adap, fe);
-       m_secfd = ::open(sec_filename, O_RDWR);
+       m_secfd = ::open(m_sec_filename, O_RDWR);
        if (m_secfd < 0)
        {
        if (m_secfd < 0)
        {
-               eWarning("failed! (%s) %m", sec_filename);
-               ok = 0;
-               return;
+               eWarning("failed! (%s) %m", m_sec_filename);
+               return -1;
        }
        FrontendInfo fe_info;
        }
        FrontendInfo fe_info;
-       sprintf(filename, "/dev/dvb/card%d/frontend%d", adap, fe);
 #else
 #else
-       dvb_frontend_info fe_info;      
-       sprintf(filename, "/dev/dvb/adapter%d/frontend%d", adap, fe);
+       dvb_frontend_info fe_info;
 #endif
 #endif
-       eDebug("opening frontend.");
-       m_fd = ::open(filename, O_RDWR|O_NONBLOCK);
+       eDebug("opening frontend %d", m_fe);
+       m_fd = ::open(m_filename, O_RDWR|O_NONBLOCK);
        if (m_fd < 0)
        {
        if (m_fd < 0)
        {
-               eWarning("failed! (%s) %m", filename);
-               ok = 0;
-               return;
-       }
-
-       result = ::ioctl(m_fd, FE_GET_INFO, &fe_info);
-       
-       if (result < 0) {
-               eWarning("ioctl FE_GET_INFO failed");
-               ::close(m_fd);
-               m_fd = -1;
-               ok = 0;
-               return;
+               eWarning("failed! (%s) %m", m_filename);
+#if HAVE_DVB_API_VERSION < 3
+               ::close(m_secfd);
+               m_secfd=-1;
+#endif
+               return -1;
        }
 
        }
 
-       switch (fe_info.type) 
+       if (m_type == -1)
        {
        {
-       case FE_QPSK:
-               m_type = feSatellite;
-               break;
-       case FE_QAM:
-               m_type = feCable;
-               break;
-       case FE_OFDM:
-               m_type = feTerrestrial;
-               break;
-       default:
-               eWarning("unknown frontend type.");
-               ::close(m_fd);
-               m_fd = -1;
-               ok = 0;
-               return;
+               if (::ioctl(m_fd, FE_GET_INFO, &fe_info) < 0)
+               {
+                       eWarning("ioctl FE_GET_INFO failed");
+                       ::close(m_fd);
+                       m_fd = -1;
+#if HAVE_DVB_API_VERSION < 3
+                       ::close(m_secfd);
+                       m_secfd=-1;
+#endif
+                       return -1;
+               }
+
+               switch (fe_info.type)
+               {
+               case FE_QPSK:
+                       m_type = iDVBFrontend::feSatellite;
+                       break;
+               case FE_QAM:
+                       m_type = iDVBFrontend::feCable;
+                       break;
+               case FE_OFDM:
+                       m_type = iDVBFrontend::feTerrestrial;
+                       break;
+               default:
+                       eWarning("unknown frontend type.");
+                       ::close(m_fd);
+                       m_fd = -1;
+#if HAVE_DVB_API_VERSION < 3
+                       ::close(m_secfd);
+                       m_secfd=-1;
+#endif
+                       return -1;
+               }
+               eDebug("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
        }
        }
-       eDebug("detected %s frontend", "satellite\0cable\0    terrestrial"+fe_info.type*10);
-       ok = 1;
+
+       setTone(iDVBFrontend::toneOff);
+       setVoltage(iDVBFrontend::voltageOff);
 
        m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
        CONNECT(m_sn->activated, eDVBFrontend::feEvent);
        m_sn->start();
 
 
        m_sn = new eSocketNotifier(eApp, m_fd, eSocketNotifier::Read);
        CONNECT(m_sn->activated, eDVBFrontend::feEvent);
        m_sn->start();
 
-       m_timeout = new eTimer(eApp);
-       CONNECT(m_timeout->timeout, eDVBFrontend::timeout);
-
-       m_tuneTimer = new eTimer(eApp);
-       CONNECT(m_tuneTimer->timeout, eDVBFrontend::tuneLoop);
-
-       int entries = sizeof(m_data) / sizeof(int);
-       for (int i=0; i<entries; ++i)
-               m_data[i] = -1;
-
-//     m_data[7] = !m_fe;
+       return 0;
+}
 
 
-//     eDebug("m_data[7] = %d %d", m_data[7], m_fe);
+void eDVBFrontend::closeFrontend()
+{
+       if (!m_fe && m_data[7] != -1)
+       {
+               // try to close the first frontend.. but the second is linked to the first
+               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*)m_data[7];
+               if (linked_fe->m_inuse)
+               {
+                       eDebug("dont close frontend %d until the linked frontend %d is still in use",
+                               m_fe, linked_fe->m_frontend->getID());
+                       return;
+               }
+       }
+       eDebug("close frontend %d", m_fe);
+       if (m_fd >= 0)
+       {
+               ::close(m_fd);
+               m_fd=-1;
+       }
+#if HAVE_DVB_API_VERSION < 3
+       if (m_secfd >= 0)
+       {
+               ::close(m_secfd);
+               m_secfd=-1;
+       }
+#endif
+       delete m_sn;
+       m_sn=0;
 
 
-       return;
+       setTone(iDVBFrontend::toneOff);
+       setVoltage(iDVBFrontend::voltageOff);
 }
 
 eDVBFrontend::~eDVBFrontend()
 {
 }
 
 eDVBFrontend::~eDVBFrontend()
 {
-       if (m_fd >= 0)
-               ::close(m_fd);
-       if (m_sn)
-               delete m_sn;
-       if (m_timeout)
-               delete m_timeout;
+       closeFrontend();
+       delete m_timeout;
+       delete m_tuneTimer;
 }
 
 void eDVBFrontend::feEvent(int w)
 }
 
 void eDVBFrontend::feEvent(int w)
@@ -609,7 +656,7 @@ void eDVBFrontend::tuneLoop()  // called by m_tuneTimer
 
 void eDVBFrontend::setFrontend()
 {
 
 void eDVBFrontend::setFrontend()
 {
-       eDebug("setting frontend..\n");
+       eDebug("setting frontend %d", m_fe);
        if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
        {
                perror("FE_SET_FRONTEND failed");
        if (ioctl(m_fd, FE_SET_FRONTEND, &parm) == -1)
        {
                perror("FE_SET_FRONTEND failed");
@@ -684,7 +731,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                parm.frequency = feparm.frequency * 1000;
                parm.u.qam.symbol_rate = feparm.symbol_rate;
 #endif
                parm.frequency = feparm.frequency * 1000;
                parm.u.qam.symbol_rate = feparm.symbol_rate;
 #endif
-               fe_modulation_t mod;
+               fe_modulation_t mod=QAM_AUTO;
                switch (feparm.modulation)
                {
                case eDVBFrontendParametersCable::Modulation::QAM16:
                switch (feparm.modulation)
                {
                case eDVBFrontendParametersCable::Modulation::QAM16:
@@ -739,7 +786,7 @@ RESULT eDVBFrontend::tune(const iDVBFrontendParameters &where)
                        break;
                }
                
                        break;
                }
                
-               fe_code_rate_t fec_inner;
+               fe_code_rate_t fec_inner=FEC_AUTO;
                switch (feparm.fec_inner)
                {               
                case eDVBFrontendParametersCable::FEC::fNone:
                switch (feparm.fec_inner)
                {               
                case eDVBFrontendParametersCable::FEC::fNone:
@@ -907,6 +954,8 @@ RESULT eDVBFrontend::connectStateChange(const Slot1<void,iDVBFrontend*> &stateCh
 
 RESULT eDVBFrontend::setVoltage(int voltage)
 {
 
 RESULT eDVBFrontend::setVoltage(int voltage)
 {
+       if (m_type != feSatellite)
+               return -1;
 #if HAVE_DVB_API_VERSION < 3
        secVoltage vlt;
 #else
 #if HAVE_DVB_API_VERSION < 3
        secVoltage vlt;
 #else
@@ -917,6 +966,8 @@ RESULT eDVBFrontend::setVoltage(int voltage)
        switch (voltage)
        {
        case voltageOff:
        switch (voltage)
        {
        case voltageOff:
+               for (int i=0; i < 3; ++i)  // reset diseqc
+                       m_data[i]=-1;
                vlt = SEC_VOLTAGE_OFF;
                break;
        case voltage13:
                vlt = SEC_VOLTAGE_OFF;
                break;
        case voltage13:
@@ -943,6 +994,8 @@ RESULT eDVBFrontend::getState(int &state)
 
 RESULT eDVBFrontend::setTone(int t)
 {
 
 RESULT eDVBFrontend::setTone(int t)
 {
+       if (m_type != feSatellite)
+               return -1;
 #if HAVE_DVB_API_VERSION < 3
        secToneMode_t tone;
 #else
 #if HAVE_DVB_API_VERSION < 3
        secToneMode_t tone;
 #else
index 8da0829c84ba30cc7731b58297940d1c80ecf9cf..7862e2eac4c47881b6bca80c5748dc4c7fa721e3 100644 (file)
@@ -40,9 +40,12 @@ class eDVBFrontend: public iDVBFrontend, public Object
        int m_type;
        int m_fe;
        int m_fd;
        int m_type;
        int m_fe;
        int m_fd;
+       char m_filename[128];
 #if HAVE_DVB_API_VERSION < 3
        int m_secfd;
 #if HAVE_DVB_API_VERSION < 3
        int m_secfd;
+       char m_secfilename[128];
 #endif
 #endif
+
        FRONTENDPARAMETERS parm;
        int m_state;
        Signal1<void,iDVBFrontend*> m_stateChanged;
        FRONTENDPARAMETERS parm;
        int m_state;
        Signal1<void,iDVBFrontend*> m_stateChanged;
@@ -93,10 +96,11 @@ public:
        RESULT setData(int num, int val);
 
        int readFrontendData(int type); // bitErrorRate, signalPower, signalQuality
        RESULT setData(int num, int val);
 
        int readFrontendData(int type); // bitErrorRate, signalPower, signalQuality
-
        int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm);
        int isCompatibleWith(ePtr<iDVBFrontendParameters> &feparm);
-       
        int getID() { return m_fe; }
        int getID() { return m_fe; }
+
+       int openFrontend();
+       void closeFrontend();
 };
 
 #endif
 };
 
 #endif
index 4842945c8c16e84dbf8525f7dcfb7d7ac0dcc5c6..ab5d6397fcba617081c9467ad1d951fedb6c50b9 100644 (file)
@@ -163,27 +163,17 @@ int eDVBSatelliteEquipmentControl::canTune(const eDVBFrontendParametersSatellite
 
                                if (linked_to != -1)  // check for linked tuners..
                                {
 
                                if (linked_to != -1)  // check for linked tuners..
                                {
-                                       bool found=false;
-                                       eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
-                                       for (; it != m_avail_frontends.end(); ++it)
-                                               if ( !linked_to )
-                                               {
-                                                       found=true;
-                                                       break;
-                                               }
-                                               else
-                                                       --linked_to;
-
-                                       if (found && it->m_inuse)
+                                       eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_to;
+                                       if (linked_fe->m_inuse)
                                        {
                                                int ocsw = -1,
                                                        oucsw = -1,
                                                        oToneburst = -1,
                                                        oRotorPos = -1;
                                        {
                                                int ocsw = -1,
                                                        oucsw = -1,
                                                        oToneburst = -1,
                                                        oRotorPos = -1;
-                                               it->m_frontend->getData(0, ocsw);
-                                               it->m_frontend->getData(1, oucsw);
-                                               it->m_frontend->getData(2, oToneburst);
-                                               it->m_frontend->getData(6, oRotorPos);
+                                               linked_fe->m_frontend->getData(0, ocsw);
+                                               linked_fe->m_frontend->getData(1, oucsw);
+                                               linked_fe->m_frontend->getData(2, oToneburst);
+                                               linked_fe->m_frontend->getData(6, oRotorPos);
 #if 0
                                                eDebug("compare csw %02x == lcsw %02x",
                                                        csw, ocsw);
 #if 0
                                                eDebug("compare csw %02x == lcsw %02x",
                                                        csw, ocsw);
@@ -251,19 +241,10 @@ RESULT eDVBSatelliteEquipmentControl::prepare(iDVBFrontend &frontend, FRONTENDPA
 
                        if (linked_to != -1)
                        {
 
                        if (linked_to != -1)
                        {
-                               bool found=false;
-                               eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin());
-                               for (; it != m_avail_frontends.end(); ++it)
-                                       if ( !linked_to )
-                                       {
-                                               found=true;
-                                               break;
-                                       }
-                                       else
-                                               --linked_to;
-                               if (found && it->m_inuse)
+                               eDVBRegisteredFrontend *linked_fe = (eDVBRegisteredFrontend*) linked_to;
+                               if (linked_fe->m_inuse)
                                {
                                {
-                                       eDebug("[SEC] frontend is linked with another one and the other is in use.. so we dont do SEC!!");
+                                       eDebug("[SEC] frontend is linked with another and the other one is in use.. so we dont do SEC!!");
                                        linked=true;
                                }
                        }
                                        linked=true;
                                }
                        }
@@ -911,27 +892,20 @@ RESULT eDVBSatelliteEquipmentControl::setTunerLinked(int tu1, int tu2)
        if (tu1 == tu2)
                return -1;
 
        if (tu1 == tu2)
                return -1;
 
-       eDVBFrontend *p1=NULL, *p2=NULL;
-       int tmp1=tu1, tmp2=tu2;
+       eDVBRegisteredFrontend *p1=NULL, *p2=NULL;
 
 
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it)
+       int cnt=0;
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_avail_frontends.begin()); it != m_avail_frontends.end(); ++it, ++cnt)
        {
        {
-               if ( !tmp1 )
-                       p1 = it->m_frontend;
-               else
-                       --tmp1;
-               if (!tmp2)
-                       p2 = it->m_frontend;
-               else
-                       --tmp2;
+               if (cnt == tu1)
+                       p1 = *it;
+               else if (cnt == tu2)
+                       p2 = *it;
        }
        if (p1 && p2)
        {
        }
        if (p1 && p2)
        {
-               p1->setData(7, tu2);
-               p1->setTone(iDVBFrontend::toneOff);
-               p1->setVoltage(iDVBFrontend::voltageOff);
-
-               p2->setData(7, tu1);
+               p1->m_frontend->setData(7, (int)p2);  // this is evil..
+               p2->m_frontend->setData(7, (int)p1);
                return 0;
        }
        return -1;
                return 0;
        }
        return -1;