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