change disc size determination and tweak dual layer growisofs arguments
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
index f4467707b3ed209664cec3cddb5d848ec840f547..aeb163f321265d68200556d3c2ac8f71b0cf325e 100644 (file)
@@ -1,19 +1,20 @@
-import DVDProject, TitleList, TitleCutter, ProjectSettings
+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.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 Components.Sources.Progress import Progress
 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 Components.Label import Label
 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
 
 from Components.Label import Label
 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
 
-class TitleList(Screen):
+class TitleList(Screen, HelpableScreen):
        skin = """
                <screen position="90,83" size="560,445" title="DVD Tool" >
                    <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
        skin = """
                <screen position="90,83" size="560,445" title="DVD Tool" >
                    <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
@@ -35,14 +36,15 @@ class TitleList(Screen):
 
        def __init__(self, session, project = None):
                Screen.__init__(self, session)
 
        def __init__(self, session, project = None):
                Screen.__init__(self, session)
+               HelpableScreen.__init__(self)
                
                self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
                        {
                                "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
                
                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")),
                                "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
                                "settings": (self.settings, _("Collection settings"), _("Settings")),
-                               "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
+                               "burnProject": (self.askBurnProject, _("Burn DVD"), _("Burn DVD")),
                        })
 
                self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
                        })
 
                self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
@@ -55,9 +57,9 @@ class TitleList(Screen):
                                "cancel": self.leave
                        })
 
                                "cancel": self.leave
                        })
 
-               self["key_red"] = StaticText(_("Remove title"))
+               self["key_red"] = StaticText()
                self["key_green"] = StaticText(_("Add title"))
                self["key_green"] = StaticText(_("Add title"))
-               self["key_yellow"] = StaticText(_("Edit title"))
+               self["key_yellow"] = StaticText()
                self["key_blue"] = StaticText(_("Settings"))
 
                self["title_label"] = StaticText()
                self["key_blue"] = StaticText(_("Settings"))
 
                self["title_label"] = StaticText()
@@ -72,41 +74,51 @@ class TitleList(Screen):
 
                self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)])
                self.updateTitleList()
 
                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.previous_size = 0
+
+       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 = []
        def showMenu(self):
                menu = []
-               menu.append((_("Burn DVD"), "burn"));
-               menu.append((_("Preview menu"), "previewMenu"));
-               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((_("Exit"), "exit"));
+               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))
+               menu.append((_("Preview menu"), self.previewMenu))
+               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))
+               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):
                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] == "settings":
-                       self.settings()
-               elif choice[1] == "previewMenu":
-                       self.previewMenu()
-               elif choice[1] == "burn":
-                       self.burnProject()
-               elif choice[1] == "exit":
-                       self.leave()
+               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()
 
        def newProject(self):
                self.project = DVDProject.DVDProject()
@@ -116,21 +128,44 @@ class TitleList(Screen):
 
        def addTitle(self):
                from Screens.MovieSelection import MovieSelection
 
        def addTitle(self):
                from Screens.MovieSelection import MovieSelection
+               from Components.Button import Button
+               from Components.ActionMap import HelpableActionMap
                class MovieSelectionNoMenu(MovieSelection):
                        def __init__(self, session):
                                MovieSelection.__init__(self, session)
                                self.skinName = "MovieSelection"
                class MovieSelectionNoMenu(MovieSelection):
                        def __init__(self, session):
                                MovieSelection.__init__(self, session)
                                self.skinName = "MovieSelection"
-
+                               self["key_red"] = Button(_("Edit title"))
+                               self["key_green"] = Button(_("Add"))
+                               self["ColorActions"] = HelpableActionMap(self, "ColorActions",
+                               {
+                                       "red": (self.movieSelected, _("Add a new title")),
+                                       "green": (self.insertWithoutEdit, ("insert without cutlist editor"))
+                               })
+                       def updateTags(self):
+                               pass
                        def doContext(self):
                                print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
                        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, MovieSelectionNoMenu)
 
        def selectedSource(self, source):
                if source is None:
                        return None
                t = self.project.addService(source)
                self.session.openWithCallback(self.selectedSource, MovieSelectionNoMenu)
 
        def selectedSource(self, source):
                if source is None:
                        return None
                t = self.project.addService(source)
-               self.editTitle(t, readOnly=False)
+               try:
+                       editor = source.edit
+               except AttributeError:
+                       editor = True
+               self.editTitle(t, editor)
 
        def removeCurrentTitle(self):
                title = self.getCurrentTitle()
 
        def removeCurrentTitle(self):
                title = self.getCurrentTitle()
@@ -141,6 +176,9 @@ class TitleList(Screen):
                        self.project.titles.remove(title)
                        self.updateTitleList()
 
                        self.project.titles.remove(title)
                        self.updateTitleList()
 
+       def toolbox(self):
+               self.session.open(DVDToolbox.DVDToolbox)
+
        def settings(self):
                self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
 
        def settings(self):
                self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
 
