some minor speedups using caches and more selective updating
authorFelix Domke <tmbinc@elitedvb.net>
Sun, 30 Jul 2006 22:56:43 +0000 (22:56 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Sun, 30 Jul 2006 22:56:43 +0000 (22:56 +0000)
17 files changed:
lib/python/Components/Converter/ConditionalShowHide.py
lib/python/Components/Converter/EventName.py
lib/python/Components/Converter/EventTime.py
lib/python/Components/Converter/Poll.py
lib/python/Components/Converter/ServiceInfo.py
lib/python/Components/Converter/ServiceName.py
lib/python/Components/Converter/ServicePosition.py
lib/python/Components/Element.py
lib/python/Components/Renderer/Label.py
lib/python/Components/Renderer/PositionGauge.py
lib/python/Components/Renderer/Progress.py
lib/python/Components/Sources/Boolean.py
lib/python/Components/Sources/Clock.py
lib/python/Components/Sources/CurrentService.py
lib/python/Components/Sources/EventInfo.py
lib/python/Components/Sources/FrontendStatus.py
lib/python/Components/Sources/MenuList.py

index 9f1f86b..cc98288 100644 (file)
@@ -6,6 +6,6 @@ class ConditionalShowHide(Converter, object):
                Converter.__init__(self, type)
                self.invert = type == "Invert"
 
-       def changed(self):
+       def changed(self, what):
                for x in self.downstream_elements:
                        x.visible = self.source.boolean
index 2b95d94..f128133 100644 (file)
@@ -15,6 +15,11 @@ class EventName(Converter, object):
                        self.type = self.NAME
 
        def getText(self):
+               if self.cache is None:
+                       self.cache = self.__getText()
+               return self.cache
+
+       def __getText(self):
                event = self.source.event
                if event is None:
                        return "N/A"
index 09fe6bf..4a73e0a 100644 (file)
@@ -30,6 +30,11 @@ class EventTime(Poll, Converter, object):
                        raise str("'%s' is not <StartTime|EndTime|Remaining|Duration> for EventTime converter" % type)
 
        def getTime(self):
+               if self.cache is None or self.cache[0] is None:
+                       self.cache = (self.__getTime(), self.cache and self.cache[1])
+               return self.cache[0]
+       
+       def __getTime(self):    
                assert self.type != self.PROGRESS
 
                event = self.source.event
@@ -53,6 +58,11 @@ class EventTime(Poll, Converter, object):
                                return (duration, None)
 
        def getValue(self):
+               if self.cache is None or self.cache[1] is None:
+                       self.cache = (self.cache and self.cache[0], self.__getValue())
+               return self.cache[1]
+
+       def __getValue(self):
                assert self.type == self.PROGRESS
 
                event = self.source.event
index 3ba5e87..2b81e32 100644 (file)
@@ -3,7 +3,7 @@ from enigma import eTimer
 class Poll(object):
        def __init__(self):
                self.__poll_timer = eTimer()
-               self.__poll_timer.timeout.get().append(self.changed)
+               self.__poll_timer.timeout.get().append(self.poll)
                self.__interval = 1000
                self.__enabled = False
 
@@ -20,3 +20,6 @@ class Poll(object):
 
        poll_interval = property(lambda self: self.__interval, __setInterval)
        poll_enabled = property(lambda self: self.__enabled, __setEnable)
+
+       def poll(self):
+               self.changed((self.CHANGED_POLL,))
index f9b65c1..e1351c5 100644 (file)
@@ -19,11 +19,11 @@ class ServiceInfo(Converter, object):
                        }[type]
 
                self.interesting_events = {
-                               self.HAS_TELETEXT: [iPlayableService.evEnd, iPlayableService.evUpdatedInfo],
-                               self.IS_MULTICHANNEL: [iPlayableService.evUpdatedInfo, iPlayableService.evEnd],
-                               self.IS_CRYPTED: [iPlayableService.evUpdatedInfo, iPlayableService.evEnd],
-                               self.IS_WIDESCREEN: [iPlayableService.evUpdatedEventInfo, iPlayableService.evEnd],
-                               self.SUBSERVICES_AVAILABLE: [iPlayableService.evUpdatedEventInfo, iPlayableService.evEnd]
+                               self.HAS_TELETEXT: [iPlayableService.evUpdatedInfo],
+                               self.IS_MULTICHANNEL: [iPlayableService.evUpdatedInfo],
+                               self.IS_CRYPTED: [iPlayableService.evUpdatedInfo],
+                               self.IS_WIDESCREEN: [iPlayableService.evUpdatedEventInfo],
+                               self.SUBSERVICES_AVAILABLE: [iPlayableService.evUpdatedEventInfo]
                        }[self.type]
 
        def getServiceInfoValue(self, info, what):
@@ -33,6 +33,11 @@ class ServiceInfo(Converter, object):
                return info.getInfoString(what)
 
        def getBoolean(self):
