aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components.py26
-rw-r--r--keymap.xml14
-rw-r--r--keymapparser.py7
-rw-r--r--lib/dvb/db.cpp183
-rw-r--r--lib/dvb/db.h13
-rw-r--r--lib/gui/elistbox.cpp1
-rw-r--r--lib/gui/ewindowstyle.cpp4
-rw-r--r--lib/gui/ewindowstyle.h3
-rw-r--r--lib/service/listboxservice.cpp42
-rw-r--r--lib/service/listboxservice.h12
-rw-r--r--screens.py26
11 files changed, 304 insertions, 27 deletions
diff --git a/components.py b/components.py
index a5df8ffe..abf25f20 100644
--- a/components.py
+++ b/components.py
@@ -277,7 +277,7 @@ class ServiceList(HTMLComponent, GUIComponent):
def __init__(self):
GUIComponent.__init__(self)
self.l = eListboxServiceContent()
-
+
def getCurrent(self):
r = eServiceReference()
self.l.getCurrent(r)
@@ -292,6 +292,19 @@ class ServiceList(HTMLComponent, GUIComponent):
def setRoot(self, root):
self.l.setRoot(root)
+
+ # mark stuff
+ def clearMarked(self):
+ self.l.clearMarked()
+
+ def isMarked(self, ref):
+ return self.l.isMarked(ref)
+
+ def addMarked(self, ref):
+ self.l.addMarked(ref)
+
+ def removeMarked(self, ref):
+ self.l.removeMarked(ref)
class ServiceScan:
@@ -338,20 +351,23 @@ class ServiceScan:
return self.state == self.Done
class ActionMap:
- def __init__(self, context, actions = { }, prio=0):
+ def __init__(self, contexts = [ ], actions = { }, prio=0):
self.actions = actions
- self.context = context
+ self.contexts = contexts
self.prio = prio
self.p = eActionMapPtr()
eActionMap.getInstance(self.p)
def execBegin(self):
- self.p.bindAction(self.context, self.prio, self.action)
+ for ctx in self.contexts:
+ self.p.bindAction(ctx, self.prio, self.action)
def execEnd(self):
- self.p.unbindAction(self.context, self.action)
+ for ctx in self.contexts:
+ self.p.unbindAction(ctx, self.action)
def action(self, context, action):
+ print " ".join(("action -> ", context, action))
try:
self.actions[action]()
except KeyError:
diff --git a/keymap.xml b/keymap.xml
index 82b8a507..e940ba74 100644
--- a/keymap.xml
+++ b/keymap.xml
@@ -13,16 +13,16 @@
<key id="m" mapto="mainMenu" flags="mr" />
<key id="c" mapto="switchChannel" flags="mr" />
</map>
- <map context="MainMenuActions">
- <key id=" " mapto="selected" flags="mr" />
- </map>
<map context="ChannelSelectActions">
- <key id=" " mapto="selectChannel" flags="mr" />
-
+ <key id="m" mapto="mark" flags="m" />
<!-- yes, this is flexible as hell. -->
- <key id="p" mapto="bouquet:PREMIERE" flags="m" />
- <key id="d" mapto="bouquet:Das Erste" flags="m" />
+ <key id="p" mapto="bouquet:(provider == PREMIERE)" flags="m" />
+ <key id="d" mapto="bouquet:(provider == ARD)" flags="m" />
+ </map>
+ <map context="OkCancelActions">
+ <key id="\x0a" mapto="ok" flags="mr" />
+ <key id="\x1b" mapto="cancel" flags="mr" />
</map>
<map context="WindowActions">
diff --git a/keymapparser.py b/keymapparser.py
index 510a47a9..032805b3 100644
--- a/keymapparser.py
+++ b/keymapparser.py
@@ -52,6 +52,13 @@ def readKeymap():
if len(id) == 1:
keyid = ord(id) | 0x8000
+ elif id[0] == '\\':
+ if id[1] == 'x':
+ keyid = int(id[2:], 0x10) | 0x8000
+ elif id[1] == 'd':
+ keyid = int(id[2:]) | 0x8000
+ else:
+ raise "key id '" + str(id) + "' is neither hex nor dec"
else:
try:
keyid = KEYIDS[id]
diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp
index fe4bcc76..4e0332ba 100644
--- a/lib/dvb/db.cpp
+++ b/lib/dvb/db.cpp
@@ -357,13 +357,192 @@ RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
return 1;
}
-RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
+/* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[AND (..)] */
+
+ /* 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)
{
+ std::list<std::string>::const_iterator end_of_exp;
+ if (*begin == "(")
+ {
+ end_of_exp = begin;
+ while (end_of_exp != end)
+ if (*end_of_exp == ")")
+ break;
+ else
+ ++end_of_exp;
+
+ if (end_of_exp == end)
+ {
+ eDebug("expression parse: end of expression while searching for closing brace");
+ return -1;
+ }
+
+ ++begin;
+ // begin..end_of_exp
+ int r = parseExpression(res, begin, end_of_exp);
+ if (r)
+ return r;
+ ++end_of_exp;
+
+ /* we had only one sub expression */
+ if (end_of_exp == end)
+ return 1;
+
+ /* otherwise we have an operator here.. */
+
+ ePtr<eDVBChannelQuery> r2 = res;
+ res = new eDVBChannelQuery();
+ res->m_p1 = r2;
+ res->m_inverse = 0;
+ r2 = 0;
+
+ if (*end_of_exp == "||")
+ res->m_type = eDVBChannelQuery::tOR;
+ else if (*end_of_exp == "&&")
+ res->m_type = eDVBChannelQuery::tAND;
+ else
+ {
+ eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str());
+ res = 0;
+ return 1;
+ }
+
+ ++end_of_exp;
+
+ return parseExpression(res->m_p2, end_of_exp, end);
+ }
+
+ // "begin" <op> "end"
+ std::string type, op, val;
+
+ res = new eDVBChannelQuery();
+
+ int cnt = 0;
+ while (begin != end)
+ {
+ switch (cnt)
+ {
+ case 0:
+ type = *begin;
+ break;
+ case 1:
+ op = *begin;
+ break;
+ case 2:
+ val = *begin;
+ break;
+ case 3:
+ eDebug("malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
+ return 1;
+ }
+ ++begin;
+ ++cnt;
+ }
+
+ if (cnt != 3)
+ {
+ eDebug("malformed query: missing stuff");
+ res = 0;
+ 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
+ {
+ 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 == "!=")
+ res->m_inverse = 1;
+ else
+ {
+ eDebug("invalid operator %s", op.c_str());
+ res = 0;
+ return 1;
+ }
+
+ res->m_string = val;
+ res->m_int = atoi(val.c_str());
+// res->m_channelid = eDVBChannelID(val);
+
+ return 0;
+}
+
+RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, const eServiceReferenceDVB &source, std::string query)
+{
+ std::list<std::string> tokens;
+
+ m_source = source;
+
+ std::string current_token;
+
+// eDebug("splitting %s....", query.c_str());
+ unsigned int i = 0;
+ const char *splitchars="()";
+ int quotemode = 0, lastsplit = 0, lastalnum = 0;
+ while (i <= query.size())
+ {
+ int c = (i < query.size()) ? query[i] : ' ';
+ ++i;
+
+ int issplit = !!strchr(splitchars, c);
+ int isaln = isalnum(c);
+ int iswhite = c == ' ';
+ int isquot = c == '\"';
+
+ if (quotemode)
+ {
+ iswhite = issplit = 0;
+ isaln = lastalnum;
+ }
+
+ if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
+ {
+ if (current_token.size())
+ tokens.push_back(current_token);
+ current_token.clear();
+ }
+
+ if (!(iswhite || isquot))
+ current_token += c;
+
+ if (isquot)
+ quotemode = !quotemode;
+ lastsplit = issplit;
+ lastalnum = isaln;
+ }
+
+// for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
+// {
+// printf("%s\n", a->c_str());
+// }
+
+ /* 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;
+ return 0; */
}
DEFINE_REF(eDVBChannelQuery);
diff --git a/lib/dvb/db.h b/lib/dvb/db.h
index 22eb0b74..7e31a22d 100644
--- a/lib/dvb/db.h
+++ b/lib/dvb/db.h
@@ -6,6 +6,12 @@
class ServiceDescriptionTable;
+struct eDVBBouquet
+{
+ std::vector<eServiceReferenceDVB> m_services;
+ int lookupService(eServiceReferenceDVB &ref);
+};
+
class eDVBDB: public iDVBChannelList
{
DECLARE_REF(eDVBDB);
@@ -19,6 +25,8 @@ private:
std::map<eDVBChannelID, channel> m_channels;
std::map<eServiceReferenceDVB, ePtr<eDVBService> > m_services;
+
+ std::map<eServiceReference, eDVBBouquet> m_bouquets;
public:
eDVBDB();
virtual ~eDVBDB();
@@ -30,7 +38,7 @@ public:
RESULT addService(const eServiceReferenceDVB &service, eDVBService *service);
RESULT getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service);
-
+
RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *query);
};
@@ -42,8 +50,9 @@ private:
std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator m_cursor;
ePtr<eDVBDB> m_db;
ePtr<eDVBChannelQuery> m_query;
+ eServiceReferenceDVB m_source;
public:
- eDVBDBQuery(eDVBDB *db, eDVBChannelQuery *query);
+ eDVBDBQuery(eDVBDB *db, const eServiceReferenceDVB &source, eDVBChannelQuery *query);
virtual RESULT getNextResult(eServiceReferenceDVB &ref);
};
diff --git a/lib/gui/elistbox.cpp b/lib/gui/elistbox.cpp
index a3fae34c..a6fe45f1 100644
--- a/lib/gui/elistbox.cpp
+++ b/lib/gui/elistbox.cpp
@@ -196,5 +196,4 @@ void eListbox::entryReset()
m_top = 0;
m_selected = 0;
invalidate();
- eDebug("inval!");
}
diff --git a/lib/gui/ewindowstyle.cpp b/lib/gui/ewindowstyle.cpp
index 3b8271f6..25b89460 100644
--- a/lib/gui/ewindowstyle.cpp
+++ b/lib/gui/ewindowstyle.cpp
@@ -80,6 +80,10 @@ void eWindowStyleSimple::setStyle(gPainter &painter, int what)
painter.setForegroundColor(gColor(0x1C));
painter.setBackgroundColor(m_background_color);
break;
+ case styleListboxMarked:
+ painter.setForegroundColor(gColor(0x2F));
+ painter.setBackgroundColor(gColor(0x2A));
+ break;
}
}
diff --git a/lib/gui/ewindowstyle.h b/lib/gui/ewindowstyle.h
index 6431c242..0014bfa4 100644
--- a/lib/gui/ewindowstyle.h
+++ b/lib/gui/ewindowstyle.h
@@ -17,7 +17,8 @@ public:
enum {
styleLabel,
styleListboxSelected,
- styleListboxNormal
+ styleListboxNormal,
+ styleListboxMarked
};
virtual void drawFrame(gPainter &painter, const eRect &frame, int type) = 0;
diff --git a/lib/service/listboxservice.cpp b/lib/service/listboxservice.cpp
index 647dbdb9..db4f6b86 100644
--- a/lib/service/listboxservice.cpp
+++ b/lib/service/listboxservice.cpp
@@ -30,6 +30,43 @@ void eListboxServiceContent::getCurrent(eServiceReference &ref)
ref = eServiceReference();
}
+void eListboxServiceContent::initMarked()
+{
+ m_marked.clear();
+}
+
+void eListboxServiceContent::addMarked(const eServiceReference &ref)
+{
+ m_marked.insert(ref);
+ if (m_listbox)
+ m_listbox->entryChanged(lookupService(ref));
+}
+
+void eListboxServiceContent::removeMarked(const eServiceReference &ref)
+{
+ m_marked.erase(ref);
+ if (m_listbox)
+ m_listbox->entryChanged(lookupService(ref));
+}
+
+int eListboxServiceContent::isMarked(const eServiceReference &ref)
+{
+ return m_marked.find(ref) != m_marked.end();
+}
+
+int eListboxServiceContent::lookupService(const eServiceReference &ref)
+{
+ /* shortcut for cursor */
+ if (ref == *m_cursor)
+ return m_cursor_number;
+ /* otherwise, search in the list.. */
+ int index = 0;
+ for (list::const_iterator i(m_list.begin()); i != m_list.end(); ++i, ++index);
+
+ /* this is ok even when the index was not found. */
+ return index;
+}
+
DEFINE_REF(eListboxServiceContent);
eListboxServiceContent::eListboxServiceContent()
@@ -118,7 +155,10 @@ void eListboxServiceContent::paint(gPainter &painter, eWindowStyle &style, const
{
ePtr<gFont> fnt = new gFont("Arial", 14);
painter.clip(eRect(offset, m_itemsize));
- style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
+ if (cursorValid() && isMarked(*m_cursor))
+ style.setStyle(painter, eWindowStyle::styleListboxMarked);
+ else
+ style.setStyle(painter, selected ? eWindowStyle::styleListboxSelected : eWindowStyle::styleListboxNormal);
painter.clear();
if (cursorValid())
diff --git a/lib/service/listboxservice.h b/lib/service/listboxservice.h
index 231bab16..d5241933 100644
--- a/lib/service/listboxservice.h
+++ b/lib/service/listboxservice.h
@@ -4,6 +4,7 @@
#include <lib/gui/elistbox.h>
#include <lib/service/iservice.h>
+#include <set>
class eServiceCenter;
class eListboxServiceContent: public virtual iListboxContent
@@ -13,6 +14,14 @@ public:
eListboxServiceContent();
void setRoot(const eServiceReference &ref);
void getCurrent(eServiceReference &ref);
+
+ /* support for marked services */
+ void initMarked();
+ void addMarked(const eServiceReference &ref);
+ void removeMarked(const eServiceReference &ref);
+ int isMarked(const eServiceReference &ref);
+ int lookupService(const eServiceReference &ref);
+
protected:
void cursorHome();
@@ -44,6 +53,9 @@ private:
ePtr<eServiceCenter> m_service_center;
eServiceReference m_root;
+
+ /* support for marked services */
+ std::set<eServiceReference> m_marked;
};
#endif
diff --git a/screens.py b/screens.py
index dd13c550..82646282 100644
--- a/screens.py
+++ b/screens.py
@@ -58,9 +58,10 @@ class mainMenu(Screen):
Screen.__init__(self, session)
b = Button("ok")
- self["actions"] = ActionMap("MainMenuActions",
+ self["actions"] = ActionMap(["OkCancelActions"],
{
- "selected": self.okbuttonClick
+ "ok": self.okbuttonClick,
+ "cancel": self.close
})
b.onClick = [ self.okbuttonClick ]
@@ -90,24 +91,33 @@ class channelSelection(Screen):
Screen.__init__(self, session)
self["list"] = ServiceList()
- self["list"].setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:PREMIERE"))
+ self["list"].setRoot(eServiceReference("""1:0:1:0:0:0:0:0:0:0:(provider=="ARD") && (type == 1)"""))
self["okbutton"] = Button("ok", [self.channelSelected])
class ChannelActionMap(ActionMap):
- def action(self, context, action):
+ def action(self, contexts, action):
if action[:7] == "bouquet":
print "setting root to " + action[8:]
self.csel["list"].setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
else:
- ActionMap.action(self, context, action)
+ ActionMap.action(self, contexts, action)
- self["actions"] = ChannelActionMap("ChannelSelectActions",
+ self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions"],
{
- "selectChannel": self.channelSelected,
+ "cancel": self.close,
+ "ok": self.channelSelected,
+ "mark": self.doMark
})
self["actions"].csel = self
+ def doMark(self):
+ ref = self["list"].getCurrent()
+ if self["list"].isMarked(ref):
+ self["list"].removeMarked(ref)
+ else:
+ self["list"].addMarked(ref)
+
def channelSelected(self):
self.session.nav.playService(self["list"].getCurrent())
self.close()
@@ -117,7 +127,7 @@ class infoBar(Screen):
def __init__(self, session):
Screen.__init__(self, session)
- self["actions"] = ActionMap("InfobarActions",
+ self["actions"] = ActionMap( [ "InfobarActions" ],
{
"switchChannel": self.switchChannel,
"mainMenu": self.mainMenu