- add opera browser.(with hbbtv)
[vuplus_dvbapp] / lib / python / Plugins / Extensions / HbbTV / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
3 from Screens.Screen import Screen
4 from Screens.InfoBar import InfoBar
5 from Screens.ChoiceBox import ChoiceBox
6 from Screens.MessageBox import MessageBox
7 from Screens.InfoBarGenerics import InfoBarNotifications
8 from Screens.VirtualKeyBoard import VirtualKeyBoard
9
10 from Components.PluginComponent import plugins
11 from Components.Button import Button
12 from Components.Label import Label
13 from Components.Sources.StaticText import StaticText
14 from Components.ActionMap import NumberActionMap, ActionMap
15 from Components.ServiceEventTracker import ServiceEventTracker
16 from Components.MenuList import MenuList
17 from Components.Label import Label, MultiColorLabel
18 from Components.ConfigList import ConfigListScreen
19 from Components.config import config, ConfigSubsection, ConfigPosition, getConfigListEntry, ConfigBoolean, ConfigInteger, ConfigText, ConfigSelection, configfile, getCharValue
20
21 from enigma import eTimer, eConsoleAppContainer, getDesktop, eServiceReference, iPlayableService, iServiceInformation, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, getPrevAsciiCode, eRCInput, fbClass
22
23 import os, struct, threading, stat, select, time, socket, select
24
25 strIsEmpty = lambda x: x is None or len(x) == 0
26
27 HBBTVAPP_PATH = "/usr/local/hbb-browser"
28 COMMAND_PATH = '/tmp/.sock.hbbtv.cmd'
29
30 class GlobalValues:
31         command_util   = None
32         command_server = None
33
34         before_service = None
35
36         channel_info_sid   = None
37         channel_info_onid  = None
38         channel_info_tsid  = None
39         channel_info_name  = None
40         channel_info_orgid = None
41
42         hbbtv_handelr = None
43
44         packet_m  = 0xBBADBEE
45         packet_h  = '!IIII'
46         packet_hl = struct.calcsize(packet_h)
47 __gval__ = GlobalValues()
48
49 def getPacketHeaders():
50         global __gval__
51         return (__gval__.packet_m, __gval__.packet_h, __gval__.packet_hl)
52
53 def setChannelInfo(sid, onid, tsid, name, orgid):
54         if sid is None:   sid   = 0;
55         if onid is None:  onid  = 0;
56         if tsid is None:  tsid  = 0;
57         if name is None:  name  = "";
58         if orgid is None: orgid = 0;
59         global __gval__
60         __gval__.channel_info_sid   = sid
61         __gval__.channel_info_onid  = onid
62         __gval__.channel_info_tsid  = tsid
63         __gval__.channel_info_name  = name
64         __gval__.channel_info_orgid = orgid
65         print "Set Channel Info >> sid : %X, onid : %X, tsid : %X, name : %s, orgid : %d " % (sid, onid, tsid, name, orgid)
66 def getChannelInfos():
67         global __gval__
68         print "Get Channel Info >> sid : %X, onid : %X, tsid : %X, name : %s, orgid : %d " % (__gval__.channel_info_sid, 
69                 __gval__.channel_info_onid, __gval__.channel_info_tsid, __gval__.channel_info_name, __gval__.channel_info_orgid)
70         return (__gval__.channel_info_sid, 
71                 __gval__.channel_info_onid, 
72                 __gval__.channel_info_tsid, 
73                 __gval__.channel_info_name, 
74                 __gval__.channel_info_orgid)
75
76 def getCommandUtil():
77         global __gval__
78         return __gval__.command_util
79 def getCommandServer():
80         global __gval__
81         return __gval__.command_server
82
83 def setBeforeService(s):
84         global __gval__
85         __gval__.before_service = s
86 def getBeforeService():
87         global __gval__
88         return __gval__.before_service
89
90 def _unpack(packed_data):
91         (mg, h, hlen) = getPacketHeaders()
92
93         if strIsEmpty(packed_data):
94                 return None
95         (m, o, l, s) = struct.unpack(h, packed_data[:hlen])
96         if m != mg:
97                 return None
98         d = 0
99         if l > 0:
100                 d = packed_data[hlen:hlen+l]
101         return (o,d,s)
102
103 def _pack(opcode, params=None, reserved=0):
104         (m, h, hlen) = getPacketHeaders()
105         if strIsEmpty(params):
106                 params = ''
107         packed_data = struct.pack(h, m, opcode, len(params), reserved)
108         return packed_data + params
109
110 class MMSStreamURL:
111         headers = [
112                    'GET %s HTTP/1.0'
113                   ,'Accept: */* '
114                   ,'User-Agent: NSPlayer/7.10.0.3059 '
115                   ,'Host: %s '
116                   ,'Connection: Close '
117                   ]
118
119         def __init__(self):
120                 self.sendmsg = ''
121                 for m in self.headers:
122                         self.sendmsg += m + '\n'
123                 self.sendmsg += '\n\n'
124
125         def request(self, host, port=80, location='/'):
126                 sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
127                 sock.connect((host, port))
128                 sock.send(self.sendmsg%(location, host))
129                 print "Send Data : "
130                 print self.sendmsg%(location, host)
131                 fullydata = ''
132                 while 1:
133                         res = sock.recv(1024)
134                         if res == '': break
135                         fullydata += res
136                 sock.close()
137                 return fullydata
138
139         def parse(self, data):
140                 for d in data.splitlines():
141                         if d.startswith('Location: '):
142                                 return d[9:]
143                 return None
144
145         def getLocationData(self, url):
146                 url_list,host,location = None,None,None
147                 try:
148                         url = url[url.find(':')+3:]
149                         url_list = url.split('/')
150                         host = url_list[0]
151                         location = url[len(url_list[0]):]
152                 except Exception, err_msg:
153                         print err_msg
154                         return None
155                 html = self.request(host=host, location=location)
156                 return self.parse(html)
157
158 class OpCodeSet:
159         def __init__(self):
160                 self._opcode_ = {
161                          "OP_UNKNOWN"                   : 0x0000
162                         ,"OP_HBBTV_EXIT"                : 0x0001
163                         ,"OP_HBBTV_OPEN_URL"            : 0x0002
164                         ,"OP_HBBTV_LOAD_AIT"            : 0x0003
165                         ,"OP_HBBTV_UNLOAD_AIT"          : 0x0004
166                         ,"OP_HBBTV_FULLSCREEN"          : 0x0005
167                         ,"OP_HBBTV_TITLE"               : 0x0006
168                         ,"OP_OIPF_GET_CHANNEL_INFO_URL" : 0x0101
169                         ,"OP_OIPF_GET_CHANNEL_INFO_AIT" : 0x0102
170                         ,"OP_OIPF_GET_CHANNEL_INFO_LIST": 0x0103
171                         ,"OP_VOD_URI"                   : 0x0201
172                         ,"OP_VOD_PLAY"                  : 0x0202
173                         ,"OP_VOD_STOP"                  : 0x0203
174                         ,"OP_VOD_PAUSE"                 : 0x0204
175                         ,"OP_VOD_STATUS"                : 0x0205
176                         ,"OP_VOD_FORBIDDEN"             : 0x0206
177                         ,"OP_BROWSER_OPEN_URL"          : 0x0301
178                 }
179                 self._opstr_ = {
180                          0x0000 : "OP_UNKNOWN"
181                         ,0x0001 : "OP_HBBTV_EXIT"
182                         ,0x0002 : "OP_HBBTV_OPEN_URL"
183                         ,0x0003 : "OP_HBBTV_LOAD_AIT"
184                         ,0x0004 : "OP_HBBTV_UNLOAD_AIT"
185                         ,0x0005 : "OP_HBBTV_FULLSCREEN"
186                         ,0x0006 : "OP_HBBTV_TITLE"
187                         ,0x0101 : "OP_OIPF_GET_CHANNEL_INFO_URL"
188                         ,0x0102 : "OP_OIPF_GET_CHANNEL_INFO_AIT"
189                         ,0x0103 : "OP_OIPF_GET_CHANNEL_INFO_LIST"
190                         ,0x0201 : "OP_VOD_URI"
191                         ,0x0202 : "OP_VOD_PLAY"
192                         ,0x0203 : "OP_VOD_STOP"
193                         ,0x0204 : "OP_VOD_PAUSE"
194                         ,0x0205 : "OP_VOD_STATUS"
195                         ,0x0206 : "OP_VOD_FORBIDDEN"
196                         ,0x0301 : "OP_BROWSER_OPEN_URL"
197                 }
198
199         def get(self, opstr):
200                 try:
201                         return self._opcode_[opstr]
202                 except: pass
203                 return self._opcode_["OP_UNKNOWN"]
204
205         def what(self, opcode):
206                 try:
207                         return self._opstr_[opcode]
208                 except: pass
209                 return self._opstr_["0x0000"]
210
211 class SocketParams:
212         def __init__(self):
213                 self.protocol = None
214                 self.type     = None
215                 self.addr     = None
216                 self.buf_size = 4096
217                 self.handler  = None
218                 self.timeout  = 5
219                 self.destroy  = None
220
221 class StreamServer:
222         def __init__(self, params):
223                 self._protocol = params.protocol
224                 self._type     = params.type
225                 self._addr     = params.addr
226                 self._buf_size = params.buf_size
227                 self._handler  = params.handler
228                 self._timeout  = params.timeout
229                 self._destroy  = params.destroy
230
231                 self._terminated = False
232                 self._server_thread = None
233
234                 self.onHbbTVCloseCB = []
235                 self.onSetPageTitleCB = []
236
237         def __del__(self):
238                 if self._destroy is not None:
239                         self._destroy(self._addr)
240
241         def stop(self):
242                 self._terminated = True
243                 if self._server_thread is not None:
244                         self._server_thread.join()
245                         self._server_thread = None
246
247         def start(self):
248                 self._socket = socket.socket(self._protocol, self._type)
249                 self._socket.settimeout(self._timeout)
250                 self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
251                 self._socket.bind(self._addr)
252                 self._socket.listen(True)
253
254                 self._server_thread = threading.Thread(target=self._listen)
255                 self._server_thread.start()
256
257         def _listen(self):
258                 select_list = [self._socket]
259                 def _accept():
260                         try:
261                                 conn, addr = self._socket.accept()
262                                 self._client(conn, addr)
263                         except Exception, ErrMsg:
264                                 print "ServerSocket Error >>", ErrMsg
265                                 pass
266
267                 while not self._terminated:
268                         readable, writable, errored = select.select(select_list, [], [], self._timeout)
269                         for s in readable:
270                                 if s is self._socket:
271                                         _accept()
272
273         def _client(self, conn, addr):
274                 try:
275                         send_data     = ''
276                         received_data = conn.recv(self._buf_size)
277                         if self._handler is not None and not strIsEmpty(received_data):
278                                 send_data = self._handler.doHandle(received_data, self.onHbbTVCloseCB, self.onSetPageTitleCB)
279                         self._send(conn, send_data)
280                 except Exception, ErrMsg: 
281                         try: conn.close()
282                         except:pass
283                         if self._handler is not None:
284                                 self._handler.printError(ErrMsg)
285         def _send(self, conn, data) :
286                 conn.send(data)
287                 conn.close()
288
289 class ServerFactory:
290         def doListenUnixTCP(self, name, handler):
291                 def destroy(name):
292                         if os.path.exists(name):
293                                 os.unlink(name)
294                                 print "Removed ", name
295                 destroy(name)
296
297                 params = SocketParams()
298                 params.protocol = socket.AF_UNIX
299                 params.type     = socket.SOCK_STREAM
300                 params.addr     = name
301                 params.handler  = handler
302                 params.destroy  = destroy
303
304                 streamServer = StreamServer(params)
305                 streamServer.start()
306                 return streamServer
307
308         def doListenInetTCP(self, ip, port, handler):
309                 print "not implemented yet!!"
310         def doListenUnixDGRAM(self, name, handler):
311                 print "not implemented yet!!"
312         def doListenInetDGRAM(self, ip, port, handler):
313                 print "not implemented yet!!"
314
315 class Handler:
316         def doUnpack(self, data):
317                 return _unpack(data)
318
319         def doPack(self, opcode, params, reserved=0):
320                 return _pack(opcode, params, reserved)
321
322         def doHandle(self, data, onCloseCB):
323                 opcode, params = 0x0, 'Invalid Request!!'
324                 return _pack(opcode, params)
325
326         def printError(self, reason):
327                 print reason
328
329 class BrowserCommandUtil(OpCodeSet):
330         def __init__(self):
331                 self._fd = None
332                 OpCodeSet.__init__(self)
333
334         def isConnected(self):
335                 if self._fd is None:
336                         return False
337                 return True
338
339         def doConnect(self, filename):
340                 if not os.path.exists(filename):
341                         print "file not exists :", filename
342                         return False
343                 try:
344                         self._fd = os.open(filename, os.O_WRONLY|os.O_NONBLOCK)
345                         if self._fd is None:
346                                 print "fail to open file :", filename
347                                 return False
348                 except Exception, ErrMsg:
349                         print ErrMsg
350                         self._fd = None
351                         return False
352                 print "connected!! to ", filename
353                 return True
354
355         def doDisconnect(self):
356                 if self._fd is None:
357                         return
358                 os.close(self._fd)
359                 self._fd = None
360
361         def doSend(self, command, params=None, reserved=0):
362                 if self._fd is None:
363                         print "connected pipe was not exists!!"
364                         return False
365                 data = ''
366                 try:
367                         data = _pack(self.get(command), params, reserved)
368                         if data is None:
369                                 return False
370                         os.write(self._fd, data)
371                         print "Send OK!! :", command
372                 except: return False
373                 return True
374
375         def sendCommand(self, command, params=None, reserved=0):
376                 if not self.isConnected():
377                         global COMMAND_PATH
378                         self.doConnect(COMMAND_PATH)
379                 result = self.doSend(command, params, reserved)
380                 self.doDisconnect()
381                 return result
382
383 class HandlerHbbTV(Handler):
384         _vod_service = None
385         def __init__(self, session):
386                 self._session = session
387                 self.opcode = OpCodeSet()
388                 self.handle_map = {
389                          0x0001 : self._cb_handleCloseHbbTVBrowser
390                         ,0x0006 : self._cb_handleSetPageTitle
391                         ,0x0101 : self._cb_handleGetChannelInfoForUrl
392                         ,0x0102 : self._cb_handleGetChannelInfoForAIT
393                         ,0x0103 : self._cb_handleGetChannelInfoList
394                         ,0x0201 : self._cb_handleVODPlayerURI
395                         ,0x0202 : self._cb_handleVODPlayerPlay
396                         ,0x0203 : self._cb_handleVODPlayerStop
397                         ,0x0204 : self._cb_handleVODPlayerPlayPause
398                 }
399                 self._on_close_cb = None
400                 self._on_set_title_cb = None
401
402                 self._vod_uri = None
403
404         def _handle_dump(self, handle, opcode, data=None):
405                 if True: return
406                 print str(handle)
407                 try:
408                         print "    - opcode : ", self.opcode.what(opcode)
409                 except: pass
410                 print "    - data   : ", data
411
412         def doHandle(self, data, onCloseCB, onSetPageTitleCB):
413                 opcode, params, reserved = None, None, 0
414                 self._on_close_cb = onCloseCB
415                 self._on_set_title_cb = onSetPageTitleCB
416                 try:
417                         datas  = self.doUnpack(data)
418                 except Exception, ErrMsg:
419                         print "Unpacking packet ERR :", ErrMsg
420                         params = 'fail to unpack packet!!'
421                         opcode = self.opcode.get("OP_UNKNOWN")
422                         return self.doPack(opcode, params)
423                 else:
424                         opcode = datas[0]
425                         params = datas[1]
426                 self.opcode.what(opcode)
427
428                 try:
429                         #print self.handle_map[opcode]
430                         (reserved, params) = self.handle_map[opcode](opcode, params)
431                 except Exception, ErrMsg:
432                         print "Handling packet ERR :", ErrMsg
433                         params = 'fail to handle packet!!'
434                         opcode = self.opcode.get("OP_UNKNOWN")
435                         return self.doPack(opcode, params)
436                 self._on_close_cb = None
437                 self._on_set_title_cb = None
438                 return self.doPack(opcode, params, reserved)
439
440         def _cb_handleGetChannelInfoForUrl(self, opcode, data):
441                 self._handle_dump(self._cb_handleGetChannelInfoForUrl, opcode, data)
442                 (sid, onid, tsid, name, orgid) = getChannelInfos()
443                 namelen = len(name)
444                 return (0, struct.pack('!IIII', sid, onid, tsid, namelen) + name)
445
446         def _cb_handleGetChannelInfoForAIT(self, opcode, data):
447                 self._handle_dump(self._cb_handleGetChannelInfoForAIT, opcode, data)
448                 (sid, onid, tsid, name, orgid) = getChannelInfos()
449                 namelen = len(name)
450                 return (0, struct.pack('!IIIII', orgid, sid, onid, tsid, namelen) + name)
451
452         def _cb_handleGetChannelInfoList(self, opcode, data):
453                 self._handle_dump(self._cb_handleGetChannelInfoList, opcode, data)
454                 (sid, onid, tsid, name, orgid) = getChannelInfos()
455                 namelen = len(name)
456                 channel_list_size = 1
457                 return (channel_list_size, struct.pack('!IIII', sid, onid, tsid, namelen) + name)
458
459         def _cb_handleSetPageTitle(self, opcode, data):
460                 self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
461                 if data.startswith('file://') or data.startswith('http://'):
462                         return "OK"
463                 if self._on_set_title_cb is not None:
464                         for x in self._on_set_title_cb:
465                                 try:
466                                         x(data)
467                                 except Exception, ErrMsg:
468                                         if x in self._on_set_title_cb:
469                                                 self._on_set_title_cb.remove(x)
470                 return (0, "OK")
471
472         def _cb_handleCloseHbbTVBrowser(self, opcode, data):
473                 self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
474
475                 if self._on_close_cb:
476                         for x in self._on_close_cb:
477                                 try:
478                                         x()
479                                 except Exception, ErrMsg:
480                                         if x in self._on_close_cb:
481                                                 self._on_close_cb.remove(x)
482
483                 command_util = getCommandUtil()
484                 command_util.sendCommand('OP_HBBTV_FULLSCREEN', None)
485
486                 before_service = getBeforeService()
487                 if before_service is not None:
488                         self._session.nav.playService(before_service)
489                 return (0, "OK")
490
491         def _cb_handleVODPlayerURI(self, opcode, data):
492                 self._vod_uri = None
493                 hl = struct.calcsize('!II')
494                 datas = struct.unpack('!II', data[:hl])
495                 uriLength = datas[1]
496                 vodUri = data[hl:hl+uriLength]
497                 self._handle_dump(self._cb_handleVODPlayerURI, opcode, vodUri)
498                 self._vod_uri = vodUri
499                 return (0, "OK")
500
501         def doStop(self, restoreBeforeService=True, needStop=True):
502                 if needStop == True:
503                         self._session.nav.stopService()
504                 if self._vod_service is not None and restoreBeforeService:
505                         before_service = getBeforeService()
506                         self._session.nav.playService(before_service)
507                         self._vod_uri = None
508                 self._vod_service = None
509
510         def getUrl(self):
511                 return self._vod_uri
512
513         def doRetryOpen(self, url):
514                 if url is None:
515                         return False
516                 for ii in range(5):
517                         self._vod_service = None
518                         try:
519                                 print "try to open vod [%d] : %s" % (ii, url)
520                                 self._vod_service = eServiceReference(4097, 0, url)
521                                 self._session.nav.playService(self._vod_service)
522                                 if self._vod_service is not None:
523                                         return True
524                         except Exception, ErrMsg: 
525                                 print "OpenVOD ERR :", ErrMsg
526                         time.sleep(1)
527                 return False
528
529         def _cb_handleVODPlayerPlay(self, opcode, data):
530                 self._handle_dump(self._cb_handleVODPlayerPlay, opcode, data)
531                 self.doStop(restoreBeforeService=False)
532                 if self.doRetryOpen(url=self._vod_uri) == False:
533                         self.doStop()
534                 return (0, "OK")
535
536         def _cb_handleVODPlayerStop(self, opcode, data):
537                 self._handle_dump(self._cb_handleVODPlayerStop, opcode, data)
538                 self.doStop()   
539                 return (0, "OK")
540
541         def _cb_handleVODPlayerPlayPause(self, opcode, data):
542                 self._handle_dump(self._cb_handleVODPlayerPlayPause, opcode, data)
543                 service = self._session.nav.getCurrentService()
544                 try:
545                         pauseFlag = data[0]
546                         servicePause = service.pause()
547                         if pauseFlag == 'U':
548                                 servicePause.unpause()
549                         elif pauseFlag == 'P':
550                                 servicePause.pause()
551                 except Exception, ErrMsg:
552                         print "onPause ERR :", ErrMsg
553                 return (0, "OK")
554
555 class HbbTVWindow(Screen, InfoBarNotifications):
556         skin =  """
557                 <screen name="HbbTVWindow" position="0,0" size="1280,720" backgroundColor="transparent" flags="wfNoBorder" title="HbbTV Plugin">
558                 </screen>
559                 """
560         def __init__(self, session, url=None, cbf=None, useAIT=False):
561                 self._session = session
562                 eRCInput.getInstance().lock()
563
564                 Screen.__init__(self, session)
565                 InfoBarNotifications.__init__(self)
566                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap = {
567                         iPlayableService.evUser+20: self._serviceForbiden,
568                 })
569
570                 self._url = url
571                 self._use_ait = useAIT
572                 self._cb_closed_func = cbf
573                 self.onLayoutFinish.append(self._layoutFinished)
574
575                 command_server = getCommandServer()
576                 if self._cb_set_page_title not in command_server.onSetPageTitleCB:
577                         command_server.onSetPageTitleCB.append(self._cb_set_page_title)
578
579                 if self._cb_close_window not in command_server.onHbbTVCloseCB:
580                         command_server.onHbbTVCloseCB.append(self._cb_close_window)
581
582                 self._closeTimer = eTimer()
583                 self._closeTimer.callback.append(self._do_close)
584
585         def _layoutFinished(self):
586                 command_util = getCommandUtil()
587                 (sid, onid, tsid, name, orgid) = getChannelInfos()
588                 params  = struct.pack('!IIIII', orgid, sid, onid, tsid, len(name)) + name
589                 if self._use_ait:
590                         command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
591                         time.sleep(1)
592                         command_util.sendCommand('OP_HBBTV_LOAD_AIT', params, 1)
593                         return
594                 command_util.sendCommand('OP_HBBTV_LOAD_AIT', params)
595                 time.sleep(1)
596                 command_util.sendCommand('OP_HBBTV_OPEN_URL', self._url)
597
598         def _cb_close_window(self):
599                 self._closeTimer.start(1000)
600
601         def _do_close(self):
602                 self._closeTimer.stop()
603                 command_server = getCommandServer()
604                 try:
605                         if self._cb_set_page_title in command_server.onSetPageTitleCB:
606                                 command_server.onSetPageTitleCB.remove(self._cb_set_page_title)
607                 except Exception, ErrMsg: pass
608                 try:
609                         if self._cb_close_window in command_server.onHbbTVCloseCB:
610                                         command_server.onHbbTVCloseCB.remove(self._cb_close_window)
611                 except Exception, ErrMsg: pass
612                 try:
613                         if self._cb_closed_func is not None:
614                                 self._cb_closed_func()
615                 except: pass
616                 eRCInput.getInstance().unlock()
617                 self.close()
618
619         def _serviceForbiden(self):
620                 global __gval__
621                 real_url = MMSStreamURL().getLocationData(__gval__.hbbtv_handelr.getUrl())
622                 print "Received URI :\n",real_url
623
624                 if real_url is not None:
625                         __gval__.hbbtv_handelr.doRetryOpen(real_url.strip())
626
627         def _cb_set_page_title(self, title=None):
628                 print "page title :",title
629                 if title is None:
630                         return
631                 self.setTitle(title)
632
633 class HbbTVHelper(Screen):
634         skin =  """<screen name="HbbTVHelper" position="0,0" size="0,0" backgroundColor="transparent" flags="wfNoBorder" title=" "></screen>"""
635         def __init__(self, session):
636                 global __gval__
637                 __gval__.hbbtv_handelr = HandlerHbbTV(session)
638                 __gval__.command_server = ServerFactory().doListenUnixTCP('/tmp/.sock.hbbtv.url', __gval__.hbbtv_handelr)
639
640                 self._urls = None
641                 self._stop_opera()
642                 self._start_opera()
643
644                 Screen.__init__(self, session)
645                 self._session = session
646                 self._timer_infobar = eTimer()
647                 self._timer_infobar.callback.append(self._cb_registrate_infobar)
648                 self._timer_infobar.start(1000)
649
650                 self._excuted_browser = False
651
652                 __gval__.command_util = BrowserCommandUtil()
653
654         def _cb_registrate_infobar(self):
655                 if InfoBar.instance:
656                         self._timer_infobar.stop()
657                         if self._cb_ready_for_ait not in InfoBar.instance.onReadyForAIT:
658                                 InfoBar.instance.onReadyForAIT.append(self._cb_ready_for_ait)
659                         if self._cb_hbbtv_activated not in InfoBar.instance.onHBBTVActivation:
660                                 InfoBar.instance.onHBBTVActivation.append(self._cb_hbbtv_activated)
661
662         def _cb_ready_for_ait(self, orgId=0):
663                 if orgId == 0:
664                         if not self._excuted_browser:
665                                 command_util = getCommandUtil()
666                                 command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
667                         return
668                 setChannelInfo(None, None, None, None, None)
669
670                 service = self._session.nav.getCurrentService()
671                 info = service and service.info()
672                 if info is not None:
673                         sid  = info.getInfo(iServiceInformation.sSID)
674                         onid = info.getInfo(iServiceInformation.sONID)
675                         tsid = info.getInfo(iServiceInformation.sTSID)
676                         name = info.getName()
677                         if name is None:
678                                 name = ""
679                         orgid   = 0
680                         namelen = len(name)
681                         for x in info.getInfoObject(iServiceInformation.sHBBTVUrl):
682                                 if x[0] == 1 :
683                                         orgid = x[3]
684                                         break
685                         setChannelInfo(sid, onid, tsid, name, orgid)
686
687         def _cb_hbbtv_activated(self, title=None, url=None):
688                 if not self._is_browser_running():
689                         message = "HbbTV Browser was not running.\nPlease running browser before start HbbTV Application."
690                         self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
691                         return
692                 service = self._session.nav.getCurrentlyPlayingServiceReference()
693                 setBeforeService(service)
694                 self._start_hbbtv_application(title, url)
695
696         def _start_hbbtv_application(self, title, url):
697                 tmp_url = self.getStartHbbTVUrl()
698                 if url is None:
699                         url = tmp_url
700                 if strIsEmpty(url):
701                         print "can't get url of hbbtv!!"
702                         return
703                 print "success to get url of hbbtv!! >>", url
704                 if self._excuted_browser:
705                         print "already excuted opera browser!!"
706                         return
707
708                 use_ait = False
709                 for x in self._urls:
710                         control_code = x[0]
711                         tmp_url = x[2]
712                         if tmp_url == url and control_code == 1:
713                                 use_ait = True
714                 self._excuted_browser = True
715                 self._session.open(HbbTVWindow, url, self._cb_closed_browser, use_ait)
716
717         def _cb_closed_browser(self):
718                 self._excuted_browser = False
719
720         def _start_opera(self):
721                 if not self._is_browser_running():
722                         global HBBTVAPP_PATH
723                         start_command = '%s/launcher start'%(HBBTVAPP_PATH)
724                         os.system(start_command)
725
726         def _stop_opera(self):
727                 global HBBTVAPP_PATH
728                 try:    os.system('%s/launcher stop'%(HBBTVAPP_PATH))
729                 except: pass
730
731         def getStartHbbTVUrl(self):
732                 url, self._urls = None, None
733                 service = self._session.nav.getCurrentService()
734                 info = service and service.info()
735                 if not info: return None
736                 self._urls = info.getInfoObject(iServiceInformation.sHBBTVUrl)
737                 for u in self._urls:
738                         if u[0] == 1: # 0:control code, 1:name, 2:url, 3:orgid, 4:appid
739                                 url = u[2]
740                 if url is None:
741                         url = info.getInfoString(iServiceInformation.sHBBTVUrl)
742                 return url
743
744         def showApplicationSelectionBox(self):
745                 applications = []
746                 if self.getStartHbbTVUrl():
747                         for x in self._urls:
748                                 applications.append((x[1], x))
749                 else: applications.append(("No detected HbbTV applications.", None))
750                 self._session.openWithCallback(self._application_selected, ChoiceBox, title=_("Please choose an HbbTV application."), list=applications)
751
752         def _application_selected(self, selected):
753                 try:
754                         if selected[1] is None: return
755                         self._cb_hbbtv_activated(selected[1][1], selected[1][2])
756                 except Exception, ErrMsg: print ErrMsg
757
758         def showBrowserConfigBox(self):
759                 start_stop_mode = []
760                 if self._is_browser_running():
761                         start_stop_mode.append(('Stop',None))
762                 else:   start_stop_mode.append(('Start',None))
763                 self._session.openWithCallback(self._browser_config_selected, ChoiceBox, title=_("Please choose one."), list=start_stop_mode)
764
765         def _browser_config_selected(self, selected):
766                 if selected is None:
767                         return
768                 try:
769                         mode = selected[0]
770                         if mode == 'Start':
771                                 if not self._is_browser_running():
772                                         self._start_opera()
773                         elif mode == 'Stop':
774                                 self._stop_opera()
775                 except Exception, ErrMsg: print "Config ERR :", ErrMsg
776
777         def _is_browser_running(self):
778                 try:
779                         global HBBTVAPP_PATH
780                         ret = os.popen('%s/launcher check'%(HBBTVAPP_PATH)).read()
781                         return ret.strip() != "0"
782                 except Exception, ErrMsg:
783                         print "Check Browser Running ERR :", ErrMsg
784                 return False
785
786 _g_helper = None
787 class OperaBrowser(Screen):
788         MENUBAR_ITEM_WIDTH  = 150
789         MENUBAR_ITEM_HEIGHT = 30
790         SUBMENULIST_WIDTH   = 200
791         SUBMENULIST_HEIGHT  = 25
792         SUBMENULIST_NEXT    = 2
793
794         skin =  """
795                 <screen name="Opera Browser" position="0,0" size="1280,720" backgroundColor="transparent" flags="wfNoBorder" title="Opera Browser">
796                         <widget name="topArea" zPosition="-1" position="0,0" size="1280,60" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
797                         <widget name="menuitemFile" position="30,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
798                         <widget name="menuitemHelp" position="180,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
799                         <widget name="menulist" position="50,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
800                         <widget name="submenulist" position="%d,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
801                         <widget name="bottomArea" position="0,640" size="1280,80" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
802                 </screen>
803                 """ % (MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH, SUBMENULIST_WIDTH+50+SUBMENULIST_NEXT, MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH)
804
805         MENUITEMS_LIST =[[('Open Location', None), ('Start/Stop',None), ('Exit', None)],
806                          [('About', None)]]
807         def __init__(self, session):
808                 Screen.__init__(self, session)
809
810                 self["actions"] = ActionMap(["MinuteInputActions", "ColorActions", "InputActions", "InfobarChannelSelection", "EPGSelectActions", "KeyboardInputActions"], {
811                          "cancel"      : self.keyCancel
812                         ,"ok"          : self.keyOK
813                         ,"left"        : self.keyLeft
814                         ,"right"       : self.keyRight
815                         ,"up"          : self.keyUp
816                         ,"down"        : self.keyDown
817                         ,"menu"        : self.keyCancel
818                 }, -2)
819
820                 self.menubarCurrentIndex = 0
821                 self.lvMenuItems = []
822                 self.lvSubMenuItems = []
823
824                 self["topArea"]    = Label()
825                 self["bottomArea"] = Label()
826
827                 self["menuitemFile"] = MultiColorLabel()
828                 self["menuitemHelp"] = MultiColorLabel()
829
830                 self["menulist"] = MenuList(self.setListOnView())
831                 self["submenulist"] = MenuList(self.setSubListOnView())
832
833                 self.toggleMainScreenFlag = True
834                 self.toggleListViewFlag = False
835                 self.toggleSubListViewFlag = False
836                 self.currentListView = self["menulist"]
837
838                 self.onLayoutFinish.append(self.layoutFinished)
839
840                 self._onCloseTimer = eTimer()
841                 self._onCloseTimer.callback.append(self._cb_onClose)
842
843         def enableRCMouse(self, mode): #mode=[0|1]|[False|True]
844                 rcmouse_path = "/proc/stb/fp/mouse"
845                 if os.path.exists(rcmouse_path):
846                         os.system("echo %d > %s" % (mode, rcmouse_path))
847
848         def layoutFinished(self):
849                 self["menuitemFile"].setText("File")
850                 self["menuitemHelp"].setText("Help")
851
852                 self["menulist"].hide()
853                 self["submenulist"].hide()
854
855                 self["bottomArea"].setText("Opera Web Browser Plugin v0.1")
856                 self.setTitle("BrowserMain")
857                 self.selectMenuitem()
858
859         def selectMenuitem(self):
860                 tmp = [self["menuitemFile"], self["menuitemHelp"]]
861                 self["menuitemFile"].setForegroundColorNum(0)
862                 self["menuitemHelp"].setForegroundColorNum(0)
863                 tmp[self.menubarCurrentIndex].setForegroundColorNum(1)
864
865         def popupCloseAll(self):
866                 self.keyLeft()
867                 self.keyLeft()
868                 self.keyUp()
869                 self.keyCancel()
870
871         def setListOnView(self):
872                 self.lvMenuItems = self.MENUITEMS_LIST[self.menubarCurrentIndex]        
873                 return self.lvMenuItems
874
875         def setSubListOnView(self):
876                 self.lvSubMenuItems = []
877                 xl = self["menulist"].getCurrent()[1]
878                 if xl is None: return []
879                 for x in xl:
880                         self.lvSubMenuItems.append((x,None))
881                 return self.lvSubMenuItems
882
883         def toggleMainScreen(self):
884                 if not self.toggleMainScreenFlag:
885                         self.show()
886                 else:   self.hide()
887                 self.toggleMainScreenFlag = not self.toggleMainScreenFlag
888
889         def toggleListView(self):
890                 if not self.toggleListViewFlag:
891                         self["menulist"].show()
892                 else:   self["menulist"].hide()
893                 self.toggleListViewFlag = not self.toggleListViewFlag
894
895         def toggleSubListView(self):
896                 if not self.toggleSubListViewFlag:
897                         self["submenulist"].show()
898                 else:   self["submenulist"].hide()
899                 self.toggleSubListViewFlag = not self.toggleSubListViewFlag
900
901         def setCurrentListView(self, listViewIdx):
902                 if listViewIdx == 0:
903                         self.currentListView = None
904                 elif listViewIdx == 1:
905                         self.currentListView = self["menulist"]
906                 elif listViewIdx == 2:
907                         self.currentListView = self["submenulist"]
908
909         def _cb_onClose(self):
910                 self._onCloseTimer.stop()
911                 command_server = getCommandServer()
912                 try:
913                         if self._on_close_window in command_server.onHbbTVCloseCB:
914                                         command_server.onHbbTVCloseCB.remove(self._on_close_window)
915                 except Exception, ErrMsg: pass
916                 try:
917                         if self._on_setPageTitle in command_server.onSetPageTitleCB:
918                                 command_server.onSetPageTitleCB.remove(self._on_setPageTitle)
919                 except Exception, ErrMsg: pass
920                 self._on_setPageTitle('Opera Browser')
921                 self.enableRCMouse(False)
922                 self.toggleMainScreen()
923                 eRCInput.getInstance().unlock()
924
925         def _on_setPageTitle(self, title=None):
926                 print "page title :",title
927                 if title is None:
928                         return
929                 self.setTitle(title)
930
931         def cbUrlText(self, data=None):
932                 print "Inputed Url :", data
933                 if strIsEmpty(data):
934                         return
935                 command_server = getCommandServer()
936                 if self._on_setPageTitle not in command_server.onSetPageTitleCB:
937                                 command_server.onSetPageTitleCB.append(self._on_setPageTitle)
938                 if self._on_close_window not in command_server.onHbbTVCloseCB:
939                         command_server.onHbbTVCloseCB.append(self._on_close_window)
940                 self.toggleMainScreen()
941                 self.enableRCMouse(True)
942                 eRCInput.getInstance().lock()
943                 command_util = getCommandUtil()
944                 command_util.sendCommand('OP_BROWSER_OPEN_URL', data)
945
946         def _on_close_window(self):
947                 self._onCloseTimer.start(1000)
948
949         def _cmd_on_OpenLocation(self):
950                 global _g_helper
951                 if not _g_helper._is_browser_running():
952                         message = "Opera Browser was not running.\nPlease running browser using [File]>[Start/Stop] menu."
953                         self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
954                         return
955                 self.session.openWithCallback(self.cbUrlText, VirtualKeyBoard, title=("Please enter URL here"), text='http://')
956         def _cmd_on_About(self):
957                 self.session.open(MessageBox, 'Opera Web Browser Plugin v0.1(beta)', type = MessageBox.TYPE_INFO)
958         def _cmd_on_Exit(self):
959                 self.close()
960         def _cmd_on_StartStop(self):
961                 global _g_helper
962                 if _g_helper is None: 
963                         return
964                 _g_helper.showBrowserConfigBox()
965         def doCommand(self, command):
966                 cmd_map = {
967                          'Exit'          :self._cmd_on_Exit
968                         ,'About'         :self._cmd_on_About
969                         ,'Open Location' :self._cmd_on_OpenLocation
970                         ,'Start/Stop'    :self._cmd_on_StartStop
971                 }
972                 try:
973                         cmd_map[command]()
974                 except: pass
975
976         def keyOK(self):
977                 if not self.toggleListViewFlag:
978                         self.keyDown()
979                         return
980                 if self.currentListView.getCurrent()[1] is None:
981                         self.doCommand(self.currentListView.getCurrent()[0])
982                         #self.session.open(MessageBox, _(self.currentListView.getCurrent()[0]), type = MessageBox.TYPE_INFO)
983                         return
984                 self.keyRight()
985
986         def updateSelectedMenuitem(self, status):
987                 if self.menubarCurrentIndex == 0 and status < 0:
988                         self.menubarCurrentIndex = 1
989                 elif self.menubarCurrentIndex == 1 and status > 0:
990                         self.menubarCurrentIndex = 0
991                 else:   self.menubarCurrentIndex += status
992                 self.selectMenuitem()
993
994         def keyLeft(self):
995                 if not self.toggleMainScreenFlag:
996                         return
997                 if not self.toggleListViewFlag:
998                         self.updateSelectedMenuitem(-1)
999                         return
1000                 if self.toggleSubListViewFlag:
1001                         self.setCurrentListView(1)
1002                         self.toggleSubListView()
1003                         return
1004                 if self.currentListView.getSelectedIndex():
1005                         self.currentListView.pageUp()
1006
1007         def keyRight(self):
1008                 if not self.toggleMainScreenFlag:
1009                         return
1010                 if not self.toggleListViewFlag:
1011                         self.updateSelectedMenuitem(1)
1012                         return
1013                 if self.currentListView is None:
1014                         return
1015                 if self.currentListView.getCurrent()[1] is not None:
1016                         parentSelectedIndex = self.currentListView.getSelectedIndex()
1017                         self.setCurrentListView(2)
1018                         self.currentListView.setList(self.setSubListOnView())
1019                         self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvSubMenuItems)+5)
1020                         self.currentListView.move(self.MENUBAR_ITEM_WIDTH*self.menubarCurrentIndex + self.SUBMENULIST_WIDTH+self.SUBMENULIST_NEXT + 50,self.MENUBAR_ITEM_HEIGHT+30+(parentSelectedIndex*self.SUBMENULIST_HEIGHT))
1021                         self.toggleSubListView()
1022
1023         def keyDown(self):
1024                 if not self.toggleMainScreenFlag:
1025                         return
1026                 if self.currentListView is None:
1027                         return
1028                 if not self.toggleListViewFlag:
1029                         self.currentListView.setList(self.setListOnView())
1030                         self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvMenuItems)+5)
1031                         self.currentListView.move(self.MENUBAR_ITEM_WIDTH*self.menubarCurrentIndex+1+ 50,self.MENUBAR_ITEM_HEIGHT+30)
1032                         self.toggleListView()
1033                         return
1034                 self.currentListView.down()
1035
1036         def keyUp(self):
1037                 if not self.toggleMainScreenFlag:
1038                         return
1039                 if self.currentListView is None:
1040                         return
1041                 if self.currentListView == self["menulist"]:
1042                         if self.currentListView.getSelectedIndex() == 0:
1043                                 self.toggleListView()
1044                                 return
1045                 self.currentListView.up()
1046
1047         def keyCancel(self):
1048                 self.toggleMainScreen()
1049
1050 def auto_start_main(reason, **kwargs):
1051         if reason:
1052                 command_server = getCommandServer()
1053                 command_server.stop()
1054
1055 def session_start_main(session, reason, **kwargs):
1056         global _g_helper
1057         _g_helper = session.open(HbbTVHelper)
1058
1059 def plugin_start_main(session, **kwargs):
1060         session.open(OperaBrowser)
1061
1062 def plugin_extension_start_application(session, **kwargs):
1063         global _g_helper
1064         if _g_helper is None: 
1065                 return
1066         _g_helper.showApplicationSelectionBox()
1067
1068 def plugin_extension_browser_config(session, **kwargs):
1069         global _g_helper
1070         if _g_helper is None: 
1071                 return
1072         _g_helper.showBrowserConfigBox()
1073
1074 def Plugins(path, **kwargs):
1075         return  [
1076                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=auto_start_main),
1077                 PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, needsRestart=True, fnc=session_start_main, weight=-10),
1078                 PluginDescriptor(name="HbbTV Applications", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_start_application),
1079                 PluginDescriptor(name="Browser Start/Stop", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_browser_config),
1080                 PluginDescriptor(name="Opera Web Browser", description="start opera web browser", where=PluginDescriptor.WHERE_PLUGINMENU, needsRestart=True, fnc=plugin_start_main)
1081                 ]
1082