1 import NavigationInstance
2 from time import localtime, mktime, gmtime
3 from ServiceReference import ServiceReference
4 from enigma import iServiceInformation, eServiceCenter, eServiceReference
5 from timer import TimerEntry
7 class TimerSanityCheck:
8 def __init__(self, timerlist, newtimer=None):
10 self.localtimediff = 25*3600 - mktime(gmtime(25*3600))
11 self.timerlist = timerlist
12 self.newtimer = newtimer
14 self.rep_eventlist = []
15 self.nrep_eventlist = []
19 def check(self, ext_timer=1):
22 self.newtimer = ext_timer
23 if self.newtimer is None:
26 self.simultimer = [ self.newtimer ]
27 return self.checkTimerlist()
29 def getSimulTimerList(self):
30 return self.simultimer
32 def doubleCheck(self):
33 if self.newtimer is not None and self.newtimer.service_ref.ref.valid():
34 self.simultimer = [ self.newtimer ]
35 for timer in self.timerlist:
36 if (timer == self.newtimer):
39 if timer.begin == self.newtimer.begin:
40 fl1 = timer.service_ref.ref.flags & eServiceReference.isGroup
41 fl2 = self.newtimer.service_ref.ref.flags & eServiceReference.isGroup
45 return timer.service_ref.ref.getPath() == self.newtimer.service_ref.ref.getPath()
46 getUnsignedDataRef1 = timer.service_ref.ref.getUnsignedData
47 getUnsignedDataRef2 = self.newtimer.service_ref.ref.getUnsignedData
48 for x in (1, 2, 3, 4):
49 if getUnsignedDataRef1(x) != getUnsignedDataRef2(x):
55 def checkTimerlist(self, ext_timer=1):
56 #with special service for external plugins
57 # Entries in eventlist
59 # BeginEndFlag 1 for begin, -1 for end
60 # index -1 for the new Timer, 0..n index of the existing timers
61 # count of running timers
63 serviceHandler = eServiceCenter.getInstance()
64 print "checkTimerlist"
65 # create a list with all start and end times
66 # split it into recurring and singleshot timers
68 ##################################################################################
69 # process the new timer
70 self.rep_eventlist = []
71 self.nrep_eventlist = []
73 self.newtimer = ext_timer
74 if (self.newtimer is not None) and (not self.newtimer.disabled):
75 if not self.newtimer.service_ref.ref.valid():
77 rflags = self.newtimer.repeated
78 rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
80 begin = self.newtimer.begin % 86400 # map to first day
81 if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400):
82 rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40)
83 elif (self.localtimediff < 0) and (begin < self.localtimediff):
84 rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01)
85 while rflags: # then arrange on the week
87 self.rep_eventlist.append((begin, -1))
91 self.nrep_eventlist.extend([(self.newtimer.begin,self.bflag,-1),(self.newtimer.end,self.eflag,-1)])
93 ##################################################################################
94 # now process existing timers
96 for timer in self.timerlist:
97 if (timer != self.newtimer) and (not timer.disabled):
99 rflags = timer.repeated
100 rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
101 begin = timer.begin % 86400 # map all to first day
102 if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400):
103 rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40)
104 elif (self.localtimediff < 0) and (begin < self.localtimediff):
105 rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01)
108 self.rep_eventlist.append((begin, idx))
111 elif timer.state < TimerEntry.StateEnded:
112 self.nrep_eventlist.extend([(timer.begin,self.bflag,idx),(timer.end,self.eflag,idx)])
115 ################################################################################
116 # journalize timer repeations
117 if self.nrep_eventlist:
118 interval_begin = min(self.nrep_eventlist)[0]
119 interval_end = max(self.nrep_eventlist)[0]
120 offset_0 = interval_begin - (interval_begin % 604800)
121 weeks = (interval_end - offset_0) / 604800
122 if ((interval_end - offset_0) % 604800):
124 for cnt in range(weeks):
125 for event in self.rep_eventlist:
126 if event[1] == -1: # -1 is the identifier of the changed timer
127 event_begin = self.newtimer.begin
128 event_end = self.newtimer.end
130 event_begin = self.timerlist[event[1]].begin
131 event_end = self.timerlist[event[1]].end
132 new_event_begin = event[0] + offset_0 + (cnt * 604800)
133 # summertime correction
134 new_lth = localtime(new_event_begin).tm_hour
135 new_event_begin += 3600 * (localtime(event_begin).tm_hour - new_lth)
136 new_event_end = new_event_begin + (event_end - event_begin)
138 if new_event_begin >= self.newtimer.begin: # is the soap already running?
139 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
141 if new_event_begin >= self.timerlist[event[1]].begin: # is the soap already running?
142 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
144 offset_0 = 345600 # the Epoch begins on Thursday
145 for cnt in (0, 1): # test two weeks to take care of Sunday-Monday transitions
146 for event in self.rep_eventlist:
147 if event[1] == -1: # -1 is the identifier of the changed timer
148 event_begin = self.newtimer.begin
149 event_end = self.newtimer.end
151 event_begin = self.timerlist[event[1]].begin
152 event_end = self.timerlist[event[1]].end
153 new_event_begin = event[0] + offset_0 + (cnt * 604800)
154 new_event_end = new_event_begin + (event_end - event_begin)
155 self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
157 ################################################################################
158 # order list chronological
159 self.nrep_eventlist.sort()
161 ##################################################################################
162 # detect overlapping timers and overlapping times
165 ConflictTunerType = None
166 newTimerTunerType = None
170 for event in self.nrep_eventlist:
172 if event[2] == -1: # new timer
173 timer = self.newtimer
175 timer = self.timerlist[event[2]]
176 if event[1] == self.bflag:
178 fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True)
180 fakeRecResult = fakeRecService.start(True)
183 if not fakeRecResult: # tune okay
184 feinfo = fakeRecService.frontendInfo().getFrontendData()
185 tunerType.append(feinfo.get("tuner_type"))
186 else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C)
188 def getServiceType(ref): # helper function to get a service type of a service reference
189 serviceInfo = serviceHandler.info(ref)
190 serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData)
191 return serviceInfo and serviceInfo["tuner_type"] or ""
193 ref = timer.service_ref.ref
194 if ref.flags & eServiceReference.isGroup: # service group ?
195 serviceList = serviceHandler.list(ref) # get all alternative services
197 for ref in serviceList.getContent("R"): # iterate over all group service references
198 type = getServiceType(ref)
199 if not type in tunerType: # just add single time
200 tunerType.append(type)
202 tunerType.append(getServiceType(ref))
204 if event[2] == -1: # new timer
205 newTimerTunerType = tunerType
206 overlaplist.append((fakeRecResult, timer, tunerType))
207 fakeRecList.append((timer, fakeRecService))
209 if ConflictTimer is None: # just take care of the first conflict
210 ConflictTimer = timer
211 ConflictTunerType = tunerType
212 elif event[1] == self.eflag:
213 for fakeRec in fakeRecList:
214 if timer == fakeRec[0] and fakeRec[1]:
215 NavigationInstance.instance.stopRecordService(fakeRec[1])
216 fakeRecList.remove(fakeRec)
218 for entry in overlaplist:
219 if entry[1] == timer:
220 overlaplist.remove(entry)
222 print "Bug: unknown flag!"
223 self.nrep_eventlist[idx] = (event[0],event[1],event[2],cnt,overlaplist[:]) # insert a duplicate into current overlaplist
226 if ConflictTimer is None: # no conflict found :)
229 ##################################################################################
230 # we have detected a conflict, now we must figure out the involved timers
232 if self.newtimer is not None: # new timer?
233 if self.newtimer is not ConflictTimer: # the new timer is not the conflicting timer?
234 for event in self.nrep_eventlist:
235 if len(event[4]) > 1: # entry in overlaplist of this event??
238 for entry in event[4]:
239 if entry[1] is ConflictTimer:
241 if entry[1] is self.newtimer:
244 ConflictTimer = self.newtimer
245 ConflictTunerType = newTimerTunerType
248 self.simultimer = [ ConflictTimer ]
249 for event in self.nrep_eventlist:
250 if len(event[4]) > 1: # entry in overlaplist of this event??
251 for entry in event[4]:
252 if entry[1] is ConflictTimer:
256 for entry in event[4]:
257 if not entry[1] in self.simultimer:
259 if x in ConflictTunerType:
260 self.simultimer.append(entry[1])
263 if len(self.simultimer) < 2:
264 print "Bug: unknown Conflict!"
266 return False # conflict detected!