fix close return values for non execing dialogs
[enigma2.git] / 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 from Screens.Menu import MainMenu, mdom
397 import xml.dom.minidom
398
399 class PowerKey:
400         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
401
402         def __init__(self, session):
403                 self.session = session
404                 globalActionMap.actions["power_down"]=self.powerdown
405                 globalActionMap.actions["power_up"]=self.powerup
406                 globalActionMap.actions["power_long"]=self.powerlong
407                 globalActionMap.actions["deepstandby"]=self.shutdown # frontpanel long power button press
408                 self.standbyblocked = 1
409
410         def MenuClosed(self, *val):
411                 self.session.infobar = None
412
413         def shutdown(self):
414                 print "PowerOff - Now!"
415                 if not Screens.Standby.inTryQuitMainloop:
416                         self.session.open(Screens.Standby.TryQuitMainloop, 1)
417                 
418         def powerlong(self):
419                 self.standbyblocked = 1
420                 action = config.usage.on_long_powerpress.value
421                 if action == "shutdown":
422                         self.shutdown()
423                 elif action == "show_menu":
424                         print "Show shutdown Menu"
425                         menu = mdom.childNodes[0]
426                         for x in menu.childNodes:
427                                 if x.nodeType != xml.dom.minidom.Element.nodeType:
428                                     continue
429                                 elif x.tagName == 'menu':
430                                         for y in x.childNodes:
431                                                 if y.nodeType != xml.dom.minidom.Element.nodeType:
432                                                         continue
433                                                 elif y.tagName == 'id':
434                                                         id = y.getAttribute("val")
435                                                         if id and id == "shutdown":
436                                                                 self.session.infobar = self
437                                                                 menu_screen = self.session.openWithCallback(self.MenuClosed, MainMenu, x, x.childNodes)
438                                                                 menu_screen.setTitle(_("Standby / Restart"))
439                                                                 return
440
441         def powerdown(self):
442                 self.standbyblocked = 0
443
444         def powerup(self):
445                 if self.standbyblocked == 0:
446                         self.standbyblocked = 1
447                         self.standby()
448
449         def standby(self):
450                 if not Screens.Standby.inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
451                         self.session.open(Screens.Standby.Standby)
452
453 from Screens.Scart import Scart
454
455 class AutoScartControl:
456         def __init__(self, session):
457                 self.force = False
458                 self.current_vcr_sb = eAVSwitch.getInstance().getVCRSlowBlanking()
459                 if self.current_vcr_sb and config.av.vcrswitch.value:
460                         self.scartDialog = session.instantiateDialog(Scart, True)
461                 else:
462                         self.scartDialog = session.instantiateDialog(Scart, False)
463                 config.av.vcrswitch.addNotifier(self.recheckVCRSb)
464                 eAVSwitch.getInstance().vcr_sb_notifier.get().append(self.VCRSbChanged)
465
466         def recheckVCRSb(self, configElement):
467                 self.VCRSbChanged(self.current_vcr_sb)
468
469         def VCRSbChanged(self, value):
470                 #print "vcr sb changed to", value
471                 self.current_vcr_sb = value
472                 if config.av.vcrswitch.value or value > 2:
473                         if value:
474                                 self.scartDialog.showMessageBox()
475                         else:
476                                 self.scartDialog.switchToTV()
477
478 from enigma import eDVBCIInterfaces
479
480 def runScreenTest():
481         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
482
483         session = Session(desktop = getDesktop(0), summary_desktop = getDesktop(1), navigation = Navigation())
484
485         screensToRun = [ ]
486
487         for p in plugins.getPlugins(PluginDescriptor.WHERE_WIZARD):
488                 screensToRun.append(p.__call__)
489
490         screensToRun += wizardManager.getWizards()
491
492         screensToRun.append(Screens.InfoBar.InfoBar)
493
494         ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
495
496 #       eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
497 #               ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
498 #                       ["PREMIERE"], #provider_list,
499 #                       [] #caid_list
500 #               ));
501
502         def runNextScreen(session, screensToRun, *result):
503                 if result:
504                         quitMainloop(*result)
505                         return
506
507                 screen = screensToRun[0]
508
509                 if len(screensToRun):
510                         session.openWithCallback(boundFunction(runNextScreen, session, screensToRun[1:]), screen)
511                 else:
512                         session.open(screen)
513
514         runNextScreen(session, screensToRun)
515
516         vol = VolumeControl(session)
517         power = PowerKey(session)
518
519         # we need session.scart to access it from within menu.xml
520         session.scart = AutoScartControl(session)
521
522         runReactor()
523
524         configfile.save()
525
526         from time import time
527         from Tools.DreamboxHardware import setFPWakeuptime
528         #get next record timer start time
529         nextRecordingTime = session.nav.RecordTimer.getNextRecordingTime()
530         #get next zap timer start time
531         nextZapTime = session.nav.RecordTimer.getNextZapTime()
532         #get currentTime
533         nowTime = time()
534         if nextZapTime != -1 and nextRecordingTime != -1:
535                 startTime = nextZapTime < nextRecordingTime and nextZapTime or nextRecordingTime
536         else:
537                 startTime = nextZapTime != -1 and nextZapTime or nextRecordingTime
538         if startTime != -1:
539                 if (startTime - nowTime < 330): # no time to switch box back on
540                         setFPWakeuptime(nowTime + 30) # so switch back on in 30 seconds
541                 else:
542                         setFPWakeuptime(startTime - 300)
543         session.nav.stopService()
544         session.nav.shutdown()
545
546         return 0
547
548 import skin
549 skin.loadSkinData(getDesktop(0))
550
551 import Components.InputDevice
552 Components.InputDevice.InitInputDevices()
553
554 import Components.AVSwitch
555 Components.AVSwitch.InitAVSwitch()
556
557 import Components.RecordingConfig
558 Components.RecordingConfig.InitRecordingConfig()
559
560 import Components.UsageConfig
561 Components.UsageConfig.InitUsageConfig()
562
563 import keymapparser
564 keymapparser.readKeymap(config.usage.keymap.value)
565
566 import Components.Network
567 Components.Network.InitNetwork()
568
569 import Components.Lcd
570 Components.Lcd.InitLcd()
571
572 import Components.SetupDevices
573 Components.SetupDevices.InitSetupDevices()
574
575 import Components.RFmod
576 Components.RFmod.InitRFmod()
577
578 import Screens.Ci
579 Screens.Ci.InitCiConfig()
580
581 # first, setup a screen
582 try:
583         runScreenTest()
584
585         plugins.shutdown()
586
587         from Components.ParentalControl import parentalControl
588         parentalControl.save()
589 except:
590         print 'EXCEPTION IN PYTHON STARTUP CODE:'
591         print '-'*60
592         print_exc(file=stdout)
593         quitMainloop(5)
594         print '-'*60