[browser] update.
authorkos <kos@dev3>
Mon, 8 Oct 2012 06:11:36 +0000 (15:11 +0900)
committerkos <kos@dev3>
Mon, 8 Oct 2012 06:11:36 +0000 (15:11 +0900)
- bookmark manager.
- startpage configuration.
- switch to mouse/keyboard mode.
- help menu.
- virtual keyboard on the browser.
- menu on the browser.

lib/python/Plugins/Extensions/HbbTV/Makefile.am
lib/python/Plugins/Extensions/HbbTV/bookmark.py [new file with mode: 0644]
lib/python/Plugins/Extensions/HbbTV/plugin.py

index 18e39a1..7449060 100644 (file)
@@ -4,6 +4,7 @@ SUBDIRS = meta
 
 install_PYTHON = \
        __init__.py \
 
 install_PYTHON = \
        __init__.py \
+       bookmark.py \
        plugin.py 
 
 
        plugin.py 
 
 
diff --git a/lib/python/Plugins/Extensions/HbbTV/bookmark.py b/lib/python/Plugins/Extensions/HbbTV/bookmark.py
new file mode 100644 (file)
index 0000000..0dc9ade
--- /dev/null
@@ -0,0 +1,268 @@
+class BookmarkData:
+       def __init__(self, _id, _title, _url, _parent):
+               self.mId        = _id
+               self.mTitle     = _title
+               self.mUrl       = _url
+               self.mParent    = _parent
+       def dump(self, _intent='  '):
+               print "%s-> %d, %s, %s, %d" % (_intent, self.mId, self.mTitle, self.mUrl, self.mParent)
+
+class CategoryData:
+       def __init__(self, _id, _name):
+               self.mId        = _id
+               self.mName      = _name
+               self.mBookmarks = {}
+
+       def setBookmarks(self, _bookmarks):
+               self.mBookmarks = _bookmarks
+
+       def appendBookmark(self, _bookmark):
+               self.mBookmarks[_bookmark.mId] = _bookmark
+
+       def dump(self):
+               print "  -> %d, %s" % (self.mId, self.mName)
+               for key in self.mBookmarks.iterkeys():
+                       self.mBookmarks[key].dump('      ')
+
+import ConfigParser
+class SimpleConfigParser:
+       def __init__(self):
+               self.mFileName = None
+               self.mConfig = None
+               self.mCategoryCurrentIdx = 0
+               self.mBookmarkCurrentIdx = 0
+               self.mDataValid = False
+               self.mPopulateValid = False
+
+       def _read(self):
+               if self.mDataValid:
+                       return
+               print "populate!!"
+               self.mConfig.read(self.mFileName)
+
+               self.mCategoryCurrentIdx = self.getNumber('__SYS__', 'category_current_idx')
+               self.mBookmarkCurrentIdx = self.getNumber('__SYS__', 'bookmark_current_idx')
+               self.mDataValid = True
+
+       def _save(self):
+               with open(self.mFileName, 'wb') as bookmarkFile:
+                       self.mConfig.write(bookmarkFile)
+               self.mDataValid = False
+               self.mPopulateValid = False
+
+       def _del(self, _section, _option=None):
+               #print _section, ' :', _option
+               if _option is None:
+                       if not self.exist(_section):
+                               return
+                       self.mConfig.remove_section(_section)
+                       return
+               if not self.exist(_section, _option):
+                       return
+               self.mConfig.remove_option(_section, _option)
+
+       def _get(self, _section, _option, _default):
+               try:
+                       data = self.mConfig.get(_section, _option)
+               except Exception, e:
+                       #print e
+                       return _default
+               else :  return data
+
+       def _set(self, _section, _option, _value):
+               self.mConfig.set(_section, _option, _value)
+
+       def exist(self, _section, _option=None):
+               if _option is None:
+                       return self.mConfig.has_section(_section)
+               return self.mConfig.has_option(_section, _option)
+
+       def setNumber(self, _section, _option, _value):
+               self._set(_section, _option, str(_value))
+
+       def setString(self, _section, _option, _value):
+               self._set(_section, _option, _value)
+
+       def getNumber(self, _section, _option, _default=0):
+               return int(self._get(_section, _option, _default))
+
+       def getString(self, _section, _option, _default=''):
+               return self._get(_section, _option, _default)
+
+       def delOption(self, _section, _option):
+               self._del(_section, _option)
+
+       def addSection(self, _section):
+               self.mConfig.add_section(_section)
+
+       def delSection(self, _section):
+               self._del(_section)
+
+       def init(self, _fileName):
+               self.mFileName = _fileName
+               self.mConfig = ConfigParser.RawConfigParser()
+               if self.mConfig is None:
+                       return False
+               self._read()
+               return True
+
+class BookmarkManager(SimpleConfigParser):
+       _instance = None
+        def __new__(cls, *args, **kwargs):
+            if not cls._instance:
+                cls._instance = super(Singleton, cls).__new__(
+                                   cls, *args, **kwargs)
+            return cls._instance
+
+       def __init__(self, _dbFileName):
+               SimpleConfigParser.__init__(self)
+
+               self.mBookmarkRoot = None
+               self.mDebugEnable = False
+
+               import os
+               if not os.path.exists(_dbFileName):
+                       os.system('echo "[__SYS__]" > %s'%(_dbFileName))
+                       os.system('echo "category_current_idx = 0" >> %s'%(_dbFileName))
+                       os.system('echo "bookmark_current_idx = 0" >> %s'%(_dbFileName))
+
+               self.init(_dbFileName)
+
+       def message(self, format, params=None):
+               if not self.mDebugEnable:
+                       return
+               if params is None:
+                       print format
+               else:   print format % (params)
+
+       def getBookmark(self, _title):
+               self.populate()
+               for key in self.mBookmarkRoot.iterkeys():
+                       for key2 in self.mBookmarkRoot[key].mBookmarks.iterkeys():
+                               if self.mBookmarkRoot[key].mBookmarks[key2].mTitle == _title:
+                                       return 'b-%d' % (self.mBookmarkRoot[key].mBookmarks[key2].mId)
+               return None
+
+       def addBookmark(self, _title, _url, _parent):
+               if self.getBookmark(_title) is not None:
+                       return False
+               i = self.mBookmarkCurrentIdx + 1
+               s = "b-%d" % (i,)
+               self.message("add bookmark : %s, %s, %d", (_title, _url, _parent,))
+
+               self.mConfig.add_section(s)
+               self.setNumber(s, 'id', i)
+               self.setString(s, 'title', _title)
+               self.setString(s, 'url', _url)
+               self.setNumber(s, 'parent', _parent)
+               self.setNumber('__SYS__', 'bookmark_current_idx', i)
+               self._save()
+
+               return True
+
+       def deleteBookmark(self, _id):
+               self.populate()
+               self.message("delete bookmark : %d", (_id,))
+               self.delSection('b-%d' % (_id,))
+               self._save()
+
+       def updateBookmark(self, _bookmark):
+               self.populate()
+               s = "b-%d" % (_bookmark.mId)
+               self.message("update bookmark : %s, %s, %d", (_bookmark.mTitle, _bookmark.mUrl, _bookmark.mParent,))
+               self.setString(s, 'title', _bookmark.mTitle)
+               self.setString(s, 'url', _bookmark.mUrl)
+               self.setNumber(s, 'parent', _bookmark.mParent)
+               self._save()
+
+       def getCategory(self, _name):
+               self.populate()
+               for key in self.mBookmarkRoot.iterkeys():
+                       if self.mBookmarkRoot[key].mName == _name:
+                               return 'c-%d' % (self.mBookmarkRoot[key].mId)
+               return None
+
+       def addCategory(self, _name):
+               if self.getCategory(_name) is not None:
+                       return False
+               self.message("add category : %s", (_name,))
+               i = self.mCategoryCurrentIdx + 1
+               s = "c-%d" % (i)
+
+               self.mConfig.add_section(s)
+               self.setNumber(s, 'id', i)
+               self.setNumber(s, 'name', _name)
+               self.setNumber('__SYS__', 'category_current_idx', i)
+               self._save()
+
+               return True
+
+       def deleteCategory(self, _id):
+               self.populate()
+               self.message("delete category : %d", (_id,))
+               try:
+                       for key in self.mBookmarkRoot[_id].mBookmarks.iterkeys():
+                               self.delSection('b-%d' % (key,))
+               except: pass
+               self.delSection('c-%d' % (_id,))
+               self._save()
+
+       def updateCategory(self, _category):
+               self.populate()
+               self.message("update category : %s", (_category.mName,))
+               s = "c-%d" % (_category.mId)
+               self.setNumber(s, 'name', _category.mName)
+               self._save()
+
+       def populate(self):
+               cx, bx = 0, 0
+               categoryList = {}
+               self.message("populate : %d, %d", (self.mPopulateValid, self.mDataValid))
+
+               self._read()
+               if self.mPopulateValid:
+                       return
+
+               while cx <= self.mCategoryCurrentIdx:
+                       s = 'c-%d' % (cx,)
+                       i = self.getNumber(s, 'id', -1)
+                       if i != -1:
+                               n = self.getString(s, 'name')
+                               categoryList[i] = CategoryData(i, n)
+                       cx += 1
+               sorted(categoryList)
+               while bx <= self.mBookmarkCurrentIdx:
+                       s = 'b-%d' % (bx,)
+                       i = self.getNumber(s, 'id', -1)
+                       if i != -1:
+                               t = self.getString(s, 'title')
+                               u = self.getString(s, 'url')
+                               p = self.getNumber(s, 'parent')
+                               try:
+                                       categoryList[p].appendBookmark(BookmarkData(i, t, u, p))
+                               except Exception, e: self._del(s)
+                       bx += 1
+               for key in categoryList.iterkeys():
+                       sorted(categoryList[key].mBookmarks)
+               self.mBookmarkRoot = categoryList
+               self.mPopulateValid = True
+               self.dump()
+
+       def getBookmarkRoot(self):
+               self.populate()
+               return self.mBookmarkRoot
+
+       def dump(self):
+               if not self.mDebugEnable:
+                       return
+               self.populate()
+               print "-- snapshot --"
+               for key in self.mBookmarkRoot.iterkeys():
+                       self.mBookmarkRoot[key].dump()
+               print "--------------"
+
+       @staticmethod
+       def getInstance():
+               return BookmarkManager('/usr/lib/enigma2/python/Plugins/Extensions/HbbTV/bookmark.ini')
+
+
index d67c281..b9ddd36 100644 (file)
@@ -6,21 +6,24 @@ from Screens.ChoiceBox import ChoiceBox
 from Screens.MessageBox import MessageBox
 from Screens.InfoBarGenerics import InfoBarNotifications
 from Screens.VirtualKeyBoard import VirtualKeyBoard
 from Screens.MessageBox import MessageBox
 from Screens.InfoBarGenerics import InfoBarNotifications
 from Screens.VirtualKeyBoard import VirtualKeyBoard
