inhibit showing infobar on chapter change, don't load cuesheet if user says no in...
[enigma2.git] / lib / python / Plugins / Extensions / DVDPlayer / plugin.py
index 45c5ddeec4a857fde4ef30e0cb7bf0fefe85ceec..79a13e6aed9935aea74eb4cb06228b9bb11eaec7 100644 (file)
@@ -1,22 +1,18 @@
 from os import path as os_path, remove as os_remove, listdir as os_listdir, system
 from os import path as os_path, remove as os_remove, listdir as os_listdir, system
-from time import strftime
-from enigma import eTimer, iPlayableService, eServiceCenter, iServiceInformation, eServiceReference, iServiceKeys
+from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys
 from Screens.Screen import Screen
 from Screens.MessageBox import MessageBox
 from Screens.ChoiceBox import ChoiceBox
 from Screens.Screen import Screen
 from Screens.MessageBox import MessageBox
 from Screens.ChoiceBox import ChoiceBox
-from Screens.InputBox import InputBox
 from Screens.HelpMenu import HelpableScreen
 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
 from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
 from Components.Label import Label
 from Components.FileList import FileList
 from Screens.HelpMenu import HelpableScreen
 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
 from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
 from Components.Label import Label
 from Components.FileList import FileList
+from Components.MenuList import MenuList
 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.config import config
 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
 from Components.config import config
-from Components.ProgressBar import ProgressBar
-from ServiceReference import ServiceReference
 from Tools.Directories import pathExists, fileExists
 
 from Tools.Directories import pathExists, fileExists
 
-import random
 import servicedvd # load c++ part of dvd player plugin
 
 lastpath = ""
 import servicedvd # load c++ part of dvd player plugin
 
 lastpath = ""
@@ -26,19 +22,25 @@ class FileBrowser(Screen):
        <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
                <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
        </screen>"""
        <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
                <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
        </screen>"""
-       def __init__(self, session):
+       def __init__(self, session, dvd_filelist = None):
                Screen.__init__(self, session)
                Screen.__init__(self, session)
-               global lastpath
-               if lastpath is not None:
-                       currDir = lastpath + "/"
+
+               if dvd_filelist:
+                       self.dvd_filelist = dvd_filelist
+                       self["filelist"] = MenuList(self.dvd_filelist)
+
                else:
                else:
-                       currDir = "/media/dvd/"
-               if not pathExists(currDir):
-                       currDir = "/"
-               #else:
-                       #print system("mount "+currDir)
-               self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
-               self["filelist"] = self.filelist
+                       self.dvd_filelist = None
+                       global lastpath
+                       if lastpath is not None:
+                               currDir = lastpath + "/"
+                       else:
+                               currDir = "/media/dvd/"
+                       if not pathExists(currDir):
+                               currDir = "/"
+
+                       self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
+                       self["filelist"] = self.filelist
 
                self["FilelistActions"] = ActionMap(["OkCancelActions"],
                        {
 
                self["FilelistActions"] = ActionMap(["OkCancelActions"],
                        {
@@ -47,21 +49,29 @@ class FileBrowser(Screen):
                        })
 
        def ok(self):
                        })
 
        def ok(self):
-               global lastpath
-               filename = self["filelist"].getFilename()
-               if filename is not None:
-                       lastpath = filename[0:filename.rfind("/")]
-                       if filename.upper().endswith("VIDEO_TS/"):
-                               print "dvd structure found, trying to open..."
-                               self.close(filename[0:-9])
-               if self["filelist"].canDescent(): # isDir
-                       self["filelist"].descent()
+               if self.dvd_filelist:
+                       print "OK " + self["filelist"].getCurrent()
+                       self.close(self["filelist"].getCurrent())
                else:
                else:
