X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/6eeefece35e4269e02fdb7abab4f79d8e7b8f98b..4c1d3d2f5cf39f72bf85041a6ba6665350ea742e:/lib/python/Components/TimerSanityCheck.py diff --git a/lib/python/Components/TimerSanityCheck.py b/lib/python/Components/TimerSanityCheck.py index 35e78de0..8f48d1ec 100644 --- a/lib/python/Components/TimerSanityCheck.py +++ b/lib/python/Components/TimerSanityCheck.py @@ -1,60 +1,265 @@ -from Components.NimManager import nimmanager -from time import localtime +import NavigationInstance +from time import localtime, mktime, gmtime +from ServiceReference import ServiceReference +from enigma import iServiceInformation, eServiceCenter, eServiceReference class TimerSanityCheck: - def __init__(self, timerlist, newtimer): + def __init__(self, timerlist, newtimer=None): + print "sanitycheck" + self.localtimediff = 25*3600 - mktime(gmtime(25*3600)) self.timerlist = timerlist self.newtimer = newtimer self.simultimer = [] - - def check(self): - self.simultimer = [ self.newtimer ] - for timer in self.timerlist: - if self.isSimultaneous(timer, self.newtimer): - self.simultimer.append(timer) - - if len(self.simultimer) > 1: - return self.checkRecordable(self.simultimer) - - return True + self.rep_eventlist = [] + self.nrep_eventlist = [] + self.bflag = 1 + self.eflag = -1 + + def check(self, ext_timer=1): + print "check" + if ext_timer != 1: + self.newtimer = ext_timer + if self.newtimer is None: + self.simultimer = [] + else: + self.simultimer = [ self.newtimer ] + return self.checkTimerlist() def getSimulTimerList(self): return self.simultimer - - def isSimultaneous(self, timer1, timer2): - # both timers are repeated - if (timer1.repeated & timer2.repeated): - return self.timeEquals(timer1, timer2) - - # one timer is repeated - if not timer1.repeated: - tmp = timer1 - timer1 = timer2 - timer2 = tmp - - if timer1.repeated: - dow2 = (localtime(timer2.begin).tm_wday - 1) % 7 - - if timer1.repeated & (2 ** dow2): - return self.timeEquals(timer1, timer2) - else: - if (timer1.begin <= timer2.begin < timer1.end) or (timer2.begin <= timer1.begin < timer2.end): - return True + def doubleCheck(self): + if self.newtimer is not None and self.newtimer.service_ref.ref.valid(): + self.simultimer = [ self.newtimer ] + for timer in self.timerlist: + if (timer == self.newtimer): + return True + else: + if timer.begin == self.newtimer.begin: + fl1 = timer.service_ref.ref.flags & eServiceReference.isGroup + fl2 = self.newtimer.service_ref.ref.flags & eServiceReference.isGroup + if fl1 != fl2: + return False + if fl1: #is group + return timer.service_ref.ref.getPath() == self.newtimer.service_ref.ref.getPath() + getUnsignedDataRef1 = timer.service_ref.ref.getUnsignedData + getUnsignedDataRef2 = self.newtimer.service_ref.ref.getUnsignedData + for x in (1, 2, 3, 4): + if getUnsignedDataRef1(x) != getUnsignedDataRef2(x): + break; + else: + return True return False - def timeEquals(self, timer1, timer2): - ltb1 = localtime(timer1.begin) - ltb2 = localtime(timer2.begin) - - begin1 = ltb1.tm_hour * 3600 + ltb1.tm_min * 60 + ltb1.tm_sec - begin2 = ltb2.tm_hour * 3600 + ltb2.tm_min * 60 + ltb2.tm_sec - - end1 = begin1 + timer1.end - timer1.begin - end2 = begin2 + timer2.end - timer2.begin - - return (begin1 <= begin2 < end1) or (begin2 <= begin1 < end2) - - def checkRecordable(self, timerlist): - # TODO: Add code here - return True \ No newline at end of file + def checkTimerlist(self, ext_timer=1): + #with special service for external plugins + # Entries in eventlist + # timeindex + # BeginEndFlag 1 for begin, -1 for end + # index -1 for the new Timer, 0..n index of the existing timers + # count of running timers + + serviceHandler = eServiceCenter.getInstance() + print "checkTimerlist" +# create a list with all start and end times +# split it into recurring and singleshot timers + +################################################################################## +# process the new timer + self.rep_eventlist = [] + self.nrep_eventlist = [] + if ext_timer != 1: + self.newtimer = ext_timer + if (self.newtimer is not None) and (not self.newtimer.disabled): + if not self.newtimer.service_ref.ref.valid(): + return False + rflags = self.newtimer.repeated + rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4) + if rflags: + begin = self.newtimer.begin % 86400 # map to first day + if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400): + rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40) + elif (self.localtimediff < 0) and (begin < self.localtimediff): + rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01) + while rflags: # then arrange on the week + if rflags & 1: + self.rep_eventlist.append((begin, -1)) + begin += 86400 + rflags >>= 1 + else: + self.nrep_eventlist.extend([(self.newtimer.begin,self.bflag,-1),(self.newtimer.end,self.eflag,-1)]) + +################################################################################## +# now process existing timers + idx = 0 + for timer in self.timerlist: + if (timer != self.newtimer) and (not timer.disabled): + if timer.repeated: + rflags = timer.repeated + rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4) + begin = timer.begin % 86400 # map all to first day + if (self.localtimediff > 0) and ((begin + self.localtimediff) > 86400): + rflags = ((rflags >> 1)& 0x3F)|((rflags << 6)& 0x40) + elif (self.localtimediff < 0) and (begin < self.localtimediff): + rflags = ((rflags << 1)& 0x7E)|((rflags >> 6)& 0x01) + while rflags: + if rflags & 1: + self.rep_eventlist.append((begin, idx)) + begin += 86400 + rflags >>= 1 + else: + self.nrep_eventlist.extend([(timer.begin,self.bflag,idx),(timer.end,self.eflag,idx)]) + idx += 1 + +################################################################################ +# journalize timer repeations + if self.nrep_eventlist: + interval_begin = min(self.nrep_eventlist)[0] + interval_end = max(self.nrep_eventlist)[0] + offset_0 = interval_begin - (interval_begin % 604800) + weeks = (interval_end - offset_0) / 604800 + if ((interval_end - offset_0) % 604800): + weeks += 1 + for cnt in range(weeks): + for event in self.rep_eventlist: + if event[1] == -1: # -1 is the identifier of the changed timer + event_begin = self.newtimer.begin + event_end = self.newtimer.end + else: + event_begin = self.timerlist[event[1]].begin + event_end = self.timerlist[event[1]].end + new_event_begin = event[0] + offset_0 + (cnt * 604800) + # summertime correction + new_lth = localtime(new_event_begin).tm_hour + new_event_begin += 3600 * (localtime(event_begin).tm_hour - new_lth) + new_event_end = new_event_begin + (event_end - event_begin) + if event[1] == -1: + if new_event_begin >= self.newtimer.begin: # is the soap already running? + self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])]) + else: + if new_event_begin >= self.timerlist[event[1]].begin: # is the soap already running? + self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])]) + else: + offset_0 = 345600 # the Epoch begins on Thursday + for cnt in (0, 1): # test two weeks to take care of Sunday-Monday transitions + for event in self.rep_eventlist: + if event[1] == -1: # -1 is the identifier of the changed timer + event_begin = self.newtimer.begin + event_end = self.newtimer.end + else: + event_begin = self.timerlist[event[1]].begin + event_end = self.timerlist[event[1]].end + new_event_begin = event[0] + offset_0 + (cnt * 604800) + new_event_end = new_event_begin + (event_end - event_begin) + self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])]) + +################################################################################ +# order list chronological + self.nrep_eventlist.sort() + +################################################################################## +# detect overlapping timers and overlapping times + fakeRecList = [] + ConflictTimer = None + ConflictTunerType = None + newTimerTunerType = None + cnt = 0 + idx = 0 + overlaplist = [] + for event in self.nrep_eventlist: + cnt += event[1] + if event[2] == -1: # new timer + timer = self.newtimer + else: + timer = self.timerlist[event[2]] + if event[1] == self.bflag: + tunerType = [ ] + fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True) + if fakeRecService: + fakeRecResult = fakeRecService.start(True) + else: + fakeRecResult = -1 + if not fakeRecResult: # tune okay + feinfo = fakeRecService.frontendInfo().getFrontendData() + tunerType.append(feinfo.get("tuner_type")) + else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C) + + def getServiceType(ref): # helper function to get a service type of a service reference + serviceInfo = serviceHandler.info(ref) + serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData) + return serviceInfo and serviceInfo["tuner_type"] or "" + + ref = timer.service_ref.ref + if ref.flags & eServiceReference.isGroup: # service group ? + serviceList = serviceHandler.list(ref) # get all alternative services + if serviceList: + for ref in serviceList.getContent("R"): # iterate over all group service references + type = getServiceType(ref) + if not type in tunerType: # just add single time + tunerType.append(type) + else: + tunerType.append(getServiceType(ref)) + + if event[2] == -1: # new timer + newTimerTunerType = tunerType + overlaplist.append((fakeRecResult, timer, tunerType)) + fakeRecList.append((timer, fakeRecService)) + if fakeRecResult: + if ConflictTimer is None: # just take care of the first conflict + ConflictTimer = timer + ConflictTunerType = tunerType + elif event[1] == self.eflag: + for fakeRec in fakeRecList: + if timer == fakeRec[0] and fakeRec[1]: + NavigationInstance.instance.stopRecordService(fakeRec[1]) + fakeRecList.remove(fakeRec) + fakeRec = None + for entry in overlaplist: + if entry[1] == timer: + overlaplist.remove(entry) + else: + print "Bug: unknown flag!" + self.nrep_eventlist[idx] = (event[0],event[1],event[2],cnt,overlaplist[:]) # insert a duplicate into current overlaplist + idx += 1 + + if ConflictTimer is None: # no conflict found :) + return True + +################################################################################## +# we have detected a conflict, now we must figure out the involved timers + + if self.newtimer is not None: # new timer? + if self.newtimer is not ConflictTimer: # the new timer is not the conflicting timer? + for event in self.nrep_eventlist: + if len(event[4]) > 1: # entry in overlaplist of this event?? + kt = False + nt = False + for entry in event[4]: + if entry[1] is ConflictTimer: + kt = True + if entry[1] is self.newtimer: + nt = True + if nt and kt: + ConflictTimer = self.newtimer + ConflictTunerType = newTimerTunerType + break + + self.simultimer = [ ConflictTimer ] + for event in self.nrep_eventlist: + if len(event[4]) > 1: # entry in overlaplist of this event?? + for entry in event[4]: + if entry[1] is ConflictTimer: + break + else: + continue + for entry in event[4]: + if not entry[1] in self.simultimer: + for x in entry[2]: + if x in ConflictTunerType: + self.simultimer.append(entry[1]) + break + + if len(self.simultimer) < 2: + print "Bug: unknown Conflict!" + + return False # conflict detected!