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