AutoTimer: add "Fast Scan" support
[vuplus_dvbapp-plugin] / autotimer / src / AutoTimer.py
index ad75673..ea72e13 100644 (file)
@@ -1,13 +1,14 @@
 # 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, buildConfig
 
 # Navigation (RecordTimer)
 import NavigationInstance
 
 # Timer
 from ServiceReference import ServiceReference
-from RecordTimer import RecordTimerEntry, AFTEREVENT
+from RecordTimer import RecordTimerEntry
 from Components.TimerSanityCheck import TimerSanityCheck
 
 # Timespan
@@ -20,33 +21,9 @@ 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"
-CURRENT_CONFIG_VERSION = "4"
-
-def getValue(definitions, default, isList = True):
-       # Initialize Output
-       ret = ""
-
-       # How many definitions are present
-       if isList:
-               Len = len(definitions)
-               if Len > 0:
-                       childNodes = definitions[Len-1].childNodes
-               else:
-                       childNodes = []
-       else:
-               childNodes = definitions.childNodes
-
-       # Iterate through nodes of last one
-       for node in childNodes:
-               # Append text if we have a text node
-               if node.nodeType == node.TEXT_NODE:
-                       ret = ret + node.data
-
-       # Return stripped output or (if empty) default
-       return ret.strip() or default
 
 def getTimeDiff(timer, begin, end):
        if begin <= timer.begin <= end:
@@ -55,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
@@ -69,17 +56,23 @@ 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 = preferredAutoTimerComponent(
+                       0,              # Id
+                       "",             # Name
+                       "",             # Match
+                       True    # Enabled
+               )
+
+# Configuration
 
        def readXml(self):
                # Abort if no config found
                if not os_path.exists(XML_CONFIG):
+                       print "[AutoTimer] No configuration file present"
                        return
 
                # Parse if mtime differs from whats saved
@@ -92,189 +85,60 @@ 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"):
-                       # Parse old configuration files
-                       if configuration.getAttribute("version") != CURRENT_CONFIG_VERSION:
-                               from OldConfigurationParser import parseConfig
-                               parseConfig(configuration, self.timers, configuration.getAttribute("version"), self.uniqueTimerId)
-                               if not self.uniqueTimerId:
-                                       self.uniqueTimerId = len(self.timers)
-                               continue
-                       # Iterate Timers
-                       for timer in configuration.getElementsByTagName("timer"):
-                               # Timers are saved as tuple (name, allowedtime (from, to) or None, list of services or None, timeoffset in m (before, after) or None, afterevent)
-
-                               # Increment uniqueTimerId
-                               self.uniqueTimerId += 1
-
-                               # Read out match
-                               match = timer.getAttribute("match").encode("UTF-8")
-                               if not match:
-                                       print '[AutoTimer] Erroneous config is missing attribute "match", skipping entry'
-                                       continue
+               parseConfig(
+                       configuration,
+                       self.timers,
+                       configuration.get("version"),
+                       0,
+                       self.defaultTimer
+               )
+               self.uniqueTimerId = len(self.timers)
 
