Streamline behavior for recordings coming from deep standby
[openblackhole/openblackhole-enigma2.git] / mytest.py
1 import sys, os
2 if os.path.isfile("/usr/lib/enigma2/python/enigma.zip"):
3         sys.path.append("/usr/lib/enigma2/python/enigma.zip")
4
5 from Tools.Profile import profile, profile_final
6 profile("PYTHON_START")
7
8 import Tools.RedirectOutput
9 import enigma
10 import eConsoleImpl
11 import eBaseImpl
12 enigma.eTimer = eBaseImpl.eTimer
13 enigma.eSocketNotifier = eBaseImpl.eSocketNotifier
14 enigma.eConsoleAppContainer = eConsoleImpl.eConsoleAppContainer
15
16 from traceback import print_exc
17 profile("SimpleSummary")
18 from Screens import InfoBar
19 from Screens.SimpleSummary import SimpleSummary
20
21 from sys import stdout, exc_info
22
23 profile("Bouquets")
24 enigma.eDVBDB.getInstance().reloadBouquets()
25
26 profile("ParentalControl")
27 import Components.ParentalControl
28 Components.ParentalControl.InitParentalControl()
29
30 profile("LOAD:Navigation")
31 from Navigation import Navigation
32
33 profile("LOAD:skin")
34 from skin import readSkin
35
36 profile("LOAD:Tools")
37 from Tools.Directories import InitFallbackFiles, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_SKIN
38 from Components.config import config, configfile, ConfigText, ConfigYesNo, ConfigInteger, NoSave
39 InitFallbackFiles()
40
41 profile("config.misc")
42 config.misc.radiopic = ConfigText(default = resolveFilename(SCOPE_CURRENT_SKIN, "radio.mvi"))
43 config.misc.blackradiopic = ConfigText(default = resolveFilename(SCOPE_CURRENT_SKIN, "black.mvi"))
44 config.misc.isNextRecordTimerAfterEventActionAuto = ConfigYesNo(default=False)
45 config.misc.useTransponderTime = ConfigYesNo(default=True)
46 config.misc.startCounter = ConfigInteger(default=0) # number of e2 starts...
47 config.misc.standbyCounter = NoSave(ConfigInteger(default=0)) # number of standby
48 config.misc.DeepStandby = NoSave(ConfigYesNo(default=False)) # detect deepstandby
49 config.misc.epgcache_filename = ConfigText(default = "/hdd/epg.dat")
50
51 def setEPGCachePath(configElement):
52         enigma.eEPGCache.getInstance().setCacheFile(configElement.value)
53
54 #demo code for use of standby enter leave callbacks
55 #def leaveStandby():
56 #       print "!!!!!!!!!!!!!!!!!leave standby"
57
58 #def standbyCountChanged(configElement):
59 #       print "!!!!!!!!!!!!!!!!!enter standby num", configElement.value
60 #       from Screens.Standby import inStandby
61 #       inStandby.onClose.append(leaveStandby)
62
63 #config.misc.standbyCounter.addNotifier(standbyCountChanged, initial_call = False)
64 ####################################################
65
66 def useTransponderTimeChanged(configElement):
67         enigma.eDVBLocalTimeHandler.getInstance().setUseDVBTime(configElement.value)
68 config.misc.useTransponderTime.addNotifier(useTransponderTimeChanged)
69
70 profile("Twisted")
71 try:
72         import twisted.python.runtime
73
74         import e2reactor
75         e2reactor.install()
76
77         from twisted.internet import reactor
78
79         def runReactor():
80                 reactor.run(installSignalHandlers=False)
81 except ImportError:
82         print "twisted not available"
83         def runReactor():
84                 enigma.runMainloop()
85
86 profile("LOAD:Plugin")
87
88 # initialize autorun plugins and plugin menu entries
89 from Components.PluginComponent import plugins
90
91 profile("LOAD:Wizard")
92 from Screens.Wizard import wizardManager
93 from Screens.StartWizard import *
94 import Screens.Rc
95 from Tools.BoundFunction import boundFunction
96 from Plugins.Plugin import PluginDescriptor
97
98 profile("misc")
99 had = dict()
100
101 def dump(dir, p = ""):
102         if isinstance(dir, dict):
103                 for (entry, val) in dir.items():
104                         dump(val, p + "(dict)/" + entry)
105         if hasattr(dir, "__dict__"):
106                 for name, value in dir.__dict__.items():
107                         if not had.has_key(str(value)):
108                                 had[str(value)] = 1
109                                 dump(value, p + "/" + str(name))
110                         else:
111                                 print p + "/" + str(name) + ":" + str(dir.__class__) + "(cycle)"
112         else:
113                 print p + ":" + str(dir)
114
115 # + ":" + str(dir.__class__)
116
117 # display
118
119 profile("LOAD:ScreenGlobals")
120 from Screens.Globals import Globals
121 from Screens.SessionGlobals import SessionGlobals
122 from Screens.Screen import Screen
123
124 profile("Screen")
125 Screen.global_screen = Globals()
126
127 # Session.open:
128 # * push current active dialog ('current_dialog') onto stack
129 # * call execEnd for this dialog
130 #   * clear in_exec flag
131 #   * hide screen
132 # * instantiate new dialog into 'current_dialog'
133 #   * create screens, components
134 #   * read, apply skin
135 #   * create GUI for screen
136 # * call execBegin for new dialog
137 #   * set in_exec
138 #   * show gui screen
139 #   * call components' / screen's onExecBegin
140 # ... screen is active, until it calls 'close'...
141 # Session.close:
142 # * assert in_exec
143 # * save return value
144 # * start deferred close handler ('onClose')
145 # * execEnd
146 #   * clear in_exec
147 #   * hide screen
148 # .. a moment later:
149 # Session.doClose:
150 # * destroy screen
151
152 class Session:
153         def __init__(self, desktop = None, summary_desktop = None, navigation = None):
154                 self.desktop = desktop
155                 self.summary_desktop = summary_desktop
156                 self.nav = navigation
157                 self.delay_timer = enigma.eTimer()
158                 self.delay_timer.callback.append(self.processDelay)
159
160                 self.current_dialog = None
161
162                 self.dialog_stack = [ ]
163                 self.summary_stack = [ ]
164                 self.summary = None
165
166                 self.in_exec = False
167
168                 self.screen = SessionGlobals(self)
169
170                 for p in plugins.getPlugins(PluginDescriptor.WHERE_SESSIONSTART):
171                         try:
172                                 p(reason=0, session=self)
173                         except:
174                                 print "Plugin raised exception at WHERE_SESSIONSTART"
175                                 import traceback
176                                 traceback.print_exc()
177
178         def processDelay(self):
179                 callback = self.current_dialog.callback
180
181                 retval = self.current_dialog.returnValue
182
183                 if self.current_dialog.isTmp:
184                         self.current_dialog.doClose()
185 #                       dump(self.current_dialog)
186                         del self.current_dialog
187                 else:
188                         del self.current_dialog.callback
189
190                 self.popCurrent()
191                 if callback is not None:
192                         callback(*retval)
193
194         def execBegin(self, first=True, do_show = True):
195                 assert not self.in_exec
196                 self.in_exec = True
197                 c = self.current_dialog
198
199                 # when this is an execbegin after a execend of a "higher" dialog,
200                 # popSummary already did the right thing.
201                 if first:
202                         self.instantiateSummaryDialog(c)
203
204                 c.saveKeyboardMode()
205                 c.execBegin()
206
207                 # when execBegin opened a new dialog, don't bother showing the old one.
208                 if c == self.current_dialog and do_show:
209                         c.show()
210
211         def execEnd(self, last=True):
212                 assert self.in_exec
213                 self.in_exec = False
214
215                 self.current_dialog.execEnd()
216                 self.current_dialog.restoreKeyboardMode()
217                 self.current_dialog.hide()
218
219                 if last:
220                         self.current_dialog.removeSummary(self.summary)
221                         self.popSummary()
222
223         def create(self, screen, arguments, **kwargs):
224                 # creates an instance of 'screen' (which is a class)
225                 try:
226                         return screen(self, *arguments, **kwargs)
227                 except:
228                         errstr = "Screen %s(%s, %s): %s" % (str(screen), str(arguments), str(kwargs), exc_info()[0])
229                         print errstr
230                         print_exc(file=stdout)
231                         enigma.quitMainloop(5)
232
233         def instantiateDialog(self, screen, *arguments, **kwargs):
234                 return self.doInstantiateDialog(screen, arguments, kwargs, self.desktop)
235
236         def deleteDialog(self, screen):
237                 screen.hide()
238                 screen.doClose()
239
240         def instantiateSummaryDialog(self, screen, **kwargs):
241                 self.pushSummary()
242                 summary = screen.createSummary() or SimpleSummary
243                 arguments = (screen,)
244                 self.summary = self.doInstantiateDialog(summary, arguments, kwargs, self.summary_desktop)
245                 self.summary.show()
246                 screen.addSummary(self.summary)
247
248         def doInstantiateDialog(self, screen, arguments, kwargs, desktop):
249                 # create dialog
250
251                 try:
252                         dlg = self.create(screen, arguments, **kwargs)
253                 except:
254                         print 'EXCEPTION IN DIALOG INIT CODE, ABORTING:'
255                         print '-'*60
256                         print_exc(file=stdout)
257                         enigma.quitMainloop(5)
258                         print '-'*60
259
260                 if dlg is None:
261                         return
262
263                 # read skin data
264                 readSkin(dlg, None, dlg.skinName, desktop)
265
266                 # create GUI view of this dialog
267                 assert desktop is not None
268
269                 dlg.setDesktop(desktop)
270                 dlg.applySkin()
271
272                 return dlg
273
274         def pushCurrent(self):
275                 if self.current_dialog is not None:
276                         self.dialog_stack.append((self.current_dialog, self.current_dialog.shown))
277                         self.execEnd(last=False)
278
279         def popCurrent(self):
280                 if self.dialog_stack:
281                         (self.current_dialog, do_show) = self.dialog_stack.pop()
282                         self.execBegin(first=False, do_show=do_show)
283                 else:
284                         self.current_dialog = None
285
286         def execDialog(self, dialog):
287                 self.pushCurrent()
288                 self.current_dialog = dialog
289                 self.current_dialog.isTmp = False
290                 self.current_dialog.callback = None # would cause re-entrancy problems.
291                 self.execBegin()
292
293         def openWithCallback(self, callback, screen, *arguments, **kwargs):
294                 dlg = self.open(screen, *arguments, **kwargs)
295                 dlg.callback = callback
296                 return dlg
297
298         def open(self, screen, *arguments, **kwargs):
299                 if self.dialog_stack and not self.in_exec:
300                         raise RuntimeError("modal open are allowed only from a screen which is modal!")
301                         # ...unless it's the very first screen.
302
303                 self.pushCurrent()
304                 dlg = self.current_dialog = self.instantiateDialog(screen, *arguments, **kwargs)
305                 dlg.isTmp = True
306                 dlg.callback = None
307                 self.execBegin()
308                 return dlg
309
310         def close(self, screen, *retval):
311                 if not self.in_exec:
312                         print "close after exec!"
313                         return
314
315                 # be sure that the close is for the right dialog!
316                 # if it's not, you probably closed after another dialog
317                 # was opened. this can happen if you open a dialog
318                 # onExecBegin, and forget to do this only once.
319                 # after close of the top dialog, the underlying will
320                 # gain focus again (for a short time), thus triggering
321                 # the onExec, which opens the dialog again, closing the loop.
322                 assert screen == self.current_dialog
323
324                 self.current_dialog.returnValue = retval
325                 self.delay_timer.start(0, 1)
326                 self.execEnd()
327
328         def pushSummary(self):
329                 if self.summary is not None:
330                         self.summary.hide()
331                 self.summary_stack.append(self.summary)
332                 self.summary = None
333
334         def popSummary(self):
335                 if self.summary is not None:
336                         self.summary.doClose()
337                 self.summary = self.summary_stack.pop()
338                 if self.summary is not None:
339                         self.summary.show()
340
341 profile("Standby,PowerKey")
342 import Screens.Standby
343 from Screens.Menu import MainMenu, mdom
344 from GlobalActions import globalActionMap
345
346 class PowerKey:
347         """ PowerKey stuff - handles the powerkey press and powerkey release actions"""
348
349         def __init__(self, session):
350                 self.session = session
351                 globalActionMap.actions["power_down"]=self.powerdown
352                 globalActionMap.actions["power_up"]=self.powerup
353                 globalActionMap.actions["power_long"]=self.powerlong
354                 globalActionMap.actions["deepstandby"]=self.shutdown # frontpanel long power button press
355                 globalActionMap.actions["discrete_off"]=self.standby
356                 self.standbyblocked = 1
357
358         def MenuClosed(self, *val):
359                 self.session.infobar = None
360
361         def shutdown(self):
362                 print "PowerOff - Now!"
363                 if not Screens.Standby.inTryQuitMainloop and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND:
364                         self.session.open(Screens.Standby.TryQuitMainloop, 1)
365
366         def powerlong(self):
367                 if Screens.Standby.inTryQuitMainloop or (self.session.current_dialog and not self.session.current_dialog.ALLOW_SUSPEND):
368                         return
369                 self.doAction(action = config.usage.on_long_powerpress.value)
370
371         def doAction(self, action):
372                 self.standbyblocked = 1
373                 if action == "shutdown":
374                         self.shutdown()
375                 elif action == "show_menu":
376                         print "Show shutdown Menu"
377                         root = mdom.getroot()
378                         for x in root.findall("menu"):
379                                 y = x.find("id")
380                                 if y is not None:
381                                         id = y.get("val")
382                                         if id and id == "shutdown":
383                                                 self.session.infobar = self
384                                                 menu_screen = self.session.openWithCallback(self.MenuClosed, MainMenu, x)
385                                                 menu_screen.setTitle(_("Standby / restart"))
386                                                 return
387                 elif action == "standby":
388                         self.standby()
389
390         def powerdown(self):
391                 self.standbyblocked = 0
392
393         def powerup(self):
394                 if self.standbyblocked == 0:
395                         self.doAction(action = config.usage.on_short_powerpress.value)
396
397         def standby(self):
398                 if not Screens.Standby.inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND and self.session.in_exec:
399                         self.session.open(Screens.Standby.Standby)
400
401 profile("Scart")
402 from Screens.Scart import Scart
403
404 class AutoScartControl:
405         def __init__(self, session):
406                 self.force = False
407                 self.current_vcr_sb = enigma.eAVSwitch.getInstance().getVCRSlowBlanking()
408                 if self.current_vcr_sb and config.av.vcrswitch.value:
409                         self.scartDialog = session.instantiateDialog(Scart, True)
410                 else:
411                         self.scartDialog = session.instantiateDialog(Scart, False)
412                 config.av.vcrswitch.addNotifier(self.recheckVCRSb)
413                 enigma.eAVSwitch.getInstance().vcr_sb_notifier.get().append(self.VCRSbChanged)
414
415         def recheckVCRSb(self, configElement):
416                 self.VCRSbChanged(self.current_vcr_sb)
417
418         def VCRSbChanged(self, value):
419                 #print "vcr sb changed to", value
420                 self.current_vcr_sb = value
421                 if config.av.vcrswitch.value or value > 2:
422                         if value:
423                                 self.scartDialog.showMessageBox()
424                         else:
425                                 self.scartDialog.switchToTV()
426
427 profile("Load:CI")
428 from enigma import eDVBCIInterfaces
429 from Screens.Ci import CiHandler
430
431 profile("Load:VolumeControl")
432 from Components.VolumeControl import VolumeControl
433
434 def runScreenTest():
435         config.misc.startCounter.value += 1
436
437         profile("readPluginList")
438         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
439
440         profile("Init:Session")
441         nav = Navigation()
442         session = Session(desktop = enigma.getDesktop(0), summary_desktop = enigma.getDesktop(1), navigation = nav)
443
444         CiHandler.setSession(session)
445
446         screensToRun = [ p.__call__ for p in plugins.getPlugins(PluginDescriptor.WHERE_WIZARD) ]
447
448         profile("wizards")
449         screensToRun += wizardManager.getWizards()
450
451         screensToRun.append((100, InfoBar.InfoBar))
452
453         screensToRun.sort()
454
455         enigma.ePythonConfigQuery.setQueryFunc(configfile.getResolvedKey)
456
457 #       eDVBCIInterfaces.getInstance().setDescrambleRules(0 # Slot Number
458 #               ,(      ["1:0:1:24:4:85:C00000:0:0:0:"], #service_list
459 #                       ["PREMIERE"], #provider_list,
460 #                       [] #caid_list
461 #               ));
462
463         def runNextScreen(session, screensToRun, *result):
464                 if result:
465                         enigma.quitMainloop(*result)
466                         return
467
468                 screen = screensToRun[0][1]
469                 args = screensToRun[0][2:]
470
471                 if screensToRun:
472                         session.openWithCallback(boundFunction(runNextScreen, session, screensToRun[1:]), screen, *args)
473                 else:
474                         session.open(screen, *args)
475
476         config.misc.epgcache_filename.addNotifier(setEPGCachePath)
477
478         runNextScreen(session, screensToRun)
479
480         profile("Init:VolumeControl")
481         vol = VolumeControl(session)
482         profile("Init:PowerKey")
483         power = PowerKey(session)
484
485         # we need session.scart to access it from within menu.xml
486         session.scart = AutoScartControl(session)
487
488         profile("Init:Trashcan")
489         import Tools.Trashcan
490         Tools.Trashcan.init(session)
491
492         profile("RunReactor")
493         profile_final()
494         runReactor()
495
496         config.misc.startCounter.save()
497
498         profile("wakeup")
499         from time import time, strftime, localtime
500         from Tools.StbHardware import setFPWakeuptime, getFPWakeuptime, setRTCtime
501         #get currentTime
502         nowTime = time()
503         wakeupList = [
504                 x for x in ((session.nav.RecordTimer.getNextRecordingTime(), 0, session.nav.RecordTimer.isNextRecordAfterEventActionAuto()),
505                                         (session.nav.RecordTimer.getNextZapTime(), 1),
506                                         (plugins.getNextWakeupTime(), 2))
507                 if x[0] != -1
508         ]
509         wakeupList.sort()
510         recordTimerWakeupAuto = False
511         if wakeupList:
512                 from time import strftime
513                 startTime = wakeupList[0]
514                 if (startTime[0] - nowTime) < 270: # no time to switch box back on
515                         wptime = nowTime + 30  # so switch back on in 30 seconds
516                 else:
517                         wptime = startTime[0] - 240
518                 if not config.misc.useTransponderTime.value:
519                         print "dvb time sync disabled... so set RTC now to current linux time!", strftime("%Y/%m/%d %H:%M", localtime(nowTime))
520                         setRTCtime(nowTime)
521                 print "set wakeup time to", strftime("%Y/%m/%d %H:%M", localtime(wptime))
522                 setFPWakeuptime(wptime)
523                 recordTimerWakeupAuto = startTime[1] == 0 and startTime[2]
524         config.misc.isNextRecordTimerAfterEventActionAuto.value = recordTimerWakeupAuto
525         config.misc.isNextRecordTimerAfterEventActionAuto.save()
526
527         profile("stopService")
528         session.nav.stopService()
529         profile("nav shutdown")
530         session.nav.shutdown()
531
532         profile("configfile.save")
533         configfile.save()
534         from Screens import InfoBarGenerics
535         InfoBarGenerics.saveResumePoints()
536
537         return 0
538
539 profile("Init:skin")
540 import skin
541 skin.loadSkinData(enigma.getDesktop(0))
542
543 profile("InputDevice")
544 import Components.InputDevice
545 Components.InputDevice.InitInputDevices()
546 import Components.InputHotplug
547
548 profile("SetupDevices")
549 import Components.SetupDevices
550 Components.SetupDevices.InitSetupDevices()
551
552 profile("AVSwitch")
553 import Components.AVSwitch
554 Components.AVSwitch.InitAVSwitch()
555
556 profile("RecordingConfig")
557 import Components.RecordingConfig
558 Components.RecordingConfig.InitRecordingConfig()
559
560 profile("UsageConfig")
561 import Components.UsageConfig
562 Components.UsageConfig.InitUsageConfig()
563
564 profile("keymapparser")
565 import keymapparser
566 keymapparser.readKeymap(config.usage.keymap.value)
567
568 profile("Network")
569 import Components.Network
570 Components.Network.InitNetwork()
571
572 profile("LCD")
573 import Components.Lcd
574 Components.Lcd.InitLcd()
575
576 profile("RFMod")
577 import Components.RFmod
578 Components.RFmod.InitRFmod()
579
580 profile("Init:CI")
581 import Screens.Ci
582 Screens.Ci.InitCiConfig()
583
584 profile("RcModel")
585 import Components.RcModel
586
587 #from enigma import dump_malloc_stats
588 #t = eTimer()
589 #t.callback.append(dump_malloc_stats)
590 #t.start(1000)
591
592 # first, setup a screen
593 try:
594         runScreenTest()
595
596         plugins.shutdown()
597
598         Components.ParentalControl.parentalControl.save()
599 except:
600         print 'EXCEPTION IN PYTHON STARTUP CODE:'
601         print '-'*60
602         print_exc(file=stdout)
603         enigma.quitMainloop(5)
604         print '-'*60