use multiple titlesets for dvd authoring which allows correct burning of videos with...
authorFraxinas <andreas.frisch@multimedia-labs.de>
Tue, 11 Nov 2008 18:19:09 +0000 (19:19 +0100)
committerFraxinas <andreas.frisch@multimedia-labs.de>
Tue, 11 Nov 2008 18:19:09 +0000 (19:19 +0100)
introduce title properties screen. this is still a draft version.

lib/python/Plugins/Extensions/DVDBurn/DVDProject.py
lib/python/Plugins/Extensions/DVDBurn/DVDTitle.py
lib/python/Plugins/Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml
lib/python/Plugins/Extensions/DVDBurn/Makefile.am
lib/python/Plugins/Extensions/DVDBurn/Process.py
lib/python/Plugins/Extensions/DVDBurn/TitleCutter.py
lib/python/Plugins/Extensions/DVDBurn/TitleList.py
lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py [new file with mode: 0644]
lib/python/Plugins/Extensions/DVDBurn/keymap.xml

index 8d02cb226eb7d0cb78275a8d3a46b1d5bf767735..55a72c10474670020e85afb80caaa07637e3e978 100644 (file)
@@ -1,5 +1,5 @@
 from Tools.Directories import fileExists
-from Components.config import config, ConfigSubsection, ConfigInteger, ConfigYesNo, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence
+from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence
 
 class ConfigColor(ConfigSequence):
        def __init__(self):
index 1bfb3d646beeb58d658694e46165090eb6808ffd..1ada9ce27a3cf1a25c9645e96d365ce515b65927 100644 (file)
@@ -1,17 +1,35 @@
+from Components.config import config, ConfigSubsection, ConfigSubList, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence, ConfigYesNo
+
+class ConfigFixedText(ConfigText):
+       def __init__(self, text, visible_width=60):
+               ConfigText.__init__(self, default = text, fixed_size = True, visible_width = visible_width)
+       def handleKey(self, key):
+               pass
+
+class ConfigActiveTrack(ConfigYesNo):
+       def __init__(self, default = True):
+               ConfigYesNo.__init__(self, default)
+
 class DVDTitle:
        def __init__(self):
+               self.properties = ConfigSubsection()
+               self.properties.menutitle = ConfigText(fixed_size = False, visible_width = 80)
+               self.properties.menusubtitle = ConfigText(fixed_size = False, visible_width = 80)
+               self.DVBname = _("Title")
+               self.DVBdescr = _("Description")
+               self.DVBchannel = _("Channel")
+               self.properties.aspect = ConfigSelection(choices = [("4:3", "4:3"), ("16:9", "16:9")])
+               self.properties.widescreen = ConfigSelection(choices = [("nopanscan", "nopanscan"), ("noletterbox", "noletterbox")])
+               self.properties.audiotracks = ConfigSubList()
                self.cuesheet = [ ]
                self.source = None
-               self.name = ""
-               self.descr = ""
                self.filesize = 0
                self.estimatedDiskspace = 0
                self.inputfile = ""
                self.cutlist = [ ]
                self.chaptermarks = [ ]
-               self.audiotracks = [ ]
                self.timeCreate = None
-               self.sVideoType = -1
+               self.VideoType = -1
 
        def addService(self, service):
                from os import path
@@ -21,18 +39,61 @@ class DVDTitle:
                self.source = service
                serviceHandler = eServiceCenter.getInstance()
                info = serviceHandler.info(service)
-               self.descr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or ""
+               sDescr = info and " " + info.getInfoString(service, iServiceInformation.sDescription) or ""
+               self.DVBdescr = sDescr
                sTimeCreate = info.getInfo(service, iServiceInformation.sTimeCreate)
                if sTimeCreate > 1:
                        self.timeCreate = localtime(sTimeCreate)
                serviceref = ServiceReference(info.getInfoString(service, iServiceInformation.sServiceref))
-               self.name = info and info.getName(service) or "Title" + t.descr
-               self.channel = serviceref.getServiceName()
+               name = info and info.getName(service) or "Title" + sDescr
+               self.DVBname = name
+               self.DVBchannel = serviceref.getServiceName()
                self.inputfile = service.getPath()
                self.filesize = path.getsize(self.inputfile)
                self.estimatedDiskspace = self.filesize
                self.length = info.getLength(service)
 
