2 from xml.dom.minidom import parse as minidom_parse
3 from os import path as os_path
4 from AutoTimerConfiguration import parseConfig, writeConfig
6 # Navigation (RecordTimer)
7 import NavigationInstance
10 from ServiceReference import ServiceReference
11 from RecordTimer import RecordTimerEntry
12 from Components.TimerSanityCheck import TimerSanityCheck
15 from time import localtime, time
18 from enigma import eEPGCache, eServiceReference
21 from Components.config import config
24 from AutoTimerComponent import AutoTimerComponent
26 XML_CONFIG = "/etc/enigma2/autotimer.xml"
28 def getTimeDiff(timer, begin, end):
29 if begin <= timer.begin <= end:
30 return end - timer.begin
31 elif timer.begin <= begin <= timer.end:
32 return timer.end - begin
35 class AutoTimerIgnoreTimerException(Exception):
36 def __init__(self, cause):
40 return "[AutoTimer] " + str(self.cause)
43 return str(type(self))
46 """Read and save xml configuration, query EPGCache"""
50 self.epgcache = eEPGCache.getInstance()
55 self.uniqueTimerId = 0
56 self.defaultTimer = AutoTimerComponent(
66 # Abort if no config found
67 if not os_path.exists(XML_CONFIG):
68 print "[AutoTimer] No configuration file present"
71 # Parse if mtime differs from whats saved
72 mtime = os_path.getmtime(XML_CONFIG)
73 if mtime == self.configMtime:
74 print "[AutoTimer] No changes in configuration, won't parse"
78 self.configMtime = mtime
81 dom = minidom_parse(XML_CONFIG)
83 # Empty out timers and reset Ids
85 self.uniqueTimerId = 0
86 self.defaultTimer.clear(-1, True)
89 for configuration in dom.getElementsByTagName("autotimer"):
93 configuration.getAttribute("version"),
97 self.uniqueTimerId = len(self.timers)
100 writeConfig(XML_CONFIG, self.defaultTimer, self.timers)
104 def add(self, timer):
105 self.timers.append(timer)
107 def getEnabledTimerList(self):
108 return [x for x in self.timers if x.enabled]
110 def getTimerList(self):
113 def getTupleTimerList(self):
114 return [(x,) for x in self.timers]
116 def getUniqueId(self):
117 self.uniqueTimerId += 1
118 return self.uniqueTimerId
120 def remove(self, uniqueId):
122 for timer in self.timers:
123 if timer.id == uniqueId:
128 def set(self, timer):
130 for stimer in self.timers:
132 self.timers[idx] = timer
135 self.timers.append(timer)
139 def parseEPG(self, simulateOnly = False):
140 if NavigationInstance.instance is None:
141 print "[AutoTimer] Navigation is not available, can't parse EPG"
151 # Save Recordings in a dict to speed things up a little
152 # We include processed timers as we might search for duplicate descriptions
154 for timer in NavigationInstance.instance.RecordTimer.timer_list + NavigationInstance.instance.RecordTimer.processed_timers:
155 if not recorddict.has_key(str(timer.service_ref)):
156 recorddict[str(timer.service_ref)] = [timer]
158 recorddict[str(timer.service_ref)].append(timer)
161 for timer in self.getEnabledTimerList():
162 # Search EPG, default to empty list
163 ret = self.epgcache.search(('RI', 100, eEPGCache.PARTIAL_TITLE_SEARCH, timer.match, eEPGCache.NO_CASE_CHECK)) or []
165 for serviceref, eit in ret:
166 eserviceref = eServiceReference(serviceref)
168 evt = self.epgcache.lookupEventId(eserviceref, eit)
170 print "[AutoTimer] Could not create Event!"
173 # Try to determine real service (we always choose the last one)
174 n = evt.getNumOfLinkageServices()
176 i = evt.getLinkageService(eserviceref, n-1)
177 serviceref = i.toString()
180 name = evt.getEventName()
181 description = evt.getShortDescription()
182 begin = evt.getBeginTime()
183 duration = evt.getDuration()
184 end = begin + duration
186 # If event starts in less than 60 seconds skip it
187 if begin < time() + 60:
191 timestamp = localtime(begin)
194 timer.update(begin, timestamp)
196 # Check Duration, Timespan and Excludes
197 if timer.checkServices(serviceref) \
198 or timer.checkDuration(duration) \
199 or timer.checkTimespan(timestamp) \
200 or timer.checkFilter(name, description,
201 evt.getExtendedDescription(), str(timestamp.tm_wday)):
204 if timer.hasOffset():
205 # Apply custom Offset
206 begin, end = timer.applyOffset(begin, end)
209 begin -= config.recording.margin_before.value * 60
210 end += config.recording.margin_after.value * 60
215 # Append to timerlist and abort if simulating
216 timers.append((name, begin, end, serviceref, timer.name))
223 # Check for double Timers
224 # We first check eit and if user wants us to guess event based on time
225 # we try this as backup. The allowed diff should be configurable though.
227 for rtimer in recorddict.get(serviceref, []):
228 if rtimer.eit == eit or config.plugins.autotimer.try_guessing.value and getTimeDiff(rtimer, begin, end) > ((duration/10)*8):
231 # Abort if we don't want to modify timers or timer is repeated
232 if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
233 raise AutoTimerIgnoreTimerException("Won't modify existing timer because either no modification allowed or repeated timer")
236 if newEntry.isAutoTimer:
237 print "[AutoTimer] Modifying existing AutoTimer!"
238 except AttributeError, ae:
239 if config.plugins.autotimer.refresh.value != "all":
240 raise AutoTimerIgnoreTimerException("Won't modify existing timer because it's no timer set by us")
241 print "[AutoTimer] Warning, we're messing with a timer which might not have been set by us"
243 func = NavigationInstance.instance.RecordTimer.timeChanged
246 # Modify values saved in timer
248 newEntry.description = description
249 newEntry.begin = int(begin)
250 newEntry.end = int(end)
251 newEntry.service_ref = ServiceReference(serviceref)
254 elif timer.getAvoidDuplicateDescription() and rtimer.description == description:
255 raise AutoTimerIgnoreTimerException("We found a timer with same description, skipping event")
257 except AutoTimerIgnoreTimerException, etite:
261 # Event not yet in Timers
263 if timer.checkCounter(timestamp):
268 print "[AutoTimer] Adding an event."
269 newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, description, eit)
270 func = NavigationInstance.instance.RecordTimer.record
272 # Mark this entry as AutoTimer (only AutoTimers will have this Attribute set)
273 newEntry.isAutoTimer = True
275 if not recorddict.has_key(serviceref):
276 recorddict[serviceref] = [newEntry]
278 recorddict[serviceref].append(newEntry)
281 if timer.hasAfterEvent():
282 afterEvent = timer.getAfterEventTimespan(localtime(end))
283 if afterEvent is None:
284 afterEvent = timer.getAfterEvent()
285 if afterEvent is not None:
286 newEntry.afterEvent = afterEvent
288 newEntry.dirname = timer.destination
289 newEntry.justplay = timer.justplay
290 newEntry.tags = timer.tags # This needs my enhanced tag support patch to work
292 # Do a sanity check, although it does not do much right now
293 timersanitycheck = TimerSanityCheck(NavigationInstance.instance.RecordTimer.timer_list, newEntry)
294 if not timersanitycheck.check():
295 print "[Autotimer] Sanity check failed"
297 print "[Autotimer] Sanity check passed"
299 # Either add to List or change time
302 return (total, new, modified, timers)