From: Andreas Monzner Date: Sat, 29 Oct 2005 14:39:20 +0000 (+0000) Subject: add bouquet support X-Git-Tag: 2.6.0~5432 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/ff84dc4ee5f57e24a0777930d5482ee4ff53da0e add bouquet support --- diff --git a/data/keymap.xml b/data/keymap.xml index c0d01185..371e53a3 100644 --- a/data/keymap.xml +++ b/data/keymap.xml @@ -75,18 +75,17 @@ - - + + - - + diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index a5a9a456..7ed27d6b 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -31,7 +31,10 @@ eDVBService &eDVBService::operator=(const eDVBService &s) RESULT eDVBService::getName(const eServiceReference &ref, std::string &name) { - name = m_service_name; + if ( ref.name.length() ) + name = ref.name; + else + name = m_service_name; return 0; } @@ -338,9 +341,114 @@ 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; + eDebug("read bouquet %s", tmp.toString().c_str()); + } + 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() @@ -394,39 +502,62 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr &query, eDVBChannelQuery *q) +RESULT eDVBDB::getBouquet(const eServiceReference &ref, const eBouquet* &bouquet) { - query = new eDVBDBQuery(this, eServiceReference(), q); + 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); + eDebug("str now %s", str.c_str()); + pos = str.find('"'); + if ( pos != std::string::npos ) + str.erase(pos); + else + str.clear(); + eDebug("str now %s", str.c_str()); + } + 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; } -DEFINE_REF(eDVBDBQuery); - -eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query): m_db(db), m_query(query) +RESULT eDVBDB::startQuery(ePtr &query, eDVBChannelQuery *q, const eServiceReference &source) { - // TODO: use SOURCE ... - m_cursor = m_db->m_services.begin(); + if ( q && q->m_bouquet_name.length() ) + { + eDebug("bouquet"); + query = new eDVBDBBouquetQuery(this, source, q); + } + else + query = new eDVBDBQuery(this, source, q); + return 0; } -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); +DEFINE_REF(eDVBDBQueryBase); - ++m_cursor; - - if (res) - return 0; - } - - ref = eServiceReferenceDVB(); - return 1; +eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :m_db(db), m_query(query), m_source(source) +{ } -int eDVBDBQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b) +int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b) { ePtr a_service, b_service; @@ -449,7 +580,7 @@ int eDVBDBQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceR case eDVBChannelQuery::tType: return a.getServiceType() < b.getServiceType(); case eDVBChannelQuery::tBouquet: - return 1; + return 0; case eDVBChannelQuery::tSatellitePosition: return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16); default: @@ -458,6 +589,59 @@ int eDVBDBQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceR return 0; } +eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query) + :eDVBDBQueryBase(db, source, query) +{ + m_cursor = m_db->m_services.begin(); +} + +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>)[||,&& (..)] */ static int decodeType(const std::string &type) @@ -603,7 +787,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="()"; @@ -647,27 +832,42 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) int sort = eDVBChannelQuery::tName; /* check for "ORDER BY ..." */ - if (tokens.size() > 2) + + while (tokens.size() > 2) { - std::list::iterator i = tokens.end(); - --i; --i; --i; - if (*i == "ORDER") + std::list::iterator it = tokens.end(); + --it; --it; --it; + if (*it == "ORDER") { - ++i; - if (*i == "BY") + ++it; + if (*it == "BY") { - ++i; - sort = decodeType(*i); + ++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; @@ -679,7 +879,10 @@ RESULT eDVBChannelQuery::compile(ePtr &res, std::string query) 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; diff --git a/lib/dvb/db.h b/lib/dvb/db.h index 604d5288..265c5970 100644 --- a/lib/dvb/db.h +++ b/lib/dvb/db.h @@ -1,21 +1,17 @@ #ifndef __db_h #define __db_h +#include #include #include class ServiceDescriptionSection; -struct eDVBBouquet -{ - std::vector m_services; - int lookupService(eServiceReferenceDVB &ref); -}; - class eDVBDB: public iDVBChannelList { DECLARE_REF(eDVBDB); friend class eDVBDBQuery; + friend class eDVBDBBouquetQuery; private: struct channel { @@ -26,10 +22,16 @@ private: std::map > m_services; - std::map m_bouquets; + std::map m_bouquets; public: void load(); void save(); + + void loadBouquet(const char *path); + void saveBouquet(const char *path); + void loadBouquets(); + void saveBouquets(); + eDVBDB(); virtual ~eDVBDB(); @@ -40,24 +42,40 @@ public: RESULT addService(const eServiceReferenceDVB &service, eDVBService *service); RESULT getService(const eServiceReferenceDVB &reference, ePtr &service); - - RESULT startQuery(ePtr &query, eDVBChannelQuery *query); + + RESULT startQuery(ePtr &query, eDVBChannelQuery *query, const eServiceReference &source); + + RESULT getBouquet(const eServiceReference &ref, const eBouquet* &bouquet); }; // we have to add a possibility to invalidate here. -class eDVBDBQuery: public iDVBChannelListQuery +class eDVBDBQueryBase: public iDVBChannelListQuery { -DECLARE_REF(eDVBDBQuery); -private: +DECLARE_REF(eDVBDBQueryBase); +protected: std::map >::iterator m_cursor; ePtr m_db; ePtr m_query; eServiceReference m_source; public: - eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query); - virtual RESULT getNextResult(eServiceReferenceDVB &ref); - + eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query); int compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b); }; +class eDVBDBQuery: public eDVBDBQueryBase +{ + std::map >::iterator m_cursor; +public: + eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query); + RESULT getNextResult(eServiceReferenceDVB &ref); +}; + +class eDVBDBBouquetQuery: public eDVBDBQueryBase +{ + std::list::iterator m_cursor; +public: + eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query); + RESULT getNextResult(eServiceReferenceDVB &ref); +}; + #endif diff --git a/lib/dvb/frontend.cpp b/lib/dvb/frontend.cpp index a4ad170d..37ce13a6 100644 --- a/lib/dvb/frontend.cpp +++ b/lib/dvb/frontend.cpp @@ -6,6 +6,10 @@ #include #include +#ifndef I2C_SLAVE_FORCE +#define I2C_SLAVE_FORCE 0x0706 +#endif + #if HAVE_DVB_API_VERSION < 3 #include #include diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index f5d3d2ee..d353611d 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -15,6 +15,13 @@ #include #include +struct eBouquet +{ + std::string m_bouquet_name; + std::string m_path; + std::list m_services; +}; + // bitte KEINE operator int() definieren, sonst bringt das ganze nix! struct eTransportStreamID { @@ -237,6 +244,7 @@ public: /* sort is only valid in root, and must be from the enum above. */ int m_sort; + std::string m_bouquet_name; static RESULT compile(ePtr &res, std::string query); @@ -254,7 +262,9 @@ public: virtual RESULT addService(const eServiceReferenceDVB &service, eDVBService *service)=0; virtual RESULT getService(const eServiceReferenceDVB &reference, ePtr &service)=0; - virtual RESULT startQuery(ePtr &query, eDVBChannelQuery *query)=0; + virtual RESULT getBouquet(const eServiceReference &ref, const eBouquet* &bouquet)=0; + + virtual RESULT startQuery(ePtr &query, eDVBChannelQuery *query, const eServiceReference &source)=0; }; class SatelliteDeliverySystemDescriptor; diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index 8b9f9b8c..43b4cd92 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -122,17 +122,22 @@ class ChannelSelection(Screen): # ... def channelSelected(self): - if not (self.movemode): - self.session.nav.playService(self["list"].getCurrent()) - print "current: " + self["list"].getCurrent().toString() - self.close() - else: + ref = self["list"].getCurrent() + if self.movemode: if self.entry_marked: self["list"].setCurrentMarked(False) self.entry_marked = False else: self["list"].setCurrentMarked(True) self.entry_marked = True + elif (ref.flags & 7) == 7: + l = self["list"] + l.setMode(l.MODE_NORMAL) + l.setRoot(ref) + else: + self.session.nav.playService(ref) + print "current: " + ref.toString() + self.close() #called from infoBar def zap(self): diff --git a/lib/service/iservice.h b/lib/service/iservice.h index abbeb1a2..92224f80 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -44,6 +44,10 @@ public: int data[8]; std::string path; +// only for override service names in bouquets or to give servicerefs a name which not have a +// real existing service ( for dvb eServiceDVB ) + std::string name; + eServiceReference() : type(idInvalid), flags(0) { diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 86ed83d2..51061c37 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -13,6 +13,80 @@ #include #include +class eStaticServiceDVBInformation: public iStaticServiceInformation +{ + DECLARE_REF(eStaticServiceDVBInformation); +public: + RESULT getName(const eServiceReference &ref, std::string &name); + int getLength(const eServiceReference &ref); +}; + +DEFINE_REF(eStaticServiceDVBInformation); + +RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name) +{ + if ( ref.name.length() ) + { + name = ref.name; + return 0; + } + else + return -1; +} + +int eStaticServiceDVBInformation::getLength(const eServiceReference &ref) +{ + return -1; +} + +class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation +{ + DECLARE_REF(eStaticServiceDVBBouquetInformation); +public: + RESULT getName(const eServiceReference &ref, std::string &name); + int getLength(const eServiceReference &ref); +}; + +DEFINE_REF(eStaticServiceDVBBouquetInformation); + +RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name) +{ + ePtr db; + ePtr res; + + int err; + if ((err = eDVBResourceManager::getInstance(res)) != 0) + { + eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!"); + return err; + } + if ((err = res->getChannelList(db)) != 0) + { + eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!"); + return err; + } + + const eBouquet *bouquet=0; + if ((err = db->getBouquet(ref, bouquet)) != 0) + { + eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!"); + return -1; + } + + if ( bouquet && bouquet->m_bouquet_name.length() ) + { + name = "[Bouquet] " + bouquet->m_bouquet_name; + return 0; + } + else + return -1; +} + +int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref) +{ + return -1; +} + class eStaticServiceDVBPVRInformation: public iStaticServiceInformation { DECLARE_REF(eStaticServiceDVBPVRInformation); @@ -163,7 +237,7 @@ RESULT eDVBServiceList::startQuery() } } - if ((err = db->startQuery(m_query, q)) != 0) + if ((err = db->startQuery(m_query, q, m_parent)) != 0) { eDebug("startQuery failed"); return err; @@ -230,18 +304,25 @@ RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr &ptr) { /* do we have a PVR service? */ - if (ref.path.size()) + if (ref.flags & eServiceReference::flagDirectory) // bouquet + { + ptr = new eStaticServiceDVBBouquetInformation; + return 0; + } + else if (ref.path.size()) { ptr = new eStaticServiceDVBPVRInformation(ref); return 0; - } else + } + else { ePtr service; int r = lookupService(service, ref); if (r) - return r; + ptr = new eStaticServiceDVBInformation; + else /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */ - ptr = service; + ptr = service; return 0; } }