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