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