from os import path as os_path, remove as os_remove, listdir as os_listdir, system
from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys, getDesktop
from Screens.Screen import Screen
from Screens.MessageBox import MessageBox
from Screens.ChoiceBox import ChoiceBox
from Screens.HelpMenu import HelpableScreen
from Screens.InfoBarGenerics import InfoBarSeek, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarShowHide, InfoBarNotifications
from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
from Components.Label import Label
from Components.Pixmap import Pixmap
from Components.FileList import FileList
from Components.MenuList import MenuList
from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
from Components.config import config
from Tools.Directories import pathExists, fileExists
from Components.Harddisk import harddiskmanager
import servicedvd # load c++ part of dvd player plugin
lastpath = ""
class FileBrowser(Screen):
skin = """
"""
def __init__(self, session, dvd_filelist = [ ]):
Screen.__init__(self, session)
self.dvd_filelist = dvd_filelist
if len(dvd_filelist):
self["filelist"] = MenuList(self.dvd_filelist)
else:
global lastpath
if lastpath is not None:
currDir = lastpath + "/"
else:
currDir = "/media/dvd/"
if not pathExists(currDir):
currDir = "/"
self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(iso)", useServiceRef = True)
self["filelist"] = self.filelist
self["FilelistActions"] = ActionMap(["OkCancelActions"],
{
"ok": self.ok,
"cancel": self.exit
})
def ok(self):
if len(self.dvd_filelist):
print "OK " + self["filelist"].getCurrent()
self.close(self["filelist"].getCurrent())
else:
global lastpath
filename = self["filelist"].getFilename()
if filename is not None:
if filename.upper().endswith("VIDEO_TS/"):
print "dvd structure found, trying to open..."
dvdpath = filename[0:-9]
lastpath = (dvdpath.rstrip("/").rsplit("/",1))[0]
print "lastpath video_ts/=", lastpath
self.close(dvdpath)
return
if self["filelist"].canDescent(): # isDir
self["filelist"].descent()
pathname = self["filelist"].getCurrentDirectory() or ""
if fileExists(pathname+"VIDEO_TS.IFO"):
print "dvd structure found, trying to open..."
lastpath = (pathname.rstrip("/").rsplit("/",1))[0]
print "lastpath video_ts.ifo=", lastpath
self.close(pathname)
else:
lastpath = filename[0:filename.rfind("/")]
print "lastpath directory=", lastpath
self.close(filename)
def exit(self):
self.close(None)
class DVDSummary(Screen):
skin = """
Name
Position
Position
"""
def __init__(self, session, parent):
Screen.__init__(self, session, parent)
self["DVDPlayer"] = Label("DVD Player")
self["Title"] = Label("")
self["Time"] = Label("")
self["Chapter"] = Label("")
def updateChapter(self, chapter):
self["Chapter"].setText(chapter)
def setTitle(self, title):
self["Title"].setText(title)
class DVDOverlay(Screen):
def __init__(self, session, args = None):
desktop_size = getDesktop(0).size()
DVDOverlay.skin = """""" %(desktop_size.width(), desktop_size.height())
Screen.__init__(self, session)
class ChapterZap(Screen):
skin = """
"""
def quit(self):
self.Timer.stop()
self.close(0)
def keyOK(self):
self.Timer.stop()
self.close(int(self["number"].getText()))
def keyNumberGlobal(self, number):
self.Timer.start(3000, True) #reset timer
self.field = self.field + str(number)
self["number"].setText(self.field)
if len(self.field) >= 4:
self.keyOK()
def __init__(self, session, number):
Screen.__init__(self, session)
self.field = str(number)
self["chapter"] = Label(_("Chapter:"))
self["number"] = Label(self.field)
self["actions"] = NumberActionMap( [ "SetupActions" ],
{
"cancel": self.quit,
"ok": self.keyOK,
"1": self.keyNumberGlobal,
"2": self.keyNumberGlobal,
"3": self.keyNumberGlobal,
"4": self.keyNumberGlobal,
"5": self.keyNumberGlobal,
"6": self.keyNumberGlobal,
"7": self.keyNumberGlobal,
"8": self.keyNumberGlobal,
"9": self.keyNumberGlobal,
"0": self.keyNumberGlobal
})
self.Timer = eTimer()
self.Timer.callback.append(self.keyOK)
self.Timer.start(3000, True)
class DVDPlayer(Screen, InfoBarBase, InfoBarNotifications, InfoBarSeek, InfoBarPVRState, InfoBarShowHide, HelpableScreen, InfoBarCueSheetSupport):
# ALLOW_SUSPEND = True
ENABLE_RESUME_SUPPORT = True
skin = """
Name
HasTelext
Position,ShowHours
Gauge
Remaining,Negate,ShowHours
"""
def save_infobar_seek_config(self):
self.saved_config_speeds_forward = config.seek.speeds_forward.value
self.saved_config_speeds_backward = config.seek.speeds_backward.value
self.saved_config_enter_forward = config.seek.enter_forward.value
self.saved_config_enter_backward = config.seek.enter_backward.value
self.saved_config_seek_stepwise_minspeed = config.seek.stepwise_minspeed.value
self.saved_config_seek_stepwise_repeat = config.seek.stepwise_repeat.value
self.saved_config_seek_on_pause = config.seek.on_pause.value
self.saved_config_seek_speeds_slowmotion = config.seek.speeds_slowmotion.value
def change_infobar_seek_config(self):
config.seek.speeds_forward.value = [2, 4, 8, 16, 32, 64]
config.seek.speeds_backward.value = [8, 16, 32, 64]
config.seek.speeds_slowmotion.value = [ ]
config.seek.enter_forward.value = "2"
config.seek.enter_backward.value = "2"
config.seek.stepwise_minspeed.value = "Never"
config.seek.stepwise_repeat.value = "3"
config.seek.on_pause.value = "play"
def restore_infobar_seek_config(self):
config.seek.speeds_forward.value = self.saved_config_speeds_forward
config.seek.speeds_backward.value = self.saved_config_speeds_backward
config.seek.speeds_slowmotion.value = self.saved_config_seek_speeds_slowmotion
config.seek.enter_forward.value = self.saved_config_enter_forward
config.seek.enter_backward.value = self.saved_config_enter_backward
config.seek.stepwise_minspeed.value = self.saved_config_seek_stepwise_minspeed
config.seek.stepwise_repeat.value = self.saved_config_seek_stepwise_repeat
config.seek.on_pause.value = self.saved_config_seek_on_pause
def __init__(self, session, dvd_device = None, dvd_filelist = [ ], args = None):
Screen.__init__(self, session)
InfoBarBase.__init__(self)
InfoBarNotifications.__init__(self)
InfoBarCueSheetSupport.__init__(self, actionmap = "MediaPlayerCueSheetActions")
InfoBarShowHide.__init__(self)
HelpableScreen.__init__(self)
self.save_infobar_seek_config()
self.change_infobar_seek_config()
InfoBarSeek.__init__(self, useSeekBackHack=False)
InfoBarPVRState.__init__(self)
self.dvdScreen = self.session.instantiateDialog(DVDOverlay)
self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
self.session.nav.stopService()
self["audioLabel"] = Label("n/a")
self["subtitleLabel"] = Label("")
self["angleLabel"] = Label("")
self["chapterLabel"] = Label("")
self["anglePix"] = Pixmap()
self["anglePix"].hide()
self.last_audioTuple = None
self.last_subtitleTuple = None
self.last_angleTuple = None
self.totalChapters = 0
self.currentChapter = 0
self.totalTitles = 0
self.currentTitle = 0
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
iPlayableService.evStopped: self.__serviceStopped,
iPlayableService.evUser: self.__timeUpdated,
iPlayableService.evUser+1: self.__statePlay,
iPlayableService.evUser+2: self.__statePause,
iPlayableService.evUser+3: self.__osdFFwdInfoAvail,
iPlayableService.evUser+4: self.__osdFBwdInfoAvail,
iPlayableService.evUser+5: self.__osdStringAvail,
iPlayableService.evUser+6: self.__osdAudioInfoAvail,
iPlayableService.evUser+7: self.__osdSubtitleInfoAvail,
iPlayableService.evUser+8: self.__chapterUpdated,
iPlayableService.evUser+9: self.__titleUpdated,
iPlayableService.evUser+11: self.__menuOpened,
iPlayableService.evUser+12: self.__menuClosed,
iPlayableService.evUser+13: self.__osdAngleInfoAvail
})
self["DVDPlayerDirectionActions"] = ActionMap(["DirectionActions"],
{
#MENU KEY DOWN ACTIONS
"left": self.keyLeft,
"right": self.keyRight,
"up": self.keyUp,
"down": self.keyDown,
#MENU KEY REPEATED ACTIONS
"leftRepeated": self.doNothing,
"rightRepeated": self.doNothing,
"upRepeated": self.doNothing,
"downRepeated": self.doNothing,
#MENU KEY UP ACTIONS
"leftUp": self.doNothing,
"rightUp": self.doNothing,
"upUp": self.doNothing,
"downUp": self.doNothing,
})
self["OkCancelActions"] = ActionMap(["OkCancelActions"],
{
"ok": self.keyOk,
"cancel": self.keyCancel,
})
self["DVDPlayerPlaybackActions"] = HelpableActionMap(self, "DVDPlayerActions",
{
#PLAYER ACTIONS
"dvdMenu": (self.enterDVDMenu, _("show DVD main menu")),
"toggleInfo": (self.toggleInfo, _("toggle time, chapter, audio, subtitle info")),
"nextChapter": (self.nextChapter, _("forward to the next chapter")),
"prevChapter": (self.prevChapter, _("rewind to the previous chapter")),
"nextTitle": (self.nextTitle, _("jump forward to the next title")),
"prevTitle": (self.prevTitle, _("jump back to the previous title")),
"tv": (self.askLeavePlayer, _("exit DVD player or return to file browser")),
"dvdAudioMenu": (self.enterDVDAudioMenu, _("(show optional DVD audio menu)")),
"nextAudioTrack": (self.nextAudioTrack, _("switch to the next audio track")),
"nextSubtitleTrack": (self.nextSubtitleTrack, _("switch to the next subtitle language")),
"nextAngle": (self.nextAngle, _("switch to the next angle")),
"seekBeginning": self.seekBeginning,
}, -2)
self["NumberActions"] = NumberActionMap( [ "NumberActions"],
{
"1": self.keyNumberGlobal,
"2": self.keyNumberGlobal,
"3": self.keyNumberGlobal,
"4": self.keyNumberGlobal,
"5": self.keyNumberGlobal,
"6": self.keyNumberGlobal,
"7": self.keyNumberGlobal,
"8": self.keyNumberGlobal,
"9": self.keyNumberGlobal,
"0": self.keyNumberGlobal,
})
self.onClose.append(self.__onClose)
from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
hotplugNotifier.append(self.hotplugCB)
if dvd_device:
self.physicalDVD = True
else:
self.scanHotplug()
self.dvd_filelist = dvd_filelist
self.onFirstExecBegin.append(self.opened)
self.service = None
self.in_menu = False
def keyNumberGlobal(self, number):
print "You pressed number " + str(number)
self.session.openWithCallback(self.numberEntered, ChapterZap, number)
def numberEntered(self, retval):
# print self.servicelist
if retval > 0:
self.zapToNumber(retval)
def getServiceInterface(self, iface):
service = self.service
if service:
attr = getattr(service, iface, None)
if callable(attr):
return attr()
return None
def __serviceStopped(self):
self.dvdScreen.hide()
subs = self.getServiceInterface("subtitle")
if subs:
subs.disableSubtitles(self.session.current_dialog.instance)
def serviceStarted(self): #override InfoBarShowHide function
self.dvdScreen.show()
def doEofInternal(self, playing):
if self.in_menu:
self.hide()
def __menuOpened(self):
self.hide()
self.in_menu = True
self["NumberActions"].setEnabled(False)
def __menuClosed(self):
self.show()
self.in_menu = False
self["NumberActions"].setEnabled(True)
def setChapterLabel(self):
chapterLCD = "Menu"
chapterOSD = "DVD Menu"
if self.currentTitle > 0:
chapterLCD = "%s %d" % (_("Chap."), self.currentChapter)
chapterOSD = "DVD %s %d/%d" % (_("Chapter"), self.currentChapter, self.totalChapters)
chapterOSD += " (%s %d/%d)" % (_("Title"), self.currentTitle, self.totalTitles)
self["chapterLabel"].setText(chapterOSD)
try:
self.session.summary.updateChapter(chapterLCD)
except:
pass
def doNothing(self):
pass
def toggleInfo(self):
if not self.in_menu:
self.toggleShow()
print "toggleInfo"
def __timeUpdated(self):
print "timeUpdated"
def __statePlay(self):
print "statePlay"
def __statePause(self):
print "statePause"
def __osdFFwdInfoAvail(self):
self.setChapterLabel()
print "FFwdInfoAvail"
def __osdFBwdInfoAvail(self):
self.setChapterLabel()
print "FBwdInfoAvail"
def __osdStringAvail(self):
print "StringAvail"
def __osdAudioInfoAvail(self):
info = self.getServiceInterface("info")
audioTuple = info and info.getInfoObject(iServiceInformation.sUser+6)
print "AudioInfoAvail ", repr(audioTuple)
if audioTuple:
audioString = "%d: %s (%s)" % (audioTuple[0],audioTuple[1],audioTuple[2])
self["audioLabel"].setText(audioString)
if audioTuple != self.last_audioTuple and not self.in_menu:
self.doShow()
self.last_audioTuple = audioTuple
def __osdSubtitleInfoAvail(self):
info = self.getServiceInterface("info")
subtitleTuple = info and info.getInfoObject(iServiceInformation.sUser+7)
print "SubtitleInfoAvail ", repr(subtitleTuple)
if subtitleTuple:
subtitleString = ""
if subtitleTuple[0] is not 0:
subtitleString = "%d: %s" % (subtitleTuple[0],subtitleTuple[1])
self["subtitleLabel"].setText(subtitleString)
if subtitleTuple != self.last_subtitleTuple and not self.in_menu:
self.doShow()
self.last_subtitleTuple = subtitleTuple
def __osdAngleInfoAvail(self):
info = self.getServiceInterface("info")
angleTuple = info and info.getInfoObject(iServiceInformation.sUser+8)
print "AngleInfoAvail ", repr(angleTuple)
if angleTuple:
angleString = ""
if angleTuple[1] > 1:
angleString = "%d / %d" % (angleTuple[0],angleTuple[1])
self["anglePix"].show()
else:
self["anglePix"].hide()
self["angleLabel"].setText(angleString)
if angleTuple != self.last_angleTuple and not self.in_menu:
self.doShow()
self.last_angleTuple = angleTuple
def __chapterUpdated(self):
info = self.getServiceInterface("info")
if info:
self.currentChapter = info.getInfo(iServiceInformation.sCurrentChapter)
self.totalChapters = info.getInfo(iServiceInformation.sTotalChapters)
self.setChapterLabel()
print "__chapterUpdated: %d/%d" % (self.currentChapter, self.totalChapters)
def __titleUpdated(self):
info = self.getServiceInterface("info")
if info:
self.currentTitle = info.getInfo(iServiceInformation.sCurrentTitle)
self.totalTitles = info.getInfo(iServiceInformation.sTotalTitles)
self.setChapterLabel()
print "__titleUpdated: %d/%d" % (self.currentTitle, self.totalTitles)
if not self.in_menu:
self.doShow()
def askLeavePlayer(self):
choices = [(_("Exit"), "exit"), (_("Continue playing"), "play")]
if True or not self.physicalDVD:
choices.insert(1,(_("Return to file browser"), "browser"))
if self.physicalDVD and not self.session.nav.getCurrentlyPlayingServiceReference().toString().endswith(harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())):
choices.insert(0,(_("Play DVD"), "playPhysical" ))
self.session.openWithCallback(self.exitCB, ChoiceBox, title=_("Leave DVD Player?"), list = choices)
def sendKey(self, key):
keys = self.getServiceInterface("keys")
if keys:
keys.keyPressed(key)
return keys
def nextAudioTrack(self):
self.sendKey(iServiceKeys.keyUser)
def nextSubtitleTrack(self):
self.sendKey(iServiceKeys.keyUser+1)
def enterDVDAudioMenu(self):
self.sendKey(iServiceKeys.keyUser+2)
def nextChapter(self):
self.sendKey(iServiceKeys.keyUser+3)
def prevChapter(self):
self.sendKey(iServiceKeys.keyUser+4)
def nextTitle(self):
self.sendKey(iServiceKeys.keyUser+5)
def prevTitle(self):
self.sendKey(iServiceKeys.keyUser+6)
def enterDVDMenu(self):
self.sendKey(iServiceKeys.keyUser+7)
def nextAngle(self):
self.sendKey(iServiceKeys.keyUser+8)
def seekBeginning(self):
if self.service:
seekable = self.getSeek()
if seekable:
seekable.seekTo(0)
def zapToNumber(self, number):
if self.service:
seekable = self.getSeek()
if seekable:
print "seek to chapter %d" % number
seekable.seekChapter(number)
# MENU ACTIONS
def keyRight(self):
self.sendKey(iServiceKeys.keyRight)
def keyLeft(self):
self.sendKey(iServiceKeys.keyLeft)
def keyUp(self):
self.sendKey(iServiceKeys.keyUp)
def keyDown(self):
self.sendKey(iServiceKeys.keyDown)
def keyOk(self):
if self.sendKey(iServiceKeys.keyOk) and not self.in_menu:
self.toggleInfo()
def keyCancel(self):
self.askLeavePlayer()
def opened(self):
if len(self.dvd_filelist) == 1:
# opened via autoplay
self.FileBrowserClosed(self.dvd_filelist[0])
elif self.physicalDVD:
# opened from menu with dvd in drive
self.session.openWithCallback(self.playPhysicalCB, MessageBox, text=_("Do you want to play DVD in drive?"), timeout=5 )
else:
# opened from menu without dvd in drive
self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, self.dvd_filelist)
def playPhysicalCB(self, answer):
if answer == True:
self.FileBrowserClosed(harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD()))
else:
self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
def FileBrowserClosed(self, val):
curref = self.session.nav.getCurrentlyPlayingServiceReference()
print "FileBrowserClosed", val
if val is None:
self.askLeavePlayer()
else:
newref = eServiceReference(4369, 0, val)
print "play", newref.toString()
if curref is None or curref != newref:
self.session.nav.playService(newref)
self.service = self.session.nav.getCurrentService()
print "self.service", self.service
print "cur_dlg", self.session.current_dialog
subs = self.getServiceInterface("subtitle")
if subs:
subs.enableSubtitles(self.dvdScreen.instance, None)
def exitCB(self, answer):
if answer is not None:
if answer[1] == "exit":
if self.service:
self.service = None
self.close()
if answer[1] == "browser":
#TODO check here if a paused dvd playback is already running... then re-start it...
#else
if self.service:
self.service = None
self.session.openWithCallback(self.FileBrowserClosed, FileBrowser)
if answer[1] == "playPhysical":
if self.service:
self.service = None
self.playPhysicalCB(True)
else:
pass
def __onClose(self):
self.restore_infobar_seek_config()
self.session.nav.playService(self.oldService)
from Plugins.SystemPlugins.Hotplug.plugin import hotplugNotifier
hotplugNotifier.remove(self.hotplugCB)
def playLastCB(self, answer): # overwrite infobar cuesheet function
print "playLastCB", answer, self.resume_point
if self.service:
if answer == True:
seekable = self.getSeek()
if seekable:
seekable.seekTo(self.resume_point)
pause = self.service.pause()
pause.unpause()
self.hideAfterResume()
def showAfterCuesheetOperation(self):
if not self.in_menu:
self.show()
def createSummary(self):
return DVDSummary
#override some InfoBarSeek functions
def doEof(self):
self.setSeekState(self.SEEK_STATE_PLAY)
def calcRemainingTime(self):
return 0
def hotplugCB(self, dev, media_state):
print "[hotplugCB]", dev, media_state
if dev == harddiskmanager.getCD():
if media_state == "1":
self.scanHotplug()
else:
self.physicalDVD = False
def scanHotplug(self):
devicepath = harddiskmanager.getAutofsMountpoint(harddiskmanager.getCD())
if pathExists(devicepath):
from Components.Scanner import scanDevice
res = scanDevice(devicepath)
list = [ (r.description, r, res[r], self.session) for r in res ]
if list:
(desc, scanner, files, session) = list[0]
for file in files:
print file
if file.mimetype == "video/x-dvd":
print "physical dvd found:", devicepath
self.physicalDVD = True
return
self.physicalDVD = False
def main(session, **kwargs):
session.open(DVDPlayer)
def menu(menuid, **kwargs):
if menuid == "mainmenu":
return [(_("DVD Player"), main, "dvd_player", 46)]
return []
from Plugins.Plugin import PluginDescriptor
def filescan_open(list, session, **kwargs):
if len(list) == 1 and list[0].mimetype == "video/x-dvd":
splitted = list[0].path.split('/')
print "splitted", splitted
if len(splitted) > 2:
if splitted[1] == 'autofs':
session.open(DVDPlayer, dvd_device="/dev/%s" %(splitted[2]))
return
else:
print "splitted[0]", splitted[1]
else:
dvd_filelist = []
for x in list:
if x.mimetype == "video/x-dvd-iso":
dvd_filelist.append(x.path)
if x.mimetype == "video/x-dvd":
dvd_filelist.append(x.path.rsplit('/',1)[0])
session.open(DVDPlayer, dvd_filelist=dvd_filelist)
def filescan(**kwargs):
from Components.Scanner import Scanner, ScanPath
# Overwrite checkFile to only detect local
class LocalScanner(Scanner):
def checkFile(self, file):
return fileExists(file.path)
return [
LocalScanner(mimetypes = ["video/x-dvd","video/x-dvd-iso"],
paths_to_scan =
[
ScanPath(path = "video_ts", with_subdirs = False),
ScanPath(path = "", with_subdirs = False),
],
name = "DVD",
description = _("Play DVD"),
openfnc = filescan_open,
)]
def Plugins(**kwargs):
return [PluginDescriptor(name = "DVDPlayer", description = "Play DVDs", where = PluginDescriptor.WHERE_MENU, fnc = menu),
PluginDescriptor(where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)]