+from Screens.HelpMenu import HelpableScreen
 
 from Components.PluginComponent import plugins
 from Components.Button import Button
 
 from Components.PluginComponent import plugins
 from Components.Button import Button
-from Components.Label import Label
 from Components.Sources.StaticText import StaticText
 from Components.Sources.StaticText import StaticText
-from Components.ActionMap import NumberActionMap, ActionMap
+from Components.ActionMap import NumberActionMap, ActionMap, HelpableActionMap
 from Components.ServiceEventTracker import ServiceEventTracker
 from Components.MenuList import MenuList
 from Components.Label import Label, MultiColorLabel
 from Components.ConfigList import ConfigListScreen
 from Components.VolumeControl import VolumeControl
 from Components.ServiceEventTracker import ServiceEventTracker
 from Components.MenuList import MenuList
 from Components.Label import Label, MultiColorLabel
 from Components.ConfigList import ConfigListScreen
 from Components.VolumeControl import VolumeControl
+from Components.Pixmap import Pixmap
 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
 
 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
 
+from bookmark import BookmarkManager, BookmarkData, CategoryData
+
 import os, struct, threading, stat, select, time, socket, select
 
 strIsEmpty = lambda x: x is None or len(x) == 0
 import os, struct, threading, stat, select, time, socket, select
 
 strIsEmpty = lambda x: x is None or len(x) == 0
@@ -47,8 +50,16 @@ class GlobalValues:
        packet_hl = struct.calcsize(packet_h)
 
        need_restart = False
        packet_hl = struct.calcsize(packet_h)
 
        need_restart = False
+       plugin_browser = None
 __gval__ = GlobalValues()
 
 __gval__ = GlobalValues()
 
+def setPluginBrowser(browser=None):
+       global __gval__
+       __gval__.plugin_browser = browser
+def getPluginBrowser():
+       global __gval__
+       return __gval__.plugin_browser
+
 def getPacketHeaders():
        global __gval__
        return (__gval__.packet_m, __gval__.packet_h, __gval__.packet_hl)
 def getPacketHeaders():
        global __gval__
        return (__gval__.packet_m, __gval__.packet_h, __gval__.packet_hl)
@@ -188,7 +199,16 @@ class OpCodeSet:
                        ,"OP_VOD_STATUS"                : 0x0205
                        ,"OP_VOD_FORBIDDEN"             : 0x0206
                        ,"OP_VOD_STOPED"                : 0x0207
                        ,"OP_VOD_STATUS"                : 0x0205
                        ,"OP_VOD_FORBIDDEN"             : 0x0206
                        ,"OP_VOD_STOPED"                : 0x0207
+                       ,"OP_VOD_SPEED_CTRL"            : 0x0208
+                       ,"OP_VOD_SEEK_CTRL"             : 0x0209
                        ,"OP_BROWSER_OPEN_URL"          : 0x0301
                        ,"OP_BROWSER_OPEN_URL"          : 0x0301
+                       ,"OP_BROWSER_VKBD_REQ"          : 0x0309
+                       ,"OP_BROWSER_VKBD_RES"          : 0x030A
+                       ,"OP_BROWSER_VKBD_PASTE_REQ"    : 0x030B
+                       ,"OP_BROWSER_VKBD_PASTE_KEY"    : 0x030C
+                       ,"OP_BROWSER_VKBD_PASTE_MOUSE"  : 0x030D
+                       ,"OP_BROWSER_MENU_REQ"          : 0x030E
+                       ,"OP_BROWSER_MENU_RES"          : 0x030F
                        ,"OP_DVBAPP_VOL_UP"             : 0x0401
                        ,"OP_DVBAPP_VOL_DOWN"           : 0x0402
                        ,"OP_SYSTEM_OUT_OF_MEMORY"      : 0x0501
                        ,"OP_DVBAPP_VOL_UP"             : 0x0401
                        ,"OP_DVBAPP_VOL_DOWN"           : 0x0402
                        ,"OP_SYSTEM_OUT_OF_MEMORY"      : 0x0501
@@ -213,7 +233,16 @@ class OpCodeSet:
                        ,0x0205 : "OP_VOD_STATUS"
                        ,0x0206 : "OP_VOD_FORBIDDEN"
                        ,0x0207 : "OP_VOD_STOPED"
                        ,0x0205 : "OP_VOD_STATUS"
                        ,0x0206 : "OP_VOD_FORBIDDEN"
                        ,0x0207 : "OP_VOD_STOPED"
+                       ,0x0208 : "OP_VOD_SPEED_CTRL"
+                       ,0x0209 : "OP_VOD_SEEK_CTRL"
                        ,0x0301 : "OP_BROWSER_OPEN_URL"
                        ,0x0301 : "OP_BROWSER_OPEN_URL"
