Merge branch 'master' of git.opendreambox.org:/git/enigma2
[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                 self.old_aspect = open("/proc/stb/video/aspect", "r").read()
373                 self.old_policy = open("/proc/stb/video/policy", "r").read()
374                 self.old_wss = open("/proc/stb/denc/0/wss", "r").read()
375
376         def keyNumberGlobal(self, number):
377                 print "You pressed number " + str(number)
378                 self.session.openWithCallback(self.numberEntered, ChapterZap, number)
379
380         def numberEntered(self, retval):
381 #               print self.servicelist
382                 if retval > 0:
383                         self.zapToNumber(retval)
384
385         def getServiceInterface(self, iface):
386                 service = self.service
387                 if service:
388                         attr = getattr(service, iface, None)
389                         if callable(attr):
390                                 return attr()
391                 return None
392
393         def __serviceStopped(self):
394                 self.dvdScreen.hide()
395                 subs = self.getServiceInterface("subtitle")
396                 if subs:
397                         subs.disableSubtitles(self.session.current_dialog.instance)
398
399         def serviceStarted(self): #override InfoBarShowHide function
400                 self.dvdScreen.show()
401
402         def doEofInternal(self, playing):
403                 if self.in_menu:
404                         self.hide()
405
406         def __menuOpened(self):
407                 self.hide()
408                 self.in_menu = True
409                 self["NumberActions"].setEnabled(False)
410
411         def __menuClosed(self):
412                 self.show()
413                 self.in_menu = False
414                 self["NumberActions"].setEnabled(True)
415
416         def setChapterLabel(self):
417                 chapterLCD = "Menu"
418                 chapterOSD = "DVD Menu"
419                 if self.currentTitle > 0:
420                         chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
421                         chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
422                         chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
423                 self["chapterLabel"].setText(chapterOSD)
424                 try:
425                         self.session.summary.updateChapter(chapterLCD)
426                 except:
427                         pass
428
429         def doNothing(self):
430                 pass
431
432         def toggleInfo(self):
433                 if not self.in_menu:
434                         self.toggleShow()
435                         print "toggleInfo"
436
437         def __timeUpdated(self):
438                 print "timeUpdated"
439
440         def __statePlay(self):
441                 print "statePlay"
442
443         def __statePause(self):
444                 print "statePause"
445
446         def __osdFFwdInfoAvail(self):
447                 self.setChapterLabel()
448                 print "FFwdInfoAvail"
449
450         def __osdFBwdInfoAvail(self):
451                 self.setChapterLabel()
452                 print "FBwdInfoAvail"
453
454         def __osdStringAvail(self):
455                 print "StringAvail"
456
457         def __osdAudioInfoAvail(self):
458                 info = self.getServiceInterface("info")
459                 audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
460                 print "AudioInfoAvail ", repr(audioTuple)
461                 if audioTuple:
462                         audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
463                         self["audioLabel"].setText(audioString)
464                         if audioTuple != self.last_audioTuple and not self.in_menu:
465                                 self.doShow()
466                 self.last_audioTuple = audioTuple
467
468         def __osdSubtitleInfoAvail(self):
469                 info = self.getServiceInterface("info")
470                 subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
471                 print "SubtitleInfoAvail ", repr(subtitleTuple)
472                 if subtitleTuple:
473                         subtitleString = ""
474                         if subtitleTuple[0] is not 0:
475                                 subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
476                         self["subtitleLabel"].setText(subtitleString)
477                         if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
478                                 self.doShow()
479                 self.last_subtitleTuple = subtitleTuple
480         
481         def __osdAngleInfoAvail(self):
482                 info = self.getServiceInterface("info")
483                 angleTuple = info and info.getInfoObject(iServiceInformation.sUser+8)
484                 print "AngleInfoAvail ", repr(angleTuple)
485                 if angleTuple:
486                         angleString = ""
487                         if angleTuple[1] > 1:
488                                 angleString = "%d / %d" % (angleTuple[0],angleTuple[1])
489                                 self["anglePix"].show()
490                         else:
491                                 self["anglePix"].hide()
492                         self["angleLabel"].setText(angleString)
493                         if angleTuple != self.last_angleTuple and not self.in_menu:
494                                 self.doShow()
495                 self.last_angleTuple = angleTuple
496
497         def __chapterUpdated(self):
498                 info = self.getServiceInterface("info")
499                 if info:
500                         self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
501                         self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
502                         self.setChapterLabel()
503                         print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
504
505         def __titleUpdated(self):
506                 info = self.getServiceInterface("info")
507                 if info:
508                         self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
509                         self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
510                         self.setChapterLabel()
511                         print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
512                         if not self.in_menu:
513                                 self.doShow()
514                 
515         def askLeavePlayer(self):
516                 choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")]
517                 if not self.physicalDVD:
518                         choices.insert(1,(_("Return to file browser"), "browser"))
519                 self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
520
521         def sendKey(self, key):
522                 keys = self.getServiceInterface("keys")
523                 if keys:
524                         keys.keyPressed(key)
525                 return keys
526
527         def nextAudioTrack(self):
528                 self.sendKey(iServiceKeys.keyUser)
529
530         def nextSubtitleTrack(self):
531                 self.sendKey(iServiceKeys.keyUser+1)
532
533         def enterDVDAudioMenu(self):
534                 self.sendKey(iServiceKeys.keyUser+2)
535
536         def nextChapter(self):
537                 self.sendKey(iServiceKeys.keyUser+3)
538
539         def prevChapter(self):
540                 self.sendKey(iServiceKeys.keyUser+4)
541
542         def nextTitle(self):
543                 self.sendKey(iServiceKeys.keyUser+5)
544
545         def prevTitle(self):
546                 self.sendKey(iServiceKeys.keyUser+6)
547
548         def enterDVDMenu(self):
549                 self.sendKey(iServiceKeys.keyUser+7)
550         
551         def nextAngle(self):
552                 self.sendKey(iServiceKeys.keyUser+8)
553
554         def seekBeginning(self):
555                 if self.service:
556                         seekable = self.getSeek()
557                         if seekable:
558                                 seekable.seekTo(0)
559
560         def zapToNumber(self, number):
561                 if self.service:
562                         seekable = self.getSeek()
563                         if seekable:
564                                 print "seek to chapter %d" % number
565                                 seekable.seekChapter(number)
566
567 #       MENU ACTIONS
568         def keyRight(self):
569                 self.sendKey(iServiceKeys.keyRight)
570
571         def keyLeft(self):
572                 self.sendKey(iServiceKeys.keyLeft)
573
574         def keyUp(self):
575                 self.sendKey(iServiceKeys.keyUp)
576
577         def keyDown(self):
578                 self.sendKey(iServiceKeys.keyDown)
579
580         def keyOk(self):
581                 if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
582                         self.toggleInfo()
583
584         def keyCancel(self):
585                 self.askLeavePlayer()
586
587         def showFileBrowser(self):
588                 if self.physicalDVD and len(self.dvd_filelist) == 0:
589                         if self.dvd_device == harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()):
590                                 self.session.openWithCallback(self.DVDdriveCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
591                         else:
592                                 self.DVDdriveCB(True)
593                 elif len(self.dvd_filelist) == 1:
594                         self.FileBrowserClosed(self.dvd_filelist[0])
595                 else:
596                         self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
597         
598         def DVDdriveCB(self, answer):
599                 if answer == True:
600                         self.FileBrowserClosed(self.dvd_device)
601                 else:
602                         self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
603                         self.physicalDVD = False
604
605         def FileBrowserClosed(self, val):
606                 curref = self.session.nav.getCurrentlyPlayingServiceReference()
607                 print "FileBrowserClosed", val
608                 if val is None:
609                         self.askLeavePlayer()
610                 else:
611                         newref = eServiceReference(4369, 0, val)
612                         print "play", newref.toString()
613                         if curref is None or curref != newref:
614                                 self.session.nav.playService(newref)
615                                 self.service = self.session.nav.getCurrentService()
616                                 print "self.service", self.service
617                                 print "cur_dlg", self.session.current_dialog
618                                 subs = self.getServiceInterface("subtitle")
619                                 if subs:
620                                         subs.enableSubtitles(self.dvdScreen.instance, None)
621
622         def exitCB(self, answer):
623                 if answer is not None:
624                         if answer[1] == "exit":
625                                 if self.service:
626                                         self.service = None
627                                 self.close()
628                         if answer[1] == "browser":
629                                 #TODO check here if a paused dvd playback is already running... then re-start it...
630                                 #else
631                                 if self.service:
632                                         self.service = None
633                                 self.showFileBrowser()
634                         else:
635                                 pass
636
637         def __onClose(self):
638                 for i in (("/proc/stb/video/aspect", self.old_aspect), ("/proc/stb/video/policy", self.old_policy), ("/proc/stb/denc/0/wss", self.old_wss)):
639                         try:
640                                 open(i[0], "w").write(i[1])
641                         except IOError:
642                                 print "restore", i[0], "failed"
643                 self.restore_infobar_seek_config()
644                 self.session.nav.playService(self.oldService)
645
646         def playLastCB(self, answer): # overwrite infobar cuesheet function
647                 print "playLastCB", answer, self.resume_point
648                 if self.service:
649                         if answer == True:
650                                 seekable = self.getSeek()
651                                 if seekable:
652                                         seekable.seekTo(self.resume_point)
653                         pause = self.service.pause()
654                         pause.unpause()
655                 self.hideAfterResume()
656
657         def showAfterCuesheetOperation(self):
658                 if not self.in_menu:
659                         self.show()
660
661         def createSummary(self):
662                 return DVDSummary
663
664 #override some InfoBarSeek functions
665         def doEof(self):
666                 self.setSeekState(self.SEEK_STATE_PLAY)
667
668         def calcRemainingTime(self):
669                 return 0
670
671 def main(session, **kwargs):
672         session.open(DVDPlayer)
673
674 def menu(menuid, **kwargs):
675         if menuid == "mainmenu":
676                 return [(_("DVD Player"), main, "dvd_player", 46)]
677         return []
678
679 from Plugins.Plugin import PluginDescriptor
680
681 def filescan_open(list, session, **kwargs):
682         if len(list) == 1 and list[0].mimetype == "video/x-dvd":
683                 splitted = list[0].path.split('/')
684                 print "splitted", splitted
685                 if len(splitted) > 2:
686                         if splitted[1] == 'autofs':
687                                 session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
688                                 return
689                         else:
690                                 print "splitted[0]", splitted[1]
691         else:
692                 dvd_filelist = []
693                 for x in list:
694                         if x.mimetype == "video/x-dvd-iso":
695                                 dvd_filelist.append(x.path)
696                         if x.mimetype == "video/x-dvd":
697                                 dvd_filelist.append(x.path.rsplit('/',1)[0])                    
698                 session.open(DVDPlayer, dvd_filelist=dvd_filelist)
699
700 def filescan(**kwargs):
701         from Components.Scanner import Scanner, ScanPath
702
703         # Overwrite checkFile to only detect local
704         class LocalScanner(Scanner):
705                 def checkFile(self, file):
706                         return fileExists(file.path)
707
708         return [
709                 LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
710                         paths_to_scan =
711                                 [
712                                         ScanPath(path = "video_ts", with_subdirs = False),
713                                         ScanPath(path = "", with_subdirs = False),
714                                 ],
715                         name = "DVD",
716                         description = "Play DVD",
717                         openfnc = filescan_open,
718                 )]              
719
720 def Plugins(**kwargs):
721         return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
722                         PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]