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;
RESULT eDVBService::getName(const eServiceReference &ref, std::string &name)
{
- name = convertDVBUTF8(m_service_name);
+ name = m_service_name;
return 0;
}
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;
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;
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)
/* 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;
std::string type, op, val;
res = new eDVBChannelQuery();
+ res->m_sort = 0;
int cnt = 0;
while (begin != end)
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 == "!=")
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;
// {
// 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);
public:
eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query);
virtual RESULT getNextResult(eServiceReferenceDVB &ref);
+
+ int compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b);
};
#endif
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;
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);
};
{
public:
virtual RESULT getNextResult(eServiceReferenceDVB &ref)=0;
+ virtual int compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)=0;
};
class eDVBChannelQuery: public iObject
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;
def setRoot(self, root):
self.l.setRoot(root)
+ self.l.sort()
# mark stuff
def clearMarked(self):
/* 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:
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()
void setElementPosition(int element, eRect where);
void setElementFont(int element, gFont *font);
+ void sort();
+
protected:
void cursorHome();
void cursorEnd();
{
ASSERT(ref == m_ref);
name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
+ return 0;
}
int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
{
}
-RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
+RESULT eDVBServiceList::startQuery()
{
ePtr<iDVBChannelList> db;
ePtr<eDVBResourceManager> res;
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)
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;
}
eDebug("starting DVB service");
r = m_service_handler.tune((eServiceReferenceDVB&)m_reference);
m_event(this, evStart);
+ return 0;
}
RESULT eDVBServicePlay::stop()
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;
}
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
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");
RESULT getContent(std::list<eServiceReference> &list);
RESULT getNext(eServiceReference &ptr);
+ int compareLessEqual(const eServiceReference &, const eServiceReference &);
};
#endif