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
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, 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 InfoBarNotifications.__init__(self)
224 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
225 InfoBarShowHide.__init__(self)
226 HelpableScreen.__init__(self)
227 self.save_infobar_seek_config()
228 self.change_infobar_seek_config()
229 InfoBarSeek.__init__(self)
230 InfoBarPVRState.__init__(self)
231 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
233 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
234 self.session.nav.stopService()
235 self["audioLabel"] = Label("1")
236 self["subtitleLabel"] = Label("")
237 self["chapterLabel"] = Label("")
238 self.totalChapters = 0
239 self.currentChapter = 0
241 self.currentTitle = 0
243 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
245 iPlayableService.evUser: self.__timeUpdated,
246 iPlayableService.evUser+1: self.__statePlay,
247 iPlayableService.evUser+2: self.__statePause,
248 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
249 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
250 iPlayableService.evUser+5: self.__osdStringAvail,
251 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
252 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
253 iPlayableService.evUser+8: self.__chapterUpdated,
254 iPlayableService.evUser+9: self.__titleUpdated,
255 #iPlayableService.evUser+10: self.__initializeDVDinfo,
256 iPlayableService.evUser+11: self.__menuOpened,
257 iPlayableService.evUser+12: self.__menuClosed
260 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
262 #MENU KEY DOWN ACTIONS
263 "left": (self.keyLeft, _("DVD left key")),
264 "right": (self.keyRight, _("DVD right key")),
265 "up": (self.keyUp, _("DVD up key")),
266 "down": (self.keyDown, _("DVD down key")),
268 #MENU KEY REPEATED ACTIONS
269 "leftRepeated": self.doNothing,
270 "rightRepeated": self.doNothing,
271 "upRepeated": self.doNothing,
272 "downRepeated": self.doNothing,
275 "leftUp": self.doNothing,
276 "rightUp": self.doNothing,
277 "upUp": self.doNothing,
278 "downUp": self.doNothing,
281 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
283 "ok": (self.keyOk, _("DVD ENTER key")),
284 "cancel": self.keyCancel,
287 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
290 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
291 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
292 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
293 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
294 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
295 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
296 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
297 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
298 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
299 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
300 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
303 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
305 "1": self.keyNumberGlobal,
306 "2": self.keyNumberGlobal,
307 "3": self.keyNumberGlobal,
308 "4": self.keyNumberGlobal,
309 "5": self.keyNumberGlobal,
310 "6": self.keyNumberGlobal,
311 "7": self.keyNumberGlobal,
312 "8": self.keyNumberGlobal,
313 "9": self.keyNumberGlobal,
314 "0": self.keyNumberGlobal,
317 self.onClose.append(self.__onClose)
318 self.onFirstExecBegin.append(self.showFileBrowser)
322 def keyNumberGlobal(self, number):
323 print "You pressed number " + str(number)
324 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
326 def numberEntered(self, retval):
327 # print self.servicelist
329 self.zapToNumber(retval)
331 def serviceStarted(self): #override InfoBarShowHide function
334 def doEofInternal(self, playing):
338 def __menuOpened(self):
342 def __menuClosed(self):
346 def setChapterLabel(self):
348 chapterOSD = "DVD Menu"
349 if self.currentTitle > 0:
350 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
351 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
352 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
353 self["chapterLabel"].setText(chapterOSD)
355 self.session.summary.updateChapter(chapterLCD)
362 def toggleInfo(self):
367 def __timeUpdated(self):
370 def __statePlay(self):
373 def __statePause(self):
376 def __osdFFwdInfoAvail(self):
377 self.setChapterLabel()
378 print "FFwdInfoAvail"
380 def __osdFBwdInfoAvail(self):
381 self.setChapterLabel()
382 print "FBwdInfoAvail"
384 def __osdStringAvail(self):
387 def __osdAudioInfoAvail(self):
388 audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
389 print "AudioInfoAvail "+audioString
390 self["audioLabel"].setText(audioString)
394 def __osdSubtitleInfoAvail(self):
395 subtitleString = self.service.info().getInfoString(iPlayableService.evUser+7)
396 print "SubtitleInfoAvail "+subtitleString
397 self["subtitleLabel"].setText(subtitleString)
401 def __chapterUpdated(self):
402 self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
403 self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
404 self.setChapterLabel()
405 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
407 def __titleUpdated(self):
408 self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
409 self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
410 self.setChapterLabel()
411 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
415 #def __initializeDVDinfo(self):
416 #self.__osdAudioInfoAvail()
417 #self.__osdSubtitleInfoAvail()
419 def askLeavePlayer(self):
420 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
422 def nextAudioTrack(self):
424 self.service.keys().keyPressed(iServiceKeys.keyUser)
426 def nextSubtitleTrack(self):
428 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
430 def enterDVDAudioMenu(self):
432 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
434 def nextChapter(self):
436 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
438 def prevChapter(self):
440 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
444 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
448 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
450 def enterDVDMenu(self):
452 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
454 def seekBeginning(self):
456 seekable = self.getSeek()
457 if seekable is not None:
460 def zapToNumber(self, number):
462 seekable = self.getSeek()
463 if seekable is not None:
464 print "seek to chapter %d" % number
465 seekable.seekChapter(number)
470 self.service.keys().keyPressed(iServiceKeys.keyRight)
474 self.service.keys().keyPressed(iServiceKeys.keyLeft)
478 self.service.keys().keyPressed(iServiceKeys.keyUp)
482 self.service.keys().keyPressed(iServiceKeys.keyDown)
488 self.service.keys().keyPressed(iServiceKeys.keyOk)
491 self.askLeavePlayer()
493 def showFileBrowser(self):
494 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
496 def FileBrowserClosed(self, val):
497 curref = self.session.nav.getCurrentlyPlayingServiceReference()
498 print "FileBrowserClosed", val
500 self.askLeavePlayer()
502 newref = eServiceReference(4369, 0, val)
503 print "play", newref.toString()
504 if curref is None or curref != newref:
505 self.session.nav.playService(newref)
506 self.service = self.session.nav.getCurrentService()
507 print "self.service", self.service
508 print "cur_dlg", self.session.current_dialog
509 self.dvdScreen.show()
510 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
512 def exitCB(self, answer):
513 if answer is not None:
514 if answer[1] == "exit":
516 self.dvdScreen.hide()
517 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
520 if answer[1] == "browser":
521 #TODO check here if a paused dvd playback is already running... then re-start it...
523 self.showFileBrowser()
528 self.restore_infobar_seek_config()
529 self.session.nav.playService(self.oldService)
531 def showAfterCuesheetOperation(self):
535 def createSummary(self):
536 print "DVDCreateSummary"
539 def main(session, **kwargs):
540 session.open(DVDPlayer)
542 def menu(menuid, **kwargs):
543 if menuid == "mainmenu":
544 return [(_("DVD Player"), main, "dvd_player", 46)]
547 from Plugins.Plugin import PluginDescriptor
548 def Plugins(**kwargs):
549 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]