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
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 skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />"""
113 def __init__(self, session, args = None):
114 Screen.__init__(self, session)
116 class ChapterZap(Screen):
118 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
119 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
120 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
129 self.close(int(self["number"].getText()))
131 def keyNumberGlobal(self, number):
132 self.Timer.start(3000, True) #reset timer
133 self.field = self.field + str(number)
134 self["number"].setText(self.field)
135 if len(self.field) >= 4:
138 def __init__(self, session, number):
139 Screen.__init__(self, session)
140 self.field = str(number)
142 self["chapter"] = Label(_("Chapter:"))
144 self["number"] = Label(self.field)
146 self["actions"] = NumberActionMap( [ "SetupActions" ],
150 "1": self.keyNumberGlobal,
151 "2": self.keyNumberGlobal,
152 "3": self.keyNumberGlobal,
153 "4": self.keyNumberGlobal,
154 "5": self.keyNumberGlobal,
155 "6": self.keyNumberGlobal,
156 "7": self.keyNumberGlobal,
157 "8": self.keyNumberGlobal,
158 "9": self.keyNumberGlobal,
159 "0": self.keyNumberGlobal
162 self.Timer = eTimer()
163 self.Timer.callback.append(self.keyOK)
164 self.Timer.start(3000, True)
166 class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport):
167 # ALLOW_SUSPEND = True
168 ENABLE_RESUME_SUPPORT = True
171 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
173 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
174 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
175 <!-- colorbuttons -->
176 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
178 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
179 <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">
180 <convert type="ServiceName">Name</convert>
182 <!-- Chapter info -->
183 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
184 <!-- Audio track info -->
185 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
186 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
187 <!-- Subtitle track info -->
188 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
189 <convert type="ServiceInfo">HasTelext</convert>
190 <convert type="ConditionalShowHide" />
192 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
193 <!-- Elapsed time -->
194 <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" >
195 <convert type="ServicePosition">Position,ShowHours</convert>
197 <!-- Progressbar (movie position)-->
198 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
199 <convert type="ServicePosition">Gauge</convert>
201 <!-- Remaining time -->
202 <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" >
203 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
207 def save_infobar_seek_config(self):
208 self.saved_config_speeds_forward = config.seek.speeds_forward.value
209 self.saved_config_speeds_backward = config.seek.speeds_backward.value
210 self.saved_config_enter_forward = config.seek.enter_forward.value
211 self.saved_config_enter_backward = config.seek.enter_backward.value
212 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
213 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
214 self.saved_config_seek_on_pause = config.seek.on_pause.value
215 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
217 def change_infobar_seek_config(self):
218 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
219 config.seek.speeds_backward.value = [8, 16, 32, 64]
220 config.seek.speeds_slowmotion.value = [ ]
221 config.seek.enter_forward.value = "2"
222 config.seek.enter_backward.value = "2"
223 config.seek.stepwise_minspeed.value = "Never"
224 config.seek.stepwise_repeat.value = "3"
225 config.seek.on_pause.value = "play"
227 def restore_infobar_seek_config(self):
228 config.seek.speeds_forward.value = self.saved_config_speeds_forward
229 config.seek.speeds_backward.value = self.saved_config_speeds_backward
230 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
231 config.seek.enter_forward.value = self.saved_config_enter_forward
232 config.seek.enter_backward.value = self.saved_config_enter_backward
233 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
234 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
235 config.seek.on_pause.value = self.saved_config_seek_on_pause
237 def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None):
238 Screen.__init__(self, session)
239 InfoBarBase.__init__(self)
240 InfoBarNotifications.__init__(self)
241 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
242 InfoBarShowHide.__init__(self)
243 HelpableScreen.__init__(self)
244 self.save_infobar_seek_config()
245 self.change_infobar_seek_config()
246 InfoBarSeek.__init__(self, useSeekBackHack=False)
247 InfoBarPVRState.__init__(self)
248 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
250 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
251 self.session.nav.stopService()
252 self["audioLabel"] = Label("n/a")
253 self["subtitleLabel"] = Label("")
254 self["chapterLabel"] = Label("")
255 self.last_audioTuple = None
256 self.last_subtitleTuple = None
257 self.totalChapters = 0
258 self.currentChapter = 0
260 self.currentTitle = 0
262 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
264 iPlayableService.evStopped: self.__serviceStopped,
265 iPlayableService.evUser: self.__timeUpdated,
266 iPlayableService.evUser+1: self.__statePlay,
267 iPlayableService.evUser+2: self.__statePause,
268 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
269 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
270 iPlayableService.evUser+5: self.__osdStringAvail,
271 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
272 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
273 iPlayableService.evUser+8: self.__chapterUpdated,
274 iPlayableService.evUser+9: self.__titleUpdated,
275 iPlayableService.evUser+11: self.__menuOpened,
276 iPlayableService.evUser+12: self.__menuClosed
279 self["DVDPlayerDirectionActions"] = ActionMap(["DirectionActions"],
281 #MENU KEY DOWN ACTIONS
282 "left": self.keyLeft,
283 "right": self.keyRight,
285 "down": self.keyDown,
287 #MENU KEY REPEATED ACTIONS
288 "leftRepeated": self.doNothing,
289 "rightRepeated": self.doNothing,
290 "upRepeated": self.doNothing,
291 "downRepeated": self.doNothing,
294 "leftUp": self.doNothing,
295 "rightUp": self.doNothing,
296 "upUp": self.doNothing,
297 "downUp": self.doNothing,
300 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
303 "cancel": self.keyCancel,
306 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
309 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
310 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
311 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
312 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
313 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
314 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
315 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
316 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
317 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
318 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
319 "seekBeginning": self.seekBeginning,
322 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
324 "1": self.keyNumberGlobal,
325 "2": self.keyNumberGlobal,
326 "3": self.keyNumberGlobal,
327 "4": self.keyNumberGlobal,
328 "5": self.keyNumberGlobal,
329 "6": self.keyNumberGlobal,
330 "7": self.keyNumberGlobal,
331 "8": self.keyNumberGlobal,
332 "9": self.keyNumberGlobal,
333 "0": self.keyNumberGlobal,
336 self.onClose.append(self.__onClose)
337 self.physicalDVD = False
338 self.dvd_device = None
340 self.dvd_device = dvd_device
341 self.physicalDVD = True
343 devicepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
344 if pathExists(devicepath):
345 from Components.Scanner import scanDevice
346 res = scanDevice(devicepath)
347 list = [ (r.description, r, res[r], self.session) for r in res ]
349 (desc, scanner, files, session) = list[0]
352 if file.mimetype == "video/x-dvd":
353 self.dvd_device = devicepath
354 print "physical dvd found:", self.dvd_device
355 self.physicalDVD = True
357 self.dvd_filelist = dvd_filelist
358 self.onFirstExecBegin.append(self.showFileBrowser)
361 self.old_aspect = open("/proc/stb/video/aspect", "r").read()
362 self.old_policy = open("/proc/stb/video/policy", "r").read()
363 self.old_wss = open("/proc/stb/denc/0/wss", "r").read()
365 def keyNumberGlobal(self, number):
366 print "You pressed number " + str(number)
367 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
369 def numberEntered(self, retval):
370 # print self.servicelist
372 self.zapToNumber(retval)
374 def getServiceInterface(self, iface):
375 service = self.service
377 attr = getattr(service, iface, None)
382 def __serviceStopped(self):
383 self.dvdScreen.hide()
384 subs = self.getServiceInterface("subtitle")
386 subs.disableSubtitles(self.session.current_dialog.instance)
388 def serviceStarted(self): #override InfoBarShowHide function
389 self.dvdScreen.show()
390 subs = self.getServiceInterface("subtitle")
392 subs.enableSubtitles(self.dvdScreen.instance, None)
394 def doEofInternal(self, playing):
398 def __menuOpened(self):
401 self["NumberActions"].setEnabled(False)
403 def __menuClosed(self):
406 self["NumberActions"].setEnabled(True)
408 def setChapterLabel(self):
410 chapterOSD = "DVD Menu"
411 if self.currentTitle > 0:
412 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
413 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
414 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
415 self["chapterLabel"].setText(chapterOSD)
417 self.session.summary.updateChapter(chapterLCD)
424 def toggleInfo(self):
429 def __timeUpdated(self):
432 def __statePlay(self):
435 def __statePause(self):
438 def __osdFFwdInfoAvail(self):
439 self.setChapterLabel()
440 print "FFwdInfoAvail"
442 def __osdFBwdInfoAvail(self):
443 self.setChapterLabel()
444 print "FBwdInfoAvail"
446 def __osdStringAvail(self):
449 def __osdAudioInfoAvail(self):
450 info = self.getServiceInterface("info")
451 audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
452 print "AudioInfoAvail ", repr(audioTuple)
454 audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
455 self["audioLabel"].setText(audioString)
456 if audioTuple != self.last_audioTuple and not self.in_menu:
458 self.last_audioTuple = audioTuple
460 def __osdSubtitleInfoAvail(self):
461 info = self.getServiceInterface("info")
462 subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
463 print "SubtitleInfoAvail ", repr(subtitleTuple)
466 if subtitleTuple[0] is not 0:
467 subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
468 self["subtitleLabel"].setText(subtitleString)
469 if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
471 self.last_subtitleTuple = subtitleTuple
473 def __chapterUpdated(self):
474 info = self.getServiceInterface("info")
476 self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
477 self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
478 self.setChapterLabel()
479 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
481 def __titleUpdated(self):
482 info = self.getServiceInterface("info")
484 self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
485 self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
486 self.setChapterLabel()
487 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
491 def askLeavePlayer(self):
492 choices = [(_("Continue playing"), "play"), (_("Exit"), "exit")]
493 if not self.physicalDVD:
494 choices.insert(1,(_("Return to file browser"), "browser"))
495 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
497 def sendKey(self, key):
498 keys = self.getServiceInterface("keys")
503 def nextAudioTrack(self):
504 self.sendKey(iServiceKeys.keyUser)
506 def nextSubtitleTrack(self):
507 self.sendKey(iServiceKeys.keyUser+1)
509 def enterDVDAudioMenu(self):
510 self.sendKey(iServiceKeys.keyUser+2)
512 def nextChapter(self):
513 self.sendKey(iServiceKeys.keyUser+3)
515 def prevChapter(self):
516 self.sendKey(iServiceKeys.keyUser+4)
519 self.sendKey(iServiceKeys.keyUser+5)
522 self.sendKey(iServiceKeys.keyUser+6)
524 def enterDVDMenu(self):
525 self.sendKey(iServiceKeys.keyUser+7)
527 def seekBeginning(self):
529 seekable = self.getSeek()
533 def zapToNumber(self, number):
535 seekable = self.getSeek()
537 print "seek to chapter %d" % number
538 seekable.seekChapter(number)
542 self.sendKey(iServiceKeys.keyRight)
545 self.sendKey(iServiceKeys.keyLeft)
548 self.sendKey(iServiceKeys.keyUp)
551 self.sendKey(iServiceKeys.keyDown)
554 if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
558 self.askLeavePlayer()
560 def showFileBrowser(self):
561 if self.physicalDVD and len(self.dvd_filelist) == 0:
562 if self.dvd_device == harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()):
563 self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
565 self.DVDdriveCB(True)
566 elif len(self.dvd_filelist) == 1:
567 self.FileBrowserClosed(self.dvd_filelist[0])
569 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
571 def DVDdriveCB(self, answer):
573 self.FileBrowserClosed(self.dvd_device)
575 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
576 self.physicalDVD = False
578 def FileBrowserClosed(self, val):
579 curref = self.session.nav.getCurrentlyPlayingServiceReference()
580 print "FileBrowserClosed", val
582 self.askLeavePlayer()
584 newref = eServiceReference(4369, 0, val)
585 print "play", newref.toString()
586 if curref is None or curref != newref:
587 self.session.nav.playService(newref)
588 self.service = self.session.nav.getCurrentService()
589 print "self.service", self.service
590 print "cur_dlg", self.session.current_dialog
592 def exitCB(self, answer):
593 if answer is not None:
594 if answer[1] == "exit":
598 if answer[1] == "browser":
599 #TODO check here if a paused dvd playback is already running... then re-start it...
603 self.showFileBrowser()
608 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)):
610 open(i[0], "w").write(i[1])
612 print "restore", i[0], "failed"
613 self.restore_infobar_seek_config()
614 self.session.nav.playService(self.oldService)
616 def playLastCB(self, answer): # overwrite infobar cuesheet function
617 print "playLastCB", answer, self.resume_point
620 seekable = self.getSeek()
622 seekable.seekTo(self.resume_point)
623 pause = self.service.pause()
625 self.hideAfterResume()
627 def showAfterCuesheetOperation(self):
631 def createSummary(self):
634 #override some InfoBarSeek functions
636 self.setSeekState(self.SEEK_STATE_PLAY)
638 def calcRemainingTime(self):
641 def main(session, **kwargs):
642 session.open(DVDPlayer)
644 def menu(menuid, **kwargs):
645 if menuid == "mainmenu":
646 return [(_("DVD Player"), main, "dvd_player", 46)]
649 from Plugins.Plugin import PluginDescriptor
651 def filescan_open(list, session, **kwargs):
652 if len(list) == 1 and list[0].mimetype == "video/x-dvd":
653 splitted = list[0].path.split('/')
654 print "splitted", splitted
655 if len(splitted) > 2:
656 if splitted[1] == 'autofs':
657 session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
660 print "splitted[0]", splitted[1]
664 if x.mimetype == "video/x-dvd-iso":
665 dvd_filelist.append(x.path)
666 if x.mimetype == "video/x-dvd":
667 dvd_filelist.append(x.path.rsplit('/',1)[0])
668 session.open(DVDPlayer, dvd_filelist=dvd_filelist)
670 def filescan(**kwargs):
671 from Components.Scanner import Scanner, ScanPath
673 # Overwrite checkFile to only detect local
674 class LocalScanner(Scanner):
675 def checkFile(self, file):
676 return fileExists(file.path)
679 LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
682 ScanPath(path = "video_ts", with_subdirs = False),
683 ScanPath(path = "", with_subdirs = False),
686 description = "Play DVD",
687 openfnc = filescan_open,
690 def Plugins(**kwargs):
691 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
692 PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]