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 not answer or answer and answer[1] == "exit":
597 if answer and answer[1] == "browser":
598 #TODO check here if a paused dvd playback is already running... then re-start it...
602 self.showFileBrowser()
605 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)):
607 open(i[0], "w").write(i[1])
609 print "restore", i[0], "failed"
610 self.restore_infobar_seek_config()
611 self.session.nav.playService(self.oldService)
613 def playLastCB(self, answer): # overwrite infobar cuesheet function
614 print "playLastCB", answer, self.resume_point
617 seekable = self.getSeek()
619 seekable.seekTo(self.resume_point)
620 pause = self.service.pause()
622 self.hideAfterResume()
624 def showAfterCuesheetOperation(self):
628 def createSummary(self):
631 #override some InfoBarSeek functions
633 self.setSeekState(self.SEEK_STATE_PLAY)
635 def calcRemainingTime(self):
638 def main(session, **kwargs):
639 session.open(DVDPlayer)
641 def menu(menuid, **kwargs):
642 if menuid == "mainmenu":
643 return [(_("DVD Player"), main, "dvd_player", 46)]
646 from Plugins.Plugin import PluginDescriptor
648 def filescan_open(list, session, **kwargs):
649 if len(list) == 1 and list[0].mimetype == "video/x-dvd":
650 splitted = list[0].path.split('/')
651 print "splitted", splitted
652 if len(splitted) > 2:
653 if splitted[1] == 'autofs':
654 session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
657 print "splitted[0]", splitted[1]
661 if x.mimetype == "video/x-dvd-iso":
662 dvd_filelist.append(x.path)
663 if x.mimetype == "video/x-dvd":
664 dvd_filelist.append(x.path.rsplit('/',1)[0])
665 session.open(DVDPlayer, dvd_filelist=dvd_filelist)
667 def filescan(**kwargs):
668 from Components.Scanner import Scanner, ScanPath
670 # Overwrite checkFile to only detect local
671 class LocalScanner(Scanner):
672 def checkFile(self, file):
673 return fileExists(file.path)
676 LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
679 ScanPath(path = "video_ts", with_subdirs = False),
680 ScanPath(path = "", with_subdirs = False),
683 description = "Play DVD",
684 openfnc = filescan_open,
687 def Plugins(**kwargs):
688 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
689 PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]