allow creating .ISO files. allow burning .ISO images or preauthored dvd structures...
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
1 import DVDProject, TitleList, TitleCutter, ProjectSettings, DVDToolbox, Process
2 from Screens.Screen import Screen
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.InputBox import InputBox
5 from Screens.MessageBox import MessageBox
6 from Screens.HelpMenu import HelpableScreen
7 from Screens.TaskView import JobView
8 from Components.Task import job_manager
9 from Components.ActionMap import HelpableActionMap, ActionMap
10 from Components.Sources.List import List
11 from Components.Sources.StaticText import StaticText
12 from Components.Sources.Progress import Progress
13 from Components.Label import Label
14 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
15 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
16
17 class TitleList(Screen, HelpableScreen):
18         skin = """
19                 <screen position="90,83" size="560,445" title="DVD Tool" >
20                     <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
21                     <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
22                     <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
23                     <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
24                     <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" />
25                     <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" />
26                     <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" />
27                     <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" />
28                     <widget source="title_label" render="Label" position="10,48" size="540,38" font="Regular;18" />
29                     <widget name="error_label" position="10,48" size="540,395" zPosition="3" font="Regular;20" />
30                     <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="10,86" size="540,312">
31                         <convert type="StaticMultiList" />
32                     </widget>
33                     <widget source="space_bar" render="Progress" position="10,410" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
34                     <widget source="space_label" render="Label" position="40,414" size="480,22" zPosition="2" font="Regular;18" halign="center" transparent="1" foregroundColor="#000000" />
35                 </screen>"""
36
37         def __init__(self, session, project = None):
38                 Screen.__init__(self, session)
39                 HelpableScreen.__init__(self)
40                 
41                 self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
42                         {
43                                 "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
44                                 "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")),
45                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
46                                 "settings": (self.settings, _("Collection settings"), _("Settings")),
47                                 "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
48                         })
49
50                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
51                         {
52                                 "contextMenu": (self.showMenu, _("menu")),
53                         })
54
55                 self["actions"] = ActionMap(["OkCancelActions"],
56                         {
57                                 "cancel": self.leave
58                         })
59
60                 self["key_red"] = StaticText(_("Remove title"))
61                 self["key_green"] = StaticText(_("Add title"))
62                 self["key_yellow"] = StaticText(_("Edit title"))
63                 self["key_blue"] = StaticText(_("Settings"))
64
65                 self["title_label"] = StaticText()
66                 self["error_label"] = Label("")
67                 self["space_label"] = StaticText()
68                 self["space_bar"] = Progress()
69
70                 if project is not None:
71                         self.project = project
72                 else:
73                         self.newProject()
74
75                 self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)])
76                 self.updateTitleList()
77                 
78         def showMenu(self):
79                 menu = []
80                 if self.project.settings.output.getValue() == "dvd":
81                         menu.append((_("Burn DVD"), "burn"));
82                 elif self.project.settings.output.getValue() == "iso":
83                         menu.append((_("Create DVD-ISO"), "burn"));
84                 menu.append((_("Preview menu"), "previewMenu"));
85                 menu.append((_("DVD media toolbox"), "toolbox"));
86                 menu.append((_("Collection settings"), "settings"));
87                 menu.append((_("Add a new title"), "addtitle"));
88                 menu.append((_("Remove title"), "removetitle"));
89                 menu.append((_("Edit chapters of current title"), "edittitle"));
90                 menu.append((_("Burn existing image to DVD"), "burniso"));
91                 menu.append((_("Exit"), "exit"));
92                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
93
94         def menuCallback(self, choice):
95                 if choice is None:
96                         return
97                 if choice[1] == "removetitle":
98                         self.removeCurrentTitle()
99                 elif choice[1] == "addtitle":
100                         self.addTitle()
101                 elif choice[1] == "edittitle":
102                         self.editTitle()
103                 elif choice[1] == "toolbox":
104                         self.toolbox()
105                 elif choice[1] == "settings":
106                         self.settings()
107                 elif choice[1] == "previewMenu":
108                         self.previewMenu()
109                 elif choice[1] == "burn":
110                         self.burnProject()
111                 elif choice[1] == "burniso":
112                         self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
113                 elif choice[1] == "exit":
114                         self.leave()
115
116         def newProject(self):
117                 self.project = DVDProject.DVDProject()
118                 if self.loadTemplate():
119                         self.project.session = self.session
120                         self.settingsCB()
121
122         def addTitle(self):
123                 from Screens.MovieSelection import MovieSelection
124                 from Components.Button import Button
125                 from Components.ActionMap import HelpableActionMap
126                 class MovieSelectionNoMenu(MovieSelection):
127                         def __init__(self, session):
128                                 MovieSelection.__init__(self, session)
129                                 self.skinName = "MovieSelection"
130                                 self["key_red"] = Button(_("Edit title"))
131                                 self["key_green"] = Button(_("Add"))
132                                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
133                                 {
134                                         "red": (self.movieSelected, _("Add a new title")),
135                                         "green": (self.insertWithoutEdit, ("insert without cutlist editor"))
136                                 })
137                         def updateTags(self):
138                                 pass
139                         def doContext(self):
140                                 print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
141                         def insertWithoutEdit(self):
142                                 current = self.getCurrent()
143                                 if current is not None:
144                                         current.edit = False
145                                         self.close(current)
146                         def movieSelected(self):
147                                 current = self.getCurrent()
148                                 if current is not None:
149                                         current.edit = True
150                                         self.close(current)
151                 self.session.openWithCallback(self.selectedSource, MovieSelectionNoMenu)
152
153         def selectedSource(self, source):
154                 if source is None:
155                         return None
156                 t = self.project.addService(source)
157                 try:
158                         editor = source.edit
159                 except AttributeError:
160                         editor = True
161                 self.editTitle(t, editor)
162
163         def removeCurrentTitle(self):
164                 title = self.getCurrentTitle()
165                 self.removeTitle(title)
166         
167         def removeTitle(self, title):
168                 if title is not None:
169                         self.project.titles.remove(title)
170                         self.updateTitleList()
171
172         def toolbox(self):
173                 self.session.open(DVDToolbox.DVDToolbox)
174
175         def settings(self):
176                 self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
177
178         def settingsCB(self, update=True):
179                 if not update:
180                         return
181                 self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
182
183         def loadTemplate(self):
184                 filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml"
185                 if self.project.loadProject(filename):
186                         self["error_label"].hide()
187                         return True
188                 else:
189                         self["error_label"].text = self.project.error
190                         self["error_label"].show()
191                         return False
192
193         def burnProject(self):
194                 if self.project.settings.authormode.getValue() == "data_ts":
195                         job = Process.DVDdataJob(self.project)
196                         job_manager.AddJob(job)
197                         job_manager.in_background = False
198                         self.session.openWithCallback(self.JobViewCB, JobView, job)
199                 else:
200                         autochapter = self.project.settings.autochapter.getValue()
201                         if autochapter > 0:
202                                 for title in self.project.titles:
203                                         title.produceAutoChapter(autochapter)
204                         job = Process.DVDJob(self.project)
205                         job_manager.AddJob(job)
206                         job_manager.in_background = False
207                         self.session.openWithCallback(self.JobViewCB, JobView, job)
208
209         def burnISO(self, path, scope):
210                 job = Process.DVDisoJob(self.project, path)
211                 job_manager.AddJob(job)
212                 job_manager.in_background = False
213                 self.session.openWithCallback(self.JobViewCB, JobView, job)
214
215         def JobViewCB(self, in_background):
216                 job_manager.in_background = in_background
217
218         def previewMenu(self):
219                 job = Process.DVDJob(self.project, menupreview=True)
220                 job_manager.in_background = False
221                 job_manager.AddJob(job)
222                 
223         def updateTitleList(self):
224                 res = [ ]
225                 totalsize = 0
226                 for title in self.project.titles:
227                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name)  ]
228                         res.append(a)
229                         totalsize += title.estimatedDiskspace
230                 self["titles"].list = res
231                 self.updateSize(totalsize)
232                 
233         def updateSize(self, totalsize):
234                 size = int((totalsize/1024)/1024)
235                 max_SL = 4370
236                 max_DL = 7950
237                 if size > max_DL:
238                         percent = 100 * size / float(max_DL)
239                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
240                         self["space_bar"].value = int(percent)
241                 elif size > max_SL:
242                         percent = 100 * size / float(max_DL)
243                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
244                         self["space_bar"].value = int(percent)
245                 elif size < max_SL:
246                         percent = 100 * size / float(max_SL)
247                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
248                         self["space_bar"].value = int(percent)
249
250         def getCurrentTitle(self):
251                 t = self["titles"].getCurrent()
252                 return t and t[0]
253
254         def editTitle(self, title = None, editor = True):
255                 t = title or self.getCurrentTitle()
256                 if t is not None:
257                         self.current_edit_title = t
258                         if editor:
259                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
260                         else:
261                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
262
263         def titleEditDone(self, cutlist):
264                 t = self.current_edit_title
265                 t.cuesheet = cutlist
266                 t.produceFinalCuesheet()
267                 if t.sVideoType != 0:
268                         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)
269                 else:
270                         self.updateTitleList()
271
272         def DVDformatCB(self, answer):
273                 t = self.current_edit_title
274                 if answer == True:
275                         self.project.settings.authormode.setValue("data_ts")
276                         self.updateTitleList()
277                 else:
278                         self.removeTitle(t)
279
280         def leave(self):
281                 self.close()