+       def initDVDmenuText(self, project, track):
+               self.properties.menutitle.setValue(self.formatDVDmenuText(project.settings.titleformat.getValue(), track))
+               self.properties.menusubtitle.setValue(self.formatDVDmenuText(project.settings.subtitleformat.getValue(), track))
+
+       def formatDVDmenuText(self, template, track):
+               properties = self.properties
+               template = template.replace("$i", str(track))
+               template = template.replace("$t", self.DVBname)
+               template = template.replace("$d", self.DVBdescr)
+               template = template.replace("$c", str(len(self.chaptermarks)+1))
+               template = template.replace("$f", self.inputfile)
+               template = template.replace("$C", self.DVBchannel)
+               
+               #if template.find("$A") >= 0:
+               from TitleProperties import languageChoices
+               audiolist = [ ]
+               for audiotrack in self.properties.audiotracks:
+                       active = audiotrack.active.getValue()
+                       if active:
+                               trackstring = audiotrack.format.getValue()
+                               language = audiotrack.language.getValue()
+                               if languageChoices.langdict.has_key(language):
+                                       trackstring += ' (' + languageChoices.langdict[language] + ')'
+                               audiolist.append(trackstring)
+               audiostring = ', '.join(audiolist)
+               template = template.replace("$A", audiostring)
+               
+               if template.find("$l") >= 0:
+                       l = self.length
+                       lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60)
+                       template = template.replace("$l", lengthstring)
+               if self.timeCreate:
+                       template = template.replace("$Y", str(self.timeCreate[0]))
+                       template = template.replace("$M", str(self.timeCreate[1]))
+                       template = template.replace("$D", str(self.timeCreate[2]))
+                       timestring = "%d:%02d" % (self.timeCreate[3], self.timeCreate[4])
+                       template = template.replace("$T", timestring)
+               else:
+                       template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "")
+               return template
+       
        def produceFinalCuesheet(self):
                CUT_TYPE_IN = 0
                CUT_TYPE_OUT = 1
@@ -84,3 +145,13 @@ class DVDTitle:
                        while chapterpts < self.length*90000:
                                chapterpts += 90000 * 60 * minutes
                                self.chaptermarks.append(chapterpts)
+
+       def getChapterMarks(self):
+               timestamps = []
+               for p in self.chaptermarks:
+                       h = p / (90000 * 3600)
+                       m = p % (90000 * 3600) / (90000 * 60)
+                       s = p % (90000 * 60) / 90000
+                       ms = (p % 90000) / 90
+                       timestamps.append("%d:%02d:%02d.%03d" % (h, m, s, ms))
+               return timestamps
\ No newline at end of file
index d9831e63bafc35bee434ff532814892ad775d6b0..9a61214a6bd1dcb1183f4ccdd824dfe66f6fdbc5 100644 (file)
@@ -4,7 +4,7 @@
                name="Dreambox DVD record"
                authormode="menu_linked"
                titleformat="$i. $t"
-               subtitleformat="$D.$M.$Y, $T $C, $d ($c chapters)"
+               subtitleformat="$D.$M.$Y, $T $C, $d"
                vmgm="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/vmgmdream.mpg"
                menubg="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/dreamdvd_boat.jpg"
                menuaudio="/usr/lib/enigma2/python/Plugins/Extensions/DVDBurn/silence.mp2"
index cb65f56aa62ec1e3546aa2be57e7a2a9fa52337c..be89ebaa9e5f3f23ff5d5a2b6f213bb1565dae5b 100644 (file)
@@ -3,7 +3,7 @@ installdir = $(LIBDIR)/enigma2/python/Plugins/Extensions/DVDBurn
 install_PYTHON =       \
        __init__.py \
        plugin.py \
-       DVDProject.py DVDTitle.py TitleCutter.py TitleList.py Process.py ProjectSettings.py DVDToolbox.py
+       DVDProject.py DVDTitle.py TitleCutter.py TitleList.py TitleProperties.py Process.py ProjectSettings.py DVDToolbox.py
 
 install_DATA = *.xml *.jpg *.mpg *.mp2 *.png
 
index 490545966e6995bec615795bb16f31a4aa0117da..3cf874c0b3ad16265c1c9d4eb40b107bad986bb5 100644 (file)
@@ -85,23 +85,34 @@ class DemuxTask(Task):
                title = job.project.titles[job.i]
                self.global_preconditions.append(DiskspacePrecondition(title.estimatedDiskspace))
                self.setTool("/usr/bin/projectx")
-               self.generated_files = [ ]
+               self.args += [inputfile, "-demux", "-out", self.job.workspace ]
                self.end = 300
                self.prog_state = 0
                self.weighting = 1000
                self.cutfile = self.job.workspace + "/cut_%d.Xcl" % (job.i+1)
                self.cutlist = title.cutlist
