X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d9ee52e4f0fbe9a1ae00d0e66f9e6f0a07fa319f..699d41f217b6d8e91dce499964f8c1a69f5602ed:/lib/dvb/db.cpp diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index fe4bcc76..fdcd428d 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -2,10 +2,11 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include DEFINE_REF(eDVBService); @@ -29,7 +30,13 @@ eDVBService &eDVBService::operator=(const eDVBService &s) RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { - name = m_service_name; + name = convertDVBUTF8(m_service_name); + return 0; +} + +int eDVBService::getLength(const eServiceReference &ref) +{ + return -1; } int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query) @@ -73,9 +80,23 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ return res; } +int eDVBService::getCachePID(cacheID id) +{ + std::map::iterator it = m_cache.find(id); + if ( it != m_cache.end() ) + return it->second; + return -1; +} + +void eDVBService::setCachePID(cacheID id, int pid) +{ + m_cache[id] = pid; +} + DEFINE_REF(eDVBDB); -eDVBDB::eDVBDB() + /* THIS CODE IS BAD. it should be replaced by somethine better. */ +void eDVBDB::load() { eDebug("---- opening lame channel db"); FILE *f=fopen("lamedb", "rt"); @@ -95,7 +116,7 @@ eDVBDB::eDVBDB() fclose(f); return; } - + // clear all transponders while (!feof(f)) @@ -109,10 +130,10 @@ eDVBDB::eDVBDB() if (original_network_id == -1) continue; eDVBChannelID channelid = eDVBChannelID( - eDVBNamespace(dvb_namespace), - eTransportStreamID(transport_stream_id), + eDVBNamespace(dvb_namespace), + eTransportStreamID(transport_stream_id), eOriginalNetworkID(original_network_id)); - + ePtr feparm = new eDVBFrontendParameters; while (!feof(f)) { @@ -133,8 +154,23 @@ eDVBDB::eDVBDB() // ... // t.setSatellite(frequency, symbol_rate, polarisation, fec, sat, inversion); feparm->setDVBS(sat); - } - if (line[1]=='c') + } 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); + ter.frequency = frequency; + ter.bandwidth = bandwidth; + ter.code_rate_HP = code_rate_HP; + ter.code_rate_LP = code_rate_LP; + ter.modulation = modulation; + ter.transmission_mode = transmission_mode; + ter.guard_interval = guard_interval; + ter.hierarchy = hierarchy; + ter.inversion = inversion; + + feparm->setDVBT(ter); + } else if (line[1]=='c') { int frequency, symbol_rate, inversion=0, modulation=3; sscanf(line+2, "%d:%d:%d:%d", &frequency, &symbol_rate, &inversion, &modulation); @@ -149,9 +185,9 @@ eDVBDB::eDVBDB() eDebug("services invalid, no services"); return; } - + // clear all services - + int count=0; while (!feof(f)) @@ -166,7 +202,7 @@ eDVBDB::eDVBDB() if (service_number == -1) continue; ePtr s = new eDVBService; - eServiceReferenceDVB ref = + eServiceReferenceDVB ref = eServiceReferenceDVB( eDVBNamespace(dvb_namespace), eTransportStreamID(transport_stream_id), @@ -224,18 +260,17 @@ eDVBDB::eDVBDB() } eDebug("loaded %d services", count); - + fclose(f); - } -eDVBDB::~eDVBDB() +void eDVBDB::save() { eDebug("---- saving lame channel db"); FILE *f=fopen("lamedb", "wt"); int channels=0, services=0; if (!f) - eFatal("couldn't save lame channel db!"); + eFatal("couldn't save lame channel db!"); fprintf(f, "eDVB services /3/\n"); fprintf(f, "transponders\n"); for (std::map::const_iterator i(m_channels.begin()); @@ -243,37 +278,53 @@ eDVBDB::~eDVBDB() { const eDVBChannelID &chid = i->first; const channel &ch = i->second; - + fprintf(f, "%08x:%04x:%04x\n", chid.dvbnamespace.get(), chid.transport_stream_id.get(), chid.original_network_id.get()); eDVBFrontendParametersSatellite sat; + eDVBFrontendParametersTerrestrial ter; if (!ch.m_frontendParameters->getDVBS(sat)) { - fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", + fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", sat.frequency, sat.symbol_rate, sat.polarisation, sat.fec, sat.inversion, sat.orbital_position); } + 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); + } fprintf(f, "/\n"); channels++; } fprintf(f, "end\nservices\n"); - + for (std::map >::iterator i(m_services.begin()); i != m_services.end(); ++i) { const eServiceReferenceDVB &s = i->first; - fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n", - s.getServiceID().get(), s.getDVBNamespace().get(), - s.getTransportStreamID().get(),s.getOriginalNetworkID().get(), + fprintf(f, "%04x:%08x:%04x:%04x:%d:%d\n", + s.getServiceID().get(), s.getDVBNamespace().get(), + s.getTransportStreamID().get(),s.getOriginalNetworkID().get(), s.getServiceType(), 0); - + fprintf(f, "%s\n", i->second->m_service_name.c_str()); 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); + + // write cached ca pids for (std::set::const_iterator ca(i->second->m_ca.begin()); ca != i->second->m_ca.end(); ++ca) fprintf(f, ",C:%04x", *ca); + fprintf(f, "\n"); services++; } @@ -282,6 +333,16 @@ eDVBDB::~eDVBDB() fclose(f); } +eDVBDB::eDVBDB() +{ + load(); +} + +eDVBDB::~eDVBDB() +{ +// save(); +} + RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm) { channel ch; @@ -330,14 +391,15 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &query, eDVBChannelQuery *q) { - query = new eDVBDBQuery(this, q); + query = new eDVBDBQuery(this, eServiceReference(), q); return 0; } DEFINE_REF(eDVBDBQuery); -eDVBDBQuery::eDVBDBQuery(eDVBDB *db, eDVBChannelQuery *query): m_db(db), m_query(query) +eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query): m_db(db), m_query(query) { + // TODO: use SOURCE ... m_cursor = m_db->m_services.begin(); } @@ -357,13 +419,190 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref) return 1; } +/* ( <==|...> <"string"|int>)[AND (..)] */ + + /* never, NEVER write a parser in C++! */ +RESULT parseExpression(ePtr &res, std::list::const_iterator begin, std::list::const_iterator end) +{ + std::list::const_iterator end_of_exp; + if (*begin == "(") + { + end_of_exp = begin; + while (end_of_exp != end) + if (*end_of_exp == ")") + break; + else + ++end_of_exp; + + if (end_of_exp == end) + { + eDebug("expression parse: end of expression while searching for closing brace"); + return -1; + } + + ++begin; + // begin..end_of_exp + int r = parseExpression(res, begin, end_of_exp); + if (r) + return r; + ++end_of_exp; + + /* we had only one sub expression */ + if (end_of_exp == end) + return 1; + + /* otherwise we have an operator here.. */ + + ePtr r2 = res; + res = new eDVBChannelQuery(); + res->m_p1 = r2; + res->m_inverse = 0; + r2 = 0; + + if (*end_of_exp == "||") + res->m_type = eDVBChannelQuery::tOR; + else if (*end_of_exp == "&&") + res->m_type = eDVBChannelQuery::tAND; + else + { + eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str()); + res = 0; + return 1; + } + + ++end_of_exp; + + return parseExpression(res->m_p2, end_of_exp, end); + } + + // "begin" "end" + std::string type, op, val; + + res = new eDVBChannelQuery(); + + int cnt = 0; + while (begin != end) + { + switch (cnt) + { + case 0: + type = *begin; + break; + case 1: + op = *begin; + break; + case 2: + val = *begin; + break; + case 3: + eDebug("malformed query: got '%s', but expected only ", begin->c_str()); + return 1; + } + ++begin; + ++cnt; + } + + if (cnt != 3) + { + eDebug("malformed query: missing stuff"); + res = 0; + 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 + { + 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 == "!=") + res->m_inverse = 1; + else + { + eDebug("invalid operator %s", op.c_str()); + res = 0; + return 1; + } + + res->m_string = val; + res->m_int = atoi(val.c_str()); +// res->m_channelid = eDVBChannelID(val); + + return 0; +} + RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) { + std::list tokens; + + std::string current_token; + +// eDebug("splitting %s....", query.c_str()); + unsigned int i = 0; + const char *splitchars="()"; + int quotemode = 0, lastsplit = 0, lastalnum = 0; + while (i <= query.size()) + { + int c = (i < query.size()) ? query[i] : ' '; + ++i; + + int issplit = !!strchr(splitchars, c); + int isaln = isalnum(c); + int iswhite = c == ' '; + int isquot = c == '\"'; + + if (quotemode) + { + iswhite = issplit = 0; + isaln = lastalnum; + } + + if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln)) + { + if (current_token.size()) + tokens.push_back(current_token); + current_token.clear(); + } + + if (!(iswhite || isquot)) + current_token += c; + + if (isquot) + quotemode = !quotemode; + lastsplit = issplit; + lastalnum = isaln; + } + +// for (std::list::const_iterator a(tokens.begin()); a != tokens.end(); ++a) +// { +// printf("%s\n", a->c_str()); +// } + + /* 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; + return 0; */ } DEFINE_REF(eDVBChannelQuery);