-                       self.close(filename)
+                       global lastpath
+                       filename = self["filelist"].getFilename()
+                       if filename is not None:
+                               lastpath = filename[0:filename.rfind("/")]
+                               if filename.upper().endswith("VIDEO_TS/"):
+                                       print "dvd structure found, trying to open..."
+                                       self.close(filename[0:-9])
+                       if self["filelist"].canDescent(): # isDir
+                               self["filelist"].descent()
+                               pathname = self["filelist"].getCurrentDirectory() or ""
+                               if fileExists(pathname+"VIDEO_TS.IFO"):
+                                       print "dvd structure found, trying to open..."
+                                       self.close(pathname)
+                       else:
+                               self.close(filename)
 
        def exit(self):
                self.close(None)
 
        def exit(self):
                self.close(None)
-               
+
 class DVDSummary(Screen):
        skin = """
        <screen position="0,0" size="132,64">
 class DVDSummary(Screen):
        skin = """
        <screen position="0,0" size="132,64">
@@ -147,10 +157,9 @@ class ChapterZap(Screen):
                self.Timer.callback.append(self.keyOK)
                self.Timer.start(3000, True)
 
                self.Timer.callback.append(self.keyOK)
                self.Timer.start(3000, True)
 
-class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
-#InfoBarCueSheetSupport, 
+class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport):
 #      ALLOW_SUSPEND = True
 #      ALLOW_SUSPEND = True
-#      ENABLE_RESUME_SUPPORT = True
+       ENABLE_RESUME_SUPPORT = True
        
        skin = """
        <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
        
        skin = """
        <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
@@ -219,24 +228,26 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
                config.seek.on_pause.value = self.saved_config_seek_on_pause
 
                config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
                config.seek.on_pause.value = self.saved_config_seek_on_pause
 
-       def __init__(self, session, args = None):
+       def __init__(self, session, dvd_device = None, dvd_filelist = None, args = None):
                Screen.__init__(self, session)
                InfoBarBase.__init__(self)
                InfoBarNotifications.__init__(self)
                Screen.__init__(self, session)
                InfoBarBase.__init__(self)
                InfoBarNotifications.__init__(self)
-#              InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
+               InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
                InfoBarShowHide.__init__(self)
                HelpableScreen.__init__(self)
                self.save_infobar_seek_config()
                self.change_infobar_seek_config()
                InfoBarShowHide.__init__(self)
                HelpableScreen.__init__(self)
                self.save_infobar_seek_config()
                self.change_infobar_seek_config()
-               InfoBarSeek.__init__(self)
+               InfoBarSeek.__init__(self, useSeekBackHack=False)
                InfoBarPVRState.__init__(self)
                self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
 
                self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
                self.session.nav.stopService()
                InfoBarPVRState.__init__(self)
                self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
 
                self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
                self.session.nav.stopService()
-               self["audioLabel"] = Label("1")
+               self["audioLabel"] = Label("n/a")
                self["subtitleLabel"] = Label("")
                self["chapterLabel"] = Label("")
                self["subtitleLabel"] = Label("")
                self["chapterLabel"] = Label("")
+               self.last_audioTuple = None
+               self.last_subtitleTuple = None
                self.totalChapters = 0
                self.currentChapter = 0
                self.totalTitles = 0
                self.totalChapters = 0
                self.currentChapter = 0
                self.totalTitles = 0
@@ -244,6 +255,7 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
 
                self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
                        {
+                               iPlayableService.evStopped: self.__serviceStopped,
                                iPlayableService.evUser: self.__timeUpdated,
                                iPlayableService.evUser+1: self.__statePlay,
                                iPlayableService.evUser+2: self.__statePause,
                                iPlayableService.evUser: self.__timeUpdated,
                                iPlayableService.evUser+1: self.__statePlay,
                                iPlayableService.evUser+2: self.__statePause,
@@ -254,7 +266,6 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                                iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
                                iPlayableService.evUser+8: self.__chapterUpdated,
                                iPlayableService.evUser+9: self.__titleUpdated,
                                iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
                                iPlayableService.evUser+8: self.__chapterUpdated,
                                iPlayableService.evUser+9: self.__titleUpdated,
-                               #iPlayableService.evUser+10: self.__initializeDVDinfo,
                                iPlayableService.evUser+11: self.__menuOpened,
                                iPlayableService.evUser+12: self.__menuClosed
                        })
                                iPlayableService.evUser+11: self.__menuOpened,
                                iPlayableService.evUser+12: self.__menuClosed
                        })
