add plugins(dlnaserver and dlnabrowser)
[vuplus_dvbapp] / lib / python / Plugins / Extensions / DLNABrowser / plugin.py
diff --git a/lib/python/Plugins/Extensions/DLNABrowser/plugin.py b/lib/python/Plugins/Extensions/DLNABrowser/plugin.py
new file mode 100644 (file)
index 0000000..b6fa471
--- /dev/null
@@ -0,0 +1,905 @@
+from Plugins.Plugin import PluginDescriptor
+
+import os
+from enigma import gFont, eTimer, eConsoleAppContainer, ePicLoad, getDesktop, eServiceReference, iPlayableService, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_HALIGN_CENTER, RT_VALIGN_CENTER
+
+from Screens.Screen import Screen
+from Screens.ChoiceBox import ChoiceBox
+from Screens.MessageBox import MessageBox
+from Screens.InfoBarGenerics import InfoBarNotifications
+
+from Components.Button import Button
+from Components.Label import Label
+from Components.ConfigList import ConfigListScreen
+from Components.Sources.StaticText import StaticText
+from Components.ActionMap import NumberActionMap, ActionMap
+from Components.config import config, ConfigSelection, getConfigListEntry, ConfigText, ConfigDirectory, ConfigYesNo, ConfigSelection
+from Components.FileList import FileList, FileEntryComponent
+from Components.MenuList import MenuList
+from Components.Pixmap import Pixmap, MovingPixmap
+from Components.AVSwitch import AVSwitch
+from Components.ServiceEventTracker import ServiceEventTracker
+from Components.MultiContent import MultiContentEntryText
+
+from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS
+
+EXTENSIONS = {
+       ".m4a" : "music",
+       ".mp2" : "music",
+       ".mp3" : "music",
+       ".wav" : "music",
+       ".ogg" : "music",
+       ".flac": "music",
+       ".ts"  : "movie",
+       ".avi" : "movie",
+       ".divx": "movie",
+       ".m4v" : "movie",
+       ".mpg" : "movie",
+       ".mpeg": "movie",
+       ".mkv" : "movie",
+       ".mp4" : "movie",
+       ".mov" : "movie",
+       ".m2ts": "movie",
+       ".wmv" : "movie",
+       ".jpg" : "picture",
+       ".jpeg": "picture",
+       ".png" : "picture",
+       ".bmp" : "picture",
+       ".m3u" : "stream",
+       ".m3u8": "stream",
+}
+
+DLNA_CONFIG_SLIDESHOW       = 10000
+DLNA_CONFIG_DEVICE_REFRESH  = 10000
+DLNA_CONFIG_ROOT_DIR        = '/media/upnp/'
+DLNA_CONFIG_CLIENT_CONFNAME = "/etc/djmount.conf"
+
+
+class DLNAFileList(FileList):
+       def __init__(self, directory):
+               self.rootDir = directory
+               inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/lib", "/proc", "/sbin", "/sys", "/usr", "/var"]
+               matchingPattern = "(?i)^.*\.(m4a|mp2|mp3|wav|ogg|flac|ts|avi|divx|m4v|mpg|mpeg|mkv|mp4|mov|m2ts|jpg|jpeg|png|bmp)"
+               FileList.__init__(self, directory=directory, matchingPattern=matchingPattern, showDirectories=True, showFiles=True, inhibitMounts=[], inhibitDirs=inhibitDirs, isTop=True)
+
+       def changeTop(self):
+               parent = ""
+               directoryItem = self.rootDir[:-1].split('/')
+               directoryItem.pop()
+               for di in directoryItem:
+                       parent += di+'/'
+               self.changeDir(self.rootDir, select=parent)
+
+       def changeParent(self):
+               i, parent, grandParent = 0, "", ""
+               currentDir = self.getCurrentDirectory()
+               if currentDir == self.rootDir:
+                       return False
+               directoryItem = currentDir[:-1].split('/')
+               directoryItem.pop()
+               for di in directoryItem:
+                       parent += di+'/'
+               if len(directoryItem) > 0:
+                       directoryItem.pop()
+               for di in directoryItem:
+                       grandParent += di+'/'
+               if parent == grandParent:
+                       return False
+               self.changeDir(parent, select=grandParent)
+               return True
+
+       def getFileType(self):
+               try:
+                       selectedFileName = self.getSelection()[0]
+                       splitedFileName  = os.path.splitext(selectedFileName)
+                       return EXTENSIONS[splitedFileName[1]]
+               except: pass
+               return 'unknown'
+
+class DLNAFileBrowser(Screen):
+       skin =  """
+               <screen name="DLNAFileBrowser" position="center,center" size="600,350" title="File Browser">
+                       <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="455,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="455,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="directory" position="10,45" size="600,40" valign="center" font="Regular;20" />
+                       <widget name="filelist" position="0,100" zPosition="1" size="560,250" scrollbarMode="showOnDemand"/>
+               </screen>
+               <!--
+               <screen name="DLNAFileBrowser" position="center,90" size="1000,580" title="File Browser">
+                       <ePixmap pixmap="skin_default/buttons/red.png" position="55,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/green.png" position="305,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/yellow.png" position="555,0" size="140,40" alphatest="on" />
+                       <ePixmap pixmap="skin_default/buttons/blue.png" position="805,0" size="140,40" alphatest="on" />
+
+                       <widget source="key_red" render="Label" position="55,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="305,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="555,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="805,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="directory" position="10,60" size="980,22" valign="center" font="Regular;22" />
+                       <widget name="filelist" position="0,100" zPosition="1" size="1000,480" scrollbarMode="showOnDemand"/>
+               </screen>
+               -->
+               """
+       def __init__(self, session, directory):
+               self.session = session
+               Screen.__init__(self, session)
+               
+               self["actions"]  = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"], {
+                       "back"  : self.keyCancel,
+                       "left"  : self.keyLeft,
+                       "right" : self.keyRight,
+                       "up"    : self.keyUp,
+                       "down"  : self.keyDown,
+                       "ok"    : self.keyOK,
+                       "green" : self.keyGreen,
+                       "red"   : self.keyCancel,
+                       "yellow": self.keyYellow,
+                       "blue"  : self.keyBlue
+               }, -1)
+
+               self["directory"]  = Label()
+               self["key_red"]    = StaticText(_("Show Device"))
+               self["key_green"]  = StaticText(_(" "))
+               self["key_yellow"] = StaticText(_("Up"))
+               self["key_blue"]   = StaticText(_("Top"))
+               self["filelist"]   = DLNAFileList(directory)
+
+               self.onLayoutFinish.append(self.layoutFinished)
+
+               self.showCB = {
+                       'movie'   : self.showMovie,
+                       'music'   : self.showMusic,
+                       'picture' : self.showPicture,
+                       'stream'  : self.showStream,
+                       'unknown' : self.showUnknown,
+               }
+
+       def layoutFinished(self):
+               self.updateDirectory()
+
+       def keyCancel(self):
+               self.close()
+
+       def keyBlue(self):
+               self["filelist"].changeTop()
+               self.updateDirectory()
+
+       def keyGreen(self):
+               print "not implements!!"
+
+       def keyYellow(self):
+               self["filelist"].changeParent()
+               self.updateDirectory()
+
+       def keyUp(self):
+               self["filelist"].up()
+               self.updateDirectory()
+
+       def keyDown(self):
+               self["filelist"].down()
+               self.updateDirectory()
+
+       def keyLeft(self):
+               self["filelist"].pageUp()
+               self.updateDirectory()
+
+       def keyRight(self):
+               self["filelist"].pageDown()
+               self.updateDirectory()
+
+       def keyOK(self):
+               try:
+                       if self["filelist"].canDescent():
+                               self["filelist"].descent()
+                               self.updateDirectory()
+                               return
+               except: return
+               fileType = self["filelist"].getFileType()
+               self.showCB[fileType]()
+
+       def updateDirectory(self):
+               directory = self["filelist"].getSelection()[0]
+               if directory is None or directory.strip() == '':
+                       directory = "Empty Directory!!"
+               self["directory"].setText(directory)
+
+       def showMovie(self):
+               from Plugins.Extensions.MediaPlayer.plugin import MediaPlayer
+               self.beforeService = self.session.nav.getCurrentlyPlayingServiceReference()
+               path = self["filelist"].getCurrentDirectory() + self["filelist"].getFilename()
+               mp = self.session.open(MediaPlayer)
+               mp.callback = self.cbShowMovie
+               mp.playlist.clear()
+               mp.savePlaylistOnExit = False
+               mp.playlist.addFile(eServiceReference(4097, 0, path))
+               mp.changeEntry(0)
+               mp.switchToPlayList()
+               
+       def showPicture(self):
+               self.session.openWithCallback(self.cbShowPicture, 
+                                             DLNAImageViewer, 
+                                             self["filelist"].getFileList(), 
+                                             self["filelist"].getSelectionIndex(), 
+                                             self["filelist"].getCurrentDirectory())
+
+       def showMusic(self):
+               self.showMovie()
+
+       def showStream(self):
+               path = self["filelist"].getCurrentDirectory() + self["filelist"].getFilename()
+               self.beforeService = self.session.nav.getCurrentlyPlayingServiceReference()
+               self.session.openWithCallback(self.cbShowMovie, 
+                                             DLNAStreamPlayer, 
+                                             eServiceReference(4097, 0, path), 
+                                             self.beforeService)
+
+       def showUnknown(self):
+               message = "Can't play selected file. It is unknown file extension."
+               self.session.open(MessageBox, message, type=MessageBox.TYPE_INFO)
+
+       def cbShowMovie(self, data=None):
+               if self.beforeService is not None:
+                       self.session.nav.playService(self.beforeService)
+                       self.beforeService = None
+
+       def cbShowPicture(self, idx=0):
+               if idx > 0: self["filelist"].moveToIndex(idx)
+
+class DLNAStreamPlayer(Screen, InfoBarNotifications):
+       skin =  """
+               <screen name="DLNAStreamPlayer" flags="wfNoBorder" position="center,620" size="455,53" title="DLNAStreamPlayer" backgroundColor="transparent">
+                       <ePixmap pixmap="Vu_HD/mp_wb_background.png" position="0,0" zPosition="-1" size="455,53" />
+                       <ePixmap pixmap="Vu_HD/icons/mp_wb_buttons.png" position="40,23" size="30,13" alphatest="on" />
+
+                       <widget source="session.CurrentService" render="PositionGauge" position="80,25" size="220,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
+                               <convert type="ServicePosition">Gauge</convert>
+                       </widget>
+                       
+                       <widget source="session.CurrentService" render="Label" position="310,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" >
+                               <convert type="ServicePosition">Position</convert>
+                       </widget>
+                       <widget name="sidebar" position="362,20" size="10,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" />
+                       <widget source="session.CurrentService" render="Label" position="374,20" size="50,20" font="Regular;18" halign="center" valign="center" backgroundColor="#4e5a74" transparent="1" > 
+                               <convert type="ServicePosition">Length</convert>
+                       </widget>
+               </screen>
+               """
+       PLAYER_IDLE     = 0
+       PLAYER_PLAYING  = 1
+       PLAYER_PAUSED   = 2
+
+       def __init__(self, session, service, lastservice):
+               Screen.__init__(self, session)
+               InfoBarNotifications.__init__(self)
+
+               self.session     = session
+               self.service     = service
+               self.lastservice = lastservice
+               self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"], {
+                       "ok": self.doInfoAction,
+                       "cancel": self.doExit,
+                       "stop": self.doExit,
+                       "playpauseService": self.playpauseService,
+               }, -2)
+               self["sidebar"] = Label(_("/"))
+
+               self.__event_tracker = ServiceEventTracker(screen = self, eventmap = {
+                       iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
+                       iPlayableService.evStart: self.__serviceStarted,
+                       iPlayableService.evEOF: self.__evEOF,
+               })
+
+               self.hidetimer = eTimer()
+               self.hidetimer.timeout.get().append(self.doInfoAction)
+
+               self.state = self.PLAYER_PLAYING
+               self.lastseekstate = self.PLAYER_PLAYING
+               self.__seekableStatusChanged()
+       
+               self.onClose.append(self.__onClose)
+               self.doPlay()
+
+       def __onClose(self):
+               self.session.nav.stopService()
+
+       def __seekableStatusChanged(self):
+               service = self.session.nav.getCurrentService()
+               if service is not None:
+                       seek = service.seek()
+                       if seek is None or not seek.isCurrentlySeekable():
+                               self.setSeekState(self.PLAYER_PLAYING)
+
+       def __serviceStarted(self):
+               self.state = self.PLAYER_PLAYING
+               self.__seekableStatusChanged()
+
+       def __evEOF(self):
+               self.doExit()
+
+       def __setHideTimer(self):
+               self.hidetimer.start(5000)
+
+       def doExit(self):
+               list = ((_("Yes"), "y"), (_("No"), "n"),)
+               self.session.openWithCallback(self.cbDoExit, ChoiceBox, title=_("Stop playing this movie?"), list = list)
+
+       def cbDoExit(self, answer):
+               answer = answer and answer[1]
+               if answer == "y":
+                       self.close()
+
+       def setSeekState(self, wantstate):
+               service = self.session.nav.getCurrentService()
+               if service is None:
+                       print "No Service found"
+                       return
+
+               pauseable = service.pause()
+               if pauseable is not None:
+                       if wantstate == self.PLAYER_PAUSED:
+                               pauseable.pause()
+                               self.state = self.PLAYER_PAUSED
+                               if not self.shown:
+                                       self.hidetimer.stop()
+                                       self.show()
+                       elif wantstate == self.PLAYER_PLAYING:
+                               pauseable.unpause()
+                               self.state = self.PLAYER_PLAYING
+                               if self.shown:
+                                       self.__setHideTimer()
+               else:
+                       self.state = self.PLAYER_PLAYING
+
+       def doInfoAction(self):
+               if self.shown:
+                       self.hidetimer.stop()
+                       self.hide()
+               else:
+                       self.show()
+                       if self.state == self.PLAYER_PLAYING:
+                               self.__setHideTimer()
+
+       def doPlay(self):
+               if self.state == self.PLAYER_PAUSED:
+                       if self.shown:
+                               self.__setHideTimer()   
+               self.state = self.PLAYER_PLAYING
+               self.session.nav.playService(self.service)
+               if self.shown:
+                       self.__setHideTimer()
+
+       def playpauseService(self):
+               if self.state == self.PLAYER_PLAYING:
+                       self.setSeekState(self.PLAYER_PAUSED)
+               elif self.state == self.PLAYER_PAUSED:
+                       self.setSeekState(self.PLAYER_PLAYING)
+
+class DLNAImageViewer(Screen):
+       s, w, h = 30, getDesktop(0).size().width(), getDesktop(0).size().height()
+       skin = """
+               <screen position="0,0" size="%d,%d" flags="wfNoBorder">
+                       <eLabel position="0,0" zPosition="0" size="%d,%d" backgroundColor="#00000000" />
+                       <widget name="image" position="%d,%d" size="%d,%d" zPosition="1" alphatest="on" />
+                       <widget name="status" position="%d,%d" size="20,20" zPosition="2" pixmap="skin_default/icons/record.png" alphatest="on" />
+                       <widget name="icon" position="%d,%d" size="20,20" zPosition="2" pixmap="skin_default/icons/ico_mp_play.png"  alphatest="on" />
+                       <widget source="message" render="Label" position="%d,%d" size="%d,25" font="Regular;20" halign="left" foregroundColor="#0038FF48" zPosition="2" noWrap="1" transparent="1" />
+               </screen>
+               """ % (w, h, w, h, s, s, w-(s*2), h-(s*2), s+5, s+2, s+25, s+2, s+45, s, w-(s*2)-50)
+
+       def __init__(self, session, fileList, index, path):
+               Screen.__init__(self, session)
+               self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "DirectionActions", "MovieSelectionActions"], {
+                       "cancel": self.keyCancel,
+                       "left"  : self.keyLeft,
+                       "right" : self.keyRight,
+                       "blue"  : self.keyBlue,
+                       "yellow": self.keyYellow,
+               }, -1)
+
+               self["icon"]    = Pixmap()
+               self["image"]   = Pixmap()
+               self["status"]  = Pixmap()
+               self["message"] = StaticText(_("Please wait, Loading image."))
+
+               self.fileList     = []
+               self.currentImage = []
+
+               self.lsatIndex      = index
+               self.fileListLen    = 0
+               self.currentIndex   = 0
+               self.directoryCount = 0
+
+               self.displayNow = True
+
+               self.makeFileList(fileList, path)
+
+               self.pictureLoad = ePicLoad()
+               self.pictureLoad.PictureData.get().append(self.finishDecode)
+
+               self.slideShowTimer = eTimer()
+               self.slideShowTimer.callback.append(self.cbSlideShow)
+
+               self.onLayoutFinish.append(self.layoutFinished)
+
+       def layoutFinished(self):
+               if self.fileListLen >= 0:
+                       self.setPictureLoadPara()
+
+       def keyLeft(self):
+               self.currentImage = []
+               self.currentIndex = self.lsatIndex
+               self.currentIndex -= 1
+               if self.currentIndex < 0:
+                       self.currentIndex = self.fileListLen
+               self.startDecode()
+               self.displayNow = True
+
+       def keyRight(self):
+               self.displayNow = True
+               self.showPicture()
+
+       def keyYellow(self):
+               if self.fileListLen < 0:
+                       return
+               from Plugins.Extensions.PicturePlayer.plugin import Pic_Exif
+               self.session.open(Pic_Exif, self.pictureLoad.getInfo(self.fileList[self.lsatIndex]))
+
+       def keyBlue(self):
+               if self.slideShowTimer.isActive():
+                       self.slideShowTimer.stop()
+                       self["icon"].hide()
+               else:
+                       global DLNA_CONFIG_SLIDESHOW
+                       self.slideShowTimer.start(DLNA_CONFIG_SLIDESHOW)
+                       self["icon"].show()
+                       self.keyRight()
+
+       def keyCancel(self):
+               del self.pictureLoad
+               self.close(self.lsatIndex + self.directoryCount)
+
+       def setPictureLoadPara(self):
+               sc = AVSwitch().getFramebufferScale()
+               self.pictureLoad.setPara([self["image"].instance.size().width(), 
+                                         self["image"].instance.size().height(), 
+                                         sc[0],
+                                         sc[1],
+                                         0,
+                                         int(config.pic.resize.value),
+                                         '#00000000'])
+               self["icon"].hide()
+               if config.pic.infoline.value == False:
+                       self["message"].setText("")
+               self.startDecode()
+
+       def makeFileList(self, fileList, path):
+               for x in fileList:
+                       l = len(fileList[0])
+                       if l == 3:
+                               if x[0][1] == False:
+                                       self.fileList.append(path + x[0][0])
+                               else:   self.directoryCount += 1
+                       elif l == 2:
+                               if x[0][1] == False:
+                                       self.fileList.append(x[0][0])
+                               else:   self.directoryCount += 1
+                       else:   self.fileList.append(x[4])
+               
+               self.currentIndex = self.lsatIndex - self.directoryCount
+               if self.currentIndex < 0:
+                       self.currentIndex = 0
+               self.fileListLen = len(self.fileList) - 1
+
+       def showPicture(self):
+               if self.displayNow and len(self.currentImage):
+                       self.displayNow = False
+                       self["message"].setText(self.currentImage[0])
+                       self.lsatIndex = self.currentImage[1]
+                       self["image"].instance.setPixmap(self.currentImage[2].__deref__())
+                       self.currentImage = []
+
+                       self.currentIndex += 1
+                       if self.currentIndex > self.fileListLen:
+                               self.currentIndex = 0
+                       self.startDecode()
+
+       def finishDecode(self, picInfo=""):
+               self["status"].hide()
+               ptr = self.pictureLoad.getData()
+               if ptr != None:
+                       text = ""
+                       try:
+                               text = picInfo.split('\n',1)
+                               text = "(" + str(self.currentIndex+1) + "/" + str(self.fileListLen+1) + ") " + text[0].split('/')[-1]
+                       except:
+                               pass
+                       self.currentImage = []
+                       self.currentImage.append(text)
+                       self.currentImage.append(self.currentIndex)
+                       self.currentImage.append(ptr)
+                       self.showPicture()
+
+       def startDecode(self):
+               self.pictureLoad.startDecode(self.fileList[self.currentIndex])
+               self["status"].show()
+
+       def cbSlideShow(self):
+               print "slide to next Picture index=" + str(self.lsatIndex)
+               if config.pic.loop.value==False and self.lsatIndex == self.fileListLen:
+                       self.PlayPause()
+               self.displayNow = True
+               self.showPicture()
+
+class TaskManager:
+       def __init__(self):
+               self.taskIdx = 0
+               self.taskList = []
+               self.gTaskInstance = None
+               self.occurError = False
+               self.cbSetStatusCB = None
+
+       def append(self, command, cbDataFunc, cbCloseFunc):
+               self.taskList.append([command+'\n', cbDataFunc, cbCloseFunc])
+
+       def dump(self):
+               print "############### TASK ###############"
+               print "Current Task Index :", self.taskIdx
+               print "Current Task Instance :", self.gTaskInstance
+               print "Occur Error :", self.occurError
+               print "Task List:\n", self.taskList
+               print "####################################"
+
+       def error(self):
+               print "[DLNAClient Plugin] Info >> set task error!!"
+               self.occurError = True
+
+       def reset(self):
+               self.taskIdx = 0
+               self.gTaskInstance = None
+               self.occurError = False
+
+       def clean(self):
+               self.reset()
+               self.taskList = []
+               self.cbSetStatusCB = None
+               print "clear task!!"
+
+       def index(self):
+               self.taskIdx
+
+       def setStatusCB(self, cbfunc):
+               self.cbSetStatusCB = cbfunc
+               
+       def next(self):
+               if self.taskIdx >= len(self.taskList) or self.occurError:
+                       print "[DLNAClient Plugin] Info >> can't run task!!"
+                       return False
+               command     = self.taskList[self.taskIdx][0]
+               cbDataFunc  = self.taskList[self.taskIdx][1]
+               cbCloseFunc = self.taskList[self.taskIdx][2]
+
+               self.gTaskInstance = eConsoleAppContainer()
+               if cbDataFunc is not None:
+                       self.gTaskInstance.dataAvail.append(cbDataFunc)
+               if cbCloseFunc is not None:
+                       self.gTaskInstance.appClosed.append(cbCloseFunc)
+               if self.cbSetStatusCB is not None:
+                       self.cbSetStatusCB(self.taskIdx)
+
+               print "[DLNAClient Plugin] Info >> prepared command : %s"%(command)
+               self.gTaskInstance.execute(command)
+               self.taskIdx += 1
+               return True
+
+class DLNAClientConfig(ConfigListScreen, Screen):
+       skin=   """
+               <screen position="center,center" size="600,350" title="Mini DLNA Runcher">
+                       <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="455,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="455,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="config" position="0,50" size="600,200" scrollbarMode="showOnDemand" />
+               </screen>
+               """
+       def __init__(self, session): 
+                self.session = session
+               Screen.__init__(self, session)
+
+               self.menulist  = []
+               self.oldConfig = {}
+               ConfigListScreen.__init__(self, self.menulist)
+
+               global DLNA_CONFIG_CLIENT_CONFNAME
+               self.configFileName = DLNA_CONFIG_CLIENT_CONFNAME
+               self["actions"] = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", ], {
+                       "red"    : self.keyExit,
+                       "green"  : self.keyOK,
+                       "cancel" : self.keyExit,
+                       "ok"     : self.keyOK,
+                }, -2)
+               self["key_red"]     = StaticText(_("Exit"))
+               self["key_green"]   = StaticText(_("Save"))
+               self["key_yellow"]  = StaticText(_(" "))
+               self["key_blue"]    = StaticText(_(" "))
+
+               self.makeMenuList()
+
+       def keyExit(self):
+               self.close(None, None, None)
+
+       def keyOK(self):
+               self.writeConfigFile()
+               #self.close(self.menuItemRefresh.value, self.menuItemRootDir.value)
+               self.close(self.menuItemRefresh.value, None, self.menuItemSlideshow.value)
+
+       def makeMenuList(self):
+               self.readConfigFile()
+               #self.menuItemRootDir   = ConfigText(default=self.oldConfig.get('rootdir'))
+               self.menuItemRefresh   = ConfigSelection(default=self.oldConfig.get('refresh'), choices = [("5", _("5")), ("10", _("10")), ("15", _("15"))])
+               self.menuItemSlideshow = ConfigSelection(default=self.oldConfig.get('slideshow'), choices = [("5", _("5")), ("10", _("10")), ("15", _("15")), ("20", _("20"))])
+
+               #self.menuEntryRootDir   = getConfigListEntry(_("Mount Point"), self.menuItemRootDir)
+               self.menuEntryRefresh   = getConfigListEntry(_("DeviceList Refresh Interval"), self.menuItemRefresh)
+               self.menuEntrySlideshow = getConfigListEntry(_("Slideshow Interval"), self.menuItemSlideshow)
+               self.resetMenuList()
+
+       def resetMenuList(self):
+               self.menulist = []
+               #self.menulist.append(self.menuEntryRootDir)
+               self.menulist.append(self.menuEntryRefresh)
+               self.menulist.append(self.menuEntrySlideshow)
+               self["config"].list = self.menulist
+               self["config"].l.setList(self.menulist)
+
+       def writeConfigFile(self):
+               def configDataAppend(origin, key, value):
+                       if key.strip() != '' and value.strip() != '':
+                               origin += "%s=%s\n" % (key,value)
+                       return origin
+               configString = ""
+               #configString = configDataAppend(configString, "rootdir", self.menuItemRootDir.value)
+               configString = configDataAppend(configString, "refresh", self.menuItemRefresh.value)
+               configString = configDataAppend(configString, "slideshow", self.menuItemSlideshow.value)
+               print configString
+               confFile = file(self.configFileName, 'w')
+               confFile.write(configString)
+               confFile.close()
+
+       def readConfigFile(self):
+               def setDefault(key, default):
+                       try:
+                               value = self.oldConfig.get(key)
+                               if value == None or value.strip() == '':
+                                       self.oldConfig[key] = default
+                       except: self.oldConfig[key] = default
+
+               self.oldConfig = {}
+               if not os.path.exists(self.configFileName):
+                       #setDefault('rootdir', '/media/upnp/')
+                       setDefault('refresh', '10')
+                       setDefault('slideshow', '10')
+                       return
+               for line in file(self.configFileName).readlines():
+                       line = line.strip()
+                       if line == '' or line[0] == '#':
+                               continue
+                       try:
+                               i   = line.find('=')
+                               k,v = line[:i],line[i+1:]
+                               self.oldConfig[k] = v
+                       except : pass
+
+               #setDefault('rootdir', '/media/upnp/')
+               setDefault('refresh', '10')
+               setDefault('slideshow', '10')
+               print "Current Config : ", self.oldConfig
+
+
+class DLNADeviceBrowser(Screen):
+       skin =  """
+               <screen name="DLNADeviceBrowser" position="center,center" size="600,350" title="Device Browser">
+                       <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="455,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="455,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" foregroundColor="#ffffff" transparent="1" />
+
+                       <widget name="devicelist" position="0,50" size="600,300" backgroundColor="#000000" zPosition="10" scrollbarMode="showOnDemand" />
+               </screen>
+               """
+       def __init__(self, session):
+               Screen.__init__(self, session)
+               self["actions"]  = ActionMap(["OkCancelActions", "ShortcutActions", "WizardActions", "ColorActions", "SetupActions", "NumberActions", "MenuActions"], {
+                       "ok"    : self.keyOK,
+                       "cancel": self.keyCancel,
+                       "red"   : self.keyCancel,
+                       "green" : self.keyGreen,
+                       "yellow": self.keyYellow,
+                       "blue"  : self.keyBlue,
+               }, -1)
+
+               global DLNA_CONFIG_CLIENT_CONFNAME
+               self.configFileName = DLNA_CONFIG_CLIENT_CONFNAME
+               self["key_red"]    = StaticText(_("Exit"))
+               self["key_green"]  = StaticText(_("Start"))
+               self["key_yellow"] = StaticText(_("Setting"))
+               self["key_blue"]   = StaticText(_("Reload Device"))
+
+               #self["devicelist"] = MenuList(self.setListOnView())
+               self["devicelist"] = MenuList([])
+               self.onLayoutFinish.append(self.layoutFinished)
+
+               self.initConfig()
+               self.taskManager = TaskManager()
+
+               self.toggleGreenButtonTimer = eTimer()
+               self.toggleGreenButtonTimer.timeout.get().append(self.cbToggleGreenButton)
+
+               self.deviceListRefreshTimer = eTimer()
+               self.deviceListRefreshTimer.timeout.get().append(self.cbDeviceListRefresh)
+               global DLNA_CONFIG_DEVICE_REFRESH
+               self.deviceListRefreshTimer.start(DLNA_CONFIG_DEVICE_REFRESH)
+
+       def layoutFinished(self):
+               if not os.path.exists('/media/upnp'):
+                       os.system('mkdir -p /media/upnp')
+               self.updateGUI()
+               if self["key_green"].getText() == 'Start':
+                       global DLNA_CONFIG_DEVICE_REFRESH
+                       self.deviceListRefreshTimer.start(DLNA_CONFIG_DEVICE_REFRESH)
+
+       def keyYellow(self):
+               self.deviceListRefreshTimer.stop()
+               self.session.openWithCallback(self.cbConfigClose, DLNAClientConfig)
+
+       def keyGreen(self):
+               global DLNA_CONFIG_ROOT_DIR
+               if self["key_green"].getText() == 'Stop':
+                       cmd = 'fusermount -u %s'%(DLNA_CONFIG_ROOT_DIR)
+                       self.taskManager.append(cmd, self.cbPrintAvail, self.cbPrintClose)
+                       cmd = 'modprobe -r fuse'
+                       self.taskManager.append(cmd, self.cbPrintAvail, self.cbStopDone)
+                       #cmd = 'killall -9 djmount'
+                       #self.taskManager.append(cmd, self.cbPrintAvail, self.cbTasksDone)
+                       self["devicelist"].setList([])
+               else:
+                       cmd = 'modprobe fuse'
+                       self.taskManager.append(cmd, self.cbPrintAvail, self.cbPrintClose)
+                       cmd = 'djmount -o allow_other -o iocharset=utf8 %s'%(DLNA_CONFIG_ROOT_DIR)
+                       self.taskManager.append(cmd, self.cbPrintAvail, self.cbStartDone)
+               self.taskManager.next()
+
+       def keyCancel(self):
+               self.close()
+
+       def keyOK(self):
+               global DLNA_CONFIG_ROOT_DIR
+               selectedFullPaht = '%s%s/'%(DLNA_CONFIG_ROOT_DIR, self["devicelist"].getCurrent()[1])
+               self.session.openWithCallback(self.cbDeviceListRefresh, DLNAFileBrowser, selectedFullPaht)
+               self.deviceListRefreshTimer.stop()
+
+       def keyBlue(self):
+               print "updated device list!!"
+               self["devicelist"].setList(self.setListOnView())
+
+       def initConfig(self):
+               global DLNA_CONFIG_ROOT_DIR
+               global DLNA_CONFIG_SLIDESHOW
+               global DLNA_CONFIG_DEVICE_REFRESH
+               if not os.path.exists(self.configFileName):
+                       DLNA_CONFIG_ROOT_DIR = '/media/upnp/'
+                       DLNA_CONFIG_DEVICE_REFRESH = 10000
+                       DLNA_CONFIG_SLIDESHOW = 10000
+                       print "config : [%s][%d][%d]"%(DLNA_CONFIG_ROOT_DIR, DLNA_CONFIG_SLIDESHOW, DLNA_CONFIG_DEVICE_REFRESH)
+                       return
+               for line in file(self.configFileName).readlines():
+                       line = line.strip()
+                       if line == '' or line[0] == '#':
+                               continue
+                       try:
+                               i   = line.find('=')
+                               k,v = line[:i],line[i+1:]
+                               if k == 'rootdir':      DLNA_CONFIG_ROOT_DIR = v
+                               elif k == 'refresh':    DLNA_CONFIG_DEVICE_REFRESH = int(v)*1000
+                               elif k == 'slideshow':  DLNA_CONFIG_SLIDESHOW = int(v)*1000
+                       except : pass
+               print "config : [%s][%d][%d]"%(DLNA_CONFIG_ROOT_DIR, DLNA_CONFIG_SLIDESHOW, DLNA_CONFIG_DEVICE_REFRESH)
+
+       def isRunning(self):
+               ps_str = os.popen('cat /etc/mtab | grep djmount').read()
+               if ps_str.strip() != '':
+                       return True
+               return False
+
+       def updateGUI(self):
+               green_btm_str = 'Start'
+               if self.isRunning():
+                       green_btm_str = 'Stop'
+               self["key_green"].setText(green_btm_str)
+               self.keyBlue()
+
+       def cbConfigClose(self, refresh, rootdir, slideshow):
+               global DLNA_CONFIG_ROOT_DIR
+               global DLNA_CONFIG_SLIDESHOW
+               global DLNA_CONFIG_DEVICE_REFRESH
+               try:
+                       if refresh is not None:
+                               newRefresh = int(refresh)*1000
+                               if DLNA_CONFIG_DEVICE_REFRESH != newRefresh:
+                                       DLNA_CONFIG_DEVICE_REFRESH = newRefresh
+               except: pass
+               try:
+                       if rootdir is not None:
+                               if DLNA_CONFIG_ROOT_DIR != rootdir:
+                                       DLNA_CONFIG_ROOT_DIR = rootdir
+                                       print "need restart!!!"
+               except: pass
+               try:
+                       if slideshow is not None:
+                               newSlideshow = int(slideshow)*1000
+                               if DLNA_CONFIG_SLIDESHOW != newSlideshow:
+                                       DLNA_CONFIG_SLIDESHOW = newSlideshow
+               except: pass
+               self.deviceListRefreshTimer.start(DLNA_CONFIG_DEVICE_REFRESH)
+               print "config : [%s][%d][%d]"%(DLNA_CONFIG_ROOT_DIR, DLNA_CONFIG_SLIDESHOW, DLNA_CONFIG_DEVICE_REFRESH)
+
+       def cbPrintAvail(self, data):
+               print data
+
+       def cbPrintClose(self, ret):
+               self.taskManager.next()
+
+       def cbStopDone(self, ret):
+               self.taskManager.clean()
+               self.toggleGreenButtonTimer.start(1000)
+               self.deviceListRefreshTimer.stop()
+
+       def cbStartDone(self, ret):
+               global DLNA_CONFIG_DEVICE_REFRESH
+               self.taskManager.clean()
+               self.toggleGreenButtonTimer.start(1000)
+               self.deviceListRefreshTimer.start(DLNA_CONFIG_DEVICE_REFRESH)
+
+       def cbToggleGreenButton(self):
+               self.toggleGreenButtonTimer.stop()
+               self.updateGUI()
+
+       def cbDeviceListRefresh(self):
+               global DLNA_CONFIG_DEVICE_REFRESH
+               self.deviceListRefreshTimer.start(DLNA_CONFIG_DEVICE_REFRESH)
+               self.keyBlue()
+
+       def setListOnView(slelf):
+               global DLNA_CONFIG_ROOT_DIR
+               items,rootdir = [],DLNA_CONFIG_ROOT_DIR
+               deviceList = [ name for name in os.listdir(rootdir) if os.path.isdir(os.path.join(rootdir, name)) ]
+               deviceList.sort()
+               for d in deviceList:
+                       if d[0] in ('.', '_'): continue
+                       items.append((d,d))
+               return items
+
+def main(session, **kwargs):
+       session.open(DLNADeviceBrowser)
+                                                           
+def Plugins(**kwargs):
+       return PluginDescriptor(name=_("DLNA/uPnP Browser"), description="This is dlna/upnp client using djmount.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)