+                       ,0x0309 : "OP_BROWSER_VKBD_REQ"
+                       ,0x030A : "OP_BROWSER_VKBD_RES"
+                       ,0x030B : "OP_BROWSER_VKBD_PASTE_REQ"
+                       ,0x030C : "OP_BROWSER_VKBD_PASTE_KEY"
+                       ,0x030D : "OP_BROWSER_VKBD_PASTE_MOUSE"
+                       ,0x030E : "OP_BROWSER_MENU_REQ"
+                       ,0x030F : "OP_BROWSER_MENU_RES"
                        ,0x0401 : "OP_DVBAPP_VOL_UP"
                        ,0x0402 : "OP_DVBAPP_VOL_DOWN"
                        ,0x0501 : "OP_SYSTEM_OUT_OF_MEMORY"
                        ,0x0401 : "OP_DVBAPP_VOL_UP"
                        ,0x0402 : "OP_DVBAPP_VOL_DOWN"
                        ,0x0501 : "OP_SYSTEM_OUT_OF_MEMORY"
@@ -383,7 +412,7 @@ class BrowserCommandUtil(OpCodeSet):
 
        def doSend(self, command, params=None, reserved=0):
                if self._fd is None:
 
        def doSend(self, command, params=None, reserved=0):
                if self._fd is None:
-                       print "Pipe was not exists!!"
+                       print "No found pipe!!"
                        return False
                data = ''
                try:
                        return False
                data = ''
                try:
@@ -421,8 +450,13 @@ class HandlerHbbTV(Handler):
                        ,0x0204 : self._cb_handleVODPlayerPlayPause
                        ,0x0401 : self._cb_handleDVBAppVolUp
                        ,0x0402 : self._cb_handleDVBAppVolDown
                        ,0x0204 : self._cb_handleVODPlayerPlayPause
                        ,0x0401 : self._cb_handleDVBAppVolUp
                        ,0x0402 : self._cb_handleDVBAppVolDown
+                       ,0x0208 : self._cb_handleVODSpeedCtrl
+                       ,0x0209 : self._cb_handleVODSeekCtrl
                        ,0x0501 : self._cb_handleSystemOutOfMemory
                        ,0x0502 : self._cb_handleSystemNotufyMyPID
                        ,0x0501 : self._cb_handleSystemOutOfMemory
                        ,0x0502 : self._cb_handleSystemNotufyMyPID
+                       ,0x0309 : self._cb_handleShowVirtualKeyboard
+                       ,0x030B : self._cb_handlePasteVirtualKeyboard
+                       ,0x030E : self._cb_handleBrowserMenuReq
                }
                self._on_close_cb = None
                self._on_set_title_cb = None
                }
                self._on_close_cb = None
                self._on_set_title_cb = None
@@ -431,7 +465,8 @@ class HandlerHbbTV(Handler):
 
                self._retry_open_url = None
                self._timer_retry_open = eTimer()
 
                self._retry_open_url = None
                self._timer_retry_open = eTimer()
-               
+               self._timer_paste_vkbd = eTimer()
+               self._curren_title = None
 
        def _handle_dump(self, handle, opcode, data=None):
                if True: return
 
        def _handle_dump(self, handle, opcode, data=None):
                if True: return
@@ -469,6 +504,72 @@ class HandlerHbbTV(Handler):
                self._on_set_title_cb = None
                return self.doPack(opcode, params, reserved)
 
                self._on_set_title_cb = None
                return self.doPack(opcode, params, reserved)
 
+       def _cb_handleBrowserMenuReq(self, opcode, data):
+               self._handle_dump(self._cb_handleBrowserMenuReq, opcode, data)
+               eRCInput.getInstance().unlock()
+               browser = getPluginBrowser()
+               if browser is not None:
+                       browser.setCurrentPageUrl(data, self._curren_title)
+               return (0, "OK")
+
+       def _cb_handlePasteVirtualKeyboard(self, opcode, data):
+               self._handle_dump(self._cb_handlePasteVirtualKeyboard, opcode, data)
+               def _cb_PasteRefocusVirtualKeyboard():
+                       self._timer_paste_vkbd.stop()
+                       command_util = getCommandUtil()
+                       command_util.sendCommand('OP_BROWSER_VKBD_PASTE_MOUSE')
+                       try:
+                               self._timer_paste_vkbd.callback.remove(_cb_PasteMouseVirtualKeyboard)
+                       except: pass
+               def _cb_PasteKeyVirtualKeyboard():
+                       self._timer_paste_vkbd.stop()
+                       command_util = getCommandUtil()
+                       command_util.sendCommand('OP_BROWSER_VKBD_PASTE_KEY')
+                       try:
+                               self._timer_paste_vkbd.callback.remove(_cb_PasteKeyVirtualKeyboard)
+                       except: pass
+                       self._timer_paste_vkbd.callback.append(_cb_PasteRefocusVirtualKeyboard)
+                       self._timer_paste_vkbd.start(100)
+               def _cb_PasteMouseVirtualKeyboard():
+                       self._timer_paste_vkbd.stop()
+                       command_util = getCommandUtil()
+                       command_util.sendCommand('OP_BROWSER_VKBD_PASTE_MOUSE')
+                       #time.sleep(1)
+                       #command_util.sendCommand('OP_BROWSER_VKBD_PASTE_MOUSE')
+                       try:
+                               self._timer_paste_vkbd.callback.remove(_cb_PasteMouseVirtualKeyboard)
+                       except: pass
+                       #self._timer_paste_vkbd.callback.append(_cb_PasteKeyVirtualKeyboard)
+                       #self._timer_paste_vkbd.start(1000)
+               self._timer_paste_vkbd.callback.append(_cb_PasteMouseVirtualKeyboard)
+               self._timer_paste_vkbd.start(50)
+               return (0, "OK")
+
+       def _cb_virtualKeyboardClosed(self, data=None):
+               eRCInput.getInstance().lock()
+               command_util = getCommandUtil()
+               command_util.sendCommand('OP_BROWSER_VKBD_RES', data)
+       def _cb_handleShowVirtualKeyboard(self, opcode, data):
+               self._handle_dump(self._cb_handleShowVirtualKeyboard, opcode, data)
+               eRCInput.getInstance().unlock()
+               if data == 0 or strIsEmpty(data):
+                       data = ""
+               self._session.openWithCallback(self._cb_virtualKeyboardClosed, VirtualKeyBoard, title=("Please enter URL here"), text=data)
+               return (0, "OK")
+
+       def _cb_handleVODSeekCtrl(self, opcode, data):
+               self._handle_dump(self._cb_handleVODSeekCtrl, opcode, data)
+               headLen = struct.calcsize('!I')
+               unpackedData = struct.unpack('!I', data[:headLen])
+               seekTime = unpackedData[0]
+               service = self._session.nav.getCurrentService()
+               seekable = service.seek()
+               if seekable is None or not seekable.isCurrentlySeekable():
+                       raise Exception("This stream is not support manual seek.")
+               pts = seekTime
+               seekable.seekRelative(pts<0 and -1 or 1, abs(pts))
+               return (0, "OK")
+
        def _cb_handleHbbTVRetryOpen(self, opcode, data):
                def _cb_HbbTVRetryOpenURL():
                        self._timer_retry_open.stop()
        def _cb_handleHbbTVRetryOpen(self, opcode, data):
                def _cb_HbbTVRetryOpenURL():
                        self._timer_retry_open.stop()
@@ -476,6 +577,9 @@ class HandlerHbbTV(Handler):
                                command_util = getCommandUtil()
                                command_util.sendCommand('OP_HBBTV_RETRY_OPEN_URL', params=self._retry_open_url)
                        self._retry_open_url = None
                                command_util = getCommandUtil()
                                command_util.sendCommand('OP_HBBTV_RETRY_OPEN_URL', params=self._retry_open_url)
                        self._retry_open_url = None
