X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/8d8294b4b354436adde202604fffb55c181d686c..ff00cc62b92da0226e4147cca49bbbb39d248e92:/lib/dvb/db.cpp diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index fdcd428d..25b0fb94 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -21,6 +21,7 @@ eDVBService::~eDVBService() eDVBService &eDVBService::operator=(const eDVBService &s) { m_service_name = s.m_service_name; + 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; @@ -30,7 +31,10 @@ eDVBService &eDVBService::operator=(const eDVBService &s) RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { - name = convertDVBUTF8(m_service_name); + if ( ref.name.length() ) + name = ref.name; + else + name = m_service_name; return 0; } @@ -45,7 +49,7 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ switch (query.m_type) { case eDVBChannelQuery::tName: - res = m_service_name.find(query.m_string) != std::string::npos; + res = m_service_name_sort.find(query.m_string) != std::string::npos; break; case eDVBChannelQuery::tProvider: res = m_provider_name.find(query.m_string) != std::string::npos; @@ -144,7 +148,7 @@ void eDVBDB::load() { eDVBFrontendParametersSatellite sat; int frequency, symbol_rate, polarisation, fec, orbital_position, inversion; - sscanf(line+2, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &inversion, &orbital_position); + sscanf(line+2, "%d:%d:%d:%d:%d:%d", &frequency, &symbol_rate, &polarisation, &fec, &orbital_position, &inversion); sat.frequency = frequency; sat.symbol_rate = symbol_rate; sat.polarisation = polarisation; @@ -213,7 +217,11 @@ void eDVBDB::load() fgets(line, 256, f); if (strlen(line)) line[strlen(line)-1]=0; - s->m_service_name=line; + + s->m_service_name = line; + s->m_service_name_sort = removeDVBChars(line); + makeUpper(s->m_service_name_sort); + fgets(line, 256, f); if (strlen(line)) line[strlen(line)-1]=0; @@ -287,8 +295,8 @@ void eDVBDB::save() { fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", sat.frequency, sat.symbol_rate, - sat.polarisation, sat.fec, sat.inversion, - sat.orbital_position); + sat.polarisation, sat.fec, sat.orbital_position, + sat.inversion); } if (!ch.m_frontendParameters->getDVBT(ter)) { @@ -333,9 +341,113 @@ void eDVBDB::save() fclose(f); } +void eDVBDB::loadBouquet(const char *path) +{ + std::string bouquet_name = path; + if (!bouquet_name.length()) + { + eDebug("Bouquet load failed.. no path given.."); + return; + } + unsigned int pos = bouquet_name.rfind('/'); + if ( pos != std::string::npos ) + bouquet_name.erase(0, pos+1); + if (bouquet_name.empty()) + { + eDebug("Bouquet load failed.. no filename given.."); + return; + } + eBouquet &bouquet = m_bouquets[bouquet_name]; + bouquet.m_path = path; + std::list &list = bouquet.m_services; + list.clear(); + + eDebug("loading bouquet... %s", path); + FILE *fp=fopen(path, "rt"); + int entries=0; + if (!fp) + { + eDebug("failed to open."); + return; + } + char line[256]; + bool read_descr=false; + eServiceReference *e = NULL; + while (1) + { + if (!fgets(line, 256, fp)) + break; + line[strlen(line)-1]=0; + if (strlen(line) && line[strlen(line)-1]=='\r') + line[strlen(line)-1]=0; + if (!line[0]) + break; + if (line[0]=='#') + { + if (!strncmp(line, "#SERVICE ", 9) || !strncmp(line, "#SERVICE: ", 10)) + { + int offs = line[8] == ':' ? 10 : 9; + eServiceReference tmp(line+offs); + if (tmp.type != eServiceReference::idDVB) + { + eDebug("only DVB Bouquets supported"); + continue; + } + if ( (tmp.flags&eServiceReference::flagDirectory) == eServiceReference::flagDirectory ) + { + std::string str = tmp.path; + unsigned int pos = str.rfind('/'); + if ( pos != std::string::npos ) + str.erase(0, pos+1); + if (str.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], str.c_str()); + tmp.path = buf; + } + list.push_back(tmp); + e = &list.back(); + read_descr=true; + ++entries; + } + else if (read_descr && !strncmp(line, "#DESCRIPTION ", 13)) + { + e->name = line+13; + read_descr=false; + } + else if (!strncmp(line, "#NAME ", 6)) + bouquet.m_bouquet_name=line+6; + continue; + } + } + fclose(fp); + eDebug("%d entries in Bouquet %s", entries, bouquet_name.c_str()); +} + +void eDVBDB::saveBouquet(const char *path) +{ + +} + +void eDVBDB::loadBouquets() +{ + loadBouquet("bouquets.tv"); + loadBouquet("bouquets.radio"); +} + +void eDVBDB::saveBouquets() +{ + +} + eDVBDB::eDVBDB() { load(); + loadBouquets(); } eDVBDB::~eDVBDB() @@ -389,17 +501,91 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &query, eDVBChannelQuery *q) +RESULT eDVBDB::getBouquet(const eServiceReference &ref, const eBouquet* &bouquet) +{ + std::string str = ref.path; + if (str.empty()) + { + eDebug("getBouquet failed.. no path given!"); + return -1; + } + unsigned int pos = str.find("FROM BOUQUET \""); + if ( pos != std::string::npos ) + { + str.erase(0, pos+14); + pos = str.find('"'); + if ( pos != std::string::npos ) + str.erase(pos); + else + str.clear(); + } + if (str.empty()) + { + eDebug("getBouquet failed.. couldn't parse bouquet name"); + return -1; + } + std::map::iterator i = + m_bouquets.find(str); + if (i == m_bouquets.end()) + { + bouquet = 0; + return -ENOENT; + } + bouquet = &i->second; + return 0; +} + +RESULT eDVBDB::startQuery(ePtr &query, eDVBChannelQuery *q, const eServiceReference &source) { - query = new eDVBDBQuery(this, eServiceReference(), q); + if ( q && q->m_bouquet_name.length() ) + query = new eDVBDBBouquetQuery(this, source, q); + else + query = new eDVBDBQuery(this, source, q); return 0; } -DEFINE_REF(eDVBDBQuery); +DEFINE_REF(eDVBDBQueryBase); -eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query): m_db(db), m_query(query) +eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :m_db(db), m_query(query), m_source(source) +{ +} + +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)) + return 1; + if (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; + case eDVBChannelQuery::tProvider: + return a_service->m_provider_name < b_service->m_provider_name; + case eDVBChannelQuery::tType: + return a.getServiceType() < b.getServiceType(); + case eDVBChannelQuery::tBouquet: + return 0; + case eDVBChannelQuery::tSatellitePosition: + return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16); + default: + return 1; + } + return 0; +} + +eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBQueryBase(db, source, query) { - // TODO: use SOURCE ... m_cursor = m_db->m_services.begin(); } @@ -408,18 +594,67 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref) while (m_cursor != m_db->m_services.end()) { ref = m_cursor->first; - + int res = (!m_query) || m_cursor->second->checkFilter(ref, *m_query); ++m_cursor; - + + if (res) + return 0; + } + + ref = eServiceReferenceDVB(); + return 1; +} + +eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin()) +{ +} + +RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref) +{ + eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name]; + std::list &list = bouquet.m_services; + while (m_cursor != list.end()) + { + ref = *((eServiceReferenceDVB*)&(*m_cursor)); + + 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); + + ++m_cursor; + if (res) return 0; } + + ref = eServiceReferenceDVB(); + return 1; } -/* ( <==|...> <"string"|int>)[AND (..)] */ +/* ( <==|...> <"string"|int>)[||,&& (..)] */ + +static int decodeType(const std::string &type) +{ + if (type == "name") + return eDVBChannelQuery::tName; + else if (type == "provider") + return eDVBChannelQuery::tProvider; + else if (type == "type") + return eDVBChannelQuery::tType; + else if (type == "bouquet") + return eDVBChannelQuery::tBouquet; + else if (type == "satellitePosition") + return eDVBChannelQuery::tSatellitePosition; + else if (type == "channelID") + return eDVBChannelQuery::tChannelID; + else + return -1; +} /* never, NEVER write a parser in C++! */ RESULT parseExpression(ePtr &res, std::list::const_iterator begin, std::list::const_iterator end) @@ -449,12 +684,16 @@ RESULT parseExpression(ePtr &res, std::list::cons /* we had only one sub expression */ if (end_of_exp == end) - return 1; + { +// eDebug("only one sub expression"); + return 0; + } /* otherwise we have an operator here.. */ ePtr r2 = res; res = new eDVBChannelQuery(); + res->m_sort = 0; res->m_p1 = r2; res->m_inverse = 0; r2 = 0; @@ -479,6 +718,7 @@ RESULT parseExpression(ePtr &res, std::list::cons std::string type, op, val; res = new eDVBChannelQuery(); + res->m_sort = 0; int cnt = 0; while (begin != end) @@ -509,27 +749,15 @@ RESULT parseExpression(ePtr &res, std::list::cons return 1; } - if (type == "name") - res->m_type = eDVBChannelQuery::tName; - else if (type == "provider") - res->m_type = eDVBChannelQuery::tProvider; - else if (type == "type") - res->m_type = eDVBChannelQuery::tType; - else if (type == "bouquet") - res->m_type = eDVBChannelQuery::tBouquet; - else if (type == "satellitePosition") - res->m_type = eDVBChannelQuery::tSatellitePosition; - else if (type == "channelID") - res->m_type = eDVBChannelQuery::tChannelID; - else + res->m_type = decodeType(type); + + if (res->m_type == -1) { eDebug("malformed query: invalid type %s", type.c_str()); res = 0; return 1; } - eDebug("type is %d, nice!", res->m_type); - if (op == "==") res->m_inverse = 0; else if (op == "!=") @@ -553,7 +781,8 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) std::list tokens; std::string current_token; - + std::string bouquet_name; + // eDebug("splitting %s....", query.c_str()); unsigned int i = 0; const char *splitchars="()"; @@ -594,15 +823,63 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) // { // printf("%s\n", a->c_str()); // } + + int sort = eDVBChannelQuery::tName; + /* check for "ORDER BY ..." */ + + while (tokens.size() > 2) + { + std::list::iterator it = tokens.end(); + --it; --it; --it; + if (*it == "ORDER") + { + ++it; + if (*it == "BY") + { + ++it; + sort = decodeType(*it); + tokens.pop_back(); // ... + tokens.pop_back(); // BY + tokens.pop_back(); // ORDER + } else + sort = -1; + } + else if (*it == "FROM") + { + ++it; + if (*it == "BOUQUET") + { + ++it; + bouquet_name = *it; + tokens.pop_back(); // ... + tokens.pop_back(); // FROM + tokens.pop_back(); // BOUQUET + } + } + else + break; + } + + if (sort == -1) + { + eWarning("ORDER BY .. string invalid."); + res = 0; + return -1; + } + +// eDebug("sort by %d", sort); /* now we recursivly parse that. */ - return parseExpression(res, tokens.begin(), tokens.end()); -/* - res = new eDVBChannelQuery(); - res->m_type = eDVBChannelQuery::tName; - res->m_inverse = 0; - res->m_string = query; - return 0; */ + int r = parseExpression(res, tokens.begin(), tokens.end()); + + if (res) + { + res->m_sort = sort; + res->m_bouquet_name = bouquet_name; + } + +// eDebug("return: %d", r); + return r; } DEFINE_REF(eDVBChannelQuery);