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 if self["filelist"].getFilename().upper().endswith("VIDEO_TS/"):
45 print "dvd structure found, trying to open..."
46 self.close(self["filelist"].getFilename()[0:-9])
48 elif self["filelist"].canDescent(): # isDir
49 self["filelist"].descent()
52 self.close(self["filelist"].getFilename())
57 class DVDSummary(Screen):
59 <screen position="0,0" size="132,64">
60 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
61 <convert type="ServiceName">Name</convert>
63 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;12" transparent="1" />
64 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
65 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
66 <convert type="ServicePosition">Position</convert>
68 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
69 <convert type="ServicePosition">Position</convert>
73 def __init__(self, session, parent):
74 Screen.__init__(self, session, parent)
76 self["DVDPlayer"] = Label("DVD Player")
77 self["Title"] = Label("")
78 self["Time"] = Label("")
79 self["Chapter"] = Label("")
81 def updateChapter(self, chapter):
82 self["Chapter"].setText(chapter)
84 def setTitle(self, title):
85 self["Title"].setText(title)
87 class DVDOverlay(Screen):
88 skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />"""
89 def __init__(self, session, args = None):
90 Screen.__init__(self, session)
92 class ChapterZap(Screen):
94 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
95 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
96 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
105 self.close(int(self["number"].getText()))
107 def keyNumberGlobal(self, number):
108 self.Timer.start(3000, True) #reset timer
109 self.field = self.field + str(number)
110 self["number"].setText(self.field)
111 if len(self.field) >= 4:
114 def __init__(self, session, number):
115 Screen.__init__(self, session)
116 self.field = str(number)
118 self["chapter"] = Label(_("Chapter:"))
120 self["number"] = Label(self.field)
122 self["actions"] = NumberActionMap( [ "SetupActions" ],
126 "1": self.keyNumberGlobal,
127 "2": self.keyNumberGlobal,
128 "3": self.keyNumberGlobal,
129 "4": self.keyNumberGlobal,
130 "5": self.keyNumberGlobal,
131 "6": self.keyNumberGlobal,
132 "7": self.keyNumberGlobal,
133 "8": self.keyNumberGlobal,
134 "9": self.keyNumberGlobal,
135 "0": self.keyNumberGlobal
138 self.Timer = eTimer()
139 self.Timer.callback.append(self.keyOK)
140 self.Timer.start(3000, True)
142 class DVDPlayer(Screen, InfoBarNotifications, InfoBarSeek, InfoBarCueSheetSupport, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
144 ENABLE_RESUME_SUPPORT = True
147 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
149 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
150 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
151 <!-- colorbuttons -->
152 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
154 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
155 <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">
156 <convert type="ServiceName">Name</convert>
158 <!-- Chapter info -->
159 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
160 <!-- Audio track info -->
161 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
162 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
163 <!-- Subtitle track info -->
164 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
165 <convert type="ServiceInfo">HasTelext</convert>
166 <convert type="ConditionalShowHide" />
168 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
169 <!-- Elapsed time -->
170 <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" >
171 <convert type="ServicePosition">Position,ShowHours</convert>
173 <!-- Progressbar (movie position)-->
174 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
175 <convert type="ServicePosition">Gauge</convert>
177 <!-- Remaining time -->
178 <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" >
179 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
183 def save_infobar_seek_config(self):
184 self.saved_config_speeds_forward = config.seek.speeds_forward.value
185 self.saved_config_speeds_backward = config.seek.speeds_backward.value
186 self.saved_config_enter_forward = config.seek.enter_forward.value
187 self.saved_config_enter_backward = config.seek.enter_backward.value
188 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
189 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
190 self.saved_config_seek_on_pause = config.seek.on_pause.value
191 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
193 def change_infobar_seek_config(self):
194 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
195 config.seek.speeds_backward.value = [8, 16, 32, 64]
196 config.seek.speeds_slowmotion.value = [ ]
197 config.seek.enter_forward.value = "2"
198 config.seek.enter_backward.value = "2"
199 config.seek.stepwise_minspeed.value = "Never"
200 config.seek.stepwise_repeat.value = "3"
201 config.seek.on_pause.value = "play"
203 def restore_infobar_seek_config(self):
204 config.seek.speeds_forward.value = self.saved_config_speeds_forward
205 config.seek.speeds_backward.value = self.saved_config_speeds_backward
206 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
207 config.seek.enter_forward.value = self.saved_config_enter_forward
208 config.seek.enter_backward.value = self.saved_config_enter_backward
209 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
210 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
211 config.seek.on_pause.value = self.saved_config_seek_on_pause
213 def __init__(self, session, args = None):
214 Screen.__init__(self, session)
215 InfoBarNotifications.__init__(self)
216 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
217 InfoBarShowHide.__init__(self)
218 HelpableScreen.__init__(self)
219 self.save_infobar_seek_config()
220 self.change_infobar_seek_config()
221 InfoBarSeek.__init__(self)
222 InfoBarPVRState.__init__(self)
223 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
225 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
226 self.session.nav.stopService()
227 self["audioLabel"] = Label("1")
228 self["subtitleLabel"] = Label("")
229 self["chapterLabel"] = Label("")
230 self.totalChapters = 0
231 self.currentChapter = 0
233 self.currentTitle = 0
235 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
237 iPlayableService.evUser: self.__timeUpdated,
238 iPlayableService.evUser+1: self.__statePlay,
239 iPlayableService.evUser+2: self.__statePause,
240 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
241 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
242 iPlayableService.evUser+5: self.__osdStringAvail,
243 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
244 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
245 iPlayableService.evUser+8: self.__chapterUpdated,
246 iPlayableService.evUser+9: self.__titleUpdated,
247 #iPlayableService.evUser+10: self.__initializeDVDinfo,
248 iPlayableService.evUser+11: self.__menuOpened,
249 iPlayableService.evUser+12: self.__menuClosed
252 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
254 #MENU KEY DOWN ACTIONS
255 "left": (self.keyLeft, _("DVD left key")),
256 "right": (self.keyRight, _("DVD right key")),
257 "up": (self.keyUp, _("DVD up key")),
258 "down": (self.keyDown, _("DVD down key")),
260 #MENU KEY REPEATED ACTIONS
261 "leftRepeated": self.doNothing,
262 "rightRepeated": self.doNothing,
263 "upRepeated": self.doNothing,
264 "downRepeated": self.doNothing,
267 "leftUp": self.doNothing,
268 "rightUp": self.doNothing,
269 "upUp": self.doNothing,
270 "downUp": self.doNothing,
273 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
275 "ok": (self.keyOk, _("DVD ENTER key")),
276 "cancel": self.keyCancel,
279 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
282 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
283 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
284 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
285 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
286 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
287 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
288 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
289 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
290 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
291 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
292 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
295 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
297 "1": self.keyNumberGlobal,
298 "2": self.keyNumberGlobal,
299 "3": self.keyNumberGlobal,
300 "4": self.keyNumberGlobal,
301 "5": self.keyNumberGlobal,
302 "6": self.keyNumberGlobal,
303 "7": self.keyNumberGlobal,
304 "8": self.keyNumberGlobal,
305 "9": self.keyNumberGlobal,
306 "0": self.keyNumberGlobal,
309 self.onClose.append(self.__onClose)
310 self.onFirstExecBegin.append(self.showFileBrowser)
314 def keyNumberGlobal(self, number):
315 print "You pressed number " + str(number)
316 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
318 def numberEntered(self, retval):
319 # print self.servicelist
321 self.zapToNumber(retval)
323 def serviceStarted(self): #override InfoBarShowHide function
326 def doEofInternal(self, playing):
330 def __menuOpened(self):
334 def __menuClosed(self):
338 def setChapterLabel(self):
340 chapterOSD = "DVD Menu"
341 if self.currentTitle > 0:
342 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
343 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
344 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
345 self["chapterLabel"].setText(chapterOSD)
347 self.session.summary.updateChapter(chapterLCD)
354 def toggleInfo(self):
359 def __timeUpdated(self):
362 def __statePlay(self):
365 def __statePause(self):
368 def __osdFFwdInfoAvail(self):
369 self.setChapterLabel()
370 print "FFwdInfoAvail"
372 def __osdFBwdInfoAvail(self):
373 self.setChapterLabel()
374 print "FBwdInfoAvail"
376 def __osdStringAvail(self):
379 def __osdAudioInfoAvail(self):
380 audioString = self.service.info().getInfoString(iPlayableService.evUser+6)
381 print "AudioInfoAvail "+audioString
382 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)
391 def __chapterUpdated(self):
392 self.currentChapter = self.service.info().getInfo(iPlayableService.evUser+8)
393 self.totalChapters = self.service.info().getInfo(iPlayableService.evUser+80)
394 self.setChapterLabel()
395 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
397 def __titleUpdated(self):
398 self.currentTitle = self.service.info().getInfo(iPlayableService.evUser+9)
399 self.totalTitles = self.service.info().getInfo(iPlayableService.evUser+90)
400 self.setChapterLabel()
401 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
404 #def __initializeDVDinfo(self):
405 #self.__osdAudioInfoAvail()
406 #self.__osdSubtitleInfoAvail()
408 def askLeavePlayer(self):
409 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
411 def nextAudioTrack(self):
413 self.service.keys().keyPressed(iServiceKeys.keyUser)
415 def nextSubtitleTrack(self):
417 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
419 def enterDVDAudioMenu(self):
421 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
423 def nextChapter(self):
425 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
427 def prevChapter(self):
429 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
433 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
437 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
439 def enterDVDMenu(self):
441 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
443 def seekBeginning(self):
445 seekable = self.getSeek()
446 if seekable is not None:
449 def zapToNumber(self, number):
451 seekable = self.getSeek()
452 if seekable is not None:
453 print "seek to chapter %d" % number
454 seekable.seekChapter(number)
459 self.service.keys().keyPressed(iServiceKeys.keyRight)
463 self.service.keys().keyPressed(iServiceKeys.keyLeft)
467 self.service.keys().keyPressed(iServiceKeys.keyUp)
471 self.service.keys().keyPressed(iServiceKeys.keyDown)
475 self.service.keys().keyPressed(iServiceKeys.keyOk)
478 self.askLeavePlayer()
480 def showFileBrowser(self):
481 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
483 def FileBrowserClosed(self, val):
484 curref = self.session.nav.getCurrentlyPlayingServiceReference()
485 print "FileBrowserClosed", val
487 self.askLeavePlayer()
489 newref = eServiceReference(4369, 0, val)
490 print "play", newref.toString()
491 if curref is None or curref != newref:
492 self.session.nav.playService(newref)
493 self.service = self.session.nav.getCurrentService()
494 print "self.service", self.service
495 print "cur_dlg", self.session.current_dialog
496 self.dvdScreen.show()
497 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
499 def exitCB(self, answer):
500 if answer is not None:
501 if answer[1] == "exit":
503 self.dvdScreen.hide()
504 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
507 if answer[1] == "browser":
508 #TODO check here if a paused dvd playback is already running... then re-start it...
510 self.showFileBrowser()
515 self.restore_infobar_seek_config()
516 self.session.nav.playService(self.oldService)
518 def showAfterCuesheetOperation(self):
521 def createSummary(self):
522 print "DVDCreateSummary"
525 def main(session, **kwargs):
526 session.open(DVDPlayer)
528 def menu(menuid, **kwargs):
529 if menuid == "mainmenu":
530 return [(_("DVD Player"), main, "dvd_player", 46)]
533 from Plugins.Plugin import PluginDescriptor
534 def Plugins(**kwargs):
535 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]