1 from os import path as os_path, remove as os_remove, listdir as os_listdir, system
2 from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys, getDesktop
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Screens.ChoiceBox import ChoiceBox
6 from Screens.HelpMenu import HelpableScreen
7 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
8 from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
9 from Components.Label import Label
10 from Components.FileList import FileList
11 from Components.MenuList import MenuList
12 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
13 from Components.config import config
14 from Tools.Directories import pathExists, fileExists
15 from Components.Harddisk import harddiskmanager
17 import servicedvd # load c++ part of dvd player plugin
21 class FileBrowser(Screen):
23 <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
24 <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
26 def __init__(self, session, dvd_filelist = [ ]):
27 Screen.__init__(self, session)
29 self.dvd_filelist = dvd_filelist
31 self["filelist"] = MenuList(self.dvd_filelist)
34 if lastpath is not None:
35 currDir = lastpath + "/"
37 currDir = "/media/dvd/"
38 if not pathExists(currDir):
41 self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
42 self["filelist"] = self.filelist
44 self["FilelistActions"] = ActionMap(["OkCancelActions"],
51 if len(self.dvd_filelist):
52 print "OK " + self["filelist"].getCurrent()
53 self.close(self["filelist"].getCurrent())
56 filename = self["filelist"].getFilename()
57 if filename is not None:
58 if filename.upper().endswith("VIDEO_TS/"):
59 print "dvd structure found, trying to open..."
60 dvdpath = filename[0:-9]
61 lastpath = (dvdpath.rstrip("/").rsplit("/",1))[0]
62 print "lastpath video_ts/=", lastpath
65 if self["filelist"].canDescent(): # isDir
66 self["filelist"].descent()
67 pathname = self["filelist"].getCurrentDirectory() or ""
68 if fileExists(pathname+"VIDEO_TS.IFO"):
69 print "dvd structure found, trying to open..."
70 lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
71 print "lastpath video_ts.ifo=", lastpath
74 lastpath = filename[0:filename.rfind("/")]
75 print "lastpath directory=", lastpath
81 class DVDSummary(Screen):
83 <screen position="0,0" size="132,64">
84 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
85 <convert type="ServiceName">Name</convert>
87 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;12" transparent="1" />
88 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
89 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
90 <convert type="ServicePosition">Position</convert>
92 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
93 <convert type="ServicePosition">Position</convert>
97 def __init__(self, session, parent):
98 Screen.__init__(self, session, parent)
100 self["DVDPlayer"] = Label("DVD Player")
101 self["Title"] = Label("")
102 self["Time"] = Label("")
103 self["Chapter"] = Label("")
105 def updateChapter(self, chapter):
106 self["Chapter"].setText(chapter)
108 def setTitle(self, title):
109 self["Title"].setText(title)
111 class DVDOverlay(Screen):
112 def __init__(self, session, args = None):
113 desktop_size = getDesktop(0).size()
114 DVDOverlay.skin = """<screen name="DVDOverlay" position="0,0" size="%d,%d" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />""" %(desktop_size.width(), desktop_size.height())
115 Screen.__init__(self, session)
117 class ChapterZap(Screen):
119 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
120 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
121 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
130 self.close(int(self["number"].getText()))
132 def keyNumberGlobal(self, number):
133 self.Timer.start(3000, True) #reset timer
134 self.field = self.field + str(number)
135 self["number"].setText(self.field)
136 if len(self.field) >= 4:
139 def __init__(self, session, number):
140 Screen.__init__(self, session)
141 self.field = str(number)
143 self["chapter"] = Label(_("Chapter:"))
145 self["number"] = Label(self.field)
147 self["actions"] = NumberActionMap( [ "SetupActions" ],
151 "1": self.keyNumberGlobal,
152 "2": self.keyNumberGlobal,
153 "3": self.keyNumberGlobal,
154 "4": self.keyNumberGlobal,
155 "5": self.keyNumberGlobal,
156 "6": self.keyNumberGlobal,
157 "7": self.keyNumberGlobal,
158 "8": self.keyNumberGlobal,
159 "9": self.keyNumberGlobal,
160 "0": self.keyNumberGlobal
163 self.Timer = eTimer()
164 self.Timer.callback.append(self.keyOK)
165 self.Timer.start(3000, True)
167 class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport):
168 # ALLOW_SUSPEND = True
169 ENABLE_RESUME_SUPPORT = True
172 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
174 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
175 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
176 <!-- colorbuttons -->
177 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
179 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
180 <widget source="session.CurrentService" render="Label" position="230,73" size="300,22" font="Regular;20" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" noWrap="1">
181 <convert type="ServiceName">Name</convert>
183 <!-- Chapter info -->
184 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
185 <!-- Audio track info -->
186 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
187 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
188 <!-- Subtitle track info -->
189 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
190 <convert type="ServiceInfo">HasTelext</convert>
191 <convert type="ConditionalShowHide" />
193 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
194 <!-- Elapsed time -->
195 <widget source="session.CurrentService" render="Label" position="205,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" >
196 <convert type="ServicePosition">Position,ShowHours</convert>
198 <!-- Progressbar (movie position)-->
199 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
200 <convert type="ServicePosition">Gauge</convert>
202 <!-- Remaining time -->
203 <widget source="session.CurrentService" render="Label" position="576,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" >
204 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
208 def save_infobar_seek_config(self):
209 self.saved_config_speeds_forward = config.seek.speeds_forward.value
210 self.saved_config_speeds_backward = config.seek.speeds_backward.value
211 self.saved_config_enter_forward = config.seek.enter_forward.value
212 self.saved_config_enter_backward = config.seek.enter_backward.value
213 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
214 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
215 self.saved_config_seek_on_pause = config.seek.on_pause.value
216 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
218 def change_infobar_seek_config(self):
219 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
220 config.seek.speeds_backward.value = [8, 16, 32, 64]
221 config.seek.speeds_slowmotion.value = [ ]
222 config.seek.enter_forward.value = "2"
223 config.seek.enter_backward.value = "2"
224 config.seek.stepwise_minspeed.value = "Never"
225 config.seek.stepwise_repeat.value = "3"
226 config.seek.on_pause.value = "play"
228 def restore_infobar_seek_config(self):
229 config.seek.speeds_forward.value = self.saved_config_speeds_forward
230 config.seek.speeds_backward.value = self.saved_config_speeds_backward
231 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
232 config.seek.enter_forward.value = self.saved_config_enter_forward
233 config.seek.enter_backward.value = self.saved_config_enter_backward
234 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
235 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
236 config.seek.on_pause.value = self.saved_config_seek_on_pause
238 def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None):
239 Screen.__init__(self, session)
240 InfoBarBase.__init__(self)
241 InfoBarNotifications.__init__(self)
242 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
243 InfoBarShowHide.__init__(self)
244 HelpableScreen.__init__(self)
245 self.save_infobar_seek_config()
246 self.change_infobar_seek_config()
247 InfoBarSeek.__init__(self, useSeekBackHack=False)
248 InfoBarPVRState.__init__(self)
249 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
251 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
252 self.session.nav.stopService()
253 self["audioLabel"] = Label("n/a")
254 self["subtitleLabel"] = Label("")
255 self["chapterLabel"] = Label("")
256 self.last_audioTuple = None
257 self.last_subtitleTuple = None
258 self.totalChapters = 0
259 self.currentChapter = 0
261 self.currentTitle = 0
263 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
265 iPlayableService.evStopped: self.__serviceStopped,
266 iPlayableService.evUser: self.__timeUpdated,
267 iPlayableService.evUser+1: self.__statePlay,
268 iPlayableService.evUser+2: self.__statePause,
269 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
270 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
271 iPlayableService.evUser+5: self.__osdStringAvail,
272 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
273 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
274 iPlayableService.evUser+8: self.__chapterUpdated,
275 iPlayableService.evUser+9: self.__titleUpdated,
276 iPlayableService.evUser+11: self.__menuOpened,
277 iPlayableService.evUser+12: self.__menuClosed
280 self["DVDPlayerDirectionActions"] = ActionMap(["DirectionActions"],
282 #MENU KEY DOWN ACTIONS
283 "left": self.keyLeft,
284 "right": self.keyRight,
286 "down": self.keyDown,
288 #MENU KEY REPEATED ACTIONS
289 "leftRepeated": self.doNothing,
290 "rightRepeated": self.doNothing,
291 "upRepeated": self.doNothing,
292 "downRepeated": self.doNothing,
295 "leftUp": self.doNothing,
296 "rightUp": self.doNothing,
297 "upUp": self.doNothing,
298 "downUp": self.doNothing,
301 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
304 "cancel": self.keyCancel,
307 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
310 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
311 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
312 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
313 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
314 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
315 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
316 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
317 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
318 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
319 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
320 "seekBeginning": self.seekBeginning,
323 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
325 "1": self.keyNumberGlobal,
326 "2": self.keyNumberGlobal,
327 "3": self.keyNumberGlobal,
328 "4": self.keyNumberGlobal,
329 "5": self.keyNumberGlobal,
330 "6": self.keyNumberGlobal,
331 "7": self.keyNumberGlobal,
332 "8": self.keyNumberGlobal,
333 "9": self.keyNumberGlobal,
334 "0": self.keyNumberGlobal,
337 self.onClose.append(self.__onClose)
338 self.physicalDVD = False
339 self.dvd_device = None
341 self.dvd_device = dvd_device
342 self.physicalDVD = True
344 devicepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
345 if pathExists(devicepath):
346 from Components.Scanner import scanDevice
347 res = scanDevice(devicepath)
348 list = [ (r.description, r, res[r], self.session) for r in res ]
350 (desc, scanner, files, session) = list[0]
353 if file.mimetype == "video/x-dvd":
354 self.dvd_device = devicepath
355 print "physical dvd found:", self.dvd_device
356 self.physicalDVD = True
358 self.dvd_filelist = dvd_filelist
359 self.onFirstExecBegin.append(self.showFileBrowser)
362 self.old_aspect = open("/proc/stb/video/aspect", "r").read()
363 self.old_policy = open("/proc/stb/video/policy", "r").read()
364 self.old_wss = open("/proc/stb/denc/0/wss", "r").read()
366 def keyNumberGlobal(self, number):
367 print "You pressed number " + str(number)
368 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
370 def numberEntered(self, retval):
371 # print self.servicelist
373 self.zapToNumber(retval)
375 def getServiceInterface(self, iface):
376 service = self.service
378 attr = getattr(service, iface, None)
383 def __serviceStopped(self):
384 self.dvdScreen.hide()
385 subs = self.getServiceInterface("subtitle")
387 subs.disableSubtitles(self.session.current_dialog.instance)
389 def serviceStarted(self): #override InfoBarShowHide function
390 self.dvdScreen.show()
392 def doEofInternal(self, playing):
396 def __menuOpened(self):
399 self["NumberActions"].setEnabled(False)
401 def __menuClosed(self):
404 self["NumberActions"].setEnabled(True)
406 def setChapterLabel(self):
408 chapterOSD = "DVD Menu"
409 if self.currentTitle > 0:
410 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
411 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
412 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
413 self["chapterLabel"].setText(chapterOSD)
415 self.session.summary.updateChapter(chapterLCD)
422 def toggleInfo(self):
427 def __timeUpdated(self):
430 def __statePlay(self):
433 def __statePause(self):
436 def __osdFFwdInfoAvail(self):
437 self.setChapterLabel()
438 print "FFwdInfoAvail"
440 def __osdFBwdInfoAvail(self):
441 self.setChapterLabel()
442 print "FBwdInfoAvail"
444 def __osdStringAvail(self):
447 def __osdAudioInfoAvail(self):
448 info = self.getServiceInterface("info")
449 audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
450 print "AudioInfoAvail ", repr(audioTuple)
452 audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
453 self["audioLabel"].setText(audioString)
454 if audioTuple != self.last_audioTuple and not self.in_menu:
456 self.last_audioTuple = audioTuple
458 def __osdSubtitleInfoAvail(self):
459 info = self.getServiceInterface("info")
460 subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
461 print "SubtitleInfoAvail ", repr(subtitleTuple)
464 if subtitleTuple[0] is not 0:
465 subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
466 self["subtitleLabel"].setText(subtitleString)
467 if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
469 self.last_subtitleTuple = subtitleTuple
471 def __chapterUpdated(self):
472 info = self.getServiceInterface("info")
474 self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
475 self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
476 self.setChapterLabel()
477 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
479 def __titleUpdated(self):
480 info = self.getServiceInterface("info")
482 self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
483 self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
484 self.setChapterLabel()
485 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
489 def askLeavePlayer(self):
490 choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")]
491 if not self.physicalDVD:
492 choices.insert(1,(_("Return to file browser"), "browser"))
493 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
495 def sendKey(self, key):
496 keys = self.getServiceInterface("keys")
501 def nextAudioTrack(self):
502 self.sendKey(iServiceKeys.keyUser)
504 def nextSubtitleTrack(self):
505 self.sendKey(iServiceKeys.keyUser+1)
507 def enterDVDAudioMenu(self):
508 self.sendKey(iServiceKeys.keyUser+2)
510 def nextChapter(self):
511 self.sendKey(iServiceKeys.keyUser+3)
513 def prevChapter(self):
514 self.sendKey(iServiceKeys.keyUser+4)
517 self.sendKey(iServiceKeys.keyUser+5)
520 self.sendKey(iServiceKeys.keyUser+6)
522 def enterDVDMenu(self):
523 self.sendKey(iServiceKeys.keyUser+7)
525 def seekBeginning(self):
527 seekable = self.getSeek()
531 def zapToNumber(self, number):
533 seekable = self.getSeek()
535 print "seek to chapter %d" % number
536 seekable.seekChapter(number)
540 self.sendKey(iServiceKeys.keyRight)
543 self.sendKey(iServiceKeys.keyLeft)
546 self.sendKey(iServiceKeys.keyUp)
549 self.sendKey(iServiceKeys.keyDown)
552 if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
556 self.askLeavePlayer()
558 def showFileBrowser(self):
559 if self.physicalDVD and len(self.dvd_filelist) == 0:
560 if self.dvd_device == harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()):
561 self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
563 self.DVDdriveCB(True)
564 elif len(self.dvd_filelist) == 1:
565 self.FileBrowserClosed(self.dvd_filelist[0])
567 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
569 def DVDdriveCB(self, answer):
571 self.FileBrowserClosed(self.dvd_device)
573 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
574 self.physicalDVD = False
576 def FileBrowserClosed(self, val):
577 curref = self.session.nav.getCurrentlyPlayingServiceReference()
578 print "FileBrowserClosed", val
580 self.askLeavePlayer()
582 newref = eServiceReference(4369, 0, val)
583 print "play", newref.toString()
584 if curref is None or curref != newref:
585 self.session.nav.playService(newref)
586 self.service = self.session.nav.getCurrentService()
587 print "self.service", self.service
588 print "cur_dlg", self.session.current_dialog
589 subs = self.getServiceInterface("subtitle")
591 subs.enableSubtitles(self.dvdScreen.instance, None)
593 def exitCB(self, answer):
594 if answer is not None:
595 if answer[1] == "exit":
599 if answer[1] == "browser":
600 #TODO check here if a paused dvd playback is already running... then re-start it...
604 self.showFileBrowser()
609 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)):
611 open(i[0], "w").write(i[1])
613 print "restore", i[0], "failed"
614 self.restore_infobar_seek_config()
615 self.session.nav.playService(self.oldService)
617 def playLastCB(self, answer): # overwrite infobar cuesheet function
618 print "playLastCB", answer, self.resume_point
621 seekable = self.getSeek()
623 seekable.seekTo(self.resume_point)
624 pause = self.service.pause()
626 self.hideAfterResume()
628 def showAfterCuesheetOperation(self):
632 def createSummary(self):
635 #override some InfoBarSeek functions
637 self.setSeekState(self.SEEK_STATE_PLAY)
639 def calcRemainingTime(self):
642 def main(session, **kwargs):
643 session.open(DVDPlayer)
645 def menu(menuid, **kwargs):
646 if menuid == "mainmenu":
647 return [(_("DVD Player"), main, "dvd_player", 46)]
650 from Plugins.Plugin import PluginDescriptor
652 def filescan_open(list, session, **kwargs):
653 if len(list) == 1 and list[0].mimetype == "video/x-dvd":
654 splitted = list[0].path.split('/')
655 print "splitted", splitted
656 if len(splitted) > 2:
657 if splitted[1] == 'autofs':
658 session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
661 print "splitted[0]", splitted[1]
665 if x.mimetype == "video/x-dvd-iso":
666 dvd_filelist.append(x.path)
667 if x.mimetype == "video/x-dvd":
668 dvd_filelist.append(x.path.rsplit('/',1)[0])
669 session.open(DVDPlayer, dvd_filelist=dvd_filelist)
671 def filescan(**kwargs):
672 from Components.Scanner import Scanner, ScanPath
674 # Overwrite checkFile to only detect local
675 class LocalScanner(Scanner):
676 def checkFile(self, file):
677 return fileExists(file.path)
680 LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
683 ScanPath(path = "video_ts", with_subdirs = False),
684 ScanPath(path = "", with_subdirs = False),
687 description = "Play DVD",
688 openfnc = filescan_open,
691 def Plugins(**kwargs):
692 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
693 PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]