@@ -317,10 +328,27 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                        })
 
                self.onClose.append(self.__onClose)
                        })
 
                self.onClose.append(self.__onClose)
+
+               if dvd_device:
+                               self.dvd_device = dvd_device
+                               self.physicalDVD = True
+               else:
+                       if fileExists("/dev/cdroms/cdrom0"):
+                               print "physical dvd found (/dev/cdroms/cdrom0)"
+                               self.dvd_device = "/dev/cdroms/cdrom0"
+                               self.physicalDVD = True
+                       else:
+                               self.dvd_device = None
+                               self.physicalDVD = False
+
+               self.dvd_filelist = dvd_filelist
                self.onFirstExecBegin.append(self.showFileBrowser)
                self.service = None
                self.in_menu = False
                self.onFirstExecBegin.append(self.showFileBrowser)
                self.service = None
                self.in_menu = False
-               
+               self.old_aspect = open("/proc/stb/video/aspect", "r").read()
+               self.old_policy = open("/proc/stb/video/policy", "r").read()
+               self.old_wss = open("/proc/stb/denc/0/wss", "r").read()
+
        def keyNumberGlobal(self, number):
                print "You pressed number " + str(number)
                self.session.openWithCallback(self.numberEntered, ChapterZap, number)
        def keyNumberGlobal(self, number):
                print "You pressed number " + str(number)
                self.session.openWithCallback(self.numberEntered, ChapterZap, number)
@@ -330,8 +358,13 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                if retval > 0:
                        self.zapToNumber(retval)
 
                if retval > 0:
                        self.zapToNumber(retval)
 
+       def __serviceStopped(self):
+               self.dvdScreen.hide()
+               self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
+
        def serviceStarted(self): #override InfoBarShowHide function
        def serviceStarted(self): #override InfoBarShowHide function
-               pass
+               self.dvdScreen.show()
+               self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
 
        def doEofInternal(self, playing):
                if self.in_menu:
 
        def doEofInternal(self, playing):
                if self.in_menu:
@@ -389,39 +422,44 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                print "StringAvail"
 
        def __osdAudioInfoAvail(self):
                print "StringAvail"
 
        def __osdAudioInfoAvail(self):
-               audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
-               print "AudioInfoAvail "+audioString
+               audioTuple = self.service.info().getInfoObject(iServiceInformation.sUser+6)
+               print "AudioInfoAvail ", repr(audioTuple)
+               audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
                self["audioLabel"].setText(audioString)
                self["audioLabel"].setText(audioString)
-               if not self.in_menu:
+               if audioTuple != self.last_audioTuple and not self.in_menu:
                        self.doShow()
                        self.doShow()
+               self.last_audioTuple = audioTuple
 
        def __osdSubtitleInfoAvail(self):
 
        def __osdSubtitleInfoAvail(self):
-               subtitleString = self.service.info().getInfoString(iPlayableService.evUser+7)
-               print "SubtitleInfoAvail "+subtitleString
+               subtitleTuple = self.service.info().getInfoObject(iServiceInformation.sUser+7)
+               print "SubtitleInfoAvail ", repr(subtitleTuple)
+               subtitleString = ""
+               if subtitleTuple[0] is not 0:
+                       subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
                self["subtitleLabel"].setText(subtitleString)
                self["subtitleLabel"].setText(subtitleString)
-               if not self.in_menu:
+               if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
                        self.doShow()
                        self.doShow()
+               self.last_subtitleTuple = subtitleTuple
 
        def __chapterUpdated(self):
 
        def __chapterUpdated(self):
