config: create config.misc, add configElementBoolean
[enigma2.git] / timer.py
1 import bisect
2 import time
3 from enigma import *
4
5 class TimerEntry:
6         EventPrepare = 0
7         EventStart   = 1
8         EventEnd     = 2
9         EventAbort   = 3
10         
11         StateWait    = 0
12         StatePrepare = 1
13         StateRunning = 2
14         StateEnded   = 3
15         
16         def __init__(self, begin, end):
17                 self.begin = begin
18                 self.prepare_time = 10
19                 self.end = end
20                 self.state = 0
21                 self.resetRepeated()
22                 
23         def resetRepeated(self):
24                 self.repeated = int(0)
25                 
26         def setRepeated(self, day):
27                 self.repeated |= (2 ** day)
28                 print "Repeated: " + str(self.repeated)
29                 
30         # update self.begin and self.end according to the self.repeated-flags
31         def processRepeated(self):
32                 print "ProcessRepeated"
33                 print time.strftime("%c", time.localtime(self.begin))
34                 print time.strftime("%c", time.localtime(self.end))
35                 if (self.repeated != 0):
36                         now = int(time.time()) + 1
37                         
38                         day = []
39                         flags = self.repeated
40                         for x in range(0, 7):
41                                 if (flags & 1 == 1):
42                                         day.append(0)
43                                         print "Day: " + str(x)
44                                 else:
45                                         day.append(1)
46                                 flags = flags >> 1
47
48                         print time.strftime("%c", time.localtime(now))
49                         print time.strftime("%c", time.localtime(self.begin))
50                         print time.strftime("%c", time.localtime(self.end))
51                         print str(time.localtime(self.begin).tm_wday)
52                         while ((day[time.localtime(self.begin).tm_wday] != 0) or ((day[time.localtime(self.begin).tm_wday] == 0) and self.end < now)):
53                                 print time.strftime("%c", time.localtime(self.begin))
54                                 print time.strftime("%c", time.localtime(self.end))
55                                 self.begin += 86400
56                                 self.end += 86400
57
58         def getTime(self):
59                 if self.state == self.StateWait:
60                         return self.begin - self.prepare_time
61                 elif self.state == self.StatePrepare:
62                         return self.begin
63                 else:
64                         return self.end 
65         
66         def __lt__(self, o):
67                 return self.getTime() < o.getTime()
68         
69         def activate(self, event):
70                 print "[timer.py] timer %s got activated (%d)!" % (self.description, event)
71
72 class Timer:
73
74         # the time between "polls". We do this because
75         # we want to account for time jumps etc.
76         # of course if they occur <100s before starting,
77         # it's not good. thus, you have to repoll when
78         # you change the time.
79         #
80         # this is just in case. We don't want the timer 
81         # hanging. we use this "edge-triggered-polling-scheme"
82         # anyway, so why don't make it a bit more fool-proof?
83         MaxWaitTime = 100
84
85         def __init__(self):
86                 self.timer_list = [ ]
87                 self.processed_timers = [ ]
88                 
89                 self.timer = eTimer()
90                 self.timer.timeout.get().append(self.calcNextActivation)
91                 self.lastActivation = time.time()
92                 
93                 self.calcNextActivation()
94         
95         def addTimerEntry(self, entry, noRecalc=0):
96                 entry.processRepeated()
97
98                 # we either go trough Prepare/Start/End-state if the timer is still running,
99                 # or skip it when it's alrady past the end.
100                 
101                 if entry.end > time.time():
102                         bisect.insort(self.timer_list, entry)
103                         if not noRecalc:
104                                 self.calcNextActivation()
105                 else:
106                         bisect.insort(self.processed_timers, entry)
107         
108         def setNextActivation(self, when):
109                 delay = int((when - time.time()) * 1000)
110                 print "[timer.py] next activation: %d (in %d ms)" % (when, delay)
111                 
112                 self.timer.start(delay, 1)
113                 self.next = when
114
115         def calcNextActivation(self):
116                 if self.lastActivation > time.time():
117                         print "[timer.py] timewarp - re-evaluating all processed timers."
118                         tl = self.processed_timers
119                         self.processed_timers = [ ]
120                         for x in tl:
121                                 self.addTimerEntry(x, noRecalc=1)
122                 
123                 self.processActivation()
124                 self.lastActivation = time.time()
125         
126                 min = int(time.time()) + self.MaxWaitTime
127                 
128                 # calculate next activation point
129                 if len(self.timer_list):
130                         w = self.timer_list[0].getTime()
131                         if w < min:
132                                 min = w
133                 
134                 self.setNextActivation(min)
135         
136         def timeChanged(self, timer):
137                 self.timer_list.remove(timer)
138
139                 self.addTimerEntry(timer)
140         
141         def doActivate(self, w):
142                 w.activate(w.state)
143                 self.timer_list.remove(w)
144
145                 w.state += 1
146                 if w.state < TimerEntry.StateEnded:
147                         bisect.insort(self.timer_list, w)
148                 else:
149                         if (w.repeated != 0):
150                                 w.processRepeated()
151                                 w.state = TimerEntry.StateWait
152                                 self.addTimerEntry(w)
153                         else:
154                                 bisect.insort(self.processed_timers, w)
155
156         
157         def processActivation(self):
158                 t = int(time.time()) + 1
159                 
160                 # we keep on processing the first entry until it goes into the future.
161                 while len(self.timer_list) and self.timer_list[0].getTime() < t:
162                         self.doActivate(self.timer_list[0])