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