Merge branch 'master' of fraxinas@git.opendreambox.org:/git/enigma2
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
1 import DVDProject, TitleList, TitleCutter, TitleProperties, 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                                 "titleProperties": (self.titleProperties, _("Properties of current title"), _("Title properties")),
45                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
46                                 "settings": (self.settings, _("Collection settings"), _("Settings")),
47                                 "burnProject": (self.askBurnProject, _("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()
61                 self["key_green"] = StaticText(_("Add title"))
62                 self["key_yellow"] = StaticText()
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                 self.previous_size = 0
78
79         def checkBackgroundJobs(self):
80                 for job in job_manager.getPendingJobs():
81                         print "type(job):", type(job)
82                         print "Process.DVDJob:", Process.DVDJob
83                         if type(job) == Process.DVDJob:
84                                 self.backgroundJob = job
85                                 return
86                 self.backgroundJob = None
87
88         def showMenu(self):
89                 menu = []
90                 self.checkBackgroundJobs()
91                 if self.backgroundJob:
92                         j = self.backgroundJob
93                         menu.append(("%s: %s (%d%%)" % (j.getStatustext(), j.name, int(100*j.progress/float(j.end))), self.showBackgroundJob))
94                 menu.append((_("DVD media toolbox"), self.toolbox))
95                 menu.append((_("Preview menu"), self.previewMenu))
96                 if self.project.settings.output.getValue() == "dvd":
97                         if len(self["titles"].list):
98                                 menu.append((_("Burn DVD"), self.burnProject))
99                 elif self.project.settings.output.getValue() == "iso":
100                         menu.append((_("Create DVD-ISO"), self.burnProject))
101                 menu.append((_("Burn existing image to DVD"), self.selectImage))
102                 menu.append((_("Edit chapters of current title"), self.editTitle))
103                 menu.append((_("Reset and renumerate title names"), self.resetTitles))
104                 menu.append((_("Exit"), self.leave))
105                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
106
107         def menuCallback(self, choice):
108                 if choice:
109                         choice[1]()
110
111         def showBackgroundJob(self):
112                 job_manager.in_background = False
113                 self.session.openWithCallback(self.JobViewCB, JobView, self.backgroundJob)
114                 self.backgroundJob = None
115         
116         def titleProperties(self):
117                 if self.getCurrentTitle():
118                         self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex())
119
120         def selectImage(self):
121                 self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
122
123         def newProject(self):
124                 self.project = DVDProject.DVDProject()
125                 if self.loadTemplate():
126                         self.project.session = self.session
127                         self.settingsCB()
128
129         def addTitle(self):
130                 from Screens.MovieSelection import MovieSelection
131                 from Components.Button import Button
132                 from Components.ActionMap import HelpableActionMap
133                 class MovieSelectionNoMenu(MovieSelection):
134                         def __init__(self, session):
135                                 MovieSelection.__init__(self, session)
136                                 self.skinName = "MovieSelection"
137                                 self["key_red"] = Button(_("Edit title"))
138                                 self["key_green"] = Button(_("Add"))
139                                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
140                                 {
141                                         "red": (self.movieSelected, _("Add a new title")),
142                                         "green": (self.insertWithoutEdit, ("insert without cutlist editor"))
143                                 })
144                         def updateTags(self):
145                                 pass
146                         def doContext(self):
147                                 print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
148                         def insertWithoutEdit(self):
149                                 current = self.getCurrent()
150                                 if current is not None:
151                                         current.edit = False
152                                         self.close(current)
153                         def movieSelected(self):
154                                 current = self.getCurrent()
155                                 if current is not None:
156                                         current.edit = True
157                                         self.close(current)
158                 self.session.openWithCallback(self.selectedSource, MovieSelectionNoMenu)
159
160         def selectedSource(self, source):
161                 if source is None:
162                         return None
163                 t = self.project.addService(source)
164                 try:
165                         editor = source.edit
166                 except AttributeError:
167                         editor = True
168                 self.editTitle(t, editor)
169
170         def removeCurrentTitle(self):
171                 title = self.getCurrentTitle()
172                 self.removeTitle(title)
173         
174         def removeTitle(self, title):
175                 if title is not None:
176                         self.project.titles.remove(title)
177                         self.updateTitleList()
178
179         def toolbox(self):
180                 self.session.open(DVDToolbox.DVDToolbox)
181
182         def settings(self):
183                 self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
184
185         def settingsCB(self, update=True):
186                 if not update:
187                         return
188                 self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
189
190         def loadTemplate(self):
191                 filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVD.ddvdp.xml"
192                 if self.project.load(filename):
193                         self["error_label"].hide()
194                         return True
195                 else:
196                         self["error_label"].text = self.project.error
197                         self["error_label"].show()
198                         return False
199
200         def askBurnProject(self):
201                 if len(self["titles"].list):
202                         self.session.openWithCallback(self.burnProject,MessageBox,text = _("Do you want to burn this collection to DVD medium?"), type = MessageBox.TYPE_YESNO)
203
204         def burnProject(self, answer=True):
205                 if not answer:
206                         return
207                 if self.project.settings.authormode.getValue() == "data_ts":
208                         job = Process.DVDdataJob(self.project)
209                         job_manager.AddJob(job)
210                         job_manager.in_background = False
211                         self.session.openWithCallback(self.JobViewCB, JobView, job)
212                 else:
213                         job = Process.DVDJob(self.project)
214                         job_manager.AddJob(job)
215                         job_manager.in_background = False
216                         self.session.openWithCallback(self.JobViewCB, JobView, job)
217
218         def burnISO(self, path, scope, configRef):
219                 if path:
220                         job = Process.DVDisoJob(self.project, path)
221                         job_manager.AddJob(job)
222                         job_manager.in_background = False
223                         self.session.openWithCallback(self.JobViewCB, JobView, job)
224
225         def JobViewCB(self, in_background):
226                 job_manager.in_background = in_background
227
228         def previewMenu(self):
229                 job = Process.DVDJob(self.project, menupreview=True)
230                 job_manager.in_background = False
231                 job_manager.AddJob(job)
232                 
233         def updateTitleList(self):
234                 res = [ ]
235                 totalsize = 0
236                 for title in self.project.titles:
237                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue())  ]
238                         res.append(a)
239                         totalsize += title.estimatedDiskspace
240                 self["titles"].list = res
241                 self.updateSize(totalsize)
242                 if len(res):
243                         self["key_red"].text = _("Remove title")
244                         self["key_yellow"].text = _("Title properties")
245                 else:
246                         self["key_red"].text = ""
247                         self["key_yellow"].text = ""
248
249         def updateSize(self, totalsize):
250                 size = int((totalsize/1024)/1024)
251                 max_SL = 4370
252                 max_DL = 7950
253                 if size > max_DL:
254                         percent = 100 * size / float(max_DL)
255                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
256                         self["space_bar"].value = int(percent)
257                         if self.previous_size < max_DL:
258                                 self.session.open(MessageBox,text = _("exceeds dual layer medium!"), type = MessageBox.TYPE_ERROR)
259                 elif size > max_SL:
260                         percent = 100 * size / float(max_DL)
261                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
262                         self["space_bar"].value = int(percent)
263                         if self.previous_size < max_SL:
264                                 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)
265                 elif size < max_SL:
266                         percent = 100 * size / float(max_SL)
267                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
268                         self["space_bar"].value = int(percent)
269                 self.previous_size = size
270
271         def getCurrentTitle(self):
272                 t = self["titles"].getCurrent()
273                 return t and t[0]
274
275         def editTitle(self, title = None, editor = True):
276                 t = title or self.getCurrentTitle()
277                 if t is not None:
278                         self.current_edit_title = t
279                         if editor:
280                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
281                         else:
282                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
283
284         def titleEditDone(self, cutlist):
285                 t = self.current_edit_title
286                 t.initDVDmenuText(self.project,len(self.project.titles))
287                 t.cuesheet = cutlist
288                 t.produceFinalCuesheet()
289                 if t.VideoType != 0:
290                         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)
291                 else:
292                         self.updateTitleList()
293
294         def resetTitles(self):
295                 count = 0
296                 for title in self.project.titles:
297                         count += 1
298                         title.initDVDmenuText(self.project,count)
299                 self.updateTitleList()
300
301         def DVDformatCB(self, answer):
302                 t = self.current_edit_title
303                 if answer == True:
304                         self.project.settings.authormode.setValue("data_ts")
305                         self.updateTitleList()
306                 else:
307                         self.removeTitle(t)
308
309         def leave(self):
310                 self.close()