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, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
151 #InfoBarCueSheetSupport,
152 # ALLOW_SUSPEND = True
153 # ENABLE_RESUME_SUPPORT = True
156 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
158 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
159 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
160 <!-- colorbuttons -->
161 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
163 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
164 <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">
165 <convert type="ServiceName">Name</convert>
167 <!-- Chapter info -->
168 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
169 <!-- Audio track info -->
170 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
171 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
172 <!-- Subtitle track info -->
173 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
174 <convert type="ServiceInfo">HasTelext</convert>
175 <convert type="ConditionalShowHide" />
177 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
178 <!-- Elapsed time -->
179 <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" >
180 <convert type="ServicePosition">Position,ShowHours</convert>
182 <!-- Progressbar (movie position)-->
183 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
184 <convert type="ServicePosition">Gauge</convert>
186 <!-- Remaining time -->
187 <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" >
188 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
192 def save_infobar_seek_config(self):
193 self.saved_config_speeds_forward = config.seek.speeds_forward.value
194 self.saved_config_speeds_backward = config.seek.speeds_backward.value
195 self.saved_config_enter_forward = config.seek.enter_forward.value
196 self.saved_config_enter_backward = config.seek.enter_backward.value
197 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
198 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
199 self.saved_config_seek_on_pause = config.seek.on_pause.value
200 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
202 def change_infobar_seek_config(self):
203 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
204 config.seek.speeds_backward.value = [8, 16, 32, 64]
205 config.seek.speeds_slowmotion.value = [ ]
206 config.seek.enter_forward.value = "2"
207 config.seek.enter_backward.value = "2"
208 config.seek.stepwise_minspeed.value = "Never"
209 config.seek.stepwise_repeat.value = "3"
210 config.seek.on_pause.value = "play"
212 def restore_infobar_seek_config(self):
213 config.seek.speeds_forward.value = self.saved_config_speeds_forward
214 config.seek.speeds_backward.value = self.saved_config_speeds_backward
215 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
216 config.seek.enter_forward.value = self.saved_config_enter_forward
217 config.seek.enter_backward.value = self.saved_config_enter_backward
218 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
219 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
220 config.seek.on_pause.value = self.saved_config_seek_on_pause
222 def __init__(self, session, args = None):
223 Screen.__init__(self, session)
224 InfoBarBase.__init__(self)
225 InfoBarNotifications.__init__(self)
226 # InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
227 InfoBarShowHide.__init__(self)
228 HelpableScreen.__init__(self)
229 self.save_infobar_seek_config()
230 self.change_infobar_seek_config()
231 InfoBarSeek.__init__(self, useSeekBackHack=False)
232 InfoBarPVRState.__init__(self)
233 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
235 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
236 self.session.nav.stopService()
237 self["audioLabel"] = Label("1")
238 self["subtitleLabel"] = Label("")
239 self["chapterLabel"] = Label("")
240 self.totalChapters = 0
241 self.currentChapter = 0
243 self.currentTitle = 0
245 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
247 iPlayableService.evStopped: self.__serviceStopped,
248 iPlayableService.evUser: self.__timeUpdated,
249 iPlayableService.evUser+1: self.__statePlay,
250 iPlayableService.evUser+2: self.__statePause,
251 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
252 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
253 iPlayableService.evUser+5: self.__osdStringAvail,
254 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
255 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
256 iPlayableService.evUser+8: self.__chapterUpdated,
257 iPlayableService.evUser+9: self.__titleUpdated,
258 #iPlayableService.evUser+10: self.__initializeDVDinfo,
259 iPlayableService.evUser+11: self.__menuOpened,
260 iPlayableService.evUser+12: self.__menuClosed
263 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
265 #MENU KEY DOWN ACTIONS
266 "left": (self.keyLeft, _("DVD left key")),
267 "right": (self.keyRight, _("DVD right key")),
268 "up": (self.keyUp, _("DVD up key")),
269 "down": (self.keyDown, _("DVD down key")),
271 #MENU KEY REPEATED ACTIONS
272 "leftRepeated": self.doNothing,
273 "rightRepeated": self.doNothing,
274 "upRepeated": self.doNothing,
275 "downRepeated": self.doNothing,
278 "leftUp": self.doNothing,
279 "rightUp": self.doNothing,
280 "upUp": self.doNothing,
281 "downUp": self.doNothing,
284 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
286 "ok": (self.keyOk, _("DVD ENTER key")),
287 "cancel": self.keyCancel,
290 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
293 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
294 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
295 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
296 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
297 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
298 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
299 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
300 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
301 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
302 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
303 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
306 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
308 "1": self.keyNumberGlobal,
309 "2": self.keyNumberGlobal,
310 "3": self.keyNumberGlobal,
311 "4": self.keyNumberGlobal,
312 "5": self.keyNumberGlobal,
313 "6": self.keyNumberGlobal,
314 "7": self.keyNumberGlobal,
315 "8": self.keyNumberGlobal,
316 "9": self.keyNumberGlobal,
317 "0": self.keyNumberGlobal,
320 self.onClose.append(self.__onClose)
321 self.onFirstExecBegin.append(self.showFileBrowser)
325 def keyNumberGlobal(self, number):
326 print "You pressed number " + str(number)
327 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
329 def numberEntered(self, retval):
330 # print self.servicelist
332 self.zapToNumber(retval)
334 def __serviceStopped(self):
335 self.dvdScreen.hide()
336 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
338 def serviceStarted(self): #override InfoBarShowHide function
339 self.dvdScreen.show()
340 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
342 def doEofInternal(self, playing):
346 def __menuOpened(self):
349 self["NumberActions"].setEnabled(False)
351 def __menuClosed(self):
354 self["NumberActions"].setEnabled(True)
356 def setChapterLabel(self):
358 chapterOSD = "DVD Menu"
359 if self.currentTitle > 0:
360 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
361 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
362 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
363 self["chapterLabel"].setText(chapterOSD)
365 self.session.summary.updateChapter(chapterLCD)
372 def toggleInfo(self):
377 def __timeUpdated(self):
380 def __statePlay(self):
383 def __statePause(self):
386 def __osdFFwdInfoAvail(self):
387 self.setChapterLabel()
388 print "FFwdInfoAvail"
390 def __osdFBwdInfoAvail(self):
391 self.setChapterLabel()
392 print "FBwdInfoAvail"
394 def __osdStringAvail(self):
397 def __osdAudioInfoAvail(self):
398 audioString = self.service.info().getInfoString(iServiceInformation.sUser+6)
399 print "AudioInfoAvail "+audioString
400 self["audioLabel"].setText(audioString)
404 def __osdSubtitleInfoAvail(self):
405 subtitleString = self.service.info().getInfoString(iServiceInformation.sUser+7)
406 print "SubtitleInfoAvail "+subtitleString
407 self["subtitleLabel"].setText(subtitleString)
411 def __chapterUpdated(self):
412 self.currentChapter = self.service.info().getInfo(iServiceInformation.sUser+8)
413 self.totalChapters = self.service.info().getInfo(iServiceInformation.sUser+80)
414 self.setChapterLabel()
415 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
417 def __titleUpdated(self):
418 self.currentTitle = self.service.info().getInfo(iServiceInformation.sUser+9)
419 self.totalTitles = self.service.info().getInfo(iServiceInformation.sUser+90)
420 self.setChapterLabel()
421 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
425 #def __initializeDVDinfo(self):
426 #self.__osdAudioInfoAvail()
427 #self.__osdSubtitleInfoAvail()
429 def askLeavePlayer(self):
430 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
432 def nextAudioTrack(self):
434 self.service.keys().keyPressed(iServiceKeys.keyUser)
436 def nextSubtitleTrack(self):
438 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
440 def enterDVDAudioMenu(self):
442 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
444 def nextChapter(self):
446 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
448 def prevChapter(self):
450 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
454 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
458 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
460 def enterDVDMenu(self):
462 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
464 def seekBeginning(self):
466 seekable = self.getSeek()
467 if seekable is not None:
470 def zapToNumber(self, number):
472 seekable = self.getSeek()
473 if seekable is not None:
474 print "seek to chapter %d" % number
475 seekable.seekChapter(number)
480 self.service.keys().keyPressed(iServiceKeys.keyRight)
484 self.service.keys().keyPressed(iServiceKeys.keyLeft)
488 self.service.keys().keyPressed(iServiceKeys.keyUp)
492 self.service.keys().keyPressed(iServiceKeys.keyDown)
498 self.service.keys().keyPressed(iServiceKeys.keyOk)
501 self.askLeavePlayer()
503 def showFileBrowser(self):
504 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
506 def FileBrowserClosed(self, val):
507 curref = self.session.nav.getCurrentlyPlayingServiceReference()
508 print "FileBrowserClosed", val
510 self.askLeavePlayer()
512 newref = eServiceReference(4369, 0, val)
513 print "play", newref.toString()
514 if curref is None or curref != newref:
515 self.session.nav.playService(newref)
516 self.service = self.session.nav.getCurrentService()
517 print "self.service", self.service
518 print "cur_dlg", self.session.current_dialog
520 def exitCB(self, answer):
521 if answer is not None:
522 if answer[1] == "exit":
526 if answer[1] == "browser":
527 #TODO check here if a paused dvd playback is already running... then re-start it...
529 self.showFileBrowser()
534 self.restore_infobar_seek_config()
535 self.session.nav.playService(self.oldService)
537 # def playLastCB(self, answer): # overwrite infobar cuesheet function
538 # print "playLastCB", answer, self.resume_point
539 # pos = self.resume_point
540 # title = self.resume_point % 90000
542 # chapter = title % 256
544 # print "pos", pos, "title", title, "chapter", chapter
546 # seek = self.service.seek()
548 # seek.seekTitle(title)
549 # self.resume_state = 1
551 # seek.seekChapter(chapter)
552 # self.resume_state = 2
555 # self.hideAfterResume()
557 def showAfterCuesheetOperation(self):
561 def createSummary(self):
562 print "DVDCreateSummary"
565 #override some InfoBarSeek functions
567 self.setSeekState(self.SEEK_STATE_PLAY)
569 def calcRemainingTime(self):
572 def main(session, **kwargs):
573 session.open(DVDPlayer)
575 def menu(menuid, **kwargs):
576 if menuid == "mainmenu":
577 return [(_("DVD Player"), main, "dvd_player", 46)]
580 from Plugins.Plugin import PluginDescriptor
581 def Plugins(**kwargs):
582 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]