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