1 from os import path as os_path, remove as os_remove, listdir as os_listdir, system
2 from time import strftime
3 from enigma import eTimer, iPlayableService, eServiceCenter, iServiceInformation, eServiceReference, iServiceKeys
4 from Screens.Screen import Screen
5 from Screens.MessageBox import MessageBox
6 from Screens.ChoiceBox import ChoiceBox
7 from Screens.InputBox import InputBox
8 from Screens.HelpMenu import HelpableScreen
9 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
10 from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
11 from Components.Label import Label
12 from Components.FileList import FileList
13 from Components.ServiceEventTracker import ServiceEventTracker
14 from Components.config import config
15 from Components.ProgressBar import ProgressBar
16 from ServiceReference import ServiceReference
17 from Tools.Directories import pathExists, fileExists
20 import servicedvd # load c++ part of dvd player plugin
22 class FileBrowser(Screen):
24 <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
25 <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
27 def __init__(self, session):
28 Screen.__init__(self, session)
29 currDir = "/media/dvd/"
30 if not pathExists(currDir):
33 #print system("mount "+currDir)
34 self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
35 self["filelist"] = self.filelist
37 self["FilelistActions"] = ActionMap(["OkCancelActions"],
44 filename = self["filelist"].getFilename()
45 if filename is not None and filename.upper().endswith("VIDEO_TS/"):
46 print "dvd structure found, trying to open..."
47 self.close(filename[0:-9])
48 elif self["filelist"].canDescent(): # isDir
49 self["filelist"].descent()
56 class DVDSummary(Screen):
58 <screen position="0,0" size="132,64">
59 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
60 <convert type="ServiceName">Name</convert>
62 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;12" transparent="1" />
63 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
64 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
65 <convert type="ServicePosition">Position</convert>
67 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
68 <convert type="ServicePosition">Position</convert>
72 def __init__(self, session, parent):
73 Screen.__init__(self, session, parent)
75 self["DVDPlayer"] = Label("DVD Player")
76 self["Title"] = Label("")
77 self["Time"] = Label("")
78 self["Chapter"] = Label("")
80 def updateChapter(self, chapter):
81 self["Chapter"].setText(chapter)
83 def setTitle(self, title):
84 self["Title"].setText(title)
86 class DVDOverlay(Screen):
87 skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />"""
88 def __init__(self, session, args = None):
89 Screen.__init__(self, session)
91 class ChapterZap(Screen):
93 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
94 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
95 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
104 self.close(int(self["number"].getText()))
106 def keyNumberGlobal(self, number):
107 self.Timer.start(3000, True) #reset timer
108 self.field = self.field + str(number)
109 self["number"].setText(self.field)
110 if len(self.field) >= 4:
113 def __init__(self, session, number):
114 Screen.__init__(self, session)
115 self.field = str(number)
117 self["chapter"] = Label(_("Chapter:"))
119 self["number"] = Label(self.field)
121 self["actions"] = NumberActionMap( [ "SetupActions" ],
125 "1": self.keyNumberGlobal,
126 "2": self.keyNumberGlobal,
127 "3": self.keyNumberGlobal,
128 "4": self.keyNumberGlobal,
129 "5": self.keyNumberGlobal,
130 "6": self.keyNumberGlobal,
131 "7": self.keyNumberGlobal,
132 "8": self.keyNumberGlobal,
133 "9": self.keyNumberGlobal,
134 "0": self.keyNumberGlobal
137 self.Timer = eTimer()
138 self.Timer.callback.append(self.keyOK)
139 self.Timer.start(3000, True)
141 class DVDPlayer(Screen, InfoBarNotifications, InfoBarSeek, InfoBarCueSheetSupport, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
143 ENABLE_RESUME_SUPPORT = True
146 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
148 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
149 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
150 <!-- colorbuttons -->
151 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
153 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
154 <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">
155 <convert type="ServiceName">Name</convert>
157 <!-- Chapter info -->
158 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
159 <!-- Audio track info -->
160 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
161 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
162 <!-- Subtitle track info -->
163 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
164 <convert type="ServiceInfo">HasTelext</convert>
165 <convert type="ConditionalShowHide" />
167 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
168 <!-- Elapsed time -->
169 <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" >
170 <convert type="ServicePosition">Position,ShowHours</convert>
172 <!-- Progressbar (movie position)-->
173 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
174 <convert type="ServicePosition">Gauge</convert>
176 <!-- Remaining time -->
177 <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" >
178 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
182 def save_infobar_seek_config(self):
183 self.saved_config_speeds_forward = config.seek.speeds_forward.value
184 self.saved_config_speeds_backward = config.seek.speeds_backward.value
185 self.saved_config_enter_forward = config.seek.enter_forward.value
186 self.saved_config_enter_backward = config.seek.enter_backward.value
187 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
188 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
189 self.saved_config_seek_on_pause = config.seek.on_pause.value
190 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
192 def change_infobar_seek_config(self):
193 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
194 config.seek.speeds_backward.value = [8, 16, 32, 64]
195 config.seek.speeds_slowmotion.value = [ ]
196 config.seek.enter_forward.value = "2"
197 config.seek.enter_backward.value = "2"
198 config.seek.stepwise_minspeed.value = "Never"
199 config.seek.stepwise_repeat.value = "3"
200 config.seek.on_pause.value = "play"
202 def restore_infobar_seek_config(self):
203 config.seek.speeds_forward.value = self.saved_config_speeds_forward
204 config.seek.speeds_backward.value = self.saved_config_speeds_backward
205 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
206 config.seek.enter_forward.value = self.saved_config_enter_forward
207 config.seek.enter_backward.value = self.saved_config_enter_backward
208 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
209 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
210 config.seek.on_pause.value = self.saved_config_seek_on_pause
212 def __init__(self, session, args = None):
213 Screen.__init__(self, session)
214 InfoBarNotifications.__init__(self)
215 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
216 InfoBarShowHide.__init__(self)
217 HelpableScreen.__init__(self)
218 self.save_infobar_seek_config()
219 self.change_infobar_seek_config()
220 InfoBarSeek.__init__(self)
221 InfoBarPVRState.__init__(self)
222 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
224 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
225 self.session.nav.stopService()
226 self["audioLabel"] = Label("1")
227 self["subtitleLabel"] = Label("")
228 self["chapterLabel"] = Label("")
229 self.totalChapters = 0
230 self.currentChapter = 0
232 self.currentTitle = 0
234 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
236 iPlayableService.evUser: self.__timeUpdated,
237 iPlayableService.evUser+1: self.__statePlay,
238 iPlayableService.evUser+2: self.__statePause,
239 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
240 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
241 iPlayableService.evUser+5: self.__osdStringAvail,
242 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
243 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
244 iPlayableService.evUser+8: self.__chapterUpdated,
245 iPlayableService.evUser+9: self.__titleUpdated,
246 #iPlayableService.evUser+10: self.__initializeDVDinfo,
247 iPlayableService.evUser+11: self.__menuOpened,
248 iPlayableService.evUser+12: self.__menuClosed
251 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
253 #MENU KEY DOWN ACTIONS
254 "left": (self.keyLeft, _("DVD left key")),
255 "right": (self.keyRight, _("DVD right key")),
256 "up": (self.keyUp, _("DVD up key")),
257 "down": (self.keyDown, _("DVD down key")),
259 #MENU KEY REPEATED ACTIONS
260 "leftRepeated": self.doNothing,
261 "rightRepeated": self.doNothing,
262 "upRepeated": self.doNothing,
263 "downRepeated": self.doNothing,
266 "leftUp": self.doNothing,
267 "rightUp": self.doNothing,
268 "upUp": self.doNothing,
269 "downUp": self.doNothing,
272 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
274 "ok": (self.keyOk, _("DVD ENTER key")),
275 "cancel": self.keyCancel,
278 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
281 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
282 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
283 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
284 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
285 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
286 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
287 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
288 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
289 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
290 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
291 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
294 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
296 "1": self.keyNumberGlobal,
297 "2": self.keyNumberGlobal,
298 "3": self.keyNumberGlobal,
299 "4": self.keyNumberGlobal,
300 "5": self.keyNumberGlobal,
301 "6": self.keyNumberGlobal,
302 "7": self.keyNumberGlobal,
303 "8": self.keyNumberGlobal,
304 "9": self.keyNumberGlobal,
305 "0": self.keyNumberGlobal,
308 self.onClose.append(self.__onClose)
309 self.onFirstExecBegin.append(self.showFileBrowser)
313 def keyNumberGlobal(self, number):
314 print "You pressed number " + str(number)
315 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
317 def numberEntered(self, retval):
318 # print self.servicelist
320 self.zapToNumber(retval)
322 def serviceStarted(self): #override InfoBarShowHide function
325 def doEofInternal(self, playing):
329 def __menuOpened(self):
333 def __menuClosed(self):
337 def setChapterLabel(self):
339 chapterOSD = "DVD Menu"
340 if self.currentTitle > 0:
341 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
342 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
343 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
344 self["chapterLabel"].setText(chapterOSD)
346 self.session.summary.updateChapter(chapterLCD)
353 def toggleInfo(self):
358 def __timeUpdated(self):
361 def __statePlay(self):
364 def __statePause(self):
367 def __osdFFwdInfoAvail(self):
368 self.setChapterLabel()
369 print "FFwdInfoAvail"
371 def __osdFBwdInfoAvail(self):
372 self.setChapterLabel()
373 print "FBwdInfoAvail"
375 def __osdStringAvail(self):
378 def __osdAudioInfoAvail(self):
379 audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
380 print "AudioInfoAvail "+audioString
381 self["audioLabel"].setText(audioString)
385 def __osdSubtitleInfoAvail(self):
386 subtitleString = self.service.info().getInfoString(iPlayableService.evUser+7)
387 print "SubtitleInfoAvail "+subtitleString
388 self["subtitleLabel"].setText(subtitleString)
392 def __chapterUpdated(self):
393 self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
394 self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
395 self.setChapterLabel()
396 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
398 def __titleUpdated(self):
399 self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
400 self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
401 self.setChapterLabel()
402 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
406 #def __initializeDVDinfo(self):
407 #self.__osdAudioInfoAvail()
408 #self.__osdSubtitleInfoAvail()
410 def askLeavePlayer(self):
411 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
413 def nextAudioTrack(self):
415 self.service.keys().keyPressed(iServiceKeys.keyUser)
417 def nextSubtitleTrack(self):
419 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
421 def enterDVDAudioMenu(self):
423 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
425 def nextChapter(self):
427 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
429 def prevChapter(self):
431 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
435 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
439 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
441 def enterDVDMenu(self):
443 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
445 def seekBeginning(self):
447 seekable = self.getSeek()
448 if seekable is not None:
451 def zapToNumber(self, number):
453 seekable = self.getSeek()
454 if seekable is not None:
455 print "seek to chapter %d" % number
456 seekable.seekChapter(number)
461 self.service.keys().keyPressed(iServiceKeys.keyRight)
465 self.service.keys().keyPressed(iServiceKeys.keyLeft)
469 self.service.keys().keyPressed(iServiceKeys.keyUp)
473 self.service.keys().keyPressed(iServiceKeys.keyDown)
477 self.service.keys().keyPressed(iServiceKeys.keyOk)
480 self.askLeavePlayer()
482 def showFileBrowser(self):
483 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
485 def FileBrowserClosed(self, val):
486 curref = self.session.nav.getCurrentlyPlayingServiceReference()
487 print "FileBrowserClosed", val
489 self.askLeavePlayer()
491 newref = eServiceReference(4369, 0, val)
492 print "play", newref.toString()
493 if curref is None or curref != newref:
494 self.session.nav.playService(newref)
495 self.service = self.session.nav.getCurrentService()
496 print "self.service", self.service
497 print "cur_dlg", self.session.current_dialog
498 self.dvdScreen.show()
499 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
501 def exitCB(self, answer):
502 if answer is not None:
503 if answer[1] == "exit":
505 self.dvdScreen.hide()
506 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
509 if answer[1] == "browser":
510 #TODO check here if a paused dvd playback is already running... then re-start it...
512 self.showFileBrowser()
517 self.restore_infobar_seek_config()
518 self.session.nav.playService(self.oldService)
520 def showAfterCuesheetOperation(self):
524 def createSummary(self):
525 print "DVDCreateSummary"
528 def main(session, **kwargs):
529 session.open(DVDPlayer)
531 def menu(menuid, **kwargs):
532 if menuid == "mainmenu":
533 return [(_("DVD Player"), main, "dvd_player", 46)]
536 from Plugins.Plugin import PluginDescriptor
537 def Plugins(**kwargs):
538 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]