fix disc size unit confusion
[vuplus_dvbapp] / 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                 for title in self.project.titles:
236                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue())  ]
237                         res.append(a)
238                 self["titles"].list = res
239                 self.updateSize()
240                 if len(res):
241                         self["key_red"].text = _("Remove title")
242                         self["key_yellow"].text = _("Title properties")
243                 else:
244                         self["key_red"].text = ""
245                         self["key_yellow"].text = ""
246
247         def updateSize(self):
248                 size = self.project.size/(1024*1024)
249                 MAX_DL = self.project.MAX_DL-100
250                 MAX_SL = self.project.MAX_SL-100
251                 print "updateSize:", size, "MAX_DL:", MAX_DL, "MAX_SL:", MAX_SL
252                 if size > MAX_DL:
253                         percent = 100 * size / float(MAX_DL)
254                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
255                         self["space_bar"].value = int(percent)
256                         if self.previous_size < MAX_DL:
257                                 self.session.open(MessageBox,text = _("exceeds dual layer medium!"), type = MessageBox.TYPE_ERROR)
258                 elif size > MAX_SL:
259                         percent = 100 * size / float(MAX_DL)
260                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
261                         self["space_bar"].value = int(percent)
262                         if self.previous_size < MAX_SL:
263                                 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)
264                 elif size < MAX_SL:
265                         percent = 100 * size / float(MAX_SL)
266                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
267                         self["space_bar"].value = int(percent)
268                 self.previous_size = size
269
270         def getCurrentTitle(self):
271                 t = self["titles"].getCurrent()
272                 return t and t[0]
273
274         def editTitle(self, title = None, editor = True):
275                 t = title or self.getCurrentTitle()
276                 if t is not None:
277                         self.current_edit_title = t
278                         if editor:
279                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
280                         else:
281                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
282
283         def titleEditDone(self, cutlist):
284                 t = self.current_edit_title
285                 t.initDVDmenuText(self.project,len(self.project.titles))
286                 t.cuesheet = cutlist
287                 t.produceFinalCuesheet()
288                 if t.VideoType != 0:
289                         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)
290                 else:
291                         self.updateTitleList()
292
293         def resetTitles(self):
294                 count = 0
295                 for title in self.project.titles:
296                         count += 1
297                         title.initDVDmenuText(self.project,count)
298                 self.updateTitleList()
299
300         def DVDformatCB(self, answer):
301                 t = self.current_edit_title
302                 if answer == True:
303                         self.project.settings.authormode.setValue("data_ts")
304                         self.updateTitleList()
305                 else:
306                         self.removeTitle(t)
307
308         def leave(self):
309                 self.close()