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):
343 def __menuClosed(self):
347 def setChapterLabel(self):
349 chapterOSD = "DVD Menu"
350 if self.currentTitle > 0:
351 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
352 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
353 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
354 self["chapterLabel"].setText(chapterOSD)
356 self.session.summary.updateChapter(chapterLCD)
363 def toggleInfo(self):
368 def __timeUpdated(self):
371 def __statePlay(self):
374 def __statePause(self):
377 def __osdFFwdInfoAvail(self):
378 self.setChapterLabel()
379 print "FFwdInfoAvail"
381 def __osdFBwdInfoAvail(self):
382 self.setChapterLabel()
383 print "FBwdInfoAvail"
385 def __osdStringAvail(self):
388 def __osdAudioInfoAvail(self):
389 audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
390 print "AudioInfoAvail "+audioString
391 self["audioLabel"].setText(audioString)
395 def __osdSubtitleInfoAvail(self):
396 subtitleString = self.service.info().getInfoString(iPlayableService.evUser+7)
397 print "SubtitleInfoAvail "+subtitleString
398 self["subtitleLabel"].setText(subtitleString)
402 def __chapterUpdated(self):
403 self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
404 self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
405 self.setChapterLabel()
406 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
408 def __titleUpdated(self):
409 self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
410 self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
411 self.setChapterLabel()
412 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
416 #def __initializeDVDinfo(self):
417 #self.__osdAudioInfoAvail()
418 #self.__osdSubtitleInfoAvail()
420 def askLeavePlayer(self):
421 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
423 def nextAudioTrack(self):
425 self.service.keys().keyPressed(iServiceKeys.keyUser)
427 def nextSubtitleTrack(self):
429 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
431 def enterDVDAudioMenu(self):
433 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
435 def nextChapter(self):
437 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
439 def prevChapter(self):
441 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
445 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
449 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
451 def enterDVDMenu(self):
453 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
455 def seekBeginning(self):
457 seekable = self.getSeek()
458 if seekable is not None:
461 def zapToNumber(self, number):
463 seekable = self.getSeek()
464 if seekable is not None:
465 print "seek to chapter %d" % number
466 seekable.seekChapter(number)
471 self.service.keys().keyPressed(iServiceKeys.keyRight)
475 self.service.keys().keyPressed(iServiceKeys.keyLeft)
479 self.service.keys().keyPressed(iServiceKeys.keyUp)
483 self.service.keys().keyPressed(iServiceKeys.keyDown)
489 self.service.keys().keyPressed(iServiceKeys.keyOk)
492 self.askLeavePlayer()
494 def showFileBrowser(self):
495 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
497 def FileBrowserClosed(self, val):
498 curref = self.session.nav.getCurrentlyPlayingServiceReference()
499 print "FileBrowserClosed", val
501 self.askLeavePlayer()
503 newref = eServiceReference(4369, 0, val)
504 print "play", newref.toString()
505 if curref is None or curref != newref:
506 self.session.nav.playService(newref)
507 self.service = self.session.nav.getCurrentService()
508 print "self.service", self.service
509 print "cur_dlg", self.session.current_dialog
510 self.dvdScreen.show()
511 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
513 def exitCB(self, answer):
514 if answer is not None:
515 if answer[1] == "exit":
517 self.dvdScreen.hide()
518 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
521 if answer[1] == "browser":
522 #TODO check here if a paused dvd playback is already running... then re-start it...
524 self.showFileBrowser()
529 self.restore_infobar_seek_config()
530 self.session.nav.playService(self.oldService)
532 def showAfterCuesheetOperation(self):
536 def createSummary(self):
537 print "DVDCreateSummary"
540 def main(session, **kwargs):
541 session.open(DVDPlayer)
543 def menu(menuid, **kwargs):
544 if menuid == "mainmenu":
545 return [(_("DVD Player"), main, "dvd_player", 46)]
548 from Plugins.Plugin import PluginDescriptor
549 def Plugins(**kwargs):
550 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]