+                       try:
+                               self._timer_retry_open.callback.remove(_cb_HbbTVRetryOpenURL)
+                       except: pass
                self._handle_dump(self._cb_handleHbbTVRetryOpen, opcode, data)
                headLen = struct.calcsize('!I')
                unpackedData = struct.unpack('!I', data[:headLen])
                self._handle_dump(self._cb_handleHbbTVRetryOpen, opcode, data)
                headLen = struct.calcsize('!I')
                unpackedData = struct.unpack('!I', data[:headLen])
@@ -496,6 +600,20 @@ class HandlerHbbTV(Handler):
                setNeedRestart(True)
                return (0, "OK")
 
                setNeedRestart(True)
                return (0, "OK")
 
+       def _cb_handleVODSpeedCtrl(self, opcode, data):
+               self._handle_dump(self._cb_handleVODSpeedCtrl, opcode, data)
+               headLen = struct.calcsize('!I')
+               unpackedData = struct.unpack('!I', data[:headLen])
+               playSpeed = unpackedData[0]
+               service = self._session.nav.getCurrentService()
+               pauseable = service.pause()
+               if playSpeed > 2:
+                       playSpeed = 2
+               if pauseable.setFastForward(playSpeed) == -1:
+                       pauseable.setFastForward(1)
+                       raise Exception("This stream is not support trick play.")
+               return (0, "OK")
+
        def _cb_handleDVBAppVolUp(self, opcode, data):
                self._handle_dump(self._cb_handleDVBAppVolUp, opcode, data)
                vcm = VolumeControl.instance
        def _cb_handleDVBAppVolUp(self, opcode, data):
                self._handle_dump(self._cb_handleDVBAppVolUp, opcode, data)
                vcm = VolumeControl.instance
@@ -535,6 +653,7 @@ class HandlerHbbTV(Handler):
                        for x in self._on_set_title_cb:
                                try:
                                        x(data)
                        for x in self._on_set_title_cb:
                                try:
                                        x(data)
+                                       self._curren_title = data
                                except Exception, ErrMsg:
                                        if x in self._on_set_title_cb:
                                                self._on_set_title_cb.remove(x)
                                except Exception, ErrMsg:
                                        if x in self._on_set_title_cb:
                                                self._on_set_title_cb.remove(x)
@@ -542,6 +661,9 @@ class HandlerHbbTV(Handler):
 
        def _cb_handleCloseHbbTVBrowser(self, opcode, data):
                self._timer_retry_open.stop()
 
        def _cb_handleCloseHbbTVBrowser(self, opcode, data):
                self._timer_retry_open.stop()
+               try:
+                       self._timer_retry_open.callback.remove(_cb_HbbTVRetryOpenURL)
+               except: pass
                self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
 
                if self._on_close_cb:
                self._handle_dump(self._cb_handleCloseHbbTVBrowser, opcode, data)
 
                if self._on_close_cb:
@@ -764,7 +886,7 @@ class HbbTVHelper(Screen):
                self._urls = None
                #self._stop_opera()
                #self._start_opera()
                self._urls = None
                #self._stop_opera()
                #self._start_opera()
-               self._restart_opera()
+               #self._restart_opera()
 
                Screen.__init__(self, session)
                self._session = session
 
                Screen.__init__(self, session)
                self._session = session
@@ -926,6 +1048,495 @@ class HbbTVHelper(Screen):
                        print "Check Browser Running ERR :", ErrMsg
                return False
 
                        print "Check Browser Running ERR :", ErrMsg
                return False
 
