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()
391 def doEofInternal(self, playing):
395 def __menuOpened(self):
398 self["NumberActions"].setEnabled(False)
400 def __menuClosed(self):
403 self["NumberActions"].setEnabled(True)
405 def setChapterLabel(self):
407 chapterOSD = "DVD Menu"
408 if self.currentTitle > 0:
409 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
410 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
411 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
412 self["chapterLabel"].setText(chapterOSD)
414 self.session.summary.updateChapter(chapterLCD)
421 def toggleInfo(self):
426 def __timeUpdated(self):
429 def __statePlay(self):
432 def __statePause(self):
435 def __osdFFwdInfoAvail(self):
436 self.setChapterLabel()
437 print "FFwdInfoAvail"
439 def __osdFBwdInfoAvail(self):
440 self.setChapterLabel()
441 print "FBwdInfoAvail"
443 def __osdStringAvail(self):
446 def __osdAudioInfoAvail(self):
447 info = self.getServiceInterface("info")
448 audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
449 print "AudioInfoAvail ", repr(audioTuple)
451 audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
452 self["audioLabel"].setText(audioString)
453 if audioTuple != self.last_audioTuple and not self.in_menu:
455 self.last_audioTuple = audioTuple
457 def __osdSubtitleInfoAvail(self):
458 info = self.getServiceInterface("info")
459 subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
460 print "SubtitleInfoAvail ", repr(subtitleTuple)
463 if subtitleTuple[0] is not 0:
464 subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
465 self["subtitleLabel"].setText(subtitleString)
466 if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
468 self.last_subtitleTuple = subtitleTuple
470 def __chapterUpdated(self):
471 info = self.getServiceInterface("info")
473 self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
474 self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
475 self.setChapterLabel()
476 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
478 def __titleUpdated(self):
479 info = self.getServiceInterface("info")
481 self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
482 self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
483 self.setChapterLabel()
484 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
488 def askLeavePlayer(self):
489 choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")]
490 if not self.physicalDVD:
491 choices.insert(1,(_("Return to file browser"), "browser"))
492 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
494 def sendKey(self, key):
495 keys = self.getServiceInterface("keys")
500 def nextAudioTrack(self):
501 self.sendKey(iServiceKeys.keyUser)
503 def nextSubtitleTrack(self):
504 self.sendKey(iServiceKeys.keyUser+1)
506 def enterDVDAudioMenu(self):
507 self.sendKey(iServiceKeys.keyUser+2)
509 def nextChapter(self):
510 self.sendKey(iServiceKeys.keyUser+3)
512 def prevChapter(self):
513 self.sendKey(iServiceKeys.keyUser+4)
516 self.sendKey(iServiceKeys.keyUser+5)
519 self.sendKey(iServiceKeys.keyUser+6)
521 def enterDVDMenu(self):
522 self.sendKey(iServiceKeys.keyUser+7)
524 def seekBeginning(self):
526 seekable = self.getSeek()
530 def zapToNumber(self, number):
532 seekable = self.getSeek()
534 print "seek to chapter %d" % number
535 seekable.seekChapter(number)
539 self.sendKey(iServiceKeys.keyRight)
542 self.sendKey(iServiceKeys.keyLeft)
545 self.sendKey(iServiceKeys.keyUp)
548 self.sendKey(iServiceKeys.keyDown)
551 if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
555 self.askLeavePlayer()
557 def showFileBrowser(self):
558 if self.physicalDVD and len(self.dvd_filelist) == 0:
559 if self.dvd_device == harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()):
560 self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
562 self.DVDdriveCB(True)
563 elif len(self.dvd_filelist) == 1:
564 self.FileBrowserClosed(self.dvd_filelist[0])
566 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
568 def DVDdriveCB(self, answer):
570 self.FileBrowserClosed(self.dvd_device)
572 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
573 self.physicalDVD = False
575 def FileBrowserClosed(self, val):
576 curref = self.session.nav.getCurrentlyPlayingServiceReference()
577 print "FileBrowserClosed", val
579 self.askLeavePlayer()
581 newref = eServiceReference(4369, 0, val)
582 print "play", newref.toString()
583 if curref is None or curref != newref:
584 self.session.nav.playService(newref)
585 self.service = self.session.nav.getCurrentService()
586 print "self.service", self.service
587 print "cur_dlg", self.session.current_dialog
588 subs = self.getServiceInterface("subtitle")
590 subs.enableSubtitles(self.dvdScreen.instance, None)
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)]