1 import NavigationInstance
2 from time import localtime, mktime, gmtime
3 from ServiceReference import ServiceReference
4 from enigma import iServiceInformation, eServiceCenter, eServiceReference, getBestPlayableServiceReference
5 from timer import TimerEntry
7 class TimerSanityCheck:
8 def __init__(self, timerlist, newtimer=None):
9 self.localtimediff = 25*3600 - mktime(gmtime(25*3600))
10 self.timerlist = timerlist
11 self.newtimer = newtimer
13 self.rep_eventlist = []
14 self.nrep_eventlist = []
18 def check(self, ext_timer=1):
20 self.newtimer = ext_timer
21 if self.newtimer is None:
24 self.simultimer = [ self.newtimer ]
25 return self.checkTimerlist()
27 def getSimulTimerList(self):
28 return self.simultimer
30 def doubleCheck(self):
31 if self.newtimer is not None and self.newtimer.service_ref.ref.valid():
32 self.simultimer = [ self.newtimer ]
33 for timer in self.timerlist:
34 if self.newtimer.begin >= timer.begin and self.newtimer.end <= timer.end:
35 if timer.justplay and not self.newtimer.justplay:
37 if timer.service_ref.ref.flags & eServiceReference.isGroup:
38 if self.newtimer.service_ref.ref.flags & eServiceReference.isGroup and timer.service_ref.ref.getPath() == self.newtimer.service_ref.ref.getPath():
41 getUnsignedDataRef1 = timer.service_ref.ref.getUnsignedData
42 getUnsignedDataRef2 = self.newtimer.service_ref.ref.getUnsignedData
43 for x in (1, 2, 3, 4):
44 if getUnsignedDataRef1(x) != getUnsignedDataRef2(x):
50 def checkTimerlist(self, ext_timer=1):
51 #with special service for external plugins
52 # Entries in eventlist
54 # BeginEndFlag 1 for begin, -1 for end
55 # index -1 for the new Timer, 0..n index of the existing timers
56 # count of running timers
58 serviceHandler = eServiceCenter.getInstance()
59 # create a list with all start and end times
60 # split it into recurring and singleshot timers
62 ##################################################################################
63 # process the new timer
64 self.rep_eventlist = []
65 self.nrep_eventlist = []
67 self.newtimer = ext_timer
68 if (self.newtimer is not None) and (not self.newtimer.disabled):
69 if not self.newtimer.service_ref.ref.valid():
71 rflags = self.newtimer.repeated
72 rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
74 begin = self.newtimer.begin % 86400 # map to first day
75 if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400):
76 rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40)
77 elif (self.localtimediff < 0) and (begin < self.localtimediff):
78 rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01)
79 while rflags: # then arrange on the week
81 self.rep_eventlist.append((begin, -1))
85 self.nrep_eventlist.extend([(self.newtimer.begin,self.bflag,-1),(self.newtimer.end,self.eflag,-1)])
87 ##################################################################################
88 # now process existing timers
90 for timer in self.timerlist:
91 if (timer != self.newtimer) and (not timer.disabled):
93 rflags = timer.repeated
94 rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
95 begin = timer.begin % 86400 # map all to first day
96 if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400):
97 rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40)
98 elif (self.localtimediff < 0) and (begin < self.localtimediff):
99 rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01)
102 self.rep_eventlist.append((begin, idx))
105 elif timer.state < TimerEntry.StateEnded:
106 self.nrep_eventlist.extend([(timer.begin,self.bflag,idx),(timer.end,self.eflag,idx)])
109 ################################################################################
110 # journalize timer repeations
111 if self.nrep_eventlist:
112 interval_begin = min(self.nrep_eventlist)[0]
113 interval_end = max(self.nrep_eventlist)[0]
114 offset_0 = interval_begin - (interval_begin % 604800)
115 weeks = (interval_end - offset_0) / 604800
116 if ((interval_end - offset_0) % 604800):
118 for cnt in range(weeks):
119 for event in self.rep_eventlist:
120 if event[1] == -1: # -1 is the identifier of the changed timer
121 event_begin = self.newtimer.begin
122 event_end = self.newtimer.end
124 event_begin = self.timerlist[event[1]].begin
125 event_end = self.timerlist[event[1]].end
126 new_event_begin = event[0] + offset_0 + (cnt * 604800)
127 # summertime correction
128 new_lth = localtime(new_event_begin).tm_hour
129 new_event_begin += 3600 * (localtime(event_begin).tm_hour - new_lth)
130 new_event_end = new_event_begin + (event_end - event_begin)
132 if new_event_begin >= self.newtimer.begin: # is the soap already running?
133 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
135 if new_event_begin >= self.timerlist[event[1]].begin: # is the soap already running?
136 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
138 offset_0 = 345600 # the Epoch begins on Thursday
139 for cnt in (0, 1): # test two weeks to take care of Sunday-Monday transitions
140 for event in self.rep_eventlist:
141 if event[1] == -1: # -1 is the identifier of the changed timer
142 event_begin = self.newtimer.begin
143 event_end = self.newtimer.end
145 event_begin = self.timerlist[event[1]].begin
146 event_end = self.timerlist[event[1]].end
147 new_event_begin = event[0] + offset_0 + (cnt * 604800)
148 new_event_end = new_event_begin + (event_end - event_begin)
149 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
151 ################################################################################
152 # order list chronological
153 self.nrep_eventlist.sort()
155 ##################################################################################
156 # detect overlapping timers and overlapping times
159 ConflictTunerType = None
160 newTimerTunerType = None
164 for event in self.nrep_eventlist:
166 if event[2] == -1: # new timer
167 timer = self.newtimer
169 timer = self.timerlist[event[2]]
170 if event[1] == self.bflag:
172 if timer.service_ref.ref and timer.service_ref.ref.flags & eServiceReference.isGroup:
173 fakeRecService = NavigationInstance.instance.recordService(getBestPlayableServiceReference(timer.service_ref.ref, eServiceReference(), True), True)
175 fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True)
177 fakeRecResult = fakeRecService.start(True)
180 if not fakeRecResult: # tune okay
181 feinfo = fakeRecService.frontendInfo().getFrontendData()
182 tunerType.append(feinfo.get("tuner_type"))
183 else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C)
185 def getServiceType(ref): # helper function to get a service type of a service reference
186 serviceInfo = serviceHandler.info(ref)
187 serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData)
188 return serviceInfo and serviceInfo["tuner_type"] or ""
190 ref = timer.service_ref.ref
191 if ref.flags & eServiceReference.isGroup: # service group ?
192 serviceList = serviceHandler.list(ref) # get all alternative services
194 for ref in serviceList.getContent("R"): # iterate over all group service references
195 type = getServiceType(ref)
196 if not type in tunerType: # just add single time
197 tunerType.append(type)
199 tunerType.append(getServiceType(ref))
201 if event[2] == -1: # new timer
202 newTimerTunerType = tunerType
203 overlaplist.append((fakeRecResult, timer, tunerType))
204 fakeRecList.append((timer, fakeRecService))
206 if ConflictTimer is None: # just take care of the first conflict
207 ConflictTimer = timer
208 ConflictTunerType = tunerType
209 elif event[1] == self.eflag:
210 for fakeRec in fakeRecList:
211 if timer == fakeRec[0] and fakeRec[1]:
212 NavigationInstance.instance.stopRecordService(fakeRec[1])
213 fakeRecList.remove(fakeRec)
215 for entry in overlaplist:
216 if entry[1] == timer:
217 overlaplist.remove(entry)
219 print "Bug: unknown flag!"
220 self.nrep_eventlist[idx] = (event[0],event[1],event[2],cnt,overlaplist[:]) # insert a duplicate into current overlaplist
223 if ConflictTimer is None: # no conflict found :)
226 ##################################################################################
227 # we have detected a conflict, now we must figure out the involved timers
229 if self.newtimer is not None: # new timer?
230 if self.newtimer is not ConflictTimer: # the new timer is not the conflicting timer?
231 for event in self.nrep_eventlist:
232 if len(event[4]) > 1: # entry in overlaplist of this event??
235 for entry in event[4]:
236 if entry[1] is ConflictTimer:
238 if entry[1] is self.newtimer:
241 ConflictTimer = self.newtimer
242 ConflictTunerType = newTimerTunerType
245 self.simultimer = [ ConflictTimer ]
246 for event in self.nrep_eventlist:
247 if len(event[4]) > 1: # entry in overlaplist of this event??
248 for entry in event[4]:
249 if entry[1] is ConflictTimer:
253 for entry in event[4]:
254 if not entry[1] in self.simultimer:
256 if x in ConflictTunerType:
257 self.simultimer.append(entry[1])
260 if len(self.simultimer) < 2:
261 print "Possible Bug: unknown Conflict!"
264 return False # conflict detected!