4.3.1r21
[enigma2.git] / usr / lib / enigma2 / python / Plugins / Extensions / HbbTV / HbbTV.py
1 from enigma import eHbbtv, eServiceReference, eTimer, eDVBVolumecontrol, cvar
2 from Plugins.Plugin import PluginDescriptor
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.MessageBox import MessageBox
5 from Screens.LocationBox import MovieLocationBox
6 from Components.config import config, ConfigSubsection, ConfigOnOff, ConfigSelection
7 from Components.PluginComponent import plugins
8 from Components.UsageConfig import preferredPath
9
10 from Plugins.Extensions.Browser.Browser import Browser
11 from Plugins.Extensions.Browser.Downloads import downloadManager, DownloadJob
12
13 config.plugins.hbbtv = ConfigSubsection()
14 config.plugins.hbbtv.enabled = ConfigOnOff(default=True)
15 config.plugins.hbbtv.testsuite = ConfigSelection([("mainmenu", _("Menu")), ("extensions", _("Extensions")), ("plugins", _("Plugin Browser")), ("disabled", _("Disabled"))], default="disabled")
16 config.plugins.hbbtv.text = ConfigOnOff(default=True)
17
18 from datetime import datetime
19 from urlparse import urlparse
20
21
22 class HbbTV(object):
23         instance = None
24         redButtonDescriptor = None
25         textDescriptor = None
26
27         def __init__(self, session):
28                 assert HbbTV.instance is None, "HbbTV is a singleton class and may only be initialized once!"
29                 HbbTV.instance = self
30
31                 self.session = session
32                 self._redButtonApp = None
33                 self._textApp = None
34                 self.eHbbtv = eHbbtv.getInstance()
35                 self.connectCallbacks()
36
37                 self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_STOPPED)
38
39                 from Screens.InfoBar import InfoBar
40                 InfoBar.instance.onServiceListRootChanged.append(self.setCurrentBouquet)
41                 InfoBar.instance.addExtension((self._getExtensionMenuText, self._showApplicationList, lambda: True), key="red")
42
43                 self.onClose = []
44
45                 self.__currentStreamRef = None
46                 self.__browser = None
47                 self.__lastService = None
48                 self.__restoreTimer = eTimer()
49                 self.__restoreTimer_conn = self.__restoreTimer.timeout.connect(self._restoreLastService)
50
51         def connectCallbacks(self):
52                 print "[HbbTV] connecting callbacks"
53                 self.conns = [ ]
54                 self.conns.append(self.eHbbtv.playServiceRequest.connect(self.zap))
55                 self.conns.append(self.eHbbtv.playStreamRequest.connect(self.playStream))
56                 self.conns.append(self.eHbbtv.pauseStreamRequest.connect(self.pauseStream))
57                 self.conns.append(self.eHbbtv.stopStreamRequest.connect(self.stopStream))
58                 self.conns.append(self.eHbbtv.nextServiceRequest.connect(self.nextService))
59                 self.conns.append(self.eHbbtv.prevServiceRequest.connect(self.prevService))
60                 self.conns.append(self.eHbbtv.setVolumeRequest.connect(self.setVolume))
61                 self.conns.append(self.eHbbtv.setVideoWindowRequest.connect(self.setVideoWindow))
62                 #AIT
63                 self.eHbbtv.setAitSignalsEnabled(True);
64                 self.conns.append(self.eHbbtv.redButtonAppplicationReady.connect(self.redButtonAppplicationReady))
65                 self.conns.append(self.eHbbtv.textApplicationReady.connect(self.textApplicationReady))
66                 self.conns.append(self.eHbbtv.aitInvalidated.connect(self.aitInvalidated))
67                 self.conns.append(self.eHbbtv.createApplicationRequest.connect(self.startApplicationByUri))
68                 self.conns.append(self.eHbbtv.show.connect(self.showBrowser))
69                 self.conns.append(self.eHbbtv.hide.connect(self.hideBrowser))
70
71         def disconnectCallbacks(self):
72                 print "[HbbTV] disconnecting callbacks"
73                 self.conns = None
74                 for fnc in self.onClose:
75                         fnc()
76
77         def _showVideoIfAvail(self):
78                 if self.__browser:
79                         self.__browser.showVideo()
80
81         def _hideVideoIfAvail(self):
82                 if self.__browser != None:
83                         self.__browser.hideVideo()
84
85
86         def setVideoWindow(self, x, y, w, h):
87                 if self.__browser:
88                         self.__browser.setVideoWindow(x, y, w, h)
89
90         def _unsetVideoWindow(self):
91                 if self.__browser:
92                         self.__browser.resetVideoWindow()
93
94         def _toggleVideoFullscreen(self):
95                 if self.__browser:
96                         return self.__browser.toggleVideoFullscreen()
97                 return False
98
99         def _saveStreamToDisk(self):
100                 if self.isStreaming():
101                         title = _("Please selection the location you want to download the current stream to.")
102                         self.session.openWithCallback(self._onSaveStreamToDisk, MovieLocationBox, title, preferredPath("<timer>"))
103                         return True
104                 return False
105
106         def _onSaveStreamToDisk(self, path):
107                 if path is not None:
108                         parsed = urlparse(self.__currentStreamRef.getPath())
109                         file = parsed.path.split("/")[-1].split(".")
110                         host = parsed.netloc.split(":")[0]
111                         datestring = datetime.now().strftime("%Y%m%d_%H%M")
112                         extension = "mp4"
113                         filename = "%s_%s_%s.%s" % (datestring, host, file[0], extension)
114                         path = "%s%s" % (path, filename)
115                         downloadManager.AddJob(DownloadJob(self.__currentStreamRef.getPath(), path, filename, cvar.hbbtvUserAgent))
116                         self.session.open(MessageBox, _("Download started..."), type=MessageBox.TYPE_INFO, timeout=3)
117
118         def _onUrlChanged(self, url):
119                 self.stopStream()
120                 self._unsetVideoWindow()
121
122         def showBrowser(self):
123                 self._showVideoIfAvail()
124 #               if self.__browser:
125                         #self.__browser.show()
126
127         def hideBrowser(self):
128                 self._hideVideoIfAvail()
129 #               if self.__browser:
130                         #self.__browser.hide()
131
132         def _unsetBrowser(self):
133                 self._unsetVideoWindow()
134                 self.stopStream()
135                 self.__browser = None
136
137         def zap(self, sref):
138                 self.session.nav.playService(eServiceReference(sref))
139
140         def isStreaming(self):
141                 if self.__currentStreamRef:
142                         return True
143                 return False
144
145         def playStream(self, sref):
146                 streamRef = eServiceReference(sref)
147                 currentService = self.session.nav.getCurrentlyPlayingServiceReference()
148                 if currentService and currentService.valid():
149                         if currentService.toCompareString() != streamRef.toCompareString():
150                                 if not self.__lastService:
151                                         self.__lastService = currentService
152                                 self._playStream(sref)
153                         else:
154                                 self._unpauseStream()
155                 else:
156                         self._playStream(sref)
157                 self._showVideoIfAvail()
158
159         def _playStream(self, sref):
160                 self.__restoreTimer.stop()
161                 self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_CONNECTING)
162                 self.session.nav.stopService()
163                 ref = eServiceReference(sref)
164                 ref.setUserAgent(cvar.hbbtvUserAgent)
165                 self.__currentStreamRef = ref
166                 self.session.nav.playService(ref)
167
168         def actionPause(self):
169                 if self.__browser:
170                         self.__browser.actionPause()
171
172         def _unpauseStream(self):
173                 pausable = self.session.nav.getCurrentService().pause()
174                 if pausable:
175                         pausable.unpause()
176                 self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_PLAYING)
177
178         def pauseStream(self):
179                 if self.isStreaming():
180                         pausable = self.session.nav.getCurrentService().pause()
181                         if pausable is None:
182                                 self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_PLAYING)
183                         else:
184                                 pausable.pause()
185                                 self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_PAUSED)
186
187         def actionStop(self):
188                 if self.__browser:
189                         self.__browser.actionStop()
190
191         def stopStream(self):
192                 if self.isStreaming():
193                         self.session.nav.stopService()
194                         self.eHbbtv.setStreamState(eHbbtv.STREAM_STATE_STOPPED)
195                         self.__currentStreamRef = None
196                         self.__restoreTimer.startLongTimer(1)
197
198         def setVolume(self, volume):
199                 vol = eDVBVolumecontrol.getInstance()
200                 vol.setVolume(volume)
201
202         def _restoreLastService(self):
203                 if self.__lastService:
204                         self.session.nav.playService(self.__lastService)
205                         self.__lastService = None
206
207         def nextService(self):
208                 from Screens.InfoBar import InfoBar
209                 ib = InfoBar.instance
210                 ib.zapDown()
211
212         def prevService(self):
213                 from Screens.InfoBar import InfoBar
214                 ib = InfoBar.instance
215                 ib.zapUp()
216
217         def redButtonAppplicationReady(self, appid):
218                 print "[HbbTV].readButtonApplicationReady, appid=%s" % (appid)
219                 self._redButtonApp = appid
220                 app = self.eHbbtv.getApplication(self._redButtonApp)
221                 HbbTV.redButtonDescriptor.name = app.getName()
222                 plugins.addPlugin(HbbTV.redButtonDescriptor)
223
224         def textApplicationReady(self, appid):
225                 print "[HbbTV].textApplicationReady, appid=%s" % (appid)
226                 if config.plugins.hbbtv.text.value:
227                         self._textApp = appid
228                         app = self.eHbbtv.getApplication(self._textApp)
229                         HbbTV.textDescriptor.name = app.getName()
230                         plugins.addPlugin(HbbTV.textDescriptor)
231
232         def aitInvalidated(self):
233                 print "[HbbTV].aitInvalidated"
234                 self._redButtonApp = None
235                 self._textApp = None
236                 if plugins.getPlugins(PluginDescriptor.WHERE_HBBTV).count(HbbTV.redButtonDescriptor) > 0:
237                         plugins.removePlugin(HbbTV.redButtonDescriptor)
238                 if plugins.getPlugins(PluginDescriptor.WHERE_TELETEXT).count(HbbTV.textDescriptor) > 0:
239                         plugins.removePlugin(HbbTV.textDescriptor)
240
241         def isRedButtonAvailable(self):
242                 return self._redButtonApp != None
243
244         def isTextAvailable(self):
245                 return self._textApp != None
246
247         def showRedButtonApplication(self):
248                 print "[HbbTV].HbbTV.showRedButtonApplication"
249                 if self._redButtonApp is not None:
250                         self.startApplicationById(self._redButtonApp)
251
252         def showTextApplication(self):
253                 print "[HbbTV].HbbTV.showTextApplication"
254                 if self._textApp is not None:
255                         self.startApplicationById(self._textApp)
256
257         def startApplicationByUri(self, uri):
258                 if uri.startswith("dvb://"):
259                         uri = self.eHbbtv.resolveApplicationLocator(uri)
260                 if uri != "":
261                         if self.__browser is not None:
262                                 if self.__browser.execing:
263                                         self.__browser.setUrl(uri)
264                                         self.__browser.show()
265                                         return
266
267                         self.__browser = self.session.open(Browser, True, uri, True, hbbtvMenu=self._showApplicationList)
268                         self.__browser.onClose.append(self._unsetBrowser)
269                         self.__browser.onPageLoadFinished.append(self.eHbbtv.pageLoadFinished)
270                         self.__browser.onActionTv.append(self._toggleVideoFullscreen)
271                         self.__browser.onActionRecord.append(self._saveStreamToDisk)
272                         self.__browser.onUrlChanged.append(self._onUrlChanged)
273                         self.__browser.onExecBegin.append(self._showVideoIfAvail)
274                         self.__browser.onExecEnd.append(self._hideVideoIfAvail)
275
276         def startApplicationById(self, appid):
277                 uri = self.eHbbtv.resolveApplicationLocator("dvb://current.ait/%s" % appid)
278                 if uri != "":
279                         self.startApplicationByUri(uri)
280
281         def setCurrentBouquet(self, ref):
282                 self.eHbbtv.setServiceList(ref.toString())
283
284         def _getExtensionMenuText(self):
285                 return _("HbbTV Applications")
286
287         def _showApplicationList(self):
288                 apps = eHbbtv.getInstance().getApplicationIdsAndName()
289                 if len(apps) == 0:
290                         apps.append((_("No HbbTV Application available"), None))
291                 self.session.openWithCallback(self._applicationSelected, ChoiceBox, title=_("Please select an HbbTV application"), list=apps)
292
293         def _applicationSelected(self, appid):
294                 appid = appid and appid[1]
295                 if appid is not None:
296                         if str(appid).startswith("http"):
297                                 self.startApplicationByUri(appid)
298                         else:
299                                 self.startApplicationById(appid)
300
301         @staticmethod
302         def redButton(**kwargs):
303                 hbbtv = HbbTV.instance
304                 if hbbtv is not None:
305                         if hbbtv.isRedButtonAvailable():
306                                 hbbtv.showRedButtonApplication()
307
308         @staticmethod
309         def textButton(**kwargs):
310                 hbbtv = HbbTV.instance
311                 if hbbtv is not None:
312                         if hbbtv.isTextAvailable():
313                                 hbbtv.showTextApplication()
314
315 HbbTV.redButtonDescriptor = PluginDescriptor(name="HbbTV", description=_("Show the current HbbTV Startapplication"), where=[PluginDescriptor.WHERE_HBBTV, ], fnc=HbbTV.redButton, needsRestart=False)
316 HbbTV.textDescriptor = PluginDescriptor(name="HbbTV", description=_("Show the current HbbTV Teletext Application"), where=[PluginDescriptor.WHERE_TELETEXT, ], fnc=HbbTV.textButton, needsRestart=False)
317
318 def start(session, **kwargs):
319         if HbbTV.instance is None:
320                 HbbTV(session)
321
322 def autostart(reason, **kwargs):
323         if reason == 1:
324                 if HbbTV.instance is not None:
325                         HbbTV.instance.disconnectCallbacks()