fix bug of setting orgid.
[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, profile=0):
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._profile = profile
573                 self._cb_closed_func = cbf
574                 self.onLayoutFinish.append(self._layoutFinished)
575
576                 command_server = getCommandServer()
577                 if self._cb_set_page_title not in command_server.onSetPageTitleCB:
578                         command_server.onSetPageTitleCB.append(self._cb_set_page_title)
579
580                 if self._cb_close_window not in command_server.onHbbTVCloseCB:
581                         command_server.onHbbTVCloseCB.append(self._cb_close_window)
582
583                 self._closeTimer = eTimer()
584                 self._closeTimer.callback.append(self._do_close)
585
586         def _layoutFinished(self):
587                 command_util = getCommandUtil()
588                 profile = self._profile
589                 (sid, onid, tsid, name, orgid) = getChannelInfos()
590                 params  = struct.pack('!IIIIII', orgid, profile, sid, onid, tsid, len(name)) + name
591                 if self._use_ait:
592                         command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
593                         time.sleep(1)
594                         command_util.sendCommand('OP_HBBTV_LOAD_AIT', params, 1)
595                         return
596                 command_util.sendCommand('OP_HBBTV_LOAD_AIT', params)
597                 time.sleep(1)
598                 command_util.sendCommand('OP_HBBTV_OPEN_URL', self._url)
599
600         def _cb_close_window(self):
601                 self._closeTimer.start(1000)
602
603         def _do_close(self):
604                 self._closeTimer.stop()
605                 command_server = getCommandServer()
606                 try:
607                         if self._cb_set_page_title in command_server.onSetPageTitleCB:
608                                 command_server.onSetPageTitleCB.remove(self._cb_set_page_title)
609                 except Exception, ErrMsg: pass
610                 try:
611                         if self._cb_close_window in command_server.onHbbTVCloseCB:
612                                         command_server.onHbbTVCloseCB.remove(self._cb_close_window)
613                 except Exception, ErrMsg: pass
614                 try:
615                         if self._cb_closed_func is not None:
616                                 self._cb_closed_func()
617                 except: pass
618                 eRCInput.getInstance().unlock()
619                 self.close()
620
621         def _serviceForbiden(self):
622                 global __gval__
623                 real_url = MMSStreamURL().getLocationData(__gval__.hbbtv_handelr.getUrl())
624                 print "Received URI :\n",real_url
625
626                 if real_url is not None:
627                         __gval__.hbbtv_handelr.doRetryOpen(real_url.strip())
628
629         def _cb_set_page_title(self, title=None):
630                 print "page title :",title
631                 if title is None:
632                         return
633                 self.setTitle(title)
634
635 class HbbTVHelper(Screen):
636         skin =  """<screen name="HbbTVHelper" position="0,0" size="0,0" backgroundColor="transparent" flags="wfNoBorder" title=" "></screen>"""
637         def __init__(self, session):
638                 global __gval__
639                 __gval__.hbbtv_handelr = HandlerHbbTV(session)
640                 __gval__.command_server = ServerFactory().doListenUnixTCP('/tmp/.sock.hbbtv.url', __gval__.hbbtv_handelr)
641
642                 self._urls = None
643                 self._stop_opera()
644                 self._start_opera()
645
646                 Screen.__init__(self, session)
647                 self._session = session
648                 self._timer_infobar = eTimer()
649                 self._timer_infobar.callback.append(self._cb_registrate_infobar)
650                 self._timer_infobar.start(1000)
651
652                 self._excuted_browser = False
653                 self._profile = 0
654
655                 __gval__.command_util = BrowserCommandUtil()
656
657         def _cb_registrate_infobar(self):
658                 if InfoBar.instance:
659                         self._timer_infobar.stop()
660                         if self._cb_ready_for_ait not in InfoBar.instance.onReadyForAIT:
661                                 InfoBar.instance.onReadyForAIT.append(self._cb_ready_for_ait)
662                         if self._cb_hbbtv_activated not in InfoBar.instance.onHBBTVActivation:
663                                 InfoBar.instance.onHBBTVActivation.append(self._cb_hbbtv_activated)
664
665         def _cb_ready_for_ait(self, orgId=0):
666                 if orgId == 0:
667                         if not self._excuted_browser:
668                                 command_util = getCommandUtil()
669                                 command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
670                         return
671                 setChannelInfo(None, None, None, None, None)
672
673                 service = self._session.nav.getCurrentService()
674                 info = service and service.info()
675                 if info is not None:
676                         sid  = info.getInfo(iServiceInformation.sSID)
677                         onid = info.getInfo(iServiceInformation.sONID)
678                         tsid = info.getInfo(iServiceInformation.sTSID)
679                         name = info.getName()
680                         if name is None:
681                                 name = ""
682                         orgid   = 0
683                         namelen = len(name)
684                         for x in info.getInfoObject(iServiceInformation.sHBBTVUrl):
685                                 if x[0] in (1, -1) :
686                                         orgid = x[3]
687                                         break
688                         setChannelInfo(sid, onid, tsid, name, orgid)
689
690         def _cb_hbbtv_activated(self, title=None, url=None):
691                 if not self._is_browser_running():
692                         message = "HbbTV Browser was not running.\nPlease running browser before start HbbTV Application."
693                         self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
694                         return
695                 service = self._session.nav.getCurrentlyPlayingServiceReference()
696                 setBeforeService(service)
697                 self._start_hbbtv_application(title, url)
698
699         def _start_hbbtv_application(self, title, url):
700                 tmp_url = self.getStartHbbTVUrl()
701                 if url is None:
702                         url = tmp_url
703                 if strIsEmpty(url):
704                         print "can't get url of hbbtv!!"
705                         return
706                 print "success to get url of hbbtv!! >>", url
707                 if self._excuted_browser:
708                         print "already excuted opera browser!!"
709                         return
710
711                 use_ait = False
712
713                 for x in self._urls:
714                         control_code = x[0]
715                         tmp_url = x[2]
716                         if tmp_url == url and control_code == 1:
717                                 use_ait = True
718
719                 self._excuted_browser = True
720                 self._session.open(HbbTVWindow, url, self._cb_closed_browser, use_ait, self._profile)
721
722         def _cb_closed_browser(self):
723                 self._excuted_browser = False
724
725         def _start_opera(self):
726                 if not self._is_browser_running():
727                         global HBBTVAPP_PATH
728                         start_command = '%s/launcher start'%(HBBTVAPP_PATH)
729                         os.system(start_command)
730
731         def _stop_opera(self):
732                 global HBBTVAPP_PATH
733                 try:    os.system('%s/launcher stop'%(HBBTVAPP_PATH))
734                 except: pass
735
736         def getStartHbbTVUrl(self):
737                 url, self._urls, self._profile = None, None, 0
738                 service = self._session.nav.getCurrentService()
739                 info = service and service.info()
740                 if not info: return None
741                 self._urls = info.getInfoObject(iServiceInformation.sHBBTVUrl)
742                 for u in self._urls:
743                         if u[0] in (1, -1): # 0:control code, 1:name, 2:url, 3:orgid, 4:appid, 5:profile code
744                                 url = u[2]
745                                 self._profile = u[5]
746                 if url is None:
747                         url = info.getInfoString(iServiceInformation.sHBBTVUrl)
748                 return url
749
750         def showApplicationSelectionBox(self):
751                 applications = []
752
753                 if self.getStartHbbTVUrl():
754                         for x in self._urls:
755                                 applications.append((x[1], x))
756                 else: applications.append(("No detected HbbTV applications.", None))
757                 self._session.openWithCallback(self._application_selected, ChoiceBox, title=_("Please choose an HbbTV application."), list=applications)
758
759         def _application_selected(self, selected):
760                 try:
761                         if selected[1] is None: return
762                         self._cb_hbbtv_activated(selected[1][1], selected[1][2])
763                 except Exception, ErrMsg: print ErrMsg
764
765         def showBrowserConfigBox(self):
766                 start_stop_mode = []
767                 if self._is_browser_running():
768                         start_stop_mode.append(('Stop',None))
769                 else:   start_stop_mode.append(('Start',None))
770                 self._session.openWithCallback(self._browser_config_selected, ChoiceBox, title=_("Please choose one."), list=start_stop_mode)
771
772         def _browser_config_selected(self, selected):
773                 if selected is None:
774                         return
775                 try:
776                         mode = selected[0]
777                         if mode == 'Start':
778                                 if not self._is_browser_running():
779                                         self._start_opera()
780                         elif mode == 'Stop':
781                                 self._stop_opera()
782                 except Exception, ErrMsg: print "Config ERR :", ErrMsg
783
784         def _is_browser_running(self):
785                 try:
786                         global HBBTVAPP_PATH
787                         ret = os.popen('%s/launcher check'%(HBBTVAPP_PATH)).read()
788                         return ret.strip() != "0"
789                 except Exception, ErrMsg:
790                         print "Check Browser Running ERR :", ErrMsg
791                 return False
792
793 _g_helper = None
794 class OperaBrowser(Screen):
795         MENUBAR_ITEM_WIDTH  = 150
796         MENUBAR_ITEM_HEIGHT = 30
797         SUBMENULIST_WIDTH   = 200
798         SUBMENULIST_HEIGHT  = 25
799         SUBMENULIST_NEXT    = 2
800
801         skin =  """
802                 <screen name="Opera Browser" position="0,0" size="1280,720" backgroundColor="transparent" flags="wfNoBorder" title="Opera Browser">
803                         <widget name="topArea" zPosition="-1" position="0,0" size="1280,60" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
804                         <widget name="menuitemFile" position="30,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
805                         <widget name="menuitemHelp" position="180,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
806                         <widget name="menulist" position="50,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
807                         <widget name="submenulist" position="%d,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
808                         <widget name="bottomArea" position="0,640" size="1280,80" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
809                 </screen>
810                 """ % (MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH, SUBMENULIST_WIDTH+50+SUBMENULIST_NEXT, MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH)
811
812         MENUITEMS_LIST =[[('Open Location', None), ('Start/Stop',None), ('Exit', None)],
813                          [('About', None)]]
814         def __init__(self, session):
815                 Screen.__init__(self, session)
816
817                 self["actions"] = ActionMap(["MinuteInputActions", "ColorActions", "InputActions", "InfobarChannelSelection", "EPGSelectActions", "KeyboardInputActions"], {
818                          "cancel"      : self.keyCancel
819                         ,"ok"          : self.keyOK
820                         ,"left"        : self.keyLeft
821                         ,"right"       : self.keyRight
822                         ,"up"          : self.keyUp
823                         ,"down"        : self.keyDown
824                         ,"menu"        : self.keyCancel
825                 }, -2)
826
827                 self.menubarCurrentIndex = 0
828                 self.lvMenuItems = []
829                 self.lvSubMenuItems = []
830
831                 self["topArea"]    = Label()
832                 self["bottomArea"] = Label()
833
834                 self["menuitemFile"] = MultiColorLabel()
835                 self["menuitemHelp"] = MultiColorLabel()
836
837                 self["menulist"] = MenuList(self.setListOnView())
838                 self["submenulist"] = MenuList(self.setSubListOnView())
839
840                 self.toggleMainScreenFlag = True
841                 self.toggleListViewFlag = False
842                 self.toggleSubListViewFlag = False
843                 self.currentListView = self["menulist"]
844
845                 self.onLayoutFinish.append(self.layoutFinished)
846
847                 self._onCloseTimer = eTimer()
848                 self._onCloseTimer.callback.append(self._cb_onClose)
849
850         def enableRCMouse(self, mode): #mode=[0|1]|[False|True]
851                 rcmouse_path = "/proc/stb/fp/mouse"
852                 if os.path.exists(rcmouse_path):
853                         os.system("echo %d > %s" % (mode, rcmouse_path))
854
855         def layoutFinished(self):
856                 self["menuitemFile"].setText("File")
857                 self["menuitemHelp"].setText("Help")
858
859                 self["menulist"].hide()
860                 self["submenulist"].hide()
861
862                 self["bottomArea"].setText("Opera Web Browser Plugin v0.1")
863                 self.setTitle("BrowserMain")
864                 self.selectMenuitem()
865
866         def selectMenuitem(self):
867                 tmp = [self["menuitemFile"], self["menuitemHelp"]]
868                 self["menuitemFile"].setForegroundColorNum(0)
869                 self["menuitemHelp"].setForegroundColorNum(0)
870                 tmp[self.menubarCurrentIndex].setForegroundColorNum(1)
871
872         def popupCloseAll(self):
873                 self.keyLeft()
874                 self.keyLeft()
875                 self.keyUp()
876                 self.keyCancel()
877
878         def setListOnView(self):
879                 self.lvMenuItems = self.MENUITEMS_LIST[self.menubarCurrentIndex]        
880                 return self.lvMenuItems
881
882         def setSubListOnView(self):
883                 self.lvSubMenuItems = []
884                 xl = self["menulist"].getCurrent()[1]
885                 if xl is None: return []
886                 for x in xl:
887                         self.lvSubMenuItems.append((x,None))
888                 return self.lvSubMenuItems
889
890         def toggleMainScreen(self):
891                 if not self.toggleMainScreenFlag:
892                         self.show()
893                 else:   self.hide()
894                 self.toggleMainScreenFlag = not self.toggleMainScreenFlag
895
896         def toggleListView(self):
897                 if not self.toggleListViewFlag:
898                         self["menulist"].show()
899                 else:   self["menulist"].hide()
900                 self.toggleListViewFlag = not self.toggleListViewFlag
901
902         def toggleSubListView(self):
903                 if not self.toggleSubListViewFlag:
904                         self["submenulist"].show()
905                 else:   self["submenulist"].hide()
906                 self.toggleSubListViewFlag = not self.toggleSubListViewFlag
907
908         def setCurrentListView(self, listViewIdx):
909                 if listViewIdx == 0:
910                         self.currentListView = None
911                 elif listViewIdx == 1:
912                         self.currentListView = self["menulist"]
913                 elif listViewIdx == 2:
914                         self.currentListView = self["submenulist"]
915
916         def _cb_onClose(self):
917                 self._onCloseTimer.stop()
918                 command_server = getCommandServer()
919                 try:
920                         if self._on_close_window in command_server.onHbbTVCloseCB:
921                                         command_server.onHbbTVCloseCB.remove(self._on_close_window)
922                 except Exception, ErrMsg: pass
923                 try:
924                         if self._on_setPageTitle in command_server.onSetPageTitleCB:
925                                 command_server.onSetPageTitleCB.remove(self._on_setPageTitle)
926                 except Exception, ErrMsg: pass
927                 self._on_setPageTitle('Opera Browser')
928                 self.enableRCMouse(False)
929                 self.toggleMainScreen()
930                 eRCInput.getInstance().unlock()
931
932         def _on_setPageTitle(self, title=None):
933                 print "page title :",title
934                 if title is None:
935                         return
936                 self.setTitle(title)
937
938         def cbUrlText(self, data=None):
939                 print "Inputed Url :", data
940                 if strIsEmpty(data):
941                         return
942                 command_server = getCommandServer()
943                 if self._on_setPageTitle not in command_server.onSetPageTitleCB:
944                                 command_server.onSetPageTitleCB.append(self._on_setPageTitle)
945                 if self._on_close_window not in command_server.onHbbTVCloseCB:
946                         command_server.onHbbTVCloseCB.append(self._on_close_window)
947                 self.toggleMainScreen()
948                 self.enableRCMouse(True)
949                 eRCInput.getInstance().lock()
950                 command_util = getCommandUtil()
951                 command_util.sendCommand('OP_BROWSER_OPEN_URL', data)
952
953         def _on_close_window(self):
954                 self._onCloseTimer.start(1000)
955
956         def _cmd_on_OpenLocation(self):
957                 global _g_helper
958                 if not _g_helper._is_browser_running():
959                         message = "Opera Browser was not running.\nPlease running browser using [File]>[Start/Stop] menu."
960                         self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
961                         return
962                 self.session.openWithCallback(self.cbUrlText, VirtualKeyBoard, title=("Please enter URL here"), text='http://')
963         def _cmd_on_About(self):
964                 self.session.open(MessageBox, 'Opera Web Browser Plugin v0.1(beta)', type = MessageBox.TYPE_INFO)
965         def _cmd_on_Exit(self):
966                 self.close()
967         def _cmd_on_StartStop(self):
968                 global _g_helper
969                 if _g_helper is None: 
970                         return
971                 _g_helper.showBrowserConfigBox()
972         def doCommand(self, command):
973                 cmd_map = {
974                          'Exit'          :self._cmd_on_Exit
975                         ,'About'         :self._cmd_on_About
976                         ,'Open Location' :self._cmd_on_OpenLocation
977                         ,'Start/Stop'    :self._cmd_on_StartStop
978                 }
979                 try:
980                         cmd_map[command]()
981                 except: pass
982
983         def keyOK(self):
984                 if not self.toggleListViewFlag:
985                         self.keyDown()
986                         return
987                 if self.currentListView.getCurrent()[1] is None:
988                         self.doCommand(self.currentListView.getCurrent()[0])
989                         #self.session.open(MessageBox, _(self.currentListView.getCurrent()[0]), type = MessageBox.TYPE_INFO)
990                         return
991                 self.keyRight()
992
993         def updateSelectedMenuitem(self, status):
994                 if self.menubarCurrentIndex == 0 and status < 0:
995                         self.menubarCurrentIndex = 1
996                 elif self.menubarCurrentIndex == 1 and status > 0:
997                         self.menubarCurrentIndex = 0
998                 else:   self.menubarCurrentIndex += status
999                 self.selectMenuitem()
1000
1001         def keyLeft(self):
1002                 if not self.toggleMainScreenFlag:
1003                         return
1004                 if not self.toggleListViewFlag:
1005                         self.updateSelectedMenuitem(-1)
1006                         return
1007                 if self.toggleSubListViewFlag:
1008                         self.setCurrentListView(1)
1009                         self.toggleSubListView()
1010                         return
1011                 if self.currentListView.getSelectedIndex():
1012                         self.currentListView.pageUp()
1013
1014         def keyRight(self):
1015                 if not self.toggleMainScreenFlag:
1016                         return
1017                 if not self.toggleListViewFlag:
1018                         self.updateSelectedMenuitem(1)
1019                         return
1020                 if self.currentListView is None:
1021                         return
1022                 if self.currentListView.getCurrent()[1] is not None:
1023                         parentSelectedIndex = self.currentListView.getSelectedIndex()
1024                         self.setCurrentListView(2)
1025                         self.currentListView.setList(self.setSubListOnView())
1026                         self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvSubMenuItems)+5)
1027                         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))
1028                         self.toggleSubListView()
1029
1030         def keyDown(self):
1031                 if not self.toggleMainScreenFlag:
1032                         return
1033                 if self.currentListView is None:
1034                         return
1035                 if not self.toggleListViewFlag:
1036                         self.currentListView.setList(self.setListOnView())
1037                         self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvMenuItems)+5)
1038                         self.currentListView.move(self.MENUBAR_ITEM_WIDTH*self.menubarCurrentIndex+1+ 50,self.MENUBAR_ITEM_HEIGHT+30)
1039                         self.toggleListView()
1040                         return
1041                 self.currentListView.down()
1042
1043         def keyUp(self):
1044                 if not self.toggleMainScreenFlag:
1045                         return
1046                 if self.currentListView is None:
1047                         return
1048                 if self.currentListView == self["menulist"]:
1049                         if self.currentListView.getSelectedIndex() == 0:
1050                                 self.toggleListView()
1051                                 return
1052                 self.currentListView.up()
1053
1054         def keyCancel(self):
1055                 self.toggleMainScreen()
1056
1057 def auto_start_main(reason, **kwargs):
1058         if reason:
1059                 command_server = getCommandServer()
1060                 command_server.stop()
1061
1062 def session_start_main(session, reason, **kwargs):
1063         global _g_helper
1064         _g_helper = session.open(HbbTVHelper)
1065
1066 def plugin_start_main(session, **kwargs):
1067         session.open(OperaBrowser)
1068
1069 def plugin_extension_start_application(session, **kwargs):
1070         global _g_helper
1071         if _g_helper is None: 
1072                 return
1073         _g_helper.showApplicationSelectionBox()
1074
1075 def plugin_extension_browser_config(session, **kwargs):
1076         global _g_helper
1077         if _g_helper is None: 
1078                 return
1079         _g_helper.showBrowserConfigBox()
1080
1081 def Plugins(path, **kwargs):
1082         return  [
1083                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=auto_start_main),
1084                 PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, needsRestart=True, fnc=session_start_main, weight=-10),
1085                 PluginDescriptor(name="HbbTV Applications", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_start_application),
1086                 PluginDescriptor(name="Browser Start/Stop", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_browser_config),
1087                 PluginDescriptor(name="Opera Web Browser", description="start opera web browser", where=PluginDescriptor.WHERE_PLUGINMENU, needsRestart=True, fnc=plugin_start_main)
1088                 ]
1089