コード例 #1
0
	def checkDuplicates(self, timer, name1, name2, shortdesc1, shortdesc2, extdesc1, extdesc2, force=False):
		if name1 and name2:
			sequenceMatcher = SequenceMatcher(" ".__eq__, name1, name2)
		else:
			return False

		ratio = sequenceMatcher.ratio()
		ratio_value = force and 0.8 or timer.ratioThresholdDuplicate
		doDebug("[AutoTimer] names ratio %f - %s - %d - %s - %d" % (ratio, name1, len(name1), name2, len(name2)))
		if name1 in name2 or (0.8 < ratio): # this is probably a match
			foundShort = True
			if (force or timer.searchForDuplicateDescription > 0) and shortdesc1 and shortdesc2:
				sequenceMatcher.set_seqs(shortdesc1, shortdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("[AutoTimer] shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
				foundShort = shortdesc1 in shortdesc2 or ((ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio))
				if foundShort:
					doLog("[AutoTimer] shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
			elif not force and timer.descShortExtEmpty and not shortdesc1 and not shortdesc2 and name1 != name2:
				foundShort = False

			foundExt = True
			# NOTE: only check extended if short description already is a match because otherwise
			# it won't evaluate to True anyway
			if foundShort and (force or timer.searchForDuplicateDescription > 1) and extdesc1 and extdesc2:
				sequenceMatcher.set_seqs(extdesc1, extdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("[AutoTimer] extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
				foundExt = (ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio)
				if foundExt:
					doLog("[AutoTimer] extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
			elif not force and timer.descShortExtEmpty and not extdesc1 and not extdesc2 and name1 != name2:
				foundExt = False
			return foundShort and foundExt
		return False
コード例 #2
0
ファイル: AutoTimer.py プロジェクト: OpenDMM/enigma2-plugins
	def addToFilterList(self, session, services, *args, **kwargs):
		
		if services:
			serviceHandler = eServiceCenter.getInstance()
			add_counter=0
			
			try:
				for service in services:
					
					info = serviceHandler.info(service)
					name = info and info.getName(service) or ""
					
					if info:
						begin = info.getInfo(service, iServiceInformation.sTimeCreate)
					else:
						doLog("No recordinfo available")
						continue
					
					ret = self.addToFilterfile(name, begin)
					if ret:
						add_counter +=1
					
				session.open( MessageBox, _("finished add to filterList with %s event(s):\n\n %s event(s) added \n %s event(s) skipped") % (len(services), add_counter,len(services)-add_counter), type = MessageBox.TYPE_INFO, timeout = config.plugins.autotimer.popup_timeout.value )
					
			except Exception as e:
				doLog("Error in addToFilterList", e)
				print ("======== Error in addToFilterList ", e)
コード例 #3
0
ファイル: AutoTimer.py プロジェクト: OpenDMM/enigma2-plugins
	def populateTimerdict(self, epgcache, recordHandler, timerdict, simulateOnly=False):
		remove = []
		for timer in chain(recordHandler.timer_list, recordHandler.processed_timers):
			if timer and timer.service_ref:
				if timer.eit is not None:
					event = epgcache.lookupEventId(timer.service_ref.ref, timer.eit)
					if event:
						timer.extdesc = event.getExtendedDescription()
					else:
						remove.append(timer)
				else:
					remove.append(timer)
					continue

				if not hasattr(timer, 'extdesc'):
					timer.extdesc = ''

				timerdict[str(timer.service_ref)].append(timer)

		if config.plugins.autotimer.check_eit_and_remove.value:
			for timer in remove:
				if hasattr(timer, "isAutoTimer") or (config.plugins.autotimer.add_autotimer_to_tags.value and TAG in timer.tags):
					try:
						# Because of the duplicate check, we only want to remove future timer
						if timer in recordHandler.timer_list:
							if not timer.isRunning():
								global NavigationInstance
								doLog("Remove timer because of eit check " + timer.name)
								self.addToSearchLogfile(timer,"-", simulateOnly)
								NavigationInstance.instance.RecordTimer.removeEntry(timer)
								
					except:
						pass
		del remove
コード例 #4
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def populateTimerdict(self, epgcache, recordHandler, timerdict):
		remove = []
		for timer in chain(recordHandler.timer_list, recordHandler.processed_timers):
			if timer and timer.service_ref:
				if timer.eit is not None:
					event = epgcache.lookupEventId(timer.service_ref.ref, timer.eit)
					if event:
						timer.extdesc = event.getExtendedDescription()
					else:
						remove.append(timer)
				else:
					remove.append(timer)
					continue

				if not hasattr(timer, 'extdesc'):
					timer.extdesc = ''

				timerdict[str(timer.service_ref)].append(timer)

		if config.plugins.autotimer.check_eit_and_remove.value:
			for timer in remove:
				if "autotimer" in timer.flags:
					try:
						# Because of the duplicate check, we only want to remove future timer
						if timer in recordHandler.timer_list:
							if not timer.isRunning():
								recordHandler.removeEntry(timer)
								doLog("[AutoTimer] Remove timer because of eit check %s." % (timer.name))
					except:
						pass
		del remove
コード例 #5
0
def blockingCallFromMainThread(f, *a, **kw):
	"""
	  Modified version of twisted.internet.threads.blockingCallFromThread
	  which waits 30s for results and otherwise assumes the system to be shut down.
	  This is an ugly workaround for a twisted-internal deadlock.
	  Please keep the look intact in case someone comes up with a way
	  to reliably detect from the outside if twisted is currently shutting
	  down.
	"""
	queue = Queue.Queue()

	def _callFromThread():
		result = defer.maybeDeferred(f, *a, **kw)
		result.addBoth(queue.put)
	reactor.callFromThread(_callFromThread)

	result = None
	while True:
		try:
			result = queue.get(True, config.plugins.autotimer.timeout.value * 60)
		except Queue.Empty as qe:
			if True: #not reactor.running: # reactor.running is only False AFTER shutdown, we are during.
				doLog("[AutoTimer] Reactor no longer active, aborting.")
		else:
			break

	if isinstance(result, failure.Failure):
		print("[AutoTimer]", result.getTraceback())
		doLog(result.getTraceback())
		result.raiseException()
	return result
コード例 #6
0
ファイル: AutoTimer.py プロジェクト: xmasmc/enigma2-plugins
    def addToFilterfile(self, name, begin, simulateOnlyValue=False):

        #== add to filterList
        path_filter_txt = "/etc/enigma2/autotimer_filter.txt"
        if os_path.exists(path_filter_txt):
            search_txt = '"' + name + '"'
            if search_txt in open(path_filter_txt).read():
                print(
                    "Skipping an event because found event in autotimer_filter"
                )
                doLog(
                    "Skipping an event because found event in autotimer_filter"
                )
                return False
        if simulateOnlyValue:
            return True
        #write eventname totextfile
        filter_txt = str(strftime('%d.%m.%Y, %H:%M',
                                  localtime(begin))) + ' - "' + name + '"\n'
        file_filter_txt = open(path_filter_txt, "a")
        file_filter_txt.write(filter_txt)
        file_filter_txt.close()
        doLog("added a new event to autotimer_filter")

        return True
コード例 #7
0
ファイル: AutoTimer.py プロジェクト: Dog6574/enigma2-plugins
	def parseEPG(self, simulateOnly=False, uniqueId=None, callback=None):

		from plugin import AUTOTIMER_VERSION
		doLog("AutoTimer Version: " + AUTOTIMER_VERSION)

		if NavigationInstance.instance is None:
			doLog("Navigation is not available, can't parse EPG")
			return (0, 0, 0, [], [], [])

		new = 0
		modified = 0
		timers = []
		conflicting = []
		similars = []
		skipped = []

		if currentThread().getName() == 'MainThread':
			doBlockingCallFromMainThread = lambda f, *a, **kw: f(*a, **kw)
		else:
			doBlockingCallFromMainThread = blockingCallFromMainThread

		# NOTE: the config option specifies "the next X days" which means today (== 1) + X
		delta = timedelta(days = config.plugins.autotimer.maxdaysinfuture.value + 1)
		evtLimit = mktime((date.today() + delta).timetuple())
		checkEvtLimit = delta.days > 1
		del delta

		# Read AutoTimer configuration
		self.readXml()

		# Get E2 instances
		epgcache = eEPGCache.getInstance()
		serviceHandler = eServiceCenter.getInstance()
		recordHandler = NavigationInstance.instance.RecordTimer

		# Save Timer in a dict to speed things up a little
		# We include processed timers as we might search for duplicate descriptions
		# NOTE: It is also possible to use RecordTimer isInTimer(), but we won't get the timer itself on a match
		timerdict = defaultdict(list)
		doBlockingCallFromMainThread(self.populateTimerdict, epgcache, recordHandler, timerdict)

		# Create dict of all movies in all folders used by an autotimer to compare with recordings
		# The moviedict will be filled only if one AutoTimer is configured to avoid duplicate description for any recordings
		moviedict = defaultdict(list)

		# Iterate Timer
		for timer in self.getEnabledTimerList():
			if uniqueId == None or timer.id == uniqueId:
				tup = doBlockingCallFromMainThread(self.parseTimer, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=simulateOnly)
				if callback:
					callback(timers, conflicting, similars, skipped)
					del timers[:]
					del conflicting[:]
					del similars[:]
					del skipped[:]
				else:
					new += tup[0]
					modified += tup[1]

		return (len(timers), new, modified, timers, conflicting, similars)
コード例 #8
0
ファイル: AutoTimer.py プロジェクト: xmasmc/enigma2-plugins
    def readXml(self, **kwargs):
        if "xml_string" in kwargs:
            # reset time
            self.configMtime = -1

            # Parse Config
            configuration = cet_fromstring(kwargs["xml_string"])
        else:
            # Abort if no config found
            if not os_path.exists(XML_CONFIG):
                doLog("No configuration file present")
                return

            # Parse if mtime differs from whats saved
            mtime = os_path.getmtime(XML_CONFIG)
            if mtime == self.configMtime:
                doLog("No changes in configuration, won't parse")
                return

            # Save current mtime
            self.configMtime = mtime

            # Parse Config
            configuration = cet_parse(XML_CONFIG).getroot()

        # Empty out timers and reset Ids
        del self.timers[:]
        self.defaultTimer.clear(-1, True)

        parseConfig(configuration, self.timers, configuration.get("version"),
                    0, self.defaultTimer)
        self.uniqueTimerId = len(self.timers)
コード例 #9
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def checkDuplicates(self, timer, name1, name2, shortdesc1, shortdesc2, extdesc1, extdesc2, force=False):
		if name1 and name2:
			sequenceMatcher = SequenceMatcher(" ".__eq__, name1, name2)
		else:
			return False

		ratio = sequenceMatcher.ratio()
		ratio_value = force and 0.8 or timer.ratioThresholdDuplicate
		doDebug("[AutoTimer] names ratio %f - %s - %d - %s - %d" % (ratio, name1, len(name1), name2, len(name2)))
		if name1 in name2 or (0.8 < ratio): # this is probably a match
			foundShort = True
			if (force or timer.searchForDuplicateDescription > 0) and shortdesc1 and shortdesc2:
				sequenceMatcher.set_seqs(shortdesc1, shortdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("[AutoTimer] shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
				foundShort = shortdesc1 in shortdesc2 or ((ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio))
				if foundShort:
					doLog("[AutoTimer] shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
			elif not force and timer.descShortExtEmpty and not shortdesc1 and not shortdesc2 and name1 != name2:
				foundShort = False

			foundExt = True
			# NOTE: only check extended if short description already is a match because otherwise
			# it won't evaluate to True anyway
			if foundShort and (force or timer.searchForDuplicateDescription > 1) and extdesc1 and extdesc2:
				sequenceMatcher.set_seqs(extdesc1, extdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("[AutoTimer] extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
				foundExt = (ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio)
				if foundExt:
					doLog("[AutoTimer] extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
			elif not force and timer.descShortExtEmpty and not extdesc1 and not extdesc2 and name1 != name2:
				foundExt = False
			return foundShort and foundExt
		return False
コード例 #10
0
	def checkDuplicates(self, timer, name1, name2, shortdesc1, shortdesc2, extdesc1, extdesc2, force=False):
		if name1 and name2:
			sequenceMatcher = SequenceMatcher(" ".__eq__, name1, name2)
		else:
			return False

		title_ratio = int(config.plugins.autotimer.title_match_ratio.value) / float(100)
		shortdesc_ratio = int(config.plugins.autotimer.shortdesc_match_ratio.value) / float(100)
		extdesc_ratio = int(config.plugins.autotimer.extdesc_match_ratio.value) / float(100)

		ratio = sequenceMatcher.ratio()
		doDebug("names ratio %f - %s - %d - %s - %d" % (ratio, name1, len(name1), name2, len(name2)))
		if name1 in name2 or (title_ratio < ratio): # this is probably a match
			foundShort = True
			if (force or timer.searchForDuplicateDescription > 0) and shortdesc1 and shortdesc2:
				sequenceMatcher.set_seqs(shortdesc1, shortdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
				foundShort = shortdesc1 in shortdesc2 or (shortdesc_ratio < ratio)
				if foundShort:
					doLog("shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))

			foundExt = True
			# NOTE: only check extended if short description already is a match because otherwise
			# it won't evaluate to True anyway
			if foundShort and (force or timer.searchForDuplicateDescription > 1) and extdesc1 and extdesc2:
				sequenceMatcher.set_seqs(extdesc1, extdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
				foundExt = (extdesc_ratio < ratio)
				if foundExt:
					doLog("extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
			return foundShort and foundExt
コード例 #11
0
	def populateTimerdict(self, epgcache, recordHandler, timerdict, simulateOnly=False):
		remove = []
		for timer in chain(recordHandler.timer_list, recordHandler.processed_timers):
			if timer and timer.service_ref:
				if timer.eit is not None:
					event = epgcache.lookupEventId(timer.service_ref.ref, timer.eit)
					if event:
						timer.extdesc = event.getExtendedDescription()
					else:
						remove.append(timer)
				else:
					remove.append(timer)
					continue

				if not hasattr(timer, 'extdesc'):
					timer.extdesc = ''

				timerdict[str(timer.service_ref)].append(timer)

		if config.plugins.autotimer.check_eit_and_remove.value:
			for timer in remove:
				if hasattr(timer, "isAutoTimer") or (config.plugins.autotimer.add_autotimer_to_tags.value and TAG in timer.tags):
					try:
						# Because of the duplicate check, we only want to remove future timer
						if timer in recordHandler.timer_list:
							if not timer.isRunning():
								global NavigationInstance
								doLog("Remove timer because of eit check " + timer.name)
								self.addToSearchLogfile(timer,"-", simulateOnly)
								NavigationInstance.instance.RecordTimer.removeEntry(timer)
								
					except:
						pass
		del remove
コード例 #12
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
def blockingCallFromMainThread(f, *a, **kw):
	"""
	  Modified version of twisted.internet.threads.blockingCallFromThread
	  which waits 30s for results and otherwise assumes the system to be shut down.
	  This is an ugly workaround for a twisted-internal deadlock.
	  Please keep the look intact in case someone comes up with a way
	  to reliably detect from the outside if twisted is currently shutting
	  down.
	"""
	queue = Queue.Queue()
	def _callFromThread():
		result = defer.maybeDeferred(f, *a, **kw)
		result.addBoth(queue.put)
	reactor.callFromThread(_callFromThread)

	result = None
	while True:
		try:
			result = queue.get(True, config.plugins.autotimer.timeout.value*60)
		except Queue.Empty as qe:
			if True: #not reactor.running: # reactor.running is only False AFTER shutdown, we are during.
				doLog("[AutoTimer] Reactor no longer active, aborting.")
		else:
			break

	if isinstance(result, failure.Failure):
		result.raiseException()
	return result
コード例 #13
0
ファイル: AutoTimer.py プロジェクト: xmasmc/enigma2-plugins
    def addToFilterList(self, session, services, *args, **kwargs):

        if services:
            serviceHandler = eServiceCenter.getInstance()
            add_counter = 0

            try:
                for service in services:

                    info = serviceHandler.info(service)
                    name = info and info.getName(service) or ""

                    if info:
                        begin = info.getInfo(service,
                                             iServiceInformation.sTimeCreate)
                    else:
                        doLog("No recordinfo available")
                        continue

                    ret = self.addToFilterfile(name, begin)
                    if ret:
                        add_counter += 1

                session.open(
                    MessageBox,
                    _("finished add to filterList with %s event(s):\n\n %s event(s) added \n %s event(s) skipped"
                      ) %
                    (len(services), add_counter, len(services) - add_counter),
                    type=MessageBox.TYPE_INFO,
                    timeout=config.plugins.autotimer.popup_timeout.value)

            except Exception as e:
                doLog("Error in addToFilterList", e)
                print("======== Error in addToFilterList ", e)
コード例 #14
0
ファイル: AutoTimer.py プロジェクト: xmasmc/enigma2-plugins
 def addDirectoryToMovieDict(self, moviedict, dest, serviceHandler):
     movielist = serviceHandler.list(
         eServiceReference("2:0:1:0:0:0:0:0:0:0:" + dest))
     if movielist is None:
         doLog("listing of movies in " + dest + " failed")
     else:
         append = moviedict[dest].append
         while 1:
             movieref = movielist.getNext()
             if not movieref.valid():
                 break
             if movieref.flags & eServiceReference.mustDescent:
                 continue
             info = serviceHandler.info(movieref)
             if info is None:
                 continue
             event = info.getEvent(movieref)
             if event is None:
                 continue
             append({
                 "name":
                 info.getName(movieref),
                 "shortdesc":
                 info.getInfoString(movieref,
                                    iServiceInformation.sDescription),
                 "extdesc":
                 event.getExtendedDescription() or
                 ''  # XXX: does event.getExtendedDescription() actually return None on no description or an empty string?
             })
コード例 #15
0
def parseConfig(configuration, list, version = None, uniqueTimerId = 0, defaultTimer = None):
	try:
		intVersion = int(version)
	except ValueError:
		doLog('[AutoTimer] Config version "%s" is not a valid integer, assuming old version' % version)
		intVersion = -1

	if intVersion < 5:
		parseConfigOld(configuration, list, uniqueTimerId)
		return

	if defaultTimer is not None:
		# Read in defaults for a new timer
		for defaults in configuration.findall("defaults"):
			parseEntry(defaults, defaultTimer, True)

	for timer in configuration.findall("timer"):
		uniqueTimerId += 1
		baseTimer = preferredAutoTimerComponent(
			uniqueTimerId,
			'',
			'',
			True
		)

		if parseEntry(timer, baseTimer):
			list.append(baseTimer)
コード例 #16
0
	def readXml(self):
		# Abort if no config found
		if not os_path.exists(XML_CONFIG):
			doLog("No configuration file present")
			return

		# Parse if mtime differs from whats saved
		mtime = os_path.getmtime(XML_CONFIG)
		if mtime == self.configMtime:
			doLog("No changes in configuration, won't parse")
			return

		# Save current mtime
		self.configMtime = mtime

		# Parse Config
		configuration = cet_parse(XML_CONFIG).getroot()

		# Empty out timers and reset Ids
		del self.timers[:]
		self.defaultTimer.clear(-1, True)

		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			0,
			self.defaultTimer
		)
		self.uniqueTimerId = len(self.timers)
コード例 #17
0
def parseConfig(configuration,
                list,
                version=None,
                uniqueTimerId=0,
                defaultTimer=None):
    try:
        intVersion = int(version)
    except ValueError:
        doLog(
            '[AutoTimer] Config version "%s" is not a valid integer, assuming old version'
            % version)
        intVersion = -1

    if intVersion < 5:
        parseConfigOld(configuration, list, uniqueTimerId)
        return

    if defaultTimer is not None:
        # Read in defaults for a new timer
        for defaults in configuration.findall("defaults"):
            parseEntry(defaults, defaultTimer, True)

    for timer in configuration.findall("timer"):
        uniqueTimerId += 1
        baseTimer = preferredAutoTimerComponent(uniqueTimerId, '', '', True)

        if parseEntry(timer, baseTimer):
            list.append(baseTimer)
コード例 #18
0
	def checkDuplicates(self, timer, name1, name2, shortdesc1, shortdesc2, extdesc1, extdesc2, force=False):
		if name1 and name2:
			sequenceMatcher = SequenceMatcher(" ".__eq__, name1, name2)
		else:
			return False

		ratio = sequenceMatcher.ratio()
		doDebug("names ratio %f - %s - %d - %s - %d" % (ratio, name1, len(name1), name2, len(name2)))
		if name1 in name2 or (0.8 < ratio): # this is probably a match
			foundShort = True
			if (force or timer.searchForDuplicateDescription > 0) and shortdesc1 and shortdesc2:
				sequenceMatcher.set_seqs(shortdesc1, shortdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
				foundShort = shortdesc1 in shortdesc2 or (0.8 < ratio)
				if foundShort:
					doLog("shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))

			foundExt = True
			# NOTE: only check extended if short description already is a match because otherwise
			# it won't evaluate to True anyway
			if foundShort and (force or timer.searchForDuplicateDescription > 1) and extdesc1 and extdesc2:
				sequenceMatcher.set_seqs(extdesc1, extdesc2)
				ratio = sequenceMatcher.ratio()
				doDebug("extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
				foundExt = (0.8 < ratio)
				if foundExt:
					doLog("extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
			return foundShort and foundExt
コード例 #19
0
	def populateTimerdict(self, epgcache, recordHandler, timerdict, simulateOnly=False):
		remove = []
		check_eit_and_remove = config.plugins.autotimer.check_eit_and_remove.value
		for timer in chain(recordHandler.timer_list, recordHandler.processed_timers):
			if timer and timer.service_ref:
				if timer.eit is not None:
					event = epgcache.lookupEventId(timer.service_ref.ref, timer.eit)
					if event:
						timer.extdesc = event.getExtendedDescription()
					elif check_eit_and_remove and "autotimer" in timer.flags and not timer.isRunning():
						remove.append(timer)
						continue
				else:
					remove.append(timer)
					continue

				if not hasattr(timer, 'extdesc'):
					timer.extdesc = ''

				timerdict[str(timer.service_ref)].append(timer)

		if check_eit_and_remove:
			for timer in remove:
				if "autotimer" in timer.flags:
					try:
						# Because of the duplicate check, we only want to remove future timer
						if timer in recordHandler.timer_list:
							if not timer.isRunning():
								recordHandler.removeEntry(timer)
								doLog("[AutoTimer] Remove timer because of eit check %s." % (timer.name))
								self.addToSearchLogfile(timer, "-", simulateOnly)
					except:
						pass
		del remove
コード例 #20
0
	def maybeRemoveWhitespaces(self):
		# XXX: Hack alert
		if self["list"].current[1] == "removeTrailingWhitespaces":
			doLog("[AutoTimer] Next step would be to remove trailing whitespaces, removing them and redirecting to 'conf2'")
			self.timer.match = self.timer.match.rstrip()
			self.match.value = self.match.value.rstrip()
			self.currStep = self.getStepWithID("conf2")
		self.trailingWhitespacesMatch = False
コード例 #21
0
def housekeepingExtensionsmenu(el):
	if el.value:
		plugins.addPlugin(extDescriptor)
	else:
		try:
			plugins.removePlugin(extDescriptor)
		except ValueError as ve:
			doLog("[AutoTimer] housekeepingExtensionsmenu got confused, tried to remove non-existant plugin entry... ignoring.")
コード例 #22
0
ファイル: plugin.py プロジェクト: dogfight76/enigma2-plugins
def housekeepingExtensionsmenu(el):
	if el.value:
		plugins.addPlugin(extDescriptor)
	else:
		try:
			plugins.removePlugin(extDescriptor)
		except ValueError as ve:
			doLog("[AutoTimer] housekeepingExtensionsmenu got confused, tried to remove non-existant plugin entry... ignoring.")
コード例 #23
0
	def maybeRemoveWhitespaces(self):
		# XXX: Hack alert
		if self["list"].current[1] == "removeTrailingWhitespaces":
			doLog("Next step would be to remove trailing whitespaces, removing them and redirecting to 'conf2'")
			self.timer.match = self.timer.match.rstrip()
			self.match.value = self.match.value.rstrip()
			self.currStep = self.getStepWithID("conf2")
		self.trailingWhitespacesMatch = False
コード例 #24
0
def add_to_filterList(session, service, services=None, *args, **kwargs):
	try:
		if services:
			if not isinstance(services, list):
				services = [services]
		else:
			services = [service]
		autotimer.addToFilterList(session, services)
	except Exception as e:
		print ("[AutoTimer] Unable to add Recordtitle to FilterList:", e)
		doLog("[AutoTimer] Unable to add Recordtitle to FilterList:", e)
コード例 #25
0
ファイル: plugin.py プロジェクト: OpenDMM/enigma2-plugins
def add_to_filterList(session, service, services=None, *args, **kwargs):
	
	try:
		if services:
			if not isinstance(services, list):
				services = [services]	
		else:
			services = [service]
		autotimer.addToFilterList(session, services)
	except Exception as e:
		print ("[AutoTimer] Unable to add Recordtitle to FilterList:", e)
		doLog("[AutoTimer] Unable to add Recordtitle to FilterList:", e)
コード例 #26
0
	def reloadTimerList(self, recordHandler):
		doLog("[AutoTimer] Start reload timers list after search")
		# checking and deleting duplicate timers
		disabled_at = removed_at = 0
		check_timer_list = recordHandler.timer_list[:]
		for timer in check_timer_list:
			check_timer_list.remove(timer)
			timersanitycheck = TimerSanityCheck(check_timer_list, timer)
			if not timersanitycheck.check():
				simulTimerList = timersanitycheck.getSimulTimerList()
				if simulTimerList and timer in simulTimerList and "autotimer" in timer.flags and not timer.isRunning():
					timer.disabled = True
					recordHandler.timeChanged(timer)
					disabled_at += 1
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in simulTimerList])
					doLog("[AutoTimer-reload] Timer %s disabled because of conflicts with %s." % (timer.name, conflictString))
			elif timersanitycheck.doubleCheck() and "autotimer" in timer.flags and not timer.isRunning():
				try:
					recordHandler.removeEntry(timer)
					removed_at += 1
					doLog("[AutoTimer-reload] Remove double timer %s." % (timer.name))
				except:
					doLog("[AutoTimer-reload] Error for remove double timer %s." % (timer.name))
		if config.plugins.autotimer.remove_double_and_conflicts_timers.value == "yes_notify":
			if Standby.inStandby is None and (disabled_at or removed_at):
				AddPopup(_("Reload timers list.\n%d autotimer(s) disabled because conflict.\n%d double autotimer(s) removed.\n") % (disabled_at, removed_at), MessageBox.TYPE_INFO, config.plugins.autotimer.popup_timeout.value, CONFLICTINGDOUBLEID)
コード例 #27
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def reloadTimerList(self, recordHandler):
		doLog("[AutoTimer] Start reload timers list after search")
		# checking and deleting duplicate timers
		disabled_at = removed_at = 0
		check_timer_list = recordHandler.timer_list[:]
		for timer in check_timer_list:
			check_timer_list.remove(timer)
			timersanitycheck = TimerSanityCheck(check_timer_list, timer)
			if not timersanitycheck.check():
				simulTimerList = timersanitycheck.getSimulTimerList()
				if simulTimerList and timer in simulTimerList and "autotimer" in timer.flags and not timer.isRunning():
					timer.disabled = True
					recordHandler.timeChanged(timer)
					disabled_at += 1
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in simulTimerList])
					doLog("[AutoTimer-reload] Timer %s disabled because of conflicts with %s." % (timer.name, conflictString))
			elif timersanitycheck.doubleCheck() and "autotimer" in timer.flags and not timer.isRunning():
				try:
					recordHandler.removeEntry(timer)
					removed_at += 1
					doLog("[AutoTimer-reload] Remove double timer %s."% (timer.name))
				except:
					doLog("[AutoTimer-reload] Error for remove double timer %s."% (timer.name))
		if config.plugins.autotimer.remove_double_and_conflicts_timers.value == "yes_notify":
			if Standby.inStandby is None and (disabled_at or removed_at):
				AddPopup(_("Reload timers list.\n%d autotimer(s) disabled because conflict.\n%d double autotimer(s) removed.\n") % (disabled_at, removed_at), MessageBox.TYPE_INFO, config.plugins.autotimer.popup_timeout.value, CONFLICTINGDOUBLEID)
コード例 #28
0
    def run(self):
        sem = self.__semaphore
        queue = self.__queue
        pump = self.__pump
        timer = self.__timer

        self.running = True
        while 1:
            sem.acquire()
            # NOTE: we have to check this here and not using the while to prevent the parser to be started on shutdown
            if not self.running: break

            if config.plugins.autotimer.skip_during_records.value:
                try:
                    import NavigationInstance
                    if NavigationInstance.instance.RecordTimer.isRecording():
                        doLog("[AutoTimer]: Skip check during running records")
                        reactor.callFromThread(
                            timer.startLongTimer,
                            config.plugins.autotimer.interval.value * 3600)
                        continue
                except:
                    pass

            if config.plugins.autotimer.skip_during_epgrefresh.value:
                try:
                    from Plugins.Extensions.EPGRefresh.EPGRefresh import epgrefresh
                    if epgrefresh.isrunning:
                        doLog("[AutoTimer]: Skip check during EPGRefresh")
                        reactor.callFromThread(
                            timer.startLongTimer,
                            config.plugins.autotimer.interval.value * 3600)
                        continue
                except:
                    pass

            from plugin import autotimer
            # Ignore any program errors
            try:
                queue.append(autotimer.parseEPG())
                pump.send(0)
            except Exception:
                # Dump error to stdout
                import traceback, sys
                traceback.print_exc(file=sys.stdout)
            #Keep that eTimer in the mainThread
            reactor.callFromThread(
                timer.startLongTimer,
                config.plugins.autotimer.interval.value * 3600)
コード例 #29
0
	def readXml(self):
		# Abort if no config found
		if not os.path.exists(XML_CONFIG):
			doLog("[AutoTimer] No configuration file present")
			return

		# Parse if mtime differs from whats saved
		mtime = os.path.getmtime(XML_CONFIG)
		if mtime == self.configMtime:
			doLog("[AutoTimer] No changes in configuration, won't parse")
			return

		# Save current mtime
		self.configMtime = mtime

		# Parse Config
		try:
			configuration = cet_parse(XML_CONFIG).getroot()
		except:
			try:
				if os_path.exists(XML_CONFIG + "_old"):
					os_rename(XML_CONFIG + "_old", XML_CONFIG + "_old(1)")
				os_rename(XML_CONFIG, XML_CONFIG + "_old")
				doLog("[AutoTimer] autotimer.xml is corrupt rename file to /etc/enigma2/autotimer.xml_old")
			except:
				pass
			if Standby.inStandby is None:
				AddPopup(_("The autotimer file (/etc/enigma2/autotimer.xml) is corrupt and could not be loaded.") + "\n" +_("A new and empty config was created. A backup of the config can be found here (/etc/enigma2/autotimer.xml_old)."), type = MessageBox.TYPE_ERROR, timeout = 0, id = "AutoTimerLoadFailed")

			self.timers = []
			self.defaultTimer = preferredAutoTimerComponent(
				0,		# Id
				"",		# Name
				"",		# Match
				True	# Enabled
			)

			try:
				self.writeXml()
				configuration = cet_parse(XML_CONFIG).getroot()
			except:
				doLog("[AutoTimer] fatal error, the autotimer.xml cannot create")
				return

		# Empty out timers and reset Ids
		del self.timers[:]
		self.defaultTimer.clear(-1, True)

		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			0,
			self.defaultTimer
		)
		self.uniqueTimerId = len(self.timers)
コード例 #30
0
	def readXmlTimer(self, xml_string):
		# Parse xml string
		try:
			configuration = cet_fromstring(xml_string)
		except:
			doLog("[AutoTimer] fatal error, the xml_string not read")
			return
		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			self.uniqueTimerId,
			self.defaultTimer
		)
		self.uniqueTimerId += 1

		# reset time
		self.configMtime = -1
コード例 #31
0
	def readXmlTimer(self, xml_string):
		# Parse xml string
		try:
			configuration = cet_fromstring(xml_string)
		except:
			doLog("[AutoTimer] fatal error, the xml_string not read")
			return
		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			self.uniqueTimerId,
			self.defaultTimer
		)
		self.uniqueTimerId += 1

		# reset time
		self.configMtime = -1
コード例 #32
0
	def addToFilterfile(self, name, begin, simulateOnlyValue=False, sp_title="xxxxxxxxxxxxxxxx"):
		path_filter_txt = "/etc/enigma2/autotimer_filter.txt"
		if os.path.exists(path_filter_txt):
			search_txt = '"' + name + '"'
			search_txt_sp = '"' + sp_title + '"'
			if (search_txt or search_txt_sp) in open(path_filter_txt).read():
				print ("[AutoTimer] Skipping an event because found event in autotimer_filter")
				doLog("[AutoTimer] Skipping an event because found event in autotimer_filter")
				return False
		if simulateOnlyValue:
			return True
		#write eventname totextfile
		filter_txt = str(strftime('%d.%m.%Y, %H:%M', localtime(begin))) + ' - "' + name + '"\n'
		file_filter_txt = open(path_filter_txt, "a")
		file_filter_txt.write(filter_txt)
		file_filter_txt.close()
		doLog("[AutoTimer] added a new event to autotimer_filter")
		return True
コード例 #33
0
ファイル: AutoPoller.py プロジェクト: Dog6574/enigma2-plugins
	def run(self):
		sem = self.__semaphore
		queue = self.__queue
		pump = self.__pump
		timer = self.__timer

		self.running = True
		while 1:
			sem.acquire()
			# NOTE: we have to check this here and not using the while to prevent the parser to be started on shutdown
			if not self.running: break
			
			if config.plugins.autotimer.skip_during_records.value:
				try:
					import NavigationInstance
					if NavigationInstance.instance.RecordTimer.isRecording():
						doLog("[AutoTimer]: Skip check during running records")
						reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
						continue
				except:
					pass

			if config.plugins.autotimer.skip_during_epgrefresh.value:
				try:
					from Plugins.Extensions.EPGRefresh.EPGRefresh import epgrefresh
					if epgrefresh.isrunning:
						doLog("[AutoTimer]: Skip check during EPGRefresh")
						reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
						continue
				except:
					pass

			from plugin import autotimer
			# Ignore any program errors
			try:
				queue.append(autotimer.parseEPG())
				pump.send(0)
			except Exception:
				# Dump error to stdout
				import traceback, sys
				traceback.print_exc(file=sys.stdout)
			#Keep that eTimer in the mainThread
			reactor.callFromThread(timer.startLongTimer, config.plugins.autotimer.interval.value*3600)
コード例 #34
0
ファイル: AutoTimer.py プロジェクト: MOA-2011/enigma2-plugins
	def modifyTimer(self, timer, name, shortdesc, begin, end, serviceref, eit=None, base_timer=None):
		if base_timer:
			old_timer = timer
			timer.justplay = base_timer.justplay
			timer.conflict_detection = base_timer.conflict_detection
			timer.always_zap = base_timer.always_zap
		timer.name = name
		timer.description = shortdesc
		timer.begin = int(begin)
		timer.end = int(end)
		timer.service_ref = ServiceReference(serviceref)
		if eit: 
			timer.eit = eit
		if base_timer:
			timersanitycheck = TimerSanityCheck(NavigationInstance.instance.RecordTimer.timer_list, timer)
			if not timersanitycheck.check():
				return False
			elif timersanitycheck.doubleCheck():
				return False
			else:
				doLog("[AutoTimer] conflict not found for modify timer %s." % timer.name)
		return True
コード例 #35
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def addDirectoryToMovieDict(self, moviedict, dest, serviceHandler):
		movielist = serviceHandler.list(eServiceReference("2:0:1:0:0:0:0:0:0:0:" + dest))
		if movielist is None:
			doLog("[AutoTimer] listing of movies in " + dest + " failed")
		else:
			append = moviedict[dest].append
			while 1:
				movieref = movielist.getNext()
				if not movieref.valid():
					break
				if movieref.flags & eServiceReference.mustDescent:
					continue
				info = serviceHandler.info(movieref)
				if info is None:
					continue
				event = info.getEvent(movieref)
				if event is None:
					continue
				append({
					"name": info.getName(movieref),
					"shortdesc": info.getInfoString(movieref, iServiceInformation.sDescription),
					"extdesc": event.getExtendedDescription() or '' # XXX: does event.getExtendedDescription() actually return None on no description or an empty string?
				})
コード例 #36
0
	def checkSimilarity(self, timer, name1, name2, shortdesc1, shortdesc2, extdesc1, extdesc2, force=False, isMovie=False):
		if name1 and name2:
			sequenceMatcher = SequenceMatcher(" ".__eq__, name1, name2)
		else:
			return False
		retValue = False
		ratio = sequenceMatcher.ratio()
		ratio_value = force and 0.8 or timer.ratioThresholdDuplicate
		doDebug("[AutoTimer] names ratio %f - %s - %d - %s - %d" % (ratio, name1, len(name1), name2, len(name2)))
		if name1 in name2 or (0.8 < ratio): # this is probably a match
			if not force and timer.descShortExtEmpty and (((isMovie and shortdesc1 and not shortdesc2) or (not isMovie and not shortdesc1 and not shortdesc2 and name1 != name2))
				or ((isMovie and extdesc1 and not extdesc2) or (not isMovie and not extdesc1 and not extdesc2 and name1 != name2))):
				doDebug("[AutoTimer] Configuration caused this sortdesc/extdesc match to be ignored!")
				return False
			if force or timer.searchForDuplicateDescription > 0:
				if shortdesc1 and shortdesc2:
					sequenceMatcher.set_seqs(shortdesc1, shortdesc2)
					ratio = sequenceMatcher.ratio()
					doDebug("[AutoTimer] shortdesc ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
					foundShort = shortdesc1 in shortdesc2 or ((ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio))
					doDebug("[AutoTimer] Final result for found shortdesc: %s" % foundShort)
					if foundShort:
						doLog("[AutoTimer] shortdesc match: ratio %f - %s - %d - %s - %d" % (ratio, shortdesc1, len(shortdesc1), shortdesc2, len(shortdesc2)))
						if force or timer.searchForDuplicateDescription > 1:
							if extdesc1 and extdesc2:
								sequenceMatcher.set_seqs(extdesc1, extdesc2)
								ratio = sequenceMatcher.ratio()
								doDebug("[AutoTimer] extdesc ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
								retValue = (ratio_value < ratio) or (ratio_value == 1.0 and ratio_value == ratio)
								doDebug("[AutoTimer] Final result for found extdesc: %s" % retValue)
								if retValue:
									doLog("[AutoTimer] extdesc match: ratio %f - %s - %d - %s - %d" % (ratio, extdesc1, len(extdesc1), extdesc2, len(extdesc2)))
						else:
							retValue = True
			else:
				retValue = True
		return retValue
コード例 #37
0
	def modifyTimer(self, timer, name, shortdesc, begin, end, serviceref, eit=None, base_timer=None):
		if base_timer:
			timer.justplay = base_timer.justplay
			timer.conflict_detection = base_timer.conflict_detection
			timer.always_zap = base_timer.always_zap
		timer.name = name
		timer.description = shortdesc
		timer.begin = int(begin)
		timer.end = int(end)
		timer.service_ref = ServiceReference(serviceref)
		if eit:
			timer.eit = eit
		if base_timer:
			check_timer_list = NavigationInstance.instance.RecordTimer.timer_list[:]
			if timer in check_timer_list:
				check_timer_list.remove(timer)
			timersanitycheck = TimerSanityCheck(check_timer_list, timer)
			if not timersanitycheck.check():
				return False
			elif timersanitycheck.doubleCheck():
				return False
			else:
				doLog("[AutoTimer] conflict not found for modify timer %s." % timer.name)
		return True
コード例 #38
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def readXml(self):
		# Abort if no config found
		if not os.path.exists(XML_CONFIG):
			doLog("[AutoTimer] No configuration file present")
			return

		# Parse if mtime differs from whats saved
		mtime = os.path.getmtime(XML_CONFIG)
		if mtime == self.configMtime:
			doLog("[AutoTimer] No changes in configuration, won't parse")
			return

		# Save current mtime
		self.configMtime = mtime

		# Parse Config
		try:
			configuration = cet_parse(XML_CONFIG).getroot()
		except:
			try:
				os.rename(XML_CONFIG, XML_CONFIG + "_old")
				doLog("[AutoTimer] autotimer.xml is corrupt rename file to /etc/enigma2/autotimer.xml_old")
			except:
				pass
			if Standby.inStandby is None:
				AddPopup(_("The autotimer file (/etc/enigma2/autotimer.xml) is corrupt and could not be loaded."), type = MessageBox.TYPE_ERROR, timeout = 0, id = "AutoTimerLoadFailed")
			return

		# Empty out timers and reset Ids
		del self.timers[:]
		self.defaultTimer.clear(-1, True)

		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			0,
			self.defaultTimer
		)
		self.uniqueTimerId = len(self.timers)
コード例 #39
0
ファイル: AutoTimer.py プロジェクト: OpenPLi/enigma2-plugins
	def parseTimer(self, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=False):
		new = 0
		modified = 0

		# Workaround to allow search for umlauts if we know the encoding
		#match = timer.match
		match = timer.match.replace('\xc2\x86', '').replace('\xc2\x87', '')
		if timer.encoding != 'UTF-8':
			try:
				match = match.decode('UTF-8').encode(timer.encoding)
			except UnicodeDecodeError:
				pass

		if timer.searchType == "description":
			epgmatches = []
			mask = (eServiceReference.isMarker | eServiceReference.isDirectory)

			casesensitive = timer.searchCase == "sensitive"
			if not casesensitive:
				match = match.lower()

			# Service filter defined
			# Search only using the specified services
			test = [(service, 0, -1, -1) for service in timer.services]

			for bouquet in timer.bouquets:
				services = serviceHandler.list(eServiceReference(bouquet))
				if not services is None:
					while True:
						service = services.getNext()
						if not service.valid(): #check end of list
							break
						if not (service.flags & mask):
							test.append( (service.toString(), 0, -1, -1 ) )

			if not test:
				# No service filter defined
				# Search within all services - could be very slow

				# Get all bouquets
				bouquetlist = []
				if config.usage.multibouquet.value:
					refstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
					bouquetroot = eServiceReference(refstr)
					bouquets = serviceHandler.list(bouquetroot)
					if bouquets:
						while True:
							s = bouquets.getNext()
							if not s.valid():
								break
							if s.flags & eServiceReference.isDirectory and not s.flags & eServiceReference.isInvisible:
								info = serviceHandler.info(s)
								if info:
									bouquetlist.append((info.getName(s), s))
					mask = (eServiceReference.isMarker | eServiceReference.isDirectory)
					for name, bouquet in bouquetlist:
						if not bouquet.valid(): #check end of list
							break
						if bouquet.flags & eServiceReference.isDirectory:
							services = serviceHandler.list(bouquet)
							if not services is None:
								while True:
									service = services.getNext()
									if not service.valid(): #check end of list
										break
									if not (service.flags & mask):
										test.append( (service.toString(), 0, -1, -1 ) )
				else:
					service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 31) || (type == 134) || (type == 195)'
					refstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(service_types_tv)
					bouquetroot = eServiceReference(refstr)
					info = serviceHandler.info(bouquetroot)
					if info:
						bouquetlist.append((info.getName(bouquetroot), bouquetroot))
					mask = (eServiceReference.isMarker | eServiceReference.isDirectory)
					for name, bouquet in bouquetlist:
						if bouquet.flags & eServiceReference.isDirectory:
							services = serviceHandler.list(bouquet)
							if not services is None:
								while True:
									service = services.getNext()
									if not service.valid(): #check end of list
										break
									if not (service.flags & mask):
										test.append( (service.toString(), 0, -1, -1 ) )

			if test:
				# Get all events
				#  eEPGCache.lookupEvent( [ format of the returned tuples, ( service, 0 = event intersects given start_time, start_time -1 for now_time), ] )
				test.insert(0, 'RITBDSE')
				allevents = epgcache.lookupEvent(test) or []

				# Filter events
				for serviceref, eit, name, begin, duration, shortdesc, extdesc in allevents:
					if match in (shortdesc if casesensitive else shortdesc.lower()) \
						or match in (extdesc if casesensitive else extdesc.lower()):
						epgmatches.append( (serviceref, eit, name, begin, duration, shortdesc, extdesc) )

		else:
			# Search EPG, default to empty list
			epgmatches = epgcache.search( ('RITBDSE', 2500, typeMap[timer.searchType], match, caseMap[timer.searchCase]) ) or []

		# Sort list of tuples by begin time 'B'
		epgmatches.sort(key=itemgetter(3))

		# Contains the the marked similar eits and the conflicting strings
		similardict = defaultdict(list)

		# Loop over all EPG matches
		for idx, ( serviceref, eit, name, begin, duration, shortdesc, extdesc ) in enumerate( epgmatches ):

			startLog()

			# timer destination dir
			dest = timer.destination

			evtBegin = begin
			evtEnd = end = begin + duration

			doLog("[AutoTimer] possible epgmatch %s" % (name))
			doLog("[AutoTimer] Serviceref %s" % (str(serviceref)))
			eserviceref = eServiceReference(serviceref)
			evt = epgcache.lookupEventId(eserviceref, eit)
			if not evt:
				doLog("[AutoTimer] Could not create Event!")
				skipped.append((name, begin, end, str(serviceref), timer.name, getLog()))
				continue
			# Try to determine real service (we always choose the last one)
			n = evt.getNumOfLinkageServices()
			if n > 0:
				i = evt.getLinkageService(eserviceref, n-1)
				serviceref = i.toString()
				doLog("[AutoTimer] Serviceref2 %s" % (str(serviceref)))


			# If event starts in less than 60 seconds skip it
			if begin < time() + 60:
				doLog("[AutoTimer] Skipping an event because it starts in less than 60 seconds")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			# Set short description to equal extended description if it is empty.
			if not shortdesc and timer.descShortEqualExt:
				shortdesc = extdesc

			# Convert begin time
			timestamp = localtime(begin)
			# Update timer
			timer.update(begin, timestamp)

			# Check if eit is in similar matches list
			# NOTE: ignore evtLimit for similar timers as I feel this makes the feature unintuitive
			similarTimer = False
			if eit in similardict:
				similarTimer = True
				dayofweek = None # NOTE: ignore day on similar timer
			else:
				# If maximum days in future is set then check time
				if checkEvtLimit:
					if begin > evtLimit:
						doLog("[AutoTimer] Skipping an event because of maximum days in future is reached")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				dayofweek = str(timestamp.tm_wday)

			# Check timer conditions
			# NOTE: similar matches do not care about the day/time they are on, so ignore them
			if timer.checkServices(serviceref):
				doLog("[AutoTimer] Skipping an event because of check services")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if timer.checkDuration(duration):
				doLog("[AutoTimer] Skipping an event because of duration check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if not similarTimer:
				if timer.checkTimespan(timestamp):
					doLog("[AutoTimer] Skipping an event because of timestamp check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
				if timer.checkTimeframe(begin):
					doLog("[AutoTimer] Skipping an event because of timeframe check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Initialize
			newEntry = None
			oldEntry = None
			oldExists = False
			allow_modify = True
			newAT = None

			# Eventually change service to alternative
			if timer.overrideAlternatives:
				serviceref = timer.getAlternative(serviceref)

			if timer.series_labeling and sp_getSeasonEpisode is not None:
				allow_modify = False
				doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (name, shortdesc, dest))
				sp = sp_getSeasonEpisode(serviceref, name, evtBegin, evtEnd, shortdesc, dest)
				if sp and type(sp) in (tuple, list) and len(sp) == 4:
					name = sp[0] or name
					shortdesc = sp[1] or shortdesc
					dest = sp[2] or dest
					doLog(str(sp[3]))
					allow_modify = True
					doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name, shortdesc, dest))
				else:
					# Nothing found
					doLog(str(sp))
					# If AutoTimer name not equal match, do a second lookup with the name
					if timer.name.lower() != timer.match.lower():
						doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (timer.name, shortdesc, dest))
						sp = sp_getSeasonEpisode(serviceref, timer.name, evtBegin, evtEnd, shortdesc, dest)
						if sp and type(sp) in (tuple, list) and len(sp) == 4:
							name = sp[0] or name
							shortdesc = sp[1] or shortdesc
							dest = sp[2] or dest
							doLog(str(sp[3]))
							allow_modify = True
							doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name, shortdesc, dest))
						else:
							doLog(str(sp))

			if timer.checkFilter(name, shortdesc, extdesc, dayofweek):
				doLog("[AutoTimer] Skipping an event because of filter check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			if timer.hasOffset():
				# Apply custom Offset
				begin, end = timer.applyOffset(begin, end)
			else:
				# Apply E2 Offset
				begin -= config.recording.margin_before.value * 60
				end += config.recording.margin_after.value * 60

			# Overwrite endtime if requested
			if timer.justplay and not timer.setEndtime:
				end = begin

			# Check for existing recordings in directory
			if timer.avoidDuplicateDescription == 3:
				# Reset movie Exists
				movieExists = False

				if dest and dest not in moviedict:
					self.addDirectoryToMovieDict(moviedict, dest, serviceHandler)
				for movieinfo in moviedict.get(dest, ()):
					if self.checkDuplicates(timer, name, movieinfo.get("name"), shortdesc, movieinfo.get("shortdesc"), extdesc, movieinfo.get("extdesc") ):
						doLog("[AutoTimer] We found a matching recorded movie, skipping event:", name)
						movieExists = True
						break
				if movieExists:
					doLog("[AutoTimer] Skipping an event because movie already exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Check for double Timers
			# We first check eit and if user wants us to guess event based on time
			# we try this as backup. The allowed diff should be configurable though.
			for rtimer in timerdict.get(serviceref, ()):
				if rtimer.eit == eit:
					oldExists = True
					doLog("[AutoTimer] We found a timer based on eit")
					newEntry = rtimer
					oldEntry = rtimer
					break
				elif config.plugins.autotimer.try_guessing.value:
					if timer.hasOffset():
						# Remove custom Offset
						rbegin = rtimer.begin + timer.offset[0] * 60
						rend = rtimer.end - timer.offset[1] * 60
					else:
						# Remove E2 Offset
						rbegin = rtimer.begin + config.recording.margin_before.value * 60
						rend = rtimer.end - config.recording.margin_after.value * 60
					# As alternative we could also do a epg lookup
					#revent = epgcache.lookupEventId(rtimer.service_ref.ref, rtimer.eit)
					#rbegin = revent.getBeginTime() or 0
					#rduration = revent.getDuration() or 0
					#rend = rbegin + rduration or 0
					if getTimeDiff(rbegin, rend, evtBegin, evtEnd) > ((duration/10)*8) or timeSimilarityPercent(rtimer, evtBegin, evtEnd, timer) > 80:
						oldExists = True
						doLog("[AutoTimer] We found a timer based on time guessing")
						newEntry = rtimer
						oldEntry = rtimer
						break
				if timer.avoidDuplicateDescription >= 1 \
					and not rtimer.disabled:
						if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
						# if searchForDuplicateDescription > 1 then check short description
							oldExists = True
							doLog("[AutoTimer] We found a timer (similar service) with same description, skipping event")
							break

			# We found no timer we want to edit
			if newEntry is None:
				# But there is a match
				if oldExists:
					doLog("[AutoTimer] Skipping an event because a timer on same service exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

				# We want to search for possible doubles
				if timer.avoidDuplicateDescription >= 2:
					for rtimer in chain.from_iterable( itervalues(timerdict) ):
						if not rtimer.disabled:
							if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
								oldExists = True
								doLog("[AutoTimer] We found a timer (any service) with same description, skipping event")
								break
					if oldExists:
						doLog("[AutoTimer] Skipping an event because a timer on any service exists")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				if timer.checkCounter(timestamp):
					doLog("[AutoTimer] Not adding new timer because counter is depleted.")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
			# Append to timerlist and abort if simulating
			timers.append((name, begin, end, serviceref, timer.name, getLog()))
			if simulateOnly:
				continue

			if newEntry is not None:
				# Abort if we don't want to modify timers or timer is repeated
				if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
					doLog("[AutoTimer] Won't modify existing timer because either no modification allowed or repeated timer")
					continue

				if "autotimer" in newEntry.flags:
					msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (timer.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					if config.plugins.autotimer.refresh.value != "all":
						doLog("[AutoTimer] Won't modify existing timer because it's no timer set by us")
						continue

					msg = "[AutoTimer] Warning, AutoTimer %s messed with a timer which might not belong to it: %s ." % (timer.name, newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)

				if allow_modify:
					if self.modifyTimer(newEntry, name, shortdesc, begin, end, serviceref, eit, base_timer=timer):
						msg = "[AutoTimer] AutoTimer modified timer: %s ." % (newEntry.name)
						doLog(msg)
						newEntry.log(501, msg)
						modified += 1
					else:
						msg = "[AutoTimer] AutoTimer modification not allowed for timer %s because conflicts or double timer." % (newEntry.name)
						doLog(msg)
						if oldEntry:
							self.setOldTimer(newEntry, oldEntry)
							doLog("[AutoTimer] conflict for modification timer %s detected return to old timer" % (newEntry.name))
						continue
				else:
					msg = "[AutoTimer] AutoTimer modification not allowed for timer: %s ." % (newEntry.name)
					doLog(msg)
					continue
			else:
				newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, shortdesc, eit)
				newAT = True

				msg = "[AutoTimer] Try to add new timer based on AutoTimer %s." % (timer.name)
				doLog(msg)
				newEntry.log(500, msg)

				# Mark this entry as AutoTimer
				newEntry.flags.add("autotimer")

			# Apply afterEvent
			if timer.hasAfterEvent():
				afterEvent = timer.getAfterEventTimespan(localtime(end))
				if afterEvent is None:
					afterEvent = timer.getAfterEvent()
				if afterEvent is not None:
					newEntry.afterEvent = afterEvent

			newEntry.dirname = dest
			newEntry.calculateFilename()
			newEntry.justplay = timer.justplay
			newEntry.vpsplugin_enabled = timer.vps_enabled
			newEntry.vpsplugin_overwrite = timer.vps_overwrite
			newEntry.conflict_detection = timer.conflict_detection
			newEntry.always_zap = timer.always_zap
			newEntry.zap_wakeup = timer.zap_wakeup

			tags = timer.tags[:]
			if config.plugins.autotimer.add_autotimer_to_tags.value:
				if 'AutoTimer' not in tags:
					tags.append('AutoTimer')
			if config.plugins.autotimer.add_name_to_tags.value:
				tagname = timer.name.strip()
				if tagname:
					tagname = tagname[0].upper() + tagname[1:].replace(" ", "_")
					if tagname not in tags:
						tags.append(tagname)
			newEntry.tags = tags

			if oldExists and newAT is None:
				if self.isResolvedConflict(newEntry):
					recordHandler.timeChanged(newEntry)
				else:
					if oldEntry:
						self.setOldTimer(newEntry, oldEntry)
						doLog("[AutoTimer] rechecking - conflict for timer %s detected return to old timer" % (newEntry.name))
					continue
			elif newAT:
				newAT = newEntry
				conflictString = ""
				if similarTimer:
					conflictString = similardict[eit].conflictString
					msg = "[AutoTimer] Try to add similar Timer because of conflicts with %s." % (conflictString)
					doLog(msg)
					newEntry.log(504, msg)

				# add new timer in AT timer list
				atDoubleTimer = False
				refstr = ':'.join(newEntry.service_ref.ref.toString().split(':')[:11])
				for at in addNewTimers:
					needed_ref = ':'.join(at.service_ref.ref.toString().split(':')[:11]) == refstr
					if needed_ref and at.eit == newEntry.eit and (newEntry.begin < at.begin <= newEntry.end or at.begin <= newEntry.begin <= at.end):
						atDoubleTimer = True
						break
				if atDoubleTimer:
					doLog("[AutoTimer] ignore double new auto timer %s." % newEntry.name)
					continue
				else:
					addNewTimers.append(newEntry)

				# Try to add timer
				conflicts = recordHandler.record(newEntry)

				if conflicts:
					# Maybe use newEntry.log
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in conflicts])
					doLog("[AutoTimer] conflict with %s detected" % (conflictString))

					if config.plugins.autotimer.addsimilar_on_conflict.value:
						# We start our search right after our actual index
						# Attention we have to use a copy of the list, because we have to append the previous older matches
						lepgm = len(epgmatches)
						for i in xrange(lepgm):
							servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS = epgmatches[ (i+idx+1)%lepgm ]
							if self.checkDuplicates(timer, name, nameS, shortdesc, shortdescS, extdesc, extdescS, force=True ):
								# Check if the similar is already known
								if eitS not in similardict:
									doLog("[AutoTimer] Found similar Timer: " + name)

									# Store the actual and similar eit and conflictString, so it can be handled later
									newEntry.conflictString = conflictString
									similardict[eit] = newEntry
									similardict[eitS] = newEntry
									similarTimer = True
									if beginS <= evtBegin:
										# Event is before our actual epgmatch so we have to append it to the epgmatches list
										epgmatches.append((servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS))
									# If we need a second similar it will be found the next time
								else:
									similarTimer = False
									newEntry = similardict[eitS]
								break

				if conflicts is None:
					timer.decrementCounter()
					if newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
						new += 1
						newEntry.extdesc = extdesc
						timerdict[serviceref].append(newEntry)

						# Similar timers are in new timers list and additionally in similar timers list
						if similarTimer:
							similars.append((name, begin, end, serviceref, timer.name))
							similardict.clear()
					else:
						doLog("[AutoTimer] ignore double timer %s." % newEntry.name)

				# Don't care about similar timers
				elif not similarTimer:
					conflicting.append((name, begin, end, serviceref, timer.name))

					if config.plugins.autotimer.disabled_on_conflict.value:
						msg = "[AutoTimer] Timer disabled because of conflicts with %s." % (conflictString)
						doLog(msg)
						newEntry.log(503, msg)
						newEntry.disabled = True
						if newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
							recordHandler.timeChanged(newEntry)
						else:
							# We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
							conflicts = recordHandler.record(newEntry)
					elif newAT != newEntry and newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
						if not self.isResolvedConflict(newEntry):
							newEntry.disabled = True
							recordHandler.timeChanged(newEntry)
							doLog("[AutoTimer] Unknown conflict, disable this timer %s." % newEntry.name)

		return (new, modified)
コード例 #40
0
ファイル: plugin.py プロジェクト: tomzza/enigma2-plugins
from AutoTimer import AutoTimer
autotimer = AutoTimer()
autopoller = None

AUTOTIMER_VERSION = "4.6.6"

try:
    from Plugins.SystemPlugins.MPHelp import registerHelp, XMLHelpReader
    from Tools.Directories import resolveFilename, SCOPE_PLUGINS
    reader = XMLHelpReader(resolveFilename(SCOPE_PLUGINS,
                                           "Extensions/AutoTimer/mphelp.xml"),
                           translate=_)
    autotimerHelp = registerHelp(*reader)
except Exception as e:
    doLog("[AutoTimer] Unable to initialize MPHelp:", e,
          "- Help not available!")
    autotimerHelp = None


def isOriginalWebifInstalled():
    try:
        from Tools.Directories import fileExists
    except:
        return False
    pluginpath = eEnv.resolve(
        '${libdir}/enigma2/python/Plugins/Extensions/WebInterface/plugin.py')
    if fileExists(pluginpath) or fileExists(pluginpath +
                                            "o") or fileExists(pluginpath +
                                                               "c"):
        return True
    return False
コード例 #41
0
ファイル: AutoTimer.py プロジェクト: xmasmc/enigma2-plugins
    def parseTimer(self,
                   timer,
                   epgcache,
                   serviceHandler,
                   recordHandler,
                   checkEvtLimit,
                   evtLimit,
                   timers,
                   conflicting,
                   similars,
                   skipped,
                   timerdict,
                   moviedict,
                   simulateOnly=False):
        new = 0
        modified = 0

        # Search EPG, default to empty list
        epgmatches = epgcache.search(
            ('RITBDSE', 1000, typeMap[timer.searchType], timer.match,
             caseMap[timer.searchCase])) or []

        # Sort list of tuples by begin time 'B'
        epgmatches.sort(key=itemgetter(3))

        # Contains the the marked similar eits and the conflicting strings
        similardict = defaultdict(list)

        # Loop over all EPG matches
        for idx, (serviceref, eit, name, begin, duration, shortdesc,
                  extdesc) in enumerate(epgmatches):

            startLog()

            # timer destination dir
            dest = timer.destination or config.usage.default_path.value

            evtBegin = begin
            evtEnd = end = begin + duration

            doLog("possible epgmatch %s" % (name))
            doLog("Serviceref %s" % (str(serviceref)))
            eserviceref = eServiceReference(serviceref)
            evt = epgcache.lookupEventId(eserviceref, eit)
            if not evt:
                doLog("Could not create Event!")
                skipped.append(
                    (name, begin, end, str(serviceref), timer.name, getLog()))
                continue
            # Try to determine real service (we always choose the last one)
            n = evt.getNumOfLinkageServices()
            if n > 0:
                i = evt.getLinkageService(eserviceref, n - 1)
                serviceref = i.toString()
                doLog("Serviceref2 %s" % (str(serviceref)))

            # If event starts in less than 60 seconds skip it
            if begin < time() + 60:
                doLog(
                    "Skipping an event because it starts in less than 60 seconds"
                )
                skipped.append(
                    (name, begin, end, serviceref, timer.name, getLog()))
                continue

            # Convert begin time
            timestamp = localtime(begin)
            # Update timer
            timer.update(begin, timestamp)

            # Check if eit is in similar matches list
            # NOTE: ignore evtLimit for similar timers as I feel this makes the feature unintuitive
            similarTimer = False
            if eit in similardict:
                similarTimer = True
                dayofweek = None  # NOTE: ignore day on similar timer
            else:
                # If maximum days in future is set then check time
                if checkEvtLimit:
                    if begin > evtLimit:
                        doLog(
                            "Skipping an event because of maximum days in future is reached"
                        )
                        skipped.append((name, begin, end, serviceref,
                                        timer.name, getLog()))
                        continue

                dayofweek = str(timestamp.tm_wday)

            # Check timer conditions
            # NOTE: similar matches do not care about the day/time they are on, so ignore them
            if timer.checkServices(serviceref):
                doLog("Skipping an event because of check services")
                skipped.append(
                    (name, begin, end, serviceref, timer.name, getLog()))
                continue
            if timer.checkDuration(duration):
                doLog("Skipping an event because of duration check")
                skipped.append(
                    (name, begin, end, serviceref, timer.name, getLog()))
                continue
            if not similarTimer:
                if timer.checkTimespan(timestamp):
                    doLog("Skipping an event because of timestamp check")
                    skipped.append(
                        (name, begin, end, serviceref, timer.name, getLog()))
                    continue
                if timer.checkTimeframe(begin):
                    doLog("Skipping an event because of timeframe check")
                    skipped.append(
                        (name, begin, end, serviceref, timer.name, getLog()))
                    continue

            # Initialize
            newEntry = None
            oldExists = False
            allow_modify = True

            # Eventually change service to alternative
            if timer.overrideAlternatives:
                serviceref = timer.getAlternative(serviceref)

            if timer.series_labeling and sp_getSeasonEpisode is not None:
                allow_modify = False
                #doLog("Request name, desc, path %s %s %s" % (name,shortdesc,dest))
                sp = sp_getSeasonEpisode(serviceref, name, evtBegin, evtEnd,
                                         shortdesc, dest)
                if sp and type(sp) in (tuple, list) and len(sp) == 4:
                    name = sp[0] or name
                    shortdesc = sp[1] or shortdesc
                    dest = sp[2] or dest
                    doLog(str(sp[3]))
                    #doLog("Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
                    allow_modify = True
                else:
                    # Nothing found
                    doLog(str(sp))

                    # If AutoTimer name not equal match, do a second lookup with the name
                    if timer.name.lower() != timer.match.lower():
                        #doLog("Request name, desc, path %s %s %s" % (timer.name,shortdesc,dest))
                        sp = sp_getSeasonEpisode(serviceref, timer.name,
                                                 evtBegin, evtEnd, shortdesc,
                                                 dest)
                        if sp and type(sp) in (tuple, list) and len(sp) == 4:
                            name = sp[0] or name
                            shortdesc = sp[1] or shortdesc
                            dest = sp[2] or dest
                            doLog(str(sp[3]))
                            #doLog("Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
                            allow_modify = True
                        else:
                            doLog(str(sp))

            if timer.checkFilter(name, shortdesc, extdesc, dayofweek):
                doLog("Skipping an event because of filter check")
                skipped.append(
                    (name, begin, end, serviceref, timer.name, getLog()))
                continue

            if timer.hasOffset():
                # Apply custom Offset
                begin, end = timer.applyOffset(begin, end)
            else:
                # Apply E2 Offset
                if ServiceRecordingSettings:
                    begin -= ServiceRecordingSettings.instance.getMarginBefore(
                        eserviceref)
                    end += ServiceRecordingSettings.instance.getMarginAfter(
                        eserviceref)
                else:
                    begin -= config.recording.margin_before.value * 60
                    end += config.recording.margin_after.value * 60

            # Overwrite endtime if requested
            if timer.justplay and not timer.setEndtime:
                end = begin

            # Check for existing recordings in directory
            if timer.avoidDuplicateDescription == 3:
                # Reset movie Exists
                movieExists = False

                if dest and dest not in moviedict:
                    self.addDirectoryToMovieDict(moviedict, dest,
                                                 serviceHandler)
                for movieinfo in moviedict.get(dest, ()):
                    if self.checkDuplicates(timer, name, movieinfo.get("name"),
                                            shortdesc,
                                            movieinfo.get("shortdesc"),
                                            extdesc, movieinfo.get("extdesc")):
                        doLog(
                            "We found a matching recorded movie, skipping event:",
                            name)
                        movieExists = True
                        break
                if movieExists:
                    doLog("Skipping an event because movie already exists")
                    skipped.append(
                        (name, begin, end, serviceref, timer.name, getLog()))
                    continue

            # Check for double Timers
            # We first check eit and if user wants us to guess event based on time
            # we try this as backup. The allowed diff should be configurable though.
            for rtimer in timerdict.get(serviceref, ()):
                if rtimer.eit == eit:
                    oldExists = True
                    doLog("We found a timer based on eit")
                    newEntry = rtimer
                    break
                elif config.plugins.autotimer.try_guessing.value:
                    if timer.hasOffset():
                        # Remove custom Offset
                        rbegin = rtimer.begin + timer.offset[0]
                        rend = rtimer.end - timer.offset[1]
                    else:
                        # Remove E2 Offset
                        rbegin = rtimer.begin + config.recording.margin_before.value * 60
                        rend = rtimer.end - config.recording.margin_after.value * 60
                    # As alternative we could also do a epg lookup
                    #revent = epgcache.lookupEventId(rtimer.service_ref.ref, rtimer.eit)
                    #rbegin = revent.getBeginTime() or 0
                    #rduration = revent.getDuration() or 0
                    #rend = rbegin + rduration or 0
                    if getTimeDiff(rbegin, rend, evtBegin,
                                   evtEnd) > ((duration / 10) * 8):
                        oldExists = True
                        doLog("We found a timer based on time guessing")
                        newEntry = rtimer
                        break
                if timer.avoidDuplicateDescription >= 1 \
                 and not rtimer.disabled:
                    if self.checkDuplicates(timer, name, rtimer.name,
                                            shortdesc, rtimer.description,
                                            extdesc, rtimer.extdesc):
                        # if searchForDuplicateDescription > 1 then check short description
                        oldExists = True
                        doLog(
                            "We found a timer (similar service) with same description, skipping event"
                        )
                        break

            # We found no timer we want to edit
            if newEntry is None:
                # But there is a match
                if oldExists:
                    doLog(
                        "Skipping an event because a timer on same service exists"
                    )
                    skipped.append(
                        (name, begin, end, serviceref, timer.name, getLog()))
                    continue

                # We want to search for possible doubles
                if timer.avoidDuplicateDescription >= 2:
                    for rtimer in chain.from_iterable(itervalues(timerdict)):
                        if not rtimer.disabled:
                            if self.checkDuplicates(timer, name, rtimer.name,
                                                    shortdesc,
                                                    rtimer.description,
                                                    extdesc, rtimer.extdesc):
                                oldExists = True
                                doLog(
                                    "We found a timer (any service) with same description, skipping event"
                                )
                                break
                    if oldExists:
                        doLog(
                            "Skipping an event because a timer on any service exists"
                        )
                        skipped.append((name, begin, end, serviceref,
                                        timer.name, getLog()))
                        continue

                if timer.checkCounter(timestamp):
                    doLog("Not adding new timer because counter is depleted.")
                    skipped.append(
                        (name, begin, end, serviceref, timer.name, getLog()))
                    continue

            # if set option for check/save timer in filterlist and only if not found an existing timer
            isnewFilterEntry = False
            if (config.plugins.autotimer.series_save_filter.value
                    or timer.series_save_filter) and oldExists == False:
                # only if use series_labeling and if sp_getSeasonEpisode was succesful
                if timer.series_labeling and sp_getSeasonEpisode is not None:
                    if sp and type(sp) in (tuple, list) and len(sp) == 4:
                        ret = self.addToFilterfile(str(sp[0]), begin,
                                                   simulateOnly)
                        if ret:
                            if simulateOnly:
                                doLog(
                                    "only simulate - new Timer would be saved in autotimer_filter"
                                )
                            else:
                                doLog("new Timer saved in autotimer_filter")
                                isnewFilterEntry = True
                        else:
                            skipped.append(
                                (name, begin, end, serviceref, timer.name,
                                 getLog()))
                            continue

            # Append to timerlist and abort if simulating
            timers.append((name, begin, end, serviceref, timer.name, getLog()))
            if simulateOnly:
                continue

            if newEntry is not None:
                # Abort if we don't want to modify timers or timer is repeated
                if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
                    doLog(
                        "Won't modify existing timer because either no modification allowed or repeated timer"
                    )
                    continue

                if hasattr(newEntry, "isAutoTimer"):
                    msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (
                        timer.name)
                    doLog(msg)
                    newEntry.log(501, msg)
                elif config.plugins.autotimer.add_autotimer_to_tags.value and TAG in newEntry.tags:
                    msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (
                        timer.name)
                    doLog(msg)
                    newEntry.log(501, msg)
                else:
                    if config.plugins.autotimer.refresh.value != "all":
                        doLog(
                            "Won't modify existing timer because it's no timer set by us"
                        )
                        continue

                    msg = "[AutoTimer] Warning, AutoTimer %s messed with a timer which might not belong to it: %s ." % (
                        timer.name, newEntry.name)
                    doLog(msg)
                    newEntry.log(501, msg)

                if newEntry.begin != begin or newEntry.end != end or newEntry.name != name:
                    modified += 1
                    #self.addToSearchLogfile(newEntry,"#", simulateOnly)

                if allow_modify:
                    modified_for_searchlog = True if newEntry.begin != begin or newEntry.end != end or newEntry.name != name else False
                    self.modifyTimer(newEntry, name, shortdesc, begin, end,
                                     serviceref, eit)
                    if modified_for_searchlog:
                        self.addToSearchLogfile(newEntry, "#", simulateOnly)
                    msg = "[AutoTimer] AutoTimer modified timer: %s ." % (
                        newEntry.name)
                    doLog(msg)
                    newEntry.log(501, msg)
                else:
                    msg = "[AutoTimer] AutoTimer modification not allowed for timer: %s ." % (
                        newEntry.name)
                    doLog(msg)
            else:
                newEntry = RecordTimerEntry(ServiceReference(serviceref),
                                            begin, end, name, shortdesc, eit)
                msg = "[AutoTimer] Try to add new timer based on AutoTimer %s." % (
                    timer.name)
                doLog(msg)
                newEntry.log(500, msg)

                # Mark this entry as AutoTimer (only AutoTimers will have this Attribute set)
                # It is only temporarily, after a restart it will be lost,
                # because it won't be stored in the timer xml file
                newEntry.isAutoTimer = True

            # Apply afterEvent
            if timer.hasAfterEvent():
                afterEvent = timer.getAfterEventTimespan(localtime(end))
                if afterEvent is None:
                    afterEvent = timer.getAfterEvent()
                if afterEvent is not None:
                    newEntry.afterEvent = afterEvent

            newEntry.dirname = dest
            newEntry.calculateFilename()

            newEntry.justplay = timer.justplay
            newEntry.vpsplugin_enabled = timer.vps_enabled
            newEntry.vpsplugin_overwrite = timer.vps_overwrite
            tags = timer.tags[:]
            if config.plugins.autotimer.add_autotimer_to_tags.value:
                if TAG not in tags:
                    tags.append(TAG)
            if config.plugins.autotimer.add_name_to_tags.value:
                tagname = timer.name.strip()
                if tagname:
                    tagname = tagname[0].upper() + tagname[1:].replace(
                        " ", "_")
                    if tagname not in tags:
                        tags.append(tagname)
            newEntry.tags = tags

            if oldExists:
                # XXX: this won't perform a sanity check, but do we actually want to do so?
                recordHandler.timeChanged(newEntry)

            else:
                conflictString = ""
                if similarTimer:
                    conflictString = similardict[eit].conflictString
                    msg = "[AutoTimer] Try to add similar Timer because of conflicts with %s." % (
                        conflictString)
                    doLog(msg)
                    newEntry.log(504, msg)

                # Try to add timer
                conflicts = recordHandler.record(newEntry)

                if conflicts:
                    # Maybe use newEntry.log
                    conflictString += ' / '.join([
                        "%s (%s)" %
                        (x.name, strftime("%Y%m%d %H%M", localtime(x.begin)))
                        for x in conflicts
                    ])
                    doLog("conflict with %s detected" % (conflictString))

                    if config.plugins.autotimer.addsimilar_on_conflict.value:
                        # We start our search right after our actual index
                        # Attention we have to use a copy of the list, because we have to append the previous older matches
                        lepgm = len(epgmatches)
                        for i in xrange(lepgm):
                            servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS = epgmatches[
                                (i + idx + 1) % lepgm]
                            if self.checkDuplicates(timer,
                                                    name,
                                                    nameS,
                                                    shortdesc,
                                                    shortdescS,
                                                    extdesc,
                                                    extdescS,
                                                    force=True):
                                # Check if the similar is already known
                                if eitS not in similardict:
                                    doLog("Found similar Timer: " + name)

                                    # Store the actual and similar eit and conflictString, so it can be handled later
                                    newEntry.conflictString = conflictString
                                    similardict[eit] = newEntry
                                    similardict[eitS] = newEntry
                                    similarTimer = True
                                    if beginS <= evtBegin:
                                        # Event is before our actual epgmatch so we have to append it to the epgmatches list
                                        epgmatches.append(
                                            (servicerefS, eitS, nameS, beginS,
                                             durationS, shortdescS, extdescS))
                                    # If we need a second similar it will be found the next time
                                else:
                                    similarTimer = False
                                    newEntry = similardict[eitS]
                                break

                if conflicts is None:
                    timer.decrementCounter()
                    new += 1
                    if isnewFilterEntry:
                        self.addToSearchLogfile(newEntry, "++", simulateOnly)
                    else:
                        self.addToSearchLogfile(newEntry, "+", simulateOnly)
                    newEntry.extdesc = extdesc
                    timerdict[serviceref].append(newEntry)

                    # Similar timers are in new timers list and additionally in similar timers list
                    if similarTimer:
                        similars.append(
                            (name, begin, end, serviceref, timer.name))
                        similardict.clear()

                # Don't care about similar timers
                elif not similarTimer:
                    conflicting.append(
                        (name, begin, end, serviceref, timer.name))
                    self.addToSearchLogfile(newEntry, "x", simulateOnly)

                    if config.plugins.autotimer.disabled_on_conflict.value:
                        msg = "[AutoTimer] Timer disabled because of conflicts with %s." % (
                            conflictString)
                        doLog(msg)
                        newEntry.log(503, msg)
                        newEntry.disabled = True
                        # We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
                        conflicts = recordHandler.record(newEntry)

        return (new, modified)
コード例 #42
0
ファイル: plugin.py プロジェクト: Cofybreak/enigma2-plugins
from AutoTimer import AutoTimer

autotimer = AutoTimer()
autopoller = None

AUTOTIMER_VERSION = "4.1.2"

# pragma mark - Help
try:
    from Plugins.SystemPlugins.MPHelp import registerHelp, XMLHelpReader
    from Tools.Directories import resolveFilename, SCOPE_PLUGINS

    reader = XMLHelpReader(resolveFilename(SCOPE_PLUGINS, "Extensions/AutoTimer/mphelp.xml"))
    autotimerHelp = registerHelp(*reader)
except Exception as e:
    doLog("[AutoTimer] Unable to initialize MPHelp:", e, "- Help not available!")
    autotimerHelp = None
# pragma mark -


def isOriginalWebifInstalled():
    try:
        from Tools.Directories import fileExists
    except:
        return False
    pluginpath = eEnv.resolve("${libdir}/enigma2/python/Plugins/Extensions/WebInterface/plugin.py")
    if fileExists(pluginpath) or fileExists(pluginpath + "o") or fileExists(pluginpath + "c"):
        return True
    return False

コード例 #43
0
	def parseTimer(self, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=False):
		new = 0
		modified = 0

		# Search EPG, default to empty list
		epgmatches = epgcache.search( ('RITBDSE', 1000, typeMap[timer.searchType], timer.match, caseMap[timer.searchCase]) ) or []

		# Sort list of tuples by begin time 'B'
		epgmatches.sort(key=itemgetter(3))

		# Contains the the marked similar eits and the conflicting strings
		similardict = defaultdict(list)		

		# Loop over all EPG matches
		for idx, ( serviceref, eit, name, begin, duration, shortdesc, extdesc ) in enumerate( epgmatches ):
			
			startLog()
			
			# timer destination dir
			dest = timer.destination or config.usage.default_path.value
			
			evtBegin = begin
			evtEnd = end = begin + duration

			doLog("possible epgmatch %s" % (name))
			doLog("Serviceref %s" % (str(serviceref)))
			eserviceref = eServiceReference(serviceref)
			evt = epgcache.lookupEventId(eserviceref, eit)
			if not evt:
				doLog("Could not create Event!")
				skipped.append((name, begin, end, str(serviceref), timer.name, getLog()))
				continue
			# Try to determine real service (we always choose the last one)
			n = evt.getNumOfLinkageServices()
			if n > 0:
				i = evt.getLinkageService(eserviceref, n-1)
				serviceref = i.toString()
				doLog("Serviceref2 %s" % (str(serviceref)))

			# If event starts in less than 60 seconds skip it
			if begin < time() + 60:
				doLog("Skipping an event because it starts in less than 60 seconds")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			# Convert begin time
			timestamp = localtime(begin)
			# Update timer
			timer.update(begin, timestamp)

			# Check if eit is in similar matches list
			# NOTE: ignore evtLimit for similar timers as I feel this makes the feature unintuitive
			similarTimer = False
			if eit in similardict:
				similarTimer = True
				dayofweek = None # NOTE: ignore day on similar timer
			else:
				# If maximum days in future is set then check time
				if checkEvtLimit:
					if begin > evtLimit:
						doLog("Skipping an event because of maximum days in future is reached")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				dayofweek = str(timestamp.tm_wday)

			# Check timer conditions
			# NOTE: similar matches do not care about the day/time they are on, so ignore them
			if timer.checkServices(serviceref):
				doLog("Skipping an event because of check services")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if timer.checkDuration(duration):
				doLog("Skipping an event because of duration check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if not similarTimer:
				if timer.checkTimespan(timestamp):
					doLog("Skipping an event because of timestamp check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
				if timer.checkTimeframe(begin):
					doLog("Skipping an event because of timeframe check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Initialize
			newEntry = None
			oldExists = False
			allow_modify = True
			
			# Eventually change service to alternative
			if timer.overrideAlternatives:
				serviceref = timer.getAlternative(serviceref)

			if timer.series_labeling and sp_getSeasonEpisode is not None:
				allow_modify = False
				#doLog("Request name, desc, path %s %s %s" % (name,shortdesc,dest))
				sp = sp_getSeasonEpisode(serviceref, name, evtBegin, evtEnd, shortdesc, dest)
				if sp and type(sp) in (tuple, list) and len(sp) == 4:
					name = sp[0] or name
					shortdesc = sp[1] or shortdesc
					dest = sp[2] or dest
					doLog(str(sp[3]))
					#doLog("Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
					allow_modify = True
				else:
					# Nothing found
					doLog(str(sp))
					
					# If AutoTimer name not equal match, do a second lookup with the name
					if timer.name.lower() != timer.match.lower():
						#doLog("Request name, desc, path %s %s %s" % (timer.name,shortdesc,dest))
						sp = sp_getSeasonEpisode(serviceref, timer.name, evtBegin, evtEnd, shortdesc, dest)
						if sp and type(sp) in (tuple, list) and len(sp) == 4:
							name = sp[0] or name
							shortdesc = sp[1] or shortdesc
							dest = sp[2] or dest
							doLog(str(sp[3]))
							#doLog("Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
							allow_modify = True
						else:
							doLog(str(sp))

			if timer.checkFilter(name, shortdesc, extdesc, dayofweek):
				doLog("Skipping an event because of filter check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			
			if timer.hasOffset():
				# Apply custom Offset
				begin, end = timer.applyOffset(begin, end)
			else:
				# Apply E2 Offset
				if ServiceRecordingSettings:
					begin -= ServiceRecordingSettings.instance.getMarginBefore(eserviceref)
					end += ServiceRecordingSettings.instance.getMarginAfter(eserviceref)
				else:
					begin -= config.recording.margin_before.value * 60
					end += config.recording.margin_after.value * 60

			# Overwrite endtime if requested
			if timer.justplay and not timer.setEndtime:
				end = begin

			# Check for existing recordings in directory
			if timer.avoidDuplicateDescription == 3:
				# Reset movie Exists
				movieExists = False

				if dest and dest not in moviedict:
					self.addDirectoryToMovieDict(moviedict, dest, serviceHandler)
				for movieinfo in moviedict.get(dest, ()):
					if self.checkDuplicates(timer, name, movieinfo.get("name"), shortdesc, movieinfo.get("shortdesc"), extdesc, movieinfo.get("extdesc") ):
						doLog("We found a matching recorded movie, skipping event:", name)
						movieExists = True
						break
				if movieExists:
					doLog("Skipping an event because movie already exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Check for double Timers
			# We first check eit and if user wants us to guess event based on time
			# we try this as backup. The allowed diff should be configurable though.
			for rtimer in timerdict.get(serviceref, ()):
				if rtimer.eit == eit:
					oldExists = True
					doLog("We found a timer based on eit")
					newEntry = rtimer
					break
				elif config.plugins.autotimer.try_guessing.value:
					if timer.hasOffset():
						# Remove custom Offset
						rbegin = rtimer.begin + timer.offset[0] * 60
						rend = rtimer.end - timer.offset[1] * 60
					else:
						# Remove E2 Offset
						rbegin = rtimer.begin + config.recording.margin_before.value * 60
						rend = rtimer.end - config.recording.margin_after.value * 60
					# As alternative we could also do a epg lookup
					#revent = epgcache.lookupEventId(rtimer.service_ref.ref, rtimer.eit)
					#rbegin = revent.getBeginTime() or 0
					#rduration = revent.getDuration() or 0
					#rend = rbegin + rduration or 0
					if getTimeDiff(rbegin, rend, evtBegin, evtEnd) > ((duration/10)*8):
						oldExists = True
						doLog("We found a timer based on time guessing")
						newEntry = rtimer
						break
				if timer.avoidDuplicateDescription >= 1 \
					and not rtimer.disabled:
						if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
						# if searchForDuplicateDescription > 1 then check short description
							oldExists = True
							doLog("We found a timer (similar service) with same description, skipping event")
							break

			# We found no timer we want to edit
			if newEntry is None:
				# But there is a match
				if oldExists:
					doLog("Skipping an event because a timer on same service exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

				# We want to search for possible doubles
				if timer.avoidDuplicateDescription >= 2:
					for rtimer in chain.from_iterable( itervalues(timerdict) ):
						if not rtimer.disabled:
							if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
								oldExists = True
								doLog("We found a timer (any service) with same description, skipping event")
								break
					if oldExists:
						doLog("Skipping an event because a timer on any service exists")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				if timer.checkCounter(timestamp):
					doLog("Not adding new timer because counter is depleted.")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Append to timerlist and abort if simulating
			timers.append((name, begin, end, serviceref, timer.name, getLog()))
			if simulateOnly:
				continue

			if newEntry is not None:
				# Abort if we don't want to modify timers or timer is repeated
				if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
					doLog("Won't modify existing timer because either no modification allowed or repeated timer")
					continue

				if hasattr(newEntry, "isAutoTimer"):
					msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (timer.name)
					doLog(msg)
					newEntry.log(501, msg)
				elif config.plugins.autotimer.add_autotimer_to_tags.value and TAG in newEntry.tags:
					msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (timer.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					if config.plugins.autotimer.refresh.value != "all":
						doLog("Won't modify existing timer because it's no timer set by us")
						continue

					msg = "[AutoTimer] Warning, AutoTimer %s messed with a timer which might not belong to it: %s ." % (timer.name, newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)

				modified += 1

				if allow_modify:
					self.modifyTimer(newEntry, name, shortdesc, begin, end, serviceref, eit)
					msg = "[AutoTimer] AutoTimer modified timer: %s ." % (newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					msg = "[AutoTimer] AutoTimer modification not allowed for timer: %s ." % (newEntry.name)
					doLog(msg)
			else:
				newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, shortdesc, eit)
				msg = "[AutoTimer] Try to add new timer based on AutoTimer %s." % (timer.name)
				doLog(msg)
				newEntry.log(500, msg)
				
				# Mark this entry as AutoTimer (only AutoTimers will have this Attribute set)
				# It is only temporarily, after a restart it will be lost,
				# because it won't be stored in the timer xml file
				newEntry.isAutoTimer = True

			# Apply afterEvent
			if timer.hasAfterEvent():
				afterEvent = timer.getAfterEventTimespan(localtime(end))
				if afterEvent is None:
					afterEvent = timer.getAfterEvent()
				if afterEvent is not None:
					newEntry.afterEvent = afterEvent

			newEntry.dirname = dest
			newEntry.calculateFilename()

			newEntry.justplay = timer.justplay
			newEntry.vpsplugin_enabled = timer.vps_enabled
			newEntry.vpsplugin_overwrite = timer.vps_overwrite
			tags = timer.tags[:]
			if config.plugins.autotimer.add_autotimer_to_tags.value:
				if TAG not in tags:
					tags.append(TAG)
			if config.plugins.autotimer.add_name_to_tags.value:
				tagname = timer.name.strip()
				if tagname:
					tagname = tagname[0].upper() + tagname[1:].replace(" ", "_")
					if tagname not in tags:
						tags.append(tagname)
			newEntry.tags = tags

			if oldExists:
				# XXX: this won't perform a sanity check, but do we actually want to do so?
				recordHandler.timeChanged(newEntry)

			else:
				conflictString = ""
				if similarTimer:
					conflictString = similardict[eit].conflictString
					msg = "[AutoTimer] Try to add similar Timer because of conflicts with %s." % (conflictString)
					doLog(msg)
					newEntry.log(504, msg)

				# Try to add timer
				conflicts = recordHandler.record(newEntry)

				if conflicts:
					# Maybe use newEntry.log
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in conflicts])
					doLog("conflict with %s detected" % (conflictString))

					if config.plugins.autotimer.addsimilar_on_conflict.value:
						# We start our search right after our actual index
						# Attention we have to use a copy of the list, because we have to append the previous older matches
						lepgm = len(epgmatches)
						for i in xrange(lepgm):
							servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS = epgmatches[ (i+idx+1)%lepgm ]
							if self.checkDuplicates(timer, name, nameS, shortdesc, shortdescS, extdesc, extdescS, force=True ):
								# Check if the similar is already known
								if eitS not in similardict:
									doLog("Found similar Timer: " + name)

									# Store the actual and similar eit and conflictString, so it can be handled later
									newEntry.conflictString = conflictString
									similardict[eit] = newEntry
									similardict[eitS] = newEntry
									similarTimer = True
									if beginS <= evtBegin:
										# Event is before our actual epgmatch so we have to append it to the epgmatches list
										epgmatches.append((servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS))
									# If we need a second similar it will be found the next time
								else:
									similarTimer = False
									newEntry = similardict[eitS]
								break

				if conflicts is None:
					timer.decrementCounter()
					new += 1
					newEntry.extdesc = extdesc
					timerdict[serviceref].append(newEntry)

					# Similar timers are in new timers list and additionally in similar timers list
					if similarTimer:
						similars.append((name, begin, end, serviceref, timer.name))
						similardict.clear()

				# Don't care about similar timers
				elif not similarTimer:
					conflicting.append((name, begin, end, serviceref, timer.name))

					if config.plugins.autotimer.disabled_on_conflict.value:
						msg = "[AutoTimer] Timer disabled because of conflicts with %s." % (conflictString)
						doLog(msg)
						newEntry.log(503, msg)
						newEntry.disabled = True
						# We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
						conflicts = recordHandler.record(newEntry)
		
		return (new, modified)
コード例 #44
0
	def parseTimer(self, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=False):
		new = 0
		modified = 0

		# enable multiple timer if services or bouquets specified (eg. recording the same event on sd service and hd service)
		enable_multiple_timer = ((timer.services and 's' in config.plugins.autotimer.enable_multiple_timer.value or False) or (timer.bouquets and 'b' in config.plugins.autotimer.enable_multiple_timer.value or False))

		# Workaround to allow search for umlauts if we know the encoding
		match = timer.match.replace('\xc2\x86', '').replace('\xc2\x87', '')
		if timer.encoding != 'UTF-8':
			try:
				match = match.decode('UTF-8').encode(timer.encoding)
			except UnicodeDecodeError:
				pass

		if timer.searchType == "favoritedesc":
			epgmatches = []

			casesensitive = timer.searchCase == "sensitive"
			if not casesensitive:
				match = match.lower()

			test = []
			if timer.services or timer.bouquets:
				if timer.services:
					test = [(service, 0, -1, -1) for service in timer.services]
				if timer.bouquets:
					for bouquet in timer.bouquets:
						services = serviceHandler.list(eServiceReference(bouquet))
						if services:
							while True:
								service = services.getNext()
								if not service.valid():
									break
								playable = not (service.flags & (eServiceReference.isMarker | eServiceReference.isDirectory)) or (service.flags & eServiceReference.isNumberedMarker)
								if playable:
									test.append((service.toString(), 0, -1, -1))
			else: # Get all bouquets
				bouquetlist = []
				if config.usage.multibouquet.value:
					refstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
					bouquetroot = eServiceReference(refstr)
					bouquets = serviceHandler.list(bouquetroot)
					if bouquets:
						while True:
							s = bouquets.getNext()
							if not s.valid():
								break
							if s.flags & eServiceReference.isDirectory and not s.flags & eServiceReference.isInvisible:
								info = serviceHandler.info(s)
								if info:
									bouquetlist.append(s)
				else:
					service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 31) || (type == 134) || (type == 195)'
					refstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet' % (service_types_tv)
					bouquetroot = eServiceReference(refstr)
					info = serviceHandler.info(bouquetroot)
					if info:
						bouquetlist.append(bouquetroot)
				if bouquetlist:
					for bouquet in bouquetlist:
						if not bouquet.valid():
							break
						if bouquet.flags & eServiceReference.isDirectory:
							services = serviceHandler.list(bouquet)
							if services:
								while True:
									service = services.getNext()
									if not service.valid():
										break
									playable = not (service.flags & (eServiceReference.isMarker | eServiceReference.isDirectory)) or (service.flags & eServiceReference.isNumberedMarker)
									if playable:
										test.append((service.toString(), 0, -1, -1))

			if test:
				# Get all events
				#  eEPGCache.lookupEvent( [ format of the returned tuples, ( service, 0 = event intersects given start_time, start_time -1 for now_time), ] )
				test.insert(0, 'RITBDSE')
				allevents = epgcache.lookupEvent(test) or []

				# Filter events
				for serviceref, eit, name, begin, duration, shortdesc, extdesc in allevents:
					if match in (shortdesc if casesensitive else shortdesc.lower()) or match in (extdesc if casesensitive else extdesc.lower()) or match in (name if casesensitive else name.lower()):
						epgmatches.append((serviceref, eit, name, begin, duration, shortdesc, extdesc))

		else:
			# Search EPG, default to empty list
			epgmatches = epgcache.search(('RITBDSE', int(config.plugins.autotimer.max_search_events_match.value), typeMap[timer.searchType], match, caseMap[timer.searchCase])) or []

		# Sort list of tuples by begin time 'B'
		epgmatches.sort(key=itemgetter(3))

		# Contains the the marked similar eits and the conflicting strings
		similardict = defaultdict(list)

		dayofweek_exclude = timer.exclude[3]
		if dayofweek_exclude:
			dayofweek_exclude_values = dayofweek_exclude[:]
			if "weekend" in dayofweek_exclude_values:
				dayofweek_exclude_values.extend(("5", "6"))
			if "weekday" in dayofweek_exclude_values:
				dayofweek_exclude_values.extend(("0", "1", "2", "3", "4"))
		dayofweek_include = timer.include[3]
		if dayofweek_include:
			dayofweek_include_values = dayofweek_include[:]
			if "weekend" in dayofweek_include_values:
				dayofweek_include_values.extend(("5", "6"))
			if "weekday" in dayofweek_include_values:
				dayofweek_include_values.extend(("0", "1", "2", "3", "4"))

		# Loop over all EPG matches
		for idx, (serviceref, eit, name, begin, duration, shortdesc, extdesc) in enumerate(epgmatches):
			startLog()

			# timer destination dir
			dest = timer.destination or config.usage.default_path.value

			evtBegin = begin
			evtEnd = end = begin + duration

			doLog("[AutoTimer] possible epgmatch %s" % (name))
			doLog("[AutoTimer] Serviceref %s" % serviceref)
			eserviceref = eServiceReference(serviceref)
			evt = epgcache.lookupEventId(eserviceref, eit)
			if not evt:
				doLog("[AutoTimer] Could not create Event!")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			# Try to determine real service (we always choose the last one)
			#n = evt.getNumOfLinkageServices()
			#if n > 0:
			#	i = evt.getLinkageService(eserviceref, n-1)
			#	serviceref = i.toString()
			#	doLog("[AutoTimer] Serviceref2 %s" % serviceref)

			# If event starts in less than 60 seconds skip it
			if begin < time() + 60:
				doLog("[AutoTimer] Skipping an event because it starts in less than 60 seconds")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			# Set short description to equal extended description if it is empty.
			if not shortdesc and timer.descShortEqualExt and extdesc:
				shortdesc = extdesc

			# Convert begin time
			timestamp = localtime(begin)
			# Update timer
			timer.update(begin, timestamp)

			# Check if eit is in similar matches list
			# NOTE: ignore evtLimit for similar timers as I feel this makes the feature unintuitive
			similarTimer = False
			if eit in similardict:
				similarTimer = True
				dayofweek = None # NOTE: ignore day on similar timer
			else:
				# If maximum days in future is set then check time
				if checkEvtLimit:
					if begin > evtLimit:
						doLog("[AutoTimer] Skipping an event because of maximum days in future is reached")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				current_dayofweek = tdow = timestamp.tm_wday
				if (timer.timespan[0] != None) and timer.timespan[2]:
					begin_offset = 60 * timestamp.tm_hour + timestamp.tm_min
					timer_offset = 60 * timer.timespan[0][0] + timer.timespan[0][1]
					if begin_offset < timer_offset:
						tdow = (tdow - 1) % 7
				dayofweek = str(tdow)

				# Update dayofweek when programmes that cross midnight and have a dayofweek filter
				if str(current_dayofweek) == dayofweek and (dayofweek_exclude or dayofweek_include):
					end_timestamp = localtime(end)
					end_dayofweek = str(end_timestamp.tm_wday)
					if dayofweek != end_dayofweek:
						if dayofweek_exclude:
							if dayofweek in dayofweek_exclude_values:
								if not end_dayofweek in dayofweek_exclude_values:
									doLog("[AutoTimer] [AutoTimer] Update dayofweek by reason of exclude dayofweek filter")
									dayofweek = end_dayofweek
						if dayofweek_include and dayofweek != end_dayofweek:
							if not dayofweek in dayofweek_include_values:
								if end_dayofweek in dayofweek_include_values:
									doLog("[AutoTimer] [AutoTimer] Update dayofweek by reason of include dayofweek filter")
									dayofweek = end_dayofweek

			# Check timer conditions
			# NOTE: similar matches do not care about the day/time they are on, so ignore them
			if timer.checkServices(serviceref):
				doLog("[AutoTimer] Skipping an event because of check services")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if timer.checkDuration(duration):
				doLog("[AutoTimer] Skipping an event because of duration check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if not similarTimer:
				if timer.checkTimespan(timestamp):
					doLog("[AutoTimer] Skipping an event because of timestamp check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
				if timer.checkTimeframe(begin):
					doLog("[AutoTimer] Skipping an event because of timeframe check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Initialize
			newEntry = None
			oldEntry = None
			oldExists = False
			allow_modify = True
			newAT = None

			# Eventually change service to alternative
			if timer.overrideAlternatives:
				serviceref = timer.getAlternative(serviceref)

			if timer.series_labeling and sp_getSeasonEpisode is not None:
				allow_modify = False
				doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (name, shortdesc, dest))
				sp = sp_getSeasonEpisode(serviceref, name, evtBegin, evtEnd, shortdesc, dest, True)
				if sp and type(sp) in (tuple, list) and len(sp) > 3:
					name = sp[0] or name
					shortdesc = sp[1] or shortdesc
					dest = sp[2] or dest
					doLog(str(sp[3]))
					allow_modify = True
					doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name, shortdesc, dest))
				else:
					# Nothing found
					doLog(str(sp))
					# If AutoTimer name not equal match, do a second lookup with the name
					if timer.name.lower() != timer.match.lower():
						doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (timer.name, shortdesc, dest))
						sp = sp_getSeasonEpisode(serviceref, timer.name, evtBegin, evtEnd, shortdesc, dest, True)
						if sp and type(sp) in (tuple, list) and len(sp) > 3:
							name = sp[0] or name
							shortdesc = sp[1] or shortdesc
							dest = sp[2] or dest
							doLog(str(sp[3]))
							allow_modify = True
							doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name, shortdesc, dest))
						else:
							doLog(str(sp))

			if timer.checkFilter(name, shortdesc, extdesc, dayofweek):
				doLog("[AutoTimer] Skipping an event because of filter check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			if timer.hasOffset():
				# Apply custom Offset
				begin, end = timer.applyOffset(begin, end)
				offsetBegin = timer.offset[0]
				offsetEnd = timer.offset[1]
			else:
				# Apply E2 Offset
				begin -= config.recording.margin_before.value * 60
				end += config.recording.margin_after.value * 60
				offsetBegin = config.recording.margin_before.value * 60
				offsetEnd = config.recording.margin_after.value * 60

			# Overwrite endtime if requested
			if timer.justplay and not timer.setEndtime:
				end = begin
				evtEnd = evtBegin

			# Check for existing recordings in directory
			if timer.avoidDuplicateDescription == 3:
				# Reset movie Exists
				movieExists = False

				if dest and dest not in moviedict:
					self.addDirectoryToMovieDict(moviedict, dest, serviceHandler)
				for movieinfo in moviedict.get(dest, ()):
					if self.checkSimilarity(timer, name, movieinfo.get("name"), shortdesc, movieinfo.get("shortdesc"), extdesc, movieinfo.get("extdesc"), isMovie=True):
						doLog("[AutoTimer] We found a matching recorded movie, skipping event:", name)
						movieExists = True
						break
				if movieExists:
					doLog("[AutoTimer] Skipping an event because movie already exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Check for double Timers
			# We first check eit and if user wants us to guess event based on time
			# we try this as backup. The allowed diff should be configurable though.
			for rtimer in timerdict.get(serviceref, ()):
				try: # protect against vps plugin not being present
					vps_changed = hasVps and (rtimer.vpsplugin_enabled != timer.vps_enabled or rtimer.vpsplugin_overwrite != timer.vps_overwrite)
				except:
					vps_changed = False
				time_changed = (evtBegin - offsetBegin != rtimer.begin) or (evtEnd + offsetEnd != rtimer.end)
				desc_changed = (timer.avoidDuplicateDescription >= 1 and shortdesc and rtimer.description and shortdesc != rtimer.description) or (timer.avoidDuplicateDescription >= 2 and extdesc and rtimer.extdesc and extdesc != rtimer.extdesc)
				if rtimer.eit == eit:
					oldExists = True
					doLog("[AutoTimer] We found a timer based on eit")
					if time_changed or desc_changed or vps_changed:
						newEntry = rtimer
						oldEntry = [rtimer.name, rtimer.description, rtimer.extdesc, rtimer.begin, rtimer.end, rtimer.service_ref, rtimer.eit, rtimer.disabled]
					break
				elif config.plugins.autotimer.try_guessing.value:
					if timeSimilarityPercent(rtimer, evtBegin, evtEnd, timer) > 80:
						oldExists = True
						doLog("[AutoTimer] We found a timer based on time guessing")
						if time_changed or desc_changed or vps_changed:
							newEntry = rtimer
							oldEntry = [rtimer.name, rtimer.description, rtimer.extdesc, rtimer.begin, rtimer.end, rtimer.service_ref, rtimer.eit, rtimer.disabled]
						break
				if oldExists is None and timer.avoidDuplicateDescription >= 1 and not rtimer.disabled:
					# searchForDuplicateDescription is 1 - check short description / searchForDuplicateDescription is 2 - check extended description
					if self.checkSimilarity(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc):
						oldExists = True
						doLog("[AutoTimer] We found a timer (similar service) with same description, skipping event")
						break

			# We found no timer we want to edit
			if newEntry is None:
				# But there is a match
				if oldExists:
					doLog("[AutoTimer] Skipping an event because a timer on same service exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

				# We want to search for possible doubles
				for rtimer in chain.from_iterable(itervalues(timerdict)):
					if not rtimer.disabled:
						if self.checkDoubleTimers(timer, name, rtimer.name, begin, rtimer.begin, end, rtimer.end, serviceref, rtimer.service_ref.ref.toString(), enable_multiple_timer):
							oldExists = True
							print("[AutoTimer] We found a timer with same start time, skipping event")
							break
						if timer.avoidDuplicateDescription >= 2:
							if self.checkSimilarity(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc):
								oldExists = True
								doLog("[AutoTimer] We found a timer (any service) with same description, skipping event")
								break
				if oldExists:
					doLog("[AutoTimer] Skipping an event because a timer on any service exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

				if timer.checkCounter(timestamp):
					doLog("[AutoTimer] Not adding new timer because counter is depleted.")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# if set option for check/save timer in filterlist and only if not found an existing timer
			isnewFilterEntry = False
			if (config.plugins.autotimer.series_save_filter.value or timer.series_save_filter) and not oldExists:
				if timer.series_labeling and sp_getSeasonEpisode is not None:
					if sp and type(sp) in (tuple, list) and len(sp) == 4:
						ret = self.addToFilterfile(str(sp[0]), begin, simulateOnly)
					if sp and type(sp) in (tuple, list) and len(sp) > 3:
						filter_title = str(sp[0])
						if len(sp) > 4:
							filter_title = "{series:s} - S{season:02d}E{rawepisode:s} - {title:s}".format(**sp[4])
						ret = self.addToFilterfile(filter_title, begin, simulateOnly, str(sp[0]))
						if ret:
							if simulateOnly:
								doLog("[AutoTimer SeriesPlugin] only simulate - new Timer would be saved in autotimer_filter")
							else:
								doLog("[AutoTimer SeriesPlugin] new Timer saved in autotimer_filter")
								isnewFilterEntry = True
						else:
							skipped.append((name, begin, end, serviceref, timer.name, getLog()))
							continue

			# Append to timerlist and abort if simulating
			timers.append((name, begin, end, serviceref, timer.name, getLog()))
			if simulateOnly:
				continue

			if newEntry is not None:
				# Abort if we don't want to modify timers or timer is repeated
				if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
					doLog("[AutoTimer] Won't modify existing timer because either no modification allowed or repeated timer")
					continue
				if "autotimer" in newEntry.flags:
					msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (timer.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					if config.plugins.autotimer.refresh.value != "all":
						doLog("[AutoTimer] Won't modify existing timer because it's no timer set by us")
						continue

					msg = "[AutoTimer] Warning, AutoTimer %s messed with a timer which might not belong to it: %s ." % (timer.name, newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)

				changed = newEntry.begin != begin or newEntry.end != end or newEntry.name != name
				if allow_modify:
					if oldExists and newEntry.service_ref.ref.toString() == serviceref and newEntry.eit == eit and newEntry.name == name and newEntry.begin < begin and newEntry.end < end and (0 < begin - newEntry.end <= 600):
						begin = newEntry.begin
						doLog("[AutoTimer] This same eit and different times end - update only end")
					if self.modifyTimer(newEntry, name, shortdesc, begin, end, serviceref, eit, base_timer=timer):
						msg = "[AutoTimer] AutoTimer modified timer: %s ." % (newEntry.name)
						doLog(msg)
						newEntry.log(501, msg)
						if changed:
							self.addToSearchLogfile(newEntry, "#", simulateOnly)
							modified += 1
					else:
						msg = "[AutoTimer] AutoTimer modification not allowed for timer %s because conflicts or double timer." % (newEntry.name)
						doLog(msg)
						if oldEntry:
							self.setOldTimer(newEntry, oldEntry)
							doLog("[AutoTimer] conflict for modification timer %s detected return to old timer" % (newEntry.name))
						continue
				else:
					msg = "[AutoTimer] AutoTimer modification not allowed for timer: %s ." % (newEntry.name)
					doLog(msg)
					continue
			else:
				newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, shortdesc, eit)
				newAT = True

				msg = "[AutoTimer] Try to add new timer based on AutoTimer %s." % (timer.name)
				doLog(msg)
				newEntry.log(500, msg)
				msg = "[AutoTimer] Timer start on: %s" % ctime(begin)
				doLog(msg)
				newEntry.log(509, msg)

				# Mark this entry as AutoTimer
				newEntry.flags.add("autotimer")
				# Mark this entry as timer name
				newEntry.flags.add(stringToXML(timer.name))

			# Apply afterEvent
			if timer.hasAfterEvent():
				afterEvent = timer.getAfterEventTimespan(localtime(end))
				if afterEvent is None:
					afterEvent = timer.getAfterEvent()
				if afterEvent is not None:
					newEntry.afterEvent = afterEvent

			newEntry.dirname = dest
			newEntry.calculateFilename()
			newEntry.justplay = timer.justplay
			newEntry.vpsplugin_enabled = timer.vps_enabled
			newEntry.vpsplugin_overwrite = timer.vps_overwrite
			newEntry.conflict_detection = timer.conflict_detection
			newEntry.always_zap = timer.always_zap
			newEntry.zap_wakeup = timer.zap_wakeup

			tags = timer.tags[:]
			if config.plugins.autotimer.add_autotimer_to_tags.value:
				if 'AutoTimer' not in tags:
					tags.append('AutoTimer')
			if config.plugins.autotimer.add_name_to_tags.value:
				tagname = timer.name.strip()
				if tagname:
					tagname = tagname[0].upper() + tagname[1:].replace(" ", "_")
					if tagname not in tags:
						tags.append(tagname)
			newEntry.tags = tags

			if oldExists and newAT is None:
				if self.isResolvedConflict(newEntry):
					recordHandler.timeChanged(newEntry)
				else:
					if oldEntry:
						self.setOldTimer(newEntry, oldEntry)
						doLog("[AutoTimer] rechecking - conflict for timer %s detected return to old timer" % (newEntry.name))
					continue
			elif newAT:
				newAT = newEntry
				conflictString = ""
				if similarTimer:
					conflictString = similardict[eit].conflictString
					msg = "[AutoTimer] Try to add similar Timer because of conflicts with %s." % (conflictString)
					doLog(msg)
					newEntry.log(504, msg)

				# add new timer in AT timer list
				atDoubleTimer = False
				refstr = ':'.join(newEntry.service_ref.ref.toString().split(':')[:11])
				for at in addNewTimers:
					needed_ref = ':'.join(at.service_ref.ref.toString().split(':')[:11]) == refstr
					if needed_ref and at.eit == newEntry.eit and (newEntry.begin < at.begin <= newEntry.end or at.begin <= newEntry.begin <= at.end):
						atDoubleTimer = True
						break
				if atDoubleTimer:
					doLog("[AutoTimer] ignore double new auto timer %s." % newEntry.name)
					continue
				else:
					addNewTimers.append(newEntry)

				# Try to add timer
				conflicts = recordHandler.record(newEntry)

				if conflicts and not timer.hasOffset() and not config.recording.margin_before.value and not config.recording.margin_after.value and len(conflicts) > 1:
					change_end = change_begin = False
					conflict_begin = conflicts[1].begin
					conflict_end = conflicts[1].end
					if conflict_begin == newEntry.end:
						newEntry.end -= 30
						change_end = True
					elif newEntry.begin == conflict_end:
						newEntry.begin += 30
						change_begin = True
					if change_end or change_begin:
						conflicts = recordHandler.record(newEntry)
						if conflicts:
							if change_end:
								newEntry.end += 30
							elif change_begin:
								newEntry.begin -= 30
						else:
							doLog("[AutoTimer] The conflict is resolved by offset time begin/end (30 sec) for %s." % newEntry.name)

				if conflicts:
					# Maybe use newEntry.log
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in conflicts])
					doLog("[AutoTimer] conflict with %s detected" % (conflictString))

					if config.plugins.autotimer.addsimilar_on_conflict.value:
						# We start our search right after our actual index
						# Attention we have to use a copy of the list, because we have to append the previous older matches
						lepgm = len(epgmatches)
						for i in xrange(lepgm):
							servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS = epgmatches[(i + idx + 1) % lepgm]
							if self.checkSimilarity(timer, name, nameS, shortdesc, shortdescS, extdesc, extdescS, force=True):
								# Check if the similar is already known
								if eitS not in similardict:
									doLog("[AutoTimer] Found similar Timer: " + name)

									# Store the actual and similar eit and conflictString, so it can be handled later
									newEntry.conflictString = conflictString
									similardict[eit] = newEntry
									similardict[eitS] = newEntry
									similarTimer = True
									if beginS <= evtBegin:
										# Event is before our actual epgmatch so we have to append it to the epgmatches list
										epgmatches.append((servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS))
									# If we need a second similar it will be found the next time
								else:
									similarTimer = False
									newEntry = similardict[eitS]
								break

				if conflicts is None:
					timer.decrementCounter()
					if newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
						new += 1
						if isnewFilterEntry:
							self.addToSearchLogfile(newEntry, "++", simulateOnly)
						else:
							self.addToSearchLogfile(newEntry, "+", simulateOnly)
						newEntry.extdesc = extdesc
						timerdict[serviceref].append(newEntry)

						# Similar timers are in new timers list and additionally in similar timers list
						if similarTimer:
							similars.append((name, begin, end, serviceref, timer.name))
							similardict.clear()
					else:
						doLog("[AutoTimer] ignore double timer %s." % newEntry.name)

				# Don't care about similar timers
				elif not similarTimer:
					conflicting.append((name, begin, end, serviceref, timer.name))

					if config.plugins.autotimer.disabled_on_conflict.value:
						msg = "[AutoTimer] Timer disabled because of conflicts with %s." % (conflictString)
						doLog(msg)
						newEntry.log(503, msg)
						newEntry.disabled = True
						if newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
							recordHandler.timeChanged(newEntry)
						else:
							# We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
							conflicts = recordHandler.record(newEntry)
					elif newAT != newEntry and newEntry in (recordHandler.timer_list[:] + recordHandler.processed_timers[:]):
						if not self.isResolvedConflict(newEntry):
							newEntry.disabled = True
							recordHandler.timeChanged(newEntry)
							doLog("[AutoTimer] Unknown conflict, disable this timer %s." % newEntry.name)

		return (new, modified)
コード例 #45
0
def parseEntry(element, baseTimer, defaults=False):
    if not defaults:
        # Read out match
        baseTimer.match = element.get("match", "").encode("UTF-8")
        if not baseTimer.match:
            doLog(
                '[AutoTimer] Erroneous config is missing attribute "match", skipping entry'
            )
            return False

        # Read out name
        baseTimer.name = element.get("name", "").encode("UTF-8")
        if not baseTimer.name:
            doLog(
                '[AutoTimer] Timer is missing attribute "name", defaulting to match'
            )
            baseTimer.name = baseTimer.match

        # Read out enabled
        enabled = element.get("enabled", "yes")
        if enabled == "no":
            baseTimer.enabled = False
        elif enabled == "yes":
            baseTimer.enabled = True
        else:
            doLog(
                '[AutoTimer] Erroneous config contains invalid value for "enabled":',
                enabled, ', disabling')
            baseTimer.enabled = False

        # Read timeframe
        before = element.get("before")
        after = element.get("after")
        if before and after:
            baseTimer.timeframe = (int(after), int(before))

    # VPS-Plugin settings
    vps_enabled = element.get("vps_enabled", "no")
    vps_overwrite = element.get("vps_overwrite", "no")
    baseTimer.vps_enabled = True if vps_enabled == "yes" else False
    baseTimer.vps_overwrite = True if vps_overwrite == "yes" else False
    del vps_enabled, vps_overwrite

    # SeriesPlugin settings
    series_labeling = element.get("series_labeling", "no")
    series_save_filter = element.get("series_save_filter", "no")
    baseTimer.series_labeling = True if series_labeling == "yes" else False
    baseTimer.series_save_filter = True if series_save_filter == "yes" else False
    del series_labeling, series_save_filter

    # Read conflict detection
    conflict_detection = element.get("conflict_detection", "yes")
    baseTimer.conflict_detection = True if conflict_detection == "yes" else False
    del conflict_detection

    # Read always_zap
    baseTimer.always_zap = int(element.get("always_zap", 0))

    # Read zap_wakeup
    baseTimer.zap_wakeup = element.get("zap_wakeup", "always")

    # Read out encoding (won't change if no value is set)
    baseTimer.encoding = element.get("encoding")

    # Read out search type/case
    baseTimer.searchType = element.get("searchType", baseTimer.searchType)
    baseTimer.searchCase = element.get("searchCase", baseTimer.searchCase)

    # Read out if we should change to alternative services
    baseTimer.overrideAlternatives = int(
        element.get("overrideAlternatives", baseTimer.overrideAlternatives))

    # Read out timespan
    start = element.get("from")
    end = element.get("to")
    if start and end:
        start = [int(x) for x in start.split(':')]
        end = [int(x) for x in end.split(':')]
        baseTimer.timespan = (start, end)

    # Read out max length
    maxduration = element.get("maxduration")
    if maxduration:
        baseTimer.maxduration = int(maxduration) * 60

    # Read out recording path
    default = baseTimer.destination or ""
    baseTimer.destination = element.get("location",
                                        default).encode("UTF-8") or None

    # Read out offset
    offset = element.get("offset")
    if offset:
        offset = offset.split(",")
        if len(offset) == 1:
            before = after = int(offset[0] or 0) * 60
        else:
            before = int(offset[0] or 0) * 60
            after = int(offset[1] or 0) * 60
        baseTimer.offset = (before, after)

    # Read out counter
    baseTimer.matchCount = int(element.get("counter", 0))
    baseTimer.matchFormatString = element.get("counterFormat", "")
    if not defaults:
        baseTimer.matchLeft = int(element.get("left", baseTimer.matchCount))
        baseTimer.matchLimit = element.get("lastActivation", "")
        baseTimer.lastBegin = int(element.get("lastBegin", 0))

    # Read out justplay
    baseTimer.justplay = int(element.get("justplay", 0))
    baseTimer.setEndtime = int(element.get("setEndtime", 1))

    # Read out avoidDuplicateDescription
    baseTimer.avoidDuplicateDescription = int(
        element.get("avoidDuplicateDescription", 0))
    baseTimer.searchForDuplicateDescription = int(
        element.get("searchForDuplicateDescription", 2))

    # Read out description behavior
    descShortEqualExt = element.get("descShortEqualExt", "no")
    baseTimer.descShortEqualExt = True if descShortEqualExt == "yes" else False
    del descShortEqualExt
    descShortExtEmpty = element.get("descShortExtEmpty", "no")
    baseTimer.descShortExtEmpty = True if descShortExtEmpty == "yes" else False
    del descShortExtEmpty

    # Read out ratioThresholdDuplicate
    baseTimer.ratioThresholdDuplicate = float(
        element.get("ratioThresholdDuplicate", 0.8))

    # Read out allowed services
    l = element.findall("serviceref")
    if l:
        servicelist = []

        for service in l:
            value = service.text
            if value:
                myref = eServiceReference(str(value))
                if not (myref.flags & eServiceReference.isGroup):
                    # strip all after last :
                    pos = value.rfind(':')
                    if pos != -1:
                        if value[pos - 1] == ':':
                            pos -= 1
                        value = value[:pos + 1]

                servicelist.append(value)
        baseTimer.services = servicelist

    # Read out allowed bouquets
    l = element.findall("bouquet")
    if l:
        bouquets = []
        for bouquet in l:
            value = bouquet.text
            if value:
                bouquets.append(value)
        baseTimer.bouquets = bouquets

    # Read out afterevent
    l = element.findall("afterevent")
    if l:
        idx = {
            "none": AFTEREVENT.NONE,
            "deepstandby": AFTEREVENT.DEEPSTANDBY,
            "shutdown": AFTEREVENT.DEEPSTANDBY,
            "standby": AFTEREVENT.STANDBY,
            "auto": AFTEREVENT.AUTO
        }
        afterevents = []
        for afterevent in l:
            value = afterevent.text

            if value in idx:
                value = idx[value]
            else:
                doLog(
                    '[AutoTimer] Erroneous config contains invalid value for "afterevent":',
                    afterevent, ', ignoring definition')
                continue

            start = afterevent.get("from")
            end = afterevent.get("to")
            if start and end:
                start = [int(x) for x in start.split(':')]
                end = [int(x) for x in end.split(':')]
                afterevents.append((value, (start, end)))
            else:
                afterevents.append((value, None))
        baseTimer.afterevent = afterevents

    # Read out exclude
    l = element.findall("exclude")
    idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
    if l:
        excludes = ([], [], [], [])
        for exclude in l:
            where = exclude.get("where")
            value = exclude.text
            if not (value and where):
                continue

            if where in idx:
                excludes[idx[where]].append(value.encode("UTF-8"))
        baseTimer.exclude = excludes

    # Read out includes (use same idx)
    l = element.findall("include")
    if l:
        includes = ([], [], [], [])
        for include in l:
            where = include.get("where")
            value = include.text
            if not (value and where):
                continue

            if where in idx:
                includes[idx[where]].append(value.encode("UTF-8"))
        baseTimer.include = includes

    # Read out recording tags
    l = element.findall("tag")
    if l:
        tags = []
        for tag in l:
            value = tag.text
            if not value:
                continue

            tags.append(value.encode("UTF-8"))
        baseTimer.tags = tags

    return True
コード例 #46
0
def parseConfigOld(configuration, list, uniqueTimerId = 0):
	doLog("[AutoTimer] Trying to parse old config")

	# Iterate Timers
	for timer in configuration.findall("timer"):
		# Increment uniqueTimerId
		uniqueTimerId += 1

		# Get name (V2+)
		name = timer.get("name")
		if name:
			name = name.encode("UTF-8")
		# Get name (= match) (V1)
		else:
			# Read out name
			name = getValue(timer.findall("name"), "").encode("UTF-8")

		if not name:
			doLog('[AutoTimer] Erroneous config is missing attribute "name", skipping entry')
			continue

		# Read out match (V3+)
		match = timer.get("match")
		if match:
			# Read out match
			match = match.encode("UTF-8")
			if not match:
				doLog('[AutoTimer] Erroneous config contains empty attribute "match", skipping entry')
				continue
		# V2-
		else:
			# Setting match to name
			match = name


		# See if Timer is ensabled (V2+)
		enabled = timer.get("enabled")
		if enabled:
			if enabled == "no":
				enabled = False
			elif enabled == "yes":
				enabled = True
			else:
				doLog('[AutoTimer] Erroneous config contains invalid value for "enabled":', enabled,', skipping entry')
				enabled = False
		# V1
		else:
			elements = timer.findall("enabled")
			if elements:
				if getValue(elements, "yes") == "no":
					enabled = False
				else:
					enabled = True
			else:
				enabled = True

		# Read out timespan (V4+; Falling back on missing definition should be OK)
		start = timer.get("from")
		end = timer.get("to")
		if start and end:
			start = [int(x) for x in start.split(':')]
			end = [int(x) for x in end.split(':')]
			timetuple = (start, end)
		# V3-
		else:
			elements = timer.findall("timespan")
			Len = len(elements)
			if Len:
				# Read out last definition
				start = elements[Len-1].get("from")
				end = elements[Len-1].get("to")
				if start and end:
					start = [int(x) for x in start.split(':')]
					end = [int(x) for x in end.split(':')]
					timetuple = (start, end)
				else:
					doLog('[AutoTimer] Erroneous config contains invalid definition of "timespan", ignoring definition')
					timetuple = None
			else:
				timetuple = None

		# Read out allowed services (V*)
		elements = timer.findall("serviceref")
		if elements:
			servicelist = []
			for service in elements:
				value = service.text
				if value:
					myref = eServiceReference(str(value))
					if not (myref.flags & eServiceReference.isGroup):
						# strip all after last :
						pos = value.rfind(':')
						if pos != -1:
							if value[pos-1] == ':':
								pos -= 1
							value = value[:pos+1]

					servicelist.append(value)
		else:
			servicelist = None

		# Read out allowed bouquets (V* though officially supported since V4)
		bouquets = []
		for bouquet in timer.findall("bouquet"):
			value = bouquet.text
			if value:
				bouquets.append(value)

		# Read out offset (V4+)
		offset = timer.get("offset")
		if offset:
			offset = offset.split(",")
			if len(offset) == 1:
				before = after = int(offset[0] or 0) * 60
			else:
				before = int(offset[0] or 0) * 60
				after = int(offset[1] or 0) * 60
			offset = (before, after)
		# V3-
		else:
			elements = timer.findall("offset")
			Len = len(elements)
			if Len:
				value = elements[Len-1].get("both")
				if value == '':
					before = int(elements[Len-1].get("before", 0)) * 60
					after = int(elements[Len-1].get("after", 0)) * 60
				else:
					before = after = int(value) * 60
				offset = (before, after)
			else:
				offset = None

		# Read out counter
		counter = int(timer.get("counter", '0'))
		counterLeft = int(timer.get("left", counter))
		counterLimit = timer.get("lastActivation")
		counterFormat = timer.get("counterFormat", "")
		lastBegin = int(timer.get("lastBegin", 0))

		# Read out justplay
		justplay = int(timer.get("justplay", '0'))
		setEndtime = int(timer.get("setEndtime", '1'))

		# Read out avoidDuplicateDescription
		avoidDuplicateDescription = int(timer.get("avoidDuplicateDescription", 0))
		searchForDuplicateDescription = int(timer.get("searchForDuplicateDescription", 3)) - 1
		if searchForDuplicateDescription < 0 or searchForDuplicateDescription > 2:
			searchForDuplicateDescription = 2

		# Read out afterevent (compatible to V* though behaviour for V3- is different as V4+ allows multiple afterevents while the last definication was chosen before)
		idx = {
			"none": AFTEREVENT.NONE,
			"deepstandby": AFTEREVENT.DEEPSTANDBY,
			"shutdown": AFTEREVENT.DEEPSTANDBY,
			"standby": AFTEREVENT.STANDBY,
			"auto": AFTEREVENT.AUTO
		}
		afterevent = []
		for element in timer.findall("afterevent"):
			value = element.text

			if value in idx:
				value = idx[value]
			else:
				doLog('[AutoTimer] Erroneous config contains invalid value for "afterevent":', afterevent,', ignoring definition')
				continue

			start = element.get("from")
			end = element.get("to")
			if start and end:
				start = [int(x) for x in start.split(':')]
				end = [int(x) for x in end.split(':')]
				afterevent.append((value, (start, end)))
			else:
				afterevent.append((value, None))

		# Read out exclude (V*)
		idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
		excludes = ([], [], [], [])
		for exclude in timer.findall("exclude"):
			where = exclude.get("where")
			value = exclude.text
			if not (value and where):
				continue

			if where in idx:
				excludes[idx[where]].append(value.encode("UTF-8"))

		# Read out includes (use same idx) (V4+ feature, should not harm V3-)
		includes = ([], [], [], [])
		for include in timer.findall("include"):
			where = include.get("where")
			value = include.text
			if not (value and where):
				continue

			if where in idx:
				includes[idx[where]].append(value.encode("UTF-8"))

		# Read out max length (V4+)
		maxlen = timer.get("maxduration")
		if maxlen:
			maxlen = int(maxlen)*60
		# V3-
		else:
			elements = timer.findall("maxduration")
			if elements:
				maxlen = getValue(elements, None)
				if maxlen is not None:
					maxlen = int(maxlen)*60
			else:
				maxlen = None

		# Read out recording path
		destination = timer.get("destination", "").encode("UTF-8") or None

		# Read out recording tags
		tags = []
		for tag in timer.findall("tag"):
			value = tag.text
			if not value:
				continue

			tags.append(value.encode("UTF-8"))

		# Finally append timer
		list.append(preferredAutoTimerComponent(
				uniqueTimerId,
				name,
				match,
				enabled,
				timespan = timetuple,
				services = servicelist,
				offset = offset,
				afterevent = afterevent,
				exclude = excludes,
				include = includes,
				maxduration = maxlen,
				destination = destination,
				matchCount = counter,
				matchLeft = counterLeft,
				matchLimit = counterLimit,
				matchFormatString = counterFormat,
				lastBegin = lastBegin,
				justplay = justplay,
				setEndtime = setEndtime,
				avoidDuplicateDescription = avoidDuplicateDescription,
				searchForDuplicateDescription = searchForDuplicateDescription,
				bouquets = bouquets,
				tags = tags
		))
コード例 #47
0
ファイル: plugin.py プロジェクト: tomzza/enigma2-plugins
def timezoneChanged(self):
    if config.plugins.autotimer.autopoll.value and autopoller is not None:
        autopoller.pause()
        autopoller.start(initial=False)
        doLog("[AutoTimer] Timezone change detected.")
コード例 #48
0
def sessionstart(reason, **kwargs):
	if reason == 0 and "session" in kwargs:
		try:
			AutoTimerChannelContextMenuInit()
		except:
			pass
		try:
			AutoTimerEPGSelectionInit()
		except:
			pass
		if isOriginalWebifInstalled():
			try:
				from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
				from Plugins.Extensions.WebInterface.WebChilds.Screenpage import ScreenPage
				from twisted.web import static
				from twisted.python import util
				from WebChilds.UploadResource import UploadResource

				from AutoTimerResource import AutoTimerDoParseResource, \
					AutoTimerListAutoTimerResource, AutoTimerAddOrEditAutoTimerResource, \
					AutoTimerRemoveAutoTimerResource, AutoTimerChangeSettingsResource, \
					AutoTimerSettingsResource, AutoTimerSimulateResource, AutoTimerTestResource, API_VERSION
			except ImportError as ie:
				pass
			else:
				if hasattr(static.File, 'render_GET'):
					class File(static.File):
						def render_POST(self, request):
							return self.render_GET(request)
				else:
					File = static.File

				# webapi
				root = AutoTimerListAutoTimerResource()
				root.putChild('parse', AutoTimerDoParseResource())
				root.putChild('remove', AutoTimerRemoveAutoTimerResource())
				root.putChild('edit', AutoTimerAddOrEditAutoTimerResource())
				root.putChild('get', AutoTimerSettingsResource())
				root.putChild('set', AutoTimerChangeSettingsResource())
				root.putChild('simulate', AutoTimerSimulateResource())
				root.putChild('test', AutoTimerTestResource())
				addExternalChild( ("autotimer", root , "AutoTimer-Plugin", API_VERSION, False) )

				# webgui
				session = kwargs["session"]
				root = File(util.sibpath(__file__, "web-data"))
				root.putChild("web", ScreenPage(session, util.sibpath(__file__, "web"), True) )
				root.putChild('tmp', File('/tmp'))
				root.putChild("uploadfile", UploadResource(session))
				addExternalChild( ("autotimereditor", root, "AutoTimer", "1", True) )
				doLog("[AutoTimer] Use WebInterface")
		else:
			if isOpenWebifInstalled():
				try:
					from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
					from AutoTimerResource import AutoTimerDoParseResource, \
						AutoTimerListAutoTimerResource, AutoTimerAddOrEditAutoTimerResource, \
						AutoTimerRemoveAutoTimerResource, AutoTimerChangeSettingsResource, \
						AutoTimerSettingsResource, AutoTimerSimulateResource, AutoTimerTestResource, API_VERSION
				except ImportError as ie:
					pass
				else:
					root = AutoTimerListAutoTimerResource()
					root.putChild('parse', AutoTimerDoParseResource())
					root.putChild('remove', AutoTimerRemoveAutoTimerResource())
					root.putChild('edit', AutoTimerAddOrEditAutoTimerResource())
					root.putChild('get', AutoTimerSettingsResource())
					root.putChild('set', AutoTimerChangeSettingsResource())
					root.putChild('simulate', AutoTimerSimulateResource())
					root.putChild('test', AutoTimerTestResource())
					addExternalChild(("autotimer", root , "AutoTimer-Plugin", API_VERSION))
					doLog("[AutoTimer] Use OpenWebif")
コード例 #49
0
def parseEntry(element, baseTimer, defaults = False):
	if not defaults:
		# Read out match
		baseTimer.match = element.get("match", "").encode("UTF-8")
		if not baseTimer.match:
			doLog('[AutoTimer] Erroneous config is missing attribute "match", skipping entry')
			return False

		# Read out name
		baseTimer.name = element.get("name", "").encode("UTF-8")
		if not baseTimer.name:
			doLog('[AutoTimer] Timer is missing attribute "name", defaulting to match')
			baseTimer.name = baseTimer.match

		# Read out enabled
		enabled = element.get("enabled", "yes")
		if enabled == "no":
			baseTimer.enabled = False
		elif enabled == "yes":
			baseTimer.enabled = True
		else:
			doLog('[AutoTimer] Erroneous config contains invalid value for "enabled":', enabled,', disabling')
			baseTimer.enabled = False

		# Read timeframe
		before = element.get("before")
		after = element.get("after")
		if before and after:
			baseTimer.timeframe = (int(after), int(before))

	# VPS-Plugin settings
	vps_enabled = element.get("vps_enabled", "no")
	vps_overwrite = element.get("vps_overwrite", "no")
	baseTimer.vps_enabled = True if vps_enabled == "yes" else False
	baseTimer.vps_overwrite = True if vps_overwrite == "yes" else False
	del vps_enabled, vps_overwrite

	# SeriesPlugin settings
	series_labeling = element.get("series_labeling", "no")
	baseTimer.series_labeling = True if series_labeling == "yes" else False
	del series_labeling

	# Read conflict detection
	conflict_detection = element.get("conflict_detection", "yes")
	baseTimer.conflict_detection = True if conflict_detection == "yes" else False
	del conflict_detection

	# Read always_zap
	baseTimer.always_zap = int(element.get("always_zap", 0))

	# Read zap_wakeup
	baseTimer.zap_wakeup = element.get("zap_wakeup", "always")

	# Read out encoding (won't change if no value is set)
	baseTimer.encoding = element.get("encoding")

	# Read out search type/case
	baseTimer.searchType = element.get("searchType", baseTimer.searchType)
	baseTimer.searchCase = element.get("searchCase", baseTimer.searchCase)

	# Read out if we should change to alternative services
	baseTimer.overrideAlternatives = int(element.get("overrideAlternatives", baseTimer.overrideAlternatives))

	# Read out timespan
	start = element.get("from")
	end = element.get("to")
	if start and end:
		start = [int(x) for x in start.split(':')]
		end = [int(x) for x in end.split(':')]
		baseTimer.timespan = (start, end)

	# Read out max length
	maxduration = element.get("maxduration")
	if maxduration:
		baseTimer.maxduration = int(maxduration)*60

	# Read out recording path
	default = baseTimer.destination or ""
	baseTimer.destination = element.get("location", default).encode("UTF-8") or None

	# Read out offset
	offset = element.get("offset")
	if offset:
		offset = offset.split(",")
		if len(offset) == 1:
			before = after = int(offset[0] or 0) * 60
		else:
			before = int(offset[0] or 0) * 60
			after = int(offset[1] or 0) * 60
		baseTimer.offset = (before, after)

	# Read out counter
	baseTimer.matchCount = int(element.get("counter", 0))
	baseTimer.matchFormatString = element.get("counterFormat", "")
	if not defaults:
		baseTimer.matchLeft = int(element.get("left", baseTimer.matchCount))
		baseTimer.matchLimit = element.get("lastActivation", "")
		baseTimer.lastBegin = int(element.get("lastBegin", 0))

	# Read out justplay
	baseTimer.justplay = int(element.get("justplay", 0))
	baseTimer.setEndtime = int(element.get("setEndtime", 1))

	# Read out avoidDuplicateDescription
	baseTimer.avoidDuplicateDescription = int(element.get("avoidDuplicateDescription", 0))
	baseTimer.searchForDuplicateDescription = int(element.get("searchForDuplicateDescription", 2))

	# Read out description behavior
	descShortEqualExt = element.get("descShortEqualExt", "no")
	baseTimer.descShortEqualExt = True if descShortEqualExt == "yes" else False
	del descShortEqualExt
	descShortExtEmpty = element.get("descShortExtEmpty", "no")
	baseTimer.descShortExtEmpty = True if descShortExtEmpty == "yes" else False
	del descShortExtEmpty

	# Read out ratioThresholdDuplicate
	baseTimer.ratioThresholdDuplicate = float(element.get("ratioThresholdDuplicate", 0.8))

	# Read out allowed services
	l = element.findall("serviceref")
	if l:
		servicelist = []

		for service in l:
			value = service.text
			if value:
				myref = eServiceReference(str(value))
				if not (myref.flags & eServiceReference.isGroup):
					# strip all after last :
					pos = value.rfind(':')
					if pos != -1:
						if value[pos-1] == ':':
							pos -= 1
						value = value[:pos+1]

				servicelist.append(value)
		baseTimer.services = servicelist

	# Read out allowed bouquets
	l = element.findall("bouquet")
	if l:
		bouquets = []
		for bouquet in l:
			value = bouquet.text
			if value:
				bouquets.append(value)
		baseTimer.bouquets = bouquets

	# Read out afterevent
	l = element.findall("afterevent")
	if l:
		idx = {
			"none": AFTEREVENT.NONE,
			"deepstandby": AFTEREVENT.DEEPSTANDBY,
			"shutdown": AFTEREVENT.DEEPSTANDBY,
			"standby": AFTEREVENT.STANDBY,
			"auto": AFTEREVENT.AUTO
		}
		afterevents = []
		for afterevent in l:
			value = afterevent.text

			if value in idx:
				value = idx[value]
			else:
				doLog('[AutoTimer] Erroneous config contains invalid value for "afterevent":', afterevent,', ignoring definition')
				continue

			start = afterevent.get("from")
			end = afterevent.get("to")
			if start and end:
				start = [int(x) for x in start.split(':')]
				end = [int(x) for x in end.split(':')]
				afterevents.append((value, (start, end)))
			else:
				afterevents.append((value, None))
		baseTimer.afterevent = afterevents

	# Read out exclude
	l = element.findall("exclude")
	idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
	if l:
		excludes = ([], [], [], [])
		for exclude in l:
			where = exclude.get("where")
			value = exclude.text
			if not (value and where):
				continue

			if where in idx:
				excludes[idx[where]].append(value.encode("UTF-8"))
		baseTimer.exclude = excludes

	# Read out includes (use same idx)
	l = element.findall("include")
	if l:
		includes = ([], [], [], [])
		for include in l:
			where = include.get("where")
			value = include.text
			if not (value and where):
				continue

			if where in idx:
				includes[idx[where]].append(value.encode("UTF-8"))
		baseTimer.include = includes

	# Read out recording tags
	l =  element.findall("tag")
	if l:
		tags = []
		for tag in l:
			value = tag.text
			if not value:
				continue

			tags.append(value.encode("UTF-8"))
		baseTimer.tags = tags

	return True
コード例 #50
0
	def parseEPG(self, simulateOnly=False, uniqueId=None, callback=None):

		from plugin import AUTOTIMER_VERSION
		doLog("AutoTimer Version: " + AUTOTIMER_VERSION)

		if NavigationInstance.instance is None:
			doLog("[AutoTimer] Navigation is not available, can't parse EPG")
			return (0, 0, 0, [], [], [])

		new = 0
		modified = 0
		timers = []
		conflicting = []
		similars = []
		skipped = []

		# Init new added timers list
		global addNewTimers
		addNewTimers = []

		if config.plugins.autotimer.searchlog_write.value and not simulateOnly:
			self.prepareSearchLogfile()

		if currentThread().getName() == 'MainThread':
			doBlockingCallFromMainThread = lambda f, *a, **kw: f(*a, **kw)
		else:
			doBlockingCallFromMainThread = blockingCallFromMainThread

		# NOTE: the config option specifies "the next X days" which means today (== 1) + X
		delta = timedelta(days=config.plugins.autotimer.maxdaysinfuture.value + 1)
		evtLimit = mktime((date.today() + delta).timetuple())
		checkEvtLimit = delta.days > 1
		del delta

		# Read AutoTimer configuration
		self.readXml()

		# Get E2 instances
		epgcache = eEPGCache.getInstance()
		serviceHandler = eServiceCenter.getInstance()
		recordHandler = NavigationInstance.instance.RecordTimer

		# Save Timer in a dict to speed things up a little
		# We include processed timers as we might search for duplicate descriptions
		# NOTE: It is also possible to use RecordTimer isInTimer(), but we won't get the timer itself on a match
		timerdict = defaultdict(list)
		doBlockingCallFromMainThread(self.populateTimerdict, epgcache, recordHandler, timerdict, simulateOnly=simulateOnly)

		# Create dict of all movies in all folders used by an autotimer to compare with recordings
		# The moviedict will be filled only if one AutoTimer is configured to avoid duplicate description for any recordings
		moviedict = defaultdict(list)

		# Iterate Timer
		for timer in self.getEnabledTimerList():
			if uniqueId is None or timer.id == uniqueId:
				doLog("[AutoTimer] Start search for %s" % (timer.match.replace('\xc2\x86', '').replace('\xc2\x87', '')))
				tup = doBlockingCallFromMainThread(self.parseTimer, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=simulateOnly)
				if callback:
					callback(timers, conflicting, similars, skipped)
					del timers[:]
					del conflicting[:]
					del similars[:]
					del skipped[:]
				else:
					new += tup[0]
					modified += tup[1]

		if not simulateOnly:
			if sp_showResult is not None:
				blockingCallFromMainThread(sp_showResult)

			if config.plugins.autotimer.remove_double_and_conflicts_timers.value != "no":
				self.reloadTimerList(recordHandler)

		return (len(timers), new, modified, timers, conflicting, similars)
コード例 #51
0
ファイル: AutoTimer.py プロジェクト: openmb/enigma2-plugins
	def parseTimer(self, timer, epgcache, serviceHandler, recordHandler, checkEvtLimit, evtLimit, timers, conflicting, similars, skipped, timerdict, moviedict, simulateOnly=False):
		new = 0
		modified = 0

		# Workaround to allow search for umlauts if we know the encoding
		#match = timer.match
		match = timer.match.replace('\xc2\x86', '').replace('\xc2\x87', '')
		if timer.encoding != 'UTF-8':
			try:
				match = match.decode('UTF-8').encode(timer.encoding)
			except UnicodeDecodeError:
				pass

		if timer.searchType == "description":
			epgmatches = []
			mask = (eServiceReference.isMarker | eServiceReference.isDirectory)

			casesensitive = timer.searchCase == "sensitive"
			if not casesensitive:
				match = match.lower()

			# Service filter defined
			# Search only using the specified services
			test = [(service, 0, -1, -1) for service in timer.services]

			for bouquet in timer.bouquets:
				services = serviceHandler.list(eServiceReference(bouquet))
				if not services is None:
					while True:
						service = services.getNext()
						if not service.valid(): #check end of list
							break
						if not (service.flags & mask):
							test.append( (service.toString(), 0, -1, -1 ) )

			if not test:
				# No service filter defined
				# Search within all services - could be very slow

				# Get all bouquets
				bouquetlist = []
				if config.usage.multibouquet.value:
					refstr = '1:7:1:0:0:0:0:0:0:0:FROM BOUQUET "bouquets.tv" ORDER BY bouquet'
					bouquetroot = eServiceReference(refstr)
					bouquets = serviceHandler.list(bouquetroot)
					if bouquets:
						while True:
							s = bouquets.getNext()
							if not s.valid():
								break
							if s.flags & eServiceReference.isDirectory:
								info = serviceHandler.info(s)
								if info:
									bouquetlist.append((info.getName(s), s))
					mask = (eServiceReference.isMarker | eServiceReference.isDirectory)
					for name, bouquet in bouquetlist:
						if not bouquet.valid(): #check end of list
							break
						if bouquet.flags & eServiceReference.isDirectory:
							services = serviceHandler.list(bouquet)
							if not services is None:
								while True:
									service = services.getNext()
									if not service.valid(): #check end of list
										break
									if not (service.flags & mask):
										test.append( (service.toString(), 0, -1, -1 ) )
				else:
					service_types_tv = '1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 22) || (type == 25) || (type == 134) || (type == 195)'
					refstr = '%s FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet'%(service_types_tv)
					bouquetroot = eServiceReference(refstr)
					info = serviceHandler.info(bouquetroot)
					if info:
						bouquetlist.append((info.getName(bouquetroot), bouquetroot))
					mask = (eServiceReference.isMarker | eServiceReference.isDirectory)
					for name, bouquet in bouquetlist:
						if bouquet.flags & eServiceReference.isDirectory:
							services = serviceHandler.list(bouquet)
							if not services is None:
								while True:
									service = services.getNext()
									if not service.valid(): #check end of list
										break
									if not (service.flags & mask):
										test.append( (service.toString(), 0, -1, -1 ) )

			if test:
				# Get all events
				#  eEPGCache.lookupEvent( [ format of the returned tuples, ( service, 0 = event intersects given start_time, start_time -1 for now_time), ] )
				test.insert(0, 'RITBDSE')
				allevents = epgcache.lookupEvent(test) or []

				# Filter events
				for serviceref, eit, name, begin, duration, shortdesc, extdesc in allevents:
					if match in (shortdesc if casesensitive else shortdesc.lower()) \
						or match in (extdesc if casesensitive else extdesc.lower()):
						epgmatches.append( (serviceref, eit, name, begin, duration, shortdesc, extdesc) )

		else:
			# Search EPG, default to empty list
			epgmatches = epgcache.search( ('RITBDSE', 2000, typeMap[timer.searchType], match, caseMap[timer.searchCase]) ) or []

		# Sort list of tuples by begin time 'B'
		epgmatches.sort(key=itemgetter(3))

		# Contains the the marked similar eits and the conflicting strings
		similardict = defaultdict(list)

		# Loop over all EPG matches
		for idx, ( serviceref, eit, name, begin, duration, shortdesc, extdesc ) in enumerate( epgmatches ):

			startLog()

			# timer destination dir
			dest = timer.destination

			evtBegin = begin
			evtEnd = end = begin + duration

			doLog("[AutoTimer] possible epgmatch %s" % (name))
			doLog("[AutoTimer] Serviceref %s" % (str(serviceref)))
			eserviceref = eServiceReference(serviceref)
			evt = epgcache.lookupEventId(eserviceref, eit)
			if not evt:
				doLog("[AutoTimer] Could not create Event!")
				skipped.append((name, begin, end, str(serviceref), timer.name, getLog()))
				continue
			# Try to determine real service (we always choose the last one)
			n = evt.getNumOfLinkageServices()
			if n > 0:
				i = evt.getLinkageService(eserviceref, n-1)
				doLog("[AutoTimer] Serviceref2 %s" % (str(serviceref)))
				serviceref = i.toString()

			evtBegin = begin
			evtEnd = end = begin + duration

			# If event starts in less than 60 seconds skip it
			if begin < time() + 60:
				doLog("[AutoTimer] Skipping an event because it starts in less than 60 seconds")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			# Set short description to equal extended description if it is empty.
			if not shortdesc:
				shortdesc = extdesc

			# Convert begin time
			timestamp = localtime(begin)
			# Update timer
			timer.update(begin, timestamp)

			# Check if eit is in similar matches list
			# NOTE: ignore evtLimit for similar timers as I feel this makes the feature unintuitive
			similarTimer = False
			if eit in similardict:
				similarTimer = True
				dayofweek = None # NOTE: ignore day on similar timer
			else:
				# If maximum days in future is set then check time
				if checkEvtLimit:
					if begin > evtLimit:
						doLog("[AutoTimer] Skipping an event because of maximum days in future is reached")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				dayofweek = str(timestamp.tm_wday)

			# Check timer conditions
			# NOTE: similar matches do not care about the day/time they are on, so ignore them
			if timer.checkServices(serviceref):
				doLog("[AutoTimer] Skipping an event because of check services")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if timer.checkDuration(duration):
				doLog("[AutoTimer] Skipping an event because of duration check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue
			if not similarTimer:
				if timer.checkTimespan(timestamp):
					doLog("[AutoTimer] Skipping an event because of timestamp check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
				if timer.checkTimeframe(begin):
					doLog("[AutoTimer] Skipping an event because of timeframe check")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Initialize
			newEntry = None
			oldExists = False
			allow_modify = True

			# Eventually change service to alternative
			if timer.overrideAlternatives:
				serviceref = timer.getAlternative(serviceref)

			if timer.series_labeling and sp_getSeasonEpisode is not None:
				allow_modify = False
				#doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (name,shortdesc,dest))
				sp = sp_getSeasonEpisode(serviceref, name, evtBegin, evtEnd, shortdesc, dest)
				if sp and type(sp) in (tuple, list) and len(sp) == 4:
					name = sp[0] or name
					shortdesc = sp[1] or shortdesc
					dest = sp[2] or dest
					doLog(str(sp[3]))
					allow_modify = True
					#doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
				else:
					# Nothing found
					doLog(str(sp))
					# If AutoTimer name not equal match, do a second lookup with the name
					if timer.name.lower() != timer.match.lower():
						#doLog("[AutoTimer SeriesPlugin] Request name, desc, path %s %s %s" % (timer.name,shortdesc,dest))
						sp = sp_getSeasonEpisode(serviceref, timer.name, evtBegin, evtEnd, shortdesc, dest)
						if sp and type(sp) in (tuple, list) and len(sp) == 4:
							name = sp[0] or name
							shortdesc = sp[1] or shortdesc
							dest = sp[2] or dest
							doLog(str(sp[3]))
							allow_modify = True
							#doLog("[AutoTimer SeriesPlugin] Returned name, desc, path %s %s %s" % (name,shortdesc,dest))
						else:
							doLog(str(sp))

			if timer.checkFilter(name, shortdesc, extdesc, dayofweek):
				doLog("[AutoTimer] Skipping an event because of filter check")
				skipped.append((name, begin, end, serviceref, timer.name, getLog()))
				continue

			if timer.hasOffset():
				# Apply custom Offset
				begin, end = timer.applyOffset(begin, end)
			else:
				# Apply E2 Offset
				begin -= config.recording.margin_before.value * 60
				end += config.recording.margin_after.value * 60

			# Overwrite endtime if requested
			if timer.justplay and not timer.setEndtime:
				end = begin

			# Check for existing recordings in directory
			if timer.avoidDuplicateDescription == 3:
				# Reset movie Exists
				movieExists = False

				if dest and dest not in moviedict:
					self.addDirectoryToMovieDict(moviedict, dest, serviceHandler)
				for movieinfo in moviedict.get(dest, ()):
					if self.checkDuplicates(timer, name, movieinfo.get("name"), shortdesc, movieinfo.get("shortdesc"), extdesc, movieinfo.get("extdesc") ):
						doLog("[AutoTimer] We found a matching recorded movie, skipping event:", name)
						movieExists = True
						break
				if movieExists:
					doLog("[AutoTimer] Skipping an event because movie already exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

			# Check for double Timers
			# We first check eit and if user wants us to guess event based on time
			# we try this as backup. The allowed diff should be configurable though.
			for rtimer in timerdict.get(serviceref, ()):
				if rtimer.eit == eit:
					oldExists = True
					doLog("[AutoTimer] We found a timer based on eit")
					newEntry = rtimer
					break
				elif config.plugins.autotimer.try_guessing.value:
					if timer.hasOffset():
						# Remove custom Offset
						rbegin = rtimer.begin + timer.offset[0] * 60
						rend = rtimer.end - timer.offset[1] * 60
					else:
						# Remove E2 Offset
						rbegin = rtimer.begin + config.recording.margin_before.value * 60
						rend = rtimer.end - config.recording.margin_after.value * 60
					# As alternative we could also do a epg lookup
					#revent = epgcache.lookupEventId(rtimer.service_ref.ref, rtimer.eit)
					#rbegin = revent.getBeginTime() or 0
					#rduration = revent.getDuration() or 0
					#rend = rbegin + rduration or 0
					if getTimeDiff(rbegin, rend, evtBegin, evtEnd) > ((duration/10)*8):
						oldExists = True
						doLog("[AutoTimer] We found a timer based on time guessing")
						newEntry = rtimer
						break
				elif timer.avoidDuplicateDescription >= 1 \
					and not rtimer.disabled:
						if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
						# if searchForDuplicateDescription > 1 then check short description
							oldExists = True
							doLog("[AutoTimer] We found a timer (similar service) with same description, skipping event")
							break

			# We found no timer we want to edit
			if newEntry is None:
				# But there is a match
				if oldExists:
					doLog("[AutoTimer] Skipping an event because a timer on same service exists")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue

				# We want to search for possible doubles
				if timer.avoidDuplicateDescription >= 2:
					for rtimer in chain.from_iterable( itervalues(timerdict) ):
						if not rtimer.disabled:
							if self.checkDuplicates(timer, name, rtimer.name, shortdesc, rtimer.description, extdesc, rtimer.extdesc ):
								oldExists = True
								doLog("[AutoTimer] We found a timer (any service) with same description, skipping event")
								break
					if oldExists:
						doLog("[AutoTimer] Skipping an event because a timer on any service exists")
						skipped.append((name, begin, end, serviceref, timer.name, getLog()))
						continue

				if timer.checkCounter(timestamp):
					doLog("[AutoTimer] Not adding new timer because counter is depleted.")
					skipped.append((name, begin, end, serviceref, timer.name, getLog()))
					continue
			# Append to timerlist and abort if simulating
			timers.append((name, begin, end, serviceref, timer.name, getLog()))
			if simulateOnly:
				continue

			if newEntry is not None:
				# Abort if we don't want to modify timers or timer is repeated
				if config.plugins.autotimer.refresh.value == "none" or newEntry.repeated:
					doLog("[AutoTimer] Won't modify existing timer because either no modification allowed or repeated timer")
					continue

				if "autotimer" in newEntry.flags:
					msg = "[AutoTimer] AutoTimer %s modified this automatically generated timer." % (timer.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					if config.plugins.autotimer.refresh.value != "all":
						doLog("[AutoTimer] Won't modify existing timer because it's no timer set by us")
						continue

					msg = "[AutoTimer] Warning, AutoTimer %s messed with a timer which might not belong to it: %s ." % (timer.name, newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)

				modified += 1

				if allow_modify:
					self.modifyTimer(newEntry, name, shortdesc, begin, end, serviceref, eit)
					msg = "[AutoTimer] AutoTimer modified timer: %s ." % (newEntry.name)
					doLog(msg)
					newEntry.log(501, msg)
				else:
					msg = "[AutoTimer] AutoTimer modification not allowed for timer: %s ." % (newEntry.name)
					doLog(msg)
			else:
				newEntry = RecordTimerEntry(ServiceReference(serviceref), begin, end, name, shortdesc, eit)

				msg = "[AutoTimer] Try to add new timer based on AutoTimer %s." % (timer.name)
				doLog(msg)
				newEntry.log(500, msg)

				# Mark this entry as AutoTimer
				newEntry.flags.add("autotimer")

			# Apply afterEvent
			if timer.hasAfterEvent():
				afterEvent = timer.getAfterEventTimespan(localtime(end))
				if afterEvent is None:
					afterEvent = timer.getAfterEvent()
				if afterEvent is not None:
					newEntry.afterEvent = afterEvent

			newEntry.dirname = dest
			newEntry.calculateFilename()
			newEntry.justplay = timer.justplay
			newEntry.vpsplugin_enabled = timer.vps_enabled
			newEntry.vpsplugin_overwrite = timer.vps_overwrite
			newEntry.conflict_detection = timer.conflict_detection
			newEntry.always_zap = timer.always_zap
			newEntry.zap_wakeup = timer.zap_wakeup

			tags = timer.tags[:]
			if config.plugins.autotimer.add_autotimer_to_tags.value:
				tags.append('AutoTimer')
			if config.plugins.autotimer.add_name_to_tags.value:
				tagname = timer.name.strip()
				if tagname:
					tagname = tagname[0].upper() + tagname[1:].replace(" ", "_")
					tags.append(tagname)
			newEntry.tags = tags

			if oldExists:
				# XXX: this won't perform a sanity check, but do we actually want to do so?
				recordHandler.timeChanged(newEntry)

			else:
				conflictString = ""
				if similarTimer:
					conflictString = similardict[eit].conflictString
					msg = "[AutoTimer] Try to add similar Timer because of conflicts with %s." % (conflictString)
					doLog(msg)
					newEntry.log(504, msg)

				# Try to add timer
				conflicts = recordHandler.record(newEntry)

				if conflicts:
					# Maybe use newEntry.log
					conflictString += ' / '.join(["%s (%s)" % (x.name, strftime("%Y%m%d %H%M", localtime(x.begin))) for x in conflicts])
					doLog("[AutoTimer] conflict with %s detected" % (conflictString))

					if config.plugins.autotimer.addsimilar_on_conflict.value:
						# We start our search right after our actual index
						# Attention we have to use a copy of the list, because we have to append the previous older matches
						lepgm = len(epgmatches)
						for i in xrange(lepgm):
							servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS = epgmatches[ (i+idx+1)%lepgm ]
							if self.checkDuplicates(timer, name, nameS, shortdesc, shortdescS, extdesc, extdescS, force=True ):
								# Check if the similar is already known
								if eitS not in similardict:
									doLog("[AutoTimer] Found similar Timer: " + name)

									# Store the actual and similar eit and conflictString, so it can be handled later
									newEntry.conflictString = conflictString
									similardict[eit] = newEntry
									similardict[eitS] = newEntry
									similarTimer = True
									if beginS <= evtBegin:
										# Event is before our actual epgmatch so we have to append it to the epgmatches list
										epgmatches.append((servicerefS, eitS, nameS, beginS, durationS, shortdescS, extdescS))
									# If we need a second similar it will be found the next time
								else:
									similarTimer = False
									newEntry = similardict[eitS]
								break

				if conflicts is None:
					timer.decrementCounter()
					new += 1
					newEntry.extdesc = extdesc
					timerdict[serviceref].append(newEntry)

					#if renameTimer is not None and timer.series_labeling:
					#	renameTimer(newEntry, name, evtBegin, evtEnd)

					# Similar timers are in new timers list and additionally in similar timers list
					if similarTimer:
						similars.append((name, begin, end, serviceref, timer.name))
						similardict.clear()

				# Don't care about similar timers
				elif not similarTimer:
					conflicting.append((name, begin, end, serviceref, timer.name))

					if config.plugins.autotimer.disabled_on_conflict.value:
						msg = "[AutoTimer] Timer disabled because of conflicts with %s." % (conflictString)
						doLog(msg)
						newEntry.log(503, msg)
						newEntry.disabled = True
						# We might want to do the sanity check locally so we don't run it twice - but I consider this workaround a hack anyway
						conflicts = recordHandler.record(newEntry)

		return (new, modified)
コード例 #52
0
def parseConfigOld(configuration, list, uniqueTimerId=0):
    doLog("[AutoTimer] Trying to parse old config")

    # Iterate Timers
    for timer in configuration.findall("timer"):
        # Increment uniqueTimerId
        uniqueTimerId += 1

        # Get name (V2+)
        name = timer.get("name")
        if name:
            name = name.encode("UTF-8")
        # Get name (= match) (V1)
        else:
            # Read out name
            name = getValue(timer.findall("name"), "").encode("UTF-8")

        if not name:
            doLog(
                '[AutoTimer] Erroneous config is missing attribute "name", skipping entry'
            )
            continue

        # Read out match (V3+)
        match = timer.get("match")
        if match:
            # Read out match
            match = match.encode("UTF-8")
            if not match:
                doLog(
                    '[AutoTimer] Erroneous config contains empty attribute "match", skipping entry'
                )
                continue
        # V2-
        else:
            # Setting match to name
            match = name

        # See if Timer is ensabled (V2+)
        enabled = timer.get("enabled")
        if enabled:
            if enabled == "no":
                enabled = False
            elif enabled == "yes":
                enabled = True
            else:
                doLog(
                    '[AutoTimer] Erroneous config contains invalid value for "enabled":',
                    enabled, ', skipping entry')
                enabled = False
        # V1
        else:
            elements = timer.findall("enabled")
            if elements:
                if getValue(elements, "yes") == "no":
                    enabled = False
                else:
                    enabled = True
            else:
                enabled = True

        # Read out timespan (V4+; Falling back on missing definition should be OK)
        start = timer.get("from")
        end = timer.get("to")
        if start and end:
            start = [int(x) for x in start.split(':')]
            end = [int(x) for x in end.split(':')]
            timetuple = (start, end)
        # V3-
        else:
            elements = timer.findall("timespan")
            Len = len(elements)
            if Len:
                # Read out last definition
                start = elements[Len - 1].get("from")
                end = elements[Len - 1].get("to")
                if start and end:
                    start = [int(x) for x in start.split(':')]
                    end = [int(x) for x in end.split(':')]
                    timetuple = (start, end)
                else:
                    doLog(
                        '[AutoTimer] Erroneous config contains invalid definition of "timespan", ignoring definition'
                    )
                    timetuple = None
            else:
                timetuple = None

        # Read out allowed services (V*)
        elements = timer.findall("serviceref")
        if elements:
            servicelist = []
            for service in elements:
                value = service.text
                if value:
                    myref = eServiceReference(str(value))
                    if not (myref.flags & eServiceReference.isGroup):
                        # strip all after last :
                        pos = value.rfind(':')
                        if pos != -1:
                            if value[pos - 1] == ':':
                                pos -= 1
                            value = value[:pos + 1]

                    servicelist.append(value)
        else:
            servicelist = None

        # Read out allowed bouquets (V* though officially supported since V4)
        bouquets = []
        for bouquet in timer.findall("bouquet"):
            value = bouquet.text
            if value:
                bouquets.append(value)

        # Read out offset (V4+)
        offset = timer.get("offset")
        if offset:
            offset = offset.split(",")
            if len(offset) == 1:
                before = after = int(offset[0] or 0) * 60
            else:
                before = int(offset[0] or 0) * 60
                after = int(offset[1] or 0) * 60
            offset = (before, after)
        # V3-
        else:
            elements = timer.findall("offset")
            Len = len(elements)
            if Len:
                value = elements[Len - 1].get("both")
                if value == '':
                    before = int(elements[Len - 1].get("before", 0)) * 60
                    after = int(elements[Len - 1].get("after", 0)) * 60
                else:
                    before = after = int(value) * 60
                offset = (before, after)
            else:
                offset = None

        # Read out counter
        counter = int(timer.get("counter", '0'))
        counterLeft = int(timer.get("left", counter))
        counterLimit = timer.get("lastActivation")
        counterFormat = timer.get("counterFormat", "")
        lastBegin = int(timer.get("lastBegin", 0))

        # Read out justplay
        justplay = int(timer.get("justplay", '0'))
        setEndtime = int(timer.get("setEndtime", '1'))

        # Read out avoidDuplicateDescription
        avoidDuplicateDescription = int(
            timer.get("avoidDuplicateDescription", 0))
        searchForDuplicateDescription = int(
            timer.get("searchForDuplicateDescription", 3)) - 1
        if searchForDuplicateDescription < 0 or searchForDuplicateDescription > 2:
            searchForDuplicateDescription = 2

        # Read out afterevent (compatible to V* though behaviour for V3- is different as V4+ allows multiple afterevents while the last definication was chosen before)
        idx = {
            "none": AFTEREVENT.NONE,
            "deepstandby": AFTEREVENT.DEEPSTANDBY,
            "shutdown": AFTEREVENT.DEEPSTANDBY,
            "standby": AFTEREVENT.STANDBY,
            "auto": AFTEREVENT.AUTO
        }
        afterevent = []
        for element in timer.findall("afterevent"):
            value = element.text

            if value in idx:
                value = idx[value]
            else:
                doLog(
                    '[AutoTimer] Erroneous config contains invalid value for "afterevent":',
                    afterevent, ', ignoring definition')
                continue

            start = element.get("from")
            end = element.get("to")
            if start and end:
                start = [int(x) for x in start.split(':')]
                end = [int(x) for x in end.split(':')]
                afterevent.append((value, (start, end)))
            else:
                afterevent.append((value, None))

        # Read out exclude (V*)
        idx = {
            "title": 0,
            "shortdescription": 1,
            "description": 2,
            "dayofweek": 3
        }
        excludes = ([], [], [], [])
        for exclude in timer.findall("exclude"):
            where = exclude.get("where")
            value = exclude.text
            if not (value and where):
                continue

            if where in idx:
                excludes[idx[where]].append(value.encode("UTF-8"))

        # Read out includes (use same idx) (V4+ feature, should not harm V3-)
        includes = ([], [], [], [])
        for include in timer.findall("include"):
            where = include.get("where")
            value = include.text
            if not (value and where):
                continue

            if where in idx:
                includes[idx[where]].append(value.encode("UTF-8"))

        # Read out max length (V4+)
        maxlen = timer.get("maxduration")
        if maxlen:
            maxlen = int(maxlen) * 60
        # V3-
        else:
            elements = timer.findall("maxduration")
            if elements:
                maxlen = getValue(elements, None)
                if maxlen is not None:
                    maxlen = int(maxlen) * 60
            else:
                maxlen = None

        # Read out recording path
        destination = timer.get("destination", "").encode("UTF-8") or None

        # Read out recording tags
        tags = []
        for tag in timer.findall("tag"):
            value = tag.text
            if not value:
                continue

            tags.append(value.encode("UTF-8"))

        # Finally append timer
        list.append(
            preferredAutoTimerComponent(
                uniqueTimerId,
                name,
                match,
                enabled,
                timespan=timetuple,
                services=servicelist,
                offset=offset,
                afterevent=afterevent,
                exclude=excludes,
                include=includes,
                maxduration=maxlen,
                destination=destination,
                matchCount=counter,
                matchLeft=counterLeft,
                matchLimit=counterLimit,
                matchFormatString=counterFormat,
                lastBegin=lastBegin,
                justplay=justplay,
                setEndtime=setEndtime,
                avoidDuplicateDescription=avoidDuplicateDescription,
                searchForDuplicateDescription=searchForDuplicateDescription,
                bouquets=bouquets,
                tags=tags))
コード例 #53
0
ファイル: plugin.py プロジェクト: Cofybreak/enigma2-plugins
def sessionstart(reason, **kwargs):
    if reason == 0 and "session" in kwargs:
        # try:
        # 	AutoTimerGraphMultiEPGInit()
        # except:
        # 	pass
        try:
            AutoTimerChannelContextMenuInit()
        except:
            pass
        try:
            AutoTimerEPGSelectionInit()
        except:
            pass
        if isOriginalWebifInstalled():
            try:
                from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
                from Plugins.Extensions.WebInterface.WebChilds.Screenpage import ScreenPage
                from twisted.web import static
                from twisted.python import util
                from WebChilds.UploadResource import UploadResource

                from AutoTimerResource import (
                    AutoTimerDoParseResource,
                    AutoTimerListAutoTimerResource,
                    AutoTimerAddOrEditAutoTimerResource,
                    AutoTimerRemoveAutoTimerResource,
                    AutoTimerChangeSettingsResource,
                    AutoTimerSettingsResource,
                    AutoTimerSimulateResource,
                    AutoTimerTestResource,
                    API_VERSION,
                )
            except ImportError as ie:
                pass
            else:
                if hasattr(static.File, "render_GET"):

                    class File(static.File):
                        def render_POST(self, request):
                            return self.render_GET(request)

                else:
                    File = static.File

                    # webapi
                root = AutoTimerListAutoTimerResource()
                root.putChild("parse", AutoTimerDoParseResource())
                root.putChild("remove", AutoTimerRemoveAutoTimerResource())
                root.putChild("edit", AutoTimerAddOrEditAutoTimerResource())
                root.putChild("get", AutoTimerSettingsResource())
                root.putChild("set", AutoTimerChangeSettingsResource())
                root.putChild("simulate", AutoTimerSimulateResource())
                root.putChild("test", AutoTimerTestResource())
                addExternalChild(("autotimer", root, "AutoTimer-Plugin", API_VERSION, False))

                # webgui
                session = kwargs["session"]
                root = File(util.sibpath(__file__, "web-data"))
                root.putChild("web", ScreenPage(session, util.sibpath(__file__, "web"), True))
                root.putChild("tmp", File("/tmp"))
                root.putChild("uploadfile", UploadResource(session))
                addExternalChild(("autotimereditor", root, "AutoTimer", "1", True))
                doLog("[AutoTimer] Use WebInterface")
        else:
            if isOpenWebifInstalled():
                try:
                    from Plugins.Extensions.WebInterface.WebChilds.Toplevel import addExternalChild
                    from AutoTimerResource import (
                        AutoTimerDoParseResource,
                        AutoTimerListAutoTimerResource,
                        AutoTimerAddOrEditAutoTimerResource,
                        AutoTimerRemoveAutoTimerResource,
                        AutoTimerChangeSettingsResource,
                        AutoTimerSettingsResource,
                        AutoTimerSimulateResource,
                        AutoTimerTestResource,
                        API_VERSION,
                    )
                except ImportError as ie:
                    pass
                else:
                    root = AutoTimerListAutoTimerResource()
                    root.putChild("parse", AutoTimerDoParseResource())
                    root.putChild("remove", AutoTimerRemoveAutoTimerResource())
                    root.putChild("edit", AutoTimerAddOrEditAutoTimerResource())
                    root.putChild("get", AutoTimerSettingsResource())
                    root.putChild("set", AutoTimerChangeSettingsResource())
                    root.putChild("simulate", AutoTimerSimulateResource())
                    root.putChild("test", AutoTimerTestResource())
                    addExternalChild(("autotimer", root, "AutoTimer-Plugin", API_VERSION))
                    doLog("[AutoTimer] Use OpenWebif")
コード例 #54
0
autotimer = AutoTimer()
autopoller = None

AUTOTIMER_VERSION = "4.3"
NOTIFICATIONDOMAIN = "AutoTimer"

#pragma mark - Help
try:
    from Plugins.SystemPlugins.MPHelp import registerHelp, XMLHelpReader
    from Tools.Directories import resolveFilename, SCOPE_PLUGINS
    reader = XMLHelpReader(resolveFilename(SCOPE_PLUGINS,
                                           "Extensions/AutoTimer/mphelp.xml"),
                           translate=_)
    autotimerHelp = registerHelp(*reader)
except Exception as e:
    doLog("[AutoTimer] Unable to initialize MPHelp:", e,
          "- Help not available!")
    autotimerHelp = None
#pragma mark -

# Notification-Domain
from Tools.Notifications import notificationQueue
try:
    notificationQueue.registerDomain(NOTIFICATIONDOMAIN,
                                     _("AutoTimer"),
                                     deferred_callable=True)
except Exception as e:
    print("[AutoTimer] Error registering Notification-Domain:", e)
# Autostart


def autostart(reason, **kwargs):
コード例 #55
0
	def readXml(self, **kwargs):
		if "xml_string" in kwargs:
			# reset time
			self.configMtime = -1
			# Parse Config
			try:
				configuration = cet_fromstring(kwargs["xml_string"])
			except:
				doLog("[AutoTimer] fatal error, the xml_string not read")
				return
		else:
			# Abort if no config found
			if not os.path.exists(XML_CONFIG):
				doLog("[AutoTimer] No configuration file present")
				return

			# Parse if mtime differs from whats saved
			mtime = os.path.getmtime(XML_CONFIG)
			if mtime == self.configMtime:
				doLog("[AutoTimer] No changes in configuration, won't parse")
				return

			# Save current mtime
			self.configMtime = mtime

			# Parse Config
			try:
				configuration = cet_parse(XML_CONFIG).getroot()
			except:
				try:
					if os.path.exists(XML_CONFIG + "_old"):
						os.rename(XML_CONFIG + "_old", XML_CONFIG + "_old(1)")
					os.rename(XML_CONFIG, XML_CONFIG + "_old")
					doLog("[AutoTimer] autotimer.xml is corrupt rename file to /etc/enigma2/autotimer.xml_old")
				except:
					pass
				if Standby.inStandby is None:
					AddPopup(_("The autotimer file (/etc/enigma2/autotimer.xml) is corrupt and could not be loaded.") + "\n" +_("A new and empty config was created. A backup of the config can be found here (/etc/enigma2/autotimer.xml_old)."), type = MessageBox.TYPE_ERROR, timeout = 0, id = "AutoTimerLoadFailed")

				self.timers = []
				self.defaultTimer = preferredAutoTimerComponent(
					0,		# Id
					"",		# Name
					"",		# Match
					True	# Enabled
				)

				try:
					self.writeXml()
					configuration = cet_parse(XML_CONFIG).getroot()
				except:
					doLog("[AutoTimer] fatal error, the autotimer.xml cannot create")
					return

		# Empty out timers and reset Ids
		del self.timers[:]
		self.defaultTimer.clear(-1, True)

		parseConfig(
			configuration,
			self.timers,
			configuration.get("version"),
			0,
			self.defaultTimer
		)
		self.uniqueTimerId = len(self.timers)