- add opera browser.(with hbbtv)
[vuplus_dvbapp] / lib / python / Plugins / Extensions / HbbTV / plugin.py
diff --git a/lib/python/Plugins/Extensions/HbbTV/plugin.py b/lib/python/Plugins/Extensions/HbbTV/plugin.py
new file mode 100644 (file)
index 0000000..9ae4d2e
--- /dev/null
@@ -0,0 +1,1082 @@
+from Plugins.Plugin import PluginDescriptor
+
+from Screens.Screen import Screen
+from Screens.InfoBar import InfoBar
+from Screens.ChoiceBox import ChoiceBox
+from Screens.MessageBox import MessageBox
+from Screens.InfoBarGenerics import InfoBarNotifications
+from Screens.VirtualKeyBoard import VirtualKeyBoard
+
+from Components.PluginComponent import plugins
+from Components.Button import Button
+from Components.Label import Label
+from Components.Sources.StaticText import StaticText
+from Components.ActionMap import NumberActionMap, ActionMap
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.MenuList import MenuList
+from Components.Label import Label, MultiColorLabel
+from Components.ConfigList import ConfigListScreen
+from Components.config import config, ConfigSubsection, ConfigPosition, getConfigListEntry, ConfigBoolean, ConfigInteger, ConfigText, ConfigSelection, configfile, getCharValue
+
+from enigma import eTimer, eConsoleAppContainer, getDesktop, eServiceReference, iPlayableService, iServiceInformation, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER, getPrevAsciiCode, eRCInput, fbClass
+
+import os, struct, threading, stat, select, time, socket, select
+
+strIsEmpty = lambda x: x is None or len(x) == 0
+
+HBBTVAPP_PATH = "/usr/local/hbb-browser"
+COMMAND_PATH = '/tmp/.sock.hbbtv.cmd'
+
+class GlobalValues:
+       command_util   = None
+       command_server = None
+
+       before_service = None
+
+       channel_info_sid   = None
+       channel_info_onid  = None
+       channel_info_tsid  = None
+       channel_info_name  = None
+       channel_info_orgid = None
+
+       hbbtv_handelr = None
+
+       packet_m  = 0xBBADBEE
+       packet_h  = '!IIII'
+       packet_hl = struct.calcsize(packet_h)
+__gval__ = GlobalValues()
+
+def getPacketHeaders():
+       global __gval__
+       return (__gval__.packet_m, __gval__.packet_h, __gval__.packet_hl)
+
+def setChannelInfo(sid, onid, tsid, name, orgid):
+       if sid is None:   sid   = 0;
+       if onid is None:  onid  = 0;
+       if tsid is None:  tsid  = 0;
+       if name is None:  name  = "";
+       if orgid is None: orgid = 0;
+       global __gval__
+       __gval__.channel_info_sid   = sid
+       __gval__.channel_info_onid  = onid
+       __gval__.channel_info_tsid  = tsid
+       __gval__.channel_info_name  = name
+       __gval__.channel_info_orgid = orgid
+       print "Set Channel Info >> sid : %X, onid : %X, tsid : %X, name : %s, orgid : %d " % (sid, onid, tsid, name, orgid)
+def getChannelInfos():
+       global __gval__
+       print "Get Channel Info >> sid : %X, onid : %X, tsid : %X, name : %s, orgid : %d " % (__gval__.channel_info_sid, 
+               __gval__.channel_info_onid, __gval__.channel_info_tsid, __gval__.channel_info_name, __gval__.channel_info_orgid)
+       return (__gval__.channel_info_sid, 
+               __gval__.channel_info_onid, 
+               __gval__.channel_info_tsid, 
+               __gval__.channel_info_name, 
+               __gval__.channel_info_orgid)
+
+def getCommandUtil():
+       global __gval__
+       return __gval__.command_util
+def getCommandServer():
+       global __gval__
+       return __gval__.command_server
+
+def setBeforeService(s):
+       global __gval__
+       __gval__.before_service = s
+def getBeforeService():
+       global __gval__
+       return __gval__.before_service
+
+def _unpack(packed_data):
+       (mg, h, hlen) = getPacketHeaders()
+
+       if strIsEmpty(packed_data):
+               return None
+       (m, o, l, s) = struct.unpack(h, packed_data[:hlen])
+       if m != mg:
+               return None
+       d = 0
+       if l > 0:
+               d = packed_data[hlen:hlen+l]
+       return (o,d,s)
+
+def _pack(opcode, params=None, reserved=0):
+       (m, h, hlen) = getPacketHeaders()
+       if strIsEmpty(params):
+               params = ''
+       packed_data = struct.pack(h, m, opcode, len(params), reserved)
+       return packed_data + params
+
+class MMSStreamURL:
+       headers = [
+                   'GET %s HTTP/1.0'
+                  ,'Accept: */* '
+                  ,'User-Agent: NSPlayer/7.10.0.3059 '
+                  ,'Host: %s '
+                  ,'Connection: Close '
+                 ]
+
+       def __init__(self):
+               self.sendmsg = ''
+               for m in self.headers:
+                       self.sendmsg += m + '\n'
+               self.sendmsg += '\n\n'
+
+       def request(self, host, port=80, location='/'):
+               sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+               sock.connect((host, port))
+               sock.send(self.sendmsg%(location, host))
+               print "Send Data : "
+               print self.sendmsg%(location, host)
+               fullydata = ''
+               while 1:
+                       res = sock.recv(1024)
+                       if res == '': break
+                       fullydata += res
+               sock.close()
+               return fullydata
+
+       def parse(self, data):
+               for d in data.splitlines():
+                       if d.startswith('Location: '):
+                               return d[9:]
+               return None
+
+       def getLocationData(self, url):
+               url_list,host,location = None,None,None
+               try:
+                       url = url[url.find(':')+3:]
+                       url_list = url.split('/')
+                       host = url_list[0]
+                       location = url[len(url_list[0]):]
+               except Exception, err_msg:
+                       print err_msg
+                       return None
+               html = self.request(host=host, location=location)
+               return self.parse(html)
+
+class OpCodeSet:
+       def __init__(self):
+               self._opcode_ = {
+                        "OP_UNKNOWN"                   : 0x0000
+                       ,"OP_HBBTV_EXIT"                : 0x0001
+                       ,"OP_HBBTV_OPEN_URL"            : 0x0002
+                       ,"OP_HBBTV_LOAD_AIT"            : 0x0003
+                       ,"OP_HBBTV_UNLOAD_AIT"          : 0x0004
+                       ,"OP_HBBTV_FULLSCREEN"          : 0x0005
+                       ,"OP_HBBTV_TITLE"               : 0x0006
+                       ,"OP_OIPF_GET_CHANNEL_INFO_URL" : 0x0101
+                       ,"OP_OIPF_GET_CHANNEL_INFO_AIT" : 0x0102
+                       ,"OP_OIPF_GET_CHANNEL_INFO_LIST": 0x0103
+                       ,"OP_VOD_URI"                   : 0x0201
+                       ,"OP_VOD_PLAY"                  : 0x0202
+                       ,"OP_VOD_STOP"                  : 0x0203
+                       ,"OP_VOD_PAUSE"                 : 0x0204
+                       ,"OP_VOD_STATUS"                : 0x0205
+                       ,"OP_VOD_FORBIDDEN"             : 0x0206
+                       ,"OP_BROWSER_OPEN_URL"          : 0x0301
+               }
+               self._opstr_ = {
+                        0x0000 : "OP_UNKNOWN"
+                       ,0x0001 : "OP_HBBTV_EXIT"
+                       ,0x0002 : "OP_HBBTV_OPEN_URL"
+                       ,0x0003 : "OP_HBBTV_LOAD_AIT"
+                       ,0x0004 : "OP_HBBTV_UNLOAD_AIT"
+                       ,0x0005 : "OP_HBBTV_FULLSCREEN"
+                       ,0x0006 : "OP_HBBTV_TITLE"
+                       ,0x0101 : "OP_OIPF_GET_CHANNEL_INFO_URL"
+                       ,0x0102 : "OP_OIPF_GET_CHANNEL_INFO_AIT"
+                       ,0x0103 : "OP_OIPF_GET_CHANNEL_INFO_LIST"
+                       ,0x0201 : "OP_VOD_URI"
+                       ,0x0202 : "OP_VOD_PLAY"
+                       ,0x0203 : "OP_VOD_STOP"
+                       ,0x0204 : "OP_VOD_PAUSE"
+                       ,0x0205 : "OP_VOD_STATUS"
+                       ,0x0206 : "OP_VOD_FORBIDDEN"
+                       ,0x0301 : "OP_BROWSER_OPEN_URL"
+               }
+
+       def get(self, opstr):
+               try:
+                       return self._opcode_[opstr]
+               except: pass
+               return self._opcode_["OP_UNKNOWN"]
+
+       def what(self, opcode):
+               try:
+                       return self._opstr_[opcode]
+               except: pass
+               return self._opstr_["0x0000"]
+
+class SocketParams:
+       def __init__(self):
+               self.protocol = None
+               self.type     = None
+               self.addr     = None
+               self.buf_size = 4096
+               self.handler  = None
+               self.timeout  = 5
+               self.destroy  = None
+
+class StreamServer:
+       def __init__(self, params):
+               self._protocol = params.protocol
+               self._type     = params.type
+               self._addr     = params.addr
+               self._buf_size = params.buf_size
+               self._handler  = params.handler
+               self._timeout  = params.timeout
+               self._destroy  = params.destroy
+
+               self._terminated = False
+               self._server_thread = None
+
+               self.onHbbTVCloseCB = []
+               self.onSetPageTitleCB = []
+
+       def __del__(self):
+               if self._destroy is not None:
+                       self._destroy(self._addr)
+
+       def stop(self):
+               self._terminated = True
+               if self._server_thread is not None:
+                       self._server_thread.join()
+                       self._server_thread = None
+
+       def start(self):
+               self._socket = socket.socket(self._protocol, self._type)
+               self._socket.settimeout(self._timeout)
+               self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+               self._socket.bind(self._addr)
+               self._socket.listen(True)
+
+               self._server_thread = threading.Thread(target=self._listen)
+               self._server_thread.start()
+
+       def _listen(self):
+               select_list = [self._socket]
+               def _accept():
+                       try:
+                               conn, addr = self._socket.accept()
+                               self._client(conn, addr)
+                       except Exception, ErrMsg:
+                               print "ServerSocket Error >>", ErrMsg
+                               pass
+
+               while not self._terminated:
+                       readable, writable, errored = select.select(select_list, [], [], self._timeout)
+                       for s in readable:
+                               if s is self._socket:
+                                       _accept()
+
+       def _client(self, conn, addr):
+               try:
+                       send_data     = ''
+                       received_data = conn.recv(self._buf_size)
+                       if self._handler is not None and not strIsEmpty(received_data):
+                               send_data = self._handler.doHandle(received_data, self.onHbbTVCloseCB, self.onSetPageTitleCB)
+                       self._send(conn, send_data)
+               except Exception, ErrMsg: 
+                       try: conn.close()
+                       except:pass
+                       if self._handler is not None:
+                               self._handler.printError(ErrMsg)
+       def _send(self, conn, data) :
+               conn.send(data)
+               conn.close()
+
+class ServerFactory:
+       def doListenUnixTCP(self, name, handler):
+               def destroy(name):
+                       if os.path.exists(name):
+                               os.unlink(name)
+                               print "Removed ", name
+               destroy(name)
+
+               params = SocketParams()
+               params.protocol = socket.AF_UNIX
+               params.type     = socket.SOCK_STREAM
+               params.addr     = name
+               params.handler  = handler
+               params.destroy  = destroy
+
+               streamServer = StreamServer(params)
+               streamServer.start()
+               return streamServer
+
+       def doListenInetTCP(self, ip, port, handler):
+               print "not implemented yet!!"
+       def doListenUnixDGRAM(self, name, handler):
+               print "not implemented yet!!"
+       def doListenInetDGRAM(self, ip, port, handler):
+               print "not implemented yet!!"
+
+class Handler:
+       def doUnpack(self, data):
+               return _unpack(data)
+
+       def doPack(self, opcode, params, reserved=0):
+               return _pack(opcode, params, reserved)
+
+       def doHandle(self, data, onCloseCB):
+               opcode, params = 0x0, 'Invalid Request!!'
+               return _pack(opcode, params)
+
+       def printError(self, reason):
+               print reason
+
+class BrowserCommandUtil(OpCodeSet):
+       def __init__(self):
+               self._fd = None
+               OpCodeSet.__init__(self)
+
+       def isConnected(self):
+               if self._fd is None:
+                       return False
+               return True
+
+       def doConnect(self, filename):
+               if not os.path.exists(filename):
+                       print "file not exists :", filename
+                       return False
+               try:
+                       self._fd = os.open(filename, os.O_WRONLY|os.O_NONBLOCK)
+                       if self._fd is None:
+                               print "fail to open file :", filename
+                               return False
+               except Exception, ErrMsg:
+                       print ErrMsg
+                       self._fd = None
+                       return False
+               print "connected!! to ", filename
+               return True
+
+       def doDisconnect(self):
+               if self._fd is None:
+                       return
+               os.close(self._fd)
+               self._fd = None
+
+       def doSend(self, command, params=None, reserved=0):
+               if self._fd is None:
+                       print "connected pipe was not exists!!"
+                       return False
+               data = ''
+               try:
+                       data = _pack(self.get(command), params, reserved)
+                       if data is None:
+                               return False
+                       os.write(self._fd, data)
+                       print "Send OK!! :", command
+               except: return False
+               return True
+
+       def sendCommand(self, command, params=None, reserved=0):
+               if not self.isConnected():
+                       global COMMAND_PATH
+                       self.doConnect(COMMAND_PATH)
+               result = self.doSend(command, params, reserved)
+               self.doDisconnect()
+               return result
+
+class HandlerHbbTV(Handler):
+       _vod_service = None
+       def __init__(self, session):
+               self._session = session
+               self.opcode = OpCodeSet()
+               self.handle_map = {
+                        0x0001 : self._cb_handleCloseHbbTVBrowser
+                       ,0x0006 : self._cb_handleSetPageTitle
+                       ,0x0101 : self._cb_handleGetChannelInfoForUrl
+                       ,0x0102 : self._cb_handleGetChannelInfoForAIT
+                       ,0x0103 : self._cb_handleGetChannelInfoList
+                       ,0x0201 : self._cb_handleVODPlayerURI
+                       ,0x0202 : self._cb_handleVODPlayerPlay
+                       ,0x0203 : self._cb_handleVODPlayerStop
+                       ,0x0204 : self._cb_handleVODPlayerPlayPause
+               }
+               self._on_close_cb = None
+               self._on_set_title_cb = None
+
+               self._vod_uri = None
+
+       def _handle_dump(self, handle, opcode, data=None):
+               if True: return
+               print str(handle)
+               try:
+                       print "    - opcode : ", self.opcode.what(opcode)
+               except: pass
+               print "    - data   : ", data
+
+       def doHandle(self, data, onCloseCB, onSetPageTitleCB):
+               opcode, params, reserved = None, None, 0
+               self._on_close_cb = onCloseCB
+               self._on_set_title_cb = onSetPageTitleCB
+               try:
+                       datas  = self.doUnpack(data)
+               except Exception, ErrMsg:
+                       print "Unpacking packet ERR :", ErrMsg
+                       params = 'fail to unpack packet!!'
+                       opcode = self.opcode.get("OP_UNKNOWN")
+                       return self.doPack(opcode, params)
+               else:
+                       opcode = datas[0]
+                       params = datas[1]
+               self.opcode.what(opcode)
+
+               try:
+                       #print self.handle_map[opcode]
+                       (reserved, params) = self.handle_map[opcode](opcode, params)
+               except Exception, ErrMsg:
+                       print "Handling packet ERR :", ErrMsg
+                       params = 'fail to handle packet!!'
+                       opcode = self.opcode.get("OP_UNKNOWN")
+                       return self.doPack(opcode, params)
+               self._on_close_cb = None
+               self._on_set_title_cb = None
+               return self.doPack(opcode, params, reserved)
+
+       def _cb_handleGetChannelInfoForUrl(self, opcode, data):
+               self._handle_dump(self._cb_handleGetChannelInfoForUrl, opcode, data)
+               (sid, onid, tsid, name, orgid) = getChannelInfos()
+               namelen = len(name)
+               return (0, struct.pack('!IIII', sid, onid, tsid, namelen) + name)
+
+       def _cb_handleGetChannelInfoForAIT(self, opcode, data):
+               self._handle_dump(self._cb_handleGetChannelInfoForAIT, opcode, data)
+               (sid, onid, tsid, name, orgid) = getChannelInfos()
+               namelen = len(name)
+               return (0, struct.pack('!IIIII', orgid, sid, onid, tsid, namelen) + name)
+
+       def _cb_handleGetChannelInfoList(self, opcode, data):
+               self._handle_dump(self._cb_handleGetChannelInfoList, opcode, data)
+               (sid, onid, tsid, name, orgid) = getChannelInfos()
+               namelen = len(name)
+               channel_list_size = 1
+               return (channel_list_size, struct.pack('!IIII', sid, onid, tsid, namelen) + name)
+
+       def _cb_handleSetPageTitle(self, opcode, data):
+               self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
+               if data.startswith('file://') or data.startswith('http://'):
+                       return "OK"
+               if self._on_set_title_cb is not None:
+                       for x in self._on_set_title_cb:
+                               try:
+                                       x(data)
+                               except Exception, ErrMsg:
+                                       if x in self._on_set_title_cb:
+                                               self._on_set_title_cb.remove(x)
+               return (0, "OK")
+
+       def _cb_handleCloseHbbTVBrowser(self, opcode, data):
+               self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
+
+               if self._on_close_cb:
+                       for x in self._on_close_cb:
+                               try:
+                                       x()
+                               except Exception, ErrMsg:
+                                       if x in self._on_close_cb:
+                                               self._on_close_cb.remove(x)
+
+               command_util = getCommandUtil()
+               command_util.sendCommand('OP_HBBTV_FULLSCREEN', None)
+
+               before_service = getBeforeService()
+               if before_service is not None:
+                       self._session.nav.playService(before_service)
+               return (0, "OK")
+
+       def _cb_handleVODPlayerURI(self, opcode, data):
+               self._vod_uri = None
+               hl = struct.calcsize('!II')
+               datas = struct.unpack('!II', data[:hl])
+               uriLength = datas[1]
+               vodUri = data[hl:hl+uriLength]
+               self._handle_dump(self._cb_handleVODPlayerURI, opcode, vodUri)
+               self._vod_uri = vodUri
+               return (0, "OK")
+
+       def doStop(self, restoreBeforeService=True, needStop=True):
+               if needStop == True:
+                       self._session.nav.stopService()
+               if self._vod_service is not None and restoreBeforeService:
+                       before_service = getBeforeService()
+                       self._session.nav.playService(before_service)
+                       self._vod_uri = None
+               self._vod_service = None
+
+       def getUrl(self):
+               return self._vod_uri
+
+       def doRetryOpen(self, url):
+               if url is None:
+                       return False
+               for ii in range(5):
+                       self._vod_service = None
+                       try:
+                               print "try to open vod [%d] : %s" % (ii, url)
+                               self._vod_service = eServiceReference(4097, 0, url)
+                               self._session.nav.playService(self._vod_service)
+                               if self._vod_service is not None:
+                                       return True
+                       except Exception, ErrMsg: 
+                               print "OpenVOD ERR :", ErrMsg
+                       time.sleep(1)
+               return False
+
+       def _cb_handleVODPlayerPlay(self, opcode, data):
+               self._handle_dump(self._cb_handleVODPlayerPlay, opcode, data)
+               self.doStop(restoreBeforeService=False)
+               if self.doRetryOpen(url=self._vod_uri) == False:
+                       self.doStop()
+               return (0, "OK")
+
+       def _cb_handleVODPlayerStop(self, opcode, data):
+               self._handle_dump(self._cb_handleVODPlayerStop, opcode, data)
+               self.doStop()   
+               return (0, "OK")
+
+       def _cb_handleVODPlayerPlayPause(self, opcode, data):
+               self._handle_dump(self._cb_handleVODPlayerPlayPause, opcode, data)
+               service = self._session.nav.getCurrentService()
+               try:
+                       pauseFlag = data[0]
+                       servicePause = service.pause()
+                       if pauseFlag == 'U':
+                               servicePause.unpause()
+                       elif pauseFlag == 'P':
+                               servicePause.pause()
+               except Exception, ErrMsg:
+                       print "onPause ERR :", ErrMsg
+               return (0, "OK")
+
+class HbbTVWindow(Screen, InfoBarNotifications):
+       skin =  """
+               <screen name="HbbTVWindow" position="0,0" size="1280,720" backgroundColor="transparent" flags="wfNoBorder" title="HbbTV Plugin">
+               </screen>
+               """
+       def __init__(self, session, url=None, cbf=None, useAIT=False):
+               self._session = session
+               eRCInput.getInstance().lock()
+
+               Screen.__init__(self, session)
+               InfoBarNotifications.__init__(self)
+               self.__event_tracker = ServiceEventTracker(screen = self, eventmap = {
+                       iPlayableService.evUser+20: self._serviceForbiden,
+               })
+
+               self._url = url
+               self._use_ait = useAIT
+               self._cb_closed_func = cbf
+               self.onLayoutFinish.append(self._layoutFinished)
+
+               command_server = getCommandServer()
+               if self._cb_set_page_title not in command_server.onSetPageTitleCB:
+                       command_server.onSetPageTitleCB.append(self._cb_set_page_title)
+
+               if self._cb_close_window not in command_server.onHbbTVCloseCB:
+                       command_server.onHbbTVCloseCB.append(self._cb_close_window)
+
+               self._closeTimer = eTimer()
+               self._closeTimer.callback.append(self._do_close)
+
+       def _layoutFinished(self):
+               command_util = getCommandUtil()
+               (sid, onid, tsid, name, orgid) = getChannelInfos()
+               params  = struct.pack('!IIIII', orgid, sid, onid, tsid, len(name)) + name
+               if self._use_ait:
+                       command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
+                       time.sleep(1)
+                       command_util.sendCommand('OP_HBBTV_LOAD_AIT', params, 1)
+                       return
+               command_util.sendCommand('OP_HBBTV_LOAD_AIT', params)
+               time.sleep(1)
+               command_util.sendCommand('OP_HBBTV_OPEN_URL', self._url)
+
+       def _cb_close_window(self):
+               self._closeTimer.start(1000)
+
+       def _do_close(self):
+               self._closeTimer.stop()
+               command_server = getCommandServer()
+               try:
+                       if self._cb_set_page_title in command_server.onSetPageTitleCB:
+                               command_server.onSetPageTitleCB.remove(self._cb_set_page_title)
+               except Exception, ErrMsg: pass
+               try:
+                       if self._cb_close_window in command_server.onHbbTVCloseCB:
+                                       command_server.onHbbTVCloseCB.remove(self._cb_close_window)
+               except Exception, ErrMsg: pass
+               try:
+                       if self._cb_closed_func is not None:
+                               self._cb_closed_func()
+               except: pass
+               eRCInput.getInstance().unlock()
+               self.close()
+
+       def _serviceForbiden(self):
+               global __gval__
+               real_url = MMSStreamURL().getLocationData(__gval__.hbbtv_handelr.getUrl())
+               print "Received URI :\n",real_url
+
+               if real_url is not None:
+                       __gval__.hbbtv_handelr.doRetryOpen(real_url.strip())
+
+       def _cb_set_page_title(self, title=None):
+               print "page title :",title
+               if title is None:
+                       return
+               self.setTitle(title)
+
+class HbbTVHelper(Screen):
+       skin =  """<screen name="HbbTVHelper" position="0,0" size="0,0" backgroundColor="transparent" flags="wfNoBorder" title=" "></screen>"""
+       def __init__(self, session):
+               global __gval__
+               __gval__.hbbtv_handelr = HandlerHbbTV(session)
+               __gval__.command_server = ServerFactory().doListenUnixTCP('/tmp/.sock.hbbtv.url', __gval__.hbbtv_handelr)
+
+               self._urls = None
+               self._stop_opera()
+               self._start_opera()
+
+               Screen.__init__(self, session)
+               self._session = session
+               self._timer_infobar = eTimer()
+               self._timer_infobar.callback.append(self._cb_registrate_infobar)
+               self._timer_infobar.start(1000)
+
+               self._excuted_browser = False
+
+               __gval__.command_util = BrowserCommandUtil()
+
+       def _cb_registrate_infobar(self):
+               if InfoBar.instance:
+                       self._timer_infobar.stop()
+                       if self._cb_ready_for_ait not in InfoBar.instance.onReadyForAIT:
+                               InfoBar.instance.onReadyForAIT.append(self._cb_ready_for_ait)
+                       if self._cb_hbbtv_activated not in InfoBar.instance.onHBBTVActivation:
+                               InfoBar.instance.onHBBTVActivation.append(self._cb_hbbtv_activated)
+
+       def _cb_ready_for_ait(self, orgId=0):
+               if orgId == 0:
+                       if not self._excuted_browser:
+                               command_util = getCommandUtil()
+                               command_util.sendCommand('OP_HBBTV_UNLOAD_AIT')
+                       return
+               setChannelInfo(None, None, None, None, None)
+
+               service = self._session.nav.getCurrentService()
+                info = service and service.info()
+               if info is not None:
+                       sid  = info.getInfo(iServiceInformation.sSID)
+                       onid = info.getInfo(iServiceInformation.sONID)
+                       tsid = info.getInfo(iServiceInformation.sTSID)
+                       name = info.getName()
+                       if name is None:
+                               name = ""
+                       orgid   = 0
+                       namelen = len(name)
+                       for x in info.getInfoObject(iServiceInformation.sHBBTVUrl):
+                               if x[0] == 1 :
+                                       orgid = x[3]
+                                       break
+                       setChannelInfo(sid, onid, tsid, name, orgid)
+
+       def _cb_hbbtv_activated(self, title=None, url=None):
+               if not self._is_browser_running():
+                       message = "HbbTV Browser was not running.\nPlease running browser before start HbbTV Application."
+                       self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
+                       return
+               service = self._session.nav.getCurrentlyPlayingServiceReference()
+               setBeforeService(service)
+               self._start_hbbtv_application(title, url)
+
+       def _start_hbbtv_application(self, title, url):
+               tmp_url = self.getStartHbbTVUrl()
+               if url is None:
+                       url = tmp_url
+               if strIsEmpty(url):
+                       print "can't get url of hbbtv!!"
+                       return
+               print "success to get url of hbbtv!! >>", url
+               if self._excuted_browser:
+                       print "already excuted opera browser!!"
+                       return
+
+               use_ait = False
+               for x in self._urls:
+                       control_code = x[0]
+                       tmp_url = x[2]
+                       if tmp_url == url and control_code == 1:
+                               use_ait = True
+               self._excuted_browser = True
+               self._session.open(HbbTVWindow, url, self._cb_closed_browser, use_ait)
+
+       def _cb_closed_browser(self):
+               self._excuted_browser = False
+
+       def _start_opera(self):
+               if not self._is_browser_running():
+                       global HBBTVAPP_PATH
+                       start_command = '%s/launcher start'%(HBBTVAPP_PATH)
+                       os.system(start_command)
+
+       def _stop_opera(self):
+               global HBBTVAPP_PATH
+               try:    os.system('%s/launcher stop'%(HBBTVAPP_PATH))
+               except: pass
+
+       def getStartHbbTVUrl(self):
+               url, self._urls = None, None
+                service = self._session.nav.getCurrentService()
+                info = service and service.info()
+                if not info: return None
+                self._urls = info.getInfoObject(iServiceInformation.sHBBTVUrl)
+               for u in self._urls:
+                       if u[0] == 1: # 0:control code, 1:name, 2:url, 3:orgid, 4:appid
+                               url = u[2]
+               if url is None:
+                       url = info.getInfoString(iServiceInformation.sHBBTVUrl)
+               return url
+
+       def showApplicationSelectionBox(self):
+               applications = []
+               if self.getStartHbbTVUrl():
+                       for x in self._urls:
+                               applications.append((x[1], x))
+               else: applications.append(("No detected HbbTV applications.", None))
+               self._session.openWithCallback(self._application_selected, ChoiceBox, title=_("Please choose an HbbTV application."), list=applications)
+
+       def _application_selected(self, selected):
+               try:
+                       if selected[1] is None: return
+                       self._cb_hbbtv_activated(selected[1][1], selected[1][2])
+               except Exception, ErrMsg: print ErrMsg
+
+       def showBrowserConfigBox(self):
+               start_stop_mode = []
+               if self._is_browser_running():
+                       start_stop_mode.append(('Stop',None))
+               else:   start_stop_mode.append(('Start',None))
+               self._session.openWithCallback(self._browser_config_selected, ChoiceBox, title=_("Please choose one."), list=start_stop_mode)
+
+       def _browser_config_selected(self, selected):
+               if selected is None:
+                       return
+               try:
+                       mode = selected[0]
+                       if mode == 'Start':
+                               if not self._is_browser_running():
+                                       self._start_opera()
+                       elif mode == 'Stop':
+                               self._stop_opera()
+               except Exception, ErrMsg: print "Config ERR :", ErrMsg
+
+       def _is_browser_running(self):
+               try:
+                       global HBBTVAPP_PATH
+                       ret = os.popen('%s/launcher check'%(HBBTVAPP_PATH)).read()
+                       return ret.strip() != "0"
+               except Exception, ErrMsg:
+                       print "Check Browser Running ERR :", ErrMsg
+               return False
+
+_g_helper = None
+class OperaBrowser(Screen):
+       MENUBAR_ITEM_WIDTH  = 150
+       MENUBAR_ITEM_HEIGHT = 30
+       SUBMENULIST_WIDTH   = 200
+       SUBMENULIST_HEIGHT  = 25
+       SUBMENULIST_NEXT    = 2
+
+       skin =  """
+               <screen name="Opera Browser" position="0,0" size="1280,720" backgroundColor="transparent" flags="wfNoBorder" title="Opera Browser">
+                       <widget name="topArea" zPosition="-1" position="0,0" size="1280,60" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
+                       <widget name="menuitemFile" position="30,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
+                       <widget name="menuitemHelp" position="180,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
+                       <widget name="menulist" position="50,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
+                       <widget name="submenulist" position="%d,%d" size="%d,150" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
+                       <widget name="bottomArea" position="0,640" size="1280,80" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" />
+               </screen>
+               """ % (MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH, SUBMENULIST_WIDTH+50+SUBMENULIST_NEXT, MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH)
+
+       MENUITEMS_LIST =[[('Open Location', None), ('Start/Stop',None), ('Exit', None)],
+                        [('About', None)]]
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self["actions"] = ActionMap(["MinuteInputActions", "ColorActions", "InputActions", "InfobarChannelSelection", "EPGSelectActions", "KeyboardInputActions"], {
+                        "cancel"      : self.keyCancel
+                       ,"ok"          : self.keyOK
+                       ,"left"        : self.keyLeft
+                       ,"right"       : self.keyRight
+                       ,"up"          : self.keyUp
+                       ,"down"        : self.keyDown
+                       ,"menu"        : self.keyCancel
+               }, -2)
+
+               self.menubarCurrentIndex = 0
+               self.lvMenuItems = []
+               self.lvSubMenuItems = []
+
+               self["topArea"]    = Label()
+               self["bottomArea"] = Label()
+
+               self["menuitemFile"] = MultiColorLabel()
+               self["menuitemHelp"] = MultiColorLabel()
+
+               self["menulist"] = MenuList(self.setListOnView())
+               self["submenulist"] = MenuList(self.setSubListOnView())
+
+               self.toggleMainScreenFlag = True
+               self.toggleListViewFlag = False
+               self.toggleSubListViewFlag = False
+               self.currentListView = self["menulist"]
+
+               self.onLayoutFinish.append(self.layoutFinished)
+
+               self._onCloseTimer = eTimer()
+               self._onCloseTimer.callback.append(self._cb_onClose)
+
+       def enableRCMouse(self, mode): #mode=[0|1]|[False|True]
+               rcmouse_path = "/proc/stb/fp/mouse"
+               if os.path.exists(rcmouse_path):
+                       os.system("echo %d > %s" % (mode, rcmouse_path))
+
+       def layoutFinished(self):
+               self["menuitemFile"].setText("File")
+               self["menuitemHelp"].setText("Help")
+
+               self["menulist"].hide()
+               self["submenulist"].hide()
+
+               self["bottomArea"].setText("Opera Web Browser Plugin v0.1")
+               self.setTitle("BrowserMain")
+               self.selectMenuitem()
+
+       def selectMenuitem(self):
+               tmp = [self["menuitemFile"], self["menuitemHelp"]]
+               self["menuitemFile"].setForegroundColorNum(0)
+               self["menuitemHelp"].setForegroundColorNum(0)
+               tmp[self.menubarCurrentIndex].setForegroundColorNum(1)
+
+       def popupCloseAll(self):
+               self.keyLeft()
+               self.keyLeft()
+               self.keyUp()
+               self.keyCancel()
+
+       def setListOnView(self):
+               self.lvMenuItems = self.MENUITEMS_LIST[self.menubarCurrentIndex]        
+               return self.lvMenuItems
+
+       def setSubListOnView(self):
+               self.lvSubMenuItems = []
+               xl = self["menulist"].getCurrent()[1]
+               if xl is None: return []
+               for x in xl:
+                       self.lvSubMenuItems.append((x,None))
+               return self.lvSubMenuItems
+
+       def toggleMainScreen(self):
+               if not self.toggleMainScreenFlag:
+                       self.show()
+               else:   self.hide()
+               self.toggleMainScreenFlag = not self.toggleMainScreenFlag
+
+       def toggleListView(self):
+               if not self.toggleListViewFlag:
+                       self["menulist"].show()
+               else:   self["menulist"].hide()
+               self.toggleListViewFlag = not self.toggleListViewFlag
+
+       def toggleSubListView(self):
+               if not self.toggleSubListViewFlag:
+                       self["submenulist"].show()
+               else:   self["submenulist"].hide()
+               self.toggleSubListViewFlag = not self.toggleSubListViewFlag
+
+       def setCurrentListView(self, listViewIdx):
+               if listViewIdx == 0:
+                       self.currentListView = None
+               elif listViewIdx == 1:
+                       self.currentListView = self["menulist"]
+               elif listViewIdx == 2:
+                       self.currentListView = self["submenulist"]
+
+       def _cb_onClose(self):
+               self._onCloseTimer.stop()
+               command_server = getCommandServer()
+               try:
+                       if self._on_close_window in command_server.onHbbTVCloseCB:
+                                       command_server.onHbbTVCloseCB.remove(self._on_close_window)
+               except Exception, ErrMsg: pass
+               try:
+                       if self._on_setPageTitle in command_server.onSetPageTitleCB:
+                               command_server.onSetPageTitleCB.remove(self._on_setPageTitle)
+               except Exception, ErrMsg: pass
+               self._on_setPageTitle('Opera Browser')
+               self.enableRCMouse(False)
+               self.toggleMainScreen()
+               eRCInput.getInstance().unlock()
+
+       def _on_setPageTitle(self, title=None):
+               print "page title :",title
+               if title is None:
+                       return
+               self.setTitle(title)
+
+       def cbUrlText(self, data=None):
+               print "Inputed Url :", data
+               if strIsEmpty(data):
+                       return
+               command_server = getCommandServer()
+               if self._on_setPageTitle not in command_server.onSetPageTitleCB:
+                               command_server.onSetPageTitleCB.append(self._on_setPageTitle)
+               if self._on_close_window not in command_server.onHbbTVCloseCB:
+                       command_server.onHbbTVCloseCB.append(self._on_close_window)
+               self.toggleMainScreen()
+               self.enableRCMouse(True)
+               eRCInput.getInstance().lock()
+               command_util = getCommandUtil()
+               command_util.sendCommand('OP_BROWSER_OPEN_URL', data)
+
+       def _on_close_window(self):
+               self._onCloseTimer.start(1000)
+
+       def _cmd_on_OpenLocation(self):
+               global _g_helper
+               if not _g_helper._is_browser_running():
+                       message = "Opera Browser was not running.\nPlease running browser using [File]>[Start/Stop] menu."
+                       self.session.open(MessageBox, message, MessageBox.TYPE_INFO)
+                       return
+               self.session.openWithCallback(self.cbUrlText, VirtualKeyBoard, title=("Please enter URL here"), text='http://')
+       def _cmd_on_About(self):
+               self.session.open(MessageBox, 'Opera Web Browser Plugin v0.1(beta)', type = MessageBox.TYPE_INFO)
+       def _cmd_on_Exit(self):
+               self.close()
+       def _cmd_on_StartStop(self):
+               global _g_helper
+               if _g_helper is None: 
+                       return
+               _g_helper.showBrowserConfigBox()
+       def doCommand(self, command):
+               cmd_map = {
+                        'Exit'          :self._cmd_on_Exit
+                       ,'About'         :self._cmd_on_About
+                       ,'Open Location' :self._cmd_on_OpenLocation
+                       ,'Start/Stop'    :self._cmd_on_StartStop
+               }
+               try:
+                       cmd_map[command]()
+               except: pass
+
+       def keyOK(self):
+               if not self.toggleListViewFlag:
+                       self.keyDown()
+                       return
+               if self.currentListView.getCurrent()[1] is None:
+                       self.doCommand(self.currentListView.getCurrent()[0])
+                       #self.session.open(MessageBox, _(self.currentListView.getCurrent()[0]), type = MessageBox.TYPE_INFO)
+                       return
+               self.keyRight()
+
+       def updateSelectedMenuitem(self, status):
+               if self.menubarCurrentIndex == 0 and status < 0:
+                       self.menubarCurrentIndex = 1
+               elif self.menubarCurrentIndex == 1 and status > 0:
+                       self.menubarCurrentIndex = 0
+               else:   self.menubarCurrentIndex += status
+               self.selectMenuitem()
+
+       def keyLeft(self):
+               if not self.toggleMainScreenFlag:
+                       return
+               if not self.toggleListViewFlag:
+                       self.updateSelectedMenuitem(-1)
+                       return
+               if self.toggleSubListViewFlag:
+                       self.setCurrentListView(1)
+                       self.toggleSubListView()
+                       return
+               if self.currentListView.getSelectedIndex():
+                       self.currentListView.pageUp()
+
+       def keyRight(self):
+               if not self.toggleMainScreenFlag:
+                       return
+               if not self.toggleListViewFlag:
+                       self.updateSelectedMenuitem(1)
+                       return
+               if self.currentListView is None:
+                       return
+               if self.currentListView.getCurrent()[1] is not None:
+                       parentSelectedIndex = self.currentListView.getSelectedIndex()
+                       self.setCurrentListView(2)
+                       self.currentListView.setList(self.setSubListOnView())
+                       self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvSubMenuItems)+5)
+                       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))
+                       self.toggleSubListView()
+
+       def keyDown(self):
+               if not self.toggleMainScreenFlag:
+                       return
+               if self.currentListView is None:
+                       return
+               if not self.toggleListViewFlag:
+                       self.currentListView.setList(self.setListOnView())
+                       self.currentListView.resize(self.SUBMENULIST_WIDTH, self.SUBMENULIST_HEIGHT*len(self.lvMenuItems)+5)
+                       self.currentListView.move(self.MENUBAR_ITEM_WIDTH*self.menubarCurrentIndex+1+ 50,self.MENUBAR_ITEM_HEIGHT+30)
+                       self.toggleListView()
+                       return
+               self.currentListView.down()
+
+       def keyUp(self):
+               if not self.toggleMainScreenFlag:
+                       return
+               if self.currentListView is None:
+                       return
+               if self.currentListView == self["menulist"]:
+                       if self.currentListView.getSelectedIndex() == 0:
+                               self.toggleListView()
+                               return
+               self.currentListView.up()
+
+       def keyCancel(self):
+               self.toggleMainScreen()
+
+def auto_start_main(reason, **kwargs):
+       if reason:
+               command_server = getCommandServer()
+               command_server.stop()
+
+def session_start_main(session, reason, **kwargs):
+       global _g_helper
+       _g_helper = session.open(HbbTVHelper)
+
+def plugin_start_main(session, **kwargs):
+       session.open(OperaBrowser)
+
+def plugin_extension_start_application(session, **kwargs):
+       global _g_helper
+       if _g_helper is None: 
+               return
+       _g_helper.showApplicationSelectionBox()
+
+def plugin_extension_browser_config(session, **kwargs):
+       global _g_helper
+       if _g_helper is None: 
+               return
+       _g_helper.showBrowserConfigBox()
+
+def Plugins(path, **kwargs):
+       return  [
+               PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=auto_start_main),
+               PluginDescriptor(where=PluginDescriptor.WHERE_SESSIONSTART, needsRestart=True, fnc=session_start_main, weight=-10),
+               PluginDescriptor(name="HbbTV Applications", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_start_application),
+               PluginDescriptor(name="Browser Start/Stop", where=PluginDescriptor.WHERE_EXTENSIONSMENU, needsRestart=True, fnc=plugin_extension_browser_config),
+               PluginDescriptor(name="Opera Web Browser", description="start opera web browser", where=PluginDescriptor.WHERE_PLUGINMENU, needsRestart=True, fnc=plugin_start_main)
+               ]
+