From 75db34c299094d2ae87941ed464e8efa79848e16 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Sat, 20 May 2006 00:21:50 +0000 Subject: [PATCH] many changes for better CI handling - the CI is now working on both tuners - the CI is no more blocked by freetv services - add multi services support (on same transponder) (yet hardcoded for Alphacrypt only) - fix bluescreen in CI MMI dialog when pressin ok/left/right --- lib/dvb/db.cpp | 69 ++++-- lib/dvb/epgcache.cpp | 2 +- lib/dvb/idvb.h | 14 +- lib/dvb/pmt.cpp | 101 +++------ lib/dvb/pmt.h | 7 +- lib/dvb/scan.cpp | 28 +-- lib/dvb/scan.h | 2 +- lib/dvb_ci/dvbci.cpp | 418 ++++++++++++++++++++++++------------ lib/dvb_ci/dvbci.h | 33 ++- lib/dvb_ci/dvbci_appmgr.cpp | 7 +- lib/dvb_ci/dvbci_camgr.cpp | 7 +- lib/dvb_ci/dvbci_session.h | 10 +- lib/dvb_ci/dvbci_ui.cpp | 128 ++++++----- lib/dvb_ci/dvbci_ui.h | 18 +- lib/python/Screens/Ci.py | 13 +- lib/service/servicedvb.cpp | 2 +- 16 files changed, 525 insertions(+), 334 deletions(-) diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index 9b2324a6..a9f58c0f 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -114,21 +114,13 @@ RESULT eBouquet::setListName(const std::string &name) } eDVBService::eDVBService() - :m_flags(0) + :m_cache(0), m_flags(0) { - memset(m_cache, -1, sizeof(m_cache)); } eDVBService::~eDVBService() { -} - -bool eDVBService::cacheEmpty() -{ - for (int i=0; i < cacheMax; ++i) - if (m_cache[i] != -1) - return false; - return true; + delete [] m_cache; } eDVBService &eDVBService::operator=(const eDVBService &s) @@ -137,8 +129,8 @@ eDVBService &eDVBService::operator=(const eDVBService &s) m_service_name_sort = s.m_service_name_sort; m_provider_name = s.m_provider_name; m_flags = s.m_flags; -// m_ca = s.m_ca; - memcpy(m_cache, s.m_cache, sizeof(m_cache)); + m_ca = s.m_ca; + copyCache(s.m_cache); return *this; } @@ -232,15 +224,47 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ return res; } +bool eDVBService::cacheEmpty() +{ + if (m_cache) + for (int i=0; i < cacheMax; ++i) + if (m_cache[i] != -1) + return false; + return true; +} + +void eDVBService::initCache() +{ + m_cache = new int[cacheMax]; + memset(m_cache, -1, sizeof(int) * cacheMax); +} + +void eDVBService::copyCache(int *source) +{ + if (source) + { + if (!m_cache) + m_cache = new int[cacheMax]; + memcpy(m_cache, source, cacheMax * sizeof(int)); + } + else + { + delete [] m_cache; + m_cache = 0; + } +} + int eDVBService::getCacheEntry(cacheID id) { - if (id >= cacheMax) + if (id >= cacheMax || !m_cache) return -1; return m_cache[id]; } void eDVBService::setCacheEntry(cacheID id, int pid) { + if (!m_cache) + initCache(); if (id < cacheMax) m_cache[id] = pid; } @@ -426,13 +450,13 @@ void eDVBDB::reloadServicelist() { int cid, val; sscanf(v.c_str(), "%02d%04x", &cid, &val); - s->m_cache[cid]=val; - }/* else if (p == 'C') + s->setCacheEntry(cid,val); + } else if (p == 'C') { int val; sscanf(v.c_str(), "%04x", &val); - s->m_ca.insert(val); - }*/ + s->m_ca.push_front((uint16_t)val); + } } addService(ref, s); } @@ -517,15 +541,16 @@ void eDVBDB::saveServicelist() // write cached pids for (int x=0; x < eDVBService::cacheMax; ++x) - if (i->second->m_cache[x] != -1) - fprintf(f, ",c:%02d%04x", x, i->second->m_cache[x]); + { + int entry = i->second->getCacheEntry(x); + if (entry != -1) + fprintf(f, ",c:%02d%04x", x, entry); + } -/* // write cached ca pids - for (std::set::const_iterator ca(i->second->m_ca.begin()); + for (CAID_LIST::const_iterator ca(i->second->m_ca.begin()); ca != i->second->m_ca.end(); ++ca) fprintf(f, ",C:%04x", *ca); -*/ if (i->second->m_flags) fprintf(f, ",f:%x", i->second->m_flags); diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index ee61268c..b04bdd89 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -2118,7 +2118,7 @@ void eEPGCache::PMTready(eDVBServicePMTHandler *pmthandler) if (tmp==3) { eServiceReferenceDVB ref; - if (!pmthandler->getService(ref)) + if (!pmthandler->getServiceReference(ref)) { int pid = (*es)->getPid(); messages.send(Message(Message::got_private_pid, ref, pid)); diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index 8b86866e..8bbbaafa 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -18,6 +18,14 @@ #include #include +#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ == 4 ) // check if gcc version >= 3.1 +#include +#define CAID_LIST __gnu_cxx::slist +#else +#include +#define CAID_LIST std::slist +#endif + struct eBouquet { std::string m_bouquet_name; @@ -220,6 +228,9 @@ class eDVBChannelQuery; class eDVBService: public iStaticServiceInformation { DECLARE_REF(eDVBService); + int *m_cache; + void initCache(); + void copyCache(int *source); public: enum cacheID { @@ -250,9 +261,8 @@ public: bool usePMT() const { return !(m_flags & dxNoDVB); } -// std::set m_ca; + CAID_LIST m_ca; - int m_cache[cacheMax]; virtual ~eDVBService(); eDVBService &operator=(const eDVBService &); diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 0cdebebf..4d48f86e 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -85,9 +85,9 @@ void eDVBServicePMTHandler::PMTready(int error) { serviceEvent(eventNewProgramInfo); eEPGCache::getInstance()->PMTready(this); - if (!m_pvr_channel) + if (!m_pvr_channel) // don't send campmt to camd.socket for playbacked services { - if(!m_ca_servicePtr) // don't send campmt to camd.socket for playbacked services + if(!m_ca_servicePtr) { int demuxes[2] = {0,0}; uint8_t tmp; @@ -98,9 +98,10 @@ void eDVBServicePMTHandler::PMTready(int error) else demuxes[1]=demuxes[0]; eDVBCAService::register_service(m_reference, demuxes, m_ca_servicePtr); - eDVBCIInterfaces::getInstance()->addPMTHandler(this); + eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); } - eDVBCIInterfaces::getInstance()->gotPMT(this); + else + eDVBCIInterfaces::getInstance()->gotPMT(this); } if (m_ca_servicePtr) { @@ -140,70 +141,21 @@ PyObject *eDVBServicePMTHandler::getCaIds() { PyObject *ret=0; - ePtr > ptr; + program prog; - if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr)) + if ( !getProgramInfo(prog) ) { - uint16_t caids[255]; - memset(caids, 0, sizeof(caids)); - std::vector::const_iterator i = ptr->getSections().begin(); - for (; i != ptr->getSections().end(); ++i) - { - const ProgramMapSection &pmt = **i; - ElementaryStreamInfoConstIterator es = pmt.getEsInfo()->begin(); - for (; es != pmt.getEsInfo()->end(); ++es) - { - for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); - desc != (*es)->getDescriptors()->end(); ++desc) - { - switch ((*desc)->getTag()) - { - case CA_DESCRIPTOR: - { - const CaDescriptor *cadescr = (const CaDescriptor*)*desc; - uint16_t caid = cadescr->getCaSystemId(); - int idx=0; - while (caids[idx] && caids[idx] != caid) - ++idx; - caids[idx]=caid; - break; - } - } - } - } - for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); - desc != pmt.getDescriptors()->end(); ++desc) - { - switch ((*desc)->getTag()) - { - case CA_DESCRIPTOR: - { - const CaDescriptor *cadescr = (const CaDescriptor*)*desc; - uint16_t caid = cadescr->getCaSystemId(); - int idx=0; - while (caids[idx] && caids[idx] != caid) - ++idx; - caids[idx]=caid; - break; - } - } - } - } - int cnt=0; - while (caids[cnt]) - ++cnt; + int cnt=prog.caids.size(); if (cnt) { ret=PyList_New(cnt); + std::set::iterator it(prog.caids.begin()); while(cnt--) - PyList_SET_ITEM(ret, cnt, PyInt_FromLong(caids[cnt])); + PyList_SET_ITEM(ret, cnt, PyInt_FromLong(*it++)); } } - if (!ret) - ret=PyList_New(0); - - return ret; + return ret ? ret : PyList_New(0); } int eDVBServicePMTHandler::getProgramInfo(struct program &program) @@ -213,7 +165,6 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) program.videoStreams.clear(); program.audioStreams.clear(); program.pcrPid = -1; - program.isCrypted = false; program.pmtPid = -1; program.textPid = -1; program.audioChannel = m_service ? m_service->getCacheEntry(eDVBService::cACHANNEL) : -1; @@ -243,7 +194,7 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { - int isaudio = 0, isvideo = 0, cadescriptors = 0; + int isaudio = 0, isvideo = 0; videoStream video; audioStream audio; audio.component_tag=-1; @@ -317,9 +268,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); break; case CA_DESCRIPTOR: - ++cadescriptors; + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program.caids.insert(descr->getCaSystemId()); break; } + } } break; } @@ -346,22 +300,15 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) } else continue; - if ( cadescriptors > 0 ) - program.isCrypted=true; } - if ( !program.isCrypted ) + for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); + desc != pmt.getDescriptors()->end(); ++desc) { - for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); - desc != pmt.getDescriptors()->end(); ++desc) + if ((*desc)->getTag() == CA_DESCRIPTOR) { - switch ((*desc)->getTag()) - { - case CA_DESCRIPTOR: - program.isCrypted=true; - break; - } + CaDescriptor *descr = (CaDescriptor*)(*desc); + program.caids.insert(descr->getCaSystemId()); } - break; } } return 0; @@ -410,6 +357,9 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) ++cnt; program.textPid = tpid; } + CAID_LIST &caids = m_service->m_ca; + for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it) + program.caids.insert(*it); if ( cnt ) return 0; } @@ -499,6 +449,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, ref.getChannelID(chid); res = m_resourceManager->allocateChannel(chid, m_channel); eDebug("allocate Channel: res %d", res); + eDVBCIInterfaces::getInstance()->addPMTHandler(this); } else { eDVBMetaParser parser; @@ -549,7 +500,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, if (ref.path.empty()) { delete m_dvb_scan; - m_dvb_scan = new eDVBScan(m_channel); + m_dvb_scan = new eDVBScan(m_channel, false); m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); } } else diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index f4e99a57..57176d1f 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -117,11 +117,11 @@ public: { std::vector videoStreams; std::vector audioStreams; - // ca info + std::set caids; int pcrPid; int pmtPid; int textPid; - bool isCrypted; + bool isCrypted() { return !caids.empty(); } int audioChannel; }; @@ -131,7 +131,8 @@ public: PyObject *getCaIds(); int getPVRChannel(ePtr &pvr_channel); - int getService(eServiceReferenceDVB &service) { service = m_reference; return 0; } + int getServiceReference(eServiceReferenceDVB &service) { service = m_reference; return 0; } + int getService(ePtr &service) { service = m_service; return 0; } int getPMT(ePtr > &ptr) { return m_PMT.getCurrent(ptr); } int getChannel(eUsePtr &channel); diff --git a/lib/dvb/scan.cpp b/lib/dvb/scan.cpp index 3bfbe571..6549e32c 100644 --- a/lib/dvb/scan.cpp +++ b/lib/dvb/scan.cpp @@ -15,17 +15,18 @@ #include #include #include -#include -#define SCAN_eDebug(x...) eDebug(x) -#define SCAN_eDebugNoNewLine(x...) eDebugNoNewLine(x) +static bool scan_debug; +#define SCAN_eDebug(x...) if (scan_debug) eDebug(x) +#define SCAN_eDebugNoNewLine(x...) if (scan_debug) eDebugNoNewLine(x) DEFINE_REF(eDVBScan); -eDVBScan::eDVBScan(iDVBChannel *channel) - :m_channel(channel), m_ready(0), m_flags(0), m_ready_all(readySDT) - ,m_channel_state(iDVBChannel::state_idle) +eDVBScan::eDVBScan(iDVBChannel *channel, bool debug) + :m_channel(channel), m_channel_state(iDVBChannel::state_idle) + ,m_ready(0), m_ready_all(readySDT), m_flags(0) { + scan_debug=debug; if (m_channel->getDemux(m_demux)) SCAN_eDebug("scan: failed to allocate demux!"); m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection); @@ -100,10 +101,10 @@ RESULT eDVBScan::nextChannel() if (m_ch_toScan.empty()) { -// SCAN_eDebug("no channels left to scan."); -// SCAN_eDebug("%d channels scanned, %d were unavailable.", -// m_ch_scanned.size(), m_ch_unavailable.size()); -// SCAN_eDebug("%d channels in database.", m_new_channels.size()); + SCAN_eDebug("no channels left to scan."); + SCAN_eDebug("%d channels scanned, %d were unavailable.", + m_ch_scanned.size(), m_ch_unavailable.size()); + SCAN_eDebug("%d channels in database.", m_new_channels.size()); m_event(evtFinish); return -ENOENT; } @@ -528,7 +529,8 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags) dvb_service->m_service_name_sort = service->second->m_service_name_sort; } dvb_service->m_provider_name = service->second->m_provider_name; - + if (service->second->m_ca.size()) + dvb_service->m_ca = service->second->m_ca; if (!dontRemoveOldFlags) // do not remove new found flags when not wished dvb_service->m_flags &= ~eDVBService::dxNewFound; } @@ -580,7 +582,6 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str()); break; } -/* case CA_IDENTIFIER_DESCRIPTOR: { CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc; @@ -589,12 +590,11 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i) { SCAN_eDebugNoNewLine("%04x ", *i); - service->m_ca.insert(*i); + service->m_ca.push_front(*i); } SCAN_eDebug(""); break; } -*/ default: SCAN_eDebug("descr<%x>", (*desc)->getTag()); break; diff --git a/lib/dvb/scan.h b/lib/dvb/scan.h index 1fc55e0f..fe5e0686 100644 --- a/lib/dvb/scan.h +++ b/lib/dvb/scan.h @@ -65,7 +65,7 @@ private: int m_flags; public: - eDVBScan(iDVBChannel *channel); + eDVBScan(iDVBChannel *channel, bool debug=false); ~eDVBScan(); enum { scanNetworkSearch = 1, scanSearchBAT = 2, scanRemoveServices = 4, scanDontRemoveFeeds=8 }; diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp index 7d96a296..1be4232e 100644 --- a/lib/dvb_ci/dvbci.cpp +++ b/lib/dvb_ci/dvbci.cpp @@ -74,6 +74,7 @@ int eDVBCIInterfaces::reset(int slotid) return -1; eDVBCISession::deleteSessions(slot); + ciRemoved(slot); return slot->reset(); } @@ -86,28 +87,25 @@ int eDVBCIInterfaces::enableTS(int slotid, int enable) return -1; int tunernum = 0; - if (enable) + PMTHandlerList::iterator it = m_pmt_handlers.begin(); + while (it != m_pmt_handlers.end()) { - PMTHandlerList::iterator it = m_pmt_handlers.begin(); - while (it != m_pmt_handlers.end()) + if ( it->cislot == slot ) { - if ( it->cislot == slot ) + eDVBServicePMTHandler *pmthandler = it->pmthandler; + eUsePtr channel; + if (!pmthandler->getChannel(channel)) { - eDVBServicePMTHandler *pmthandler = it->pmthandler; - eUsePtr channel; - if (!pmthandler->getChannel(channel)) + ePtr frontend; + if (!channel->getFrontend(frontend)) { - ePtr frontend; - if (!channel->getFrontend(frontend)) - { - eDVBFrontend *fe = (eDVBFrontend*) &(*frontend); - tunernum = fe->getID(); - } + eDVBFrontend *fe = (eDVBFrontend*) &(*frontend); + tunernum = fe->getID(); } - break; } - ++it; + break; } + ++it; } return slot->enableTS(enable, tunernum); } @@ -119,19 +117,9 @@ int eDVBCIInterfaces::initialize(int slotid) if( (slot = getSlot(slotid)) == 0 ) return -1; - slot->resetPrevSentCAPMTVersion(); - PMTHandlerList::iterator it = m_pmt_handlers.begin(); - while (it != m_pmt_handlers.end()) - { - if ( it->cislot == slot ) - { - slot->sendCAPMT(it->pmthandler); // send capmt - break; - } - ++it; - } + slot->removeService(); - return slot->initialize(); + return sendCAPMT(slotid); } int eDVBCIInterfaces::sendCAPMT(int slotid) @@ -141,19 +129,15 @@ int eDVBCIInterfaces::sendCAPMT(int slotid) if( (slot = getSlot(slotid)) == 0 ) return -1; - slot->resetPrevSentCAPMTVersion(); PMTHandlerList::iterator it = m_pmt_handlers.begin(); while (it != m_pmt_handlers.end()) { if ( it->cislot == slot ) - { slot->sendCAPMT(it->pmthandler); // send capmt - return 0; - } ++it; } - return -1; + return 0; } int eDVBCIInterfaces::startMMI(int slotid) @@ -206,44 +190,147 @@ int eDVBCIInterfaces::cancelEnq(int slotid) return slot->cancelEnq(); } -void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler) +void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot) { - CIPmtHandler new_handler(pmthandler); - - eServiceReferenceDVB service; - pmthandler->getService(service); - - eDebug("[eDVBCIInterfaces] addPMTHandler %s", service.toString().c_str()); - - // HACK the first service get the CI.. - eSmartPtrList::iterator ci_it(m_slots.begin()); - for (; ci_it != m_slots.end(); ++ci_it) + for (PMTHandlerList::iterator it(m_pmt_handlers.begin()); + it != m_pmt_handlers.end(); ++it) { - if (ci_it->use_count) - continue; - ci_it->use_count=1; - new_handler.cislot = ci_it; - new_handler.cislot->resetPrevSentCAPMTVersion(); + if (it->cislot == slot) + { + eServiceReferenceDVB ref; + it->pmthandler->getServiceReference(ref); + slot->removeService(ref.getServiceID().get()); + if (!--slot->use_count) + enableTS(slot->getSlotID(), 0); + it->cislot=0; + } } +} - if (ci_it == m_slots.end()) +void eDVBCIInterfaces::recheckPMTHandlers() +{ +// eDebug("recheckPMTHAndlers()"); + for (PMTHandlerList::iterator it(m_pmt_handlers.begin()); + it != m_pmt_handlers.end(); ++it) { - PMTHandlerList::iterator it = m_pmt_handlers.begin(); - while (it != m_pmt_handlers.end()) + CAID_LIST caids; + ePtr service; + eServiceReferenceDVB ref; + eDVBServicePMTHandler *pmthandler = it->pmthandler; + eDVBServicePMTHandler::program p; + + pmthandler->getServiceReference(ref); + pmthandler->getService(service); + if (!pmthandler->getProgramInfo(p)) { - eServiceReferenceDVB ref; - it->pmthandler->getService(ref); - if ( service == ref && it->cislot ) + int cnt=0; + for (std::set::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt) + caids.push_front(*x); + if (service && cnt) + service->m_ca = caids; + } + + if (it->cislot) + continue; // already running + + if (service) + caids = service->m_ca; + + if (!caids.empty()) + { + for (eSmartPtrList::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it) { - new_handler.cislot = it->cislot; - ++new_handler.cislot->use_count; - break; + if (ci_it->getState() == eDVBCISlot::stateInvalid) + ci_it->reset(); + + bool useThis=false; + eDVBCICAManagerSession *ca_manager = ci_it->getCAManager(); + if (ca_manager) + { + const std::vector &ci_caids = ca_manager->getCAIDs(); + for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca) + { + std::vector::const_iterator z = + std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca); + if ( z != ci_caids.end() && *z == *ca ) + { + eDebug("found ci for caid %04x", *z); + useThis=true; + break; + } + } + } + + if (useThis) + { + bool send_ca_pmt = false; + if (ci_it->use_count) // check if this CI can descramble more than one service + { + PMTHandlerList::iterator tmp = m_pmt_handlers.begin(); + while (tmp != m_pmt_handlers.end()) + { + if ( tmp->cislot ) + { + bool canHandleMultipleServices=false; + eServiceReferenceDVB ref2; + tmp->pmthandler->getServiceReference(ref2); + eDVBChannelID s1, s2; + if (ref != ref2) + { + ref.getChannelID(s1); + ref2.getChannelID(s2); + // FIXME .. build a "ci can handle multiple services" config entry + // Yes / No / Auto + if ( eDVBCI_UI::getInstance()->getAppName(ci_it->getSlotID()) == "AlphaCrypt" ) + { + canHandleMultipleServices = true; + eDebug("Alphacrypt can handle multiple services"); + } + } + if (ref == ref2 || (s1 == s2 && canHandleMultipleServices) ) + { + it->cislot = tmp->cislot; + ++it->cislot->use_count; + send_ca_pmt = true; +// eDebug("usecount now %d", it->cislot->use_count); + break; + } + } + ++tmp; + } + } + else + { + ci_it->use_count=1; + it->cislot = ci_it; +// eDebug("usecount now %d", it->cislot->use_count); + enableTS(ci_it->getSlotID(), 1); + send_ca_pmt = true; + } + if (send_ca_pmt) + gotPMT(pmthandler); + } } - ++it; } } +} + +void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler) +{ + // check if this pmthandler is already registered + PMTHandlerList::iterator it = m_pmt_handlers.begin(); + while (it != m_pmt_handlers.end()) + { + if ( *it++ == pmthandler ) + return; + } + + eServiceReferenceDVB ref; + pmthandler->getServiceReference(ref); + eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str()); - m_pmt_handlers.push_back(new_handler); + m_pmt_handlers.push_back(CIPmtHandler(pmthandler)); + recheckPMTHandlers(); } void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) @@ -252,41 +339,52 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) if (it != m_pmt_handlers.end()) { eDVBCISlot *slot = it->cislot; -// eDVBServicePMTHandler *pmthandler = it->pmthandler; + eDVBServicePMTHandler *pmthandler = it->pmthandler; m_pmt_handlers.erase(it); - if (slot && !--slot->use_count) + + eServiceReferenceDVB service_to_remove; + pmthandler->getServiceReference(service_to_remove); + + bool sameServiceExist=false; + for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i) { -#if 0 - eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt"); - std::vector caids; - caids.push_back(0xFFFF); - slot->resetPrevSentCAPMTVersion(); - slot->sendCAPMT(pmthandler, caids); -#endif - // check if another service is running - it = m_pmt_handlers.begin(); - while (it != m_pmt_handlers.end()) + eServiceReferenceDVB ref; + i->pmthandler->getServiceReference(ref); + if ( ref == service_to_remove ) { - if ( !it->cislot ) - { - it->cislot = slot; - ++slot->use_count; - slot->resetPrevSentCAPMTVersion(); - slot->sendCAPMT(it->pmthandler); - break; - } - ++it; + sameServiceExist=true; + break; } } + + if (slot && !sameServiceExist) + { + if (slot->getNumOfServices() > 1) // fixme make it dependend of "ci can handle more than one service" + { + eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt", + service_to_remove.toString().c_str()); + std::vector caids; + caids.push_back(0xFFFF); + slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service + } + slot->removeService(service_to_remove.getServiceID().get()); + } + + if (slot && !--slot->use_count) + { + ASSERT(!slot->getNumOfServices()); + enableTS(slot->getSlotID(),0); + } } + // check if another service is waiting for the CI + recheckPMTHandlers(); } void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler) { eDebug("[eDVBCIInterfaces] gotPMT"); PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler); - eServiceReferenceDVB service; - if ( it != m_pmt_handlers.end() && it->cislot) + if (it != m_pmt_handlers.end() && it->cislot) it->cislot->sendCAPMT(pmthandler); } @@ -302,29 +400,41 @@ int eDVBCIInterfaces::getMMIState(int slotid) int eDVBCISlot::send(const unsigned char *data, size_t len) { - int res; + int res=0; //int i; //printf("< "); //for(i=0;isetRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write); + if (res < 0 || (unsigned int)res != len) + { + unsigned char *d = new unsigned char[len]; + memcpy(d, data, len); + sendqueue.push( queueData(d, len) ); + notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write); + } return res; } void eDVBCISlot::data(int what) { + if (state == stateInvalid) + return; if(what == eSocketNotifier::Priority) { if(state != stateRemoved) { state = stateRemoved; - enableTS(0); printf("ci removed\n"); + while(sendqueue.size()) + { + delete [] sendqueue.top().data; + sendqueue.pop(); + } + eDVBCIInterfaces::getInstance()->ciRemoved(this); eDVBCISession::deleteSessions(this); notifier->setRequested(eSocketNotifier::Read); //HACK @@ -333,36 +443,42 @@ void eDVBCISlot::data(int what) return; } - __u8 data[4096]; - int r; - r = ::read(fd, data, 4096); - if(state != stateInserted) { - state = stateInserted; eDebug("ci inserted"); - - //HACK + state = stateInserted; +// HACK eDVBCI_UI::getInstance()->setState(0,1); - + notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority); /* enable PRI to detect removal or errors */ - notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Write); } - if(r > 0) { - //int i; - //printf("> "); - //for(i=0;isetRequested(eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Write); - return; + if (what & eSocketNotifier::Read) { + __u8 data[4096]; + int r; + r = ::read(fd, data, 4096); + if(r > 0) { +// int i; +// printf("> "); +// for(i=0;isetRequested(eSocketNotifier::Read | eSocketNotifier::Priority); + else if (what & eSocketNotifier::Write) { + if (!sendqueue.empty()) { + const queueData &qe = sendqueue.top(); + int res = ::write(fd, qe.data, qe.len); + if (res >= 0 && (unsigned int)res == qe.len) + { + delete [] qe.data; + sendqueue.pop(); + } } + else + notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority); } } @@ -384,22 +500,22 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr) fd = ::open(filename, O_RDWR | O_NONBLOCK); eDebug("eDVBCISlot has fd %d", fd); - - state = stateInserted; + state = stateInvalid; if (fd >= 0) { - notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority); + notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write); CONNECT(notifier->activated, eDVBCISlot::data); } else { perror(filename); } + + enableTS(0, 0); } eDVBCISlot::~eDVBCISlot() { - enableTS(0); } void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session ) @@ -426,16 +542,22 @@ int eDVBCISlot::reset() { printf("edvbcislot: reset requested\n"); - enableTS(0); + if (state == stateInvalid) + { + unsigned char buf[256]; + eDebug("ci flush"); + while(::read(fd, buf, 256)>0); + state = stateResetted; + } - ioctl(fd, 0); + while(sendqueue.size()) + { + delete [] sendqueue.top().data; + sendqueue.pop(); + } - return 0; -} + ioctl(fd, 0); -int eDVBCISlot::initialize() -{ - printf("edvbcislot: initialize()\n"); return 0; } @@ -513,18 +635,34 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vectorgetSpec(table_spec); int pmt_version = table_spec.version & 0x1F; // just 5 bits - if ( pmt_version == prev_sent_capmt_version ) + + eServiceReferenceDVB ref; + pmthandler->getServiceReference(ref); + uint16_t program_number = ref.getServiceID().get(); + std::map::iterator it = + running_services.find(program_number); + + if ( it != running_services.end() && + (pmt_version == it->second) && + !(caids.size() == 1 && caids[0] == 0xFFFF) ) { eDebug("[eDVBCISlot] dont sent self capmt version twice"); return -1; } + std::vector::const_iterator i=ptr->getSections().begin(); if ( i == ptr->getSections().end() ) return -1; else { unsigned char raw_data[2048]; - CaProgramMapSection capmt(*i++, prev_sent_capmt_version != 0xFF ? 0x05 /*update*/ : 0x03 /*only*/, 0x01, caids ); + +// eDebug("send %s capmt for service %04x", +// it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD", +// program_number); + + CaProgramMapSection capmt(*i++, + it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids ); while( i != ptr->getSections().end() ) { // eDebug("append"); @@ -552,22 +690,39 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vectorsendCAPMT(raw_data + hlen, wp - hlen); - prev_sent_capmt_version = pmt_version; + running_services[program_number] = pmt_version; } } return 0; } +void eDVBCISlot::removeService(uint16_t program_number) +{ + if (program_number == 0xFFFF) + running_services.clear(); // remove all + else + running_services.erase(program_number); // remove single service +} + int eDVBCISlot::enableTS(int enable, int tuner) { - printf("eDVBCISlot::enableTS(%d %d)\n", enable, tuner); +// printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); +// printf("eDVBCISlot::enableTS(%d %d)\n", enable, tuner); FILE *input0, *input1, *ci; if((input0 = fopen("/proc/stb/tsmux/input0", "wb")) == NULL) { @@ -593,9 +748,4 @@ int eDVBCISlot::enableTS(int enable, int tuner) return 0; } -void eDVBCISlot::resendCAPMT() -{ - eDVBCIInterfaces::getInstance()->sendCAPMT(slotid); -} - eAutoInitP0 init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots"); diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h index e8f30ab6..2ef70b0e 100644 --- a/lib/dvb_ci/dvbci.h +++ b/lib/dvb_ci/dvbci.h @@ -4,6 +4,7 @@ #include #include +#include class eDVBCISession; class eDVBCIApplicationManagerSession; @@ -12,6 +13,22 @@ class eDVBCIMMISession; class eDVBServicePMTHandler; class eDVBCISlot; +struct queueData +{ + __u8 prio; + unsigned char *data; + unsigned int len; + queueData( unsigned char *data, unsigned int len, __u8 prio = 0 ) + :prio(prio), data(data), len(len) + { + + } + bool operator < ( const struct queueData &a ) const + { + return prio < a.prio; + } +}; + class eDVBCISlot: public iObject, public Object { DECLARE_REF(eDVBCISlot); @@ -22,12 +39,13 @@ private: eSocketNotifier *notifier; int state; - enum {stateRemoved, stateInserted}; - uint8_t prev_sent_capmt_version; + std::map running_services; eDVBCIApplicationManagerSession *application_manager; eDVBCICAManagerSession *ca_manager; eDVBCIMMISession *mmi_session; + std::priority_queue sendqueue; public: + enum {stateRemoved, stateInserted, stateInvalid, stateResetted}; int use_count; eDVBCISlot(eMainloop *context, int nr); @@ -43,19 +61,18 @@ public: eDVBCIMMISession *getMMIManager() { return mmi_session; } eDVBCICAManagerSession *getCAManager() { return ca_manager; } + int getState() { return state; } int getSlotID(); int reset(); - int initialize(); int startMMI(); int stopMMI(); int answerText(int answer); int answerEnq(char *value); int cancelEnq(); int getMMIState(); - void resendCAPMT(); int sendCAPMT(eDVBServicePMTHandler *ptr, const std::vector &caids=std::vector()); - uint8_t getPrevSentCAPMTVersion() const { return prev_sent_capmt_version; } - void resetPrevSentCAPMTVersion() { prev_sent_capmt_version = 0xFF; } + void removeService(uint16_t program_number=0xFFFF); + int getNumOfServices() { return running_services.size(); } int enableTS(int enable, int tuner=0); @@ -84,7 +101,7 @@ class eDVBCIInterfaces DECLARE_REF(eDVBCIInterfaces); static eDVBCIInterfaces *instance; private: - eSmartPtrList m_slots; + eSmartPtrList m_slots; eDVBCISlot *getSlot(int slotid); PMTHandlerList m_pmt_handlers; @@ -94,7 +111,9 @@ public: void addPMTHandler(eDVBServicePMTHandler *pmthandler); void removePMTHandler(eDVBServicePMTHandler *pmthandler); + void recheckPMTHandlers(); void gotPMT(eDVBServicePMTHandler *pmthandler); + void ciRemoved(eDVBCISlot *slot); static eDVBCIInterfaces *getInstance(); diff --git a/lib/dvb_ci/dvbci_appmgr.cpp b/lib/dvb_ci/dvbci_appmgr.cpp index 28e0659d..201b36c4 100644 --- a/lib/dvb_ci/dvbci_appmgr.cpp +++ b/lib/dvb_ci/dvbci_appmgr.cpp @@ -46,9 +46,10 @@ int eDVBCIApplicationManagerSession::receivedAPDU(const unsigned char *tag,const for (int i = 0; i < dl; ++i) printf("%c", ((unsigned char*)data)[i+6]); printf("\n"); - - eDVBCI_UI::getInstance()->setState(0,2); - eDVBCI_UI::getInstance()->setAppName(0,str); + + eDVBCI_UI::getInstance()->setState(slot->getSlotID(), 2); + + eDVBCI_UI::getInstance()->setAppName(slot->getSlotID(), str); break; } default: diff --git a/lib/dvb_ci/dvbci_camgr.cpp b/lib/dvb_ci/dvbci_camgr.cpp index e1afd174..ef69ed4d 100644 --- a/lib/dvb_ci/dvbci_camgr.cpp +++ b/lib/dvb_ci/dvbci_camgr.cpp @@ -31,8 +31,9 @@ int eDVBCICAManagerSession::receivedAPDU(const unsigned char *tag, const void *d printf("%04x ", (((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1])); caids.push_back((((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1])); } + std::sort(caids.begin(), caids.end()); printf("\n"); - slot->resendCAPMT(); + eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); break; default: printf("unknown APDU tag 9F 80 %02x\n", tag[2]); @@ -64,8 +65,8 @@ int eDVBCICAManagerSession::sendCAPMT(unsigned char *data, int len) { const unsigned char tag[3]={0x9F, 0x80, 0x32}; // ca_pmt - sendAPDU(tag, data, len); - + sendAPDU(tag, data, len); + return 0; } diff --git a/lib/dvb_ci/dvbci_session.h b/lib/dvb_ci/dvbci_session.h index cf69ca9a..ae0d340d 100644 --- a/lib/dvb_ci/dvbci_session.h +++ b/lib/dvb_ci/dvbci_session.h @@ -11,9 +11,9 @@ class eDVBCISession { DECLARE_REF(eDVBCISession); static ePtr sessions[SLMS]; - static void eDVBCISession::deleteSessions(const eDVBCISlot *slot); - static void eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr &ptr); - static void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag,const void *data, int len, unsigned short session_nb, const void *apdu=0,int alen=0); + static void deleteSessions(const eDVBCISlot *slot); + static void createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr &ptr); + static void sendSPDU(eDVBCISlot *slot, unsigned char tag,const void *data, int len, unsigned short session_nb, const void *apdu=0,int alen=0); static void sendOpenSessionResponse(eDVBCISlot *slot,unsigned char session_status, const unsigned char *resource_identifier,unsigned short session_nb); void recvCreateSessionResponse(const unsigned char *data); void recvCloseSessionRequest(const unsigned char *data); @@ -24,8 +24,8 @@ protected: eDVBCISlot *slot; //base only unsigned short session_nb; virtual int receivedAPDU(const unsigned char *tag, const void *data, int len) = 0; - void eDVBCISession::sendAPDU(const unsigned char *tag, const void *data=0,int len=0); - void eDVBCISession::sendSPDU(unsigned char tag, const void *data, int len,const void *apdu=0, int alen=0); + void sendAPDU(const unsigned char *tag, const void *data=0,int len=0); + void sendSPDU(unsigned char tag, const void *data, int len,const void *apdu=0, int alen=0); virtual int doAction()=0; void handleClose(); public: diff --git a/lib/dvb_ci/dvbci_ui.cpp b/lib/dvb_ci/dvbci_ui.cpp index 4ff047de..ddb42fdb 100644 --- a/lib/dvb_ci/dvbci_ui.cpp +++ b/lib/dvb_ci/dvbci_ui.cpp @@ -11,23 +11,28 @@ #include #include -eDVBCI_UI *eDVBCI_UI::instance = 0; +eDVBCI_UI *eDVBCI_UI::instance; eDVBCI_UI::eDVBCI_UI() - :mmiScreen(NULL) - ,mmiTuplePos(0) - ,mmiScreenReady(0) { ASSERT(!instance); instance = this; - for(int i=0;ienableTS(slot, 1); + if (slot < MAX_SLOTS) + slotdata[slot].state = newState; } std::string eDVBCI_UI::getAppName(int slot) { - return appName; + if (slot < MAX_SLOTS) + return slotdata[slot].appName; + return ""; } void eDVBCI_UI::setAppName(int slot, const char *name) { - //printf("set name to -%c-\n", name); - appName = name; + if (slot < MAX_SLOTS) + slotdata[slot].appName = name; } void eDVBCI_UI::setInit(int slot) { - eDVBCIInterfaces::getInstance()->sendCAPMT(slot); + eDVBCIInterfaces::getInstance()->initialize(slot); } void eDVBCI_UI::setReset(int slot) @@ -81,12 +88,6 @@ int eDVBCI_UI::stopMMI(int slot) return 0; } -int eDVBCI_UI::initialize(int slot) -{ - eDVBCIInterfaces::getInstance()->initialize(slot); - return 0; -} - int eDVBCI_UI::answerMenu(int slot, int answer) { eDVBCIInterfaces::getInstance()->answerText(slot, answer); @@ -107,20 +108,27 @@ int eDVBCI_UI::cancelEnq(int slot) int eDVBCI_UI::availableMMI(int slot) { - return mmiScreenReady; + if (slot < MAX_SLOTS) + return slotdata[slot].mmiScreenReady; + return false; } int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text) { - mmiScreenReady = 0; + if (slot >= MAX_SLOTS) + return 0; - if(mmiScreen) - Py_DECREF(mmiScreen); - mmiScreen = PyList_New(2); + slot_ui_data &data = slotdata[slot]; + + data.mmiScreenReady = 0; + + if (data.mmiScreen) + Py_DECREF(data.mmiScreen); + data.mmiScreen = PyList_New(2); PyObject *tuple = PyTuple_New(1); PyTuple_SET_ITEM(tuple, 0, PyString_FromString("ENQ")); - PyList_SET_ITEM(mmiScreen, 0, tuple); + PyList_SET_ITEM(data.mmiScreen, 0, tuple); tuple = PyTuple_New(4); PyTuple_SET_ITEM(tuple, 0, PyString_FromString("PIN")); @@ -128,47 +136,58 @@ int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text) PyTuple_SET_ITEM(tuple, 2, PyString_FromString(text)); PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(blind)); - PyList_SET_ITEM(mmiScreen, 1, tuple); + PyList_SET_ITEM(data.mmiScreen, 1, tuple); - mmiScreenReady = 1; + data.mmiScreenReady = 1; return 0; } int eDVBCI_UI::mmiScreenBegin(int slot, int listmenu) { + if (slot >= MAX_SLOTS) + return 0; + printf("eDVBCI_UI::mmiScreenBegin\n"); - mmiScreenReady = 0; + slot_ui_data &data = slotdata[slot]; - if(mmiScreen) - Py_DECREF(mmiScreen); - mmiScreen = PyList_New(1); + data.mmiScreenReady = 0; + + if (data.mmiScreen) + Py_DECREF(data.mmiScreen); + + data.mmiScreen = PyList_New(1); PyObject *tuple = PyTuple_New(1); - if(listmenu == 0) //menu + if (listmenu == 0) //menu PyTuple_SET_ITEM(tuple, 0, PyString_FromString("MENU")); else //list PyTuple_SET_ITEM(tuple, 0, PyString_FromString("LIST")); - PyList_SET_ITEM(mmiScreen, 0, tuple); + PyList_SET_ITEM(data.mmiScreen, 0, tuple); - mmiTuplePos = 1; + data.mmiTuplePos = 1; return 0; } int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value) { - eDebug("eDVBCI_UI::mmiScreenAddText(%s)",value); + if (slot >= MAX_SLOTS) + return 0; + + eDebug("eDVBCI_UI::mmiScreenAddText(%s)",value ? value : ""); + + slot_ui_data &data = slotdata[slot]; PyObject *tuple = PyTuple_New(3); - if(type == 0) //title + if (type == 0) //title PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TITLE")); - else if(type == 1) //subtitle + else if (type == 1) //subtitle PyTuple_SET_ITEM(tuple, 0, PyString_FromString("SUBTITLE")); - else if(type == 2) //bottom + else if (type == 2) //bottom PyTuple_SET_ITEM(tuple, 0, PyString_FromString("BOTTOM")); else PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TEXT")); @@ -177,12 +196,12 @@ int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value) PyTuple_SET_ITEM(tuple, 1, PyString_FromString(value)); - if(type > 2) + if (type > 2) PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(type-2)); else PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(-1)); - PyList_Append(mmiScreen, tuple); + PyList_Append(data.mmiScreen, tuple); Py_DECREF(tuple); return 0; @@ -190,10 +209,11 @@ int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value) int eDVBCI_UI::mmiScreenFinish(int slot) { - printf("eDVBCI_UI::mmiScreenFinish\n"); - - mmiScreenReady = 1; - + if (slot < MAX_SLOTS) + { + printf("eDVBCI_UI::mmiScreenFinish\n"); + slotdata[slot].mmiScreenReady = 1; + } return 0; } @@ -204,11 +224,15 @@ int eDVBCI_UI::getMMIState(int slot) PyObject *eDVBCI_UI::getMMIScreen(int slot) { - if(mmiScreenReady) + if (slot < MAX_SLOTS) { - mmiScreenReady = 0; - Py_INCREF(mmiScreen); - return mmiScreen; + slot_ui_data &data = slotdata[slot]; + if (data.mmiScreenReady) + { + data.mmiScreenReady = 0; + Py_INCREF(data.mmiScreen); + return data.mmiScreen; + } } Py_INCREF(Py_None); return Py_None; diff --git a/lib/dvb_ci/dvbci_ui.h b/lib/dvb_ci/dvbci_ui.h index 4f23974e..3db215fa 100644 --- a/lib/dvb_ci/dvbci_ui.h +++ b/lib/dvb_ci/dvbci_ui.h @@ -7,16 +7,21 @@ #define _POSIX_C_SOURCE 200112L #include -#define MAX_SLOTS 2 +#define MAX_SLOTS 4 -class eDVBCI_UI +struct slot_ui_data { - int state[MAX_SLOTS]; - static eDVBCI_UI *instance; std::string appName; + int state; PyObject *mmiScreen; int mmiTuplePos; int mmiScreenReady; +}; + +class eDVBCI_UI +{ + static eDVBCI_UI *instance; + slot_ui_data slotdata[MAX_SLOTS]; #ifdef SWIG eDVBCI_UI(); ~eDVBCI_UI(); @@ -27,14 +32,13 @@ public: ~eDVBCI_UI(); #endif static eDVBCI_UI *getInstance(); - + int getState(int slot); void setState(int slot, int state); std::string getAppName(int slot); void setAppName(int slot, const char *name); void setInit(int slot); void setReset(int slot); - int initialize(int slot); int startMMI(int slot); int stopMMI(int slot); int availableMMI(int slot); @@ -44,7 +48,7 @@ public: int answerEnq(int slot, char *val); int cancelEnq(int slot); - PyObject *eDVBCI_UI::getMMIScreen(int slot); + PyObject *getMMIScreen(int slot); int mmiScreenEnq(int slot, int blind, int answerLen, char *text); int mmiScreenBegin(int slot, int listmenu); diff --git a/lib/python/Screens/Ci.py b/lib/python/Screens/Ci.py index 01df7947..a32ce344 100644 --- a/lib/python/Screens/Ci.py +++ b/lib/python/Screens/Ci.py @@ -124,14 +124,20 @@ class CiMmi(Screen): else: print "give cancel action to ci" + def keyConfigEntry(self, key): + try: + self["entries"].handleKey(key) + except AttributeError: + pass + def keyNumberGlobal(self, number): - self["entries"].handleKey(config.key[str(number)]) + self.keyConfigEntry(config.key[str(number)]) def keyLeft(self): - self["entries"].handleKey(config.key["prevElement"]) + self.keyConfigEntry(config.key["prevElement"]) def keyRight(self): - self["entries"].handleKey(config.key["nextElement"]) + self.keyConfigEntry(config.key["nextElement"]) def updateList(self, list): List = self["entries"] @@ -156,7 +162,6 @@ class CiMmi(Screen): List.l.setList(list) - def showWait(self): self.tag = "WAIT" self["title"].setText("") diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 928690d0..9cfe7073 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1129,7 +1129,7 @@ int eDVBServicePlay::getInfo(int w) } } return -1; - case sIsCrypted: return program.isCrypted; + case sIsCrypted: return program.isCrypted(); case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid; case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type; case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid; -- 2.30.2