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