-               self.args += [inputfile, "-demux", "-out", self.job.workspace ]
+               self.currentPID = None
+               self.relevantAudioPIDs = [ ]
+               self.getRelevantAudioPIDs(title)
+               self.generated_files = [ ]
+               self.mplex_streamfiles = [ ]
                if len(self.cutlist) > 1:
                        self.args += [ "-cut", self.cutfile ]
 
        def prepare(self):
                self.writeCutfile()
 
+       def getRelevantAudioPIDs(self, title):
+               for audiotrack in title.properties.audiotracks:
+                       if audiotrack.active.getValue():
+                               self.relevantAudioPIDs.append(audiotrack.pid.getValue())
+
        def processOutputLine(self, line):
                line = line[:-1]
                MSG_NEW_FILE = "---> new File: "
                MSG_PROGRESS = "[PROGRESS] "
+               MSG_NEW_MP2 = "--> MPEG Audio (0x"
+               MSG_NEW_AC3 = "--> AC-3/DTS Audio on PID "
 
                if line.startswith(MSG_NEW_FILE):
                        file = line[len(MSG_NEW_FILE):]
@@ -111,10 +122,14 @@ class DemuxTask(Task):
                elif line.startswith(MSG_PROGRESS):
                        progress = line[len(MSG_PROGRESS):]
                        self.haveProgress(progress)
+               elif line.startswith(MSG_NEW_MP2) or line.startswith(MSG_NEW_AC3):
+                       self.currentPID = str(int(line.rstrip()[-6:].rsplit('0x',1)[-1],16))
 
        def haveNewFile(self, file):
-               print "PRODUCED FILE [%s]" % file
+               print "[DemuxTask] produced file:", file
                self.generated_files.append(file)
+               if self.currentPID in self.relevantAudioPIDs or file.endswith("m2v"):
+                       self.mplex_streamfiles.append(file)
 
        def haveProgress(self, progress):
                #print "PROGRESS [%s]" % progress
@@ -131,7 +146,6 @@ class DemuxTask(Task):
                                if p > self.progress:
                                        self.progress = p
                        except ValueError:
-                               print "val error"
                                pass
 
        def writeCutfile(self):
@@ -151,8 +165,8 @@ class DemuxTask(Task):
        def cleanup(self, failed):
                if failed:
                        import os
-                       for f in self.generated_files:
-                               os.remove(f)
+                       for file in self.generated_files.itervalues():
+                               os.remove(file)
 
 class MplexTaskPostcondition(Condition):
        def check(self, task):
@@ -185,9 +199,9 @@ class MplexTask(Task):
                # we don't want the ReturncodePostcondition in this case because for right now we're just gonna ignore the fact that mplex fails with a buffer underrun error on some streams (this always at the very end)
 
        def prepare(self):
-               self.error = None                       
+               self.error = None
                if self.demux_task:
-                       self.args += self.demux_task.generated_files
+                       self.args += self.demux_task.mplex_streamfiles
 
        def processOutputLine(self, line):
                print "[MplexTask] ", line[:-1]
@@ -206,7 +220,7 @@ class RemoveESFiles(Task):
 
        def prepare(self):
                self.args += ["-f"]
-               self.args += self.demux_task.generated_files
+               self.args += self.demux_task.generated_files.values()
                self.args += [self.demux_task.cutfile]
 
 class DVDAuthorTask(Task):
@@ -411,27 +425,6 @@ class PreviewTaskPostcondition(Condition):
        def getErrorMessage(self, task):
                return "Cancel"
 
-def formatTitle(template, title, track):
-       template = template.replace("$i", str(track))
-       template = template.replace("$t", title.name)
-       template = template.replace("$d", title.descr)
-       template = template.replace("$c", str(len(title.chaptermarks)+1))
-       template = template.replace("$A", str(title.audiotracks))
-       template = template.replace("$f", title.inputfile)
-       template = template.replace("$C", title.channel)
-       l = title.length
-       lengthstring = "%d:%02d:%02d" % (l/3600, l%3600/60, l%60)
-       template = template.replace("$l", lengthstring)
-       if title.timeCreate:
-               template = template.replace("$Y", str(title.timeCreate[0]))
-               template = template.replace("$M", str(title.timeCreate[1]))
-               template = template.replace("$D", str(title.timeCreate[2]))
-               timestring = "%d:%02d" % (title.timeCreate[3], title.timeCreate[4])
-               template = template.replace("$T", timestring)
-       else:
-               template = template.replace("$Y", "").replace("$M", "").replace("$D", "").replace("$T", "")
-       return template.decode("utf-8")
-
 class ImagingPostcondition(Condition):
        def check(self, task):
                return task.returncode == 0
