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, InfoBarBase
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
24 class FileBrowser(Screen):
26 <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
27 <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
29 def __init__(self, session):
30 Screen.__init__(self, session)
32 if lastpath is not None:
33 currDir = lastpath + "/"
35 currDir = "/media/dvd/"
36 if not pathExists(currDir):
39 #print system("mount "+currDir)
40 self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
41 self["filelist"] = self.filelist
43 self["FilelistActions"] = ActionMap(["OkCancelActions"],
51 filename = self["filelist"].getFilename()
52 if filename is not None:
53 lastpath = filename[0:filename.rfind("/")]
54 if filename.upper().endswith("VIDEO_TS/"):
55 print "dvd structure found, trying to open..."
56 self.close(filename[0:-9])
57 if self["filelist"].canDescent(): # isDir
58 self["filelist"].descent()
65 class DVDSummary(Screen):
67 <screen position="0,0" size="132,64">
68 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
69 <convert type="ServiceName">Name</convert>
71 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;12" transparent="1" />
72 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
73 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
74 <convert type="ServicePosition">Position</convert>
76 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
77 <convert type="ServicePosition">Position</convert>
81 def __init__(self, session, parent):
82 Screen.__init__(self, session, parent)
84 self["DVDPlayer"] = Label("DVD Player")
85 self["Title"] = Label("")
86 self["Time"] = Label("")
87 self["Chapter"] = Label("")
89 def updateChapter(self, chapter):
90 self["Chapter"].setText(chapter)
92 def setTitle(self, title):
93 self["Title"].setText(title)
95 class DVDOverlay(Screen):
96 skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />"""
97 def __init__(self, session, args = None):
98 Screen.__init__(self, session)
100 class ChapterZap(Screen):
102 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
103 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
104 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
113 self.close(int(self["number"].getText()))
115 def keyNumberGlobal(self, number):
116 self.Timer.start(3000, True) #reset timer
117 self.field = self.field + str(number)
118 self["number"].setText(self.field)
119 if len(self.field) >= 4:
122 def __init__(self, session, number):
123 Screen.__init__(self, session)
124 self.field = str(number)
126 self["chapter"] = Label(_("Chapter:"))
128 self["number"] = Label(self.field)
130 self["actions"] = NumberActionMap( [ "SetupActions" ],
134 "1": self.keyNumberGlobal,
135 "2": self.keyNumberGlobal,
136 "3": self.keyNumberGlobal,
137 "4": self.keyNumberGlobal,
138 "5": self.keyNumberGlobal,
139 "6": self.keyNumberGlobal,
140 "7": self.keyNumberGlobal,
141 "8": self.keyNumberGlobal,
142 "9": self.keyNumberGlobal,
143 "0": self.keyNumberGlobal
146 self.Timer = eTimer()
147 self.Timer.callback.append(self.keyOK)
148 self.Timer.start(3000, True)
150 class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarCueSheetSupport, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
152 ENABLE_RESUME_SUPPORT = True
155 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
157 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
158 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
159 <!-- colorbuttons -->
160 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
162 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
163 <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">
164 <convert type="ServiceName">Name</convert>
166 <!-- Chapter info -->
167 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
168 <!-- Audio track info -->
169 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
170 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
171 <!-- Subtitle track info -->
172 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
173 <convert type="ServiceInfo">HasTelext</convert>
174 <convert type="ConditionalShowHide" />
176 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
177 <!-- Elapsed time -->
178 <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" >
179 <convert type="ServicePosition">Position,ShowHours</convert>
181 <!-- Progressbar (movie position)-->
182 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
183 <convert type="ServicePosition">Gauge</convert>
185 <!-- Remaining time -->
186 <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" >
187 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
191 def save_infobar_seek_config(self):
192 self.saved_config_speeds_forward = config.seek.speeds_forward.value
193 self.saved_config_speeds_backward = config.seek.speeds_backward.value
194 self.saved_config_enter_forward = config.seek.enter_forward.value
195 self.saved_config_enter_backward = config.seek.enter_backward.value
196 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
197 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
198 self.saved_config_seek_on_pause = config.seek.on_pause.value
199 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
201 def change_infobar_seek_config(self):
202 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
203 config.seek.speeds_backward.value = [8, 16, 32, 64]
204 config.seek.speeds_slowmotion.value = [ ]
205 config.seek.enter_forward.value = "2"
206 config.seek.enter_backward.value = "2"
207 config.seek.stepwise_minspeed.value = "Never"
208 config.seek.stepwise_repeat.value = "3"
209 config.seek.on_pause.value = "play"
211 def restore_infobar_seek_config(self):
212 config.seek.speeds_forward.value = self.saved_config_speeds_forward
213 config.seek.speeds_backward.value = self.saved_config_speeds_backward
214 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
215 config.seek.enter_forward.value = self.saved_config_enter_forward
216 config.seek.enter_backward.value = self.saved_config_enter_backward
217 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
218 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
219 config.seek.on_pause.value = self.saved_config_seek_on_pause
221 def __init__(self, session, args = None):
222 Screen.__init__(self, session)
223 InfoBarBase.__init__(self)
224 InfoBarNotifications.__init__(self)
225 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
226 InfoBarShowHide.__init__(self)
227 HelpableScreen.__init__(self)
228 self.save_infobar_seek_config()
229 self.change_infobar_seek_config()
230 InfoBarSeek.__init__(self)
231 InfoBarPVRState.__init__(self)
232 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
234 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
235 self.session.nav.stopService()
236 self["audioLabel"] = Label("1")
237 self["subtitleLabel"] = Label("")
238 self["chapterLabel"] = Label("")
239 self.totalChapters = 0
240 self.currentChapter = 0
242 self.currentTitle = 0
244 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
246 iPlayableService.evUser: self.__timeUpdated,
247 iPlayableService.evUser+1: self.__statePlay,
248 iPlayableService.evUser+2: self.__statePause,
249 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
250 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
251 iPlayableService.evUser+5: self.__osdStringAvail,
252 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
253 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
254 iPlayableService.evUser+8: self.__chapterUpdated,
255 iPlayableService.evUser+9: self.__titleUpdated,
256 #iPlayableService.evUser+10: self.__initializeDVDinfo,
257 iPlayableService.evUser+11: self.__menuOpened,
258 iPlayableService.evUser+12: self.__menuClosed
261 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
263 #MENU KEY DOWN ACTIONS
264 "left": (self.keyLeft, _("DVD left key")),
265 "right": (self.keyRight, _("DVD right key")),
266 "up": (self.keyUp, _("DVD up key")),
267 "down": (self.keyDown, _("DVD down key")),
269 #MENU KEY REPEATED ACTIONS
270 "leftRepeated": self.doNothing,
271 "rightRepeated": self.doNothing,
272 "upRepeated": self.doNothing,
273 "downRepeated": self.doNothing,
276 "leftUp": self.doNothing,
277 "rightUp": self.doNothing,
278 "upUp": self.doNothing,
279 "downUp": self.doNothing,
282 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
284 "ok": (self.keyOk, _("DVD ENTER key")),
285 "cancel": self.keyCancel,
288 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
291 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
292 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
293 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
294 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
295 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
296 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
297 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
298 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
299 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
300 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
301 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
304 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
306 "1": self.keyNumberGlobal,
307 "2": self.keyNumberGlobal,
308 "3": self.keyNumberGlobal,
309 "4": self.keyNumberGlobal,
310 "5": self.keyNumberGlobal,
311 "6": self.keyNumberGlobal,
312 "7": self.keyNumberGlobal,
313 "8": self.keyNumberGlobal,
314 "9": self.keyNumberGlobal,
315 "0": self.keyNumberGlobal,
318 self.onClose.append(self.__onClose)
319 self.onFirstExecBegin.append(self.showFileBrowser)
323 def keyNumberGlobal(self, number):
324 print "You pressed number " + str(number)
325 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
327 def numberEntered(self, retval):
328 # print self.servicelist
330 self.zapToNumber(retval)
332 def serviceStarted(self): #override InfoBarShowHide function
335 def doEofInternal(self, playing):
339 def __menuOpened(self):
342 self["NumberActions"].setEnabled(False)
344 def __menuClosed(self):
347 self["NumberActions"].setEnabled(True)
349 def setChapterLabel(self):
351 chapterOSD = "DVD Menu"
352 if self.currentTitle > 0:
353 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
354 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
355 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
356 self["chapterLabel"].setText(chapterOSD)
358 self.session.summary.updateChapter(chapterLCD)
365 def toggleInfo(self):
370 def __timeUpdated(self):
373 def __statePlay(self):
376 def __statePause(self):
379 def __osdFFwdInfoAvail(self):
380 self.setChapterLabel()
381 print "FFwdInfoAvail"
383 def __osdFBwdInfoAvail(self):
384 self.setChapterLabel()
385 print "FBwdInfoAvail"
387 def __osdStringAvail(self):
390 def __osdAudioInfoAvail(self):
391 audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
392 print "AudioInfoAvail "+audioString
393 self["audioLabel"].setText(audioString)
397 def __osdSubtitleInfoAvail(self):
398 subtitleString = self.service.info().getInfoString(iPlayableService.evUser+7)
399 print "SubtitleInfoAvail "+subtitleString
400 self["subtitleLabel"].setText(subtitleString)
404 def __chapterUpdated(self):
405 self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
406 self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
407 self.setChapterLabel()
408 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
410 def __titleUpdated(self):
411 self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
412 self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
413 self.setChapterLabel()
414 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
418 #def __initializeDVDinfo(self):
419 #self.__osdAudioInfoAvail()
420 #self.__osdSubtitleInfoAvail()
422 def askLeavePlayer(self):
423 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
425 def nextAudioTrack(self):
427 self.service.keys().keyPressed(iServiceKeys.keyUser)
429 def nextSubtitleTrack(self):
431 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
433 def enterDVDAudioMenu(self):
435 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
437 def nextChapter(self):
439 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
441 def prevChapter(self):
443 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
447 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
451 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
453 def enterDVDMenu(self):
455 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
457 def seekBeginning(self):
459 seekable = self.getSeek()
460 if seekable is not None:
463 def zapToNumber(self, number):
465 seekable = self.getSeek()
466 if seekable is not None:
467 print "seek to chapter %d" % number
468 seekable.seekChapter(number)
473 self.service.keys().keyPressed(iServiceKeys.keyRight)
477 self.service.keys().keyPressed(iServiceKeys.keyLeft)
481 self.service.keys().keyPressed(iServiceKeys.keyUp)
485 self.service.keys().keyPressed(iServiceKeys.keyDown)
491 self.service.keys().keyPressed(iServiceKeys.keyOk)
494 self.askLeavePlayer()
496 def showFileBrowser(self):
497 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
499 def FileBrowserClosed(self, val):
500 curref = self.session.nav.getCurrentlyPlayingServiceReference()
501 print "FileBrowserClosed", val
503 self.askLeavePlayer()
505 newref = eServiceReference(4369, 0, val)
506 print "play", newref.toString()
507 if curref is None or curref != newref:
508 self.session.nav.playService(newref)
509 self.service = self.session.nav.getCurrentService()
510 print "self.service", self.service
511 print "cur_dlg", self.session.current_dialog
512 self.dvdScreen.show()
513 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
515 def exitCB(self, answer):
516 if answer is not None:
517 if answer[1] == "exit":
519 self.dvdScreen.hide()
520 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
523 if answer[1] == "browser":
524 #TODO check here if a paused dvd playback is already running... then re-start it...
526 self.showFileBrowser()
531 self.restore_infobar_seek_config()
532 self.session.nav.playService(self.oldService)
534 def playLastCB(self, answer): # overwrite infobar cuesheet function
535 print "playLastCB", answer, self.resume_point
537 # self.doSeek(self.resume_point)
538 self.hideAfterResume()
540 def showAfterCuesheetOperation(self):
544 def createSummary(self):
545 print "DVDCreateSummary"
548 #override some InfoBarSeek functions
550 self.setSeekState(self.SEEK_STATE_PLAY)
552 def calcRemainingTime(self):
555 def main(session, **kwargs):
556 session.open(DVDPlayer)
558 def menu(menuid, **kwargs):
559 if menuid == "mainmenu":
560 return [(_("DVD Player"), main, "dvd_player", 46)]
563 from Plugins.Plugin import PluginDescriptor
564 def Plugins(**kwargs):
565 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]