X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/f973710dc6bcfc13f8db4e5720dd2aeb1518b012..193333b7bc72ab13d4dee5750b31c3c33041c696:/lib/dvb/db.cpp diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index 33a422f8..64ef6ed7 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -66,7 +66,7 @@ RESULT eBouquet::moveService(const eServiceReference &ref, unsigned int pos) RESULT eBouquet::flushChanges() { - FILE *f=fopen(m_path.c_str(), "wt"); + 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 ) @@ -103,26 +103,42 @@ RESULT eBouquet::flushChanges() return 0; err: fclose(f); - eDebug("couldn't write file %s", m_path.c_str()); + 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) { + 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; +} + 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; - m_cache = s.m_cache; +// m_ca = s.m_ca; + memcpy(m_cache, s.m_cache, sizeof(m_cache)); return *this; } @@ -132,7 +148,7 @@ void eDVBService::genSortName() 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"; @@ -140,7 +156,7 @@ void eDVBService::genSortName() RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { - if (!ref.name.empty()) + if (!ref.name.empty()) name = ref.name; // use renamed service name.. else if (!m_service_name.empty()) name = m_service_name; @@ -187,7 +203,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: { @@ -202,6 +221,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) @@ -212,26 +234,37 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ int eDVBService::getCachePID(cacheID id) { - std::map::iterator it = m_cache.find(id); - if ( it != m_cache.end() ) - return it->second; - return -1; + if (id >= cacheMax) + return -1; + return m_cache[id]; } void eDVBService::setCachePID(cacheID id, int pid) { - m_cache[id] = pid; + if (id < cacheMax) + 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)) { @@ -273,14 +306,21 @@ void eDVBDB::load() if (line[1]=='s') { 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, &orbital_position, &inversion); + 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); sat.frequency = frequency; 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; + sat.system = system; + sat.modulation = modulation; + sat.roll_off = rolloff; feparm->setDVBS(sat); } else if (line[1]=='t') { @@ -296,13 +336,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); @@ -344,11 +392,10 @@ void eDVBDB::load() s->m_service_name = line; 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) @@ -380,12 +427,12 @@ void eDVBDB::load() int cid, val; sscanf(v.c_str(), "%02d%04x", &cid, &val); s->m_cache[cid]=val; - } else if (p == 'C') + }/* else if (p == 'C') { int val; sscanf(v.c_str(), "%04x", &val); s->m_ca.insert(val); - } + }*/ } addService(ref, s); } @@ -395,10 +442,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!"); @@ -414,12 +461,28 @@ 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.inversion); + if (sat.system == eDVBFrontendParametersSatellite::System::DVB_S2) + { + fprintf(f, "\ts %d:%d:%d:%d:%d:%d:%d:%d:%d\n", + 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); + } + else + { + fprintf(f, "\ts %d:%d:%d:%d:%d:%d\n", + sat.frequency, sat.symbol_rate, + sat.polarisation, sat.fec, + sat.orbital_position > 1800 ? sat.orbital_position - 3600 : sat.orbital_position, + sat.inversion); + } } if (!ch.m_frontendParameters->getDVBT(ter)) { @@ -428,6 +491,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++; } @@ -444,17 +512,23 @@ 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 - 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) + if (i->second->m_cache[x] != -1) + fprintf(f, ",c:%02d%04x", x, i->second->m_cache[x]); +/* // 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); +*/ + + if (i->second->m_flags) + fprintf(f, ",f:%x", i->second->m_flags); fprintf(f, "\n"); services++; @@ -481,15 +555,24 @@ 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") ) { @@ -530,18 +613,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); @@ -563,15 +645,16 @@ void eDVBDB::loadBouquet(const char *path) eDebug("%d entries in Bouquet %s", entries, bouquet_name.c_str()); } -void eDVBDB::loadBouquets() +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_path = "userbouquet.favourites.tv"; + b.m_filename = "userbouquet.favourites.tv"; b.m_bouquet_name = "Favourites (TV)"; b.flushChanges(); eServiceReference ref; @@ -587,14 +670,14 @@ void eDVBDB::loadBouquets() if ( m_bouquets.find("userbouquet.favourites.radio") == m_bouquets.end() ) { eBouquet &b = m_bouquets["userbouquet.favourites.radio"]; - b.m_path = "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]=1; + 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); @@ -602,15 +685,171 @@ void eDVBDB::loadBouquets() } } +eDVBDB *eDVBDB::instance; + eDVBDB::eDVBDB() { - load(); - loadBouquets(); + instance = this; + reloadServicelist(); } eDVBDB::~eDVBDB() { -// save(); + instance=NULL; +} + +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); +} + +RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos) +{ + 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; +} + +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) +{ + 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) @@ -642,7 +881,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; } @@ -661,7 +902,7 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &query, eDVBChannelQuery *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) @@ -829,7 +1086,15 @@ RESULT eDVBDBListQuery::getNextResult(eServiceReferenceDVB &ref) int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b) { if ( m_query->m_sort == eDVBChannelQuery::tSatellitePosition ) - return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16); + { + 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; } @@ -855,8 +1120,8 @@ eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference eServiceReferenceDVB ref; ref.setDVBNamespace(dvbnamespace); ref.flags=eServiceReference::flagDirectory; - char buf[64]; - snprintf(buf, 64, "(satellitePosition == %d) && ", dvbnamespace>>16); + char buf[128]; + snprintf(buf, 128, "(satellitePosition == %d) && ", dvbnamespace>>16); ref.path=buf+source.path; unsigned int pos=ref.path.find("FROM"); @@ -869,6 +1134,14 @@ eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference 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); } @@ -933,6 +1206,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; } @@ -941,6 +1216,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; @@ -1157,6 +1439,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;