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