+               if self.cache is None:
+                       self.cache = self.__getBoolean()
+               return self.cache
+
+       def __getBoolean(self):
                service = self.source.service
                info = service and service.info()
                if not info:
@@ -62,7 +67,6 @@ class ServiceInfo(Converter, object):
 
        boolean = property(getBoolean)
 
-       def changed(self, *args):
-               if not len(args) or args[0] in [iPlayableService.evStart, iPlayableService.evEnd, 
-                       iPlayableService.evUpdatedInfo, iPlayableService.evUpdatedEventInfo]:
-                       Converter.changed(self)
+       def changed(self, what):
+               if what[0] != self.CHANGED_SPECIFIC or what[1] in self.interesting_events:
+                       Converter.changed(self, what)
index 78a3dca..cffe494 100644 (file)
@@ -31,6 +31,6 @@ class ServiceName(Converter, object):
 
        text = property(getText)
 
-       def changed(self, *args):
-               if not len(args) or args[0] in [iPlayableService.evStart, iPlayableService.evEnd]:
-                       Converter.changed(self)
+       def changed(self, what):
+               if what[0] != self.CHANGED_SPECIFIC or what[1] in [iPlayableService.evStart]:
+                       Converter.changed(self, what)
index e072aa5..dfb792a 100644 (file)
@@ -70,13 +70,13 @@ class ServicePosition(Converter, Poll, object):
        cutlist = property(getCutlist)
        text = property(getText)
        
-       def changed(self, *args):
-               cutlist_refresh = len(args) and args[0] in [iPlayableService.evCuesheetChanged, iPlayableService.evStart, iPlayableService.evEnd]
-               time_refresh = not len(args) or args[0] in [iPlayableService.evStart, iPlayableService.evEnd]
+       def changed(self, what):
+               cutlist_refresh = what[0] != self.CHANGED_SPECIFIC or what[1] in [iPlayableService.evCuesheetChanged]
+               time_refresh = what[0] == self.CHANGED_POLL or what[0] == self.CHANGED_SPECIFIC and what[1] in [iPlayableService.evCuesheetChanged]
                
                if cutlist_refresh:
                        if self.type == self.TYPE_GAUGE:
                                self.downstream_elements.cutlist_changed()
 
                if time_refresh:
-                       self.downstream_elements.changed()
+                       self.downstream_elements.changed(what)
index 880274b..1221846 100644 (file)
@@ -5,10 +5,17 @@ from Tools.CList import CList
 
 # a bidirectional connection
 class Element:
+       CHANGED_DEFAULT = 0   # initial "pull" state
+       CHANGED_ALL = 1       # really everything changed
+       CHANGED_CLEAR = 2     # we're expecting a real update soon. don't bother polling NOW, but clear data.
+       CHANGED_SPECIFIC = 3  # second tuple will specify what exactly changed
+       CHANGED_POLL = 4      # a timer expired
+
        def __init__(self):
                self.downstream_elements = CList()
                self.master = None
                self.source = None
+               self.clearCache()
 
        def connectDownstream(self, downstream):
                self.downstream_elements.append(downstream)
@@ -18,7 +25,7 @@ class Element:
        def connectUpstream(self, upstream):
                assert self.source is None
                self.source = upstream
-               self.changed()
+               self.changed((self.CHANGED_DEFAULT,))
        
        def connect(self, upstream):
                self.connectUpstream(upstream)
@@ -44,8 +51,13 @@ class Element:
 
        # default action: push downstream
        def changed(self, *args, **kwargs):
+               self.clearCache()
                self.downstream_elements.changed(*args, **kwargs)
+               self.clearCache()
 
        def reconnectUpstream(self, new_upstream):
                assert self.source is not None
                self.source = new_upstream
+
+       def clearCache(self):
+               self.cache = None
index 1d06a21..3813ce2 100644 (file)
@@ -12,7 +12,10 @@ class Label(VariableText, Renderer):
 
        def connect(self, source):
                Renderer.connect(self, source)
-               self.changed()
+               self.changed((self.CHANGED_DEFAULT,))
 
-       def changed(self):
-               self.text = self.source.text
+       def changed(self, what):
+               if what[0] == self.CHANGED_CLEAR:
+                       self.text = ""
+               else:
+                       self.text = self.source.text
index abc9b7f..4b49501 100644 (file)
@@ -11,12 +11,15 @@ class PositionGauge(Renderer):
        GUI_WIDGET = ePositionGauge
        
        def postWidgetCreate(self, instance):
-               self.changed()
+               self.changed((self.CHANGED_DEFAULT,))
                self.cutlist_changed()
                instance.setInOutList(self.__cutlist)
 