+class OperaBrowserSetting:
+       def __init__(self):
+               self._settingFileName = '/usr/local/hbb-browser/home/setting.ini'
+               self._start = None
+               self._read()
+       def _read(self):
+               f = open(self._settingFileName)
+               for line in f.readlines():
+                       if line.startswith('start='):
+                               self._start = line[6:len(line)-1]
+               f.close()
+       def _write(self):
+               tmpstr = []
+               tmpstr.append('start=%s\n' % (self._start))
+               f = open(self._settingFileName, 'w')
+               f.writelines(tmpstr)
+               f.close()
+       def setData(self, start):
+               self._start = start
+               self._write()
+       def getData(self):
+               return {
+                       'start':self._start
+               }
+
+class OperaBrowserPreferenceWindow(ConfigListScreen, Screen):
+       skin=   """
+               <screen position="center,center" size="600,350" title="Proference">
+                       <widget name="url" position="5,0" size="590,100" valign="center" font="Regular;20" />
+                       <widget name="config" position="0,100" size="600,200" scrollbarMode="showOnDemand" />
+
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="310,310" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="150,310" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="310,310" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="150,310" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+               </screen>
+               """
+       def __init__(self, session, currentUrl): 
+                self.session = session
+               Screen.__init__(self, session)
+
+               self.menulist = []
+               ConfigListScreen.__init__(self, self.menulist)
+
+               self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ], {
+                       "red"    : self.keyRed,
+                       "green"  : self.keyGreen,
+                       "ok"     : self.keyOK,
+                       "cancel" : self.keyRed
+                }, -2)
+               self["key_red"]   = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Save"))
+               self["url"]       = Label()
+
+               self._currentPageUrl = currentUrl
+               if self._currentPageUrl is None:
+                       self._currentPageUrl = ''
+               self._startPageUrl   = None
+
+               self.makeMenuEntry()
+               self.onLayoutFinish.append(self.layoutFinished)
+
+       def layoutFinished(self):
+               try:
+                       self._startPageUrl = OperaBrowserSetting().getData()['start']
+               except: self._startPageUrl = 'http://vuplus.com'
+               self.updateStartPageUrl()
+
+       def updateStartPageUrl(self):
+               if self.menuItemStartpage.value == "startpage":
+                       self["url"].setText(self._startPageUrl)
+               elif self.menuItemStartpage.value == "current":
+                       self["url"].setText(self._currentPageUrl)
+               elif self.menuItemStartpage.value == "direct":
+                       self["url"].setText('')
+
+       def keyGreen(self):
+               url = self["url"].getText()
+               if strIsEmpty(url):
+                       self.session.open(MessageBox, 'Invalid URL!!(Empty)\nPlease, Input to the URL.', type = MessageBox.TYPE_INFO)
+                       return
+               OperaBrowserSetting().setData(url)
+               self.close()
+
+       def keyRed(self):
+               self.close()
+
+       def keyOK(self):
+               def _cb_directInputUrl(data):
+                       if strIsEmpty(data):
+                               return
+                       self["url"].setText(data)
+               if self.menuItemStartpage.value == "direct":
+                       self.session.openWithCallback(_cb_directInputUrl, VirtualKeyBoard, title=("Please enter URL here"), text='http://')
+
+       def keyLeft(self):
+               ConfigListScreen.keyLeft(self)
+               self.updateStartPageUrl()
+
+       def keyRight(self):
+               ConfigListScreen.keyRight(self)
+               self.updateStartPageUrl()
+
+       def makeMenuEntry(self):
+               l = []
+               l.append(("startpage", _("Start Page")))
+               if not strIsEmpty(self._currentPageUrl):
+                       l.append(("current", _("Current Page")))
+               l.append(("direct", _("Direct Input")))
+               self.menuItemStartpage  = ConfigSelection(default="startpage", choices = l)
+               self.menuEntryStartpage = getConfigListEntry(_("Startpage"), self.menuItemStartpage)
+               self.resetMenuList()
+
+       def resetMenuList(self):
+               self.menulist = []
+               self.menulist.append(self.menuEntryStartpage)
+
+               self["config"].list = self.menulist
+               self["config"].l.setList(self.menulist)
+
+class BookmarkEditWindow(ConfigListScreen, Screen):
+       CATEGORY,BOOKMARK = 0,1
+       skin=   """
+               <screen position="center,center" size="600,140" title="Bookmark Edit">
+                       <widget name="config" position="0,0" size="600,100" scrollbarMode="showOnDemand" />
+
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="310,100" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="150,100" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="310,100" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="150,100" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="VKeyIcon" pixmap="skin_default/buttons/key_text.png" position="0,100" zPosition="10" size="35,25" transparent="1" alphatest="on" />
+
+               </screen>
+               """
+       def __init__(self, session, _mode, _type, _data, _bm):
+               self.mMode = _mode
+               self.mType = _type
+               self.mData = _data
+                self.session = session
+               self.mBookmarkManager = _bm
+
+               if _data is not None:
+                       print _data.mId
+
+               Screen.__init__(self, session)
+
+               self.menulist = []
+               ConfigListScreen.__init__(self, self.menulist)
+
+               self["actions"] = ActionMap(["OkCancelActions", "ColorActions",], {
+                       "ok"     : self.keyGreen,
+                       "green"  : self.keyGreen,
+                       "red"    : self.keyRed,
+                       "cancel" : self.keyRed,
+                }, -2)
+
+               self["VKeyIcon"]  = Pixmap()
+               self["key_red"]   = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("Save"))
+
+               self.menuItemTitle = None
+               self.menuItemUrl   = None
+               self.menuItemName  = None
+
+               self.makeConfigList()
+               self.onLayoutFinish.append(self.layoutFinished)
+
+       def layoutFinished(self):
+               self.setTitle('Bookmark ' + self.mMode)
+       def saveData(self):
+               if self.mType == BookmarkEditWindow.CATEGORY:
+                       if self.mMode == 'Add':
+                               categoryName = self.menuItemName.value
+                               if strIsEmpty(categoryName):
+                                       msg = "Invalid Category Name!!(Empty)\nPlease, Input to the Category Name."
+                                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                                       return False
+                               self.mBookmarkManager.addCategory(categoryName)
+                       else:
+                               if strIsEmpty(self.menuItemName.value):
+                                       msg = "Invalid Category Name!!(Empty)\nPlease, Input to the Category Name."
+                                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                                       return False
+                               self.mData.mName = self.menuItemName.value
+                               self.mBookmarkManager.updateCategory(self.mData)
+               else:
+                       if self.mMode == 'Add':
+                               bookmarkTitle = self.menuItemTitle.value
+                               bookmarkUrl   = self.menuItemUrl.value
+                               if strIsEmpty(bookmarkTitle):
+                                       msg = "Invalid Bookmark Title!!(Empty)\nPlease input to the Bookmark Title."
+                                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                                       return False
+                               self.mBookmarkManager.addBookmark(bookmarkTitle, bookmarkUrl, self.mData.mParent)
+                       else:
+                               if strIsEmpty(self.menuItemTitle.value):
+                                       msg = "Invalid Bookmark Title!!(Empty)\nPlease input to the Bookmark Title."
+                                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                                       return False
+                               self.mData.mTitle = self.menuItemTitle.value
+                               self.mData.mUrl   = self.menuItemUrl.value
+                               self.mBookmarkManager.updateBookmark(self.mData)
+               return True
+       def keyGreen(self):
+               if not self.saveData():
+                       return
+               self.close(True)
+       def keyRed(self):
+               self.close(False)
+       def keyLeft(self):
+               ConfigListScreen.keyLeft(self)
+       def keyRight(self):
+               ConfigListScreen.keyRight(self)
+       def makeConfigList(self):
+               self.menulist = []
+
+               if self.mType == BookmarkEditWindow.CATEGORY:
+                       self.menuItemName = ConfigText(default=self.mData.mName, visible_width=65, fixed_size=False)
+                       menuEntryName  = getConfigListEntry(_("Name"), self.menuItemName)
+                       self.menulist.append(menuEntryName)
+               else:
+                       self.menuItemTitle = ConfigText(default=self.mData.mTitle, visible_width=65, fixed_size=False)
+                       self.menuItemUrl   = ConfigText(default=self.mData.mUrl, visible_width=65, fixed_size=False)
+                       menuEntryTitle = getConfigListEntry(_("Title"), self.menuItemTitle)
+                       menuEntryUrl   = getConfigListEntry(_("Url"), self.menuItemUrl)
+                       self.menulist.append(menuEntryTitle)
+                       self.menulist.append(menuEntryUrl)
+                       
+               self["config"].list = self.menulist
+               self["config"].l.setList(self.menulist)
+
+class OperaBrowserBookmarkWindow(Screen):
+       skin =  """
+               <screen name="HbbTVBrowserBookmarkWindow" position="center,center" size="600,400" title="Bookmark" >
+                       <widget name="bookmarklist" position="0,0" size="600,200" zPosition="10" scrollbarMode="showOnDemand" />
+
+                       <ePixmap pixmap="skin_default/buttons/key_0.png" position="556,330" size="35,30" alphatest="on" />
+                       <widget source="key_0" render="Label" position="258,330" zPosition="1" size="300,30" font="Regular;20" halign="right" valign="center"/>
+
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="5,360" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="155,360" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,360" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/blue.png" position="450,360" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="5,360" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="155,360" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_yellow" render="Label" position="305,360" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_blue" render="Label" position="450,360" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+               </screen>
+               """
+
+       def __init__(self, _session, _url=None, _title=None):
+               self.mUrl   = _url
+               self.mTitle = _title
+               self.mBookmarkManager = BookmarkManager.getInstance()
+               self.mSession = _session
+               Screen.__init__(self, _session)
+               self["actions"] = ActionMap(["DirectionActions", "OkCancelActions","ColorActions", "NumberActions"], {
+                               "ok"    : self.keyOK,
+                               "cancel": self.keyCancel,
+                               "red"   : self.keyRed,
+                               "green" : self.keyGreen,
+                               "yellow": self.keyYellow,
+                               "blue"  : self.keyBlue,
+                               "0"     : self.keyNumber,
+                       },-2)
+
+               self["key_red"]    = StaticText(_("Exit"))
+               self["key_green"]  = StaticText(_("Add"))
+               self["key_yellow"] = StaticText(_("Edit"))
+               self["key_blue"]   = StaticText(_("Delete"))
+               self["key_0"]      = StaticText(_("Set as Startpage"))
+
+               self.mBookmarkList = self.setBookmarkList()
+               self["bookmarklist"] = MenuList(self.mBookmarkList)
+
+       def setBookmarkList(self):
+               l = []
+               #self.mBookmarkManager.dump()
+               cd = self.mBookmarkManager.getBookmarkRoot()
+               for ck in cd.iterkeys():
+                       l.append(('# ' + cd[ck].mName, cd[ck]))
+                       bd = cd[ck].mBookmarks
+                       for bk in bd.iterkeys():
+                               l.append(('    - ' + bd[bk].mTitle, bd[bk]))
+               return l
+       def updateBookmarkList(self):
+               self.mBookmarkList = self.setBookmarkList()
+               self["bookmarklist"].setList(self.mBookmarkList)
+       def cbEditWindow(self, ret=False):
+               if not ret: 
+                       return
+               self.updateBookmarkList()
+       def getParentCategory(self):
+               idx = self["bookmarklist"].getSelectedIndex()
+               while idx >= 0:
+                       data = self.mBookmarkList[idx][0].strip()
+                       if data[0] == '#':
+                               return self.mBookmarkList[idx][1]
+                       idx -= 1
+               return None
+       def isCategoryItem(self):
+               head = self["bookmarklist"].getCurrent()[0].strip()
+               if head[0] == '#':
+                       return True
+               return False
+       def keyNumber(self):
+               data = self["bookmarklist"].getCurrent()[1]
+               if strIsEmpty(data.mUrl):
+                       msg = "Invalid URL. Please check again!!"
+                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                       return
+               def cbSetStartpage(ret=None):
+                       if ret is None: return
+                       if ret:
+                               data = self["bookmarklist"].getCurrent()[1]
+                               OperaBrowserSetting().setData(data.mUrl)
+               msg = "Do you want to set selected url to the Startpage?"
+               self.mSession.openWithCallback(cbSetStartpage, MessageBox, msg, MessageBox.TYPE_YESNO, default=True)
+
+       def keyGreen(self):
+               def cbGreen(data):
+                       if data is None:
+                               return
+                       if data[1] == 1:
+                               parent = self.getParentCategory()
+                               if parent is None:
+                                       return
+                               if strIsEmpty(self.mTitle):
+                                       return
+                               retAdd = self.mBookmarkManager.addBookmark(self.mTitle, self.mUrl, parent.mId)
+                               if not retAdd:
+                                       msg = "Current page is already exist."
+                                       self.mSession.open(MessageBox, msg, MessageBox.TYPE_INFO)
+                               self.cbEditWindow(True)
+                       elif data[1] == 2:
+                               parent = self.getParentCategory()
+                               if parent is None:
+                                       return
+                               b = BookmarkData(0, '', '', parent.mId)
+                               self.mSession.openWithCallback(self.cbEditWindow, BookmarkEditWindow, 'Add', BookmarkEditWindow.BOOKMARK, b, self.mBookmarkManager)
+                       elif data[1] == 3:
+                               c = CategoryData(0, '')
+                               self.mSession.openWithCallback(self.cbEditWindow, BookmarkEditWindow, 'Add', BookmarkEditWindow.CATEGORY, c, self.mBookmarkManager)
+               if strIsEmpty(self.mUrl):
+                       l = [('Direct Input(Bookmark)',2,), ('Direct Input(Category)',3,)]
+               else:   l = [('Currentpage(Bookmark)',1,), ('Direct Input(Bookmark)',2,), ('Direct Input(Category)',3,)]
+               self.mSession.openWithCallback(cbGreen, ChoiceBox, title=_("Please choose."), list=l)
+       def keyYellow(self):
+               data = self["bookmarklist"].getCurrent()[1]
+               if self.isCategoryItem():
+                       self.mSession.openWithCallback(self.cbEditWindow, BookmarkEditWindow, 'Edit', BookmarkEditWindow.CATEGORY, data, self.mBookmarkManager)
+               else:   self.mSession.openWithCallback(self.cbEditWindow, BookmarkEditWindow, 'Edit', BookmarkEditWindow.BOOKMARK, data, self.mBookmarkManager)
+       def keyBlue(self):
+               def cbBlue(ret=None):
+                       if not ret: return
+                       data = self["bookmarklist"].getCurrent()[1]
+                       if self.isCategoryItem():
+                               self.mBookmarkManager.deleteCategory(data.mId)
+                       else:   self.mBookmarkManager.deleteBookmark(data.mId)
+                       self.updateBookmarkList()
+               if self.isCategoryItem():
+                       msg = "Do you want to delete the category and the bookmarks?"
+               else:   msg = "Do you want to delete the bookmark?"
+               self.mSession.openWithCallback(cbBlue, MessageBox, msg, MessageBox.TYPE_YESNO, default=True)
+       def keyOK(self):
+               if self.isCategoryItem(): return
+
+               data = self["bookmarklist"].getCurrent()[1]
+               url = data.mUrl.strip()
+               if len(url) == 0:
+                       self.session.open(MessageBox, "Can't open selected bookmark.\n   - URL data is empty!!", type = MessageBox.TYPE_INFO)
+                       return
+               self.close(url)
+       def keyRed(self):
+               self.keyCancel()
+       def keyCancel(self):
+               self.close()
+
+
+class BrowserHelpWindow(Screen, HelpableScreen):
+       MODE_GLOBAL,MODE_KEYBOARD,MODE_MOUSE = 1,2,3
+        skin = """
+                <screen name="BrowserHelpWindow" position="center,center" size="600,40" title="Browser Help" >
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="5,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="155,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/yellow.png" position="305,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/blue.png" position="450,0" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="5,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_green" render="Label" position="155,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_yellow" render="Label" position="305,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" foregroundColor="#ffffff" transparent="1" />
+                       <widget source="key_blue" render="Label" position="450,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+                </screen>
+               """
+        def __init__(self, session):
+                Screen.__init__(self, session)
+               HelpableScreen.__init__(self)
+
+               self["key_red"]    = StaticText(_("Exit"))
+               self["key_green"]  = StaticText(_("Global"))
+               self["key_yellow"] = StaticText(_("Mouse"))
+               self["key_blue"]   = StaticText(_("Keyboard"))
+
+               self["actions"] = ActionMap(["DirectionActions", "OkCancelActions","ColorActions"], {
+                               "ok"    : self.keyRed,
+                               "cancel": self.keyRed,
+                               "red"   : self.keyRed,
+                               "green" : self.keyGreen,
+                               "yellow": self.keyYellow,
+                               "blue"  : self.keyBlue,
+                       },-2)
+
+               self.showHelpTimer = eTimer()
+               self.showHelpTimer.callback.append(self.cbShowHelpTimerClosed)
+               self.showHelpTimer.start(500)
+
+       def cbShowHelpTimerClosed(self):
+               self.showHelpTimer.stop()
+               self.setHelpModeActions(self.MODE_GLOBAL)
+
+       def setHelpModeActions(self, _mode=0):
+               self.helpList = []
+               if _mode == self.MODE_GLOBAL:
+                       self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", {
+                               "cancel" : (self.keyPass, _("Exit the Opera browser.")),
+                       })
+                       self["MenuActions"] = HelpableActionMap(self, "MenuActions", {
+                               "menu" : (self.keyPass, _("Show the Menu window.")),
+                       })
+                       self["ColorActions"] = HelpableActionMap(self, "ColorActions", {
+                               "green"  : (self.keyPass, _("Enter Key")),
+                               "yellow" : (self.keyPass, _("Show the Virtual keyboard window.")),
+                               "blue"   : (self.keyPass, _("Backspace Key")),
+                       })
+                       self["EPGSelectActions"] = HelpableActionMap(self, "EPGSelectActions", {
+                               "info" : (self.keyPass, _("Switch to keyboard/mouse mode.")),
+                       })
+
+               elif _mode == self.MODE_MOUSE:
+                       self["DirectionActions"] = HelpableActionMap(self, "DirectionActions", {
+                               "up"    : (self.keyPass, _("It will move the mouse pointer up.")),
+                               "down"  : (self.keyPass, _("It will move the mouse pointer down.")),
+                               "left"  : (self.keyPass, _("It will move the mouse pointer left.")),
+                               "right" : (self.keyPass, _("It will move the mouse pointer right.")),
+                       })
+                       self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", {
+                               "ok" : (self.keyPass, _("Left Mouse Button")),
+                       })
+                       self["EPGSelectActions"] = HelpableActionMap(self, "EPGSelectActions", {
+                               "nextBouquet" : (self.keyPass, _("Right Mouse Button")),
+                               "nextService" : (self.keyPass, _("Left Key")),
+                               "prevService" : (self.keyPass, _("Right Key")),
+                       })
+               elif _mode == self.MODE_KEYBOARD:
+                       self["DirectionActions"] = HelpableActionMap(self, "DirectionActions", {
+                               "up"    : (self.keyPass, _("Up Key")),
+                               "down"  : (self.keyPass, _("Down Key")),
+                               "left"  : (self.keyPass, _("Left Key")),
+                               "right" : (self.keyPass, _("Right Key")),
+                       })
+                       self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions", {
+                               "ok" : (self.keyPass, _("Enter Key")),
+                       })
+                       self["EPGSelectActions"] = HelpableActionMap(self, "EPGSelectActions", {
+                               "nextBouquet" : (self.keyPass, _("PageUp Key")),
+                               "prevBouquet" : (self.keyPass, _("PageDown Key")),
+                               "nextService" : (self.keyPass, _("Go to previous page.")),
+                               "prevService" : (self.keyPass, _("Go to next page.")),
+                       })
+
+               if _mode > 0:
+                       self.showHelp()
+
+       def keyPass(self):
+               pass
+
+       def keyRed(self):
+               self.close()
+       def keyGreen(self):
+               self.setHelpModeActions(self.MODE_GLOBAL)
+       def keyYellow(self):
+               self.setHelpModeActions(self.MODE_MOUSE)
+       def keyBlue(self):
+               self.setHelpModeActions(self.MODE_KEYBOARD)
+
 _g_helper = None
 class OperaBrowser(Screen):
        MENUBAR_ITEM_WIDTH  = 150
 _g_helper = None
 class OperaBrowser(Screen):
        MENUBAR_ITEM_WIDTH  = 150
