make keymap configurable with config.usage.keymap
[openblackhole/openblackhole-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                         c.show()
177
178         def execEnd(self, last=True):
179                 assert self.in_exec
180                 self.in_exec = False
181
182                 self.current_dialog.execEnd()
183                 self.current_dialog.hide()
184
185                 if last:
186                         self.current_dialog.removeSummary(self.summary)
187                         self.popSummary()
188
189         def create(self, screen, arguments, **kwargs):
190                 # creates an instance of 'screen' (which is a class)
191                 try:
192                         return screen(self, *arguments, **kwargs)
193                 except:
194                         errstr = "Screen %s(%s, %s): %s" % (str(screen), str(arguments), str(kwargs), exc_info()[0])
195                         print errstr
196                         print_exc(file=stdout)
197                         quitMainloop(5)
198
199         def instantiateDialog(self, screen, *arguments, **kwargs):
200                 return self.doInstantiateDialog(screen, arguments, kwargs, self.desktop)
201
202         def deleteDialog(self, screen):
203                 screen.hide()
204                 screen.doClose()
205
206         def instantiateSummaryDialog(self, screen, *arguments, **kwargs):
207                 return self.doInstantiateDialog(screen, arguments, kwargs, self.summary_desktop)
208
209         def doInstantiateDialog(self, screen, arguments, kwargs, desktop):
210                 # create dialog
211
212                 try:
213                         dlg = self.create(screen, arguments, **kwargs)
214                 except:
215                         print 'EXCEPTION IN DIALOG INIT CODE, ABORTING:'
216                         print '-'*60
217                         print_exc(file=stdout)
218                         quitMainloop(5)
219                         print '-'*60
220
221                 if dlg is None:
222                         return
223
224                 # read skin data
225                 readSkin(dlg, None, dlg.skinName, desktop)
226
227                 # create GUI view of this dialog
228                 assert desktop is not None
229
230                 z = 0
231                 title = ""
232                 for (key, value) in dlg.skinAttributes:
233                         if key == "zPosition":
234                                 z = int(value)
235                         elif key == "title":
236                                 title = value
237
238                 dlg.instance = eWindow(desktop, z)
239                 dlg.title = title
240                 applyAllAttributes(dlg.instance, desktop, dlg.skinAttributes)
241                 gui = GUIOutputDevice()
242                 gui.parent = dlg.instance
243                 gui.create(dlg, desktop)
244
245                 return dlg
246
247         def pushCurrent(self):
248                 if self.current_dialog is not None:
249                         self.dialog_stack.append((self.current_dialog, self.current_dialog.shown))
250                         self.execEnd(last=False)
251
252         def popCurrent(self):
253                 if len(self.dialog_stack):
254                         (self.current_dialog, do_show) = self.dialog_stack.pop()
255                         self.execBegin(first=False, do_show=do_show)
256                 else:
257                         self.current_dialog = None
258
259         def execDialog(self, dialog):
260                 self.pushCurrent()
261                 self.current_dialog = dialog
262                 self.current_dialog.isTmp = False
263                 self.current_dialog.callback = None # would cause re-entrancy problems.
264                 self.execBegin()
265
266         def openWithCallback(self, callback, screen, *arguments, **kwargs):
267                 dlg = self.open(screen, *arguments, **kwargs)
268                 dlg.callback = callback
269                 return dlg
270
271         def open(self, screen, *arguments, **kwargs):
272                 if len(self.dialog_stack) and not self.in_exec:
273                         raise "modal open are allowed only from a screen which is modal!"
274                         # ...unless it's the very first screen.
275
276                 self.pushCurrent()
277                 dlg = self.current_dialog = self.instantiateDialog(screen, *arguments, **kwargs)
278                 dlg.isTmp = True
279                 dlg.callback = None
280                 self.execBegin()
281                 return dlg
282
283         def close(self, screen, *retval):
284                 if not self.in_exec:
285                         print "close after exec!"
286                         return
287
288                 # be sure that the close is for the right dialog!
289                 # if it's not, you probably closed after another dialog
290                 # was opened. this can happen if you open a dialog
291                 # onExecBegin, and forget to do this only once.
292                 # after close of the top dialog, the underlying will
293                 # gain focus again (for a short time), thus triggering
294                 # the onExec, which opens the dialog again, closing the loop.
295                 assert screen == self.current_dialog
296
297                 self.current_dialog.returnValue = retval
298                 self.delay_timer.start(0, 1)
299                 self.execEnd()
300
301         def pushSummary(self):
302                 if self.summary is not None:
303                         self.summary.hide()
304                 self.summary_stack.append(self.summary)
305                 self.summary = None
306
307         def popSummary(self):
308                 if self.summary is not None:
309                         self.summary.doClose()
310                 self.summary = self.summary_stack.pop()
311                 if self.summary is not None:
312                         self.summary.show()
313
314 from Screens.Volume import Volume
315 from Screens.Mute import Mute
316 from GlobalActions import globalActionMap
317
318 #TODO .. move this to a own .py file
319 class VolumeControl:
320         """Volume control, handles volUp, volDown, volMute actions and display
321         a corresponding dialog"""
322         def __init__(self, session):
323                 global globalActionMap
324                 globalActionMap.actions["volumeUp"]=self.volUp
325                 globalActionMap.actions["volumeDown"]=self.volDown
326                 globalActionMap.actions["volumeMute"]=self.volMute
327
328                 config.audio = ConfigSubsection()
329                 config.audio.volume = ConfigInteger(default = 100, limits = (0, 100))
330
331                 self.volumeDialog = session.instantiateDialog(Volume)
332                 self.muteDialog = session.instantiateDialog(Mute)
333
334                 self.hideVolTimer = eTimer()
335                 self.hideVolTimer.timeout.get().append(self.volHide)
336
337                 vol = config.audio.volume.value
338                 self.volumeDialog.setValue(vol)
339                 self.volctrl = eDVBVolumecontrol.getInstance()
340                 self.volctrl.setVolume(vol, vol)
341
342         def volSave(self):
343                 if self.volctrl.isMuted():
344                         config.audio.volume.value = 0
345                 else:
346                         config.audio.volume.value = self.volctrl.getVolume()
347                 config.audio.volume.save()
348
349         def volUp(self):
350                 self.setVolume(+1)
351
352         def volDown(self):
353                 self.setVolume(-1)
354
355         def setVolume(self, direction):
356                 oldvol = self.volctrl.getVolume()
357                 if direction > 0:
358                         self.volctrl.volumeUp()
359                 else:
360                         self.volctrl.volumeDown()
361                 is_muted = self.volctrl.isMuted()
362                 vol = self.volctrl.getVolume()
363                 self.volumeDialog.show()
364                 if is_muted:
365                         self.volMute() # unmute
366                 elif not vol:
367                         self.volMute(False, True) # mute but dont show mute symbol
368                 if self.volctrl.isMuted():
369                         self.volumeDialog.setValue(0)
370                 else:
371                         self.volumeDialog.setValue(self.volctrl.getVolume())
372                 self.volSave()
373                 self.hideVolTimer.start(3000, True)
374
375         def volHide(self):
376                 self.volumeDialog.hide()
377
378         def volMute(self, showMuteSymbol=True, force=False):
379                 vol = self.volctrl.getVolume()
380                 if vol or force:
381                         self.volctrl.volumeToggleMute()
382                         if self.volctrl.isMuted():
383                                 if showMuteSymbol:
384                                         self.muteDialog.show()
385                                 self.volumeDialog.setValue(0)
386                         else:
387                                 self.muteDialog.hide()
388                                 self.volumeDialog.setValue(vol)
389
390 import Screens.Standby
391
392 class PowerKey:
393         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
394
395         def __init__(self, session):
396                 self.session = session
397                 self.powerKeyTimer = eTimer()
398                 self.powerKeyTimer.timeout.get().append(self.powertimer)
399                 globalActionMap.actions["powerdown"]=self.powerdown
400                 globalActionMap.actions["powerup"]=self.powerup
401                 self.standbyblocked = 1
402 #               self["PowerKeyActions"] = HelpableActionMap(self, "PowerKeyActions",
403                         #{
404                                 #"powerdown": self.powerdown,
405                                 #"powerup": self.powerup,
406                                 #"discreteStandby": (self.standby, "Go standby"),
407                                 #"discretePowerOff": (self.quit, "Go to deep standby"),
408                         #})
409
410         def powertimer(self):
411                 print "PowerOff - Now!"
412                 if not Screens.Standby.inTryQuitMainloop:
413                         self.session.open(Screens.Standby.TryQuitMainloop, 1)
414
415         def powerdown(self):
416                 self.standbyblocked = 0
417                 self.powerKeyTimer.start(3000, True)
418
419         def powerup(self):
420                 self.powerKeyTimer.stop()
421                 if self.standbyblocked == 0:
422                         self.standbyblocked = 1
423                         self.standby()
424
425         def standby(self):
426                 if not Screens.Standby.inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
427                         self.session.open(Screens.Standby.Standby)
428
429 from Screens.Scart import Scart
430
431 class AutoScartControl:
432         def __init__(self, session):
433                 self.force = False
434                 self.current_vcr_sb = eAVSwitch.getInstance().getVCRSlowBlanking()
435                 if self.current_vcr_sb and config.av.vcrswitch.value:
436                         self.scartDialog = session.instantiateDialog(Scart, True)
437                 else:
438                         self.scartDialog = session.instantiateDialog(Scart, False)
439                 config.av.vcrswitch.addNotifier(self.recheckVCRSb)
440                 eAVSwitch.getInstance().vcr_sb_notifier.get().append(self.VCRSbChanged)
441
442         def recheckVCRSb(self, configElement):
443                 self.VCRSbChanged(self.current_vcr_sb)
444
445         def VCRSbChanged(self, value):
446                 #print "vcr sb changed to", value
447                 self.current_vcr_sb = value
448                 if config.av.vcrswitch.value or value > 2:
449                         if value:
450                                 self.scartDialog.showMessageBox()
451                         else:
452                                 self.scartDialog.switchToTV()
453
454 from enigma import eDVBCIInterfaces
455
456 def runScreenTest():
457         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
458
459         session = Session(desktop = getDesktop(0), summary_desktop = getDesktop(1), navigation = Navigation())
460
461         screensToRun = [ ]
462
463         for p in plugins.getPlugins(PluginDescriptor.WHERE_WIZARD):
464                 screensToRun.append(p.__call__)
465
466         screensToRun += wizardManager.getWizards()
467
468         screensToRun.append(Screens.InfoBar.InfoBar)
469
470         ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
471
472 #       eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
473 #               ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
474 #                       ["PREMIERE"], #provider_list,
475 #                       [] #caid_list
476 #               ));
477
478         def runNextScreen(session, screensToRun, *result):
479                 if result:
480                         quitMainloop(*result)
481                         return
482
483                 screen = screensToRun[0]
484
485                 if len(screensToRun):
486                         session.openWithCallback(boundFunction(runNextScreen, session, screensToRun[1:]), screen)
487                 else:
488                         session.open(screen)
489
490         runNextScreen(session, screensToRun)
491
492         vol = VolumeControl(session)
493         power = PowerKey(session)
494
495         # we need session.scart to access it from within menu.xml
496         session.scart = AutoScartControl(session)
497
498         runReactor()
499
500         configfile.save()
501
502         from time import time
503         from Tools.DreamboxHardware import setFPWakeuptime
504         #get next record timer start time
505         nextRecordingTime = session.nav.RecordTimer.getNextRecordingTime()
506         #get next zap timer start time
507         nextZapTime = session.nav.RecordTimer.getNextZapTime()
508         #get currentTime
509         nowTime = time()
510         if nextZapTime != -1 and nextRecordingTime != -1:
511                 startTime = nextZapTime < nextRecordingTime and nextZapTime or nextRecordingTime
512         else:
513                 startTime = nextZapTime != -1 and nextZapTime or nextRecordingTime
514         if startTime != -1:
515                 if (startTime - nowTime < 330): # no time to switch box back on
516                         setFPWakeuptime(nowTime + 30) # so switch back on in 30 seconds
517                 else:
518                         setFPWakeuptime(startTime - 300)
519         session.nav.stopService()
520         session.nav.shutdown()
521
522         return 0
523
524 import skin
525 skin.loadSkinData(getDesktop(0))
526
527 import Components.InputDevice
528 Components.InputDevice.InitInputDevices()
529
530 import Components.AVSwitch
531 Components.AVSwitch.InitAVSwitch()
532
533 import Components.RecordingConfig
534 Components.RecordingConfig.InitRecordingConfig()
535
536 import Components.UsageConfig
537 Components.UsageConfig.InitUsageConfig()
538
539 import keymapparser
540 keymapparser.readKeymap(config.usage.keymap.value)
541
542 import Components.Network
543 Components.Network.InitNetwork()
544
545 import Components.Lcd
546 Components.Lcd.InitLcd()
547
548 import Components.SetupDevices
549 Components.SetupDevices.InitSetupDevices()
550
551 import Components.RFmod
552 Components.RFmod.InitRFmod()
553
554 import Components.NimManager
555
556 import Screens.Ci
557 Screens.Ci.InitCiConfig()
558
559 # first, setup a screen
560 try:
561         runScreenTest()
562
563         plugins.shutdown()
564
565         from Components.ParentalControl import parentalControl
566         parentalControl.save()
567 except:
568         print 'EXCEPTION IN PYTHON STARTUP CODE:'
569         print '-'*60
570         print_exc(file=stdout)
571         quitMainloop(5)
572         print '-'*60