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