@@ -938,28 +1549,33 @@ class OperaBrowser(Screen):
                <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" />
                <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="menuitemTool" position="180,20" size="150,30" font="Regular;20" valign="center" halign="center" backgroundColor="#000000" foregroundColors="#9f1313,#a08500" />
+                       <widget name="menuitemHelp" position="330,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>
                        <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)
+               """ % (MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH, SUBMENULIST_WIDTH+50+SUBMENULIST_NEXT, MENUBAR_ITEM_HEIGHT+30, SUBMENULIST_WIDTH)# modify menu
 
 
-       MENUITEMS_LIST =[[('Open Location', None), ('Start/Stop',None), ('Exit', None)],
-                        [('About', None)]]
+       MENUITEMS_LIST =[[('Open Startpage', None), ('Open URL', None), ('Start/Stop',None), ('Exit', None)],
+                        [('Bookmark', None), ('Preference', None)],
+                        [('About', None), ('Help', None)]]
        def __init__(self, session):
                Screen.__init__(self, session)
        def __init__(self, session):
                Screen.__init__(self, session)
-
-               self["actions"] = ActionMap(["MinuteInputActions", "ColorActions", "InputActions", "InfobarChannelSelection", "EPGSelectActions", "KeyboardInputActions"], {
+               self["actions"] = ActionMap(["DirectionActions", "MenuActions", "OkCancelActions"], {
                         "cancel"      : self.keyCancel
                        ,"ok"          : self.keyOK
                        ,"left"        : self.keyLeft
                        ,"right"       : self.keyRight
                        ,"up"          : self.keyUp
                        ,"down"        : self.keyDown
                         "cancel"      : self.keyCancel
                        ,"ok"          : self.keyOK
                        ,"left"        : self.keyLeft
                        ,"right"       : self.keyRight
                        ,"up"          : self.keyUp
                        ,"down"        : self.keyDown
-                       ,"menu"        : self.keyCancel
+                       ,"menu"        : self.keyMenu
                }, -2)
 
                }, -2)
 
+               self._terminatedBrowser = True
+               self._enableKeyEvent = True
+               self._currentPageUrl = None
+               self._currentPageTitle = None
                self.menubarCurrentIndex = 0
                self.lvMenuItems = []
                self.lvSubMenuItems = []
                self.menubarCurrentIndex = 0
                self.lvMenuItems = []
                self.lvSubMenuItems = []
@@ -967,7 +1583,8 @@ class OperaBrowser(Screen):
                self["topArea"]    = Label()
                self["bottomArea"] = Label()
 
                self["topArea"]    = Label()
                self["bottomArea"] = Label()
 
-               self["menuitemFile"] = MultiColorLabel()
+               self["menuitemFile"] = MultiColorLabel()# modify menu
+               self["menuitemTool"] = MultiColorLabel()
                self["menuitemHelp"] = MultiColorLabel()
 
                self["menulist"] = MenuList(self.setListOnView())
                self["menuitemHelp"] = MultiColorLabel()
 
                self["menulist"] = MenuList(self.setListOnView())
@@ -989,19 +1606,21 @@ class OperaBrowser(Screen):
                        os.system("echo %d > %s" % (mode, rcmouse_path))
 
        def layoutFinished(self):
                        os.system("echo %d > %s" % (mode, rcmouse_path))
 
        def layoutFinished(self):
-               self["menuitemFile"].setText("File")
+               self["menuitemFile"].setText("File")# modify menu
+               self["menuitemTool"].setText("Tools")
                self["menuitemHelp"].setText("Help")
 
                self["menulist"].hide()
                self["submenulist"].hide()
 
                self["menuitemHelp"].setText("Help")
 
                self["menulist"].hide()
                self["submenulist"].hide()
 
-               self["bottomArea"].setText("Opera Web Browser Plugin v0.1")
+               self["bottomArea"].setText("Opera Web Browser Plugin v1.0")
                self.setTitle("BrowserMain")
                self.selectMenuitem()
 
        def selectMenuitem(self):
                self.setTitle("BrowserMain")
                self.selectMenuitem()
 
        def selectMenuitem(self):
-               tmp = [self["menuitemFile"], self["menuitemHelp"]]
+               tmp = [self["menuitemFile"], self["menuitemTool"], self["menuitemHelp"]]# modify menu
                self["menuitemFile"].setForegroundColorNum(0)
                self["menuitemFile"].setForegroundColorNum(0)
+               self["menuitemTool"].setForegroundColorNum(0)
                self["menuitemHelp"].setForegroundColorNum(0)
                tmp[self.menubarCurrentIndex].setForegroundColorNum(1)
 
                self["menuitemHelp"].setForegroundColorNum(0)
                tmp[self.menubarCurrentIndex].setForegroundColorNum(1)
 
@@ -1012,7 +1631,10 @@ class OperaBrowser(Screen):
                self.keyCancel()
 
        def setListOnView(self):
                self.keyCancel()
 
        def setListOnView(self):
-               self.lvMenuItems = self.MENUITEMS_LIST[self.menubarCurrentIndex]        
+               l = self.MENUITEMS_LIST[self.menubarCurrentIndex]
+               if not self._terminatedBrowser and self.menubarCurrentIndex == 0: # running
+                       l = [('Return', None)]
+               self.lvMenuItems = l #self.MENUITEMS_LIST[self.menubarCurrentIndex]     
                return self.lvMenuItems
 
        def setSubListOnView(self):
                return self.lvMenuItems
 
        def setSubListOnView(self):
@@ -1064,6 +1686,12 @@ class OperaBrowser(Screen):
                self.enableRCMouse(False)
                self.toggleMainScreen()
                eRCInput.getInstance().unlock()
                self.enableRCMouse(False)
                self.toggleMainScreen()
                eRCInput.getInstance().unlock()
+               self._terminatedBrowser = True
+               self._enableKeyEvent = True
+               #if not self.toggleListViewFlag:
+               #       self.keyDown()
+               self.keyRight()
+               self.keyLeft()
 
        def _on_setPageTitle(self, title=None):
                print "Title :",title
 
        def _on_setPageTitle(self, title=None):
                print "Title :",title
@@ -1075,6 +1703,7 @@ class OperaBrowser(Screen):
                print "Inputed Url :", data
                if strIsEmpty(data):
                        return
                print "Inputed Url :", data
                if strIsEmpty(data):
                        return
+               #self.hideSubmenu()
                command_server = getCommandServer()
                if self._on_setPageTitle not in command_server.onSetPageTitleCB:
                                command_server.onSetPageTitleCB.append(self._on_setPageTitle)
                command_server = getCommandServer()
                if self._on_setPageTitle not in command_server.onSetPageTitleCB:
                                command_server.onSetPageTitleCB.append(self._on_setPageTitle)
@@ -1085,11 +1714,18 @@ class OperaBrowser(Screen):
                eRCInput.getInstance().lock()
                command_util = getCommandUtil()
                command_util.sendCommand('OP_BROWSER_OPEN_URL', data)
                eRCInput.getInstance().lock()
                command_util = getCommandUtil()
                command_util.sendCommand('OP_BROWSER_OPEN_URL', data)
+               self._terminatedBrowser = False
+               self._enableKeyEvent = False
 
        def _on_close_window(self):
                self._onCloseTimer.start(1000)
 
 
        def _on_close_window(self):
                self._onCloseTimer.start(1000)
 
-       def _cmd_on_OpenLocation(self):
+       def _cb_bookmarkWindowClosed(self, data=None):
+               if data is None:
+                       return
+               self.cbUrlText(data)
+
+       def _cmd_on_OpenUrl(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."
                global _g_helper
                if not _g_helper._is_browser_running():
                        message = "Opera Browser was not running.\nPlease running browser using [File]>[Start/Stop] menu."
@@ -1097,7 +1733,7 @@ class OperaBrowser(Screen):
                        return
                self.session.openWithCallback(self.cbUrlText, VirtualKeyBoard, title=("Please enter URL here"), text='http://')
        def _cmd_on_About(self):
                        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)
+               self.session.open(MessageBox, 'Opera Web Browser Plugin v1.0', type = MessageBox.TYPE_INFO)
        def _cmd_on_Exit(self):
                self.close()
        def _cmd_on_StartStop(self):
        def _cmd_on_Exit(self):
                self.close()
        def _cmd_on_StartStop(self):
@@ -1105,16 +1741,46 @@ class OperaBrowser(Screen):
                if _g_helper is None: 
                        return
                _g_helper.showBrowserConfigBox()
                if _g_helper is None: 
                        return
                _g_helper.showBrowserConfigBox()
+       def _cmd_on_Bookmark(self):
+               url = self._currentPageUrl
+               if url is None:
+                       url = ''
+               title = self._currentPageTitle
+               if title is None:
+                       title = ''
+               self.session.openWithCallback(self._cb_bookmarkWindowClosed, OperaBrowserBookmarkWindow, url, title)
+       def _cmd_on_Preference(self):
+               url = self._currentPageUrl
+               if url is None:
+                       url = ''
+               self.session.open(OperaBrowserPreferenceWindow, url)
+       def _cmd_on_OpenStartpage(self):
+               start = 'http://vuplus.com'
+               try:
+                       start = OperaBrowserSetting().getData()['start']
+               except: pass
+               self.cbUrlText(start)
+       def _cmd_on_ReturnToBrowser(self):
+               self.keyCancel()
+
+       def _cmd_on_Help(self):
+               self.session.open(BrowserHelpWindow)
+
        def doCommand(self, command):
        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
+               cmd_map = {# modify menu
+                        'Exit'         :self._cmd_on_Exit
+                       ,'Help'         :self._cmd_on_Help
+                       ,'About'        :self._cmd_on_About
+                       ,'Open URL'     :self._cmd_on_OpenUrl
+                       ,'Start/Stop'   :self._cmd_on_StartStop
+                       ,'Bookmark'     :self._cmd_on_Bookmark
+                       ,'Preference'   :self._cmd_on_Preference
+                       ,'Return'       :self._cmd_on_ReturnToBrowser
+                       ,'Open Startpage' :self._cmd_on_OpenStartpage
                }
                try:
                        cmd_map[command]()
                }
                try:
                        cmd_map[command]()
-               except: pass
+               except Exception, ErrMsg: print ErrMsg
 
        def keyOK(self):
                if not self.toggleListViewFlag:
 
        def keyOK(self):
                if not self.toggleListViewFlag:
@@ -1128,8 +1794,8 @@ class OperaBrowser(Screen):
 
        def updateSelectedMenuitem(self, status):
                if self.menubarCurrentIndex == 0 and status < 0:
 
        def updateSelectedMenuitem(self, status):
                if self.menubarCurrentIndex == 0 and status < 0:
-                       self.menubarCurrentIndex = 1
-               elif self.menubarCurrentIndex == 1 and status > 0:
+                       self.menubarCurrentIndex = 2 # modify menu
+               elif self.menubarCurrentIndex == 2 and status > 0: # modify menu
                        self.menubarCurrentIndex = 0
                else:   self.menubarCurrentIndex += status
                self.selectMenuitem()
                        self.menubarCurrentIndex = 0
                else:   self.menubarCurrentIndex += status
                self.selectMenuitem()
@@ -1144,8 +1810,11 @@ class OperaBrowser(Screen):
                        self.setCurrentListView(1)
                        self.toggleSubListView()
                        return
                        self.setCurrentListView(1)
                        self.toggleSubListView()
                        return
-               if self.currentListView.getSelectedIndex():
-                       self.currentListView.pageUp()
+               #if self.currentListView.getSelectedIndex():
+               self.currentListView.pageUp()
+               self.keyUp()
+               self.keyLeft()
+               self.keyDown()
 
        def keyRight(self):
                if not self.toggleMainScreenFlag:
 
        def keyRight(self):
                if not self.toggleMainScreenFlag:
@@ -1162,6 +1831,11 @@ class OperaBrowser(Screen):
                        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()
                        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()
+                       return
+               self.currentListView.pageUp()
+               self.keyUp()
+               self.keyRight()
+               self.keyDown()
 
        def keyDown(self):
                if not self.toggleMainScreenFlag:
 
        def keyDown(self):
                if not self.toggleMainScreenFlag:
@@ -1188,8 +1862,39 @@ class OperaBrowser(Screen):
                self.currentListView.up()
 
        def keyCancel(self):
                self.currentListView.up()
 
        def keyCancel(self):
+               if not self._terminatedBrowser:
+                       #self._session.openWithCallback(self._cb_virtualKeyboardClosed, VirtualKeyBoard, title=("Please enter URL here"), text="")
+                       eRCInput.getInstance().lock()
+                       if self.toggleListViewFlag:
+                               self.toggleMainScreen()
+                       self._currentPageUrl   = None
+                       self._currentPageTitle = None
+                       command_util = getCommandUtil()
+                       command_util.sendCommand('OP_BROWSER_MENU_RES')
+                       return
+               self.close()
+
+       def keyMenu(self):
                self.toggleMainScreen()
 
                self.toggleMainScreen()
 
+       def setCurrentPageUrl(self, url, title=None):
+               self._currentPageUrl = url
+               if title is None:
+                       idx = len(url)
+                       if idx > 10: idx = 10
+                       title = url[:idx]
+               self._currentPageTitle = title
+               print self._currentPageUrl
+               self.toggleMainScreen()
+               self.hideSubmenu()
+               self.keyDown()
+
+       def hideSubmenu(self):
+               self.currentListView.pageUp()
+               self.keyUp()
+
+
+
 def auto_start_main(reason, **kwargs):
        if reason:
                command_server = getCommandServer()
 def auto_start_main(reason, **kwargs):
        if reason:
                command_server = getCommandServer()
@@ -1200,8 +1905,18 @@ def session_start_main(session, reason, **kwargs):
        global _g_helper
        _g_helper = session.open(HbbTVHelper)
 
        global _g_helper
        _g_helper = session.open(HbbTVHelper)
 
+_g_clearBrowserDataTimer = eTimer()
 def plugin_start_main(session, **kwargs):
 def plugin_start_main(session, **kwargs):
-       session.open(OperaBrowser)
+       #session.open(OperaBrowser)
+       def _do_clean():
+               _g_clearBrowserDataTimer.stop()
+               try:    _g_clearBrowserDataTimer.callback.remove(_do_clean)
+               except: pass
+               setPluginBrowser(None)
+       def clearBrowserData():
+               _g_clearBrowserDataTimer.callback.append(_do_clean)
+               _g_clearBrowserDataTimer.start(50)
+       setPluginBrowser(session.openWithCallback(clearBrowserData, OperaBrowser))
 
 def plugin_extension_start_application(session, **kwargs):
        global _g_helper
 
 def plugin_extension_start_application(session, **kwargs):
        global _g_helper