aboutsummaryrefslogtreecommitdiff
path: root/lib/python/Components/TimerSanityCheck.py
blob: 10dc31bd810dd614e7aeb5caa83c4e6b92f81107 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
import NavigationInstance
from time import localtime
from ServiceReference import ServiceReference
from enigma import iServiceInformation, eServiceCenter, eServiceReference

class TimerSanityCheck:
	def __init__(self, timerlist, newtimer=None):
		print "sanitycheck"
		self.timerlist = timerlist
		self.newtimer = newtimer
		self.simultimer = []
		self.rep_eventlist = []
		self.nrep_eventlist = []
		self.bflag = 1
		self.eflag = -1

	def check(self, ext_timer=1):
		print "check"
		if ext_timer != 1:
			self.newtimer = ext_timer
		if self.newtimer is None:
			self.simultimer = []
		else:
			self.simultimer = [ self.newtimer ]
		return self.checkTimerlist()

	def getSimulTimerList(self):
		return self.simultimer

	def doubleCheck(self):
		if self.newtimer is not None and self.newtimer.service_ref.ref.valid():
			self.simultimer = [ self.newtimer ]
			for timer in self.timerlist:
				if (timer == self.newtimer):
					return True
				else:
					if timer.begin == self.newtimer.begin:
						getUnsignedDataRef1 = timer.service_ref.ref.getUnsignedData
						getUnsignedDataRef2 = self.newtimer.service_ref.ref.getUnsignedData
						for x in range(1,5):
							if getUnsignedDataRef1(x) != getUnsignedDataRef2(x):
								break;
						else:
							return True
		return False

	def checkTimerlist(self, ext_timer=1):
		#with special service for external plugins
		# Entries in eventlist
		# timeindex
		# BeginEndFlag 1 for begin, -1 for end
		# index -1 for the new Timer, 0..n index of the existing timers
		# count of running timers

		serviceHandler = eServiceCenter.getInstance()
		print "checkTimerlist"
# create a list with all start and end times
# split it into recurring and singleshot timers

##################################################################################
# process the new timer
		self.rep_eventlist = []
		self.nrep_eventlist = []
		if ext_timer != 1:
			self.newtimer = ext_timer
		if (self.newtimer is not None) and (not self.newtimer.disabled):
			if not self.newtimer.service_ref.ref.valid():
				return False
			rflags = self.newtimer.repeated
			rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
			if rflags:
				begin = self.newtimer.begin % 86400 # map to first day
				while rflags: # then arrange on the week
					if rflags & 1:
						self.rep_eventlist.append((begin, -1))
					begin += 86400
					rflags >>= 1
			else:
				self.nrep_eventlist.extend([(self.newtimer.begin,self.bflag,-1),(self.newtimer.end,self.eflag,-1)])

##################################################################################
# now process existing timers
		idx = 0
		for timer in self.timerlist:
			if (timer != self.newtimer) and (not timer.disabled):
				if timer.repeated:
					rflags = timer.repeated
					rflags = ((rflags & 0x7F)>> 3)|((rflags & 0x07)<<4)
					begin = timer.begin % 86400 # map all to first day
					while rflags:
						if rflags & 1:
							self.rep_eventlist.append((begin, idx))
						begin += 86400
						rflags >>= 1
				else:
					self.nrep_eventlist.extend([(timer.begin,self.bflag,idx),(timer.end,self.eflag,idx)])
			idx += 1

################################################################################
# journalize timer repeations
		if self.nrep_eventlist:
			interval_begin = min(self.nrep_eventlist)[0]
			interval_end = max(self.nrep_eventlist)[0]
			offset_0 = interval_begin - (interval_begin % 604800)
			weeks = (interval_end - offset_0) / 604800
			if ((interval_end - offset_0) % 604800):
				weeks += 1
			for cnt in range(weeks):
				for event in self.rep_eventlist:
					if event[1] == -1: # -1 is the identifier of the changed timer
						event_begin = self.newtimer.begin
						event_end = self.newtimer.end
					else:
						event_begin = self.timerlist[event[1]].begin
						event_end = self.timerlist[event[1]].end
					new_event_begin = event[0] + offset_0 + (cnt * 604800)
					# summertime correction
					new_lth = localtime(new_event_begin).tm_hour
					new_event_begin += 3600 * (localtime(event_begin).tm_hour - new_lth)
					new_event_end = new_event_begin + (event_end - event_begin)
					if event[1] == -1:
						if new_event_begin >= self.newtimer.begin: # is the soap already running?
							self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
					else:
						if new_event_begin >= self.timerlist[event[1]].begin: # is the soap already running?
							self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])
		else:
			offset_0 = 345600 # the Epoch begins on Thursday
			weeks = 2 # test two weeks to take care of Sunday-Monday transitions
			for cnt in range(weeks):
				for event in self.rep_eventlist:
					if event[1] == -1: # -1 is the identifier of the changed timer
						event_begin = self.newtimer.begin
						event_end = self.newtimer.end
					else:
						event_begin = self.timerlist[event[1]].begin
						event_end = self.timerlist[event[1]].end
					new_event_begin = event[0] + offset_0 + (cnt * 604800)
					new_event_end = new_event_begin + (event_end - event_begin)
					self.nrep_eventlist.extend([(new_event_begin, self.bflag, event[1]),(new_event_end, self.eflag, event[1])])

