add possibility to assign CI Slots to services, provider names or caids....
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Fri, 13 Apr 2007 17:33:37 +0000 (17:33 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Fri, 13 Apr 2007 17:33:37 +0000 (17:33 +0000)
(not configurable via gui yet)

lib/dvb_ci/dvbci.cpp
lib/dvb_ci/dvbci.h
lib/python/enigma_python.i
mytest.py

index 1f1fa1663481265f1cf5b874e9f978e187197078..17754adf86505a79b38f4ab04d8b0535ee96e2d5 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <lib/base/eerror.h>
 #include <lib/base/nconfig.h> // access to python config
+#include <lib/dvb/db.h>
 #include <lib/dvb/pmt.h>
 #include <lib/dvb_ci/dvbci.h>
 #include <lib/dvb_ci/dvbci_session.h>
@@ -44,6 +45,16 @@ eDVBCIInterfaces::eDVBCIInterfaces()
                ++num_ci;
        }
 
+#if defined(DM8000)
+       setInputSource(0, TUNER_A);
+       setInputSource(1, TUNER_B);
+       setInputSource(2, TUNER_C);
+       setInputSource(3, TUNER_D);
+#else // force DM7025
+       setInputSource(0, TUNER_A);
+       setInputSource(1, TUNER_B);
+#endif
+
        eDebug("done, found %d common interface slots", num_ci);
 }
 
@@ -252,13 +263,60 @@ void eDVBCIInterfaces::recheckPMTHandlers()
                if (service)
                        caids = service->m_ca;
 
