X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/461b3a99fd4128ad8a3b00dc0acbe28a73ecdd0d..23cc33141cdf93dad750965ee559849aa99410a3:/lib/dvb/db.cpp diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index de2de1e4..65b37862 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -1,6 +1,8 @@ #include #include +#include #include +#include #include #include #include @@ -34,24 +36,85 @@ RESULT eBouquet::moveService(const eServiceReference &ref, unsigned int pos) { if ( pos < 0 || pos >= m_services.size() ) return -1; + ++pos; list::iterator source=m_services.end(); list::iterator dest=m_services.end(); + bool forward = false; for (list::iterator it(m_services.begin()); it != m_services.end(); ++it) { - if (dest == m_services.end() && !pos--) + if (dest == m_services.end() && !--pos) dest = it; if (*it == ref) + { source = it; + forward = pos>0; + } if (dest != m_services.end() && source != m_services.end()) break; } if (dest == m_services.end() || source == m_services.end() || source == dest) return -1; - std::iter_swap(source,dest); + while (source != dest) + { + if (forward) + std::iter_swap(source++, source); + else + std::iter_swap(source--, source); + } + return 0; +} + +RESULT eBouquet::flushChanges() +{ + FILE *f=fopen((CONFIGDIR"/enigma2/"+m_filename).c_str(), "w"); + if (!f) + return -1; + if ( fprintf(f, "#NAME %s\r\n", m_bouquet_name.c_str()) < 0 ) + goto err; + for (list::iterator i(m_services.begin()); i != m_services.end(); ++i) + { + 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() ) + if ( fprintf(f, "#DESCRIPTION %s\r\n", i->name.c_str()) < 0 ) + goto err; + } + fclose(f); + return 0; +err: + fclose(f); + eDebug("couldn't write file %s", m_filename.c_str()); + return -1; +} + +RESULT eBouquet::setListName(const std::string &name) +{ + m_bouquet_name = name; return 0; } eDVBService::eDVBService() + :m_flags(0) { } @@ -70,10 +133,22 @@ eDVBService &eDVBService::operator=(const eDVBService &s) return *this; } +void eDVBService::genSortName() +{ + m_service_name_sort = removeDVBChars(m_service_name); + makeUpper(m_service_name_sort); + while ((!m_service_name_sort.empty()) && m_service_name_sort[0] == ' ') + m_service_name_sort.erase(0, 1); + + /* put unnamed services at the end, not at the beginning. */ + if (m_service_name_sort.empty()) + m_service_name_sort = "\xFF"; +} + RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { if (!ref.name.empty()) - name = ref.name; + name = ref.name; // use renamed service name.. else if (!m_service_name.empty()) name = m_service_name; else @@ -81,9 +156,24 @@ RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) return 0; } -int eDVBService::getLength(const eServiceReference &ref) +RESULT eDVBService::getEvent(const eServiceReference &ref, ePtr &ptr, time_t start_time) { - return -1; + return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr); +} + +bool eDVBService::isPlayable(const eServiceReference &ref, const eServiceReference &ignore) +{ + ePtr res_mgr; + if ( eDVBResourceManager::getInstance( res_mgr ) ) + eDebug("isPlayble... no res manager!!"); + else + { + eDVBChannelID chid, chid_ignore; + ((const eServiceReferenceDVB&)ref).getChannelID(chid); + ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore); + return res_mgr->canAllocateChannel(chid, chid_ignore); + } + return false; } int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query) @@ -104,7 +194,10 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ res = 0; break; case eDVBChannelQuery::tSatellitePosition: - res = (ref.getDVBNamespace().get() >> 16) == query.m_int; + res = ((unsigned int)ref.getDVBNamespace().get())>>16 == (unsigned int)query.m_int; + break; + case eDVBChannelQuery::tFlags: + res = (m_flags & query.m_int) == query.m_int; break; case eDVBChannelQuery::tChannelID: { @@ -119,6 +212,9 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ case eDVBChannelQuery::tOR: res = checkFilter(ref, *query.m_p1) || checkFilter(ref, *query.m_p2); break; + case eDVBChannelQuery::tAny: + res = 1; + break; } if (query.m_inverse) @@ -137,18 +233,32 @@ int eDVBService::getCachePID(cacheID id) void eDVBService::setCachePID(cacheID id, int pid) { - m_cache[id] = pid; + if (pid == -1) + m_cache.erase(id); + else + m_cache[id] = pid; } DEFINE_REF(eDVBDB); /* THIS CODE IS BAD. it should be replaced by somethine better. */ -void eDVBDB::load() +void eDVBDB::reloadServicelist() { eDebug("---- opening lame channel db"); - FILE *f=fopen("lamedb", "rt"); + FILE *f=fopen(CONFIGDIR"/enigma2/lamedb", "rt"); if (!f) + { + struct stat s; + if ( !stat("lamedb", &s) ) + { + if ( !stat(CONFIGDIR"/enigma2", &s) ) + { + rename("lamedb", CONFIGDIR"/enigma2/lamedb" ); + reloadServicelist(); + } + } return; + } char line[256]; if ((!fgets(line, 256, f)) || strncmp(line, "eDVB services", 13)) { @@ -196,7 +306,8 @@ void eDVBDB::load() sat.symbol_rate = symbol_rate; sat.polarisation = polarisation; sat.fec = fec; - sat.orbital_position = orbital_position; + sat.orbital_position = + orbital_position < 0 ? orbital_position + 3600 : orbital_position; sat.inversion = inversion; feparm->setDVBS(sat); } else if (line[1]=='t') @@ -213,13 +324,21 @@ void eDVBDB::load() 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); -// t.setCable(frequency, symbol_rate, inversion, modulation); + eDVBFrontendParametersCable cab; + int frequency, symbol_rate, + 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); + cab.frequency = frequency; + cab.fec_inner = fec_inner; + cab.inversion = inversion; + cab.symbol_rate = symbol_rate; + cab.modulation = modulation; + feparm->setDVBC(cab); } } addChannelToList(channelid, feparm); @@ -260,19 +379,11 @@ void eDVBDB::load() line[strlen(line)-1]=0; s->m_service_name = line; - s->m_service_name_sort = removeDVBChars(line); - makeUpper(s->m_service_name_sort); - while ((!s->m_service_name_sort.empty()) && s->m_service_name_sort[0] == ' ') - s->m_service_name_sort.erase(0, 1); - - /* put unnamed services at the end, not at the beginning. */ - if (s->m_service_name_sort.empty()) - s->m_service_name_sort = "\xFF"; - + s->genSortName(); + fgets(line, 256, f); if (strlen(line)) line[strlen(line)-1]=0; - std::string str=line; if (str[1]!=':') // old ... (only service_provider) @@ -319,10 +430,10 @@ void eDVBDB::load() fclose(f); } -void eDVBDB::save() +void eDVBDB::saveServicelist() { eDebug("---- saving lame channel db"); - FILE *f=fopen("lamedb", "wt"); + FILE *f=fopen(CONFIGDIR"/enigma2/lamedb", "w"); int channels=0, services=0; if (!f) eFatal("couldn't save lame channel db!"); @@ -338,11 +449,13 @@ void eDVBDB::save() chid.transport_stream_id.get(), chid.original_network_id.get()); eDVBFrontendParametersSatellite sat; eDVBFrontendParametersTerrestrial ter; + eDVBFrontendParametersCable cab; if (!ch.m_frontendParameters->getDVBS(sat)) { fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", sat.frequency, sat.symbol_rate, - sat.polarisation, sat.fec, sat.orbital_position, + sat.polarisation, sat.fec, + sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position, sat.inversion); } if (!ch.m_frontendParameters->getDVBT(ter)) @@ -352,6 +465,11 @@ void eDVBDB::save() ter.code_rate_LP, ter.modulation, ter.transmission_mode, ter.guard_interval, ter.hierarchy, ter.inversion); } + 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); + } fprintf(f, "/\n"); channels++; } @@ -368,6 +486,7 @@ void eDVBDB::save() 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 @@ -380,6 +499,9 @@ void eDVBDB::save() 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); + fprintf(f, "\n"); services++; } @@ -388,49 +510,6 @@ void eDVBDB::save() fclose(f); } -RESULT eBouquet::flushChanges() -{ - FILE *f=fopen(m_path.c_str(), "wt"); - if (!f) - return -1; - if ( fprintf(f, "#NAME %s\r\n", m_bouquet_name.c_str()) < 0 ) - goto err; - for (list::iterator i(m_services.begin()); i != m_services.end(); ++i) - { - 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() ) - if ( fprintf(f, "#DESCRIPTION %s\r\n", i->name.c_str()) < 0 ) - goto err; - } - fclose(f); - return 0; -err: - fclose(f); - eDebug("couldn't write file %s", m_path.c_str()); - return -1; -} - void eDVBDB::loadBouquet(const char *path) { std::string bouquet_name = path; @@ -448,16 +527,37 @@ void eDVBDB::loadBouquet(const char *path) return; } eBouquet &bouquet = m_bouquets[bouquet_name]; - bouquet.m_path = path; + bouquet.m_filename = bouquet_name; std::list &list = bouquet.m_services; list.clear(); - eDebug("loading bouquet... %s", path); - FILE *fp=fopen(path, "rt"); + std::string p = CONFIGDIR"/enigma2/"; + p+=path; + eDebug("loading bouquet... %s", p.c_str()); + FILE *fp=fopen(p.c_str(), "rt"); int entries=0; if (!fp) { + struct stat s; + if ( !stat(path, &s) ) + { + rename(path, p.c_str() ); + loadBouquet(path); + return; + } eDebug("failed to open."); + if ( strstr(path, "bouquets.tv") ) + { + eDebug("recreate bouquets.tv"); + bouquet.m_bouquet_name="Bouquets (TV)"; + bouquet.flushChanges(); + } + else if ( strstr(path, "bouquets.radio") ) + { + eDebug("recreate bouquets.radio"); + bouquet.m_bouquet_name="Bouquets (Radio)"; + bouquet.flushChanges(); + } return; } char line[256]; @@ -485,18 +585,17 @@ void eDVBDB::loadBouquet(const char *path) } if ( (tmp.flags&eServiceReference::flagDirectory) == eServiceReference::flagDirectory ) { - std::string str = tmp.path; - unsigned int pos = str.rfind('/'); + unsigned int pos = tmp.path.rfind('/'); if ( pos != std::string::npos ) - str.erase(0, pos+1); - if (str.empty()) + tmp.path.erase(0, pos+1); + if (tmp.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], str.c_str()); + snprintf(buf, 256, "(type == %d) FROM BOUQUET \"%s\" ORDER BY bouquet", tmp.data[0], tmp.path.c_str()); tmp.path = buf; } list.push_back(tmp); @@ -518,31 +617,211 @@ void eDVBDB::loadBouquet(const char *path) eDebug("%d entries in Bouquet %s", entries, bouquet_name.c_str()); } -void eDVBDB::saveBouquet(const char *path) +void eDVBDB::reloadBouquets() { + m_bouquets.clear(); + loadBouquet("bouquets.tv"); + loadBouquet("bouquets.radio"); +// create default bouquets when missing + if ( m_bouquets.find("userbouquet.favourites.tv") == m_bouquets.end() ) + { + eBouquet &b = m_bouquets["userbouquet.favourites.tv"]; + b.m_filename = "userbouquet.favourites.tv"; + b.m_bouquet_name = "Favourites (TV)"; + b.flushChanges(); + eServiceReference ref; + memset(ref.data, 0, sizeof(ref.data)); + ref.type=1; + ref.flags=7; + ref.data[0]=1; + ref.path="(type == 1) FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet"; + eBouquet &parent = m_bouquets["bouquets.tv"]; + parent.m_services.push_back(ref); + parent.flushChanges(); + } + if ( m_bouquets.find("userbouquet.favourites.radio") == m_bouquets.end() ) + { + eBouquet &b = m_bouquets["userbouquet.favourites.radio"]; + b.m_filename = "userbouquet.favourites.radio"; + b.m_bouquet_name = "Favourites (Radio)"; + b.flushChanges(); + eServiceReference ref; + memset(ref.data, 0, sizeof(ref.data)); + ref.type=1; + ref.flags=7; + ref.data[0]=2; + ref.path="(type == 2) FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet"; + eBouquet &parent = m_bouquets["bouquets.radio"]; + parent.m_services.push_back(ref); + parent.flushChanges(); + } +} +eDVBDB *eDVBDB::instance; + +eDVBDB::eDVBDB() +{ + instance = this; + reloadServicelist(); } -void eDVBDB::loadBouquets() +eDVBDB::~eDVBDB() { - loadBouquet("bouquets.tv"); - loadBouquet("bouquets.radio"); + instance=NULL; } -void eDVBDB::saveBouquets() +RESULT eDVBDB::removeService(const eServiceReference &ref) { + if (ref.type == eServiceReference::idDVB) + { + eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref; + std::map >::iterator it(m_services.find(service)); + if (it != m_services.end()) + { + m_services.erase(it); + return 0; + } + } + return -1; +} +RESULT eDVBDB::removeServices(int dvb_namespace, int tsid, int onid, unsigned int orb_pos) +{ + return removeServices(eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos); } -eDVBDB::eDVBDB() +RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos) { - load(); - loadBouquets(); + RESULT ret=-1; + eDVBNamespace eNs; + eTransportStreamID eTsid; + eOriginalNetworkID eOnid; + std::map::iterator it(m_channels.begin()); + std::set removed_chids; + while (it != m_channels.end()) + { + const eDVBChannelID &ch = it->first; + bool remove=true; + int system; + it->second.m_frontendParameters->getSystem(system); + if ( orbpos != 0xFFFFFFFF && 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.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 ) + remove=false; + if ( remove ) + { + eDebug("remove %08x %04x %04x", + ch.dvbnamespace.get(), + ch.original_network_id.get(), + ch.transport_stream_id.get()); + removed_chids.insert(it->first); + m_channels.erase(it++); + } + else + ++it; + } + if (!removed_chids.empty()) + { + std::map >::iterator service(m_services.begin()); + while(service != m_services.end()) + { + eDVBChannelID chid; + service->first.getChannelID(chid); + std::set::iterator it(removed_chids.find(chid)); + if (it != removed_chids.end()) + m_services.erase(service++); + else + ++service; + ret=0; + } + } + return ret; } -eDVBDB::~eDVBDB() +RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask) +{ + if (ref.type == eServiceReference::idDVB) + { + eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref; + std::map >::iterator it(m_services.find(service)); + if (it != m_services.end()) + it->second->m_flags |= ~flagmask; + return 0; + } + return -1; +} + +RESULT eDVBDB::removeFlag(const eServiceReference &ref, unsigned int flagmask) +{ + if (ref.type == eServiceReference::idDVB) + { + eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref; + std::map >::iterator it(m_services.find(service)); + if (it != m_services.end()) + it->second->m_flags &= ~flagmask; + return 0; + } + return -1; +} + +RESULT eDVBDB::removeFlags(unsigned int flagmask, int dvb_namespace, int tsid, int onid, unsigned int orb_pos) +{ + return removeFlags(flagmask, eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos); +} + +RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orbpos) { -// save(); + eDVBNamespace eNs; + eTransportStreamID eTsid; + eOriginalNetworkID eOnid; + std::map::iterator it(m_channels.begin()); + std::set removed_chids; + while (it != m_channels.end()) + { + const eDVBChannelID &ch = it->first; + bool remove=true; + int system; + it->second.m_frontendParameters->getSystem(system); + if ( orbpos != 0xFFFFFFFF && 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.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 ) + remove=false; + if ( remove ) + removed_chids.insert(it->first); + ++it; + } + if (!removed_chids.empty()) + { + std::map >::iterator service(m_services.begin()); + while(service != m_services.end()) + { + eDVBChannelID chid; + service->first.getChannelID(chid); + std::set::iterator it(removed_chids.find(chid)); + if (it != removed_chids.end()) + service->second->m_flags &= ~flagmask; + ++service; + } + } + return 0; } RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm) @@ -574,7 +853,9 @@ RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr >(serviceref, service)); + std::map >::iterator it(m_services.find(serviceref)); + if (it == m_services.end()) + m_services.insert(std::pair >(serviceref, service)); return 0; } @@ -591,6 +872,12 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &query, eDVBChannelQuery *q, const eServiceReference &source) { - if ( q && q->m_bouquet_name.length() ) - query = new eDVBDBBouquetQuery(this, source, q); + if ( source.path.find("FROM") != std::string::npos ) + { + if ( source.path.find("BOUQUET") != std::string::npos ) + query = new eDVBDBBouquetQuery(this, source, q); + else if ( source.path.find("SATELLITES") != std::string::npos ) + query = new eDVBDBSatellitesQuery(this, source, q); + else if ( source.path.find("PROVIDERS") != std::string::npos ) + query = new eDVBDBProvidersQuery(this, source, q); + else + eFatal("invalid query %s", source.toString().c_str()); + } else query = new eDVBDBQuery(this, source, q); return 0; } +eServiceReference eDVBDB::searchReference(int tsid, int onid, int sid) +{ + eServiceID Sid(sid); + eTransportStreamID Tsid(tsid); + eOriginalNetworkID Onid(onid); + for (std::map >::iterator sit(m_services.begin()); + sit != m_services.end(); ++sit) + { + if (sit->first.getTransportStreamID() == Tsid && + sit->first.getOriginalNetworkID() == Onid && + sit->first.getServiceID() == Sid) + return sit->first; + } + return eServiceReference(); +} + DEFINE_REF(eDVBDBQueryBase); eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) @@ -727,6 +1039,129 @@ RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref) return 1; } +eDVBDBListQuery::eDVBDBListQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBQueryBase(db, source, query), m_cursor(m_list.end()) +{ +} + +RESULT eDVBDBListQuery::getNextResult(eServiceReferenceDVB &ref) +{ + if (m_cursor != m_list.end()) + { + ref = *m_cursor++; + return 0; + } + ref.type = eServiceReference::idInvalid; + return 1; +} + +int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b) +{ + if ( m_query->m_sort == eDVBChannelQuery::tSatellitePosition ) + { + int x = (a.getDVBNamespace().get() >> 16); + int y = (b.getDVBNamespace().get() >> 16); + if ( x > 1800 ) + x -= 3600; + if ( y > 1800 ) + y -= 3600; + return x < y; + } + return a.name < b.name; +} + +eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBListQuery(db, source, query) +{ + 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); + 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) + { + eServiceReferenceDVB ref; + ref.setDVBNamespace(dvbnamespace); + ref.flags=eServiceReference::flagDirectory; + char buf[128]; + snprintf(buf, 128, "(satellitePosition == %d) && ", dvbnamespace>>16); + + ref.path=buf+source.path; + unsigned int pos=ref.path.find("FROM"); + ref.path.erase(pos); + ref.path+="ORDER BY name"; +// eDebug("ref.path now %s", ref.path.c_str()); + m_list.push_back(ref); + + ref.path=buf+source.path; + pos=ref.path.find("FROM"); + ref.path.erase(pos+5); + ref.path+="PROVIDERS ORDER BY name"; +// eDebug("ref.path now %s", ref.path.c_str()); + m_list.push_back(ref); + + snprintf(buf, 128, "(satellitePosition == %d) && (flags == %d) && ", dvbnamespace>>16, eDVBService::dxNewFound); + ref.path=buf+source.path; + pos=ref.path.find("FROM"); + ref.path.erase(pos); + ref.path+="ORDER BY name"; +// eDebug("ref.path now %s", ref.path.c_str()); + m_list.push_back(ref); + } + } + } + m_cursor=m_list.begin(); +} + +eDVBDBProvidersQuery::eDVBDBProvidersQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBListQuery(db, source, query) +{ + 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); + 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) + { + eServiceReferenceDVB ref; + char buf[64]; + ref.name=provider_name; + snprintf(buf, 64, "(provider == \"%s\") && ", provider_name); + ref.path=buf+source.path; + unsigned int pos = ref.path.find("FROM"); + ref.flags=eServiceReference::flagDirectory; + ref.path.erase(pos); + ref.path+="ORDER BY name"; +// eDebug("ref.path now %s", ref.path.c_str()); + m_list.push_back(ref); + } + } + } + m_cursor=m_list.begin(); +} + /* ( <==|...> <"string"|int>)[||,&& (..)] */ static int decodeType(const std::string &type) @@ -743,6 +1178,8 @@ static int decodeType(const std::string &type) return eDVBChannelQuery::tSatellitePosition; else if (type == "channelID") return eDVBChannelQuery::tChannelID; + else if (type == "flags") + return eDVBChannelQuery::tFlags; else return -1; } @@ -751,6 +1188,13 @@ static int decodeType(const std::string &type) RESULT parseExpression(ePtr &res, std::list::const_iterator begin, std::list::const_iterator end) { std::list::const_iterator end_of_exp; + + if (begin == end) + { + eDebug("empty expression!"); + return 0; + } + if (*begin == "(") { end_of_exp = begin; @@ -918,37 +1362,41 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) int sort = eDVBChannelQuery::tName; /* check for "ORDER BY ..." */ - while (tokens.size() > 2) + std::list::iterator it = tokens.begin(); + while (it != tokens.end()) { - std::list::iterator it = tokens.end(); - --it; --it; --it; if (*it == "ORDER") { - ++it; - if (*it == "BY") + tokens.erase(it++); + if (it != tokens.end() && *it == "BY") { - ++it; + tokens.erase(it++); sort = decodeType(*it); - tokens.pop_back(); // ... - tokens.pop_back(); // BY - tokens.pop_back(); // ORDER + tokens.erase(it++); } else sort = -1; } else if (*it == "FROM") { - ++it; - if (*it == "BOUQUET") + tokens.erase(it++); + if (it != tokens.end() && *it == "BOUQUET") { - ++it; + tokens.erase(it++); bouquet_name = *it; - tokens.pop_back(); // ... - tokens.pop_back(); // FROM - tokens.pop_back(); // BOUQUET + tokens.erase(it++); + } + else if (it != tokens.end() && *it == "SATELLITES") + tokens.erase(it++); + else if (it != tokens.end() && *it == "PROVIDERS") + tokens.erase(it++); + else + { + eDebug("FROM unknown %s", (*it).c_str()); + tokens.erase(it++); } } else - break; + ++it; } if (sort == -1) @@ -963,6 +1411,14 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) /* now we recursivly parse that. */ int r = parseExpression(res, tokens.begin(), tokens.end()); + /* we have an empty (but valid!) expression */ + if (!r && !res) + { + res = new eDVBChannelQuery(); + res->m_inverse = 0; + res->m_type = eDVBChannelQuery::tAny; + } + if (res) { res->m_sort = sort;