3cc62b04940d35136e666bac6923c1ec517df183
[vuplus_dvbapp] / lib / python / Plugins / Extensions / HbbTV / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Screen import Screen
3 from Screens.InfoBar import InfoBar
4 from Screens.ChoiceBox import ChoiceBox
5 from Screens.HelpMenu import HelpableScreen
6 from Screens.MessageBox import MessageBox
7 from Screens.VirtualKeyBoard import VirtualKeyBoard
8 from Components.config import config
9 from Components.ActionMap import ActionMap
10 from Components.Language import language
11 from Components.ServiceEventTracker import ServiceEventTracker
12 from Components.VolumeControl import VolumeControl
13
14 from enigma import eTimer, fbClass, eRCInput, iServiceInformation, iPlayableService
15
16 import os, struct, vbcfg
17
18 from __init__ import _
19 from hbbtv import HbbTVWindow
20 from browser import Browser
21 from youtube import YoutubeTVWindow, YoutubeTVSettings
22 from vbipc import VBController, VBServerThread, VBHandlers
23
24 strIsEmpty = lambda x: x is None or len(x) == 0
25
26 vbcfg.SOCKETFILE = '/tmp/.browser.support'
27 vbcfg.CONTROLFILE = '/tmp/.browser.controller'
28 _OPCODE_LIST = [
29                 'CONTROL_BACK',
30                 'CONTROL_FORWARD',
31                 'CONTROL_STOP',
32                 'CONTROL_RELOAD',
33                 'CONTROL_OPENURL',
34                 'CONTROL_EXIT',
35                 'CONTROL_TITLE',
36                 'CONTROL_OK',
37                 'CONTROL_OUT_OF_MEMORY',
38                 'CONTROL_GET_VOLUME',
39                 'CONTROL_SET_VOLUME',
40                 'CONTROL_VOLUME_UP',
41                 'CONTROL_VOLUME_DOWN',
42                 'HBBTV_LOADAIT',
43                 'HBBTV_OPENURL',
44                 'YOUTUBETV_OPENURL',
45                 'BROWSER_OPENURL',
46                 'BROWSER_MENU_OPEN',
47                 'BROWSER_MENU_CLOSE',
48                 'BROWSER_VKB_OPEN',
49                 'BROWSER_VKB_CLOSE',
50                 'OOIF_GET_CURRENT_CHANNEL',
51                 'OOIF_BROADCAST_PLAY',
52                 'OOIF_BROADCAST_STOP',
53                 'OOIF_BROADCAST_CHECK',
54                 'OPCODE_END'
55                 ]
56
57 class VBHandler(VBHandlers):
58         def __init__(self, session):
59                 self._session = session
60                 self.current_title = None
61                 self.max_volume = -1
62                 self.soft_volume = -1
63                 self.videobackend_activate = False
64                 self.onSetTitleCB = []
65                 self.onCloseCB = []
66                 VBHandlers.__init__(self, _OPCODE_LIST, '_CB_')
67
68         def set_volume(self, volume):
69                 if self.max_volume < 0:
70                         self.max_volume = VolumeControl.instance.volctrl.getVolume()
71
72                 self.max_volume += volume
73                 if self.max_volume > 100:
74                         self.max_volume = 100
75                 elif self.max_volume < 0:
76                         self.max_volume = 0
77
78                 if self.soft_volume > 0:
79                         v = int((self.max_volume * self.soft_volume) / 100)
80                         VolumeControl.instance.volctrl.setVolume(v, v)
81                 else:
82                         VolumeControl.instance.volctrl.setVolume(self.max_volume, self.max_volume)
83
84         def close_vkb(self, data=""):
85                 fbClass.getInstance().lock()
86                 eRCInput.getInstance().lock()
87
88                 if strIsEmpty(data):
89                         data = ""
90                 VBController.command("BROWSER_VKB_CLOSE", data)
91
92         def _CB_CONTROL_EXIT(self, result, packet):
93                 if self.onCloseCB:
94                         for x in self.onCloseCB:
95                                 try:
96                                         x()
97                                 except Exception:
98                                         if x in self.onCloseCB:
99                                                 self.onCloseCB.remove(x)
100                 if self.videobackend_activate is False:
101                         if vbcfg.g_service is not None:
102                                 self._session.nav.playService(vbcfg.g_service)
103                 return (True, None)
104
105         def _CB_CONTROL_TITLE(self, result, packet):
106                 if packet.startswith('file://') or packet.startswith('http://'):
107                         return (True, None)
108                 for x in self.onSetTitleCB:
109                         try:
110                                 x(packet)
111                                 self.current_title = packet
112                         except Exception:
113                                 if x in self.onSetTitleCB:
114                                         self.onSetTitleCB.remove(x)
115                 return (True, None)
116
117         def _CB_CONTROL_OK(self, result, packet):
118                 if vbcfg.g_browser and packet.startswith('stop'):
119                         vbcfg.g_browser.keyOK()
120                 return (True, None)
121
122         def _CB_CONTROL_OUT_OF_MEMORY(self, result, packet):
123                 vbcfg.need_restart = True;
124                 return (True, None)
125
126         def _CB_CONTROL_SET_VOLUME(self, result, packet):
127                 if self.max_volume < 0:
128                         self.max_volume = VolumeControl.instance.volctrl.getVolume()
129                 self.soft_volume = int(packet)
130
131                 v = 0
132                 if self.soft_volume > 0 and self.max_volume > 0:
133                         v = int((self.max_volume * self.soft_volume) / 100)
134                 VolumeControl.instance.volctrl.setVolume(v, v)
135                 return (True, None)
136
137         def _CB_CONTROL_VOLUME_UP(self, result, packet):
138                 self.set_volume(5)
139                 return (True, None)
140
141         def _CB_CONTROL_VOLUME_DOWN(self, result, packet):
142                 self.set_volume(-5)
143                 return (True, None)
144
145         def _CB_BROWSER_MENU_OPEN(self, result, packet):
146                 if vbcfg.g_browser and vbcfg.g_browser.is_browser_opened:
147                         vbcfg.setPosition(vbcfg.g_position)
148                         fbClass.getInstance().unlock()
149                         eRCInput.getInstance().unlock()
150
151                         vbcfg.g_browser.toggle_browser(packet, self.current_title)
152                 return (True, None)
153
154         def _CB_BROWSER_VKB_OPEN(self, result, packet):
155                 if vbcfg.g_browser and vbcfg.g_browser.is_browser_opened:
156                         vbcfg.setPosition(vbcfg.g_position)
157                         fbClass.getInstance().unlock()
158                         eRCInput.getInstance().unlock()
159
160                         if strIsEmpty(packet):
161                                 packet = ""
162                         self._session.openWithCallback(self.close_vkb, VirtualKeyBoard, title=("Please enter URL here"), text=str(packet))
163                 return (True, None)
164
165         def _CB_OOIF_GET_CURRENT_CHANNEL(self, result, packet):
166                 if (vbcfg.g_channel_info):
167                         try:
168                                 data = struct.pack('iiii', vbcfg.g_channel_info[0], vbcfg.g_channel_info[1], vbcfg.g_channel_info[2], len(vbcfg.g_channel_info[3])) + vbcfg.g_channel_info[3]
169                         except Exception, err:
170                                 vbcfg.ERR(err)
171                                 return (False, None)
172                 else:
173                         return (False, None)
174                 return (True, data)
175
176         def _CB_OOIF_BROADCAST_PLAY(self, result, packet):
177                 if vbcfg.g_service is not None:
178                         self._session.nav.playService(vbcfg.g_service)
179                 self.videobackend_activate = False
180                 return (True, None)
181
182         def _CB_OOIF_BROADCAST_STOP(self, result, packet):
183                 vbcfg.g_service = self._session.nav.getCurrentlyPlayingServiceReference()
184                 self._session.nav.stopService()
185                 self.videobackend_activate = True
186                 return (True, None)
187
188         def _CB_OOIF_BROADCAST_CHECK(self, result, packet):
189                 if self._session.nav.getCurrentService() is None:
190                         return (False, None)
191                 return (True, None)
192
193 class VBMain(Screen):
194         skin = """<screen name="VBMAIN" position="0,0" size="0,0" backgroundColor="transparent" flags="wfNoBorder" title=" "></screen>"""
195         def __init__(self, session):
196                 Screen.__init__(self, session)
197
198                 self.vbcallback = None
199                 self.vbhandler = VBHandler(session)
200                 self.vbserver = VBServerThread()
201                 self.vbserver.open(1)
202                 self.vbserver.start()
203
204                 # comment for dev
205                 self.restart_browser()
206                 vbcfg.LOG("browser start")
207
208                 self._timer_infobar = eTimer()
209                 self._timer_infobar.callback.append(self._cb_register_infobar)
210                 self._timer_infobar.start(1000)
211
212                 self._event = ServiceEventTracker(screen=self, eventmap={
213                                 iPlayableService.evHBBTVInfo: self._cb_ait_detected,
214                                 iPlayableService.evUpdatedInfo: self._cb_info_updated
215                         })
216                 self._applicationList = None
217                 self._app_info = None
218
219                 try:
220                         from Screens.InfoBarGenerics import gHbbtvApplication
221                         self.m_vuplus = gHbbtvApplication.getUseAit()
222                 except:
223                         self.m_vuplus = False
224
225         def _cb_register_infobar(self):
226                 if InfoBar.instance:
227                         self._timer_infobar.stop()
228                         if self._cb_hbbtv_activated not in InfoBar.instance.onHBBTVActivation:
229                                 InfoBar.instance.onHBBTVActivation.append(self._cb_hbbtv_activated)
230                 vbcfg.DEBUG("registred HbbTV in InfoBar")
231
232         def _cb_hbbtv_activated(self, url=None, app_info=None):
233                 if not self.check_browser():
234                         message = _("HbbTV Browser was not running.\nPlease running browser before start HbbTV Application.")
235                         self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
236                         return
237                 self.start_hbbtv_application(url, app_info)
238
239         def _cb_ait_detected(self):
240                 vbcfg.g_channel_info = None
241                 self._applicationList = None
242                 self._app_info = self.get_autostart_application()
243                 vbcfg.DEBUG("detected AIT")
244
245         def _cb_info_updated(self):
246                 vbcfg.g_service = self.session.nav.getCurrentlyPlayingServiceReference()
247                 vbcfg.DEBUG("updated channel info")
248
249         def start_hbbtv_application(self, url, app_info):
250                 if vbcfg.need_restart:
251                         self.restart_browser()
252                         os.time.sleep(2)
253                         vbcfg.need_restart = False
254
255                 if not app_info:
256                         app_info = self._app_info
257                 self.session.open(HbbTVWindow, url, app_info)
258
259         def menu_toggle_browser(self, callback=None):
260                 mode = []
261                 self.vbcallback = callback
262                 if self.check_browser():
263                         mode.append((_('Stop'), 'Stop'))
264                 else:
265                         mode.append((_('Start'), 'Start'))
266                 self.session.openWithCallback(self.toggle_browser, ChoiceBox, title=_("Please choose one."), list=mode)
267
268         def toggle_browser(self, selected):
269                 if selected is not None:
270                         if self.vbcallback:
271                                 self.vbcallback()
272                         try:
273                                 mode = selected[1]
274                                 if mode == 'Start':
275                                         if not self.check_browser():
276                                                 self.start_browser()
277                                 elif mode == 'Stop':
278                                         self.stop_browser()
279
280                         except Exception, ErrMsg:
281                                 vbcfg.ERR("toggle browser: %s" % ErrMsg)
282
283         def menu_hbbtv_applications(self):
284                 applications = []
285                 if self._applicationList is not None:
286                         for x in self._applicationList:
287                                 applications.append((x["name"], x))
288                 else:
289                         applications.append((_("No detected HbbTV applications."), None))
290                 self.session.openWithCallback(self.start_application_selected, ChoiceBox, title=_("Please choose an HbbTV application."), list=applications)
291
292         def start_application_selected(self, selected):
293                 vbcfg.DEBUG(selected)
294                 try:
295                         if selected[1] is not None:
296                                 self._cb_hbbtv_activated(selected[1]["url"], selected[1])
297                 except Exception, ErrMsg:
298                         vbcfg.ERR(ErrMsg)
299
300         def get_autostart_application(self):
301                 if self._applicationList is None:
302                         service = self.session.nav.getCurrentService()
303                         info = service and service.info()
304                         if info is not None:
305                                 sid = info.getInfo(iServiceInformation.sSID)
306                                 onid = info.getInfo(iServiceInformation.sONID)
307                                 tsid = info.getInfo(iServiceInformation.sTSID)
308                                 name = info.getName()
309                                 vbcfg.g_channel_info = (sid, onid, tsid, name)
310
311                                 pmtid = info.getInfo(iServiceInformation.sPMTPID)
312                                 demux = info.getInfoString(iServiceInformation.sLiveStreamDemuxId)
313                                 vbcfg.DEBUG("demux = %s, pmtid = 0x%x, sid = 0x%x" % (demux, pmtid, sid))
314
315                                 from aitreader import eAITSectionReader
316                                 reader = eAITSectionReader(demux, pmtid, sid)
317                                 if reader.doOpen(info, self.m_vuplus):
318                                         reader.doParseApplications()
319                                         reader.doDump()
320                                 else:
321                                         vbcfg.ERR("no AIT")
322
323                                 try:
324                                         self._applicationList = reader.getApplicationList()
325                                 except:
326                                         pass
327
328                 if self._applicationList is not None:
329                         for app in self._applicationList:
330                                 if app["control"] in (1, -1):
331                                         return app
332                 return None
333
334         def start_browser(self):
335                 if not self.check_browser():
336                         os.system("%s/%s start"%(vbcfg.APPROOT, vbcfg.APP_RUN))
337                 return True
338
339         def stop_browser(self):
340                 VBController.command('CONTROL_EXIT')
341                 return True
342                 try:
343                         os.system("%s/%s stop"%(vbcfg.APPROOT, vbcfg.APP_RUN))
344                 except:
345                         pass
346                 return True
347
348         def check_browser(self):
349                 try:
350                         ret = os.popen('%s/%s check'%(vbcfg.APPROOT, vbcfg.APP_RUN)).read()
351                         return ret.strip() != "0"
352                 except Exception, ErrMsg:
353                         vbcfg.ERR("check browser running: %s" % ErrMsg)
354                 return False
355
356         def restart_browser(self):
357                 try:
358                         os.system("%s/%s restart"%(vbcfg.APPROOT, vbcfg.APP_RUN))
359                 except:
360                         pass
361                 return True
362
363 def HelpableScreen__init__(self):
364         if isinstance(self, HelpableScreen):
365                 HelpableScreen.showManual = showManual
366
367                 self["helpActions"] = ActionMap(["HelpbuttonActions"], {
368                         "help_b" : self.showHelp,
369                         "help_l" : self.showManual,
370                 }, -2)
371
372 def showManual(self):
373         if not os.path.exists(vbcfg.MANUALROOT):
374                 return
375
376         url = 'file://' + vbcfg.MANUALROOT + '/main.html'
377         lang = language.getLanguage()
378         if os.path.exists(vbcfg.MANUALROOT + '/' + lang):
379                 url = 'file://' + vbcfg.MANUALROOT + '/' + lang + '/main.html'
380
381         vbcfg.g_browser = self.session.open(Browser, url)
382
383 def auto_start_main(reason, **kwargs):
384         if reason:
385                 try:
386                         if vbcfg.g_main.vbserver is not None:
387                                 vbcfg.g_main.vbserver.kill()
388                 except: pass
389
390 def session_start_main(session, reason, **kwargs):
391         vbcfg.g_main = session.open(VBMain)
392         HelpableScreen.__init__ = HelpableScreen__init__
393         HelpableScreen.session = session
394
395 def start_youtubetv_main(session, **kwargs):
396         def _cb_youtubetv_close(ret):
397                 if ret:
398                         vbcfg.g_service = session.nav.getCurrentlyPlayingServiceReference()
399                         if vbcfg.g_service is not None:
400                                 session.nav.stopService()
401                         vbcfg.g_browser = session.open(Browser, vbcfg.g_youtubetv_cfg.uri.value, True)
402
403         if config.plugins.youtubetv.showhelp.value == True:
404                 _cb_youtubetv_close(True)
405         else:
406                 session.openWithCallback(_cb_youtubetv_close, YoutubeTVWindow)
407
408
409 def menu_start_youtube(menuid, **kwargs):
410         if menuid == "mainmenu":
411                 return [(_("YouTube TV"), start_youtubetv_main, "youtube_tv", 46)]
412         return []
413
414 def plugin_setting_youtube(session, **kwargs):
415         session.open(YoutubeTVSettings)
416
417 def plugin_start_browser(session, **kwargs):
418         vbcfg.g_browser = session.open(Browser)
419
420 def extension_toggle_browser(session, **kwargs):
421         if vbcfg.g_main is not None:
422                 vbcfg.g_main.menu_toggle_browser()
423
424 def extension_start_application(session, **kwargs):
425         if vbcfg.g_main is not None:
426                 vbcfg.g_main.menu_hbbtv_applications()
427
428 def Plugins(**kwargs):
429         l = []
430         l.append(PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=auto_start_main))
431         l.append(PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, needsRestart=True, fnc=session_start_main, weight=-10))
432         l.append(PluginDescriptor(name=_("YouTube TV"), where=PluginDescriptor.WHERE_MENU, fnc=menu_start_youtube))
433         l.append(PluginDescriptor(name=_("YouTube TV Settings"), where=PluginDescriptor.WHERE_PLUGINMENU, fnc=plugin_setting_youtube))
434         l.append(PluginDescriptor(name=_("Browser Start/Stop"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=extension_toggle_browser))
435         l.append(PluginDescriptor(name=_("HbbTV Applications"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=extension_start_application))
436         l.append(PluginDescriptor(name=_("Opera Web Browser"), description=_("start opera web browser"), where=PluginDescriptor.WHERE_PLUGINMENU, needsRestart=True, fnc=plugin_start_browser))
437         return l