experimentally enable AudioSelection Dialog for DVDPlayer (#440)
[vuplus_dvbapp] / lib / python / Plugins / Extensions / DVDPlayer / plugin.py
1 from os import path as os_path, remove as os_remove, listdir as os_listdir, system
2 from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys, getDesktop
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Screens.ChoiceBox import ChoiceBox
6 from Screens.HelpMenu import HelpableScreen
7 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications, InfoBarAudioSelection, InfoBarSubtitleSupport
8 from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
9 from Components.Label import Label
10 from Components.Sources.StaticText import StaticText
11 from Components.Pixmap import Pixmap
12 from Components.FileList import FileList
13 from Components.MenuList import MenuList
14 from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
15 from Components.config import config
16 from Tools.Directories import pathExists, fileExists
17 from Components.Harddisk import harddiskmanager
18
19 import servicedvd # load c++ part of dvd player plugin
20
21 lastpath = ""
22
23 class FileBrowser(Screen):
24
25         def __init__(self, session, dvd_filelist = [ ]):
26                 Screen.__init__(self, session)
27
28                 # for the skin: first try FileBrowser_DVDPlayer, then FileBrowser, this allows individual skinning
29                 self.skinName = ["FileBrowser_DVDPlayer", "FileBrowser" ]
30
31                 self.dvd_filelist = dvd_filelist
32                 if len(dvd_filelist):   
33                         self["filelist"] = MenuList(self.dvd_filelist)
34                 else:
35                         global lastpath
36                         if lastpath is not None:
37                                 currDir = lastpath + "/"
38                         else:
39                                 currDir = "/media/dvd/"
40                         if not pathExists(currDir):
41                                 currDir = "/"
42                         if lastpath == "":  # 'None' is magic to start at the list of mountpoints
43                                 currDir = None
44
45                         inhibitDirs = ["/bin", "/boot", "/dev", "/etc", "/home", "/lib", "/proc", "/sbin", "/share", "/sys", "/tmp", "/usr", "/var"]
46                         self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso|img)", useServiceRef = True)
47                         self["filelist"] = self.filelist
48
49                 self["FilelistActions"] = ActionMap(["SetupActions"],
50                         {
51                                 "save": self.ok,
52                                 "ok": self.ok,
53                                 "cancel": self.exit
54                         })
55                 self["key_red"] = StaticText(_("Cancel"))
56                 self["key_green"] = StaticText(_("OK"))
57                 self.onLayoutFinish.append(self.layoutFinished)
58
59         def layoutFinished(self):
60                 self.setTitle(_("DVD File Browser"))
61
62         def ok(self):
63                 if len(self.dvd_filelist):
64                         print "OK " + self["filelist"].getCurrent()
65                         self.close(self["filelist"].getCurrent())
66                 else:
67                         global lastpath
68                         filename = self["filelist"].getFilename()
69                         if filename is not None:
70                                 if filename.upper().endswith("VIDEO_TS/"):
71                                         print "dvd structure found, trying to open..."
72                                         dvdpath = filename[0:-9]
73                                         lastpath = (dvdpath.rstrip("/").rsplit("/",1))[0]
74                                         print "lastpath video_ts/=", lastpath
75                                         self.close(dvdpath)
76                                         return
77                         if self["filelist"].canDescent(): # isDir
78                                 self["filelist"].descent()
79                                 pathname = self["filelist"].getCurrentDirectory() or ""
80                                 if fileExists(pathname+"VIDEO_TS.IFO"):
81                                         print "dvd structure found, trying to open..."
82                                         lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
83                                         print "lastpath video_ts.ifo=", lastpath
84                                         self.close(pathname)
85                                 if fileExists(pathname+"VIDEO_TS/VIDEO_TS.IFO"):
86                                         print "dvd structure found, trying to open..."
87                                         lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
88                                         print "lastpath video_ts.ifo=", lastpath
89                                         pathname += "VIDEO_TS"
90                                         self.close(pathname)
91                         else:
92                                 lastpath = filename[0:filename.rfind("/")]
93                                 print "lastpath directory=", lastpath
94                                 self.close(filename)
95
96         def exit(self):
97                 self.close(None)
98
99 class DVDSummary(Screen):
100         skin = (
101         """<screen name="DVDSummary" position="0,0" size="132,64" id="1">
102                 <widget source="session.CurrentService" render="Label" position="5,4" size="120,28" font="Regular;12" transparent="1" >
103                         <convert type="ServiceName">Name</convert>
104                 </widget>
105                 <widget name="DVDPlayer" position="5,30" size="66,16" font="Regular;11" transparent="1" />
106                 <widget name="Chapter" position="72,30" size="54,16" font="Regular;12" transparent="1" halign="right" />
107                 <widget source="session.CurrentService" render="Label" position="66,46" size="60,18" font="Regular;16" transparent="1" halign="right" >
108                         <convert type="ServicePosition">Position</convert>
109                 </widget>
110                 <widget source="session.CurrentService" render="Progress" position="6,46" size="60,18" borderWidth="1" >
111                         <convert type="ServicePosition">Position</convert>
112                 </widget>
113         </screen>""",
114         """<screen name="DVDSummary" position="0,0" size="96,64" id="2">
115                 <widget source="session.CurrentService" render="Label" position="0,0" size="96,25" font="Regular;12" transparent="1" >
116                         <convert type="ServiceName">Name</convert>
117                 </widget>
118                 <widget name="DVDPlayer" position="0,26" size="96,12" font="Regular;10" transparent="1" />
119                 <widget name="Chapter" position="0,40" size="66,12" font="Regular;10" transparent="1" halign="left" />
120                 <widget source="session.CurrentService" render="Label" position="66,40" size="30,12" font="Regular;10" transparent="1" halign="right" >
121                         <convert type="ServicePosition">Position</convert>
122                 </widget>
123                 <widget source="session.CurrentService" render="Progress" position="0,52" size="96,12" borderWidth="1" >
124                         <convert type="ServicePosition">Position</convert>
125                 </widget>
126         </screen>""")
127
128         def __init__(self, session, parent):
129                 Screen.__init__(self, session, parent)
130
131                 self["DVDPlayer"] = Label("DVD Player")
132                 self["Title"] = Label("")
133                 self["Time"] = Label("")
134                 self["Chapter"] = Label("")
135
136         def updateChapter(self, chapter):
137                 self["Chapter"].setText(chapter)
138
139         def setTitle(self, title):
140                 self["Title"].setText(title)
141
142 class DVDOverlay(Screen):
143         def __init__(self, session, args = None):
144                 desktop_size = getDesktop(0).size()
145                 DVDOverlay.skin = """<screen name="DVDOverlay" position="0,0" size="%d,%d" flags="wfNoBorder" zPosition="-1" backgroundColor="transparent" />""" %(desktop_size.width(), desktop_size.height())
146                 Screen.__init__(self, session)
147
148 class ChapterZap(Screen):
149         skin = """
150         <screen name="ChapterZap" position="235,255" size="250,60" title="Chapter" >
151                 <widget name="chapter" position="35,15" size="110,25" font="Regular;23" />
152                 <widget name="number" position="145,15" size="80,25" halign="right" font="Regular;23" />
153         </screen>"""
154         
155         def quit(self):
156                 self.Timer.stop()
157                 self.close(0)
158
159         def keyOK(self):
160                 self.Timer.stop()
161                 self.close(int(self["number"].getText()))
162
163         def keyNumberGlobal(self, number):
164                 self.Timer.start(3000, True)            #reset timer
165                 self.field = self.field + str(number)
166                 self["number"].setText(self.field)
167                 if len(self.field) >= 4:
168                         self.keyOK()
169
170         def __init__(self, session, number):
171                 Screen.__init__(self, session)
172                 self.field = str(number)
173
174                 self["chapter"] = Label(_("Chapter:"))
175
176                 self["number"] = Label(self.field)
177
178                 self["actions"] = NumberActionMap( [ "SetupActions" ],
179                         {
180                                 "cancel": self.quit,
181                                 "ok": self.keyOK,
182                                 "1": self.keyNumberGlobal,
183                                 "2": self.keyNumberGlobal,
184                                 "3": self.keyNumberGlobal,
185                                 "4": self.keyNumberGlobal,
186                                 "5": self.keyNumberGlobal,
187                                 "6": self.keyNumberGlobal,
188                                 "7": self.keyNumberGlobal,
189                                 "8": self.keyNumberGlobal,
190                                 "9": self.keyNumberGlobal,
191                                 "0": self.keyNumberGlobal
192                         })
193
194                 self.Timer = eTimer()
195                 self.Timer.callback.append(self.keyOK)
196                 self.Timer.start(3000, True)
197
198 class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport, InfoBarAudioSelection, InfoBarSubtitleSupport):
199         ALLOW_SUSPEND = Screen.SUSPEND_PAUSES
200         ENABLE_RESUME_SUPPORT = True
201         
202         skin = """
203         <screen name="DVDPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="InfoBar" backgroundColor="transparent" >
204                 <!-- Background -->
205                 <ePixmap position="0,0" zPosition="-2" size="720,160" pixmap="skin_default/info-bg_mp.png" alphatest="off" />
206                 <ePixmap position="29,40" zPosition="0" size="665,104" pixmap="skin_default/screws_mp.png" alphatest="on" transparent="1" />
207                 <!-- colorbuttons -->
208                 <ePixmap position="48,70" zPosition="0" size="108,13" pixmap="skin_default/icons/mp_buttons.png" alphatest="on" />
209                 <!-- Servicename -->
210                 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" zPosition="1" size="15,10" alphatest="on" />
211                 <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">
212                         <convert type="ServiceName">Name</convert>
213                 </widget>
214                 <!-- Chapter info -->
215                 <widget name="chapterLabel" position="230,96" size="360,22" font="Regular;20" foregroundColor="#c3c3c9" backgroundColor="#263c59" transparent="1" />
216                 <!-- Audio track info -->
217                 <ePixmap pixmap="skin_default/icons/icon_dolby.png" position="540,60" zPosition="1" size="26,16" alphatest="on"/>
218                 <widget name="audioLabel" position="570,60" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
219                 <!-- Subtitle track info -->
220                 <widget source="session.CurrentService" render="Pixmap" pixmap="skin_default/icons/icon_txt.png" position="540,83" zPosition="1" size="26,16" alphatest="on" >
221                         <convert type="ServiceInfo">HasTelext</convert>
222                         <convert type="ConditionalShowHide" />
223                 </widget>
224                 <widget name="subtitleLabel" position="570,83" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
225                 <!-- Angle info -->
226                 <widget name="anglePix" pixmap="skin_default/icons/icon_view.png" position="540,106" size="26,16" alphatest="on" />
227                 <widget name="angleLabel" position="570,106" size="130,22" font="Regular;18" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1" />
228                 <!-- Elapsed time -->
229                 <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" >
230                         <convert type="ServicePosition">Position,ShowHours</convert>
231                 </widget>
232                 <!-- Progressbar (movie position)-->
233                 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" >
234                         <convert type="ServicePosition">Gauge</convert>
235                 </widget>
236                 <!-- Remaining time -->
237                 <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" >
238                         <convert type="ServicePosition">Remaining,Negate,ShowHours</convert>
239                 </widget>
240         </screen>"""
241
242         def save_infobar_seek_config(self):
243                 self.saved_config_speeds_forward = config.seek.speeds_forward.value
244                 self.saved_config_speeds_backward = config.seek.speeds_backward.value
245                 self.saved_config_enter_forward = config.seek.enter_forward.value
246                 self.saved_config_enter_backward = config.seek.enter_backward.value
247                 self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
248                 self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
249                 self.saved_config_seek_on_pause = config.seek.on_pause.value
250                 self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
251
252         def change_infobar_seek_config(self):
253                 config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
254                 config.seek.speeds_backward.value = [8, 16, 32, 64]
255                 config.seek.speeds_slowmotion.value = [ ]
256                 config.seek.enter_forward.value = "2"
257                 config.seek.enter_backward.value = "2"
258                 config.seek.stepwise_minspeed.value = "Never"
259                 config.seek.stepwise_repeat.value = "3"
260                 config.seek.on_pause.value = "play"
261
262         def restore_infobar_seek_config(self):
263                 config.seek.speeds_forward.value = self.saved_config_speeds_forward
264                 config.seek.speeds_backward.value = self.saved_config_speeds_backward
265                 config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
266                 config.seek.enter_forward.value = self.saved_config_enter_forward
267                 config.seek.enter_backward.value = self.saved_config_enter_backward
268                 config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
269                 config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
270                 config.seek.on_pause.value = self.saved_config_seek_on_pause
271
272         def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None):
273                 Screen.__init__(self, session)
274                 InfoBarBase.__init__(self)
275                 InfoBarNotifications.__init__(self)
276                 InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
277                 InfoBarShowHide.__init__(self)
278                 InfoBarAudioSelection.__init__(self)
279                 InfoBarSubtitleSupport.__init__(self)
280                 HelpableScreen.__init__(self)
281                 self.save_infobar_seek_config()
282                 self.change_infobar_seek_config()
283                 InfoBarSeek.__init__(self, useSeekBackHack=False)
284                 InfoBarPVRState.__init__(self)
285                 self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
286
287                 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
288                 self.session.nav.stopService()
289                 self["audioLabel"] = Label("n/a")
290                 self["subtitleLabel"] = Label("")
291                 self["angleLabel"] = Label("")
292                 self["chapterLabel"] = Label("")
293                 self["anglePix"] = Pixmap()
294                 self["anglePix"].hide()
295                 self.last_audioTuple = None
296                 self.last_subtitleTuple = None
297                 self.last_angleTuple = None
298                 self.totalChapters = 0
299                 self.currentChapter = 0
300                 self.totalTitles = 0
301                 self.currentTitle = 0
302
303                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
304                         {
305                                 iPlayableService.evStopped: self.__serviceStopped,
306                                 iPlayableService.evUser: self.__timeUpdated,
307                                 iPlayableService.evUser+1: self.__statePlay,
308                                 iPlayableService.evUser+2: self.__statePause,
309                                 iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
310                                 iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
311                                 iPlayableService.evUser+5: self.__osdStringAvail,
312                                 iPlayableService.evUser+6: self.__osdAudioInfoAvail,
313                                 iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
314                                 iPlayableService.evUser+8: self.__chapterUpdated,
315                                 iPlayableService.evUser+9: self.__titleUpdated,
316                                 iPlayableService.evUser+11: self.__menuOpened,
317                                 iPlayableService.evUser+12: self.__menuClosed,
318                                 iPlayableService.evUser+13: self.__osdAngleInfoAvail
319                         })
320
321                 self["DVDPlayerDirectionActions"] = ActionMap(["DirectionActions"],
322                         {
323                                 #MENU KEY DOWN ACTIONS
324                                 "left": self.keyLeft,
325                                 "right": self.keyRight,
326                                 "up": self.keyUp,
327                                 "down": self.keyDown,
328
329                                 #MENU KEY REPEATED ACTIONS
330                                 "leftRepeated": self.doNothing,
331                                 "rightRepeated": self.doNothing,
332                                 "upRepeated": self.doNothing,
333                                 "downRepeated": self.doNothing,
334
335                                 #MENU KEY UP ACTIONS
336                                 "leftUp": self.doNothing,
337                                 "rightUp": self.doNothing,
338                                 "upUp": self.doNothing,
339                                 "downUp": self.doNothing,
340                         })
341
342                 self["OkCancelActions"] = ActionMap(["OkCancelActions"],
343                         {
344                                 "ok": self.keyOk,
345                                 "cancel": self.keyCancel,
346                         })
347
348                 self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
349                         {
350                                 #PLAYER ACTIONS
351                                 "dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
352                                 "toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
353                                 "nextChapter": (self.nextChapter, _("forward to the next chapter")),
354                                 "prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
355                                 "nextTitle": (self.nextTitle, _("jump forward to the next title")),
356                                 "prevTitle": (self.prevTitle, _("jump back to the previous title")),
357                                 "tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
358                                 "dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
359                                 "nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
360                                 "nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
361                                 "nextAngle": (self.nextAngle, _("switch to the next angle")),
362                                 "seekBeginning": self.seekBeginning,
363                         }, -2)
364                         
365                 self["NumberActions"] = NumberActionMap( [ "NumberActions"],
366                         {
367                                 "1": self.keyNumberGlobal,
368                                 "2": self.keyNumberGlobal,
369                                 "3": self.keyNumberGlobal,
370                                 "4": self.keyNumberGlobal,
371                                 "5": self.keyNumberGlobal,
372                                 "6": self.keyNumberGlobal,
373                                 "7": self.keyNumberGlobal,
374                                 "8": self.keyNumberGlobal,
375                                 "9": self.keyNumberGlobal,
376                                 "0": self.keyNumberGlobal,
377                         })
378
379                 self.onClose.append(self.__onClose)
380
381                 from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
382                 hotplugNotifier.append(self.hotplugCB)
383                 
384                 self.autoplay = dvd_device or dvd_filelist
385
386                 if dvd_device:
387                         self.physicalDVD = True
388                 else:
389                         self.scanHotplug()
390
391                 self.dvd_filelist = dvd_filelist
392                 self.onFirstExecBegin.append(self.opened)
393                 self.service = None
394                 self.in_menu = False
395
396         def keyNumberGlobal(self, number):
397                 print "You pressed number " + str(number)
398                 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
399
400         def numberEntered(self, retval):
401 #               print self.servicelist
402                 if retval > 0:
403                         self.zapToNumber(retval)
404
405         def getServiceInterface(self, iface):
406                 service = self.service
407                 if service:
408                         attr = getattr(service, iface, None)
409                         if callable(attr):
410                                 return attr()
411                 return None
412
413         def __serviceStopped(self):
414                 self.dvdScreen.hide()
415                 subs = self.getServiceInterface("subtitle")
416                 if subs:
417                         subs.disableSubtitles(self.session.current_dialog.instance)
418
419         def serviceStarted(self): #override InfoBarShowHide function
420                 self.dvdScreen.show()
421
422         def doEofInternal(self, playing):
423                 if self.in_menu:
424                         self.hide()
425
426         def __menuOpened(self):
427                 self.hide()
428                 self.in_menu = True
429                 self["NumberActions"].setEnabled(False)
430
431         def __menuClosed(self):
432                 self.show()
433                 self.in_menu = False
434                 self["NumberActions"].setEnabled(True)
435
436         def setChapterLabel(self):
437                 chapterLCD = "Menu"
438                 chapterOSD = "DVD Menu"
439                 if self.currentTitle > 0:
440                         chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
441                         chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
442                         chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
443                 self["chapterLabel"].setText(chapterOSD)
444                 try:
445                         self.session.summary.updateChapter(chapterLCD)
446                 except:
447                         pass
448
449         def doNothing(self):
450                 pass
451
452         def toggleInfo(self):
453                 if not self.in_menu:
454                         self.toggleShow()
455                         print "toggleInfo"
456
457         def __timeUpdated(self):
458                 print "timeUpdated"
459
460         def __statePlay(self):
461                 print "statePlay"
462
463         def __statePause(self):
464                 print "statePause"
465
466         def __osdFFwdInfoAvail(self):
467                 self.setChapterLabel()
468                 print "FFwdInfoAvail"
469
470         def __osdFBwdInfoAvail(self):
471                 self.setChapterLabel()
472                 print "FBwdInfoAvail"
473
474         def __osdStringAvail(self):
475                 print "StringAvail"
476
477         def __osdAudioInfoAvail(self):
478                 info = self.getServiceInterface("info")
479                 audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
480                 print "AudioInfoAvail ", repr(audioTuple)
481                 if audioTuple:
482                         audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
483                         self["audioLabel"].setText(audioString)
484                         if audioTuple != self.last_audioTuple and not self.in_menu:
485                                 self.doShow()
486                 self.last_audioTuple = audioTuple
487
488         def __osdSubtitleInfoAvail(self):
489                 info = self.getServiceInterface("info")
490                 subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
491                 print "SubtitleInfoAvail ", repr(subtitleTuple)
492                 if subtitleTuple:
493                         subtitleString = ""
494                         if subtitleTuple[0] is not 0:
495                                 subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
496                         self["subtitleLabel"].setText(subtitleString)
497                         if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
498                                 self.doShow()
499                 self.last_subtitleTuple = subtitleTuple
500         
501         def __osdAngleInfoAvail(self):
502                 info = self.getServiceInterface("info")
503                 angleTuple = info and info.getInfoObject(iServiceInformation.sUser+8)
504                 print "AngleInfoAvail ", repr(angleTuple)
505                 if angleTuple:
506                         angleString = ""
507                         if angleTuple[1] > 1:
508                                 angleString = "%d / %d" % (angleTuple[0],angleTuple[1])
509                                 self["anglePix"].show()
510                         else:
511                                 self["anglePix"].hide()
512                         self["angleLabel"].setText(angleString)
513                         if angleTuple != self.last_angleTuple and not self.in_menu:
514                                 self.doShow()
515                 self.last_angleTuple = angleTuple
516
517         def __chapterUpdated(self):
518                 info = self.getServiceInterface("info")
519                 if info:
520                         self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
521                         self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
522                         self.setChapterLabel()
523                         print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
524
525         def __titleUpdated(self):
526                 info = self.getServiceInterface("info")
527                 if info:
528                         self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
529                         self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
530                         self.setChapterLabel()
531                         print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
532                         if not self.in_menu:
533                                 self.doShow()
534                 
535         def askLeavePlayer(self):
536                 choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")]
537                 if True or not self.physicalDVD:
538                         choices.insert(1,(_("Return to file browser"), "browser"))
539                 if self.physicalDVD:
540                         cur = self.session.nav.getCurrentlyPlayingServiceReference()
541                         if cur and not cur.toString().endswith(harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())):
542                             choices.insert(0,(_("Play DVD"), "playPhysical" ))
543                 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
544
545         def sendKey(self, key):
546                 keys = self.getServiceInterface("keys")
547                 if keys:
548                         keys.keyPressed(key)
549                 return keys
550
551         def nextAudioTrack(self):
552                 self.sendKey(iServiceKeys.keyUser)
553
554         def nextSubtitleTrack(self):
555                 self.sendKey(iServiceKeys.keyUser+1)
556
557         def enterDVDAudioMenu(self):
558                 self.audioSelection()
559                 #self.sendKey(iServiceKeys.keyUser+2)
560
561         def nextChapter(self):
562                 self.sendKey(iServiceKeys.keyUser+3)
563
564         def prevChapter(self):
565                 self.sendKey(iServiceKeys.keyUser+4)
566
567         def nextTitle(self):
568                 self.sendKey(iServiceKeys.keyUser+5)
569
570         def prevTitle(self):
571                 self.sendKey(iServiceKeys.keyUser+6)
572
573         def enterDVDMenu(self):
574                 self.sendKey(iServiceKeys.keyUser+7)
575         
576         def nextAngle(self):
577                 self.sendKey(iServiceKeys.keyUser+8)
578
579         def seekBeginning(self):
580                 if self.service:
581                         seekable = self.getSeek()
582                         if seekable:
583                                 seekable.seekTo(0)
584
585         def zapToNumber(self, number):
586                 if self.service:
587                         seekable = self.getSeek()
588                         if seekable:
589                                 print "seek to chapter %d" % number
590                                 seekable.seekChapter(number)
591
592 #       MENU ACTIONS
593         def keyRight(self):
594                 self.sendKey(iServiceKeys.keyRight)
595
596         def keyLeft(self):
597                 self.sendKey(iServiceKeys.keyLeft)
598
599         def keyUp(self):
600                 self.sendKey(iServiceKeys.keyUp)
601
602         def keyDown(self):
603                 self.sendKey(iServiceKeys.keyDown)
604
605         def keyOk(self):
606                 if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
607                         self.toggleInfo()
608
609         def keyCancel(self):
610                 self.askLeavePlayer()
611
612         def opened(self):
613                 if self.autoplay and self.dvd_filelist:
614                         # opened via autoplay
615                         self.FileBrowserClosed(self.dvd_filelist[0])
616                 elif self.autoplay and self.physicalDVD:
617                         self.playPhysicalCB(True)
618                 elif self.physicalDVD:
619                         # opened from menu with dvd in drive
620                         self.session.openWithCallback(self.playPhysicalCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
621                 else:
622                         # opened from menu without dvd in drive
623                         self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
624
625         def playPhysicalCB(self, answer):
626                 if answer == True:
627                         self.FileBrowserClosed(harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()))
628                 else:
629                         self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
630
631         def FileBrowserClosed(self, val):
632                 curref = self.session.nav.getCurrentlyPlayingServiceReference()
633                 print "FileBrowserClosed", val
634                 if val is None:
635                         self.askLeavePlayer()
636                 else:
637                         newref = eServiceReference(4369, 0, val)
638                         print "play", newref.toString()
639                         if curref is None or curref != newref:
640                                 if newref.toString().endswith("/VIDEO_TS") or newref.toString().endswith("/"):
641                                         names = newref.toString().rsplit("/",3)
642                                         if names[2].startswith("Disk ") or names[2].startswith("DVD "):
643                                                 name = str(names[1]) + " - " + str(names[2])
644                                         else:
645                                                 name = names[2]
646                                         print "setting name to: ", self.service
647                                         newref.setName(str(name))
648                                 self.session.nav.playService(newref)
649                                 self.service = self.session.nav.getCurrentService()
650                                 print "self.service", self.service
651                                 print "cur_dlg", self.session.current_dialog
652                                 subs = self.getServiceInterface("subtitle")
653                                 if subs:
654                                         subs.enableSubtitles(self.dvdScreen.instance, None)
655
656         def exitCB(self, answer):
657                 if answer is not None:
658                         if answer[1] == "exit":
659                                 if self.service:
660                                         self.service = None
661                                 self.close()
662                         if answer[1] == "browser":
663                                 #TODO check here if a paused dvd playback is already running... then re-start it...
664                                 #else
665                                 if self.service:
666                                         self.service = None
667                                 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
668                         if answer[1] == "playPhysical":
669                                 if self.service:
670                                         self.service = None
671                                 self.playPhysicalCB(True)
672                         else:
673                                 pass
674
675         def __onClose(self):
676                 self.restore_infobar_seek_config()
677                 self.session.nav.playService(self.oldService)
678                 from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
679                 hotplugNotifier.remove(self.hotplugCB)
680
681         def playLastCB(self, answer): # overwrite infobar cuesheet function
682                 print "playLastCB", answer, self.resume_point
683                 if self.service:
684                         if answer == True:
685                                 seekable = self.getSeek()
686                                 if seekable:
687                                         seekable.seekTo(self.resume_point)
688                         pause = self.service.pause()
689                         pause.unpause()
690                 self.hideAfterResume()
691
692         def showAfterCuesheetOperation(self):
693                 if not self.in_menu:
694                         self.show()
695
696         def createSummary(self):
697                 return DVDSummary
698
699 #override some InfoBarSeek functions
700         def doEof(self):
701                 self.setSeekState(self.SEEK_STATE_PLAY)
702
703         def calcRemainingTime(self):
704                 return 0
705
706         def hotplugCB(self, dev, media_state):
707                 print "[hotplugCB]", dev, media_state
708                 if dev == harddiskmanager.getCD():
709                         if media_state == "1":
710                                 self.scanHotplug()
711                         else:
712                                 self.physicalDVD = False
713
714         def scanHotplug(self):
715                 devicepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
716                 if pathExists(devicepath):
717                         from Components.Scanner import scanDevice
718                         res = scanDevice(devicepath)
719                         list = [ (r.description, r, res[r], self.session) for r in res ]
720                         if list:
721                                 (desc, scanner, files, session) = list[0]
722                                 for file in files:
723                                         print file
724                                         if file.mimetype == "video/x-dvd":
725                                                 print "physical dvd found:", devicepath
726                                                 self.physicalDVD = True
727                                                 return
728                 self.physicalDVD = False
729
730 def main(session, **kwargs):
731         session.open(DVDPlayer)
732
733 def menu(menuid, **kwargs):
734         if menuid == "mainmenu":
735                 return [(_("DVD Player"), main, "dvd_player", 46)]
736         return []
737
738 from Plugins.Plugin import PluginDescriptor
739
740 def filescan_open(list, session, **kwargs):
741         if len(list) == 1 and list[0].mimetype == "video/x-dvd":
742                 splitted = list[0].path.split('/')
743                 print "splitted", splitted
744                 if len(splitted) > 2:
745                         if splitted[1] == 'autofs':
746                                 session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
747                                 return
748                         else:
749                                 print "splitted[0]", splitted[1]
750         else:
751                 dvd_filelist = []
752                 for x in list:
753                         if x.mimetype == "video/x-dvd-iso":
754                                 dvd_filelist.append(x.path)
755                         if x.mimetype == "video/x-dvd":
756                                 dvd_filelist.append(x.path.rsplit('/',1)[0])                    
757                 session.open(DVDPlayer, dvd_filelist=dvd_filelist)
758
759 def filescan(**kwargs):
760         from Components.Scanner import Scanner, ScanPath
761
762         # Overwrite checkFile to only detect local
763         class LocalScanner(Scanner):
764                 def checkFile(self, file):
765                         return fileExists(file.path)
766
767         return [
768                 LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
769                         paths_to_scan =
770                                 [
771                                         ScanPath(path = "video_ts", with_subdirs = False),
772                                         ScanPath(path = "VIDEO_TS", with_subdirs = False),
773                                         ScanPath(path = "", with_subdirs = False),
774                                 ],
775                         name = "DVD",
776                         description = _("Play DVD"),
777                         openfnc = filescan_open,
778                 )]              
779
780 def Plugins(**kwargs):
781         return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
782                         PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]