AutoTimer: add "Fast Scan" support
[vuplus_dvbapp-plugin] / autotimer / src / AutoTimer.py
index da43c05..ea72e13 100644 (file)
@@ -1,7 +1,7 @@
 # Plugins Config
-from xml.dom.minidom import parse as minidom_parse
+from xml.etree.cElementTree import parse as cet_parse
 from os import path as os_path
-from AutoTimerConfiguration import parseConfig, writeConfig
+from AutoTimerConfiguration import parseConfig, buildConfig
 
 # Navigation (RecordTimer)
 import NavigationInstance
@@ -21,7 +21,7 @@ from enigma import eEPGCache, eServiceReference
 from Components.config import config
 
 # AutoTimer Component
-from AutoTimerComponent import AutoTimerComponent
+from AutoTimerComponent import preferredAutoTimerComponent
 
 XML_CONFIG = "/etc/enigma2/autotimer.xml"
 
@@ -32,6 +32,16 @@ def getTimeDiff(timer, begin, end):
                return timer.end - begin
        return 0
 
+typeMap = {
+       "exact": eEPGCache.EXAKT_TITLE_SEARCH,
+       "partial": eEPGCache.PARTIAL_TITLE_SEARCH
+}
+
+caseMap = {
+       "sensitive": eEPGCache.CASE_CHECK,
+       "insensitive": eEPGCache.NO_CASE_CHECK
+}
+
 class AutoTimerIgnoreTimerException(Exception):
        def __init__(self, cause):
                self.cause = cause
@@ -46,14 +56,11 @@ class AutoTimer:
        """Read and save xml configuration, query EPGCache"""
 
        def __init__(self):
-               # Keep EPGCache
-               self.epgcache = eEPGCache.getInstance()
-
                # Initialize
                self.timers = []
                self.configMtime = -1
                self.uniqueTimerId = 0
