aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFelix Domke <tmbinc@elitedvb.net>2005-10-09 03:32:46 +0000
committerFelix Domke <tmbinc@elitedvb.net>2005-10-09 03:32:46 +0000
commit32e4324b9b5e615a84885b9132505e4706ededfe (patch)
tree59a0679a05553423489f3dc7fb9d0f3bae7225b0 /lib
parent699d41f217b6d8e91dce499964f8c1a69f5602ed (diff)
downloadenigma2-32e4324b9b5e615a84885b9132505e4706ededfe.tar.gz
enigma2-32e4324b9b5e615a84885b9132505e4706ededfe.zip
service: add sort of servicelist including all required layers
Diffstat (limited to 'lib')
-rw-r--r--lib/dvb/db.cpp136
-rw-r--r--lib/dvb/db.h2
-rw-r--r--lib/dvb/idvb.h9
-rw-r--r--lib/python/Components/ServiceList.py1
-rw-r--r--lib/service/iservice.h19
-rw-r--r--lib/service/listboxservice.cpp13
-rw-r--r--lib/service/listboxservice.h2
-rw-r--r--lib/service/servicedvb.cpp54
-rw-r--r--lib/service/servicedvb.h11
-rw-r--r--lib/service/servicefs.cpp12
-rw-r--r--lib/service/servicefs.h1
11 files changed, 215 insertions, 45 deletions
diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp
index fdcd428d..314a96ec 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,7 @@ eDVBService &eDVBService::operator=(const eDVBService &s)
RESULT eDVBService::getName(const eServiceReference &ref, std::string &name)
{
- name = convertDVBUTF8(m_service_name);
+ name = m_service_name;
return 0;
}
@@ -45,7 +46,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;
@@ -213,7 +214,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;
@@ -416,10 +421,62 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
if (res)
return 0;
}
+
+ ref = eServiceReferenceDVB();
return 1;
}
-/* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[AND (..)] */
+int eDVBDBQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
+{
+ ePtr<eDVBService> 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 1;
+ case eDVBChannelQuery::tSatellitePosition:
+ return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16);
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+/* (<name|provider|type|bouquet|satpos|chid> <==|...> <"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<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
@@ -449,12 +506,16 @@ RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::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<eDVBChannelQuery> r2 = res;
res = new eDVBChannelQuery();
+ res->m_sort = 0;
res->m_p1 = r2;
res->m_inverse = 0;
r2 = 0;
@@ -479,6 +540,7 @@ RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::cons
std::string type, op, val;
res = new eDVBChannelQuery();
+ res->m_sort = 0;
int cnt = 0;
while (begin != end)
@@ -509,27 +571,15 @@ RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::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 == "!=")
@@ -554,7 +604,7 @@ RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
std::string current_token;
-// eDebug("splitting %s....", query.c_str());
+ eDebug("splitting %s....", query.c_str());
unsigned int i = 0;
const char *splitchars="()";
int quotemode = 0, lastsplit = 0, lastalnum = 0;
@@ -594,15 +644,45 @@ RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
// {
// printf("%s\n", a->c_str());
// }
+
+ int sort = eDVBChannelQuery::tName;
+ /* check for "ORDER BY ..." */
+ if (tokens.size() > 2)
+ {
+ std::list<std::string>::iterator i = tokens.end();
+ --i; --i; --i;
+ if (*i == "ORDER")
+ {
+ ++i;
+ if (*i == "BY")
+ {
+ ++i;
+ sort = decodeType(*i);
+ tokens.pop_back(); // ...
+ tokens.pop_back(); // BY
+ tokens.pop_back(); // ORDER
+ } else
+ sort = -1;
+ }
+ }
+
+ 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;
+
+ eDebug("return: %d", r);
+ return r;
}
DEFINE_REF(eDVBChannelQuery);
diff --git a/lib/dvb/db.h b/lib/dvb/db.h
index 084c877a..604d5288 100644
--- a/lib/dvb/db.h
+++ b/lib/dvb/db.h
@@ -56,6 +56,8 @@ private:
public:
eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query);
virtual RESULT getNextResult(eServiceReferenceDVB &ref);
+
+ int compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b);
};
#endif
diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h
index add9ba85..d94bf5fd 100644
--- a/lib/dvb/idvb.h
+++ b/lib/dvb/idvb.h
@@ -180,7 +180,8 @@ public:
bool cacheEmpty() { return m_cache.empty(); }
eDVBService();
- std::string m_service_name;
+ /* m_service_name_sort is uppercase, with special chars removed, to increase sort performance. */
+ std::string m_service_name, m_service_name_sort;
std::string m_provider_name;
int m_flags;
@@ -194,7 +195,7 @@ public:
RESULT getName(const eServiceReference &ref, std::string &name);
int getLength(const eServiceReference &ref);
- // for filtering:
+ /* for filtering: */
int checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQuery &query);
};
@@ -208,6 +209,7 @@ class iDVBChannelListQuery: public iObject
{
public:
virtual RESULT getNextResult(eServiceReferenceDVB &ref)=0;
+ virtual int compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)=0;
};
class eDVBChannelQuery: public iObject
@@ -233,6 +235,9 @@ public:
int m_int;
eDVBChannelID m_channelid;
+ /* sort is only valid in root, and must be from the enum above. */
+ int m_sort;
+
static RESULT compile(ePtr<eDVBChannelQuery> &res, std::string query);
ePtr<eDVBChannelQuery> m_p1, m_p2;
diff --git a/lib/python/Components/ServiceList.py b/lib/python/Components/ServiceList.py
index 73727403..93c79296 100644
--- a/lib/python/Components/ServiceList.py
+++ b/lib/python/Components/ServiceList.py
@@ -32,6 +32,7 @@ class ServiceList(HTMLComponent, GUIComponent):
def setRoot(self, root):
self.l.setRoot(root)
+ self.l.sort()
# mark stuff
def clearMarked(self):
diff --git a/lib/service/iservice.h b/lib/service/iservice.h
index 54d7b11f..d0dc1e2b 100644
--- a/lib/service/iservice.h
+++ b/lib/service/iservice.h
@@ -250,10 +250,29 @@ public:
/* new, shiny interface: streaming. */
virtual SWIG_VOID(RESULT) getNext(eServiceReference &SWIG_OUTPUT)=0;
+
+ /* use this for sorting. output is not sorted because of either
+ - performance reasons: the whole list must be buffered or
+ - the interface would be restricted to a list. streaming
+ (as well as a future "active" extension) won't be possible.
+ */
+ virtual int compareLessEqual(const eServiceReference &, const eServiceReference &)=0;
};
TEMPLATE_TYPEDEF(ePtr<iListableService>, iListableServicePtr);
+ /* a helper class which can be used as argument to stl's sort(). */
+class iListableServiceCompare
+{
+ ePtr<iListableService> m_list;
+public:
+ iListableServiceCompare(iListableService *list): m_list(list) { }
+ bool operator()(const eServiceReference &a, const eServiceReference &b)
+ {
+ return m_list->compareLessEqual(a, b);
+ }
+};
+
class iServiceOfflineOperations: public iObject
{
public:
diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp
index 07838722..d4cbff20 100644
--- a/lib/service/listboxservice.cpp
+++ b/lib/service/listboxservice.cpp
@@ -108,6 +108,19 @@ void eListboxServiceContent::setElementFont(int element, gFont *font)
m_element_font[element] = font;
}
+void eListboxServiceContent::sort()
+{
+ ePtr<iListableService> lst;
+ if (!m_service_center->list(m_root, lst))
+ {
+ m_list.sort(iListableServiceCompare(lst));
+ /* FIXME: is this really required or can we somehow keep the current entry? */
+ cursorHome();
+ if (m_listbox)
+ m_listbox->entryReset();
+ }
+}
+
DEFINE_REF(eListboxServiceContent);
eListboxServiceContent::eListboxServiceContent()
diff --git a/lib/service/listboxservice.h b/lib/service/listboxservice.h
index f560b627..4e5a8dd5 100644
--- a/lib/service/listboxservice.h
+++ b/lib/service/listboxservice.h
@@ -45,6 +45,8 @@ public:
void setElementPosition(int element, eRect where);
void setElementFont(int element, gFont *font);
+ void sort();
+
protected:
void cursorHome();
void cursorEnd();
diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp
index ca08d481..a29b77ce 100644
--- a/lib/service/servicedvb.cpp
+++ b/lib/service/servicedvb.cpp
@@ -36,6 +36,7 @@ RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, st
{
ASSERT(ref == m_ref);
name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
+ return 0;
}
int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
@@ -133,7 +134,7 @@ eDVBServiceList::~eDVBServiceList()
{
}
-RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
+RESULT eDVBServiceList::startQuery()
{
ePtr<iDVBChannelList> db;
ePtr<eDVBResourceManager> res;
@@ -150,30 +151,50 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
return err;
}
- ePtr<iDVBChannelListQuery> query;
-
ePtr<eDVBChannelQuery> q;
if (m_parent.path.size())
+ {
eDVBChannelQuery::compile(q, m_parent.path);
+ if (!q)
+ {
+ eDebug("compile query failed");
+ return err;
+ }
+ }
- if ((err = db->startQuery(query, q)) != 0)
+ if ((err = db->startQuery(m_query, q)) != 0)
{
eDebug("startQuery failed");
return err;
}
-
+
+ return 0;
+}
+
+RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
+{
eServiceReferenceDVB ref;
- while (!query->getNextResult(ref))
+ if (!m_query)
+ return -1;
+
+ while (!m_query->getNextResult(ref))
list.push_back(ref);
return 0;
}
-RESULT eDVBServiceList::getNext(eServiceReference &)
+RESULT eDVBServiceList::getNext(eServiceReference &ref)
{
- /* implement me */
- return -1;
+ if (!m_query)
+ return -1;
+
+ return m_query->getNextResult((eServiceReferenceDVB&)ref);
+}
+
+int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
+{
+ return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
}
RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
@@ -195,7 +216,14 @@ RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordable
RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
{
- ptr = new eDVBServiceList(ref);
+ ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
+ if (list->startQuery())
+ {
+ ptr = 0;
+ return -1;
+ }
+
+ ptr = list;
return 0;
}
@@ -389,6 +417,7 @@ RESULT eDVBServicePlay::start()
eDebug("starting DVB service");
r = m_service_handler.tune((eServiceReferenceDVB&)m_reference);
m_event(this, evStart);
+ return 0;
}
RESULT eDVBServicePlay::stop()
@@ -459,8 +488,11 @@ RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
RESULT eDVBServicePlay::getName(std::string &name)
{
if (m_dvb_service)
+ {
m_dvb_service->getName(m_reference, name);
- else
+ if (name.empty())
+ name = "(...)";
+ } else
name = "DVB service";
return 0;
}
diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h
index accdd20d..57dca9a0 100644
--- a/lib/service/servicedvb.h
+++ b/lib/service/servicedvb.h
@@ -28,14 +28,17 @@ private:
class eDVBServiceList: public iListableService
{
DECLARE_REF(eDVBServiceList);
-private:
- eServiceReference m_parent;
- friend class eServiceFactoryDVB;
- eDVBServiceList(const eServiceReference &parent);
public:
virtual ~eDVBServiceList();
RESULT getContent(std::list<eServiceReference> &list);
RESULT getNext(eServiceReference &ptr);
+ int compareLessEqual(const eServiceReference &a, const eServiceReference &b);
+private:
+ RESULT startQuery();
+ eServiceReference m_parent;
+ friend class eServiceFactoryDVB;
+ eDVBServiceList(const eServiceReference &parent);
+ ePtr<iDVBChannelListQuery> m_query;
};
class eDVBServicePlay: public iPlayableService, iSeekableService, public Object, public iServiceInformation
diff --git a/lib/service/servicefs.cpp b/lib/service/servicefs.cpp
index 057498d7..c5846abd 100644
--- a/lib/service/servicefs.cpp
+++ b/lib/service/servicefs.cpp
@@ -163,4 +163,16 @@ RESULT eServiceFS::getNext(eServiceReference &ptr)
return 0;
}
+int eServiceFS::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
+{
+ /* directories first */
+ if ((a.flags & ~b.flags) & eServiceReference::isDirectory)
+ return 1;
+ else if ((~a.flags & b.flags) & eServiceReference::isDirectory)
+ return 0;
+ /* sort by filename */
+ else
+ return a.path < b.path;
+}
+
eAutoInitPtr<eServiceFactoryFS> init_eServiceFactoryFS(eAutoInitNumbers::service+1, "eServiceFactoryFS");
diff --git a/lib/service/servicefs.h b/lib/service/servicefs.h
index 73bfd985..3400fb85 100644
--- a/lib/service/servicefs.h
+++ b/lib/service/servicefs.h
@@ -36,6 +36,7 @@ public:
RESULT getContent(std::list<eServiceReference> &list);
RESULT getNext(eServiceReference &ptr);
+ int compareLessEqual(const eServiceReference &, const eServiceReference &);
};
#endif