################################################################################
# order list chronological
		self.nrep_eventlist.sort()

##################################################################################
# detect overlapping timers and overlapping times
		fakeRecList = []
		ConflictTimer = None
		ConflictTunerType = None
		newTimerTunerType = None
		cnt = 0
		idx = 0
		overlaplist = []
		for event in self.nrep_eventlist:
			cnt += event[1]
			if event[2] == -1: # new timer
				timer = self.newtimer
			else:
				timer = self.timerlist[event[2]]
			if event[1] == self.bflag:
				tunerType = [ ]
				fakeRecService = NavigationInstance.instance.recordService(timer.service_ref, True)
				if fakeRecService:
					fakeRecResult = fakeRecService.start(True)
				else:
					fakeRecResult = -1
				if not fakeRecResult: # tune okay
					feinfo = fakeRecService.frontendInfo().getFrontendData()
					tunerType.append(feinfo.get("tuner_type"))
				else: # tune failed.. so we must go another way to get service type (DVB-S, DVB-T, DVB-C)

					def getServiceType(ref): # helper function to get a service type of a service reference
						serviceInfo = serviceHandler.info(ref)
						serviceInfo = serviceInfo and serviceInfo.getInfoObject(ref, iServiceInformation.sTransponderData)
						if serviceInfo:
							return { "Satellite" : "DVB-S", "Cable" : "DVB-C", "Terrestrial" : "DVB-T"}[serviceInfo["type"]]

					ref = timer.service_ref.ref
					if ref.flags & eServiceReference.isGroup: # service group ?
						serviceList = serviceHandler.list(ref) # get all alternative services
						if serviceList:
							for ref in serviceList.getContent("R"): # iterate over all group service references
								type = getServiceType(ref)
								if not type in tunerType: # just add single time
									tunerType.append(type) 
					else:
						tunerType.append(getServiceType(ref))

				if event[2] == -1: # new timer
					newTimerTunerType = tunerType
				overlaplist.append((fakeRecResult, timer, tunerType))
				fakeRecList.append((timer, fakeRecService))
				if fakeRecResult:
					if ConflictTimer is None: # just take care of the first conflict
						ConflictTimer = timer
						ConflictTunerType = tunerType
			elif event[1] == self.eflag:
				for fakeRec in fakeRecList:
					if timer == fakeRec[0] and fakeRec[1]:
						NavigationInstance.instance.stopRecordService(fakeRec[1])
						fakeRecList.remove(fakeRec)
				fakeRec = None
				for entry in overlaplist:
					if entry[1] == timer:
						overlaplist.remove(entry)
			else:
				print "Bug: unknown flag!"
			self.nrep_eventlist[idx] = (event[0],event[1],event[2],cnt,overlaplist[:]) # insert a duplicate into current overlaplist
			idx += 1

		if ConflictTimer is None: # no conflict found :)
			return True

##################################################################################
# we have detected a conflict, now we must figure out the involved timers

		if self.newtimer is not None: # new timer?
			if self.newtimer is not ConflictTimer: # the new timer is not the conflicting timer?
				for event in self.nrep_eventlist:
					if len(event[4]) > 1: # entry in overlaplist of this event??
						kt = False
						nt = False
						for entry in event[4]:
							if entry[1] is ConflictTimer:
								kt = True
							if entry[1] is self.newtimer:
								nt = True
						if nt and kt:
							ConflictTimer = self.newtimer
							ConflictTunerType = newTimerTunerType
							break

		self.simultimer = [ ConflictTimer ]
		for event in self.nrep_eventlist:
			if len(event[4]) > 1: # entry in overlaplist of this event??
				for entry in event[4]:
					if entry[1] is ConflictTimer:
						break
				else:
					continue
				for entry in event[4]:
					if not entry[1] in self.simultimer:
						for x in entry[2]:
							if x in ConflictTunerType:
								self.simultimer.append(entry[1])
								break

		if len(self.simultimer) < 2:
			print "Bug: unknown Conflict!"

		return False # conflict detected!