@@ -518,14 +511,13 @@ class MenuImageTask(Task):
                                menu_end_title = nr_titles+1
                        menu_i = 0
                        for title_no in range( menu_start_title , menu_end_title ):
-                               i = title_no-1
-                               top = s_top + ( menu_i * rowheight )
                                menu_i += 1
-                               title = self.job.project.titles[i]
-                               titleText = formatTitle(s.titleformat.getValue(), title, title_no)
+                               title = self.job.project.titles[title_no-1]
+                               top = s_top + ( menu_i * rowheight )
+                               titleText = title.formatDVDmenuText(s.titleformat.getValue(), title_no).decode("utf-8")
                                draw_bg.text((s_left,top), titleText, fill=self.Menus.color_button, font=fonts[1])
                                draw_high.text((s_left,top), titleText, fill=1, font=self.Menus.fonts[1])
-                               subtitleText = formatTitle(s.subtitleformat.getValue(), title, title_no)
+                               subtitleText = title.formatDVDmenuText(s.subtitleformat.getValue(), title_no).decode("utf-8")
                                draw_bg.text((s_left,top+36), subtitleText, fill=self.Menus.color_button, font=fonts[2])
                                bottom = top+rowheight
                                if bottom > self.Menus.imgheight:
@@ -607,7 +599,7 @@ class Menus:
                        menuoutputfilename = job.workspace+"/dvdmenu"+num+".mpg"
                        spumuxTask(job, spuxmlfilename, menubgmpgfilename, menuoutputfilename)
                
-def CreateAuthoringXML(job):
+def CreateAuthoringXML_simple(job):
        nr_titles = len(job.project.titles)
        mode = job.project.settings.authormode.getValue()
        authorxml = []
@@ -649,9 +641,7 @@ def CreateAuthoringXML(job):
                authorxml.append('   </menus>\n')
        authorxml.append('   <titles>\n')
        for i in range( nr_titles ):
-               #for audiotrack in job.project.titles[i].audiotracks:
-                       #authorxml.append('    <audio lang="'+audiotrack[0][:2]+'" format="'+audiotrack[1]+'" />\n')
-               chapters = ','.join(["%d:%02d:%02d.%03d" % (p / (90000 * 3600), p % (90000 * 3600) / (90000 * 60), p % (90000 * 60) / 90000, (p % 90000) / 90) for p in job.project.titles[i].chaptermarks])
+               chapters = ','.join(job.project.titles[i].getChapterMarks())
                title_no = i+1
                title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no)
                if job.menupreview:
@@ -677,6 +667,84 @@ def CreateAuthoringXML(job):
                f.write(x)
        f.close()
 