-               self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
-               self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
+               self.currentChapter = self.service.info().getInfo(iServiceInformation.sCurrentChapter)
+               self.totalChapters = self.service.info().getInfo(iServiceInformation.sTotalChapters)
                self.setChapterLabel()
                print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
 
        def __titleUpdated(self):
                self.setChapterLabel()
                print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
 
        def __titleUpdated(self):
-               self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
-               self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
+               self.currentTitle = self.service.info().getInfo(iServiceInformation.sCurrentTitle)
+               self.totalTitles = self.service.info().getInfo(iServiceInformation.sTotalTitles)
                self.setChapterLabel()
                print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
                if not self.in_menu:
                        self.doShow()
                
                self.setChapterLabel()
                print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
                if not self.in_menu:
                        self.doShow()
                
-       #def __initializeDVDinfo(self):
-               #self.__osdAudioInfoAvail()
-               #self.__osdSubtitleInfoAvail()
-
        def askLeavePlayer(self):
        def askLeavePlayer(self):
-               self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
+               if self.physicalDVD:
+                       self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Continue playing"), "play"), (_("Exit"), "exit")])
+               else:
+                       self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Continue playing"), "play"), (_("Return to file browser"), "browser"), (_("Exit"), "exit")])
 
        def nextAudioTrack(self):
                if self.service:
 
        def nextAudioTrack(self):
                if self.service:
@@ -454,13 +492,13 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
        def enterDVDMenu(self):
                if self.service:
                        self.service.keys().keyPressed(iServiceKeys.keyUser+7)
        def enterDVDMenu(self):
                if self.service:
                        self.service.keys().keyPressed(iServiceKeys.keyUser+7)
-                       
+
        def seekBeginning(self):
                if self.service:
                        seekable = self.getSeek()
                        if seekable is not None:
                                seekable.seekTo(0)
        def seekBeginning(self):
                if self.service:
                        seekable = self.getSeek()
                        if seekable is not None:
                                seekable.seekTo(0)
-                               
+
        def zapToNumber(self, number):
                if self.service:
                        seekable = self.getSeek()
        def zapToNumber(self, number):
                if self.service:
                        seekable = self.getSeek()
@@ -495,7 +533,19 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                self.askLeavePlayer()
 
        def showFileBrowser(self):
                self.askLeavePlayer()
 
        def showFileBrowser(self):
-               self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
+               if self.physicalDVD:
+                       if self.dvd_device == "/dev/cdroms/cdrom0":
+                               self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
+                       else:
+                               self.DVDdriveCB(True)
+               else:
+                       self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
+       
+       def DVDdriveCB(self, answer):
+               if answer == True:
+                       self.FileBrowserClosed(self.dvd_device)
+               else:
+                       self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
 
        def FileBrowserClosed(self, val):
                curref = self.session.nav.getCurrentlyPlayingServiceReference()
 
        def FileBrowserClosed(self, val):
                curref = self.session.nav.getCurrentlyPlayingServiceReference()
@@ -510,54 +560,43 @@ class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarP
                                self.service = self.session.nav.getCurrentService()
                                print "self.service", self.service
                                print "cur_dlg", self.session.current_dialog
                                self.service = self.session.nav.getCurrentService()
                                print "self.service", self.service
                                print "cur_dlg", self.session.current_dialog
-                               self.dvdScreen.show()
-                               self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
 
        def exitCB(self, answer):
                if answer is not None:
                        if answer[1] == "exit":
                                if self.service:
 
        def exitCB(self, answer):
                if answer is not None:
                        if answer[1] == "exit":
                                if self.service:
-                                       self.dvdScreen.hide()
-                                       self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
                                        self.service = None
                                self.close()
                        if answer[1] == "browser":
                                #TODO check here if a paused dvd playback is already running... then re-start it...
                                #else
                                        self.service = None
                                self.close()
                        if answer[1] == "browser":
                                #TODO check here if a paused dvd playback is already running... then re-start it...
                                #else
