aboutsummaryrefslogtreecommitdiff
path: root/timer.py
blob: 525014fe719460591bf6ab7a2b5eadab6992692c (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
import bisect
import time
from enigma import *

class TimerEntry:
	EventPrepare = 0
	EventStart   = 1
	EventEnd     = 2
	EventAbort   = 3
	
	StateWait    = 0
	StatePrepare = 1
	StateRunning = 2
	StateEnded   = 3
	
	def __init__(self, begin, end):
		self.begin = begin
		self.prepare_time = 10
		self.end = end
		self.state = 0
		self.resetRepeated()
		
	def resetRepeated(self):
		self.repeated = int(0)
		
	def setRepeated(self, day):
		self.repeated |= (2 ** day)
		print "Repeated: " + str(self.repeated)
		
	# update self.begin and self.end according to the self.repeated-flags
	def processRepeated(self):
		if (self.repeated != 0):
			now = time.time()
			
			day = []
			flags = self.repeated
			for x in range(0, 7):
				if (flags & 1 == 1):
					day.append(0)
				else:
					day.append(1)
				flags = flags >> 1

			while ((day[time.localtime(self.begin).tm_wday] != 0) and (self.end > now)):
				self.begin += 86400
				self.end += 86400
			
					
		
	def getTime(self):
		if self.state == self.StateWait:
			return self.begin - self.prepare_time
		elif self.state == self.StatePrepare:
			return self.begin
		else:
			return self.end 
	
	def __lt__(self, o):
		return self.getTime() < o.getTime()
	
	def activate(self, event):
		print "[timer.py] timer %s got activated (%d)!" % (self.description, event)

class Timer:

	# the time between "polls". We do this because
	# we want to account for time jumps etc.
	# of course if they occur <100s before starting,
	# it's not good. thus, you have to repoll when
	# you change the time.
	#
	# this is just in case. We don't want the timer 
	# hanging. we use this "edge-triggered-polling-scheme"
	# anyway, so why don't make it a bit more fool-proof?
	MaxWaitTime = 100

	def __init__(self):
		self.timer_list = [ ]
		self.processed_timers = [ ]
		
		self.timer = eTimer()
		self.timer.timeout.get().append(self.calcNextActivation)
		self.lastActivation = time.time()
		
		self.calcNextActivation()
	
	def addTimerEntry(self, entry, noRecalc=0):
		entry.processRepeated()

		# we either go trough Prepare/Start/End-state if the timer is still running,
		# or skip it when it's alrady past the end.
		
		if entry.end > time.time():
			bisect.insort(self.timer_list, entry)
			if not noRecalc:
				self.calcNextActivation()
		else:
			bisect.insort(self.processed_timers, entry)
	
	def setNextActivation(self, when):
		delay = int((when - time.time()) * 1000)
		print "[timer.py] next activation: %d (in %d ms)" % (when, delay)
		
		self.timer.start(delay, 1)
		self.next = when

	def calcNextActivation(self):
		if self.lastActivation > time.time():
			print "[timer.py] timewarp - re-evaluating all processed timers."
			tl = self.processed_timers
			self.processed_timers = [ ]
			for x in tl:
				self.addTimerEntry(x, noRecalc=1)
		
		self.processActivation()
		self.lastActivation = time.time()
	
		min = int(time.time()) + self.MaxWaitTime
		
		# calculate next activation point
		if len(self.timer_list):
			w = self.timer_list[0].getTime()
			if w < min:
				min = w
		
		self.setNextActivation(min)
	
	def timeChanged(self, timer):
		self.timer_list.remove(timer)
		self.addTimerEntry(timer)
	
	def doActivate(self, w):
		w.activate(w.state)
		self.timer_list.remove(w)
		w.state += 1
		if w.state < TimerEntry.StateEnded:
			bisect.insort(self.timer_list, w)
		else:
			bisect.insort(self.processed_timers, w)
	
	def processActivation(self):
		t = int(time.time()) + 1
		
		# we keep on processing the first entry until it goes into the future.
		while len(self.timer_list) and self.timer_list[0].getTime() < t:
			self.doActivate(self.timer_list[0])