@@ -150,85 +188,119 @@ class TitleList(Screen):
                self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
 
        def loadTemplate(self):
                self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
 
        def loadTemplate(self):
-               filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml"
-               if self.project.loadProject(filename):
+               filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVD.ddvdp.xml"
+               if self.project.load(filename):
                        self["error_label"].hide()
                        return True
                else:
                        self["error_label"].text = self.project.error
                        self["error_label"].show()
                        self["error_label"].hide()
                        return True
                else:
                        self["error_label"].text = self.project.error
                        self["error_label"].show()
-                       print self.project.error
                        return False
 
                        return False
 
-       def burnProject(self):
-               autochapter = self.project.settings.autochapter.getValue()
-               if autochapter > 0:
-                       for title in self.project.titles:
-                               title.produceAutoChapter(autochapter)
-               self.project.waitboxref = self.project.session.open(ProjectSettings.WaitBox,self.burnProjectCB)
+       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 burnProjectCB(self):
-               import Process
-               job = Process.Burn(self.session, self.project)
-               from Screens.TaskView import JobView
-               self.session.open(JobView, job)
+       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):
 
        def previewMenu(self):
-               self.project.waitboxref = self.project.session.open(ProjectSettings.WaitBox,self.previewMenuCB)
+               job = Process.DVDJob(self.project, menupreview=True)
+               job_manager.in_background = False
+               job_manager.AddJob(job)
                
                
-       def previewMenuCB(self):
-               import Process
-               job = Process.PreviewMenu(self.session, self.project)
-
        def updateTitleList(self):
                res = [ ]
        def updateTitleList(self):
                res = [ ]
-               totalsize = 0
                for title in self.project.titles:
                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, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue())  ]
                        res.append(a)
                        res.append(a)
-                       totalsize += title.estimatedDiskspace
                self["titles"].list = res
                self["titles"].list = res
-               self.updateSize(totalsize)
-               
-       def updateSize(self, totalsize):
-               size = int((totalsize/1024)/1024)
-               max_SL = 4370
-               max_DL = 7950
-               if size > max_DL:
-                       percent = 100 * size / float(max_DL)
+               self.updateSize()
+               if len(res):
+                       self["key_red"].text = _("Remove title")
+                       self["key_yellow"].text = _("Title properties")
+               else:
+                       self["key_red"].text = ""
+                       self["key_yellow"].text = ""
+
+       def updateSize(self):
+               size = self.project.size
+               if size > self.project.MAX_DL:
+                       percent = 100 * size / float(self.project.MAX_DL)
                        self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
                        self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
-               elif size > max_SL:
-                       percent = 100 * size / float(max_DL)
+                       if self.previous_size < self.project.MAX_DL:
+                               self.session.open(MessageBox,text = _("exceeds dual layer medium!"), type = MessageBox.TYPE_ERROR)
+               elif size > self.project.MAX_SL:
+                       percent = 100 * size / float(self.project.MAX_DL)
                        self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
                        self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
-               elif size < max_SL:
-                       percent = 100 * size / float(max_SL)
+                       if self.previous_size < self.project.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!"), type = MessageBox.TYPE_INFO)
+               elif size < self.project.MAX_SL:
+                       percent = 100 * size / float(self.project.MAX_SL)
                        self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
                        self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
                        self["space_bar"].value = int(percent)
+               self.previous_size = size
 
        def getCurrentTitle(self):
                t = self["titles"].getCurrent()
                return t and t[0]
 
 
        def getCurrentTitle(self):
                t = self["titles"].getCurrent()
                return t and t[0]
 
-       def editTitle(self, title = None, readOnly = False):
+       def editTitle(self, title = None, editor = True):
                t = title or self.getCurrentTitle()
                if t is not None:
                        self.current_edit_title = t
                t = title or self.getCurrentTitle()
                if t is not None:
                        self.current_edit_title = t
-                       if readOnly:
-                               self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
-                       else:
+                       if editor:
                                self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
                                self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
+                       else:
+                               self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
 
        def titleEditDone(self, cutlist):
 
        def titleEditDone(self, cutlist):
-               if cutlist != False:
-                       t = self.current_edit_title
-                       t.cuesheet = cutlist
-                       t.produceFinalCuesheet()
+               t = self.current_edit_title
+               t.initDVDmenuText(self.project,len(self.project.titles))
+               t.cuesheet = cutlist
+               t.produceFinalCuesheet()
+               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:
+                       self.project.settings.authormode.setValue("data_ts")
                        self.updateTitleList()
                else:
                        self.updateTitleList()
                else:
-                       self.session.open(MessageBox,text = _("The DVD standard doesn't support H.264 (HDTV) video streams!"),type = MessageBox.TYPE_ERROR)
-                       self.removeTitle(self.current_edit_title)
+                       self.removeTitle(t)
 
        def leave(self):
                self.close()
 
        def leave(self):
                self.close()