dbc988b1cdf8a41ad16d3beb5de8e2dd7cb1a270
[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.MultiContent import MultiContentEntryText
14 from enigma import gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT
15 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
16
17 class TitleList(Screen, HelpableScreen):
18         skin = """
19                 <screen name="TitleList" position="center,center" 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" transparent="1" />
29                         <widget source="error_label" render="Label" position="10,48" size="540,395" zPosition="3" font="Regular;20" transparent="1" />
30                         <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="10,86" size="540,312" zPosition="3" transparent="1" >
31                                 <convert type="TemplatedMultiContent">
32                                         {"template": [
33                                                         MultiContentEntryText(pos = (0, 0), size = (420, 20), font = 0, flags = RT_HALIGN_LEFT, text = 1), # index 1 Title,
34                                                         MultiContentEntryText(pos = (0, 20), size = (328, 17), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 description,
35                                                         MultiContentEntryText(pos = (420, 6), size = (120, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 3), # index 3 begin time,
36                                                         MultiContentEntryText(pos = (328, 20), size = (154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = 4), # index 4 channel,
37                                                         MultiContentEntryText(pos = (482, 20), size = (58, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # index 4 channel,
38                                                 ],
39                                         "fonts": [gFont("Regular", 20), gFont("Regular", 14)],
40                                         "itemHeight": 37
41                                         }
42                                 </convert>
43                         </widget>
44                         <widget source="space_bar" render="Progress" position="10,410" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
45                         <widget source="space_label" render="Label" position="40,414" size="480,22" zPosition="2" font="Regular;18" halign="center" transparent="1" foregroundColor="#000000" />
46                 </screen>"""
47
48         def __init__(self, session, project = None):
49                 Screen.__init__(self, session)
50                 HelpableScreen.__init__(self)
51                 
52                 self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
53                         {
54                                 "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
55                                 "titleProperties": (self.titleProperties, _("Properties of current title"), _("Title properties")),
56                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
57                                 "settings": (self.settings, _("Collection settings"), _("Settings")),
58                                 "burnProject": (self.askBurnProject, _("Burn DVD"), _("Burn DVD")),
59                         })
60
61                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
62                         {
63                                 "contextMenu": (self.showMenu, _("menu")),
64                         })
65
66                 self["actions"] = ActionMap(["OkCancelActions"],
67                         {
68                                 "cancel": self.leave
69                         })
70
71                 self["key_red"] = StaticText()
72                 self["key_green"] = StaticText(_("Add title"))
73                 self["key_yellow"] = StaticText()
74                 self["key_blue"] = StaticText(_("Settings"))
75
76                 self["title_label"] = StaticText()
77                 self["error_label"] = StaticText()
78                 self["space_label"] = StaticText()
79                 self["space_bar"] = Progress()
80
81                 if project is not None:
82                         self.project = project
83                 else:
84                         self.newProject()
85
86                 self["titles"] = List([])
87                 self.updateTitleList()
88                 self.previous_size = 0
89                 self.onLayoutFinish.append(self.layoutFinished)
90
91         def layoutFinished(self):
92                 self.setTitle(_("DVD Titlelist"))
93
94         def checkBackgroundJobs(self):
95                 for job in job_manager.getPendingJobs():
96                         print "type(job):", type(job)
97                         print "Process.DVDJob:", Process.DVDJob
98                         if type(job) == Process.DVDJob:
99                                 self.backgroundJob = job
100                                 return
101                 self.backgroundJob = None
102
103         def showMenu(self):
104                 menu = []
105                 self.checkBackgroundJobs()
106                 if self.backgroundJob:
107                         j = self.backgroundJob
108                         menu.append(("%s: %s (%d%%)" % (j.getStatustext(), j.name, int(100*j.progress/float(j.end))), self.showBackgroundJob))
109                 menu.append((_("DVD media toolbox"), self.toolbox))
110                 menu.append((_("Preview menu"), self.previewMenu))
111                 if self.project.settings.output.getValue() == "dvd":
112                         if len(self["titles"].list):
113                                 menu.append((_("Burn DVD"), self.burnProject))
114                 elif self.project.settings.output.getValue() == "iso":
115                         menu.append((_("Create DVD-ISO"), self.burnProject))
116                 menu.append((_("Burn existing image to DVD"), self.selectImage))
117                 menu.append((_("Edit chapters of current title"), self.editTitle))
118                 menu.append((_("Reset and renumerate title names"), self.resetTitles))
119                 menu.append((_("Exit"), self.leave))
120                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
121
122         def menuCallback(self, choice):
123                 if choice:
124                         choice[1]()
125
126         def showBackgroundJob(self):
127                 job_manager.in_background = False
128                 self.session.openWithCallback(self.JobViewCB, JobView, self.backgroundJob)
129                 self.backgroundJob = None
130         
131         def titleProperties(self):
132                 if self.getCurrentTitle():
133                         self.session.openWithCallback(self.updateTitleList, TitleProperties.TitleProperties, self, self.project, self["titles"].getIndex())
134
135         def selectImage(self):
136                 self.session.openWithCallback(self.burnISO, ProjectSettings.FileBrowser, "image", self.project.settings)
137
138         def newProject(self):
139                 self.project = DVDProject.DVDProject()
140                 if self.loadTemplate():
141                         self.project.session = self.session
142                         self.settingsCB()
143
144         def addTitle(self):
145                 from Screens.MovieSelection import MovieSelection
146                 from Components.ActionMap import HelpableActionMap
147                 class DVDMovieSelection(MovieSelection):
148                         skin = """<screen name="DVDMovieSelection" position="center,center" size="560,445" title="Select a movie">
149                                 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
150                                 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
151                                 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
152                                 <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" />
153                                 <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" />
154                                 <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" />
155                                 <widget name="waitingtext" position="0,45" size="560,395" zPosition="4" font="Regular;22" halign="center" valign="center" />
156                                 <widget name="list" position="5,40" size="550,375" zPosition="2" scrollbarMode="showOnDemand" />
157                                 <widget name="DescriptionBorder" pixmap="skin_default/border_eventinfo.png" position="0,316" zPosition="1" size="560,103" transparent="1" alphatest="on" />
158                                 <widget source="Service" render="Label" position="5,318" zPosition="1" size="480,35" font="Regular;17" foregroundColor="#cccccc">
159                                         <convert type="MovieInfo">ShortDescription</convert>
160                                 </widget>
161                                 <widget source="Service" render="Label" position="495,318" zPosition="1" size="60,22" font="Regular;17" halign="right">
162                                         <convert type="ServiceTime">Duration</convert>
163                                         <convert type="ClockToText">AsLength</convert>
164                                 </widget>
165                                 <widget source="Service" render="Label" position="380,337" zPosition="2" size="175,22" font="Regular;17" halign="right">
166                                         <convert type="MovieInfo">RecordServiceName</convert>
167                                 </widget>
168                                 <widget source="Service" render="Label" position="5,357" zPosition="1" size="550,58" font="Regular;19">
169                                         <convert type="EventName">ExtendedDescription</convert>
170                                 </widget>
171                                 <widget name="freeDiskSpace" position="10,425" size="540,20" font="Regular;19" valign="center" halign="right" />
172                         </screen>"""
173                         def __init__(self, session):
174                                 MovieSelection.__init__(self, session)
175                                 self["key_red"] = StaticText(_("Close"))
176                                 self["key_green"] = StaticText(_("Add"))
177                                 self["key_yellow"] = StaticText(_("Edit title"))
178                                 self["ColorActions"] = HelpableActionMap(self, "ColorActions",
179                                 {
180                                         "red": (self.close, _("Close title selection")),
181                                         "green": (self.insertWithoutEdit, ("insert without cutlist editor")),
182                                         "yellow": (self.movieSelected, _("Add a new title"))
183                                 })
184                         def updateTags(self):
185                                 pass
186                         def doContext(self):
187                                 print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
188                         def insertWithoutEdit(self):
189                                 current = self.getCurrent()
190                                 if current is not None:
191                                         current.edit = False
192                                         self.close(current)
193                         def movieSelected(self):
194                                 current = self.getCurrent()
195                                 if current is not None:
196                                         current.edit = True
197                                         self.close(current)
198                 self.session.openWithCallback(self.selectedSource, DVDMovieSelection)
199
200         def selectedSource(self, source):
201                 if source is None:
202                         return None
203                 if not source.getPath().endswith(".ts"):
204                         self.session.open(MessageBox,text = _("You can only burn Dreambox recordings!"), type = MessageBox.TYPE_ERROR)
205                         return None
206                 t = self.project.addService(source)
207                 try:
208                         editor = source.edit
209                 except AttributeError:
210                         editor = True
211                 self.editTitle(t, editor)
212
213         def removeCurrentTitle(self):
214                 title = self.getCurrentTitle()
215                 self.removeTitle(title)
216         
217         def removeTitle(self, title):
218                 if title is not None:
219                         self.project.titles.remove(title)
220                         self.updateTitleList()
221
222         def toolbox(self):
223                 self.session.open(DVDToolbox.DVDToolbox)
224
225         def settings(self):
226                 self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
227
228         def settingsCB(self, update=True):
229                 if not update:
230                         return
231                 self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
232
233         def loadTemplate(self):
234                 filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVD.ddvdp.xml"
235                 if self.project.load(filename):
236                         self["error_label"].setText("")
237                         return True
238                 else:
239                         self["error_label"].setText(self.project.error)
240                         return False
241
242         def askBurnProject(self):
243                 if len(self["titles"].list):
244                         self.session.openWithCallback(self.burnProject,MessageBox,text = _("Do you want to burn this collection to DVD medium?"), type = MessageBox.TYPE_YESNO)
245
246         def burnProject(self, answer=True):
247                 if not answer:
248                         return
249                 if self.project.settings.authormode.getValue() == "data_ts":
250                         job = Process.DVDdataJob(self.project)
251                         job_manager.AddJob(job)
252                         job_manager.in_background = False
253                         self.session.openWithCallback(self.JobViewCB, JobView, job)
254                 else:
255                         job = Process.DVDJob(self.project)
256                         job_manager.AddJob(job)
257                         job_manager.in_background = False
258                         self.session.openWithCallback(self.JobViewCB, JobView, job)
259
260         def burnISO(self, path, scope, configRef):
261                 if path:
262                         job = Process.DVDisoJob(self.project, path)
263                         job_manager.AddJob(job)
264                         job_manager.in_background = False
265                         self.session.openWithCallback(self.JobViewCB, JobView, job)
266
267         def JobViewCB(self, in_background):
268                 job_manager.in_background = in_background
269
270         def previewMenu(self):
271                 job = Process.DVDJob(self.project, menupreview=True)
272                 job_manager.in_background = False
273                 job_manager.AddJob(job)
274
275         def updateTitleList(self):
276                 list = [ ]
277                 for title in self.project.titles:
278                         list.append((title, title.properties.menutitle.getValue(), title.properties.menusubtitle.getValue(), title.DVBchannel, title.formatDVDmenuText("$D.$M.$Y, $T", 0), title.formatDVDmenuText("$l", 0)))
279                 self["titles"].list = list
280                 self.updateSize()
281                 if len(list):
282                         self["key_red"].text = _("Remove title")
283                         self["key_yellow"].text = _("Title properties")
284                 else:
285                         self["key_red"].text = ""
286                         self["key_yellow"].text = ""
287
288         def updateSize(self):
289                 size = self.project.size/(1024*1024)
290                 MAX_DL = self.project.MAX_DL-100
291                 MAX_SL = self.project.MAX_SL-100
292                 print "updateSize:", size, "MAX_DL:", MAX_DL, "MAX_SL:", MAX_SL
293                 if size > MAX_DL:
294                         percent = 100 * size / float(MAX_DL)
295                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
296                         self["space_bar"].value = int(percent)
297                         if self.previous_size < MAX_DL:
298                                 self.session.open(MessageBox,text = _("exceeds dual layer medium!"), type = MessageBox.TYPE_ERROR)
299                 elif size > MAX_SL:
300                         percent = 100 * size / float(MAX_DL)
301                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
302                         self["space_bar"].value = int(percent)
303                         if self.previous_size < MAX_SL:
304                                 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)
305                 elif size < MAX_SL:
306                         percent = 100 * size / float(MAX_SL)
307                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
308                         self["space_bar"].value = int(percent)
309                 self.previous_size = size
310
311         def getCurrentTitle(self):
312                 t = self["titles"].getCurrent()
313                 return t and t[0]
314
315         def editTitle(self, title = None, editor = True):
316                 t = title or self.getCurrentTitle()
317                 if t is not None:
318                         self.current_edit_title = t
319                         if editor:
320                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
321                         else:
322                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
323
324         def titleEditDone(self, cutlist):
325                 t = self.current_edit_title
326                 t.initDVDmenuText(self.project,len(self.project.titles))
327                 t.cuesheet = cutlist
328                 t.produceFinalCuesheet()
329                 if t.VideoType != 0:
330                         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)
331                 else:
332                         self.updateTitleList()
333
334         def resetTitles(self):
335                 count = 0
336                 for title in self.project.titles:
337                         count += 1
338                         title.initDVDmenuText(self.project,count)
339                 self.updateTitleList()
340
341         def DVDformatCB(self, answer):
342                 t = self.current_edit_title
343                 if answer == True:
344                         self.project.settings.authormode.setValue("data_ts")
345                         self.updateTitleList()
346                 else:
347                         self.removeTitle(t)
348
349         def leave(self):
350                 self.close()