don't handle powerlong unless dialog can handle it
[enigma2.git] / 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 RuntimeError("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                 if Screens.Standby.inTryQuitMainloop or (self.session.current_dialog and not self.session.current_dialog.ALLOW_SUSPEND):
347                         return
348
349                 self.standbyblocked = 1
350                 action = config.usage.on_long_powerpress.value
351                 if action == "shutdown":
352                         self.shutdown()
353                 elif action == "show_menu":
354                         print "Show shutdown Menu"
355                         root = mdom.getroot()
356                         for x in root.findall("menu"):
357                                 y = x.find("id")
358                                 if y is not None:
359                                         id = y.get("val")
360                                         if id and id == "shutdown":
361                                                 self.session.infobar = self
362                                                 menu_screen = self.session.openWithCallback(self.MenuClosed, MainMenu, x)
363                                                 menu_screen.setTitle(_("Standby / Restart"))
364                                                 return
365
366         def powerdown(self):
367                 self.standbyblocked = 0
368
369         def powerup(self):
370                 if self.standbyblocked == 0:
371                         self.standbyblocked = 1
372                         self.standby()
373
374         def standby(self):
375                 if not Screens.Standby.inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
376                         self.session.open(Screens.Standby.Standby)
377
378 profile("Scart")
379 from Screens.Scart import Scart
380
381 class AutoScartControl:
382         def __init__(self, session):
383                 self.force = False
384                 self.current_vcr_sb = eAVSwitch.getInstance().getVCRSlowBlanking()
385                 if self.current_vcr_sb and config.av.vcrswitch.value:
386                         self.scartDialog = session.instantiateDialog(Scart, True)
387                 else:
388                         self.scartDialog = session.instantiateDialog(Scart, False)
389                 config.av.vcrswitch.addNotifier(self.recheckVCRSb)
390                 eAVSwitch.getInstance().vcr_sb_notifier.get().append(self.VCRSbChanged)
391
392         def recheckVCRSb(self, configElement):
393                 self.VCRSbChanged(self.current_vcr_sb)
394
395         def VCRSbChanged(self, value):
396                 #print "vcr sb changed to", value
397                 self.current_vcr_sb = value
398                 if config.av.vcrswitch.value or value > 2:
399                         if value:
400                                 self.scartDialog.showMessageBox()
401                         else:
402                                 self.scartDialog.switchToTV()
403
404 profile("Load:CI")
405 from enigma import eDVBCIInterfaces
406 from Screens.Ci import CiHandler
407
408 profile("Load:VolumeControl")
409 from Components.VolumeControl import VolumeControl
410
411 def runScreenTest():
412         profile("readPluginList")
413         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
414
415         profile("Init:Session")
416         nav = Navigation(config.misc.isNextRecordTimerAfterEventActionAuto.value)
417         session = Session(desktop = getDesktop(0), summary_desktop = getDesktop(1), navigation = nav)
418
419         CiHandler.setSession(session)
420
421         screensToRun = [ ]
422
423         for p in plugins.getPlugins(PluginDescriptor.WHERE_WIZARD):
424                 screensToRun.append(p.__call__)
425
426         profile("wizards")
427         screensToRun += wizardManager.getWizards()
428
429         screensToRun.append((100, Screens.InfoBar.InfoBar))
430
431         screensToRun.sort()
432
433         ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
434
435 #       eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
436 #               ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
437 #                       ["PREMIERE"], #provider_list,
438 #                       [] #caid_list
439 #               ));
440
441         def runNextScreen(session, screensToRun, *result):
442                 if result:
443                         quitMainloop(*result)
444                         return
445
446                 screen = screensToRun[0][1]
447
448                 if len(screensToRun):
449                         session.openWithCallback(boundFunction(runNextScreen, session, screensToRun[1:]), screen)
450                 else:
451                         session.open(screen)
452
453         runNextScreen(session, screensToRun)
454
455         profile("Init:VolumeControl")
456         vol = VolumeControl(session)
457         profile("Init:PowerKey")
458         power = PowerKey(session)
459
460         # we need session.scart to access it from within menu.xml
461         session.scart = AutoScartControl(session)
462
463         profile("RunReactor")
464         profile_final()
465         runReactor()
466
467         profile("wakeup")
468         from time import time
469         from Tools.DreamboxHardware import setFPWakeuptime, getFPWakeuptime
470         #get currentTime
471         nowTime = time()
472         wakeupList = [
473                 x for x in ((session.nav.RecordTimer.getNextRecordingTime(), 0, session.nav.RecordTimer.isNextRecordAfterEventActionAuto()),
474                                         (session.nav.RecordTimer.getNextZapTime(), 1),
475                                         (plugins.getNextWakeupTime(), 2))
476                 if x[0] != -1
477         ]
478         wakeupList.sort()
479         recordTimerWakeupAuto = False
480         if len(wakeupList):
481                 startTime = wakeupList.pop(0)
482                 if (startTime[0] - nowTime) < 330: # no time to switch box back on
483                         wptime = nowTime + 30  # so switch back on in 30 seconds
484                 else:
485                         wptime = startTime[0] - 300
486                 setFPWakeuptime(wptime)
487                 recordTimerWakeupAuto = startTime[1] == 0 and startTime[2]
488         config.misc.isNextRecordTimerAfterEventActionAuto.value = recordTimerWakeupAuto
489         config.misc.isNextRecordTimerAfterEventActionAuto.save()
490
491         profile("stopService")
492         session.nav.stopService()
493         profile("nav shutdown")
494         session.nav.shutdown()
495
496         profile("configfile.save")
497         configfile.save()
498
499         return 0
500
501 profile("Init:skin")
502 import skin
503 skin.loadSkinData(getDesktop(0))
504
505 profile("InputDevice")
506 import Components.InputDevice
507 Components.InputDevice.InitInputDevices()
508
509 profile("AVSwitch")
510 import Components.AVSwitch
511 Components.AVSwitch.InitAVSwitch()
512
513 profile("RecordingConfig")
514 import Components.RecordingConfig
515 Components.RecordingConfig.InitRecordingConfig()
516
517 profile("UsageConfig")
518 import Components.UsageConfig
519 Components.UsageConfig.InitUsageConfig()
520
521 profile("keymapparser")
522 import keymapparser
523 keymapparser.readKeymap(config.usage.keymap.value)
524
525 profile("Network")
526 import Components.Network
527 Components.Network.InitNetwork()
528
529 profile("LCD")
530 import Components.Lcd
531 Components.Lcd.InitLcd()
532
533 profile("SetupDevices")
534 import Components.SetupDevices
535 Components.SetupDevices.InitSetupDevices()
536
537 profile("RFMod")
538 import Components.RFmod
539 Components.RFmod.InitRFmod()
540
541 profile("Init:CI")
542 import Screens.Ci
543 Screens.Ci.InitCiConfig()
544
545 #from enigma import dump_malloc_stats
546 #t = eTimer()
547 #t.callback.append(dump_malloc_stats)
548 #t.start(1000)
549
550 # first, setup a screen
551 try:
552         runScreenTest()
553
554         plugins.shutdown()
555
556         from Components.ParentalControl import parentalControl
557         parentalControl.save()
558 except:
559         print 'EXCEPTION IN PYTHON STARTUP CODE:'
560         print '-'*60
561         print_exc(file=stdout)
562         quitMainloop(5)
563         print '-'*60