-                               # Read out name
-                               name = timer.getAttribute("name").encode("UTF-8")
-                               if not name:
-                                       print '[AutoTimer] Timer is missing attribute "name", defaulting to match'
-                                       name = match
-
-                               # Read out enabled
-                               enabled = timer.getAttribute("enabled") or "yes"
-                               if enabled == "no":
-                                       enabled = False
-                               elif enabled == "yes":
-                                       enabled = True
-                               else:
-                                       print '[AutoTimer] Erroneous config contains invalid value for "enabled":', enabled,', disabling'
-                                       enabled = False
-
-                               # Read out timespan
-                               start = timer.getAttribute("from")
-                               end = timer.getAttribute("to")
-                               if start and end:
-                                       start = [int(x) for x in start.split(':')]
-                                       end = [int(x) for x in end.split(':')]
-                                       timetuple = (start, end)
-                               else:
-                                       timetuple = None
-
-                               # Read out max length
-                               maxlen = timer.getAttribute("maxduration") or None
-                               if maxlen:
-                                       maxlen = int(maxlen)*60
-
-                               # Read out recording path (needs my Location-select patch)
-                               destination = timer.getAttribute("destination").encode("UTF-8") or None
-
-                               # Read out offset
-                               offset = timer.getAttribute("offset") or None
-                               if offset:
-                                       offset = offset.split(",")
-                                       if len(offset) == 1:
-                                               before = after = int(offset[0] or 0) * 60
-                                       else:
-                                               before = int(offset[0] or 0) * 60
-                                               after = int(offset[1] or 0) * 60
-                                       offset = (before, after)
-
-                               # Read out counter
-                               counter = int(timer.getAttribute("counter") or '0')
-                               counterLeft = int(timer.getAttribute("left") or counter)
-                               counterLimit = timer.getAttribute("lastActivation")
-                               counterFormat = timer.getAttribute("counterFormat")
-                               lastBegin = int(timer.getAttribute("lastBegin") or 0)
-
-                               # Read out justplay
-                               justplay = int(timer.getAttribute("justplay") or '0')
-
-                               # Read out avoidDuplicateDescription
-                               avoidDuplicateDescription = bool(timer.getAttribute("avoidDuplicateDescription") or False)
-
-                               # Read out allowed services
-                               servicelist = []                                        
-                               for service in timer.getElementsByTagName("serviceref"):
-                                       value = getValue(service, None, False)
-                                       if value:
-                                               # strip all after last :
-                                               pos = value.rfind(':')
-                                               if pos != -1:
-                                                       value = value[:pos+1]
-
-                                               servicelist.append(value)
-
-                               # Read out afterevent
-                               idx = {"none": AFTEREVENT.NONE, "standby": AFTEREVENT.STANDBY, "shutdown": AFTEREVENT.DEEPSTANDBY, "deepstandby": AFTEREVENT.DEEPSTANDBY}
-                               afterevent = []
-                               for element in timer.getElementsByTagName("afterevent"):
-                                       value = getValue(element, None, False)
-
-                                       try:
-                                               value = idx[value]
-                                               start = element.getAttribute("from")
-                                               end = element.getAttribute("to")
-                                               if start and end:
-                                                       start = [int(x) for x in start.split(':')]
-                                                       end = [int(x) for x in end.split(':')]
-                                                       afterevent.append((value, (start, end)))
-                                               else:
-                                                       afterevent.append((value, None))
-                                       except KeyError, ke:
-                                               print '[AutoTimer] Erroneous config contains invalid value for "afterevent":', afterevent,', ignoring definition'
-                                               continue
-
-                               # Read out exclude
-                               idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
-                               excludes = ([], [], [], []) 
-                               for exclude in timer.getElementsByTagName("exclude"):
-                                       where = exclude.getAttribute("where")
-                                       value = getValue(exclude, None, False)
-                                       if not (value and where):
-                                               continue
+       def getXml(self):
+               return buildConfig(self.defaultTimer, self.timers, webif = True)
 
-                                       try:
-                                               excludes[idx[where]].append(value.encode("UTF-8"))
-                                       except KeyError, ke:
-                                               pass
-
-                               # Read out includes (use same idx)
-                               includes = ([], [], [], []) 
-                               for include in timer.getElementsByTagName("include"):
-                                       where = include.getAttribute("where")
-                                       value = getValue(include, None, False)
-                                       if not (value and where):
-                                               continue
+       def writeXml(self):
+               file = open(XML_CONFIG, 'w')
+               file.writelines(buildConfig(self.defaultTimer, self.timers))
+               file.close()
 
-                                       try:
-                                               includes[idx[where]].append(value.encode("UTF-8"))
-                                       except KeyError, ke:
-                                               pass
-
-                               # Finally append tuple
-                               self.timers.append(AutoTimerComponent(
-                                               self.uniqueTimerId,
-                                               name,
-                                               match,
-                                               enabled,
-                                               timespan = timetuple,
-                                               services = servicelist,
-                                               offset = offset,
-                                               afterevent = afterevent,
-                                               exclude = excludes,
-                                               include = includes,
-                                               maxduration = maxlen,
-                                               destination = destination,
-                                               matchCount = counter,
-                                               matchLeft = counterLeft,
-                                               matchLimit = counterLimit,
-                                               matchFormatString = counterFormat,
-                                               lastBegin = lastBegin,
-                                               justplay = justplay,
-                                               avoidDuplicateDescription = avoidDuplicateDescription
-                               ))
+# Manage List
 
-       def getTimerList(self):
-               return self.timers
+       def add(self, timer):
+               self.timers.append(timer)
 
        def getEnabledTimerList(self):
                return [x for x in self.timers if x.enabled]
 
+       def getTimerList(self):
+               return self.timers
+
        def getTupleTimerList(self):
-               return [(x,) for x in self.timers]
+               list = self.timers
+               return [(x,) for x in list]
+
+       def getSortedTupleTimerList(self):
+               list = self.timers[:]
+               list.sort()
+               return [(x,) for x in list]
 
        def getUniqueId(self):
                self.uniqueTimerId += 1
                return self.uniqueTimerId
 