-               self.defaultTimer = AutoTimerComponent(
+               self.defaultTimer = preferredAutoTimerComponent(
                        0,              # Id
                        "",             # Name
                        "",             # Match
@@ -78,26 +85,28 @@ class AutoTimer:
                self.configMtime = mtime
 
                # Parse Config
-               dom = minidom_parse(XML_CONFIG)
-               
+               configuration = cet_parse(XML_CONFIG).getroot()
+
                # Empty out timers and reset Ids
                del self.timers[:]
-               self.uniqueTimerId = 0
                self.defaultTimer.clear(-1, True)
 
-               # Get Config Element
-               for configuration in dom.getElementsByTagName("autotimer"):
-                       parseConfig(
-                               configuration,
-                               self.timers,
-                               configuration.getAttribute("version"),
-                               self.uniqueTimerId,
-                               self.defaultTimer
-                       )
-                       self.uniqueTimerId = len(self.timers)
+               parseConfig(
+                       configuration,
+                       self.timers,
+                       configuration.get("version"),
+                       0,
+                       self.defaultTimer
+               )
+               self.uniqueTimerId = len(self.timers)
+
+       def getXml(self):
+               return buildConfig(self.defaultTimer, self.timers, webif = True)
 
        def writeXml(self):
-               writeConfig(XML_CONFIG, self.defaultTimer, self.timers)
+               file = open(XML_CONFIG, 'w')
+               file.writelines(buildConfig(self.defaultTimer, self.timers))
+               file.close()
 
 # Manage List
 
@@ -158,20 +167,26 @@ class AutoTimer:
                # We include processed timers as we might search for duplicate descriptions
                recorddict = {}
                for timer in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers:
-                       if not recorddict.has_key(str(timer.service_ref)):
-                               recorddict[str(timer.service_ref)] = [timer]
-                       else:
-                               recorddict[str(timer.service_ref)].append(timer)
+                       recorddict.setdefault(str(timer.service_ref), []).append(timer)
 
                # Iterate Timer
                for timer in self.getEnabledTimerList():
+                       # Workaround to allow search for umlauts if we know the encoding
+                       match = timer.match
+                       if timer.encoding != 'UTF-8':
+                               try:
+                                       match = match.decode('UTF-8').encode(timer.encoding)
+                               except UnicodeDecodeError:
+                                       pass
+
                        # Search EPG, default to empty list
-                       ret = self.epgcache.search(('RI', 100, eEPGCache.PARTIAL_TITLE_SEARCH, timer.match, eEPGCache.NO_CASE_CHECK)) or []
+                       epgcache = eEPGCache.getInstance()
+                       ret = epgcache.search(('RI', 100, typeMap[timer.searchType], match, caseMap[timer.searchCase])) or ()
 
                        for serviceref, eit in ret:
                                eserviceref = eServiceReference(serviceref)
 
-                               evt = self.epgcache.lookupEventId(eserviceref, eit)
+                               evt = epgcache.lookupEventId(eserviceref, eit)
                                if not evt:
                                        print "[AutoTimer] Could not create Event!"
                                        continue
@@ -215,6 +230,9 @@ class AutoTimer:
                                        begin -= config.recording.margin_before.value * 60
                                        end += config.recording.margin_after.value * 60
 
+                               # Eventually change service to alternative
+                               if timer.overrideAlternatives:
+                                       serviceref = timer.getAlternative(serviceref)
 
                                total += 1
 
@@ -225,55 +243,65 @@ class AutoTimer:
 
                                # Initialize
                                newEntry = None
-                               isNew = False
+                               oldExists = False
 
                                # Check for double Timers
                                # We first check eit and if user wants us to guess event based on time
                                # we try this as backup. The allowed diff should be configurable though.
-                               try:
-                                       for rtimer in recorddict.get(serviceref, []):
-                                               if rtimer.eit == eit or config.plugins.autotimer.try_guessing.value and getTimeDiff(rtimer, begin, end) > ((duration/10)*8):
-                                                       newEntry = rtimer
-
-                                                       # Abort if we don't want to modify timers or timer is repeated
-                                                       if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
-                                                               raise AutoTimerIgnoreTimerException("Won't modify existing timer because either no modification allowed or repeated timer")
-
-                                                       if hasattr(newEntry, "isAutoTimer"):
-                                                                       print "[AutoTimer] Modifying existing AutoTimer!"
-                                                       else:
-                                                               if config.plugins.autotimer.refresh.value != "all":
-                                                                       raise AutoTimerIgnoreTimerException("Won't modify existing timer because it's no timer set by us")
-                                                               print "[AutoTimer] Warning, we're messing with a timer which might not have been set by us"
-
-                                                       modified += 1
-
-                                                       # Modify values saved in timer
-                                                       newEntry.name = name
-                                                       newEntry.description = description
-                                                       newEntry.begin = int(begin)
-                                                       newEntry.end = int(end)
-                                                       newEntry.service_ref = ServiceReference(serviceref)
+                               for rtimer in recorddict.get(serviceref, ()):
+                                       if rtimer.eit == eit or config.plugins.autotimer.try_guessing.value and getTimeDiff(rtimer, begin, end) > ((duration/10)*8):
+                                               oldExists = True
 
+                                               # Abort if we don't want to modify timers or timer is repeated
+                                               if config.plugins.autotimer.refresh.value == "none" or rtimer.repeated:
+                                                       print "[AutoTimer] Won't modify existing timer because either no modification allowed or repeated timer"
                                                        break
-                                               elif timer.getAvoidDuplicateDescription() == 1 and rtimer.description == description:
-                                                               raise AutoTimerIgnoreTimerException("We found a timer with same description, skipping event")
-                                       if newEntry is None and timer.getAvoidDuplicateDescription() == 2:
-                                               for list in recorddict.values():
-                                                       for rtimer in list:
-                                                               if rtimer.description == description:
-                                                                       raise AutoTimerIgnoreTimerException("We found a timer with same description, skipping event")
-
-                               except AutoTimerIgnoreTimerException, etite:
-                                       print etite
-                                       continue
 
-                               # Event not yet in Timers
+                                               if hasattr(rtimer, "isAutoTimer"):
+                                                               print "[AutoTimer] Modifying existing AutoTimer!"
+                                               else:
+                                                       if config.plugins.autotimer.refresh.value != "all":
+                                                               print "[AutoTimer] Won't modify existing timer because it's no timer set by us"
+                                                               break
+
+                                                       print "[AutoTimer] Warning, we're messing with a timer which might not have been set by us"
+
+                                               newEntry = rtimer
+                                               modified += 1
+
+                                               # Modify values saved in timer
+                                               newEntry.name = name
+                                               newEntry.description = description
+                                               newEntry.begin = int(begin)
+                                               newEntry.end = int(end)
+                                               newEntry.service_ref = ServiceReference(serviceref)
+
+                                               break
+                                       elif timer.avoidDuplicateDescription == 1 and rtimer.description == description:
+                                               oldExists = True
+                                               print "[AutoTimer] We found a timer with same description, skipping event"
+                                               break
+
+                               # We found no timer we want to edit
                                if newEntry is None:
-                                       if timer.checkCounter(timestamp):
+                                       # But there is a match
+                                       if oldExists:
                                                continue
 
-                                       isNew = True
+                                       # We want to search for possible doubles
+                                       if timer.avoidDuplicateDescription == 2:
+                                               # I thinks thats the fastest way to do this, though it's a little ugly
+                                               try:
+                                                       for list in recorddict.values():
+                                                               for rtimer in list:
+                                                                       if rtimer.description == description:
+                                                                               raise AutoTimerIgnoreTimerException("We found a timer with same description, skipping event")
+                                               except AutoTimerIgnoreTimerException, etite:
+                                                       print etite
+                                                       continue
+
+                                       if timer.checkCounter(timestamp):
+                                               continue
 
                                        print "[AutoTimer] Adding an event."
                                        newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, description, eit)
@@ -291,18 +319,21 @@ class AutoTimer:
 
                                newEntry.dirname = timer.destination
                                newEntry.justplay = timer.justplay
-                               newEntry.tags = timer.tags # This needs my enhanced tag support patch to work
+                               newEntry.tags = timer.tags
 
-                               if isNew:
-                                       if NavigationInstance.instance.RecordTimer.record(newEntry) is None:
-                                               new += 1
-                                               if recorddict.has_key(serviceref):
-                                                       recorddict[serviceref].append(newEntry)
-                                               else:
-                                                       recorddict[serviceref] = [newEntry]
-                               else:
+                               if oldExists:
                                        # XXX: this won't perform a sanity check, but do we actually want to do so?
                                        NavigationInstance.instance.RecordTimer.timeChanged(newEntry)
+                               else:
+                                       conflicts = NavigationInstance.instance.RecordTimer.record(newEntry)
+                                       if conflicts and config.plugins.autotimer.disabled_on_conflict.value:
+                                               newEntry.disabled = True
+                                               # We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
+                                               conflicts = NavigationInstance.instance.RecordTimer.record(newEntry)
+                                       if conflicts is None:
+                                               timer.decrementCounter()
+                                               new += 1
+                                               recorddict.setdefault(serviceref, []).append(newEntry)
 
                return (total, new, modified, timers)