timer fixes and improvements by adenin
[vuplus_dvbapp] / mytest.py
1 import eConsoleImpl
2 import eBaseImpl
3 import enigma
4 enigma.eTimer = eBaseImpl.eTimer
5 enigma.eSocketNotifier = eBaseImpl.eSocketNotifier
6 enigma.eConsoleAppContainer = eConsoleImpl.eConsoleAppContainer
7
8 from Tools.Profile import profile, profile_final
9
10 profile("PYTHON_START")
11
12 from enigma import runMainloop, eDVBDB, eTimer, quitMainloop, \
13         getDesktop, ePythonConfigQuery, eAVSwitch, eServiceEvent
14 from tools import *
15
16 profile("LANGUAGE")
17
18 from Components.Language import language
19
20 def setEPGLanguage():
21         print "language set to", language.getLanguage()
22         eServiceEvent.setEPGLanguage(language.getLanguage())
23
24 language.addCallback(setEPGLanguage)
25
26 from traceback import print_exc
27 profile("LOAD:InfoBar")
28 import Screens.InfoBar
29 from Screens.SimpleSummary import SimpleSummary
30
31 from sys import stdout, exc_info
32
33 profile("ParentalControl")
34 from Components.ParentalControl import InitParentalControl
35 InitParentalControl()
36
37 profile("LOAD:Navigation")
38 from Navigation import Navigation
39
40 profile("LOAD:skin")
41 from skin import readSkin
42
43 profile("LOAD:Tools")
44 from Tools.Directories import InitFallbackFiles, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
45 from Components.config import config, configfile, ConfigText, ConfigYesNo
46 InitFallbackFiles()
47
48 profile("ReloadProfiles")
49 eDVBDB.getInstance().reloadBouquets()
50
51 config.misc.radiopic = ConfigText(default = resolveFilename(SCOPE_SKIN_IMAGE)+"radio.mvi")
52 config.misc.isNextRecordTimerAfterEventActionAuto = ConfigYesNo(default=False)
53
54 profile("Twisted")
55 try:
56         import twisted.python.runtime
57         twisted.python.runtime.platform.supportsThreads = lambda: False
58
59         import e2reactor
60         e2reactor.install()
61
62         from twisted.internet import reactor
63
64         def runReactor():
65                 reactor.run(installSignalHandlers=False)
66 except ImportError:
67         print "twisted not available"
68         def runReactor():
69                 runMainloop()
70
71 profile("LOAD:Plugin")
72
73 # initialize autorun plugins and plugin menu entries
74 from Components.PluginComponent import plugins
75
76 profile("LOAD:Wizard")
77 from Screens.Wizard import wizardManager
78 from Screens.DefaultWizard import *
79 from Screens.ImageWizard import *
80 from Screens.StartWizard import *
81 from Screens.TutorialWizard import *
82 import Screens.Rc
83 from Tools.BoundFunction import boundFunction
84 from Plugins.Plugin import PluginDescriptor
85
86 profile("misc")
87 had = dict()
88
89 def dump(dir, p = ""):
90         if isinstance(dir, dict):
91                 for (entry, val) in dir.items():
92                         dump(val, p + "(dict)/" + entry)
93         if hasattr(dir, "__dict__"):
94                 for name, value in dir.__dict__.items():
95                         if not had.has_key(str(value)):
96                                 had[str(value)] = 1
97                                 dump(value, p + "/" + str(name))
98                         else:
99                                 print p + "/" + str(name) + ":" + str(dir.__class__) + "(cycle)"
100         else:
101                 print p + ":" + str(dir)
102
103 # + ":" + str(dir.__class__)
104
105 # display
106
107 profile("LOAD:ScreenGlobals")
108 from Screens.Globals import Globals
109 from Screens.SessionGlobals import SessionGlobals
110 from Screens.Screen import Screen
111
112 profile("Screen")
113 Screen.global_screen = Globals()
114
115 # Session.open:
116 # * push current active dialog ('current_dialog') onto stack
117 # * call execEnd for this dialog
118 #   * clear in_exec flag
119 #   * hide screen
120 # * instantiate new dialog into 'current_dialog'
121 #   * create screens, components
122 #   * read, apply skin
123 #   * create GUI for screen
124 # * call execBegin for new dialog
125 #   * set in_exec
126 #   * show gui screen
127 #   * call components' / screen's onExecBegin
128 # ... screen is active, until it calls 'close'...
129 # Session.close:
130 # * assert in_exec
131 # * save return value
132 # * start deferred close handler ('onClose')
133 # * execEnd
134 #   * clear in_exec
135 #   * hide screen
136 # .. a moment later:
137 # Session.doClose:
138 # * destroy screen
139
140 class Session:
141         def __init__(self, desktop = None, summary_desktop = None, navigation = None):
142                 self.desktop = desktop
143                 self.summary_desktop = summary_desktop
144                 self.nav = navigation
145                 self.delay_timer = eTimer()
146                 self.delay_timer.callback.append(self.processDelay)
147
148                 self.current_dialog = None
149
150                 self.dialog_stack = [ ]
151                 self.summary_stack = [ ]
152                 self.summary = None
153
154                 self.in_exec = False
155
156                 self.screen = SessionGlobals(self)
157
158                 for p in plugins.getPlugins(PluginDescriptor.WHERE_SESSIONSTART):
159                         p(reason=0, session=self)
160
161         def processDelay(self):
162                 callback = self.current_dialog.callback
163
164                 retval = self.current_dialog.returnValue
165
166                 if self.current_dialog.isTmp:
167                         self.current_dialog.doClose()
168 #                       dump(self.current_dialog)
169                         del self.current_dialog
170                 else:
171                         del self.current_dialog.callback
172
173                 self.popCurrent()
174                 if callback is not None:
175                         callback(*retval)
176
177         def execBegin(self, first=True, do_show = True):
178                 assert not self.in_exec 
179                 self.in_exec = True
180                 c = self.current_dialog
181
182                 # when this is an execbegin after a execend of a "higher" dialog,
183                 # popSummary already did the right thing.
184                 if first:
185                         self.pushSummary()
186                         summary = c.createSummary() or SimpleSummary
187                         self.summary = self.instantiateSummaryDialog(summary, c)
188                         self.summary.show()
189                         c.addSummary(self.summary)
190
191                 c.execBegin()
192
193                 # when execBegin opened a new dialog, don't bother showing the old one.
194                 if c == self.current_dialog and do_show:
195                         c.show()
196
197         def execEnd(self, last=True):
198                 assert self.in_exec
199                 self.in_exec = False
200
201                 self.current_dialog.execEnd()
202                 self.current_dialog.hide()
203
204                 if last:
205                         self.current_dialog.removeSummary(self.summary)
206                         self.popSummary()
207
208         def create(self, screen, arguments, **kwargs):
209                 # creates an instance of 'screen' (which is a class)
210                 try:
211                         return screen(self, *arguments, **kwargs)
212                 except:
213                         errstr = "Screen %s(%s, %s): %s" % (str(screen), str(arguments), str(kwargs), exc_info()[0])
214                         print errstr
215                         print_exc(file=stdout)
216                         quitMainloop(5)
217
218         def instantiateDialog(self, screen, *arguments, **kwargs):
219                 return self.doInstantiateDialog(screen, arguments, kwargs, self.desktop)
220
221         def deleteDialog(self, screen):
222                 screen.hide()
223                 screen.doClose()
224
225         def instantiateSummaryDialog(self, screen, *arguments, **kwargs):
226                 return self.doInstantiateDialog(screen, arguments, kwargs, self.summary_desktop)
227
228         def doInstantiateDialog(self, screen, arguments, kwargs, desktop):
229                 # create dialog
230
231                 try:
232                         dlg = self.create(screen, arguments, **kwargs)
233                 except:
234                         print 'EXCEPTION IN DIALOG INIT CODE, ABORTING:'
235                         print '-'*60
236                         print_exc(file=stdout)
237                         quitMainloop(5)
238                         print '-'*60
239
240                 if dlg is None:
241                         return
242
243                 # read skin data
244                 readSkin(dlg, None, dlg.skinName, desktop)
245
246                 # create GUI view of this dialog
247                 assert desktop is not None
248
249                 dlg.setDesktop(desktop)
250                 dlg.applySkin()
251
252                 return dlg
253
254         def pushCurrent(self):
255                 if self.current_dialog is not None:
256                         self.dialog_stack.append((self.current_dialog, self.current_dialog.shown))
257                         self.execEnd(last=False)
258
259         def popCurrent(self):
260                 if len(self.dialog_stack):
261                         (self.current_dialog, do_show) = self.dialog_stack.pop()
262                         self.execBegin(first=False, do_show=do_show)
263                 else:
264                         self.current_dialog = None
265
266         def execDialog(self, dialog):
267                 self.pushCurrent()
268                 self.current_dialog = dialog
269                 self.current_dialog.isTmp = False
270                 self.current_dialog.callback = None # would cause re-entrancy problems.
271                 self.execBegin()
272
273         def openWithCallback(self, callback, screen, *arguments, **kwargs):
274                 dlg = self.open(screen, *arguments, **kwargs)
275                 dlg.callback = callback
276                 return dlg
277
278         def open(self, screen, *arguments, **kwargs):
279                 if len(self.dialog_stack) and not self.in_exec:
280                         raise "modal open are allowed only from a screen which is modal!"
281                         # ...unless it's the very first screen.
282
283                 self.pushCurrent()
284                 dlg = self.current_dialog = self.instantiateDialog(screen, *arguments, **kwargs)
285                 dlg.isTmp = True
286                 dlg.callback = None
287                 self.execBegin()
288                 return dlg
289
290         def close(self, screen, *retval):
291                 if not self.in_exec:
292                         print "close after exec!"
293                         return
294
295                 # be sure that the close is for the right dialog!
296                 # if it's not, you probably closed after another dialog
297                 # was opened. this can happen if you open a dialog
298                 # onExecBegin, and forget to do this only once.
299                 # after close of the top dialog, the underlying will
300                 # gain focus again (for a short time), thus triggering
301                 # the onExec, which opens the dialog again, closing the loop.
302                 assert screen == self.current_dialog
303
304                 self.current_dialog.returnValue = retval
305                 self.delay_timer.start(0, 1)
306                 self.execEnd()
307
308         def pushSummary(self):
309                 if self.summary is not None:
310                         self.summary.hide()
311                 self.summary_stack.append(self.summary)
312                 self.summary = None
313
314         def popSummary(self):
315                 if self.summary is not None:
316                         self.summary.doClose()
317                 self.summary = self.summary_stack.pop()
318                 if self.summary is not None:
319                         self.summary.show()
320
321 profile("Standby,PowerKey")
322 import Screens.Standby
323 from Screens.Menu import MainMenu, mdom
324 from GlobalActions import globalActionMap
325
326 class PowerKey:
327         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
328
329         def __init__(self, session):
330                 self.session = session
331                 globalActionMap.actions["power_down"]=self.powerdown
332                 globalActionMap.actions["power_up"]=self.powerup
333                 globalActionMap.actions["power_long"]=self.powerlong
334                 globalActionMap.actions["deepstandby"]=self.shutdown # frontpanel long power button press
335                 self.standbyblocked = 1
336
337         def MenuClosed(self, *val):
338                 self.session.infobar = None
339
340         def shutdown(self):
341                 print "PowerOff - Now!"
342                 if not Screens.Standby.inTryQuitMainloop and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
343                         self.session.open(Screens.Standby.TryQuitMainloop, 1)
344
345         def powerlong(self):
346                 self.standbyblocked = 1
347                 action = config.usage.on_long_powerpress.value
348                 if action == "shutdown":
349                         self.shutdown()
350                 elif action == "show_menu":
351                         print "Show shutdown Menu"
352                         root = mdom.getroot()
353                         for x in root.findall("menu"):
354                                 y = x.find("id")
355                                 if y is not None:
356                                         id = y.get("val")
357                                         if id and id == "shutdown":
358                                                 self.session.infobar = self
359                                                 menu_screen = self.session.openWithCallback(self.MenuClosed, MainMenu, x)
360                                                 menu_screen.setTitle(_("Standby / Restart"))
361                                                 return
362
363         def powerdown(self):
364                 self.standbyblocked = 0
365
366         def powerup(self):
367                 if self.standbyblocked == 0:
368                         self.standbyblocked = 1
369                         self.standby()
370
371         def standby(self):
372                 if not Screens.Standby.inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
373                         self.session.open(Screens.Standby.Standby)
374
375 profile("Scart")
376 from Screens.Scart import Scart
377
378 class AutoScartControl:
379         def __init__(self, session):
380                 self.force = False
381                 self.current_vcr_sb = eAVSwitch.getInstance().getVCRSlowBlanking()
382                 if self.current_vcr_sb and config.av.vcrswitch.value:
383                         self.scartDialog = session.instantiateDialog(Scart, True)
384                 else:
385                         self.scartDialog = session.instantiateDialog(Scart, False)
386                 config.av.vcrswitch.addNotifier(self.recheckVCRSb)
387                 eAVSwitch.getInstance().vcr_sb_notifier.get().append(self.VCRSbChanged)
388
389         def recheckVCRSb(self, configElement):
390                 self.VCRSbChanged(self.current_vcr_sb)
391
392         def VCRSbChanged(self, value):
393                 #print "vcr sb changed to", value
394                 self.current_vcr_sb = value
395                 if config.av.vcrswitch.value or value > 2:
396                         if value:
397                                 self.scartDialog.showMessageBox()
398                         else:
399                                 self.scartDialog.switchToTV()
400
401 profile("Load:CI")
402 from enigma import eDVBCIInterfaces
403 from Screens.Ci import CiHandler
404
405 profile("Load:VolumeControl")
406 from Components.VolumeControl import VolumeControl
407
408 def runScreenTest():
409         profile("readPluginList")
410         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
411
412         profile("Init:Session")
413         nav = Navigation(config.misc.isNextRecordTimerAfterEventActionAuto.value)
414         session = Session(desktop = getDesktop(0), summary_desktop = getDesktop(1), navigation = nav)
415
416         CiHandler.setSession(session)
417
418         screensToRun = [ ]
419
420         for p in plugins.getPlugins(PluginDescriptor.WHERE_WIZARD):
421                 screensToRun.append(p.__call__)
422
423         profile("wizards")
424         screensToRun += wizardManager.getWizards()
425
426         screensToRun.append((100, Screens.InfoBar.InfoBar))
427
428         screensToRun.sort()
429
430         ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
431
432 #       eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
433 #               ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
434 #                       ["PREMIERE"], #provider_list,
435 #                       [] #caid_list
436 #               ));
437
438         def runNextScreen(session, screensToRun, *result):
439                 if result:
440                         quitMainloop(*result)
441                         return
442
443                 screen = screensToRun[0][1]
444
445                 if len(screensToRun):
446                         session.openWithCallback(boundFunction(runNextScreen, session, screensToRun[1:]), screen)
447                 else:
448                         session.open(screen)
449
450         runNextScreen(session, screensToRun)
451
452         profile("Init:VolumeControl")
453         vol = VolumeControl(session)
454         profile("Init:PowerKey")
455         power = PowerKey(session)
456
457         # we need session.scart to access it from within menu.xml
458         session.scart = AutoScartControl(session)
459
460         profile("RunReactor")
461         profile_final()
462         runReactor()
463
464         profile("wakeup")
465         from time import time
466         from Tools.DreamboxHardware import setFPWakeuptime, getFPWakeuptime
467         #get currentTime
468         nowTime = time()
469         wakeupList = [
470                 x for x in ((session.nav.RecordTimer.getNextRecordingTime(), 0, session.nav.RecordTimer.isNextRecordAfterEventActionAuto()),
471                                         (session.nav.RecordTimer.getNextZapTime(), 1),
472                                         (plugins.getNextWakeupTime(), 2))
473                 if x[0] != -1
474         ]
475         wakeupList.sort()
476         recordTimerWakeupAuto = False
477         if len(wakeupList):
478                 startTime = wakeupList.pop(0)
479                 if (startTime[0] - nowTime) < 330: # no time to switch box back on
480                         wptime = nowTime + 30  # so switch back on in 30 seconds
481                 else:
482                         wptime = startTime[0] - 300
483                 setFPWakeuptime(wptime)
484                 recordTimerWakeupAuto = startTime[1] == 0 and startTime[2]
485         config.misc.isNextRecordTimerAfterEventActionAuto.value = recordTimerWakeupAuto
486         config.misc.isNextRecordTimerAfterEventActionAuto.save()
487
488         profile("stopService")
489         session.nav.stopService()
490         profile("nav shutdown")
491         session.nav.shutdown()
492
493         profile("configfile.save")
494         configfile.save()
495
496         return 0
497
498 profile("Init:skin")
499 import skin
500 skin.loadSkinData(getDesktop(0))
501
502 profile("InputDevice")
503 import Components.InputDevice
504 Components.InputDevice.InitInputDevices()
505
506 profile("AVSwitch")
507 import Components.AVSwitch
508 Components.AVSwitch.InitAVSwitch()
509
510 profile("RecordingConfig")
511 import Components.RecordingConfig
512 Components.RecordingConfig.InitRecordingConfig()
513
514 profile("UsageConfig")
515 import Components.UsageConfig
516 Components.UsageConfig.InitUsageConfig()
517
518 profile("keymapparser")
519 import keymapparser
520 keymapparser.readKeymap(config.usage.keymap.value)
521
522 profile("Network")
523 import Components.Network
524 Components.Network.InitNetwork()
525
526 profile("LCD")
527 import Components.Lcd
528 Components.Lcd.InitLcd()
529
530 profile("SetupDevices")
531 import Components.SetupDevices
532 Components.SetupDevices.InitSetupDevices()
533
534 profile("RFMod")
535 import Components.RFmod
536 Components.RFmod.InitRFmod()
537
538 profile("Init:CI")
539 import Screens.Ci
540 Screens.Ci.InitCiConfig()
541
542 #from enigma import dump_malloc_stats
543 #t = eTimer()
544 #t.callback.append(dump_malloc_stats)
545 #t.start(1000)
546
547 # first, setup a screen
548 try:
549         runScreenTest()
550
551         plugins.shutdown()
552
553         from Components.ParentalControl import parentalControl
554         parentalControl.save()
555 except:
556         print 'EXCEPTION IN PYTHON STARTUP CODE:'
557         print '-'*60
558         print_exc(file=stdout)
559         quitMainloop(5)
560         print '-'*60