-       def changed(self):
-               (self.length, self.position) = (self.source.length or 0, self.source.position or 0)
+       def changed(self, what):
+               if what[0] == self.CHANGED_CLEAR:
+                       (self.length, self.position) = 0
+               else:
+                       (self.length, self.position) = (self.source.length or 0, self.source.position or 0)
 
        def cutlist_changed(self):
                self.cutlist = self.source.cutlist or [ ]
index b6f2b1c..f32802e 100644 (file)
@@ -12,7 +12,11 @@ class Progress(VariableValue, Renderer):
 
        GUI_WIDGET = eSlider
 
-       def changed(self):
+       def changed(self, what):
+               if what[0] == self.CHANGED_CLEAR:
+                       (self.range, self.value) = ((0, 1), 0)
+                       return
+
                range = self.source.range or 100
                value = self.source.value
                if value is None:
index c25b462..bd5222a 100644 (file)
@@ -13,7 +13,7 @@ class Boolean(Source, object):
                Source.__init__(self)
                if poll > 0:
                        self.poll_timer = eTimer()
-                       self.poll_timer.timeout.get().append(self.changed)
+                       self.poll_timer.timeout.get().append(self.poll)
                        self.poll_timer.start(poll)
 
        def getBoolean(self):
@@ -23,3 +23,6 @@ class Boolean(Source, object):
                        return self.fixed
 
        boolean = property(getBoolean)
+
+       def poll(self):
+               self.changed((self.CHANGED_ALL,))
index 608a719..e2d7faa 100644 (file)
@@ -8,10 +8,13 @@ class Clock(Source):
        def __init__(self):
                Source.__init__(self)
                self.clock_timer = eTimer()
-               self.clock_timer.timeout.get().append(self.changed)
+               self.clock_timer.timeout.get().append(self.poll)
                self.clock_timer.start(1000)
 
        def getClock(self):
                return time.time()
 
        time = property(getClock)
+
+       def poll(self):
+               self.changed((self.CHANGED_POLL,))
index 100822b..08d67ee 100644 (file)
@@ -2,6 +2,8 @@ from Components.PerServiceDisplay import PerServiceBase
 from enigma import iPlayableService
 from Source import Source
 
+from time import time
+
 class CurrentService(PerServiceBase, Source):
        def __init__(self, navcore):
                Source.__init__(self)
@@ -18,9 +20,11 @@ class CurrentService(PerServiceBase, Source):
                self.navcore = navcore
 
        def serviceEvent(self, event):
-               self.changed(event)
+               self.changed((self.CHANGED_SPECIFIC, event))
 
        def getCurrentService(self):
-               return self.navcore.getCurrentService()
+               if self.cache is None:
+                       self.cache = self.navcore.getCurrentService()
+               return self.cache
 
        service = property(getCurrentService)
index 4026999..20e5f10 100644 (file)
@@ -3,6 +3,8 @@ from Tools.Event import Event
 from enigma import iPlayableService
 from Source import Source
 
+from time import time
+
 class EventInfo(PerServiceBase, Source, object):
        NOW = 0
        NEXT = 1
@@ -11,16 +13,25 @@ class EventInfo(PerServiceBase, Source, object):
                Source.__init__(self)
                PerServiceBase.__init__(self, navcore, 
                        { 
-                               iPlayableService.evStart: self.changed,
-                               iPlayableService.evUpdatedEventInfo: self.changed,
-                               iPlayableService.evEnd: self.changed
-                       })
+                               iPlayableService.evStart: self.gotEvent,
+                               iPlayableService.evUpdatedEventInfo: self.gotEvent,
+                               iPlayableService.evEnd: self.gotEvent
+                       }, with_event=True)
                
                self.now_or_next = now_or_next
                
        def getEvent(self):
-               service = self.navcore.getCurrentService()
-               info = service and service.info()
-               return info and info.getEvent(self.now_or_next)
+               if self.cache is None:
+                       service = self.navcore.getCurrentService()
+                       info = service and service.info()
+                       self.cache = (True, info and info.getEvent(self.now_or_next)) # we always store a tuple for negative caching
+               
+               return self.cache[1]
 
        event = property(getEvent)
+
+       def gotEvent(self, what):
+               if what in [iPlayableService.evStart, iPlayableService.evEnd]:
+                       self.changed((self.CHANGED_CLEAR,))
+               else:
+                       self.changed((self.CHANGED_ALL,))
index 6682e82..f1402f1 100644 (file)
@@ -27,7 +27,7 @@ class FrontendStatus(Source):
                                                iFrontendInformation.bitErrorRate, 
                                                iFrontendInformation.lockState] ]
 
-               self.changed()
+               self.changed((self.CHANGED_ALL, ))
 
        def getFrontendInfo(self):
                if self.frontend_source:
index 9876441..dd5e18f 100644 (file)
@@ -9,7 +9,7 @@ class MenuList(Source, object):
        
        def setList(self, list):
                self.__list = list
-               self.changed()
+               self.changed((self.CHANGED_ALL,))
        
        list = property(lambda self: self.__list, setList)