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()
59 pathname = self["filelist"].getCurrentDirectory()
60 print self["filelist"].getFilename()
61 if fileExists(pathname+"VIDEO_TS.IFO"):
62 print "dvd structure found, trying to open..."
70 class DVDSummary(Screen):
72 <screen position="0,0" size="132,64">
73 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
74 <convert type="ServiceName">Name</convert>
76 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;12" transparent="1" />
77 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
78 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
79 <convert type="ServicePosition">Position</convert>
81 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
82 <convert type="ServicePosition">Position</convert>
86 def __init__(self, session, parent):
87 Screen.__init__(self, session, parent)
89 self["DVDPlayer"] = Label("DVD Player")
90 self["Title"] = Label("")
91 self["Time"] = Label("")
92 self["Chapter"] = Label("")
94 def updateChapter(self, chapter):
95 self["Chapter"].setText(chapter)
97 def setTitle(self, title):
98 self["Title"].setText(title)
100 class DVDOverlay(Screen):
101 skin = """<screen name="DVDOverlay" position="0,0" size="720,576" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />"""
102 def __init__(self, session, args = None):
103 Screen.__init__(self, session)
105 class ChapterZap(Screen):
107 <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
108 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
109 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
118 self.close(int(self["number"].getText()))
120 def keyNumberGlobal(self, number):
121 self.Timer.start(3000, True) #reset timer
122 self.field = self.field + str(number)
123 self["number"].setText(self.field)
124 if len(self.field) >= 4:
127 def __init__(self, session, number):
128 Screen.__init__(self, session)
129 self.field = str(number)
131 self["chapter"] = Label(_("Chapter:"))
133 self["number"] = Label(self.field)
135 self["actions"] = NumberActionMap( [ "SetupActions" ],
139 "1": self.keyNumberGlobal,
140 "2": self.keyNumberGlobal,
141 "3": self.keyNumberGlobal,
142 "4": self.keyNumberGlobal,
143 "5": self.keyNumberGlobal,
144 "6": self.keyNumberGlobal,
145 "7": self.keyNumberGlobal,
146 "8": self.keyNumberGlobal,
147 "9": self.keyNumberGlobal,
148 "0": self.keyNumberGlobal
151 self.Timer = eTimer()
152 self.Timer.callback.append(self.keyOK)
153 self.Timer.start(3000, True)
155 class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen):
156 #InfoBarCueSheetSupport,
157 # ALLOW_SUSPEND = True
158 # ENABLE_RESUME_SUPPORT = True
161 <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
163 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
164 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
165 <!-- colorbuttons -->
166 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
168 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
169 <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">
170 <convert type="ServiceName">Name</convert>
172 <!-- Chapter info -->
173 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
174 <!-- Audio track info -->
175 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,73" zPosition="1" size="26,16" alphatest="on"/>
176 <widget name="audioLabel" position="570,73" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
177 <!-- Subtitle track info -->
178 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,96" zPosition="1" size="26,16" alphatest="on" >
179 <convert type="ServiceInfo">HasTelext</convert>
180 <convert type="ConditionalShowHide" />
182 <widget name="subtitleLabel" position="570,96" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
183 <!-- Elapsed time -->
184 <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" >
185 <convert type="ServicePosition">Position,ShowHours</convert>
187 <!-- Progressbar (movie position)-->
188 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
189 <convert type="ServicePosition">Gauge</convert>
191 <!-- Remaining time -->
192 <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" >
193 <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
197 def save_infobar_seek_config(self):
198 self.saved_config_speeds_forward = config.seek.speeds_forward.value
199 self.saved_config_speeds_backward = config.seek.speeds_backward.value
200 self.saved_config_enter_forward = config.seek.enter_forward.value
201 self.saved_config_enter_backward = config.seek.enter_backward.value
202 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
203 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
204 self.saved_config_seek_on_pause = config.seek.on_pause.value
205 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
207 def change_infobar_seek_config(self):
208 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
209 config.seek.speeds_backward.value = [8, 16, 32, 64]
210 config.seek.speeds_slowmotion.value = [ ]
211 config.seek.enter_forward.value = "2"
212 config.seek.enter_backward.value = "2"
213 config.seek.stepwise_minspeed.value = "Never"
214 config.seek.stepwise_repeat.value = "3"
215 config.seek.on_pause.value = "play"
217 def restore_infobar_seek_config(self):
218 config.seek.speeds_forward.value = self.saved_config_speeds_forward
219 config.seek.speeds_backward.value = self.saved_config_speeds_backward
220 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
221 config.seek.enter_forward.value = self.saved_config_enter_forward
222 config.seek.enter_backward.value = self.saved_config_enter_backward
223 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
224 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
225 config.seek.on_pause.value = self.saved_config_seek_on_pause
227 def __init__(self, session, args = None):
228 Screen.__init__(self, session)
229 InfoBarBase.__init__(self)
230 InfoBarNotifications.__init__(self)
231 # InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
232 InfoBarShowHide.__init__(self)
233 HelpableScreen.__init__(self)
234 self.save_infobar_seek_config()
235 self.change_infobar_seek_config()
236 InfoBarSeek.__init__(self, useSeekBackHack=False)
237 InfoBarPVRState.__init__(self)
238 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
240 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
241 self.session.nav.stopService()
242 self["audioLabel"] = Label("1")
243 self["subtitleLabel"] = Label("")
244 self["chapterLabel"] = Label("")
245 self.totalChapters = 0
246 self.currentChapter = 0
248 self.currentTitle = 0
250 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
252 iPlayableService.evStopped: self.__serviceStopped,
253 iPlayableService.evUser: self.__timeUpdated,
254 iPlayableService.evUser+1: self.__statePlay,
255 iPlayableService.evUser+2: self.__statePause,
256 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
257 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
258 iPlayableService.evUser+5: self.__osdStringAvail,
259 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
260 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
261 iPlayableService.evUser+8: self.__chapterUpdated,
262 iPlayableService.evUser+9: self.__titleUpdated,
263 #iPlayableService.evUser+10: self.__initializeDVDinfo,
264 iPlayableService.evUser+11: self.__menuOpened,
265 iPlayableService.evUser+12: self.__menuClosed
268 self["DVDPlayerDirectionActions"] = HelpableActionMap(self, "DirectionActions",
270 #MENU KEY DOWN ACTIONS
271 "left": (self.keyLeft, _("DVD left key")),
272 "right": (self.keyRight, _("DVD right key")),
273 "up": (self.keyUp, _("DVD up key")),
274 "down": (self.keyDown, _("DVD down key")),
276 #MENU KEY REPEATED ACTIONS
277 "leftRepeated": self.doNothing,
278 "rightRepeated": self.doNothing,
279 "upRepeated": self.doNothing,
280 "downRepeated": self.doNothing,
283 "leftUp": self.doNothing,
284 "rightUp": self.doNothing,
285 "upUp": self.doNothing,
286 "downUp": self.doNothing,
289 self["OkCancelActions"] = HelpableActionMap(self, "OkCancelActions",
291 "ok": (self.keyOk, _("DVD ENTER key")),
292 "cancel": self.keyCancel,
295 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
298 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
299 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
300 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
301 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
302 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
303 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
304 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
305 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
306 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
307 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
308 "seekBeginning": (self.seekBeginning, _("Jump to video title 1 (play movie from start)")),
311 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
313 "1": self.keyNumberGlobal,
314 "2": self.keyNumberGlobal,
315 "3": self.keyNumberGlobal,
316 "4": self.keyNumberGlobal,
317 "5": self.keyNumberGlobal,
318 "6": self.keyNumberGlobal,
319 "7": self.keyNumberGlobal,
320 "8": self.keyNumberGlobal,
321 "9": self.keyNumberGlobal,
322 "0": self.keyNumberGlobal,
325 self.onClose.append(self.__onClose)
327 if fileExists("/dev/cdroms/cdrom0"):
328 print "physical dvd found (/dev/cdroms/cdrom0)"
329 self.physicalDVD = True
331 self.physicalDVD = False
333 self.onFirstExecBegin.append(self.showFileBrowser)
336 self.old_aspect = open("/proc/stb/video/aspect", "r").read()
337 self.old_policy = open("/proc/stb/video/policy", "r").read()
338 self.old_wss = open("/proc/stb/denc/0/wss", "r").read()
340 def keyNumberGlobal(self, number):
341 print "You pressed number " + str(number)
342 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
344 def numberEntered(self, retval):
345 # print self.servicelist
347 self.zapToNumber(retval)
349 def __serviceStopped(self):
350 self.dvdScreen.hide()
351 self.service.subtitle().disableSubtitles(self.session.current_dialog.instance)
353 def serviceStarted(self): #override InfoBarShowHide function
354 self.dvdScreen.show()
355 self.service.subtitle().enableSubtitles(self.dvdScreen.instance, None)
357 def doEofInternal(self, playing):
361 def __menuOpened(self):
364 self["NumberActions"].setEnabled(False)
366 def __menuClosed(self):
369 self["NumberActions"].setEnabled(True)
371 def setChapterLabel(self):
373 chapterOSD = "DVD Menu"
374 if self.currentTitle > 0:
375 chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
376 chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
377 chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
378 self["chapterLabel"].setText(chapterOSD)
380 self.session.summary.updateChapter(chapterLCD)
387 def toggleInfo(self):
392 def __timeUpdated(self):
395 def __statePlay(self):
398 def __statePause(self):
401 def __osdFFwdInfoAvail(self):
402 self.setChapterLabel()
403 print "FFwdInfoAvail"
405 def __osdFBwdInfoAvail(self):
406 self.setChapterLabel()
407 print "FBwdInfoAvail"
409 def __osdStringAvail(self):
412 def __osdAudioInfoAvail(self):
413 audioString = self.service.info().getInfoString(iServiceInformation.sUser+6)
414 print "AudioInfoAvail "+audioString
415 self["audioLabel"].setText(audioString)
419 def __osdSubtitleInfoAvail(self):
420 subtitleString = self.service.info().getInfoString(iServiceInformation.sUser+7)
421 print "SubtitleInfoAvail "+subtitleString
422 self["subtitleLabel"].setText(subtitleString)
426 def __chapterUpdated(self):
427 self.currentChapter = self.service.info().getInfo(iServiceInformation.sUser+8)
428 self.totalChapters = self.service.info().getInfo(iServiceInformation.sUser+80)
429 self.setChapterLabel()
430 print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
432 def __titleUpdated(self):
433 self.currentTitle = self.service.info().getInfo(iServiceInformation.sUser+9)
434 self.totalTitles = self.service.info().getInfo(iServiceInformation.sUser+90)
435 self.setChapterLabel()
436 print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
440 #def __initializeDVDinfo(self):
441 #self.__osdAudioInfoAvail()
442 #self.__osdSubtitleInfoAvail()
444 def askLeavePlayer(self):
445 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list=[(_("Exit"), "exit"), (_("Return to file browser"), "browser"), (_("Continue playing"), "play")])
447 def nextAudioTrack(self):
449 self.service.keys().keyPressed(iServiceKeys.keyUser)
451 def nextSubtitleTrack(self):
453 self.service.keys().keyPressed(iServiceKeys.keyUser+1)
455 def enterDVDAudioMenu(self):
457 self.service.keys().keyPressed(iServiceKeys.keyUser+2)
459 def nextChapter(self):
461 self.service.keys().keyPressed(iServiceKeys.keyUser+3)
463 def prevChapter(self):
465 self.service.keys().keyPressed(iServiceKeys.keyUser+4)
469 self.service.keys().keyPressed(iServiceKeys.keyUser+5)
473 self.service.keys().keyPressed(iServiceKeys.keyUser+6)
475 def enterDVDMenu(self):
477 self.service.keys().keyPressed(iServiceKeys.keyUser+7)
479 def seekBeginning(self):
481 seekable = self.getSeek()
482 if seekable is not None:
485 def zapToNumber(self, number):
487 seekable = self.getSeek()
488 if seekable is not None:
489 print "seek to chapter %d" % number
490 seekable.seekChapter(number)
495 self.service.keys().keyPressed(iServiceKeys.keyRight)
499 self.service.keys().keyPressed(iServiceKeys.keyLeft)
503 self.service.keys().keyPressed(iServiceKeys.keyUp)
507 self.service.keys().keyPressed(iServiceKeys.keyDown)
513 self.service.keys().keyPressed(iServiceKeys.keyOk)
516 self.askLeavePlayer()
518 def showFileBrowser(self):
520 self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
522 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
524 def DVDdriveCB(self, answer):
526 self.FileBrowserClosed("/dev/cdroms/cdrom0")
528 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
530 def FileBrowserClosed(self, val):
531 curref = self.session.nav.getCurrentlyPlayingServiceReference()
532 print "FileBrowserClosed", val
534 self.askLeavePlayer()
536 newref = eServiceReference(4369, 0, val)
537 print "play", newref.toString()
538 if curref is None or curref != newref:
539 self.session.nav.playService(newref)
540 self.service = self.session.nav.getCurrentService()
541 print "self.service", self.service
542 print "cur_dlg", self.session.current_dialog
544 def exitCB(self, answer):
545 if answer is not None:
546 if answer[1] == "exit":
550 if answer[1] == "browser":
551 #TODO check here if a paused dvd playback is already running... then re-start it...
553 self.showFileBrowser()
558 for i in (("/proc/stb/video/aspect", self.old_aspect), ("/proc/stb/video/policy", self.old_policy), ("/proc/stb/denc/0/wss", self.old_wss)):
560 open(i[0], "w").write(i[1])
562 print "restore", i[0], "failed"
563 self.restore_infobar_seek_config()
564 self.session.nav.playService(self.oldService)
566 # def playLastCB(self, answer): # overwrite infobar cuesheet function
567 # print "playLastCB", answer, self.resume_point
568 # pos = self.resume_point
569 # title = self.resume_point % 90000
571 # chapter = title % 256
573 # print "pos", pos, "title", title, "chapter", chapter
575 # seek = self.service.seek()
577 # seek.seekTitle(title)
578 # self.resume_state = 1
580 # seek.seekChapter(chapter)
581 # self.resume_state = 2
584 # self.hideAfterResume()
586 def showAfterCuesheetOperation(self):
590 def createSummary(self):
591 print "DVDCreateSummary"
594 #override some InfoBarSeek functions
596 self.setSeekState(self.SEEK_STATE_PLAY)
598 def calcRemainingTime(self):
601 def main(session, **kwargs):
602 session.open(DVDPlayer)
604 def menu(menuid, **kwargs):
605 if menuid == "mainmenu":
606 return [(_("DVD Player"), main, "dvd_player", 46)]
609 from Plugins.Plugin import PluginDescriptor
610 def Plugins(**kwargs):
611 return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu)]