+def CreateAuthoringXML_multiset(job):
+       nr_titles = len(job.project.titles)
+       mode = job.project.settings.authormode.getValue()
+       authorxml = []
+       authorxml.append('<?xml version="1.0" encoding="utf-8"?>\n')
+       authorxml.append(' <dvdauthor dest="' + (job.workspace+"/dvd") + '" jumppad="yes">\n')
+       authorxml.append('  <vmgm>\n')
+       authorxml.append('   <menus>\n')
+       authorxml.append('    <video aspect="4:3"/>\n')
+       if mode.startswith("menu"):
+               for menu_count in range(1 , job.nr_menus+1):
+                       authorxml.append('    <pgc>\n')
+                       menu_start_title = (menu_count-1)*job.titles_per_menu + 1
+                       menu_end_title = (menu_count)*job.titles_per_menu + 1
+                       if menu_end_title > nr_titles:
+                               menu_end_title = nr_titles+1
+                       for i in range( menu_start_title , menu_end_title ):
+                               authorxml.append('     <button name="button' + (str(i).zfill(2)) + '"> jump titleset ' + str(i) +' title 1; </button>\n')
+                       if menu_count > 1:
+                               authorxml.append('     <button name="button_prev"> jump menu ' + str(menu_count-1) + '; </button>\n')
+                       if menu_count < job.nr_menus:
+                               authorxml.append('     <button name="button_next"> jump menu ' + str(menu_count+1) + '; </button>\n')
+                       menuoutputfilename = job.workspace+"/dvdmenu"+str(menu_count)+".mpg"
+                       authorxml.append('     <vob file="' + menuoutputfilename + '" pause="inf"/>\n')
+                       authorxml.append('    </pgc>\n')
+       else:
+               authorxml.append('    <pgc>\n')
+               authorxml.append('     <vob file="' + job.project.settings.vmgm.getValue() + '" />\n' )
+               authorxml.append('     <post> jump titleset 1 title 1; </post>\n')
+               authorxml.append('    </pgc>\n')
+       authorxml.append('   </menus>\n')
+       authorxml.append('  </vmgm>\n')
+
+       for i in range( nr_titles ):
+               title = job.project.titles[i]
+               authorxml.append('  <titleset>\n')
+               authorxml.append('   <titles>\n')
+               for audiotrack in title.properties.audiotracks:
+                       active = audiotrack.active.getValue()
+                       if active:
+                               format = audiotrack.format.getValue()
+                               language = audiotrack.language.getValue()
+                               audio_tag = '    <audio format="%s"' % format
+                               if language != "nolang":
+                                       audio_tag += ' lang="%s"' % language
+                               audio_tag += ' />\n'
+                               authorxml.append(audio_tag)
+               aspect = title.properties.aspect.getValue()
+               video_tag = '    <video aspect="'+aspect+'"'
+               if title.properties.widescreen.getValue() == "4:3":
+                       video_tag += ' widescreen="'+title.properties.widescreen.getValue()+'"'
+               video_tag += ' />\n'
+               authorxml.append(video_tag)
+               chapters = ','.join(title.getChapterMarks())
+               title_no = i+1
+               title_filename = job.workspace + "/dvd_title_%d.mpg" % (title_no)
+               if job.menupreview:
+                       LinkTS(job, job.project.settings.vmgm.getValue(), title_filename)
+               else:
+                       MakeFifoNode(job, title_no)
+               if mode.endswith("linked") and title_no < nr_titles:
+                       post_tag = "jump titleset %d title 1;" % ( title_no+1 )
+               elif mode.startswith("menu"):
+                       post_tag = "call vmgm menu 1;"
+               else:   post_tag = ""
+
+               authorxml.append('    <pgc>\n')
+               authorxml.append('     <vob file="' + title_filename + '" chapters="' + chapters + '" />\n')
+               authorxml.append('     <post> ' + post_tag + ' </post>\n')
+               authorxml.append('    </pgc>\n')
+               authorxml.append('   </titles>\n')
+               authorxml.append('  </titleset>\n')
+       authorxml.append(' </dvdauthor>\n')
+       f = open(job.workspace+"/dvdauthor.xml", "w")
+       for x in authorxml:
+               f.write(x)
+       f.close()
+
 def getISOfilename(isopath, volName):
        from Tools.Directories import fileExists
        i = 0
@@ -703,7 +771,7 @@ class DVDJob(Job):
                CheckDiskspaceTask(self)
                if self.project.settings.authormode.getValue().startswith("menu") or self.menupreview:
                        Menus(self)
-               CreateAuthoringXML(self)
+               CreateAuthoringXML_multiset(self)
 
                DVDAuthorTask(self)
                
@@ -713,14 +781,14 @@ class DVDJob(Job):
                        PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/")
                else:
                        for self.i in range(nr_titles):
-                               title = self.project.titles[self.i]
+                               self.title = self.project.titles[self.i]
                                link_name =  self.workspace + "/source_title_%d.ts" % (self.i+1)
                                title_filename = self.workspace + "/dvd_title_%d.mpg" % (self.i+1)
-                               LinkTS(self, title.inputfile, link_name)
+                               LinkTS(self, self.title.inputfile, link_name)
                                demux = DemuxTask(self, link_name)
                                self.mplextask = MplexTask(self, outputfile=title_filename, demux_task=demux)
                                self.mplextask.end = self.estimateddvdsize
-                               RemoveESFiles(self, demux)
+                               #RemoveESFiles(self, demux)
                        WaitForResidentTasks(self)
                        PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/")
                        output = self.project.settings.output.getValue()
index 163269c74ff05bbe9757ba439c8784398849d0fc..be5ad245a410ccf5f35905b73ee84f7c58813819 100644 (file)
@@ -20,16 +20,31 @@ class TitleCutter(CutListEditor):
                audio = service and service.audioTracks()
                n = audio and audio.getNumberOfTracks() or 0
                if n > 0:
+                       from DVDTitle import ConfigFixedText, ConfigActiveTrack
+                       from TitleProperties import languageChoices
+                       from Components.config import config, ConfigSubsection, ConfigSelection
                        for x in range(n):
                                i = audio.getTrackInfo(x)
                                language = i.getLanguage()
                                description = i.getDescription()