-               if (!caids.empty())
+               if (caids.empty())
+                       continue; // unscrambled service
+
+               for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
                {
-                       for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
+                       bool useThis=false;
+                       eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
+                       if (ca_manager)
                        {
-                               bool useThis=false;
-                               eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
-                               if (ca_manager)
+                               int mask=0;
+                               if (!ci_it->possible_services.empty())
+                               {
+                                       mask |= 1;
+                                       std::set<eServiceReference>::iterator it = ci_it->possible_services.find(ref);
+                                       if (it != ci_it->possible_services.end())
+                                       {
+                                               eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
+                                               useThis = true;
+                                       }
+                               }
+                               if (!useThis && !ci_it->possible_providers.empty())
+                               {
+                                       bool parent=false;
+                                       mask |= 2;
+                                       if (!service) // subservice?
+                                       {
+                                               eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
+                                               eDVBDB::getInstance()->getService(parent_ref, service);
+                                               parent=true;
+                                       }
+                                       if (service)
+                                       {
+                                               std::set<std::string>::iterator it = ci_it->possible_providers.find(service->m_provider_name);
+                                               if (it != ci_it->possible_providers.end())
+                                               {
+                                                       eDebug("'%s' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ci_it->getSlotID());
+                                                       useThis = true;
+                                               }
+                                       }
+                               }
+                               if (!useThis && !ci_it->possible_caids.empty())
+                               {
+                                       for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
+                                       {
+                                               std::set<uint16_t>::iterator it = ci_it->possible_caids.find(*ca);
+                                               if (it != ci_it->possible_caids.end())
+                                               {
+                                                       eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
+                                                       useThis=true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if (!useThis && !mask)
                                {
                                        const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
                                        for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
@@ -267,107 +325,107 @@ void eDVBCIInterfaces::recheckPMTHandlers()
                                                        std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
                                                if ( z != ci_caids.end() && *z == *ca )
                                                {
-//                                                     eDebug("found ci for caid %04x", *z);
+                                                       eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
                                                        useThis=true;
                                                        break;
                                                }
                                        }
                                }
+                       }
 
-                               if (useThis)
+                       if (useThis)
+                       {
+                               if (ci_it->use_count)  // check if this CI can descramble more than one service
                                {
-                                       if (ci_it->use_count)  // check if this CI can descramble more than one service
+                                       useThis = false;
+                                       PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
+                                       while (tmp != m_pmt_handlers.end())
                                        {
-                                               useThis = false;
-                                               PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
-                                               while (tmp != m_pmt_handlers.end())
+                                               if ( tmp->cislot == ci_it && it != tmp )
                                                {
-                                                       if ( tmp->cislot == ci_it && it != tmp )
+                                                       eServiceReferenceDVB ref2;
+                                                       tmp->pmthandler->getServiceReference(ref2);
+                                                       eDVBChannelID s1, s2;
+                                                       if (ref != ref2)
                                                        {
-                                                               eServiceReferenceDVB ref2;
-                                                               tmp->pmthandler->getServiceReference(ref2);
-                                                               eDVBChannelID s1, s2;
-                                                               if (ref != ref2)
-                                                               {
-                                                                       ref.getChannelID(s1);
-                                                                       ref2.getChannelID(s2);
-                                                               }
-                                                               if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
-                                                               {
-                                                                       useThis = true;
-                                                                       break;
-                                                               }
+                                                               ref.getChannelID(s1);
+                                                               ref2.getChannelID(s2);
+                                                       }
+                                                       if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
+                                                       {
+                                                               useThis = true;
+                                                               break;
                                                        }
-                                                       ++tmp;
                                                }
+                                               ++tmp;
                                        }
-                                       if (useThis)
+                               }
+                               if (useThis)
+                               {
+                                       // check if this CI is already assigned to this pmthandler
+                                       eDVBCISlot *tmp = it->cislot;
+                                       while(tmp)
                                        {
-                                               // check if this CI is already assigned to this pmthandler
-                                               eDVBCISlot *tmp = it->cislot;
-                                               while(tmp)
-                                               {
-                                                       if (tmp == ci_it)
-                                                               break;
-                                               }
+                                               if (tmp == ci_it)
+                                                       break;
+                                       }
 
-                                               if (tmp) // ignore already assigned cislots...
-                                                       continue;
+                                       if (tmp) // ignore already assigned cislots...
+                                               continue;
 
-                                               ++ci_it->use_count;
-//                                             eDebug("usecount now %d", ci_it->use_count);
+                                       ++ci_it->use_count;
+//                                     eDebug("usecount now %d", ci_it->use_count);
 
-                                               data_source ci_source=CI_A;
-                                               switch(ci_it->getSlotID())
-                                               {
-                                                       case 0: ci_source = CI_A; break;
-                                                       case 1: ci_source = CI_B; break;
-                                                       case 2: ci_source = CI_C; break;
-                                                       case 3: ci_source = CI_D; break;
-                                                       default:
-                                                               eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
-                                                               break;
-                                               }
+                                       data_source ci_source=CI_A;
+                                       switch(ci_it->getSlotID())
+                                       {
+                                               case 0: ci_source = CI_A; break;
+                                               case 1: ci_source = CI_B; break;
+                                               case 2: ci_source = CI_C; break;
+                                               case 3: ci_source = CI_D; break;
+                                               default:
+                                                       eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
+                                                       break;
+                                       }
 
-                                               if (!it->cislot)
+                                       if (!it->cislot)
+                                       {
+                                               int tunernum = -1;
+                                               eUsePtr<iDVBChannel> channel;
+                                               if (!pmthandler->getChannel(channel))
                                                {
-                                                       int tunernum = -1;
-                                                       eUsePtr<iDVBChannel> channel;
-                                                       if (!pmthandler->getChannel(channel))
+                                                       ePtr<iDVBFrontend> frontend;
+                                                       if (!channel->getFrontend(frontend))
                                                        {
-                                                               ePtr<iDVBFrontend> frontend;
-                                                               if (!channel->getFrontend(frontend))
-                                                               {
-                                                                       eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
-                                                                       tunernum = fe->getID();
-                                                               }
+                                                               eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
+                                                               tunernum = fe->getID();
                                                        }
-                                                       ASSERT(tunernum != -1);
-                                                       data_source tuner_source = TUNER_A;
-                                                       switch (tunernum)
-                                                       {
-                                                               case 0: tuner_source = TUNER_A; break;
-                                                               case 1: tuner_source = TUNER_B; break;
-                                                               case 2: tuner_source = TUNER_C; break;
-                                                               case 3: tuner_source = TUNER_D; break;
-                                                               default:
-                                                                       eDebug("try to get source for tuner %d!!\n", tunernum);
-                                                                       break;
-                                                       }
-                                                       ci_it->current_tuner = tunernum;
-                                                       setInputSource(tunernum, ci_source);
-                                                       ci_it->setSource(tuner_source);
                                                }
-                                               else
+                                               ASSERT(tunernum != -1);
+                                               data_source tuner_source = TUNER_A;
+                                               switch (tunernum)
                                                {
-                                                       ci_it->current_tuner = it->cislot->current_tuner;
-                                                       ci_it->linked_next = it->cislot;
-                                                       ci_it->setSource(ci_it->linked_next->current_source);
-                                                       ci_it->linked_next->setSource(ci_source);
+                                                       case 0: tuner_source = TUNER_A; break;
+                                                       case 1: tuner_source = TUNER_B; break;
+                                                       case 2: tuner_source = TUNER_C; break;
+                                                       case 3: tuner_source = TUNER_D; break;
+                                                       default:
+                                                               eDebug("try to get source for tuner %d!!\n", tunernum);
+                                                               break;
                                                }
-                                               it->cislot = ci_it;
-                                               gotPMT(pmthandler);
+                                               ci_it->current_tuner = tunernum;
+                                               setInputSource(tunernum, ci_source);
+                                               ci_it->setSource(tuner_source);
                                        }
+                                       else
+                                       {
+                                               ci_it->current_tuner = it->cislot->current_tuner;
+                                               ci_it->linked_next = it->cislot;
+                                               ci_it->setSource(ci_it->linked_next->current_source);
+                                               ci_it->linked_next->setSource(ci_source);
+                                       }
+                                       it->cislot = ci_it;
+                                       gotPMT(pmthandler);
                                }
                        }
                }
@@ -574,6 +632,155 @@ int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
        return 0;
 }
 
+PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
+{
+       eDVBCISlot *slot = getSlot(slotid);
+       if (!slot)
+       {
+               char tmp[255];
+               snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
+               PyErr_SetString(PyExc_StandardError, tmp);
+               return 0;
+       }
+       ePyObject tuple = PyTuple_New(3);
+       int caids = slot->possible_caids.size();
+       int services = slot->possible_services.size();
+       int providers = slot->possible_providers.size();
+       ePyObject caid_list = PyList_New(caids);
+       ePyObject service_list = PyList_New(services);
+       ePyObject provider_list = PyList_New(providers);
+       std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
+       while(caids)
+       {
+               --caids;
+               PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
+               ++caid_it;
+       }
+       std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
+       while(services)
+       {
+               --services;
+               PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
+               ++ref_it;
+       }
+       std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
+       while(providers)
+       {
+               --providers;
+               PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
+               ++provider_it;
+       }
+       PyTuple_SET_ITEM(tuple, 0, service_list);
+       PyTuple_SET_ITEM(tuple, 1, provider_list);
+       PyTuple_SET_ITEM(tuple, 2, caid_list);
+       return tuple;
+}
+
+const char *PyObject_TypeStr(PyObject *o)
+{
+       return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
+}
+
+RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
+{
+       eDVBCISlot *slot = getSlot(slotid);
+       if (!slot)
+       {
+               char tmp[255];
+               snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
+               PyErr_SetString(PyExc_StandardError, tmp);
+               return -1;
+       }
+       if (!PyTuple_Check(obj))
+       {
+               char tmp[255];
+               snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
+               PyErr_SetString(PyExc_StandardError, tmp);
+               return -1;
+       }
+       if (PyTuple_Size(obj) != 3)
+       {
+               const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
+                       "first argument should be a pythonlist with possible services\n"
+                       "second argument should be a pythonlist with possible providers\n"
+                       "third argument should be a pythonlist with possible caids";
+               PyErr_SetString(PyExc_StandardError, errstr);
+               return -1;
+       }
+       ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
+       ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
+       ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
+       if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
+       {
+               char errstr[512];
+               snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
+                       "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
+                       "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
+                       "third argument(%s) should be a pythonlist with possible caids (ints)",
+                       PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
+               PyErr_SetString(PyExc_StandardError, errstr);
+               return -1;
+       }
+       slot->possible_caids.clear();
+       slot->possible_services.clear();
+       slot->possible_providers.clear();
+       int size = PyList_Size(service_list);
+       while(size)
+       {
+               --size;
+               ePyObject refstr = PyList_GET_ITEM(service_list, size);
+               if (!PyString_Check(refstr))
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               char *tmpstr = PyString_AS_STRING(refstr);
+               eServiceReference ref(tmpstr);
+               if (ref.valid())
+                       slot->possible_services.insert(ref);
+               else
+                       eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
+       };
+       size = PyList_Size(provider_list);
+       while(size)
+       {
+               --size;
+               ePyObject str = PyList_GET_ITEM(provider_list, size);
+               if (!PyString_Check(str))
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               char *tmpstr = PyString_AS_STRING(str);
+               if (strlen(tmpstr))
+                       slot->possible_providers.insert(tmpstr);
+               else
+                       eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
+       };
+       size = PyList_Size(caid_list);
+       while(size)
+       {
+               --size;
+               ePyObject caid = PyList_GET_ITEM(caid_list, size);
+               if (!PyInt_Check(caid))
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               int tmpcaid = PyInt_AsLong(caid);
+               if (tmpcaid > 0 && tmpcaid < 0x10000)
+                       slot->possible_caids.insert(tmpcaid);
+               else
+                       eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
+       };
+       return 0;
+}
 
 int eDVBCISlot::send(const unsigned char *data, size_t len)
 {
@@ -687,6 +894,7 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
        {
                perror(filename);
        }
+       setSource(TUNER_A);
 }
 
 eDVBCISlot::~eDVBCISlot()
index 2f528d2de452b427aa0bb1ead682bd324bbb13e2..603fadfdac5cf475cd21f7046ddd17b3e71b9f9f 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef __dvbci_dvbci_h
 #define __dvbci_dvbci_h
 
-#include <lib/base/ebase.h>
+#ifndef SWIG
 
+#include <lib/base/ebase.h>
+#include <lib/service/iservice.h>
+#include <lib/python/python.h>
 #include <set>
 #include <queue>
 
@@ -12,6 +15,7 @@ class eDVBCICAManagerSession;
 class eDVBCIMMISession;
 class eDVBServicePMTHandler;
 class eDVBCISlot;
+class eDVBCIInterfaces;
 
 struct queueData
 {
@@ -36,26 +40,28 @@ enum data_source
 
 class eDVBCISlot: public iObject, public Object
 {
+       friend class eDVBCIInterfaces;
 DECLARE_REF(eDVBCISlot);
 private:
        int slotid;
        int fd;
-       void data(int);
        eSocketNotifier *notifier;
-
        int state;
        std::map<uint16_t, uint8_t> running_services;
        eDVBCIApplicationManagerSession *application_manager;
        eDVBCICAManagerSession *ca_manager;
        eDVBCIMMISession *mmi_session;
        std::priority_queue<queueData> sendqueue;
-public:
-       enum {stateRemoved, stateInserted, stateInvalid, stateResetted};
+       std::set<uint16_t> possible_caids;
+       std::set<eServiceReference> possible_services;
+       std::set<std::string> possible_providers;
        int use_count;
        eDVBCISlot *linked_next; // needed for linked CI handling
        data_source current_source;
        int current_tuner;
-
+       void data(int);
+public:
+       enum {stateRemoved, stateInserted, stateInvalid, stateResetted};
        eDVBCISlot(eMainloop *context, int nr);
        ~eDVBCISlot();
        
@@ -102,6 +108,8 @@ struct CIPmtHandler
 
 typedef std::list<CIPmtHandler> PMTHandlerList;
 
+#endif // SWIG
+
 class eDVBCIInterfaces
 {
 DECLARE_REF(eDVBCIInterfaces);
@@ -110,7 +118,9 @@ private:
        eSmartPtrList<eDVBCISlot> m_slots;
        eDVBCISlot *getSlot(int slotid);
        PMTHandlerList m_pmt_handlers; 
+#ifndef SWIG
 public:
+#endif
        eDVBCIInterfaces();
        ~eDVBCIInterfaces();
 
@@ -121,8 +131,6 @@ public:
        void ciRemoved(eDVBCISlot *slot);
        int getSlotState(int slot);
 
-       static eDVBCIInterfaces *getInstance();
-       
        int reset(int slot);
        int initialize(int slot);
        int startMMI(int slot);
@@ -133,6 +141,13 @@ public:
        int getMMIState(int slot);
        int sendCAPMT(int slot);
        int setInputSource(int tunerno, data_source source);
+#ifdef SWIG
+public:
+#endif
+       static eDVBCIInterfaces *getInstance();
+       int getNumOfSlots() { return m_slots.size(); }
+       PyObject *getDescrambleRules(int slotid);
+       RESULT setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) );
 };
 
 #endif
index 13eca6b4e2f8af3c6c5fd376acf28e9b08ba9302..0d559aba2ca92af27844890af18828a6f858615c 100644 (file)
@@ -90,6 +90,7 @@ is usually caused by not marking PSignals as immutable.
 #include <lib/driver/misc_options.h>
 #include <lib/driver/etimezone.h>
 #include <lib/gdi/lcd.h>
+#include <lib/dvb_ci/dvbci.h>
 #include <lib/dvb_ci/dvbci_ui.h>
 #include <lib/python/python.h>
 #include <lib/gdi/picload.h>
@@ -202,6 +203,7 @@ typedef long time_t;
 %include <lib/driver/misc_options.h>
 %include <lib/driver/etimezone.h>
 %include <lib/gdi/lcd.h>
+%include <lib/dvb_ci/dvbci.h>
 %include <lib/dvb_ci/dvbci_ui.h>
 %include <lib/dvb/db.h>
 %include <lib/python/python.h>
index 098675b60ea423334cb083faf5e999a0d0b29d2e..93c42142f84ac562f13592720a14c7a86ff557e4 100644 (file)
--- a/mytest.py
+++ b/mytest.py
@@ -451,6 +451,8 @@ class AutoScartControl:
                        else:
                                self.scartDialog.switchToTV()
 
+from enigma import eDVBCIInterfaces
+
 def runScreenTest():
        plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
 
@@ -467,6 +469,12 @@ def runScreenTest():
 
        ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
 
+#      eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
+#              ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
+#                      ["PREMIERE"], #provider_list,
+#                      [] #caid_list
+#              ));
+
        def runNextScreen(session, screensToRun, *result):
                if result:
                        quitMainloop(*result)