[KiddyTimer] Add feature to automatically start KiddyTimer when
[enigma2-plugins.git] / kiddytimer / src / KTmain.py
1 from Components.Label import Label
2 from Components.ProgressBar import ProgressBar
3 from KTMultiPixmap import KTmultiPixmap
4 from Components.config import config, configfile
5 from Screens.ChoiceBox import ChoiceBox
6 from Screens.InputBox import PinInput
7 from Screens.MessageBox import MessageBox
8 from Screens.MinuteInput import MinuteInput
9 from Screens.Screen import Screen
10 from Screens import Standby
11 from Tools.BoundFunction import boundFunction
12 from Tools import Notifications
13 from Tools.Directories import resolveFilename, SCOPE_CONFIG
14 from enigma import ePoint, eTimer, eDVBLocalTimeHandler
15
16 from __init__ import _
17 import KTglob
18 import NavigationInstance
19 import time
20
21 PARAM_NONE = -1
22 PARAM_STOPTIMER = 1
23 PARAM_STARTTIMER = 2
24 PARAM_DISABLETIMER = 3
25 PARAM_ENABLETIMER = 4
26 PARAM_INCREASETIMER = 5
27 PARAM_DECREASETIMER = 6
28 PARAM_SETTIMER = 7
29 PARAM_ENABLETIMERONCE = 8
30 PARAM_RESETTIMER = 9
31
32 class KiddyTimerScreen(Screen):    
33
34     def __init__(self, session):
35         Screen.__init__(self, session)
36         self.skin = KTglob.SKIN
37         self.onShow.append(self.movePosition)
38         
39         self.skin_path = KTglob.plugin_path
40         
41         self["TimerGraph"] = KTmultiPixmap()
42         self["TimerText"] = Label(_("??:??"))
43         self["TimerSlider"] = ProgressBar()
44         self["TimerSliderText"] = Label(_("??:??"))
45         
46     def renderScreen(self):
47         self["TimerSlider"].setValue(int(kiddyTimer.remainingPercentage*100)) 
48         self["TimerGraph"].setPixmapNum(kiddyTimer.curImg)
49         self.sTimeLeft = KTglob.getTimeFromSeconds( (kiddyTimer.remainingTime + 59) , False ) # Add 59 Seconds to show one minute if less than 1 minute left...
50         self["TimerText"].setText(self.sTimeLeft)
51         self["TimerSliderText"].setText(self.sTimeLeft)
52
53         if config.plugins.KiddyTimer.timerStyle.value == "clock":
54             self["TimerGraph"].show()
55             self["TimerText"].show()
56             self["TimerSlider"].hide()    
57             self["TimerSliderText"].hide()
58         else:
59             self["TimerGraph"].hide()
60             self["TimerText"].hide()
61             self["TimerSlider"].show()
62             self["TimerSliderText"].show()
63
64     def movePosition(self):
65         if self.instance:
66             self.getPixmapList()
67             self.instance.move(ePoint(config.plugins.KiddyTimer.position_x.value, config.plugins.KiddyTimer.position_y.value))
68
69     def getPixmapList(self):
70         self.percentageList = []
71         for sPixmap in self["TimerGraph"].pixmapFiles:
72             i = int(sPixmap[-8:-4])
73             self.percentageList.append(i)
74       
75 ##############################################################################
76
77 class KiddyTimer():
78
79     def __init__(self):
80         self.session = None 
81         self.dialog = None
82         self.active = False
83
84         self.iServiceReference = None
85         self.curImg = 0
86
87         self.sessionStartTime = None
88
89         self.loopTimerStep = 1000
90         self.loopTimer = eTimer()
91         self.loopTimer.callback.append(self.calculateTimes)
92
93         self.observeTimerStep = 60000 # Check every minute, if the time to acitivate the timer has come
94         self.observeTimer = eTimer()
95         self.observeTimer.callback.append(self.observeTime)
96
97         config.misc.standbyCounter.addNotifier(self.enterStandby, initial_call = False)
98
99     def gotSession(self, session):
100         self.session = session
101         self.startTimer()   
102          
103     def enterStandby(self,configElement):
104         Standby.inStandby.onClose.append(self.endStandby)
105         self.stopTimer()    
106       
107     def endStandby(self):
108         self.sessionStartTime = None
109         self.startTimer()
110         
111     def startTimer(self,bForceStart=False,iRemainingSeconds=0):
112         curStartYear = time.localtime().tm_year 
113         if curStartYear < 2011: 
114             # Time has not yet been set from transponder, wait until it has been set
115             eDVBLocalTimeHandler.getInstance().m_timeUpdated.get().append(self.gotTime)
116         else:
117             bDoStandardInit = True
118             if bForceStart:
119                 self.enabled = True
120             else:
121                 self.enabled = config.plugins.KiddyTimer.enabled.value
122             if (self.enabled == True and self.timerHasToRun()) or bForceStart:   
123                 # This command may be double, just made to be sure, the observer is stopped when the real timer starts
124                 self.stopObserve()
125                 # Date of the current day
126                 self.currentDay = time.strftime("%d.%m.%Y" , time.localtime())
127                 # First check for Cheat- attempts by kids
128                 if self.detectCheatAttempt():
129                     config.plugins.KiddyTimer.remainingTime.value = 0
130                     configfile.save()
131                     bForceStart = True
132                 elif iRemainingSeconds > 0:
133                     self.resetTimer(setTime=iRemainingSeconds)
134                     bDoStandardInit = False
135                 elif self.currentDay != config.plugins.KiddyTimer.lastStartDay.getValue():
136                     self.resetTimer()
137                     bDoStandardInit = False
138                 if bDoStandardInit:             
139                     self.setCurrentDayTime()
140                     self.setSessionTime(config.plugins.KiddyTimer.remainingTime.getValue())
141                     self.setRemainingTime(self.sessionTime)
142                     self.setSessionStartTime()
143     
144                 self.setPluginStatus("RUNNING")
145                 self.toggleActiveState(True)
146                 if not bForceStart:
147                     self.askForActivation()
148                 else:
149                     self.startLoop()
150             else:
151                 if (self.enabled == True):
152                     self.startObserve()
153
154     def gotTime(self):
155         eDVBLocalTimeHandler.getInstance().m_timeUpdated.get().remove(self.gotTime)
156         self.startTimer()
157     
158     def stopTimer(self):
159         if self.active:
160             self.saveValues()
161         self.toggleActiveState(False)
162         self.stopLoop()
163         self.stopObserve()
164         self.setPluginStatus("SHUTDOWN")
165         self.iServiceReference = None
166         self.dialog = None
167                 
168     def resetTimer(self,**kwargs):
169         if "setTime" in kwargs.keys():
170             self.setCurrentDayTime(kwargs["setTime"])
171         else:            
172             self.setCurrentDayTime()
173         
174         self.setSessionTime(self.currentDayTime)
175         self.setRemainingTime(self.currentDayTime)
176         self.setSessionStartTime()
177
178     def timerHasToRun(self):
179         curStartTime = time.localtime()
180         iPluginStart = KTglob.getSecondsFromClock( [curStartTime[3],curStartTime[4]] )
181         iMonitorEnd = KTglob.getSecondsFromClock(config.plugins.KiddyTimer.monitorEndTime.getValue())  
182         iMonitorStart = KTglob.getSecondsFromClock(config.plugins.KiddyTimer.monitorStartTime.getValue())  
183         return (iPluginStart < iMonitorEnd) & (iPluginStart >= iMonitorStart)
184
185     def startLoop(self):
186         self.loopTimer.start(self.loopTimerStep,1)
187     
188     def stopLoop(self):
189         self.loopTimer.stop()
190     
191     def startObserve(self):
192         curStartTime = time.localtime()
193         iPluginStart = KTglob.getSecondsFromClock( [curStartTime[3],curStartTime[4]] )
194         iMonitorStart = KTglob.getSecondsFromClock(config.plugins.KiddyTimer.monitorStartTime.getValue())  
195
196         # If we are after Pluginstart, then sleep until next day
197         if (iPluginStart > iMonitorStart):
198             iMonitorStart += 86400
199
200         iObserveTimerStep = (iMonitorStart - iPluginStart)*1000 + 1000
201         print "[KiddyTimer] setting plugin idle for ms=", iObserveTimerStep
202         self.observeTimer.start(iObserveTimerStep, False)
203         
204     def stopObserve(self):
205         self.observeTimer.stop()
206     
207     def observeTime(self):
208         print "[KiddyTimer] Observer checking if plugin has to run"
209         if (self.timerHasToRun()):
210             self.stopObserve()
211             self.startTimer()
212     
213     def detectCheatAttempt(self):
214         sLastStatus = config.plugins.KiddyTimer.lastStatus.value
215         if (sLastStatus == "RUNNING"):
216             # cheat detected: RUNNING is NEVER a valid entry when checking.
217             Notifications.AddNotification(MessageBox, _("Cheat attempt detected. \nBox has not been shudown correctly. \nRemaining time was set to 0."), MessageBox.TYPE_WARNING, 0)
218             return True
219         else:
220             return False
221
222     def setPluginStatus(self,sStatus):
223         # Set values for detection of cheat attempts
224         config.plugins.KiddyTimer.lastStatus.value = sStatus
225         config.plugins.KiddyTimer.lastStatus.save()
226         configfile.save()
227
228     def askForActivation(self):
229         iTimeOut = config.plugins.KiddyTimer.activationDialogTimeout.getValue()
230         Notifications.AddNotificationWithCallback(self.callbackAskForActivation, MessageBox, _("Do you want to start the kiddytimer- plugin now."), MessageBox.TYPE_YESNO, iTimeOut)
231
232     def callbackAskForActivation(self, value):
233         if not value:
234             self.callbackParameter = PARAM_STOPTIMER
235             self.askForPIN()
236
237         self.startLoop()
238
239     def askForPIN(self):
240         self.session.openWithCallback( self.pinEntered, PinInput, pinList = [config.plugins.KiddyTimer.pin.getValue()], triesEntry = self.getTriesEntry(), title = _("Please enter the correct pin code"), windowTitle = _("Enter pin code"))
241     
242     def getTriesEntry(self):
243         return config.ParentalControl.retries.setuppin
244
245     def pinEntered(self, result):
246         if not result:
247             pass
248         else:
249             if self.callbackParameter == PARAM_STOPTIMER:
250                 self.stopTimer()      
251             elif self.callbackParameter == PARAM_DISABLETIMER:
252                 self.toggleEnabledState(False)
253             elif self.callbackParameter == PARAM_INCREASETIMER:
254                 self.session.openWithCallback(self.modifySessionTime, MinuteInput)
255             elif self.callbackParameter == PARAM_SETTIMER:
256                 self.session.openWithCallback(self.callbackSetTimer, MinuteInput)
257             elif self.callbackParameter == PARAM_RESETTIMER:
258                 self.resetTimer()
259             elif self.callbackParameter == PARAM_ENABLETIMERONCE:
260                 self.session.openWithCallback(self.callbackEnableTimerOnce, MinuteInput)
261
262     def setCurrentDayTime(self,iDayTime=PARAM_NONE):
263         if iDayTime == PARAM_NONE:
264             iDayTime = KTglob.getTodaysTimeInSeconds()
265         self.currentDayTime = iDayTime
266
267     def setSessionStartTime(self):
268         self.sessionStartTime = time.localtime()
269                 
270     def modifySessionTime(self, iMinutes):
271         iSeconds = iMinutes * 60
272         if self.callbackParameter == PARAM_INCREASETIMER:
273             iSeconds += self.sessionTime
274         else:
275             iSeconds = self.sessionTime - iSeconds 
276         self.setSessionTime(iSeconds)
277         
278
279     def setSessionTime(self, iSeconds):
280         self.sessionTime = iSeconds
281         if self.sessionTime > self.currentDayTime:
282             self.setCurrentDayTime(self.sessionTime)
283         if self.sessionTime < 0:
284             self.sessionTime = 0
285
286     def setRemainingTime(self,iRemaining):
287         if iRemaining < 0:
288             iRemaining = 0
289         self.remainingTime = iRemaining
290         if self.currentDayTime > 0:
291             self.remainingPercentage = iRemaining / self.currentDayTime
292         else:
293             self.remainingPercentage = 0
294
295     def callbackSetTimer(self, iMinutes):
296         iSeconds = iMinutes * 60
297         self.resetTimer(setTime=iSeconds)
298                 
299     def callbackEnableTimerOnce(self, iMinutes):
300         iSeconds = iMinutes * 60
301         if iSeconds > 0:
302             #If timer is active: stop it first to prohibit conflicts
303             if self.active:
304                 self.stopTimer()
305             self.startTimer(True, iSeconds)
306     
307     def toggleActiveState(self , bStatus):
308         # Initialize dialog
309         if self.dialog == None and bStatus:
310             self.dialog = self.session.instantiateDialog(KiddyTimerScreen)
311         self.active = bStatus
312         if bStatus == True:
313             self.dialog.show()
314         else:
315             if self.dialog != None:
316                 self.dialog.hide()
317
318     def toggleEnabledState(self, bStatus):
319         config.plugins.KiddyTimer.enabled.value = bStatus
320         self.enabled = bStatus
321         config.plugins.KiddyTimer.enabled.save()
322         configfile.save()
323         if self.enabled:
324             self.startTimer()
325         else:
326             self.stopTimer()
327
328     def calculateTimes(self):
329         self.stopLoop()
330         if self.active == True and self.timerHasToRun():
331             odtEnd = time.mktime(time.localtime())
332             iDiff = odtEnd - time.mktime(self.sessionStartTime)
333             iRemaining = self.sessionTime - iDiff
334             if iRemaining < 0:
335                 iRemaining = 0
336             self.remainingTime = iRemaining
337             if self.currentDayTime > 0:
338                 self.remainingPercentage = iRemaining / self.currentDayTime
339             else:
340                 self.remainingPercentage = 0
341
342             self.setImageNumber()
343             
344             if self.remainingTime == 0:
345                 self.iServiceReference = NavigationInstance.instance.getCurrentlyPlayingServiceReference()
346                 NavigationInstance.instance.stopService()
347             self.dialog.renderScreen()
348             self.startLoop()
349         else:
350             self.stopTimer()
351
352     def setImageNumber(self):
353         iCurPercent = int( self.remainingPercentage * 1000 )
354         iCount = 0
355         for iPercent in self.dialog.percentageList:
356            if iCurPercent <= iPercent:
357                iCount = iCount + 1
358         iCount = iCount - 1
359         if iCount < 0:
360             iCount = 0
361         self.curImg = iCount
362         
363     def saveValues(self):
364         if hasattr(self,"currentDay"):
365             config.plugins.KiddyTimer.lastStartDay.value = self.currentDay
366             config.plugins.KiddyTimer.lastStartDay.save()
367         if hasattr(self,"remainingTime"):
368             config.plugins.KiddyTimer.remainingTime.value = int(self.remainingTime)
369             config.plugins.KiddyTimer.remainingTime.save()
370
371     def showExtensionsMenu(self):
372         keyList = []
373         if self.enabled:
374             if self.active:
375                 keyList.append((_("Stop KiddyTimer (this session only)"),PARAM_STOPTIMER))
376                 keyList.append((_("Increase remaining time"),PARAM_INCREASETIMER))
377                 keyList.append((_("Decrease remaining time"),PARAM_DECREASETIMER))
378                 keyList.append((_("Set remaining time"),PARAM_SETTIMER))
379                 keyList.append((_("Reset todays remaining time"),PARAM_RESETTIMER))
380             else:
381                 keyList.append((_("Start KiddyTimer"),PARAM_STARTTIMER))
382             keyList.append((_("Enable KiddyTimer for x minutes"),PARAM_ENABLETIMERONCE))
383             keyList.append((_("Disable KiddyTimer"),PARAM_DISABLETIMER))
384         else:
385             keyList.append((_("Enable KiddyTimer"),PARAM_ENABLETIMER))
386             keyList.append((_("Enable KiddyTimer for x minutes"),PARAM_ENABLETIMERONCE))
387         self.session.openWithCallback(self.DoSelectionExtensionsMenu,ChoiceBox,_("Please select your KiddyTimer- option"),keyList)
388         
389     def DoSelectionExtensionsMenu(self,answer):
390         self.callbackParameter = PARAM_NONE
391         if answer is None:
392             pass
393         elif answer[1] in [PARAM_DISABLETIMER,PARAM_STOPTIMER,PARAM_INCREASETIMER,PARAM_SETTIMER,PARAM_ENABLETIMERONCE,PARAM_RESETTIMER]:
394             self.callbackParameter = answer[1]
395             self.askForPIN()
396         elif  answer[1] == PARAM_STARTTIMER:
397             self.startTimer()
398         elif  answer[1] == PARAM_ENABLETIMER: 
399             self.toggleEnabledState(True)
400         elif answer[1] == PARAM_DECREASETIMER:
401             self.session.openWithCallback(self.modifySessionTime, MinuteInput)
402         else:
403             self.session.open(MessageBox,_("Invalid selection"), MessageBox.TYPE_ERROR, 5)
404
405 # Assign global variable kiddyTimer
406 kiddyTimer = KiddyTimer()