X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/7f19468027d025ce8597318e7211995871f17376..239220f7ef72fe65d5e2289b19b2a0a5cf21a40f:/lib/dvb/db.cpp diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index 22b6267b..9035b8f0 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,13 +13,19 @@ DEFINE_REF(eDVBService); -RESULT eBouquet::addService(const eServiceReference &ref) +RESULT eBouquet::addService(const eServiceReference &ref, eServiceReference before) { list::iterator it = std::find(m_services.begin(), m_services.end(), ref); if ( it != m_services.end() ) return -1; - m_services.push_back(ref); + if (before.valid()) + { + it = std::find(m_services.begin(), m_services.end(), before); + m_services.insert(it, ref); + } + else + m_services.push_back(ref); return 0; } @@ -75,24 +82,6 @@ RESULT eBouquet::flushChanges() { eServiceReference tmp = *i; std::string str = tmp.path; - if ( (i->flags&eServiceReference::flagDirectory) == eServiceReference::flagDirectory ) - { - unsigned int p1 = str.find("FROM BOUQUET \""); - if (p1 == std::string::npos) - { - eDebug("doof... kaputt"); - continue; - } - str.erase(0, p1+14); - p1 = str.find("\""); - if (p1 == std::string::npos) - { - eDebug("doof2... kaputt"); - continue; - } - str.erase(p1); - tmp.path=str; - } if ( fprintf(f, "#SERVICE %s\r\n", tmp.toString().c_str()) < 0 ) goto err; if ( i->name.length() ) @@ -114,12 +103,13 @@ RESULT eBouquet::setListName(const std::string &name) } eDVBService::eDVBService() - :m_flags(0) + :m_cache(0), m_flags(0) { } eDVBService::~eDVBService() { + delete [] m_cache; } eDVBService &eDVBService::operator=(const eDVBService &s) @@ -129,7 +119,7 @@ eDVBService &eDVBService::operator=(const eDVBService &s) m_provider_name = s.m_provider_name; m_flags = s.m_flags; m_ca = s.m_ca; - m_cache = s.m_cache; + copyCache(s.m_cache); return *this; } @@ -161,7 +151,7 @@ RESULT eDVBService::getEvent(const eServiceReference &ref, ePtr & return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr); } -bool eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore) +int eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { ePtr res_mgr; if ( eDVBResourceManager::getInstance( res_mgr ) ) @@ -173,7 +163,7 @@ bool eDVBService::isPlayable(const eServiceReference &ref, const eServiceReferen ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore); return res_mgr->canAllocateChannel(chid, chid_ignore); } - return false; + return 0; } int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query) @@ -223,30 +213,64 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ return res; } -int eDVBService::getCachePID(cacheID id) +bool eDVBService::cacheEmpty() { - std::map::iterator it = m_cache.find(id); - if ( it != m_cache.end() ) - return it->second; - return -1; + if (m_cache) + for (int i=0; i < cacheMax; ++i) + if (m_cache[i] != -1) + return false; + return true; } -void eDVBService::setCachePID(cacheID id, int pid) +void eDVBService::initCache() { - if (pid == -1) - m_cache.erase(id); + 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 || !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; } DEFINE_REF(eDVBDB); - /* THIS CODE IS BAD. it should be replaced by somethine better. */ void eDVBDB::reloadServicelist() +{ + loadServicelist(CONFIGDIR"/enigma2/lamedb"); +} + + /* THIS CODE IS BAD. it should be replaced by somethine better. */ +void eDVBDB::loadServicelist(const char *file) { eDebug("---- opening lame channel db"); - FILE *f=fopen(CONFIGDIR"/enigma2/lamedb", "rt"); - if (!f) + FILE *f=fopen(file, "rt"); + if (!f && strcmp(file, CONFIGDIR"/enigma2/lamedb") == 0) { struct stat s; if ( !stat("lamedb", &s) ) @@ -303,8 +327,9 @@ void eDVBDB::reloadServicelist() int frequency, symbol_rate, polarisation, fec, orbital_position, inversion, system=eDVBFrontendParametersSatellite::System::DVB_S, modulation=eDVBFrontendParametersSatellite::Modulation::QPSK, - rolloff=eDVBFrontendParametersSatellite::RollOff::alpha_auto; - sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion, &system, &modulation, &rolloff); + rolloff=eDVBFrontendParametersSatellite::RollOff::alpha_0_35, + pilot=eDVBFrontendParametersSatellite::Pilot::Unknown; + sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion, &system, &modulation, &rolloff, &pilot); sat.frequency = frequency; sat.symbol_rate = symbol_rate; sat.polarisation = polarisation; @@ -314,13 +339,14 @@ void eDVBDB::reloadServicelist() sat.inversion = inversion; sat.system = system; sat.modulation = modulation; - sat.roll_off = rolloff; + sat.rolloff = rolloff; + sat.pilot = pilot; feparm->setDVBS(sat); } else if (line[1]=='t') { eDVBFrontendParametersTerrestrial ter; int frequency, bandwidth, code_rate_HP, code_rate_LP, modulation, transmission_mode, guard_interval, hierarchy, inversion; - sscanf(line+2, "%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation, &transmission_mode, &guard_interval, &hierarchy, &inversion); + sscanf(line+3, "%d:%d:%d:%d:%d:%d:%d:%d:%d", &frequency, &bandwidth, &code_rate_HP, &code_rate_LP, &modulation, &transmission_mode, &guard_interval, &hierarchy, &inversion); ter.frequency = frequency; ter.bandwidth = bandwidth; ter.code_rate_HP = code_rate_HP; @@ -338,7 +364,7 @@ void eDVBDB::reloadServicelist() inversion=eDVBFrontendParametersCable::Inversion::Unknown, modulation=eDVBFrontendParametersCable::Modulation::Auto, fec_inner=eDVBFrontendParametersCable::FEC::fAuto; - sscanf(line+2, "%d:%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation, &fec_inner); + sscanf(line+3, "%d:%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation, &fec_inner); cab.frequency = frequency; cab.fec_inner = fec_inner; cab.inversion = inversion; @@ -398,7 +424,7 @@ void eDVBDB::reloadServicelist() } else while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d... { - unsigned int c=str.find(','); + size_t c=str.find(','); char p=str[0]; std::string v; if (c == std::string::npos) @@ -419,13 +445,13 @@ void eDVBDB::reloadServicelist() } else if (p == 'c') { int cid, val; - sscanf(v.c_str(), "%02d%04x", &cid, &val); - s->m_cache[cid]=val; + sscanf(v.c_str(), "%02d%x", &cid, &val); + s->setCacheEntry((eDVBService::cacheID)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); @@ -436,10 +462,10 @@ void eDVBDB::reloadServicelist() fclose(f); } -void eDVBDB::saveServicelist() +void eDVBDB::saveServicelist(const char *file) { eDebug("---- saving lame channel db"); - FILE *f=fopen(CONFIGDIR"/enigma2/lamedb", "w"); + FILE *f=fopen(file, "w"); int channels=0, services=0; if (!f) eFatal("couldn't save lame channel db!"); @@ -460,14 +486,18 @@ void eDVBDB::saveServicelist() { if (sat.system == eDVBFrontendParametersSatellite::System::DVB_S2) { - fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d\n", + fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d", sat.frequency, sat.symbol_rate, sat.polarisation, sat.fec, sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position, sat.inversion, sat.system, sat.modulation, - sat.roll_off); + sat.rolloff); + if (sat.modulation == eDVBFrontendParametersSatellite::Modulation::M8PSK) + fprintf(f, ":%d\n", sat.pilot); + else + fprintf(f, "\n"); } else { @@ -478,14 +508,14 @@ void eDVBDB::saveServicelist() sat.inversion); } } - if (!ch.m_frontendParameters->getDVBT(ter)) + else if (!ch.m_frontendParameters->getDVBT(ter)) { fprintf(f, "\tt %d:%d:%d:%d:%d:%d:%d:%d:%d\n", ter.frequency, ter.bandwidth, ter.code_rate_HP, ter.code_rate_LP, ter.modulation, ter.transmission_mode, ter.guard_interval, ter.hierarchy, ter.inversion); } - if (!ch.m_frontendParameters->getDVBC(cab)) + else if (!ch.m_frontendParameters->getDVBC(cab)) { fprintf(f, "\tc %d:%d:%d:%d:%d\n", cab.frequency, cab.symbol_rate, cab.inversion, cab.modulation, cab.fec_inner); @@ -510,12 +540,15 @@ void eDVBDB::saveServicelist() fprintf(f, "p:%s", i->second->m_provider_name.c_str()); // write cached pids - for (std::map::const_iterator ca(i->second->m_cache.begin()); - ca != i->second->m_cache.end(); ++ca) - fprintf(f, ",c:%02d%04x", ca->first, ca->second); + for (int x=0; x < eDVBService::cacheMax; ++x) + { + int entry = i->second->getCacheEntry((eDVBService::cacheID)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); @@ -530,6 +563,11 @@ void eDVBDB::saveServicelist() fclose(f); } +void eDVBDB::saveServicelist() +{ + saveServicelist(CONFIGDIR"/enigma2/lamedb"); +} + void eDVBDB::loadBouquet(const char *path) { std::string bouquet_name = path; @@ -538,7 +576,7 @@ void eDVBDB::loadBouquet(const char *path) eDebug("Bouquet load failed.. no path given.."); return; } - unsigned int pos = bouquet_name.rfind('/'); + size_t pos = bouquet_name.rfind('/'); if ( pos != std::string::npos ) bouquet_name.erase(0, pos+1); if (bouquet_name.empty()) @@ -594,7 +632,7 @@ void eDVBDB::loadBouquet(const char *path) break; if (line[0]=='#') { - if (!strncmp(line, "#SERVICE ", 9) || !strncmp(line, "#SERVICE: ", 10)) + if (!strncmp(line, "#SERVICE", 8)) { int offs = line[8] == ':' ? 10 : 9; eServiceReference tmp(line+offs); @@ -603,29 +641,48 @@ void eDVBDB::loadBouquet(const char *path) eDebug("only DVB Bouquets supported"); continue; } - if ( (tmp.flags&eServiceReference::flagDirectory) == eServiceReference::flagDirectory ) + if ( tmp.flags&eServiceReference::canDescent ) { - unsigned int pos = tmp.path.rfind('/'); + size_t pos = tmp.path.rfind('/'); + char buf[256]; + std::string path = tmp.path; if ( pos != std::string::npos ) - tmp.path.erase(0, pos+1); - if (tmp.path.empty()) + path.erase(0, pos+1); + if (path.empty()) { eDebug("Bouquet load failed.. no filename given.."); continue; } - loadBouquet(tmp.path.c_str()); - char buf[256]; - snprintf(buf, 256, "(type == %d) FROM BOUQUET \"%s\" ORDER BY bouquet", tmp.data[0], tmp.path.c_str()); - tmp.path = buf; + pos = path.find("FROM BOUQUET "); + if (pos != std::string::npos) + { + char endchr = path[pos+13]; + if (endchr != '"') + { + eDebug("ignore invalid bouquet '%s' (only \" are allowed)", + tmp.toString().c_str()); + continue; + } + char *beg = &path[pos+14]; + char *end = strchr(beg, endchr); + path.assign(beg, end - beg); + } + else + { + snprintf(buf, 256, "FROM BOUQUET \"%s\" ORDER BY bouquet", path.c_str()); + tmp.path = buf; + } + loadBouquet(path.c_str()); } list.push_back(tmp); e = &list.back(); read_descr=true; ++entries; } - else if (read_descr && !strncmp(line, "#DESCRIPTION ", 13)) + else if (read_descr && !strncmp(line, "#DESCRIPTION", 12)) { - e->name = line+13; + int offs = line[12] == ':' ? 14 : 13; + e->name = line+offs; read_descr=false; } else if (!strncmp(line, "#NAME ", 6)) @@ -654,7 +711,7 @@ void eDVBDB::reloadBouquets() ref.type=1; ref.flags=7; ref.data[0]=1; - ref.path="(type == 1) FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet"; + ref.path="FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet"; eBouquet &parent = m_bouquets["bouquets.tv"]; parent.m_services.push_back(ref); parent.flushChanges(); @@ -670,7 +727,7 @@ void eDVBDB::reloadBouquets() ref.type=1; ref.flags=7; ref.data[0]=2; - ref.path="(type == 2) FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet"; + ref.path="FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet"; eBouquet &parent = m_bouquets["bouquets.radio"]; parent.m_services.push_back(ref); parent.flushChanges(); @@ -679,12 +736,409 @@ void eDVBDB::reloadBouquets() eDVBDB *eDVBDB::instance; +using namespace xmlcc; + eDVBDB::eDVBDB() { instance = this; reloadServicelist(); } +PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObject tp_dict) +{ + if (!PyDict_Check(tp_dict)) { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 2 is not a python dict"); + return NULL; + } + else if (!PyDict_Check(sat_dict)) + { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 1 is not a python dict"); + return NULL; + } + else if (!PyList_Check(sat_list)) + { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 0 is not a python list"); + return NULL; + } + XMLTree tree; + tree.setFilename("/etc/tuxbox/satellites.xml"); + tree.read(); + Element *root = tree.getRoot(); + if (!root) + { + eDebug("couldn't open /etc/tuxbox/satellites.xml!!"); + Py_INCREF(Py_False); + return Py_False; + } + int tmp, *dest = NULL, + modulation, system, freq, sr, pol, fec, inv, pilot, rolloff; + char *end_ptr; + const Attribute *at; + std::string name; + const ElementList &root_elements = root->getElementList(); + for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it) + { +// eDebug("element: %s", (*it)->name().c_str()); + const Element *el = *it; + const ElementList &sat_elements = el->getElementList(); + const AttributeList &sat_attributes = el->getAttributeList(); + ePyObject sat_name; + ePyObject sat_pos; + ePyObject sat_flags; + for (AttributeConstIterator it(sat_attributes.begin()); it != sat_attributes.end(); ++it) + { +// eDebug("\tattr: %s", at->name().c_str()); + at = *it; + name = at->name(); + if (name == "name") + sat_name = PyString_FromString(at->value().c_str()); + else if (name == "flags") + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + sat_flags = PyInt_FromLong(tmp); + } + else if (name == "position") + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + { + if (tmp < 0) + tmp = 3600 + tmp; + sat_pos = PyInt_FromLong(tmp); + } + } + } + if (sat_pos && sat_name) + { + ePyObject tplist = PyList_New(0); + ePyObject tuple = PyTuple_New(3); + if (!sat_flags) + sat_flags = PyInt_FromLong(0); + PyTuple_SET_ITEM(tuple, 0, sat_pos); + PyTuple_SET_ITEM(tuple, 1, sat_name); + PyTuple_SET_ITEM(tuple, 2, sat_flags); + PyList_Append(sat_list, tuple); + Py_DECREF(tuple); + PyDict_SetItem(sat_dict, sat_pos, sat_name); + PyDict_SetItem(tp_dict, sat_pos, tplist); + for (ElementConstIterator it(sat_elements.begin()); it != sat_elements.end(); ++it) + { +// eDebug("\telement: %s", (*it)->name().c_str()); + const AttributeList &tp_attributes = (*it)->getAttributeList(); + AttributeConstIterator end = tp_attributes.end(); + modulation = 1; // QPSK default + system = 0; // DVB-S default + freq = 0; + sr = 0; + pol = -1; + fec = 0; // AUTO default + inv = 2; // AUTO default + pilot = 2; // AUTO default + rolloff = 0; // alpha 0.35 + for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it) + { +// eDebug("\t\tattr: %s", at->name().c_str()); + at = *it; + name = at->name(); + if (name == "modulation") dest = &modulation; + else if (name == "system") dest = &system; + else if (name == "frequency") dest = &freq; + else if (name == "symbol_rate") dest = &sr; + else if (name == "polarization") dest = &pol; + else if (name == "fec_inner") dest = &fec; + else if (name == "inversion") dest = &inv; + else if (name == "rolloff") dest = &rolloff; + else if (name == "pilot") dest = &pilot; + if (dest) + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + *dest = tmp; + } + } + if (freq && sr && pol != -1) + { + tuple = PyTuple_New(10); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr)); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(pol)); + PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec)); + PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(system)); + PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(modulation)); + PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(inv)); + PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(rolloff)); + PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(pilot)); + PyList_Append(tplist, tuple); + Py_DECREF(tuple); + } + } + Py_DECREF(tplist); + } + else + { + if (sat_pos) + Py_DECREF(sat_pos); + if (sat_name) + Py_DECREF(sat_name); + if (sat_flags) + Py_DECREF(sat_flags); + } + } + Py_INCREF(Py_True); + return Py_True; +} + +PyObject *eDVBDB::readCables(ePyObject cab_list, ePyObject tp_dict) +{ + if (!PyDict_Check(tp_dict)) { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 1 is not a python dict"); + return NULL; + } + else if (!PyList_Check(cab_list)) + { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 0 is not a python list"); + return NULL; + } + XMLTree tree; + tree.setFilename("/etc/tuxbox/cables.xml"); + tree.read(); + Element *root = tree.getRoot(); + if (!root) + { + eDebug("couldn't open /etc/tuxbox/cables.xml!!"); + Py_INCREF(Py_False); + return Py_False; + } + const Attribute *at; + int tmp, *dest, + modulation, fec, freq, sr; + std::string name; + char *end_ptr; + const ElementList &root_elements = root->getElementList(); + for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it) + { +// eDebug("element: %s", el->name().c_str()); + const Element *el = *it; + const ElementList &cab_elements = el->getElementList(); + const AttributeList &cab_attributes = el->getAttributeList(); + ePyObject cab_name; + ePyObject cab_flags; + for (AttributeConstIterator it(cab_attributes.begin()); it != cab_attributes.end(); ++it) + { +// eDebug("\tattr: %s", at->name().c_str()); + at = *it; + name = at->name(); + if (name == "name") + cab_name = PyString_FromString(at->value().c_str()); + else if (name == "flags") + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + cab_flags = PyInt_FromLong(tmp); + } + } + if (cab_name) + { + ePyObject tplist = PyList_New(0); + ePyObject tuple = PyTuple_New(2); + if (!cab_flags) + cab_flags = PyInt_FromLong(0); + PyTuple_SET_ITEM(tuple, 0, cab_name); + PyTuple_SET_ITEM(tuple, 1, cab_flags); + PyList_Append(cab_list, tuple); + Py_DECREF(tuple); + PyDict_SetItem(tp_dict, cab_name, tplist); + for (ElementConstIterator it(cab_elements.begin()); it != cab_elements.end(); ++it) + { +// eDebug("\telement: %s", (*it)->name().c_str()); + const AttributeList &tp_attributes = (*it)->getAttributeList(); + AttributeConstIterator end = tp_attributes.end(); + modulation = 3; // QAM64 default + fec = 0; // AUTO default + freq = 0; + sr = 0; + for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it) + { +// eDebug("\t\tattr: %s", at->name().c_str()); + at = *it; + dest = 0; + name = at->name(); + if (name == "modulation") dest = &modulation; + else if (name == "frequency") dest = &freq; + else if (name == "symbol_rate") dest = &sr; + else if (name == "fec_inner") dest = &fec; + if (dest) + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + *dest = tmp; + } + } + if (freq && sr) + { + while (freq > 999999) + freq /= 10; + tuple = PyTuple_New(5); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr)); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(modulation)); + PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec)); + PyList_Append(tplist, tuple); + Py_DECREF(tuple); + } + } + Py_DECREF(tplist); + } + else if (cab_flags) + Py_DECREF(cab_flags); + } + Py_INCREF(Py_True); + return Py_True; +} + +PyObject *eDVBDB::readTerrestrials(ePyObject ter_list, ePyObject tp_dict) +{ + if (!PyDict_Check(tp_dict)) { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 1 is not a python dict"); + return NULL; + } + else if (!PyList_Check(ter_list)) + { + PyErr_SetString(PyExc_StandardError, + "type error"); + eDebug("arg 0 is not a python list"); + return NULL; + } + XMLTree tree; + tree.setFilename("/etc/tuxbox/terrestrial.xml"); + tree.read(); + Element *root = tree.getRoot(); + if (!root) + { + eDebug("couldn't open /etc/tuxbox/terrestrial.xml!!"); + Py_INCREF(Py_False); + return Py_False; + } + const Attribute *at; + std::string name; + int tmp, *dest, + freq, bw, constellation, crh = 5, crl = 5, guard = 4, transm, hierarchy, inv = 2; + char *end_ptr; + const ElementList &root_elements = root->getElementList(); + for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it) + { +// eDebug("element: %s", el->name().c_str()); + const Element *el = *it; + const ElementList &ter_elements = el->getElementList(); + const AttributeList &ter_attributes = el->getAttributeList(); + ePyObject ter_name; + ePyObject ter_flags; + for (AttributeConstIterator it(ter_attributes.begin()); it != ter_attributes.end(); ++it) + { +// eDebug("\tattr: %s", at->name().c_str()); + at = *it; + name = at->name(); + if (name == "name") + ter_name = PyString_FromString(at->value().c_str()); + else if (name == "flags") + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + ter_flags = PyInt_FromLong(tmp); + } + } + if (ter_name) + { + ePyObject tplist = PyList_New(0); + ePyObject tuple = PyTuple_New(2); + if (!ter_flags) + ter_flags = PyInt_FromLong(0); + PyTuple_SET_ITEM(tuple, 0, ter_name); + PyTuple_SET_ITEM(tuple, 1, ter_flags); + PyList_Append(ter_list, tuple); + Py_DECREF(tuple); + PyDict_SetItem(tp_dict, ter_name, tplist); + for (ElementConstIterator it(ter_elements.begin()); it != ter_elements.end(); ++it) + { +// eDebug("\telement: %s", (*it)->name().c_str()); + const AttributeList &tp_attributes = (*it)->getAttributeList(); + AttributeConstIterator end = tp_attributes.end(); + freq = 0; + bw = 3; // AUTO + constellation = 1; // AUTO + crh = 5; // AUTO + crl = 5; // AUTO + guard = 4; // AUTO + transm = 2; // AUTO + hierarchy = 4; // AUTO + inv = 2; // AUTO + for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it) + { +// eDebug("\t\tattr: %s", at->name().c_str()); + at = *it; + dest = 0; + name = at->name(); + if (name == "centre_frequency") dest = &freq; + else if (name == "bandwidth") dest = &bw; + else if (name == "constellation") dest = &constellation; + else if (name == "code_rate_hp") dest = &crh; + else if (name == "code_rate_lp") dest = &crl; + else if (name == "guard_interval") dest = &guard; + else if (name == "transmission_mode") dest = &transm; + else if (name == "hierarchy_information") dest = &hierarchy; + else if (name == "inversion") dest = &inv; + if (dest) + { + tmp = strtol(at->value().c_str(), &end_ptr, 10); + if (!*end_ptr) + *dest = tmp; + } + } + if (freq) + { + if (crh > 5) // our terrestrial.xml is buggy... 6 for AUTO + crh = 5; + if (crl > 5) // our terrestrial.xml is buggy... 6 for AUTO + crl = 5; + tuple = PyTuple_New(10); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq)); + PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(bw)); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(constellation)); + PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(crh)); + PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(crl)); + PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(guard)); + PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(transm)); + PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(hierarchy)); + PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(inv)); + PyList_Append(tplist, tuple); + Py_DECREF(tuple); + } + } + Py_DECREF(tplist); + } + else if (ter_flags) + Py_DECREF(ter_flags); + } + Py_INCREF(Py_True); + return Py_True; +} + eDVBDB::~eDVBDB() { instance=NULL; @@ -724,15 +1178,22 @@ RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos) bool remove=true; int system; it->second.m_frontendParameters->getSystem(system); - if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite ) + if ( system == iDVBFrontend::feSatellite ) { eDVBFrontendParametersSatellite sat; it->second.m_frontendParameters->getDVBS(sat); if ((unsigned int)sat.orbital_position != orbpos) remove=false; } - if ( remove && chid.dvbnamespace != eNs && chid.dvbnamespace != ch.dvbnamespace ) - remove=false; + if ( remove && chid.dvbnamespace != eNs ) + { + if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000) + ; + else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000) + ; + else if ( chid.dvbnamespace != ch.dvbnamespace ) + remove=false; + } if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id ) remove=false; if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id ) @@ -818,8 +1279,15 @@ RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned i if ((unsigned int)sat.orbital_position != orbpos) remove=false; } - if ( remove && chid.dvbnamespace != eNs && chid.dvbnamespace != ch.dvbnamespace ) - remove=false; + if ( remove && chid.dvbnamespace != eNs ) + { + if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000) + ; + else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000) + ; + else if ( chid.dvbnamespace != ch.dvbnamespace ) + remove=false; + } if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id ) remove=false; if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id ) @@ -906,7 +1374,7 @@ RESULT eDVBDB::getBouquet(const eServiceReference &ref, eBouquet* &bouquet) eDebug("getBouquet failed.. no path given!"); return -1; } - unsigned int pos = str.find("FROM BOUQUET \""); + size_t pos = str.find("FROM BOUQUET \""); if ( pos != std::string::npos ) { str.erase(0, pos+14); @@ -976,21 +1444,43 @@ eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eD int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b) { ePtr a_service, b_service; - int sortmode = m_query ? m_query->m_sort : eDVBChannelQuery::tName; if ((sortmode == eDVBChannelQuery::tName) || (sortmode == eDVBChannelQuery::tProvider)) { - if (m_db->getService(a, a_service)) + if (a.name.empty() && m_db->getService(a, a_service)) return 1; - if (m_db->getService(b, b_service)) + if (b.name.empty() && m_db->getService(b, b_service)) return 1; } switch (sortmode) { case eDVBChannelQuery::tName: - return a_service->m_service_name_sort < b_service->m_service_name_sort; + if (a_service) + { + if (b_service) + return a_service->m_service_name_sort < b_service->m_service_name_sort; + else + { + std::string str = b.name; + makeUpper(str); + return a_service->m_service_name_sort < str; + } + } + else if (b_service) + { + std::string str = a.name; + makeUpper(str); + return str < b_service->m_service_name_sort; + } + else + { + std::string aa = a.name, bb = b.name; + makeUpper(aa); + makeUpper(bb); + return aa < bb; + } case eDVBChannelQuery::tProvider: return a_service->m_provider_name < b_service->m_provider_name; case eDVBChannelQuery::tType: @@ -1015,14 +1505,20 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref) { while (m_cursor != m_db->m_services.end()) { - ref = m_cursor->first; + ePtr service = m_cursor->second; + if (service->isHidden()) + ++m_cursor; + else + { + ref = m_cursor->first; - int res = (!m_query) || m_cursor->second->checkFilter(ref, *m_query); + int res = (!m_query) || service->checkFilter(ref, *m_query); - ++m_cursor; + ++m_cursor; - if (res) - return 0; + if (res) + return 0; + } } ref.type = eServiceReference::idInvalid; @@ -1046,7 +1542,7 @@ RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref) std::map >::iterator it = m_db->m_services.find(ref); - int res = (!m_query) || it == m_db->m_services.end() || it->second->checkFilter(ref, *m_query); + int res = (!m_query) || it == m_db->m_services.end() || !(it->second->isHidden() && it->second->checkFilter(ref, *m_query)); ++m_cursor; @@ -1087,28 +1583,26 @@ int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServ y -= 3600; return x < y; } - return a.name < b.name; + std::string aa = a.name, bb = b.name; + makeUpper(aa); + makeUpper(bb); + return aa < bb; } eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) :eDVBDBListQuery(db, source, query) { + std::set found; for (std::map >::iterator it(m_db->m_services.begin()); it != m_db->m_services.end(); ++it) { - int res = it->second->checkFilter(it->first, *query); + int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query); if (res) { unsigned int dvbnamespace = it->first.getDVBNamespace().get()&0xFFFF0000; - bool found=0; - for (std::list::iterator i(m_list.begin()); i != m_list.end(); ++i) - if ( (i->getDVBNamespace().get()&0xFFFF0000) == dvbnamespace ) - { - found=true; - break; - } - if (!found) + if (found.find(dvbnamespace) == found.end()) { + found.insert(dvbnamespace); eServiceReferenceDVB ref; ref.setDVBNamespace(dvbnamespace); ref.flags=eServiceReference::flagDirectory; @@ -1145,26 +1639,19 @@ eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference eDVBDBProvidersQuery::eDVBDBProvidersQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) :eDVBDBListQuery(db, source, query) { + std::set found; for (std::map >::iterator it(m_db->m_services.begin()); it != m_db->m_services.end(); ++it) { - int res = it->second->checkFilter(it->first, *query); + int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query); if (res) { - bool found=0; - const char *provider_name = it->second->m_provider_name.length() ? it->second->m_provider_name.c_str() : "Unknown"; - - for (std::list::iterator i(m_list.begin()); i != m_list.end(); ++i) - if (i->name == provider_name) - { - found=true; - break; - } - if (!found) + if (found.find(std::string(provider_name)) == found.end()) { + found.insert(std::string(provider_name)); eServiceReferenceDVB ref; char buf[64]; ref.name=provider_name; @@ -1210,10 +1697,7 @@ RESULT parseExpression(ePtr &res, std::list::cons std::list::const_iterator end_of_exp; if (begin == end) - { - eDebug("empty expression!"); return 0; - } if (*begin == "(") { @@ -1325,9 +1809,18 @@ RESULT parseExpression(ePtr &res, std::list::cons } res->m_string = val; - res->m_int = atoi(val.c_str()); -// res->m_channelid = eDVBChannelID(val); - + + if (res->m_type == eDVBChannelQuery::tChannelID) + { + int ns, tsid, onid; + if (sscanf(val.c_str(), "%08x%04x%04x", &ns, &tsid, &onid) == 3) + res->m_channelid = eDVBChannelID(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid)); + else + eDebug("couldn't parse channelid !! format should be hex NNNNNNNNTTTTOOOO (namespace, tsid, onid)"); + } + else + res->m_int = atoi(val.c_str()); + return 0; }