+                               pid = str(i.getPID())
                                if description == "MPEG":
                                        description = "MP2"
-                               self.t.audiotracks.append((language, description))
-               print "[DVDBurn getAudioTracks]", self.t.audiotracks
-               self.t.sVideoType = service.info().getInfo(iServiceInformation.sVideoType)
-               print "[DVDBurn getVideoType]", self.t.sVideoType
+                               if not languageChoices.langdict.has_key(language):
+                                       language="nolang"
+                               print "[audiotrack] pid:", pid, "description:", description, "language:", language
+                               self.t.properties.audiotracks.append(ConfigSubsection())
+                               self.t.properties.audiotracks[-1].active = ConfigActiveTrack()
+                               self.t.properties.audiotracks[-1].format = ConfigFixedText(description)
+                               self.t.properties.audiotracks[-1].language = ConfigSelection(choices = languageChoices.choices, default=language)
+                               self.t.properties.audiotracks[-1].pid = ConfigFixedText(pid)
+               sAspect = service.info().getInfo(iServiceInformation.sAspect)
+               if sAspect in ( 1, 2, 5, 6, 9, 0xA, 0xD, 0xE ):
+                       aspect = "4:3"
+               else:
+                       aspect = "16:9"
+               self.t.properties.aspect.setValue(aspect)
+               self.t.VideoType = service.info().getInfo(iServiceInformation.sVideoType)
 
        def exit(self):
                self.session.nav.stopService()
index 19380af48793b1fcb257281ffbf5c6fb489b49b8..caec6198d82ab6e07c32d3a733bbb73ffb5375d9 100644 (file)
@@ -1,4 +1,4 @@
-import DVDProject, TitleList, TitleCutter, ProjectSettings, DVDToolbox, Process
+import DVDProject, TitleList, TitleCutter, TitleProperties, ProjectSettings, DVDToolbox, Process
 from Screens.Screen import Screen
 from Screens.ChoiceBox import ChoiceBox
 from Screens.InputBox import InputBox
@@ -41,7 +41,7 @@ class TitleList(Screen, HelpableScreen):
                self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
                        {
                                "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
-                               "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")),
+                               "titleProperties": (self.titleProperties, ("Properties of current title"), _("Title properties")),
                                "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
                                "settings": (self.settings, _("Collection settings"), _("Settings")),
                                "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
@@ -59,7 +59,7 @@ class TitleList(Screen, HelpableScreen):
 
                self["key_red"] = StaticText(_("Remove title"))
                self["key_green"] = StaticText(_("Add title"))
-               self["key_yellow"] = StaticText(_("Edit title"))
+               self["key_yellow"] = StaticText(_("Title properties"))
                self["key_blue"] = StaticText(_("Settings"))
 
                self["title_label"] = StaticText()
@@ -78,40 +78,31 @@ class TitleList(Screen, HelpableScreen):
        def showMenu(self):
                menu = []
                if self.project.settings.output.getValue() == "dvd":
-                       menu.append((_("Burn DVD"), "burn"));
+                       menu.append((_("Burn DVD"), self.burnProject))
                elif self.project.settings.output.getValue() == "iso":
-                       menu.append((_("Create DVD-ISO"), "burn"));
-               menu.append((_("Preview menu"), "previewMenu"));
-               menu.append((_("DVD media toolbox"), "toolbox"));
-               menu.append((_("Collection settings"), "settings"));
-               menu.append((_("Add a new title"), "addtitle"));
-               menu.append((_("Remove title"), "removetitle"));
-               menu.append((_("Edit chapters of current title"), "edittitle"));
-               menu.append((_("Burn existing image to DVD"), "burniso"));
-               menu.append((_("Exit"), "exit"));
+                       menu.append((_("Create DVD-ISO"), self.burnProject))
+               menu.append((_("Burn existing image to DVD"), self.selectImage))
+               menu.append((_("DVD media toolbox"), self.toolbox))
+               menu.append((_("Preview menu"), self.previewMenu))
+               menu.append((_("Collection settings"), self.settings))
+               menu.append(("Reset and renumerate title names", self.resetTitles))
+               menu.append((_("Edit chapters of current title"), self.editTitle))
+               menu.append(("Properties of current title", self.titleProperties))
+               menu.append((_("Add a new title"), self.addTitle))
+               menu.append((_("Remove title"), self.removeCurrentTitle))
+               menu.append((_("Exit"), self.leave))
                self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
 
        def menuCallback(self, choice):
