X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/f7ba19535c38284fff0fcb4c218aaa5f5513dc57..c18bde2f75df7aa93eefbaf866d28fe1a5d290b8:/lib/python/Plugins/Extensions/DVDBurn/TitleList.py?ds=sidebyside diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py old mode 100644 new mode 100755 index efbab91a..2cbeb633 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -1,179 +1,381 @@ -import DVDProject, DVDTitle, TitleList, TitleCutter - +import DVDProject, TitleList, TitleCutter, TitleProperties, ProjectSettings, DVDToolbox, Process from Screens.Screen import Screen +from Screens.ChoiceBox import ChoiceBox +from Screens.InputBox import InputBox +from Screens.MessageBox import MessageBox +from Screens.HelpMenu import HelpableScreen +from Screens.TaskView import JobView +from Components.Task import job_manager from Components.ActionMap import HelpableActionMap, ActionMap from Components.Sources.List import List from Components.Sources.StaticText import StaticText -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT - -class TitleList(Screen): +from Components.Sources.Progress import Progress +from Components.MultiContent import MultiContentEntryText +from Components.Label import MultiColorLabel +from enigma import gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT +from Tools.Directories import resolveFilename, SCOPE_PLUGINS +class TitleList(Screen, HelpableScreen): skin = """ - - - - - - - - - - - - - - + + + + + + + + + + + + + + {"template": [ + MultiContentEntryText(pos = (0, 0), size = (360, 20), font = 0, flags = RT_HALIGN_LEFT, text = 1), # index 1 Title, + MultiContentEntryText(pos = (0, 20), size = (360, 17), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 description, + MultiContentEntryText(pos = (366, 6), size = (152, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 3), # index 3 channel, + MultiContentEntryText(pos = (366, 20), size = (102, 17), font = 1, flags = RT_HALIGN_RIGHT, text = 4), # index 4 begin time, + MultiContentEntryText(pos = (470, 20), size = (48, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # index 5 duration, + ], + "fonts": [gFont("Regular", 20), gFont("Regular", 14)], + "itemHeight": 37 + } + + + + + + + + + + + """ def __init__(self, session, project = None): Screen.__init__(self, session) - - if project is not None: - self.project = project - else: - self.newProject() - + HelpableScreen.__init__(self) + self["titleactions"] = HelpableActionMap(self, "DVDTitleList", { - "addTitle": (self.addTitle, _("Add a new title"), _("Add title...")), - "editTitle": (self.editTitle, _("Edit current title"), _("Edit title...")), + "addTitle": (self.addTitle, _("Add a new title"), _("Add title")), + "titleProperties": (self.titleProperties, _("Properties of current title"), _("Title properties")), "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")), - "saveProject": (self.saveProject, _("Save current project to disk"), _("Save...")), - "burnProject": (self.burnProject, _("Burn DVD"), _("Burn")), + "settings": (self.settings, _("Collection settings"), _("Settings")), + "burnProject": (self.askBurnProject, _("Burn DVD"), _("Burn DVD")), }) - self["key_red"] = StaticText(_("Add title")) - self["key_green"] = StaticText(_("Edit title")) - self["key_yellow"] = StaticText(_("Remove title")) - self["key_blue"] = StaticText(_("Save")) - - self["title_label"] = StaticText(_("Table of content to be burned to DVD:")) - self["statusbar"] = StaticText(_("When complete, press Key 0 to burn the collection!")) + self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions", + { + "contextMenu": (self.showMenu, _("menu")), + }) self["actions"] = ActionMap(["OkCancelActions"], { "cancel": self.leave }) - #Action("addTitle", self.addTitle) - - self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)]) - self.updateTitleList() - - #self["addTitle"] = ActionButton("titleactions", "addTitle") - #self["editTitle"] = ActionButton("titleactions", "editTitle") - #self["removeCurrentTitle"] = ActionButton("titleactions", "removeCurrentTitle") - #self["saveProject"] = ActionButton("titleactions", "saveProject") - #self["burnProject"] = ActionButton("titleactions", "burnProject") + self["key_red"] = StaticText() + self["key_green"] = StaticText(_("Add title")) + self["key_yellow"] = StaticText() + self["key_blue"] = StaticText(_("Settings")) + + self["title_label"] = StaticText() + self["error_label"] = StaticText() + self["space_label_single"] = StaticText() + self["space_label_dual"] = StaticText() + self["hint"] = StaticText(_("Advanced Options")) + self["medium_label"] = MultiColorLabel() + self["space_bar_single"] = Progress() + self["space_bar_dual"] = Progress() + + self["titles"] = List([]) + self.previous_size = 0 + if project is not None: + self.project = project + else: + self.newProject() + self.onLayoutFinish.append(self.layoutFinished) + + def layoutFinished(self): + self.setTitle(_("DVD Titlelist")) + + def checkBackgroundJobs(self): + for job in job_manager.getPendingJobs(): + print "type(job):", type(job) + print "Process.DVDJob:", Process.DVDJob + if type(job) == Process.DVDJob: + self.backgroundJob = job + return + self.backgroundJob = None + + def showMenu(self): + menu = [] + self.checkBackgroundJobs() + if self.backgroundJob: + j = self.backgroundJob + menu.append(("%s: %s (%d%%)" % (j.getStatustext(), j.name, int(100*j.progress/float(j.end))), self.showBackgroundJob)) + menu.append((_("DVD media toolbox"), self.toolbox)) + if self.project.settings.output.getValue() == "dvd": + if len(self["titles"].list): + menu.append((_("Burn DVD"), self.burnProject)) + elif self.project.settings.output.getValue() == "iso": + menu.append((_("Create DVD-ISO"), self.burnProject)) + menu.append((_("Burn existing image to DVD"), self.selectImage)) + if len(self["titles"].list): + menu.append((_("Preview menu"), self.previewMenu)) + menu.append((_("Edit chapters of current title"), self.editTitle)) + menu.append((_("Reset and renumerate title names"), self.resetTitles)) + menu.append((_("Exit"), self.leave)) + self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu) + + def menuCallback(self, choice): + if choice: + choice[1]() + + def showBackgroundJob(self): + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, self.backgroundJob) + self.backgroundJob = None + + def titleProperties(self): + if self.getCurrentTitle(): + self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex()) + + def selectImage(self): + self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings) def newProject(self): self.project = DVDProject.DVDProject() - self.project.titles = [ ] + if self.loadTemplate(): + self.project.session = self.session + self.settingsCB() def addTitle(self): from Screens.MovieSelection import MovieSelection - self.session.openWithCallback(self.selectedSource, MovieSelection) - - def selectedSource(self, source): + from Components.ActionMap import HelpableActionMap + class DVDMovieSelection(MovieSelection): + skin = """ + + + + + + + + + + + ShortDescription + + + Duration + AsLength + + + RecordServiceName + + + ExtendedDescription + + + """ + def __init__(self, session): + MovieSelection.__init__(self, session) + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Add")) + self["key_yellow"] = StaticText(_("Edit title")) + self["ColorActions"] = HelpableActionMap(self, "ColorActions", + { + "red": (self.close, _("Close title selection")), + "green": (self.insertWithoutEdit, ("insert without cutlist editor")), + "yellow": (self.movieSelected, _("Add a new title")) + }) + def updateTags(self): + pass + def doContext(self): + print "context menu forbidden inside DVDBurn to prevent calling multiple instances" + def insertWithoutEdit(self): + current = self.getCurrent() + if current is not None: + current.edit = False + self.close(current) + def movieSelected(self): + current = self.getCurrent() + if current is not None: + current.edit = True + self.close(current) + self.session.openWithCallback(self.selectedSource, DVDMovieSelection) + + def selectedSource(self, source = None): if source is None: return None + if not source.getPath().endswith(".ts"): + self.session.open(MessageBox,text = _("You can only burn Dreambox recordings!"), type = MessageBox.TYPE_ERROR) + return None t = self.project.addService(source) - self.updateTitleList() - - self.editTitle(t) + try: + editor = source.edit + except AttributeError: + editor = True + self.editTitle(t, editor) def removeCurrentTitle(self): title = self.getCurrentTitle() + self.removeTitle(title) + + def removeTitle(self, title): if title is not None: self.project.titles.remove(title) self.updateTitleList() - def saveProject(self): - pass + def toolbox(self): + self.session.open(DVDToolbox.DVDToolbox) + + def settings(self): + self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project) - def burnProject(self): - print "producing final cue sheet:" - cue = self.produceFinalCuesheet() - import Process - job = Process.Burn(self.session, cue) - print cue - from Screens.TaskView import JobView - self.session.open(JobView, job) + def settingsCB(self, update=True): + if not update: + return + self.updateTitleList() + + def loadTemplate(self): + filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVD.ddvdp.xml" + if self.project.load(filename): + self["error_label"].setText("") + return True + else: + self["error_label"].setText(self.project.error) + return False + + def askBurnProject(self): + if len(self["titles"].list): + self.session.openWithCallback(self.burnProject,MessageBox,text = _("Do you want to burn this collection to DVD medium?"), type = MessageBox.TYPE_YESNO) + + def burnProject(self, answer=True): + if not answer: + return + if self.project.settings.authormode.getValue() == "data_ts": + job = Process.DVDdataJob(self.project) + job_manager.AddJob(job) + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, job) + else: + job = Process.DVDJob(self.project) + job_manager.AddJob(job) + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, job) + + def burnISO(self, path, scope, configRef): + if path: + job = Process.DVDisoJob(self.project, path) + job_manager.AddJob(job) + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, job) + + def JobViewCB(self, in_background): + job_manager.in_background = in_background + + def previewMenu(self): + job = Process.DVDJob(self.project, menupreview=True) + job_manager.in_background = False + job_manager.AddJob(job) def updateTitleList(self): - res = [ ] + list = [ ] for title in self.project.titles: - a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 400, 50, 0, RT_HALIGN_LEFT, title.name) ] - res.append(a) - - self["titles"].list = res + list.append((title, title.properties.menutitle.getValue(), title.properties.menusubtitle.getValue(), title.DVBchannel, title.formatDVDmenuText("$D.$M.$Y, $T", 0), title.formatDVDmenuText("$l", 0))) + self["titles"].list = list + self.updateSize() + if len(list): + self["key_red"].text = _("Remove title") + self["key_yellow"].text = _("Title properties") + self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":" + else: + self["key_red"].text = "" + self["key_yellow"].text = "" + self["title_label"].text = _("Please add titles to the compilation.") + + def updateSize(self): + size = self.project.size/(1024*1024) + MAX_DL = self.project.MAX_DL-100 + MAX_SL = self.project.MAX_SL-100 + print "updateSize:", size, "MAX_DL:", MAX_DL, "MAX_SL:", MAX_SL + if size > MAX_DL: + percent = 100 * size / float(MAX_DL) + self["space_label_dual"].text = "%d MB (%.2f%%)" % (size, percent) + self["space_bar_dual"].value = int(percent) + self["space_bar_single"].value = 100 + self["space_label_single"].text = "" + self["medium_label"].setText(_("Exceeds dual layer medium!")) + self["medium_label"].setForegroundColorNum(2) + if self.previous_size < MAX_DL: + self.session.open(MessageBox,text = _("Exceeds dual layer medium!"), type = MessageBox.TYPE_ERROR) + elif size > MAX_SL: + percent = 100 * size / float(MAX_DL) + self["space_label_dual"].text = "%d MB (%.2f%%)" % (size, percent) + self["space_bar_dual"].value = int(percent) + self["space_bar_single"].value = 100 + self["space_label_single"].text = "" + self["medium_label"].setText(_("Required medium type:") + " " + _("DUAL LAYER DVD") + ", %d MB " % (MAX_DL - size) + _("free")) + self["medium_label"].setForegroundColorNum(1) + if self.previous_size < MAX_SL: + self.session.open(MessageBox, text = _("Your collection exceeds the size of a single layer medium, you will need a blank dual layer DVD!"), timeout = 10, type = MessageBox.TYPE_INFO) + elif size < MAX_SL: + percent = 100 * size / float(MAX_SL) + self["space_label_single"].text = "%d MB (%.2f%%)" % (size, percent) + self["space_bar_single"].value = int(percent) + self["space_bar_dual"].value = 0 + self["space_label_dual"].text = "" + self["medium_label"].setText(_("Required medium type:") + " " + _("SINGLE LAYER DVD") + ", %d MB " % (MAX_SL - size) + _("free")) + self["medium_label"].setForegroundColorNum(0) + self.previous_size = size def getCurrentTitle(self): t = self["titles"].getCurrent() return t and t[0] - def editTitle(self, title = None): + def editTitle(self, title = None, editor = True): t = title or self.getCurrentTitle() if t is not None: self.current_edit_title = t - self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t) + if editor: + self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t) + else: + self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t) def titleEditDone(self, cutlist): t = self.current_edit_title - t.cutlist = cutlist - print "title edit of %s done, resulting cutlist:" % (t.source.toString()), t.cutlist - - def leave(self): - self.close() + t.titleEditDone(cutlist) + if t.VideoType != 0: + self.session.openWithCallback(self.DVDformatCB,MessageBox,text = _("The DVD standard doesn't support H.264 (HDTV) video streams. Do you want to create a Dreambox format data DVD (which will not play in stand-alone DVD players) instead?"), type = MessageBox.TYPE_YESNO) + else: + self.updateTitleList() - def produceFinalCuesheet(self): - res = [ ] + def resetTitles(self): + count = 0 for title in self.project.titles: - path = title.source.getPath() - print ">>> path:", path - cutlist = title.cutlist - - # our demuxer expects *stricly* IN,OUT lists. - first = True - currently_in = False - CUT_TYPE_IN = 0 - CUT_TYPE_OUT = 1 - CUT_TYPE_MARK = 2 - CUT_TYPE_LAST = 3 - - accumulated_in = 0 - accumulated_at = 0 - last_in = 0 - - res_cutlist = [ ] - - res_chaptermarks = [0] - - for (pts, type) in cutlist: - if first and type == CUT_TYPE_OUT: # first mark is "out" - res_cutlist.append(0) # emulate "in" at first - currently_in = True - - first = False - - if type == CUT_TYPE_IN and not currently_in: - res_cutlist.append(pts) - last_in = pts - currently_in = True - - if type == CUT_TYPE_OUT and currently_in: - res_cutlist.append(pts) - - # accumulate the segment - accumulated_in += pts - last_in - accumulated_at = pts - currently_in = False + count += 1 + title.initDVDmenuText(count) + self.updateTitleList() - if type == CUT_TYPE_MARK and currently_in: - # relocate chaptermark against "in" time. This is not 100% accurate, - # as the in/out points are not. - res_chaptermarks.append(pts - accumulated_at + accumulated_in) + def DVDformatCB(self, answer): + t = self.current_edit_title + if answer == True: + self.project.settings.authormode.setValue("data_ts") + self.updateTitleList() + else: + self.removeTitle(t) - res.append( (path, res_cutlist, res_chaptermarks) ) + def leave(self, close = False): + if not len(self["titles"].list) or close: + self.close() + else: + self.session.openWithCallback(self.exitCB, MessageBox,text = _("Your current collection will get lost!") + "\n" + _("Do you really want to exit?"), type = MessageBox.TYPE_YESNO) - return res + def exitCB(self, answer): + print "exitCB", answer + if answer is not None and answer: + self.close() \ No newline at end of file