From: Andreas Monzner Date: Tue, 31 Jul 2007 11:00:01 +0000 (+0000) Subject: add graphical multiepg plugin (like e1) X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=b1d4a0b06608906144928198f66062705a8041fd add graphical multiepg plugin (like e1) yet it is just startable via blue button menu --- diff --git a/configure.ac b/configure.ac index 0c303ef..bdf6f00 100644 --- a/configure.ac +++ b/configure.ac @@ -91,6 +91,7 @@ lib/python/Plugins/Extensions/CutListEditor/Makefile lib/python/Plugins/Extensions/MediaScanner/Makefile lib/python/Plugins/Extensions/PicturePlayer/Makefile lib/python/Plugins/Extensions/PicturePlayer/data/Makefile +lib/python/Plugins/Extensions/GraphMultiEPG/Makefile lib/python/Tools/Makefile lib/service/Makefile lib/components/Makefile diff --git a/data/skin_default.xml b/data/skin_default.xml index e52ab77..c04e3c0 100644 --- a/data/skin_default.xml +++ b/data/skin_default.xml @@ -342,6 +342,33 @@ + + + + + WithSeconds + + + + + + + + + + + + StartTime + + + + EndTime + Format:- %H:%M + + + + + diff --git a/lib/gui/elistboxcontent.cpp b/lib/gui/elistboxcontent.cpp index 24a2951..b397ddc 100644 --- a/lib/gui/elistboxcontent.cpp +++ b/lib/gui/elistboxcontent.cpp @@ -726,11 +726,11 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c pwidth = PyTuple_GET_ITEM(item, 3), pheight = PyTuple_GET_ITEM(item, 4), ppixmap = PyTuple_GET_ITEM(item, 5), - pforeColor, pbackColor, pbackColorSelected; + pbackColor, pbackColorSelected; if (!(px && py && pwidth && pheight && ppixmap)) { - eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, foreColor, backColor, backColorSelected] ))"); + eDebug("eListboxPythonMultiContent received too small tuple (must be (TYPE_PIXMAP, x, y, width, height, pixmap [, backColor, backColorSelected] ))"); goto error_out; } @@ -747,29 +747,23 @@ void eListboxPythonMultiContent::paint(gPainter &painter, eWindowStyle &style, c if (size > 6) { - pforeColor = PyTuple_GET_ITEM(item, 6); - if (pforeColor == Py_None) - pforeColor=ePyObject(); - } - if (size > 7) - { - pbackColor = PyTuple_GET_ITEM(item, 7); + pbackColor = PyTuple_GET_ITEM(item, 6); if (pbackColor == Py_None) pbackColor=ePyObject(); } - if (size > 8) + if (size > 7) { - pbackColorSelected = PyTuple_GET_ITEM(item, 8); + pbackColorSelected = PyTuple_GET_ITEM(item, 7); if (pbackColorSelected == Py_None) pbackColorSelected=ePyObject(); } eRect rect(x, y, width, height); painter.clip(rect); - if (pbackColor || pbackColorSelected || pforeColor) + if (pbackColor || pbackColorSelected) { gRegion rc(rect); - clearRegion(painter, style, pforeColor, pbackColor, pbackColorSelected, selected, rc, sel_clip); + clearRegion(painter, style, ePyObject(), pbackColor, pbackColorSelected, selected, rc, sel_clip); reset_colors=true; } diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py b/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py new file mode 100644 index 0000000..d8c654b --- /dev/null +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/GraphMultiEpg.py @@ -0,0 +1,500 @@ +from Components.config import config, ConfigClock, ConfigInteger +from Components.Button import Button +from Components.Pixmap import Pixmap +from Components.ActionMap import ActionMap +from Components.HTMLComponent import HTMLComponent +from Components.GUIComponent import GUIComponent +from Components.EpgList import Rect +from Components.Sources.Event import Event +from Components.Sources.Clock import Clock +from Screens.Screen import Screen +from Screens.EventView import EventViewSimple +from Screens.TimeDateInput import TimeDateInput +from Screens.TimerEntry import TimerEntry +from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE +from RecordTimer import RecordTimerEntry, parseEvent +from ServiceReference import ServiceReference +from enigma import eEPGCache, eListbox, eListboxPythonMultiContent, gFont, loadPNG, \ + RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, RT_WRAP, eRect, eTimer + +from time import localtime, time, strftime + +class EPGList(HTMLComponent, GUIComponent): + def __init__(self, selChangedCB=None, timer = None, time_epoch = 120, overjump_empty=True): + self.cur_event = None + self.cur_service = None + self.offs = 0 + self.timer = timer + self.onSelChanged = [ ] + if selChangedCB is not None: + self.onSelChanged.append(selChangedCB) + GUIComponent.__init__(self) + self.l = eListboxPythonMultiContent() + self.l.setItemHeight(54); + self.l.setBuildFunc(self.buildEntry) + if overjump_empty: + self.l.setSelectableFunc(self.isSelectable) + self.epgcache = eEPGCache.getInstance() + self.clock_pixmap = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, 'epgclock-fs8.png')) + self.time_base = None + self.time_epoch = time_epoch + self.list = None + self.entry_rect = None + + def isSelectable(self, service, sname, event_list): + return (event_list and len(event_list) and True) or False + + def setEpoch(self, epoch): + if self.cur_event is not None and self.cur_service is not None: + self.offs = 0 + self.time_epoch = epoch + self.fillMultiEPG(None) # refill + + def getEventFromId(self, service, eventid): + event = None + if self.epgcache is not None and eventid is not None: + event = self.epgcache.lookupEventId(service.ref, eventid) + return event + + def getCurrent(self): + if self.cur_service is None or self.cur_event is None: + return ( None, None ) + old_service = self.cur_service #(service, service_name, events) + events = self.cur_service[2] + refstr = self.cur_service[0] + if not events or not len(events): + return ( None, None ) + event = events[self.cur_event] #(event_id, event_title, begin_time, duration) + eventid = event[0] + service = ServiceReference(refstr) + event = self.getEventFromId(service, eventid) + return ( event, service ) + + def connectSelectionChanged(func): + if not self.onSelChanged.count(func): + self.onSelChanged.append(func) + + def disconnectSelectionChanged(func): + self.onSelChanged.remove(func) + + def serviceChanged(self): + cur_sel = self.l.getCurrentSelection() + if cur_sel: + self.findBestEvent() + + def findBestEvent(self): + old_service = self.cur_service #(service, service_name, events) + cur_service = self.cur_service = self.l.getCurrentSelection() + last_time = 0; + if old_service and self.cur_event is not None: + events = old_service[2] + cur_event = events[self.cur_event] #(event_id, event_title, begin_time, duration) + last_time = cur_event[2] + if cur_service: + self.cur_event = 0 + events = cur_service[2] + if events and len(events): + if last_time: + best_diff = 0 + best = len(events) #set invalid + idx = 0 + for event in events: #iterate all events + diff = abs(event[2]-last_time) + if (best == len(events)) or (diff < best_diff): + best = idx + best_diff = diff + idx += 1 + if best != len(events): + self.cur_event = best + else: + self.cur_event = None + self.selEntry(0) + + def selectionChanged(self): + for x in self.onSelChanged: + if x is not None: + try: + x() + except: # FIXME!!! + print "FIXME in EPGList.selectionChanged" + pass + + GUI_WIDGET = eListbox + + def postWidgetCreate(self, instance): + instance.setWrapAround(True) + instance.selectionChanged.get().append(self.serviceChanged) + instance.setContent(self.l) + + def recalcEntrySize(self): + esize = self.l.getItemSize() + self.l.setFont(0, gFont("Regular", 20)) + self.l.setFont(1, gFont("Regular", 14)) + width = esize.width() + height = esize.height() + xpos = 0; + w = width/10*2; + self.service_rect = Rect(xpos, 0, w-10, height) + xpos += w; + w = width/10*8; + self.event_rect = Rect(xpos, 0, w, height) + self.l.setSelectionClip(eRect(xpos, 0, w, height), False) + + def calcEntryPosAndWidthHelper(self, stime, duration, start, end, width): + xpos = (stime - start) * width / (end - start) + ewidth = (stime + duration - start) * width / (end - start) + ewidth -= xpos; + if xpos < 0: + ewidth += xpos; + xpos = 0; + if (xpos+ewidth) > width: + ewidth = width - xpos + return xpos, ewidth + + def calcEntryPosAndWidth(self, event_rect, time_base, time_epoch, ev_start, ev_duration): + xpos, width = self.calcEntryPosAndWidthHelper(ev_start, ev_duration, time_base, time_base + time_epoch * 60, event_rect.width()) + return xpos+event_rect.left(), width + + def buildEntry(self, service, service_name, events): + r1=self.service_rect + r2=self.event_rect + res = [ None ] # no private data needed + res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, service_name)) + start = self.time_base+self.offs*self.time_epoch*60 + end = start + self.time_epoch * 60 + left = r2.left() + top = r2.top() + width = r2.width() + height = r2.height() + if events: + for ev in events: #(event_id, event_title, begin_time, duration) + rec=self.timer.isInTimer(ev[0], ev[2], ev[3], service) > ((ev[3]/10)*8) + xpos, ewidth = self.calcEntryPosAndWidthHelper(ev[2], ev[3], start, end, width) + res.append((eListboxPythonMultiContent.TYPE_TEXT, left+xpos, top, ewidth, height, 1, RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, ev[1], None, 0x586d88, 0x808080, 1)) + if rec and ewidth > 23: + res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, left+xpos+ewidth-22, top+height-22, 21, 21, self.clock_pixmap, 0x586d88, 0x808080)) + return res + + def selEntry(self, dir): + cur_service = self.cur_service #(service, service_name, events) + if not self.entry_rect: + self.recalcEntrySize() + if cur_service and self.cur_event is not None: + update = True + entries = cur_service[2] + if dir == 0: #current + update = False + pass + elif dir == +1: #next + if self.cur_event+1 < len(entries): + self.cur_event+=1 + else: + self.offs += 1 + self.fillMultiEPG(None) # refill + return + elif dir == -1: #prev + if self.cur_event-1 >= 0: + self.cur_event-=1 + elif self.offs > 0: + self.offs -= 1 + self.fillMultiEPG(None) # refill + return + entry = entries[self.cur_event] #(event_id, event_title, begin_time, duration) + time_base = self.time_base+self.offs*self.time_epoch*60 + xpos, width = self.calcEntryPosAndWidth(self.event_rect, time_base, self.time_epoch, entry[2], entry[3]) + self.l.setSelectionClip(eRect(xpos, 0, width, self.event_rect.height()), update) + else: + self.l.setSelectionClip(eRect(self.event_rect.left(), self.event_rect.top(), self.event_rect.width(), self.event_rect.height()), False) + self.selectionChanged() + + def queryEPG(self, list, buildFunc=None): + if self.epgcache is not None: + if buildFunc is not None: + return self.epgcache.lookupEvent(list, buildFunc) + else: + return self.epgcache.lookupEvent(list) + return [ ] + + def fillMultiEPG(self, services, stime=-1): + if services is None: + time_base = self.time_base+self.offs*self.time_epoch*60 + test = [ (service[0], 0, time_base, self.time_epoch) for service in self.list ] + else: + self.cur_event = None + self.cur_service = None + self.time_base = int(stime) + test = [ (service.ref.toString(), 0, self.time_base, self.time_epoch) for service in services ] + test.insert(0, 'RnITBD') + epg_data = self.queryEPG(test) + + self.list = [ ] + tmp_list = None + service = "" + sname = "" + for x in epg_data: + if service != x[0]: + if tmp_list is not None: + self.list.append((service, sname, tmp_list[0][0] and tmp_list)) + service = x[0] + sname = x[1] + tmp_list = [ ] + tmp_list.append((x[2], x[3], x[4], x[5])) + if tmp_list and len(tmp_list): + self.list.append((service, sname, tmp_list[0][0] and tmp_list)) + + self.l.setList(self.list) + self.findBestEvent() + + def getEventRect(self): + return self.event_rect + + def getTimeEpoch(self): + return self.time_epoch + + def getTimeBase(self): + return self.time_base + +class TimelineText(HTMLComponent, GUIComponent): + def __init__(self): + GUIComponent.__init__(self) + self.l = eListboxPythonMultiContent() + self.l.setSelectionClip(eRect(0,0,0,0)) + self.l.setItemHeight(25); + self.l.setFont(0, gFont("Regular", 20)) + + GUI_WIDGET = eListbox + + def postWidgetCreate(self, instance): + instance.setContent(self.l) + + def setEntries(self, entries): + res = [ None ] # no private data needed + for x in entries: + tm = x[0] + xpos = x[1] + str = strftime("%H:%M", localtime(tm)) + res.append((eListboxPythonMultiContent.TYPE_TEXT, xpos-30, 0, 60, 25, 0, RT_HALIGN_CENTER|RT_VALIGN_CENTER, str)) + self.l.setList([res]) + +config.misc.graph_mepg_prev_time=ConfigClock(default = time()) +config.misc.graph_mepg_prev_time_period=ConfigInteger(default=120, limits=(60,300)) + +class GraphMultiEPG(Screen): + def __init__(self, session, services, zapFunc=None, bouquetChangeCB=None): + Screen.__init__(self, session) + self.bouquetChangeCB = bouquetChangeCB + now = time() + tmp = now % 900 + self.ask_time = now - tmp + self.closeRecursive = False + self["key_red"] = Button("") + self["key_green"] = Button(_("Add timer")) + self["timeline_text"] = TimelineText() + self["Event"] = Event() + self["Clock"] = Clock() + self.time_lines = [ ] + for x in (0,1,2,3,4,5): + pm = Pixmap() + self.time_lines.append(pm) + self["timeline%d"%(x)] = pm + self["timeline_now"] = Pixmap() + self.services = services + self.zapFunc = zapFunc + + self["list"] = EPGList(selChangedCB = self.onSelectionChanged, timer = self.session.nav.RecordTimer, time_epoch = config.misc.graph_mepg_prev_time_period.value ) + + self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions"], + { + "cancel": self.closeScreen, + "ok": self.eventSelected, + "timerAdd": self.timerAdd, + "info": self.infoKeyPressed, + "red": self.zapTo, + "input_date_time": self.enterDateTime, + "nextBouquet": self.nextBouquet, + "prevBouquet": self.prevBouquet, + }) + self["actions"].csel = self + + self["input_actions"] = ActionMap(["InputActions"], + { + "left": self.prevEvent, + "right": self.nextEvent, + "1": self.key1, + "2": self.key2, + "3": self.key3, + "4": self.key4, + "5": self.key5, + },-1) + + self.updateTimelineTimer = eTimer() + self.updateTimelineTimer.timeout.get().append(self.moveTimeLines) + self.updateTimelineTimer.start(60*1000) + self.onLayoutFinish.append(self.onCreate) + + def nextEvent(self): + self["list"].selEntry(+1) + + def prevEvent(self): + self["list"].selEntry(-1) + + def key1(self): + self["list"].setEpoch(60) + config.misc.graph_mepg_prev_time_period.value = 60 + self.moveTimeLines() + + def key2(self): + self["list"].setEpoch(120) + config.misc.graph_mepg_prev_time_period.value = 120 + self.moveTimeLines() + + def key3(self): + self["list"].setEpoch(180) + config.misc.graph_mepg_prev_time_period.value = 180 + self.moveTimeLines() + + def key4(self): + self["list"].setEpoch(240) + config.misc.graph_mepg_prev_time_period.value = 240 + self.moveTimeLines() + + def key5(self): + self["list"].setEpoch(300) + config.misc.graph_mepg_prev_time_period.value = 300 + self.moveTimeLines() + + def nextBouquet(self): + if self.bouquetChangeCB: + self.bouquetChangeCB(1, self) + + def prevBouquet(self): + if self.bouquetChangeCB: + self.bouquetChangeCB(-1, self) + + def enterDateTime(self): + self.session.openWithCallback(self.onDateTimeInputClosed, TimeDateInput, config.misc.graph_mepg_prev_time ) + + def onDateTimeInputClosed(self, ret): + if len(ret) > 1: + if ret[0]: + self.ask_time=ret[1] + self["list"].fillMultiEPG(self.services, ret[1]) + self.moveTimeLines() + + def closeScreen(self): + self.close(self.closeRecursive) + + def infoKeyPressed(self): + cur = self["list"].getCurrent() + event = cur[0] + service = cur[1] + if event is not None: + self.session.open(EventViewSimple, event, service, self.eventViewCallback, self.openSimilarList) + + def openSimilarList(self, eventid, refstr): + self.session.open(EPGSelection, refstr, None, eventid) + + def setServices(self, services): + self.services = services + self.onCreate() + + #just used in multipeg + def onCreate(self): + self["list"].fillMultiEPG(self.services, self.ask_time) + self.moveTimeLines() + + def eventViewCallback(self, setEvent, setService, val): + l = self["list"] + old = l.getCurrent() + if val == -1: + l.selEntry(-1) + elif val == +1: + self.selEntry(+1) + cur = l.getCurrent() + if cur[0] is None and cur[1].ref != old[1].ref: + self.eventViewCallback(setEvent, setService, val) + else: + setService(cur[1]) + setEvent(cur[0]) + + def zapTo(self): + if self.zapFunc and self["key_red"].getText() == "Zap": + self.closeRecursive = True + ref = self["list"].getCurrent()[1] + self.zapFunc(ref.ref) + + def eventSelected(self): + self.infoKeyPressed() + + def timerAdd(self): + cur = self["list"].getCurrent() + event = cur[0] + serviceref = cur[1] + if event is None: + return + newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event)) + self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry) + + def timerEditFinished(self, answer): + if answer[0]: + self.session.nav.RecordTimer.record(answer[1]) + else: + print "Timeredit aborted" + + def onSelectionChanged(self): + evt = self["list"].getCurrent() + self["Event"].newEvent(evt and evt[0]) + if evt and evt[0]: + evt = evt[0] + now = time() + start = evt.getBeginTime() + end = start + evt.getDuration() + if now >= start and now <= end: + self["key_red"].setText("Zap") + else: + self["key_red"].setText("") + + def moveTimeLines(self): + l = self["list"] + event_rect = l.getEventRect() + time_epoch = l.getTimeEpoch() + time_base = l.getTimeBase() + if event_rect is None or time_epoch is None or time_base is None: + return + time_steps = time_epoch > 180 and 60 or 30 + num_lines = time_epoch/time_steps + incWidth=event_rect.width()/num_lines + pos=event_rect.left() + timeline_entries = [ ] + x = 0 + changecount = 0 + for line in self.time_lines: + old_pos = line.position + new_pos = (x == num_lines and event_rect.left()+event_rect.width() or pos, old_pos[1]) + if not x or x >= num_lines: + line.visible = False + else: + if old_pos != new_pos: + line.setPosition(new_pos[0], new_pos[1]) + changecount += 1 + line.visible = True + if not x or line.visible: + timeline_entries.append((time_base + x * time_steps * 60, new_pos[0])) + x += 1 + pos += incWidth + + if changecount: + self["timeline_text"].setEntries(timeline_entries) + + now=time() + timeline_now = self["timeline_now"] + if now >= time_base and now < (time_base + time_epoch * 60): + bla = (event_rect.width() * 1000) / time_epoch + xpos = ((now/60) - (time_base/60)) * bla / 1000 + old_pos = timeline_now.position + new_pos = (xpos+event_rect.left(), old_pos[1]) + if old_pos != new_pos: + timeline_now.setPosition(new_pos[0], new_pos[1]) + timeline_now.visible = True + else: + timeline_now.visible = False diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/Makefile.am b/lib/python/Plugins/Extensions/GraphMultiEPG/Makefile.am new file mode 100644 index 0000000..eeaef4f --- /dev/null +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/Makefile.am @@ -0,0 +1,7 @@ +installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/GraphMultiEPG + +install_PYTHON = \ + __init__.py \ + plugin.py \ + GraphMultiEpg.py + diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/__init__.py b/lib/python/Plugins/Extensions/GraphMultiEPG/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py new file mode 100644 index 0000000..a247a61 --- /dev/null +++ b/lib/python/Plugins/Extensions/GraphMultiEPG/plugin.py @@ -0,0 +1,96 @@ +from Plugins.Plugin import PluginDescriptor +from GraphMultiEpg import GraphMultiEPG +from Screens.ChannelSelection import BouquetSelector +from enigma import eServiceCenter, eServiceReference +from ServiceReference import ServiceReference + +Session = None +Servicelist = None + +bouquetSel = None +epg_bouquet = None +dlg_stack = [ ] + +def zapToService(service): + if not service is None: + if Servicelist.getRoot() != epg_bouquet: #already in correct bouquet? + Servicelist.clearPath() + if Servicelist.bouquet_root != epg_bouquet: + Servicelist.enterPath(Servicelist.bouquet_root) + Servicelist.enterPath(epg_bouquet) + Servicelist.setCurrentSelection(service) #select the service in Servicelist + Servicelist.zap() + +def getBouquetServices(bouquet): + services = [ ] + Servicelist = eServiceCenter.getInstance().list(bouquet) + if not Servicelist is None: + while True: + service = Servicelist.getNext() + if not service.valid(): #check if end of list + break + if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): #ignore non playable services + continue + services.append(ServiceReference(service)) + return services + +def cleanup(): + global Session + Session = None + global Servicelist + Servicelist = None + +def closed(ret=False): + closedScreen = dlg_stack.pop() + if bouquetSel and closedScreen == bouquetSel: + global bouquetSel + bouquetSel = None + dlgs=len(dlg_stack) + if ret and dlgs > 0: # recursive close wished + dlg_stack[dlgs-1].close(dlgs > 1) + if dlgs <= 0: + cleanup() + +def openBouquetEPG(bouquet): + services = getBouquetServices(bouquet) + if len(services): + global epg_bouquet + epg_bouquet = bouquet + dlg_stack.append(Session.openWithCallback(closed, GraphMultiEPG, services, zapToService, changeBouquetCB)) + return True + return False + +def changeBouquetCB(direction, epg): + if bouquetSel: + if direction > 0: + bouquetSel.down() + else: + bouquetSel.up() + bouquet = bouquetSel.getCurrent() + services = getBouquetServices(bouquet) + if len(services): + epg_bouquet = bouquet + epg.setServices(services) + +def main(session, servicelist, **kwargs): + global Session + Session = session + global Servicelist + Servicelist = servicelist + bouquets = Servicelist.getBouquetList() + if bouquets is None: + cnt = 0 + else: + cnt = len(bouquets) + if cnt > 1: # show bouquet list + global bouquetSel + bouquetSel = Session.openWithCallback(closed, BouquetSelector, bouquets, openBouquetEPG, enableWrapAround=True) + dlg_stack.append(bouquetSel) + elif cnt == 1: + if not openBouquetEPG(bouquets[0][1]): + cleanup() + +def Plugins(**kwargs): + name = _("Graphical Multi EPG") + descr = _("A graphical EPG for all services of an specific bouquet") + return [ PluginDescriptor(name=name, description=descr, where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main) ] diff --git a/lib/python/Plugins/Extensions/Makefile.am b/lib/python/Plugins/Extensions/Makefile.am index eca436b..ce80cd6 100644 --- a/lib/python/Plugins/Extensions/Makefile.am +++ b/lib/python/Plugins/Extensions/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = TuxboxPlugins FileManager CutListEditor FritzCall PicturePlayer MediaScanner IpkgInstaller +SUBDIRS = TuxboxPlugins FileManager CutListEditor FritzCall PicturePlayer MediaScanner IpkgInstaller GraphMultiEPG # SimpleRSS is still not finished