Merge branch 'master' of git+ssh://scm.schwerkraft.elitedvb.net/scmrepos/git/enigma2...
[enigma2-plugins.git] / advhdmi / src / plugin.py
1 # -*- coding: utf-8 -*-
2
3 from traceback import print_exc
4 from sys import stdout, exc_info
5 from . import _
6
7 # Plugin
8 from Plugins.Plugin import PluginDescriptor
9 from Components.config import config, configfile, ConfigSelection, ConfigSubsection, getConfigListEntry, ConfigSubList, \
10         ConfigClock, ConfigInteger, ConfigYesNo 
11 from Components.ConfigList import ConfigListScreen
12
13 # for function
14 from time import localtime, mktime
15 from Components.HdmiCec import hdmi_cec
16
17 def _print(outtxt):
18         ltim = localtime()
19         headerstr = "[AdvHdmiCec] %04d%02d%02d-%02d%02d%02d " %(ltim[0],ltim[1],ltim[2],ltim[3],ltim[4],ltim[5])
20         outtxt = headerstr + outtxt
21         print outtxt
22
23 try:
24         from Plugins.SystemPlugins.AdvHdmi.AdvHdmiCecSetup import AdvHdmiCecSetup
25         g_AdvHdmi_setup_available = True
26 except ImportError:
27         g_AdvHdmi_setup_available = False
28         _print("error while loading AdvHdmiCecSetup")
29         print_exc(file=stdout) 
30
31 # overwrite functions
32 from Plugins.SystemPlugins.HdmiCec.plugin import Cec
33 try:
34         from Plugins.Extensions.WebInterface.WebComponents.Sources.RemoteControl import RemoteControl
35         from Plugins.Extensions.WebInterface.WebComponents.Sources.PowerState import PowerState
36         g_AdvHdmi_webif_available = True
37 except ImportError:
38         _print("No Webinterface-Plugin installed")
39         g_AdvHdmi_webif_available = False
40
41 config.plugins.AdvHdmiCec = ConfigSubsection()
42 config.plugins.AdvHdmiCec.enable = ConfigYesNo(default = False)
43 config.plugins.AdvHdmiCec.debug = ConfigYesNo(default = False)
44 config.plugins.AdvHdmiCec.enable_power_on = ConfigYesNo(default = True)
45 config.plugins.AdvHdmiCec.enable_power_off = ConfigYesNo(default = True)
46 config.plugins.AdvHdmiCec.disable_after_enigmastart = ConfigYesNo(default = False)
47 config.plugins.AdvHdmiCec.disable_from_webif = ConfigYesNo(default = False)
48 config.plugins.AdvHdmiCec.entriescount =  ConfigInteger(0)
49 config.plugins.AdvHdmiCec.Entries = ConfigSubList()
50 config.plugins.AdvHdmiCec.show_in = ConfigSelection(choices=[
51                 ("system", _("systemmenue")),
52                 ("plugin", _("pluginmenue")),
53                 ("extension", _("extensions")),
54         ], default = "system")
55
56 WEEKDAYS = [ 
57         _("Monday"),
58         _("Tuesday"),
59         _("Wednesday"),
60         _("Thursday"),
61         _("Friday"),
62         _("Saturday"),
63         _("Sunday")]
64
65 ADVHDMI_VERSION = "1.4.2"
66
67 # HDMI-Hook-Events
68 # To implement a hook, just instantiate a AdvHdmiCecIF, 
69 # and overwrite the methods before_event and/or after_event
70
71 # Events with boolean-return, that means if the CEC-signal has to be send / handled
72 ADVHDMI_BEFORE_POWERON = "BEFORE_POWERON"
73 ADVHDMI_BEFORE_POWEROFF = "BEFORE_POWEROFF"
74 ADVHDMI_BEFORE_RECEIVED_STANDBY = "BEFORE_RECEIVED_STANDBY"
75 ADVHDMI_BEFORE_RECEIVED_NOWACTIVE = "BEFORE_RECEIVED_NOWACTIVE"
76 # Events without return-value
77 ADVHDMI_AFTER_POWERON = "AFTER_POWERON"
78 ADVHDMI_AFTER_POWEROFF = "AFTER_POWEROFF"
79 ADVHDMI_AFTER_RECEIVED_STANDBY = "AFTER_RECEIVED_STANDBY"
80 ADVHDMI_AFTER_RECEIVED_NOWACTIVE = "AFTER_RECEIVED_NOWACTIVE"
81
82 # registered Hooks
83 advhdmiHooks = {}
84
85 def callHook(advhdmi_event):
86         if config.plugins.AdvHdmiCec.debug.value: _print("Debug: call Hooks for Event '" + str(advhdmi_event) + "'")
87         if advhdmiHooks:
88                 for hookKey,hook in advhdmiHooks.iteritems():
89                         if config.plugins.AdvHdmiCec.debug.value: _print("Debug: call Hook '" + str(hookKey) + "'")
90                         try: 
91                                 if advhdmi_event in (ADVHDMI_BEFORE_POWERON, ADVHDMI_BEFORE_POWEROFF, ADVHDMI_BEFORE_RECEIVED_STANDBY, ADVHDMI_BEFORE_RECEIVED_NOWACTIVE):
92                                         if not hook.before_event(advhdmi_event):
93                                                 _print("Hook '" + str(hookKey) + "' prevents sending HDMI-Cec-signal!")
94                                                 return False
95                                 else:
96                                         hook.after_event(advhdmi_event)
97                         except:
98                                 _print("Error while calling Hook " + str(hookKey))
99                                 print_exc(file=stdout)
100         if advhdmi_event in (ADVHDMI_BEFORE_POWERON, ADVHDMI_BEFORE_POWEROFF, ADVHDMI_BEFORE_RECEIVED_STANDBY, ADVHDMI_BEFORE_RECEIVED_NOWACTIVE):
101                 return True
102
103 def TimeSpanPresenter(confsection):
104         presenter = [
105                 WEEKDAYS[int(confsection.fromWD.value)],
106                 WEEKDAYS[int(confsection.toWD.value)] ]
107         timestr = "%02d:%02d" % tuple(confsection.begin.value)
108         presenter.append(str(timestr))
109         timestr = "%02d:%02d" % tuple(confsection.end.value)
110         presenter.append(str(timestr))
111         return presenter
112
113 # functionality
114 def autostart(reason, **kwargs):
115         global g_AdvHdmi_sessionstarted
116         if reason == 0:
117                 g_AdvHdmi_sessionstarted = True
118
119 def main(session, **kwargs):
120         global g_AdvHdmi_setup_available
121         if g_AdvHdmi_setup_available:
122                 session.open(AdvHdmiCecSetup)
123
124 def showinSetup(menuid):
125         if menuid != "system":
126                 return []
127         return [(_("Advanced HDMI-Cec Setup"), main, "", 46)]
128
129 def Plugins(**kwargs):
130         list = [
131                 PluginDescriptor(
132                         where = PluginDescriptor.WHERE_AUTOSTART,
133                         fnc = autostart)
134         ]
135         if config.plugins.AdvHdmiCec.show_in.value == "system":
136                 list.append (PluginDescriptor(
137                         name="Advanced HDMI-Cec Control", 
138                         description=_("manage when HDMI Cec is enabled"), 
139                         where = PluginDescriptor.WHERE_MENU, 
140                         fnc=showinSetup)
141                 )
142         if config.plugins.AdvHdmiCec.show_in.value == "plugin":
143                 list.append (PluginDescriptor(
144                         name = "Advanced HDMI-Cec Control",
145                         description = _("manage when HDMI Cec is enabled"),
146                         where = PluginDescriptor.WHERE_PLUGINMENU,
147                         fnc = main,
148                         needsRestart = False)
149                 )
150         if config.plugins.AdvHdmiCec.show_in.value == "extension":
151                 list.append (PluginDescriptor(
152                                 name = "Advanced HDMI-Cec Control",
153                                 description = _("manage when HDMI Cec is enabled"),
154                                 where = PluginDescriptor.WHERE_EXTENSIONSMENU,
155                                 fnc = main,
156                                 needsRestart = False)
157                 )
158         
159         return list
160         
161 def checkTimespan(lt, begin, end):
162         # Check if we span a day
163         if begin[0] > end[0] or (begin[0] == end[0] and begin[1] >= end[1]):
164                 # Check if begin of event is later than our timespan starts
165                 if lt.tm_hour > begin[0] or (lt.tm_hour == begin[0] and lt.tm_min >= begin[1]):
166                         # If so, event is in our timespan
167                         return True
168                 # Check if begin of event is earlier than our timespan end
169                 if lt.tm_hour < end[0] or (lt.tm_hour == end[0] and lt.tm_min <= end[1]):
170                         # If so, event is in our timespan
171                         return True
172                 return False
173         else:
174                 # Check if event begins earlier than our timespan starts
175                 if lt.tm_hour < begin[0] or (lt.tm_hour == begin[0] and lt.tm_min < begin[1]):
176                         # Its out of our timespan then
177                         return False
178                 # Check if event begins later than our timespan ends
179                 if lt.tm_hour > end[0] or (lt.tm_hour == end[0] and lt.tm_min > end[1]):
180                         # Its out of our timespan then
181                         return False
182                 return True
183
184 def AdvHdmiCecDOIT():
185         global g_AdvHdmi_sessionstarted
186         global g_AdvHdmi_fromwebif
187         ret_val = True
188         if config.plugins.AdvHdmiCec.enable.value:
189                 if g_AdvHdmi_sessionstarted and config.plugins.AdvHdmiCec.disable_after_enigmastart.value:
190                         _print("prevent sending HDMICec, because of enigmastart")
191                         ret_val = False
192
193                 if ret_val and g_AdvHdmi_fromwebif and config.plugins.AdvHdmiCec.disable_from_webif.value:
194                         _print("prevent sending HDMICec, because it was from webif")
195                         ret_val = False
196                 
197                 if ret_val and int(config.plugins.AdvHdmiCec.entriescount.value) > 0:
198                         lt = localtime()
199                         for e in config.plugins.AdvHdmiCec.Entries:
200                                 entr = [e]
201                                 if config.plugins.AdvHdmiCec.debug.value:
202                                         presenter = TimeSpanPresenter(e)
203                                         _print("Debug: Checking timespan '" + ", ".join( str(x) for x in presenter ) + "'")
204                                 if int(e.fromWD.getValue()) <=  int(lt[6]) \
205                                         and int(e.toWD.getValue()) >= int(lt[6]) :
206                                         presenter = TimeSpanPresenter(e)
207                                         if checkTimespan(lt, e.begin.getValue(), e.end.getValue()):
208                                                 _print("prevent sending HDMICec, because of timespan '" + ", ".join( str(x) for x in presenter ) + "'")
209                                                 ret_val = False
210                                         else:
211                                                 if config.plugins.AdvHdmiCec.debug.value: _print("Debug: Local Time is not between " + str(presenter[2]) + " and " + str(presenter[3]))
212                                 else:
213                                         if config.plugins.AdvHdmiCec.debug.value: _print("Debug: Local weekday (" + str(lt[6]) + ") is not between " + str(presenter[0]) + " and " + str(presenter[1]))
214                                 if not ret_val:
215                                         if config.plugins.AdvHdmiCec.debug.value: _print("Debug: Found matching Timespan, exit loop!")
216                                         break
217         g_AdvHdmi_sessionstarted = False
218         g_AdvHdmi_fromwebif = False
219
220         return ret_val
221
222 # Overwrite CEC-Base
223 def Cec__receivedStandby(self):
224         if config.plugins.cec.receivepower.value:
225                 from Screens.Standby import Standby, inStandby
226                 if not inStandby and self.session.current_dialog and self.session.current_dialog.ALLOW_SUSPEND and self.session.in_exec:
227                         if callHook(ADVHDMI_BEFORE_RECEIVED_STANDBY):
228                                 self.session.open(Standby)
229                                 callHook(ADVHDMI_AFTER_RECEIVED_STANDBY)
230
231 def Cec__receivedNowActive(self):
232         if config.plugins.cec.receivepower.value:
233                 from Screens.Standby import inStandby
234                 if inStandby != None:
235                         if callHook(ADVHDMI_BEFORE_RECEIVED_NOWACTIVE):
236                                 inStandby.Power()
237                                 callHook(ADVHDMI_AFTER_RECEIVED_NOWACTIVE)
238
239 def Cec_powerOn(self):
240         global g_AdvHdmi_initalized
241         if config.plugins.cec.sendpower.value:
242                 if self.session.shutdown:
243                         self.idle_to_standby = True
244                 else:
245                         if config.plugins.AdvHdmiCec.enable_power_on.value and AdvHdmiCecDOIT():
246                                 g_AdvHdmi_initalized = True
247                                 if callHook(ADVHDMI_BEFORE_POWERON):
248                                         _print("power on")
249                                         hdmi_cec.otp_source_enable()
250                                         callHook(ADVHDMI_AFTER_POWERON)
251
252 def Cec_powerOff(self):
253         global g_AdvHdmi_initalized
254         if config.plugins.cec.sendpower.value and config.plugins.AdvHdmiCec.enable_power_off.value and AdvHdmiCecDOIT():
255                 if callHook(ADVHDMI_BEFORE_POWEROFF):
256                         _print("power off")
257                         if not g_AdvHdmi_initalized:
258                                 _print("Workaround: enable Hdmi-Cec-Source (^=poweron)")
259                                 hdmi_cec.otp_source_enable()
260                         hdmi_cec.ss_standby()
261                         callHook(ADVHDMI_AFTER_POWEROFF)
262
263 # Overwrite WebIf
264 def RemoteControl_handleCommand(self, cmd):
265         global g_AdvHdmi_fromwebif
266         g_AdvHdmi_fromwebif = True
267         self.cmd = cmd
268         self.res = self.sendEvent()
269
270 def PowerState_handleCommand(self, cmd):
271         global g_AdvHdmi_fromwebif
272         g_AdvHdmi_fromwebif = True
273         self.cmd = cmd
274
275 g_AdvHdmi_sessionstarted = False
276 g_AdvHdmi_fromwebif = False
277 g_AdvHdmi_initalized = False
278
279 if config.plugins.AdvHdmiCec.enable.value:
280         _print("enabled")
281         Cec.__receivedStandby = Cec__receivedStandby
282         Cec.__receivedNowActive = Cec__receivedNowActive
283         Cec.powerOn = Cec_powerOn
284         Cec.powerOff = Cec_powerOff
285         if g_AdvHdmi_webif_available:
286                 RemoteControl.handleCommand = RemoteControl_handleCommand
287                 PowerState.handleCommand = PowerState_handleCommand