allow burning videos (also H.264) to data DVDs
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
1 import DVDProject, TitleList, TitleCutter, ProjectSettings
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 Components.ActionMap import HelpableActionMap, ActionMap
8 from Components.Sources.List import List
9 from Components.Sources.StaticText import StaticText
10 from Components.Sources.Progress import Progress
11 from Components.FileList import FileList
12 from Components.Label import Label
13 from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
14 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
15
16 class TitleList(Screen):
17         skin = """
18                 <screen position="90,83" 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" />
28                     <widget name="error_label" position="10,48" size="540,395" zPosition="3" font="Regular;20" />
29                     <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="10,86" size="540,312">
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                 
39                 self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
40                         {
41                                 "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
42                                 "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")),
43                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
44                                 "settings": (self.settings, _("Collection settings"), _("Settings")),
45                                 "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
46                         })
47
48                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
49                         {
50                                 "contextMenu": (self.showMenu, _("menu")),
51                         })
52
53                 self["actions"] = ActionMap(["OkCancelActions"],
54                         {
55                                 "cancel": self.leave
56                         })
57
58                 self["key_red"] = StaticText(_("Remove title"))
59                 self["key_green"] = StaticText(_("Add title"))
60                 self["key_yellow"] = StaticText(_("Edit title"))
61                 self["key_blue"] = StaticText(_("Settings"))
62
63                 self["title_label"] = StaticText()
64                 self["error_label"] = Label("")
65                 self["space_label"] = StaticText()
66                 self["space_bar"] = Progress()
67
68                 if project is not None:
69                         self.project = project
70                 else:
71                         self.newProject()
72
73                 self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)])
74                 self.updateTitleList()
75                                 
76                 #self["addTitle"] = ActionButton("titleactions", "addTitle")
77                 #self["editTitle"] = ActionButton("titleactions", "editTitle")
78                 #self["removeCurrentTitle"] = ActionButton("titleactions", "removeCurrentTitle")
79                 #self["saveProject"] = ActionButton("titleactions", "saveProject")
80                 #self["burnProject"] = ActionButton("titleactions", "burnProject")
81                 
82         def showMenu(self):
83                 menu = []
84                 menu.append((_("Burn DVD"), "burn"));
85                 menu.append((_("Preview menu"), "previewMenu"));
86                 menu.append((_("Collection settings"), "settings"));
87                 menu.append((_("Add a new title"), "addtitle"));
88                 menu.append((_("Remove title"), "removetitle"));
89                 menu.append((_("Edit chapters of current title"), "edittitle"));
90                 menu.append((_("Exit"), "exit"));
91                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
92
93         def menuCallback(self, choice):
94                 if choice is None:
95                         return
96                 if choice[1] == "removetitle":
97                         self.removeCurrentTitle()
98                 elif choice[1] == "addtitle":
99                         self.addTitle()
100                 elif choice[1] == "edittitle":
101                         self.editTitle()
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                 class MovieSelectionNoMenu(MovieSelection):
120                         def __init__(self, session):
121                                 MovieSelection.__init__(self, session)
122                                 self.skinName = "MovieSelection"
123
124                         def doContext(self):
125                                 print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
126                                 
127                 self.session.openWithCallback(self.selectedSource, MovieSelectionNoMenu)
128
129         def selectedSource(self, source):
130                 if source is None:
131                         return None
132                 t = self.project.addService(source)
133                 self.editTitle(t, readOnly=False)
134
135         def removeCurrentTitle(self):
136                 title = self.getCurrentTitle()
137                 self.removeTitle(title)
138         
139         def removeTitle(self, title):
140                 if title is not None:
141                         self.project.titles.remove(title)
142                         self.updateTitleList()
143
144         def settings(self):
145                 self.session.openWithCallback(self.settingsCB, ProjectSettings.ProjectSettings, self.project)
146
147         def settingsCB(self, update=True):
148                 if not update:
149                         return
150                 self["title_label"].text = _("Table of content for collection") + " \"" + self.project.settings.name.getValue() + "\":"
151
152         def loadTemplate(self):
153                 filename = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/DreamboxDVDtemplate.ddvdp.xml"
154                 if self.project.loadProject(filename):
155                         self["error_label"].hide()
156                         return True
157                 else:
158                         self["error_label"].text = self.project.error
159                         self["error_label"].show()
160                         print self.project.error
161                         return False
162
163         def burnProject(self):
164                 if self.project.settings.authormode.getValue() == "data_ts":
165                         import Process
166                         job = Process.BurnDataTS(self.session, self.project)
167                         from Screens.TaskView import JobView
168                         self.session.open(JobView, job)
169                 else:
170                         autochapter = self.project.settings.autochapter.getValue()
171                         if autochapter > 0:
172                                 for title in self.project.titles:
173                                         title.produceAutoChapter(autochapter)
174                         self.project.waitboxref = self.project.session.open(ProjectSettings.WaitBox,self.burnProjectCB)
175
176         def burnProjectCB(self):
177                 import Process
178                 job = Process.Burn(self.session, self.project)
179                 from Screens.TaskView import JobView
180                 self.session.open(JobView, job)
181
182         def previewMenu(self):
183                 self.project.waitboxref = self.project.session.open(ProjectSettings.WaitBox,self.previewMenuCB)
184                 
185         def previewMenuCB(self):
186                 import Process
187                 job = Process.PreviewMenu(self.session, self.project)
188
189         def updateTitleList(self):
190                 res = [ ]
191                 totalsize = 0
192                 for title in self.project.titles:
193                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name)  ]
194                         res.append(a)
195                         totalsize += title.estimatedDiskspace
196                 self["titles"].list = res
197                 self.updateSize(totalsize)
198                 
199         def updateSize(self, totalsize):
200                 size = int((totalsize/1024)/1024)
201                 max_SL = 4370
202                 max_DL = 7950
203                 if size > max_DL:
204                         percent = 100 * size / float(max_DL)
205                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
206                         self["space_bar"].value = int(percent)
207                 elif size > max_SL:
208                         percent = 100 * size / float(max_DL)
209                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
210                         self["space_bar"].value = int(percent)
211                 elif size < max_SL:
212                         percent = 100 * size / float(max_SL)
213                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
214                         self["space_bar"].value = int(percent)
215
216         def getCurrentTitle(self):
217                 t = self["titles"].getCurrent()
218                 return t and t[0]
219
220         def editTitle(self, title = None, readOnly = False):
221                 t = title or self.getCurrentTitle()
222                 if t is not None:
223                         self.current_edit_title = t
224                         if readOnly:
225                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
226                         else:
227                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
228
229         def titleEditDone(self, cutlist):
230                 t = self.current_edit_title
231                 t.cuesheet = cutlist
232                 t.produceFinalCuesheet()
233                 if t.sVideoType != 0:
234                         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)
235                 else:
236                         self.updateTitleList()
237
238         def DVDformatCB(self, answer):
239                 t = self.current_edit_title
240                 if answer == True:
241                         self.project.settings.authormode.setValue("data_ts")
242                         self.updateTitleList()
243                 else:
244                         self.removeTitle(t)
245
246         def leave(self):
247                 self.close()