1 from enigma import eEPGCache, getBestPlayableServiceReference, \
2 eServiceReference, iRecordableService, quitMainloop
4 from Components.config import config
5 from Components.UsageConfig import defaultMoviePath
6 from Components.TimerSanityCheck import TimerSanityCheck
8 from Screens.MessageBox import MessageBox
10 from Tools import Directories, Notifications, ASCIItranslit
11 from Tools.XMLTools import stringToXML
14 import xml.etree.cElementTree
15 import NavigationInstance
16 from ServiceReference import ServiceReference
18 from time import localtime, strftime, ctime, time
19 from bisect import insort
23 # ok, for descriptions etc we have:
24 # service reference (to get the service name)
26 # description (description)
27 # event data (ONLY for time adjustments etc.)
30 # parses an event, and gives out a (begin, end, name, duration, eit)-tuple.
31 # begin and end will be corrected
32 def parseEvent(ev, description = True):
34 name = ev.getEventName()
35 description = ev.getShortDescription()
39 begin = ev.getBeginTime()
40 end = begin + ev.getDuration()
42 begin -= config.recording.margin_before.value * 60
43 end += config.recording.margin_after.value * 60
44 return (begin, end, name, description, eit)
52 def findSafeRecordPath(dirname):
56 from Components import Harddisk
57 dirname = os.path.realpath(dirname)
58 mountpoint = Harddisk.findMountPoint(dirname)
59 if mountpoint in ('/', '/media'):
60 print '[RecordTimer] media is not mounted:', dirname
62 if not os.path.isdir(dirname):
66 print '[RecordTimer] Failed to create dir "%s":' % dirname, ex
71 # please do not translate log messages
72 class RecordTimerEntry(timer.TimerEntry, object):
73 ######### the following static methods and members are only in use when the box is in (soft) standby
74 receiveRecordEvents = False
81 def staticGotRecordEvent(recservice, event):
82 if event == iRecordableService.evEnd:
83 print "RecordTimer.staticGotRecordEvent(iRecordableService.evEnd)"
84 recordings = NavigationInstance.instance.getRecordings()
85 if not recordings: # no more recordings exist
86 rec_time = NavigationInstance.instance.RecordTimer.getNextRecordingTime()
87 if rec_time > 0 and (rec_time - time()) < 360:
88 print "another recording starts in", rec_time - time(), "seconds... do not shutdown yet"
90 print "no starting records in the next 360 seconds... immediate shutdown"
91 RecordTimerEntry.shutdown() # immediate shutdown
92 elif event == iRecordableService.evStart:
93 print "RecordTimer.staticGotRecordEvent(iRecordableService.evStart)"
96 def stopTryQuitMainloop():
97 print "RecordTimer.stopTryQuitMainloop"
98 NavigationInstance.instance.record_event.remove(RecordTimerEntry.staticGotRecordEvent)
99 RecordTimerEntry.receiveRecordEvents = False
102 def TryQuitMainloop(default_yes = True):
103 if not RecordTimerEntry.receiveRecordEvents:
104 print "RecordTimer.TryQuitMainloop"
105 NavigationInstance.instance.record_event.append(RecordTimerEntry.staticGotRecordEvent)
106 RecordTimerEntry.receiveRecordEvents = True
107 # send fake event.. to check if another recordings are running or
108 # other timers start in a few seconds
109 RecordTimerEntry.staticGotRecordEvent(None, iRecordableService.evEnd)
110 # send normal notification for the case the user leave the standby now..
111 Notifications.AddNotification(Screens.Standby.TryQuitMainloop, 1, onSessionOpenCallback=RecordTimerEntry.stopTryQuitMainloop, default_yes = default_yes)
112 #################################################################
114 def __init__(self, serviceref, begin, end, name, description, eit, disabled = False, justplay = False, afterEvent = AFTEREVENT.AUTO, checkOldTimers = False, dirname = None, tags = None, descramble = True, record_ecm = False, filename = None):
115 timer.TimerEntry.__init__(self, int(begin), int(end))
117 if checkOldTimers == True:
118 if self.begin < time() - 1209600:
119 self.begin = int(time())
121 if self.end < self.begin:
122 self.end = self.begin
124 assert isinstance(serviceref, ServiceReference)
126 if serviceref.isRecordable():
127 self.service_ref = serviceref
129 self.service_ref = ServiceReference(None)
131 self.dontSave = False
133 self.description = description
134 self.disabled = disabled
136 self.__record_service = None
137 self.start_prepare = 0
138 self.justplay = justplay
139 self.afterEvent = afterEvent
140 self.dirname = dirname
141 self.dirnameHadToFallback = False
142 self.autoincrease = False
143 self.autoincreasetime = 3600 * 24 # 1 day
144 self.tags = tags or []
146 self.descramble = descramble
147 self.record_ecm = record_ecm
149 self.log_entries = []
152 self.Filename = filename
153 self.pvrConvert = False
155 def log(self, code, msg):
156 self.log_entries.append((int(time()), code, msg))
159 def calculateFilename(self):
161 self.log(0, "Filename calculated as: '%s'" % self.Filename)
164 service_name = self.service_ref.getServiceName()
165 begin_date = strftime("%Y%m%d %H%M", localtime(self.begin))
166 begin_shortdate = strftime("%Y%m%d", localtime(self.begin))
168 print "begin_date: ", begin_date
169 print "service_name: ", service_name
170 print "name:", self.name
171 print "description: ", self.description
173 filename = begin_date + " - " + service_name
175 if config.usage.setup_level.index >= 2: # expert+
176 if config.recording.filename_composition.value == "short":
177 filename = begin_shortdate + " - " + self.name
178 elif config.recording.filename_composition.value == "long":
179 filename += " - " + self.name + " - " + self.description
181 filename += " - " + self.name # standard
183 filename += " - " + self.name
185 if config.recording.ascii_filenames.value:
186 filename = ASCIItranslit.legacyEncode(filename)
189 dirname = findSafeRecordPath(defaultMoviePath())
191 dirname = findSafeRecordPath(self.dirname)
193 dirname = findSafeRecordPath(defaultMoviePath())
194 self.dirnameHadToFallback = True
199 self.Filename = Directories.getRecordingFilename(filename, dirname)
200 self.log(0, "Filename calculated as: '%s'" % self.Filename)
201 #begin_date + " - " + service_name + description)
204 def tryPrepare(self):
208 if not self.calculateFilename():
210 self.start_prepare = time() + self.backoff
213 rec_ref = self.service_ref and self.service_ref.ref
214 if rec_ref and rec_ref.flags & eServiceReference.isGroup:
215 rec_ref = getBestPlayableServiceReference(rec_ref, eServiceReference())
217 self.log(1, "'get best playable service for group... record' failed")
220 self.record_service = rec_ref and NavigationInstance.instance.recordService(rec_ref)
222 if not self.record_service:
223 self.log(1, "'record service' failed")
227 epgcache = eEPGCache.getInstance()
228 queryTime=self.begin+(self.end-self.begin)/2
229 evt = epgcache.lookupEventTime(rec_ref, queryTime)
231 self.description = evt.getShortDescription()
232 event_id = evt.getEventId()
240 prep_res=self.record_service.prepare(self.Filename + ".ts", self.begin, self.end, event_id, self.name.replace("\n", ""), self.description.replace("\n", ""), ' '.join(self.tags), bool(self.descramble), bool(self.record_ecm))
243 self.log(4, "failed to write meta information")
245 self.log(2, "'prepare' failed: error %d" % prep_res)
247 # we must calc nur start time before stopRecordService call because in Screens/Standby.py TryQuitMainloop tries to get
248 # the next start time in evEnd event handler...
250 self.start_prepare = time() + self.backoff
252 NavigationInstance.instance.stopRecordService(self.record_service)
253 self.record_service = None
257 def do_backoff(self):
258 if self.backoff == 0:
262 if self.backoff > 100:
264 self.log(10, "backoff: retry in %d seconds" % self.backoff)
267 next_state = self.state + 1
268 self.log(5, "activating state %d" % next_state)
270 if next_state == self.StatePrepared:
271 if self.tryPrepare():
272 self.log(6, "prepare ok, waiting for begin")
273 # create file to "reserve" the filename
274 # because another recording at the same time on another service can try to record the same event
275 # i.e. cable / sat.. then the second recording needs an own extension... when we create the file
276 # here than calculateFilename is happy
277 if not self.justplay:
278 open(self.Filename + ".ts", "w").close()
279 # fine. it worked, resources are allocated.
280 self.next_activation = self.begin
284 self.log(7, "prepare failed")
285 if self.first_try_prepare:
286 self.first_try_prepare = False
287 cur_ref = NavigationInstance.instance.getCurrentlyPlayingServiceReference()
288 if cur_ref and not cur_ref.getPath():
289 if not config.recording.asktozap.value:
290 self.log(8, "asking user to zap away")
291 Notifications.AddNotificationWithCallback(self.failureCB, MessageBox, _("A timer failed to record!\nDisable TV and try again?\n"), timeout=20)
292 else: # zap without asking
293 self.log(9, "zap without asking")
294 Notifications.AddNotification(MessageBox, _("In order to record a timer, the TV was switched to the recording service!\n"), type=MessageBox.TYPE_INFO, timeout=20)
297 self.log(8, "currently running service is not a live service.. so stop it makes no sense")
299 self.log(8, "currently no service running... so we dont need to stop it")
301 elif next_state == self.StateRunning:
302 # if this timer has been cancelled, just go to "end" state.
307 if Screens.Standby.inStandby:
308 self.log(11, "wakeup and zap")
309 #set service to zap after standby
310 Screens.Standby.inStandby.prev_running_service = self.service_ref.ref
312 Screens.Standby.inStandby.Power()
314 self.log(11, "zapping")
315 NavigationInstance.instance.playService(self.service_ref.ref)
318 self.log(11, "start recording")
319 record_res = self.record_service.start()
322 self.log(13, "start record returned %d" % record_res)
325 self.begin = time() + self.backoff
329 elif next_state == self.StateEnded:
331 if self.setAutoincreaseEnd():
332 self.log(12, "autoincrase recording %d minute(s)" % int((self.end - old_end)/60))
335 self.log(12, "stop recording")
336 if not self.justplay:
337 NavigationInstance.instance.stopRecordService(self.record_service)
338 self.record_service = None
339 if self.afterEvent == AFTEREVENT.STANDBY:
340 if not Screens.Standby.inStandby: # not already in standby
341 Notifications.AddNotificationWithCallback(self.sendStandbyNotification, MessageBox, _("A finished record timer wants to set your\nSTB to standby. Do that now?"), timeout = 20)
342 elif self.afterEvent == AFTEREVENT.DEEPSTANDBY:
343 if not Screens.Standby.inTryQuitMainloop: # not a shutdown messagebox is open
344 if Screens.Standby.inStandby: # in standby
345 RecordTimerEntry.TryQuitMainloop() # start shutdown handling without screen
347 Notifications.AddNotificationWithCallback(self.sendTryQuitMainloopNotification, MessageBox, _("A finished record timer wants to shut down\nyour STB. Shutdown now?"), timeout = 20)
350 def setAutoincreaseEnd(self, entry = None):
351 if not self.autoincrease:
354 new_end = int(time()) + self.autoincreasetime
356 new_end = entry.begin -30
358 dummyentry = RecordTimerEntry(self.service_ref, self.begin, new_end, self.name, self.description, self.eit, disabled=True, justplay = self.justplay, afterEvent = self.afterEvent, dirname = self.dirname, tags = self.tags)
359 dummyentry.disabled = self.disabled
360 timersanitycheck = TimerSanityCheck(NavigationInstance.instance.RecordTimer.timer_list, dummyentry)
361 if not timersanitycheck.check():
362 simulTimerList = timersanitycheck.getSimulTimerList()
363 if simulTimerList is not None and len(simulTimerList) > 1:
364 new_end = simulTimerList[1].begin
365 new_end -= 30 # 30 Sekunden Prepare-Zeit lassen
366 if new_end <= time():
371 def sendStandbyNotification(self, answer):
373 Notifications.AddNotification(Screens.Standby.Standby)
375 def sendTryQuitMainloopNotification(self, answer):
377 Notifications.AddNotification(Screens.Standby.TryQuitMainloop, 1)
379 def getNextActivation(self):
380 if self.state == self.StateEnded:
383 next_state = self.state + 1
385 return {self.StatePrepared: self.start_prepare,
386 self.StateRunning: self.begin,
387 self.StateEnded: self.end }[next_state]
389 def failureCB(self, answer):
391 self.log(13, "ok, zapped away")
392 #NavigationInstance.instance.stopUserServices()
393 NavigationInstance.instance.playService(self.service_ref.ref)
395 self.log(14, "user didn't want to zap away, record will probably fail")
397 def timeChanged(self):
398 old_prepare = self.start_prepare
399 self.start_prepare = self.begin - self.prepare_time
402 if int(old_prepare) != int(self.start_prepare):
403 self.log(15, "record time changed, start prepare is now: %s" % ctime(self.start_prepare))
405 def gotRecordEvent(self, record, event):
406 # TODO: this is not working (never true), please fix. (comparing two swig wrapped ePtrs)
407 if self.__record_service.__deref__() != record.__deref__():
409 self.log(16, "record event %d" % event)
410 if event == iRecordableService.evRecordWriteError:
411 print "WRITE ERROR on recording, disk full?"
412 # show notification. the 'id' will make sure that it will be
413 # displayed only once, even if more timers are failing at the
414 # same time. (which is very likely in case of disk fullness)
415 Notifications.AddPopup(text = _("Write error while recording. Disk full?\n"), type = MessageBox.TYPE_ERROR, timeout = 0, id = "DiskFullMessage")
416 # ok, the recording has been stopped. we need to properly note
417 # that in our state, with also keeping the possibility to re-try.
418 # TODO: this has to be done.
419 elif event == iRecordableService.evStart:
423 text = _("A record has been started:\n%s") % self.name
424 if self.dirnameHadToFallback:
425 text = '\n'.join((text, _("Please note that the previously selected media could not be accessed and therefore the default directory is being used instead.")))
427 if config.usage.show_message_when_recording_starts.value:
428 Notifications.AddPopup(text = text, type = MessageBox.TYPE_INFO, timeout = 3)
430 # we have record_service as property to automatically subscribe to record service events
431 def setRecordService(self, service):
432 if self.__record_service is not None:
433 print "[remove callback]"
434 NavigationInstance.instance.record_event.remove(self.gotRecordEvent)
436 self.__record_service = service
438 if self.__record_service is not None:
439 print "[add callback]"
440 NavigationInstance.instance.record_event.append(self.gotRecordEvent)
442 record_service = property(lambda self: self.__record_service, setRecordService)
444 def isUsbRecordingPath(self):
448 dirname = findSafeRecordPath(self.dirname)
451 dirname = findSafeRecordPath(defaultMoviePath())
453 from Components import Harddisk
454 return Harddisk.isUsbStorage(dirname)
456 def createTimer(xml):
457 begin = int(xml.get("begin"))
458 end = int(xml.get("end"))
459 serviceref = ServiceReference(xml.get("serviceref").encode("utf-8"))
460 description = xml.get("description").encode("utf-8")
461 repeated = xml.get("repeated").encode("utf-8")
462 disabled = long(xml.get("disabled") or "0")
463 justplay = long(xml.get("justplay") or "0")
464 afterevent = str(xml.get("afterevent") or "nothing")
466 "nothing": AFTEREVENT.NONE,
467 "standby": AFTEREVENT.STANDBY,
468 "deepstandby": AFTEREVENT.DEEPSTANDBY,
469 "auto": AFTEREVENT.AUTO
472 if eit and eit != "None":
476 location = xml.get("location")
477 if location and location != "None":
478 location = location.encode("utf-8")
481 tags = xml.get("tags")
482 if tags and tags != "None":
483 tags = tags.encode("utf-8").split(' ')
487 name = xml.get("name").encode("utf-8")
488 #filename = xml.get("filename").encode("utf-8")
489 entry = RecordTimerEntry(serviceref, begin, end, name, description, eit, disabled, justplay, afterevent, dirname = location, tags = tags)
490 entry.repeated = int(repeated)
492 for l in xml.findall("log"):
493 time = int(l.get("time"))
494 code = int(l.get("code"))
495 msg = l.text.strip().encode("utf-8")
496 entry.log_entries.append((time, code, msg))
500 class RecordTimer(timer.Timer):
502 timer.Timer.__init__(self)
504 self.Filename = Directories.resolveFilename(Directories.SCOPE_CONFIG, "timers.xml")
509 print "unable to load timers from file!"
511 def doActivate(self, w):
512 if w.state == RecordTimerEntry.StateWaiting:
513 from Components.SystemInfo import SystemInfo
514 if SystemInfo.get("DisableUsbRecord", True) and w.isUsbRecordingPath():
515 service_name = w.service_ref.getServiceName()
516 self.timer_list.remove(w)
517 if w.dontSave is False:
520 self.addTimerEntry(w)
521 Notifications.AddNotification(MessageBox, _("Can not recording on a USB storage.\nService name : %s"% service_name), MessageBox.TYPE_ERROR)
524 # when activating a timer which has already passed,
525 # simply abort the timer. don't run trough all the stages.
527 w.state = RecordTimerEntry.StateEnded
529 # when active returns true, this means "accepted".
530 # otherwise, the current state is kept.
531 # the timer entry itself will fix up the delay then.
535 self.timer_list.remove(w)
537 # did this timer reached the last state?
538 if w.state < RecordTimerEntry.StateEnded:
539 # no, sort it into active list
540 insort(self.timer_list, w)
542 # yes. Process repeated, and re-add.
545 w.state = RecordTimerEntry.StateWaiting
546 self.addTimerEntry(w)
548 insort(self.processed_timers, w)
552 def isRecording(self):
554 for timer in self.timer_list:
555 if timer.isRunning() and not timer.justplay:
562 doc = xml.etree.cElementTree.parse(self.Filename)
564 from Tools.Notifications import AddPopup
565 from Screens.MessageBox import MessageBox
567 AddPopup(_("The timer file (timers.xml) is corrupt and could not be loaded."), type = MessageBox.TYPE_ERROR, timeout = 0, id = "TimerLoadFailed")
569 print "timers.xml failed to load!"
572 os.rename(self.Filename, self.Filename + "_old")
573 except (IOError, OSError):
574 print "renaming broken timer failed"
577 print "timers.xml not found!"
582 # put out a message when at least one timer overlaps
584 for timer in root.findall("timer"):
585 newTimer = createTimer(timer)
586 if (self.record(newTimer, True, dosave=False) is not None) and (checkit == True):
587 from Tools.Notifications import AddPopup
588 from Screens.MessageBox import MessageBox
589 AddPopup(_("Timer overlap in timers.xml detected!\nPlease recheck it!"), type = MessageBox.TYPE_ERROR, timeout = 0, id = "TimerLoadFailed")
590 checkit = False # at moment it is enough when the message is displayed one time
593 #root_element = xml.etree.cElementTree.Element('timers')
594 #root_element.text = "\n"
596 #for timer in self.timer_list + self.processed_timers:
597 # some timers (instant records) don't want to be saved.
601 #t = xml.etree.cElementTree.SubElement(root_element, 'timers')
602 #t.set("begin", str(int(timer.begin)))
603 #t.set("end", str(int(timer.end)))
604 #t.set("serviceref", str(timer.service_ref))
605 #t.set("repeated", str(timer.repeated))
606 #t.set("name", timer.name)
607 #t.set("description", timer.description)
608 #t.set("afterevent", str({
609 # AFTEREVENT.NONE: "nothing",
610 # AFTEREVENT.STANDBY: "standby",
611 # AFTEREVENT.DEEPSTANDBY: "deepstandby",
612 # AFTEREVENT.AUTO: "auto"}))
613 #if timer.eit is not None:
614 # t.set("eit", str(timer.eit))
615 #if timer.dirname is not None:
616 # t.set("location", str(timer.dirname))
617 #t.set("disabled", str(int(timer.disabled)))
618 #t.set("justplay", str(int(timer.justplay)))
622 #for time, code, msg in timer.log_entries:
623 #l = xml.etree.cElementTree.SubElement(t, 'log')
624 #l.set("time", str(time))
625 #l.set("code", str(code))
629 #doc = xml.etree.cElementTree.ElementTree(root_element)
630 #doc.write(self.Filename)
634 list.append('<?xml version="1.0" ?>\n')
635 list.append('<timers>\n')
637 for timer in self.timer_list + self.processed_timers:
641 list.append('<timer')
642 list.append(' begin="' + str(int(timer.begin)) + '"')
643 list.append(' end="' + str(int(timer.end)) + '"')
644 list.append(' serviceref="' + stringToXML(str(timer.service_ref)) + '"')
645 list.append(' repeated="' + str(int(timer.repeated)) + '"')
646 list.append(' name="' + str(stringToXML(timer.name)) + '"')
647 list.append(' description="' + str(stringToXML(timer.description)) + '"')
648 list.append(' afterevent="' + str(stringToXML({
649 AFTEREVENT.NONE: "nothing",
650 AFTEREVENT.STANDBY: "standby",
651 AFTEREVENT.DEEPSTANDBY: "deepstandby",
652 AFTEREVENT.AUTO: "auto"
653 }[timer.afterEvent])) + '"')
654 if timer.eit is not None:
655 list.append(' eit="' + str(timer.eit) + '"')
656 if timer.dirname is not None:
657 list.append(' location="' + str(stringToXML(timer.dirname)) + '"')
658 if timer.tags is not None:
659 list.append(' tags="' + str(stringToXML(' '.join(timer.tags))) + '"')
660 list.append(' disabled="' + str(int(timer.disabled)) + '"')
661 list.append(' justplay="' + str(int(timer.justplay)) + '"')
664 if config.recording.debug.value:
665 for time, code, msg in timer.log_entries:
667 list.append(' code="' + str(code) + '"')
668 list.append(' time="' + str(time) + '"')
670 list.append(str(stringToXML(msg)))
671 list.append('</log>\n')
673 list.append('</timer>\n')
675 list.append('</timers>\n')
677 file = open(self.Filename, "w")
682 def getNextZapTime(self):
684 for timer in self.timer_list:
685 if not timer.justplay or timer.begin < now:
690 def getNextRecordingTime(self):
692 for timer in self.timer_list:
693 next_act = timer.getNextActivation()
694 if timer.justplay or next_act < now:
699 def isNextRecordAfterEventActionAuto(self):
702 for timer in self.timer_list:
703 if timer.justplay or timer.begin < now:
705 if t is None or t.begin == timer.begin:
707 if t.afterEvent == AFTEREVENT.AUTO:
711 def record(self, entry, ignoreTSC=False, dosave=True): #wird von loadTimer mit dosave=False aufgerufen
712 timersanitycheck = TimerSanityCheck(self.timer_list,entry)
713 if not timersanitycheck.check():
714 if ignoreTSC != True:
715 print "timer conflict detected!"
716 print timersanitycheck.getSimulTimerList()
717 return timersanitycheck.getSimulTimerList()
719 print "ignore timer conflict"
720 elif timersanitycheck.doubleCheck():
721 print "ignore double timer"
724 print "[Timer] Record " + str(entry)
726 self.addTimerEntry(entry)
731 def isInTimer(self, eventid, begin, duration, service):
735 chktimecmp_end = None
736 end = begin + duration
737 refstr = str(service)
738 for x in self.timer_list:
739 check = x.service_ref.ref.toString() == refstr
741 sref = x.service_ref.ref
742 parent_sid = sref.getUnsignedData(5)
743 parent_tsid = sref.getUnsignedData(6)
744 if parent_sid and parent_tsid: # check for subservice
745 sid = sref.getUnsignedData(1)
746 tsid = sref.getUnsignedData(2)
747 sref.setUnsignedData(1, parent_sid)
748 sref.setUnsignedData(2, parent_tsid)
749 sref.setUnsignedData(5, 0)
750 sref.setUnsignedData(6, 0)
751 check = sref.toCompareString() == refstr
755 event = eEPGCache.getInstance().lookupEventId(sref, eventid)
756 num = event and event.getNumOfLinkageServices() or 0
757 sref.setUnsignedData(1, sid)
758 sref.setUnsignedData(2, tsid)
759 sref.setUnsignedData(5, parent_sid)
760 sref.setUnsignedData(6, parent_tsid)
761 for cnt in range(num):
762 subservice = event.getLinkageService(sref, cnt)
763 if sref.toCompareString() == subservice.toCompareString():
769 chktime = localtime(begin)
770 chktimecmp = chktime.tm_wday * 1440 + chktime.tm_hour * 60 + chktime.tm_min
771 chktimecmp_end = chktimecmp + (duration / 60)
772 time = localtime(x.begin)
773 for y in (0, 1, 2, 3, 4, 5, 6):
774 if x.repeated & (1 << y) and (x.begin <= begin or begin <= x.begin <= end):
775 timecmp = y * 1440 + time.tm_hour * 60 + time.tm_min
776 if timecmp <= chktimecmp < (timecmp + ((x.end - x.begin) / 60)):
777 time_match = ((timecmp + ((x.end - x.begin) / 60)) - chktimecmp) * 60
778 elif chktimecmp <= timecmp < chktimecmp_end:
779 time_match = (chktimecmp_end - timecmp) * 60
780 else: #if x.eit is None:
781 if begin <= x.begin <= end:
783 if time_match < diff:
785 elif x.begin <= begin <= x.end:
787 if time_match < diff:
793 def removeEntry(self, entry):
794 print "[Timer] Remove " + str(entry)
797 entry.repeated = False
800 # this sets the end time to current time, so timer will be stopped.
801 entry.autoincrease = False
804 if entry.state != entry.StateEnded:
805 self.timeChanged(entry)
807 print "state: ", entry.state
808 print "in processed: ", entry in self.processed_timers
809 print "in running: ", entry in self.timer_list
810 # autoincrease instanttimer if possible
811 if not entry.dontSave:
812 for x in self.timer_list:
813 if x.setAutoincreaseEnd():
815 # now the timer should be in the processed_timers list. remove it from there.
816 self.processed_timers.remove(entry)