-               if choice is None:
-                       return
-               if choice[1] == "removetitle":
-                       self.removeCurrentTitle()
-               elif choice[1] == "addtitle":
-                       self.addTitle()
-               elif choice[1] == "edittitle":
-                       self.editTitle()
-               elif choice[1] == "toolbox":
-                       self.toolbox()
-               elif choice[1] == "settings":
-                       self.settings()
-               elif choice[1] == "previewMenu":
-                       self.previewMenu()
-               elif choice[1] == "burn":
-                       self.burnProject()
-               elif choice[1] == "burniso":
-                       self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
-               elif choice[1] == "exit":
-                       self.leave()
+               if choice:
+                       choice[1]()
+
+       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()
@@ -225,7 +216,7 @@ class TitleList(Screen, HelpableScreen):
                res = [ ]
                totalsize = 0
                for title in self.project.titles:
-                       a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name)  ]
+                       a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue())  ]
                        res.append(a)
                        totalsize += title.estimatedDiskspace
                self["titles"].list = res
@@ -263,13 +254,21 @@ class TitleList(Screen, HelpableScreen):
 
        def titleEditDone(self, cutlist):
                t = self.current_edit_title
+               t.initDVDmenuText(self.project,len(self.project.titles))
                t.cuesheet = cutlist
                t.produceFinalCuesheet()
-               if t.sVideoType != 0:
+               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 resetTitles(self):
+               count = 0
+               for title in self.project.titles:
+                       count += 1
+                       title.initDVDmenuText(self.project,count)
+               self.updateTitleList()
+
        def DVDformatCB(self, answer):
                t = self.current_edit_title
                if answer == True:
diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py
new file mode 100644 (file)
index 0000000..72071a5
--- /dev/null
@@ -0,0 +1,152 @@
+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 Components.ActionMap import HelpableActionMap, ActionMap
+from Components.Sources.List import List
+from Components.Sources.StaticText import StaticText
+from Components.Sources.Progress import Progress
+from Components.FileList import FileList
+from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
+from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD
+from Components.config import config, getConfigListEntry, ConfigInteger, ConfigSubsection, ConfigSelection
+from Components.ConfigList import ConfigListScreen
+import DVDTitle
+
+class TitleProperties(Screen,ConfigListScreen):
+       skin = """
+               <screen position="90,83" size="560,445" title="Title properties" >
+                   <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
+                   <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
+                   <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
+                   <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
+                   <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
+                   <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
+                   <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
+                   <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
+                   <widget name="config" position="10,50" size="540,276" scrollbarMode="showOnDemand" />
+                   <widget source="serviceinfo_headline" render="Label" position="20,350" size="520,20" font="Regular;20" />
+                   <widget source="serviceinfo" render="Label" position="20,374" size="520,66" font="Regular;16" />
+               </screen>"""
+
+       def __init__(self, session, parent, project, title_idx):
+               Screen.__init__(self, session)
+               self.parent = parent
+               self.project = project
+               self.title_idx = title_idx
+
+               self["key_red"] = StaticText(_("Cancel"))
+               self["key_green"] = StaticText(_("OK"))
+               self["key_yellow"] = StaticText(_("Edit Title"))
+               self["key_blue"] = StaticText(_("Save"))
+               self["serviceinfo_headline"] = StaticText("DVB info:")
+               self["serviceinfo"] = StaticText()
+
+               self.properties = project.titles[title_idx].properties
+               ConfigListScreen.__init__(self, [])
+               self.properties.crop = DVDTitle.ConfigFixedText("crop")
+               self.initConfigList()
+                       
+               self["setupActions"] = ActionMap(["SetupActions", "ColorActions"],
+               {
+                   "green": self.exit,
+                   "red": self.cancel,
+                   #"blue": self.saveProject,
+                   "yellow": self.editTitle,
+                   "cancel": self.cancel,
+                   "ok": self.ok,
+               }, -2)
+
+       def initConfigList(self):
+               self.properties.position = ConfigInteger(default = self.title_idx+1, limits = (1, len(self.project.titles)))
+               title = self.project.titles[self.title_idx]
+               self.list = []
+               self.list.append(getConfigListEntry("DVD " + _("Track"), self.properties.position))
+               self.list.append(getConfigListEntry("DVD " + _("Title"), self.properties.menutitle))
+               self.list.append(getConfigListEntry("DVD " + _("Description"), self.properties.menusubtitle))
+               for audiotrack in self.properties.audiotracks:
+                       pid = audiotrack.pid.getValue()
+                       self.list.append(getConfigListEntry("burn audio track (%s)" % pid, audiotrack.active))
+                       if audiotrack.active.getValue():
+                               self.list.append(getConfigListEntry("audio track (%s) format" % pid, audiotrack.format))
+                               self.list.append(getConfigListEntry("audio track (%s) language" % pid, audiotrack.language))
+                               
+               self.list.append(getConfigListEntry("DVD " + _("Aspect Ratio"), self.properties.aspect))
+               if self.properties.aspect.getValue() == "16:9":
+                       self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.widescreen))
+               else:
+                       self.list.append(getConfigListEntry("DVD " + "widescreen", self.properties.crop))
+               
+               self["config"].setList(self.list)
+               
+               infotext = _("Available format variables") + ":\n$i=" + _("Track") + ", $t=" + _("Title") + ", $d=" + _("Description") + ", $l=" + _("length") + ", $c=" + _("chapters") + ",\n" + _("Record") + " $T=" + _("Begin time") + ", $Y=" + _("year") + ", $M=" + _("month") + ", $D=" + _("day") + ",\n$A=" + _("audio tracks") + ", $C=" + _("Channel") + ", $f=" + _("filename")
+               self["info"] = StaticText(infotext)
+               
+               chapters_count = len(title.chaptermarks)
+               infotext = _("Title") + ': ' + title.DVBname + "\n" + _("Description") + ': ' + title.DVBdescr + "\n" + _("Channel") + ': ' + title.DVBchannel
+               if chapters_count:
+                       infotext += ', ' + str(chapters_count+1) + ' ' + _("chapters") + ' ('
+                       infotext += ' / '.join(title.getChapterMarks()) + ')'
+               self["serviceinfo"].setText(infotext)
+
+       def editTitle(self):
+               self.parent.editTitle()
+               self.initConfigList()
+
+       def changedConfigList(self):
+               self.initConfigList()
+       
+       def keyLeft(self):
+               ConfigListScreen.keyLeft(self)
+               if type(self["config"].getCurrent()[1]) in [DVDTitle.ConfigActiveTrack, ConfigSelection]:
+                       self.initConfigList()
+
+       def keyRight(self):
+               ConfigListScreen.keyRight(self)
+               if type(self["config"].getCurrent()[1]) in [DVDTitle.ConfigActiveTrack, ConfigSelection]:
+                       self.initConfigList()
+
+       def exit(self):
+               self.applySettings()
+               self.close()
+
+       def applySettings(self):
+               for x in self["config"].list:
+                       x[1].save()
+               current_pos = self.title_idx+1
+               new_pos = self.properties.position.getValue()
+               if new_pos != current_pos:
+                       print "title got repositioned from ", current_pos, "to", new_pos
+                       swaptitle = self.project.titles.pop(current_pos-1)
+                       self.project.titles.insert(new_pos-1, swaptitle)
+
+       def ok(self):
+               #key = self.keydict[self["config"].getCurrent()[1]]
+               #if key in self.project.filekeys:
+                       #self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, key, self.settings)
+               pass
+
+       def cancel(self):
+               self.close()
+
+class LanguageChoices():
+       def __init__(self):
+               from Tools.ISO639 import LanguageCodes
+               from Components.Language import language as syslanguage
+               syslang = syslanguage.getLanguage()[:2]
+               self.langdict = { }
+               self.choices = []
+               for key, val in LanguageCodes.iteritems():
+                       if len(key) == 2:
+                               self.langdict[key] = val[0]
+               for key, val in self.langdict.iteritems():
+                       if key not in [syslang, 'en']:
+                               self.langdict[key] = val
+                               self.choices.append((key, val))
+               self.choices.sort()
+               self.choices.insert(0,("nolang", ("unspecified")))
+               self.choices.insert(1,(syslang, self.langdict[syslang]))
+               self.choices.insert(2,("en", self.langdict["en"]))
+
+languageChoices = LanguageChoices()
\ No newline at end of file
index 13fa3ee0bf1335261fd9e0609c08994a2689ed16..e8bc10452279f9b2e827bc12aedc7faad1721316 100644 (file)
@@ -2,7 +2,7 @@
        <map context="DVDTitleList">
                <key id="KEY_RED" mapto="removeCurrentTitle" flags="m" />
                <key id="KEY_GREEN" mapto="addTitle" flags="m" />
-               <key id="KEY_YELLOW" mapto="editTitle" flags="m" />
+               <key id="KEY_YELLOW" mapto="titleProperties" flags="m" />
                <key id="KEY_BLUE" mapto="settings" flags="m" />
                <key id="KEY_RECORD" mapto="burnProject" flags="m" />
                <key id="KEY_0" mapto="burnProject" flags="m" />