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