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