-       def add(self, timer):
-               self.timers.append(timer)
+       def remove(self, uniqueId):
+               idx = 0
+               for timer in self.timers:
+                       if timer.id == uniqueId:
+                               self.timers.pop(idx)
+                               return
+                       idx += 1
 
        def set(self, timer):
                idx = 0
@@ -285,112 +149,7 @@ class AutoTimer:
                        idx += 1
                self.timers.append(timer)
 
-       def remove(self, uniqueId):
-               idx = 0
-               for timer in self.timers:
-                       if timer.id == uniqueId:
-                               self.timers.pop(idx)
-                               return
-                       idx += 1
-
-       def writeXml(self):
-               # Generate List in RAM
-               list = ['<?xml version="1.0" ?>\n<autotimer version="', CURRENT_CONFIG_VERSION, '">\n\n']
-
-               # Iterate timers
-               for timer in self.timers:
-                       # Common attributes (match, enabled)
-                       list.extend([' <timer name="', timer.name, '" match="', timer.match, '" enabled="', timer.getEnabled(), '"'])
-
-                       # Timespan
-                       if timer.hasTimespan():
-                               list.extend([' from="', timer.getTimespanBegin(), '" to="', timer.getTimespanEnd(), '"'])
-
-                       # Duration
-                       if timer.hasDuration():
-                               list.extend([' maxduration="', str(timer.getDuration()), '"'])
-
-                       # Destination (needs my Location-select patch)
-                       if timer.hasDestination():
-                               list.extend([' destination="', str(timer.destination), '"'])
-
-                       # Offset
-                       if timer.hasOffset():
-                               if timer.isOffsetEqual():
-                                       list.extend([' offset="', str(timer.getOffsetBegin()), '"'])
-                               else:
-                                       list.extend([' offset="', str(timer.getOffsetBegin()), ',', str(timer.getOffsetEnd()), '"'])
-
-                       # Counter
-                       if timer.hasCounter():
-                               list.extend([' lastBegin="', str(timer.getLastBegin()), '" counter="', str(timer.getCounter()), '" left="', str(timer.getCounterLeft()) ,'"'])
-                               if timer.hasCounterFormatString():
-                                       list.extend([' lastActivation="', str(timer.getCounterLimit()), '"'])
-                                       list.extend([' counterFormat="', str(timer.getCounterFormatString()), '"'])
-
-                       # Duplicate Description
-                       if timer.getAvoidDuplicateDescription():
-                               list.append(' avoidDuplicateDescription="1" ')
-
-                       # Only display justplay if true
-                       if timer.justplay:
-                               list.extend([' justplay="', str(timer.getJustplay()), '"'])
-
-                       # Close still opened timer tag
-                       list.append('>\n')
-
-                       # Services
-                       for serviceref in timer.getServices():
-                               list.extend(['  <serviceref>', serviceref, '</serviceref>'])
-                               ref = ServiceReference(str(serviceref))
-                               list.extend([' <!-- ', ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''), ' -->\n'])
-
-                       # AfterEvent
-                       if timer.hasAfterEvent():
-                               idx = {AFTEREVENT.NONE: "none", AFTEREVENT.STANDBY: "standby", AFTEREVENT.DEEPSTANDBY: "shutdown"}
-                               for afterevent in timer.getCompleteAfterEvent():
-                                       action, timespan = afterevent
-                                       list.append('  <afterevent')
-                                       if timespan[0] is not None:
-                                               list.append(' from="%02d:%02d" to="%02d:%02d"' % (timespan[0][0], timespan[0][1], timespan[1][0], timespan[1][1]))
-                                       list.extend(['>', idx[action], '</afterevent>\n'])
-
-                       # Excludes
-                       for title in timer.getExcludedTitle():
-                               list.extend(['  <exclude where="title">', title, '</exclude>\n'])
-                       for short in timer.getExcludedShort():
-                               list.extend(['  <exclude where="shortdescription">', short, '</exclude>\n'])
-                       for desc in timer.getExcludedDescription():
-                               list.extend(['  <exclude where="description">', desc, '</exclude>\n'])
-                       for day in timer.getExcludedDays():
-                               list.extend(['  <exclude where="dayofweek">', day, '</exclude>\n'])
-
-                       # Includes
-                       for title in timer.getIncludedTitle():
-                               list.extend(['  <include where="title">', title, '</include>\n'])
-                       for short in timer.getIncludedShort():
-                               list.extend(['  <include where="shortdescription">', short, '</include>\n'])
-                       for desc in timer.getIncludedDescription():
-                               list.extend(['  <include where="description">', desc, '</include>\n'])
-                       for day in timer.getIncludedDays():
-                               list.extend(['  <include where="dayofweek">', day, '</include>\n'])
-
-                       # End of Timer
-                       list.append(' </timer>\n\n')
-
-               # End of Configuration
-               list.append('</autotimer>\n')
-
-               # Try Saving to Flash
-               file = None
-               try:
-                       file = open(XML_CONFIG, 'w')
-                       file.writelines(list)
-
-                       # FIXME: This should actually be placed inside a finally-block but python 2.4 does not support this - waiting for some images to upgrade
-                       file.close()
-               except Exception, e:
-                       print "[AutoTimer] Error Saving Timer List:", e
+# Main function
 
        def parseEPG(self, simulateOnly = False):
                if NavigationInstance.instance is None:
@@ -405,22 +164,29 @@ class AutoTimer:
                self.readXml()
 
                # Save Recordings in a dict to speed things up a little
+               # We include processed timers as we might search for duplicate descriptions
                recorddict = {}
-               for timer in NavigationInstance.instance.RecordTimer.timer_list:
-                       if not recorddict.has_key(str(timer.service_ref)):
-                               recorddict[str(timer.service_ref)] = [timer]
-                       else:
-                               recorddict[str(timer.service_ref)].append(timer)
+               for timer in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers:
+                       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
@@ -449,15 +215,24 @@ class AutoTimer:
                                timer.update(begin, timestamp)
 
                                # Check Duration, Timespan and Excludes
-                               if timer.checkServices(serviceref) or timer.checkDuration(duration) or timer.checkTimespan(timestamp) or timer.checkFilter(name, description, evt.getExtendedDescription(), str(timestamp.tm_wday)):
+                               if timer.checkServices(serviceref) \
+                                       or timer.checkDuration(duration) \
+                                       or timer.checkTimespan(timestamp) \
+                                       or timer.checkFilter(name, description,
+                                               evt.getExtendedDescription(), str(timestamp.tm_wday)):
                                        continue
 
-                               # Apply E2 Offset
-                               begin -= config.recording.margin_before.value * 60
-                               end += config.recording.margin_after.value * 60
-                               # Apply custom Offset
-                               begin, end = timer.applyOffset(begin, end)
+                               if timer.hasOffset():
+                                       # Apply custom Offset
+                                       begin, end = timer.applyOffset(begin, end)
+                               else:
+                                       # Apply E2 Offset
+                                       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
 
@@ -468,55 +243,68 @@ class AutoTimer:
 
                                # Initialize
                                newEntry = None
+                               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")
-
-                                                       try:
-                                                               if newEntry.isAutoTimer:
-                                                                       print "[AutoTimer] Modifying existing AutoTimer!"
-                                                       except AttributeError, ae:
-                                                               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"
-
-                                                       func = NavigationInstance.instance.RecordTimer.timeChanged
-                                                       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() and rtimer.description == description:
-                                                       raise AutoTimerIgnoreTimerException("We found a timer with same description, skipping event")
 
-                               except AutoTimerIgnoreTimerException, etite:
-                                       print etite
-                                       continue
+                                               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)
 
-                               # Event not yet in Timers
+                                               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
 
-                                       new += 1
+                                       # 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)
-                                       func = NavigationInstance.instance.RecordTimer.record
 
                                        # Mark this entry as AutoTimer (only AutoTimers will have this Attribute set)
                                        newEntry.isAutoTimer = True
@@ -529,22 +317,23 @@ class AutoTimer:
                                        if afterEvent is not None:
                                                newEntry.afterEvent = afterEvent
 
-                               # Set custom destination directory (needs my Location-select patch)
-                               if timer.hasDestination():
-                                       # TODO: add warning when patch not installed?
-                                       newEntry.dirname = timer.destination
-                               # Make this timer a zap-timer if wanted
-                               newEntry.justplay = timer.justplay
-                               # Do a sanity check, although it does not do much right now
-                               timersanitycheck = TimerSanityCheck(NavigationInstance.instance.RecordTimer.timer_list, newEntry)
-                               if not timersanitycheck.check():
-                                       print "[Autotimer] Sanity check failed"
-                               else:
-                                       print "[Autotimer] Sanity check passed"
-
-                               # Either add to List or change time
-                               func(newEntry)
-
-               return (total, new, modified, timers)
\ No newline at end of file
+                               newEntry.dirname = timer.destination
+                               newEntry.justplay = timer.justplay
+                               newEntry.tags = timer.tags
+
+                               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)
+