+                               if self.service:
+                                       self.service = None
                                self.showFileBrowser()
                        else:
                                pass
 
        def __onClose(self):
                                self.showFileBrowser()
                        else:
                                pass
 
        def __onClose(self):
+               for i in (("/proc/stb/video/aspect", self.old_aspect), ("/proc/stb/video/policy", self.old_policy), ("/proc/stb/denc/0/wss", self.old_wss)):
+                       try:
+                               open(i[0], "w").write(i[1])
+                       except IOError:
+                               print "restore", i[0], "failed"
                self.restore_infobar_seek_config()
                self.session.nav.playService(self.oldService)
 
                self.restore_infobar_seek_config()
                self.session.nav.playService(self.oldService)
 
-#      def playLastCB(self, answer): # overwrite infobar cuesheet function
-#              print "playLastCB", answer, self.resume_point
-#              pos = self.resume_point
-#              title = self.resume_point % 90000
-#              pos -= title
-#              chapter = title % 256
-#              title /= 256
-#              print "pos", pos, "title", title, "chapter", chapter
-#              if self.service:
-#                      seek = self.service.seek()
-#                      if title != 1:
-#                              seek.seekTitle(title)
-#                              self.resume_state = 1
-#                      elif chapter != 1:
-#                              seek.seekChapter(chapter)
-#                              self.resume_state = 2
-#                      else:
-#                              seek.seekTo(pos)
-#              self.hideAfterResume()
+       def playLastCB(self, answer): # overwrite infobar cuesheet function
+               print "playLastCB", answer, self.resume_point
+               if self.service and answer == True:
+                       seek = self.service.seek()
+                       seek.seekTo(self.resume_point)
+               self.hideAfterResume()
 
        def showAfterCuesheetOperation(self):
                if not self.in_menu:
                        self.show()
 
        def createSummary(self):
 
        def showAfterCuesheetOperation(self):
                if not self.in_menu:
                        self.show()
 
        def createSummary(self):
-               print "DVDCreateSummary"
                return DVDSummary
 
 #override some InfoBarSeek functions
                return DVDSummary
 
 #override some InfoBarSeek functions
@@ -576,5 +615,46 @@ def menu(menuid, **kwargs):
        return []
 
 from Plugins.Plugin import PluginDescriptor
        return []
 
 from Plugins.Plugin import PluginDescriptor
+
+def filescan_open(list, session, **kwargs):
+       if len(list) == 1 and list[0].mimetype == "video/x-dvd":
+               splitted = list[0].path.split('/')
+               print "splitted", splitted
+               if len(splitted) > 2:
+                       if splitted[1] == 'autofs':
+                               session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
+                               return
+                       else:
+                               print "splitted[0]", splitted[1]
+       else:
+               dvd_filelist = []
+               for x in list:
+                       if x.mimetype == "video/x-dvd-iso":
+                               dvd_filelist.append(x.path)
+                       if x.mimetype == "video/x-dvd":
+                               dvd_filelist.append(x.path.rsplit('/',1)[0])                    
+               session.open(DVDPlayer, dvd_filelist=dvd_filelist)
+
+def filescan(**kwargs):
+       from Components.Scanner import Scanner, ScanPath
+
+       # Overwrite checkFile to only detect local
+       class LocalScanner(Scanner):
+               def checkFile(self, file):
+                       return fileExists(file.path)
+
+       return [
+               LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
+                       paths_to_scan =
+                               [
+                                       ScanPath(path = "video_ts", with_subdirs = False),
+                                       ScanPath(path = "", with_subdirs = False),
+                               ],
+                       name = "DVD",
+                       description = "Play DVD",
+                       openfnc = filescan_open,
+               )]              
+
 def Plugins(**kwargs):
 def Plugins(**kwargs):
-       return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]
+       return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
+                       PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]