fix cuesheets, add multiple menu pages support, add preview support, add project...
[enigma2.git] / lib / python / Plugins / Extensions / DVDBurn / TitleList.py
1 import DVDProject, TitleList, TitleCutter
2
3 from Screens.Screen import Screen
4 from Screens.ChoiceBox import ChoiceBox
5 from Screens.InputBox import InputBox
6 from Screens.MessageBox import MessageBox
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 enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT
13
14 class WaitBox(MessageBox):
15         def __init__(self, session, callback):
16                 MessageBox.__init__(self, session, text=_("Preparing... Please wait"), type = MessageBox.TYPE_INFO)
17                 self.skinName = "MessageBox"
18                 self.CB = callback
19                 self.onShown.append(self.runCB)
20         
21         def ok(self):
22                 pass
23
24         def runCB(self):
25                 from enigma import eTimer
26                 self.delayTimer = eTimer()
27                 self.delayTimer.callback.append(self.CB)
28                 self.delayTimer.start(10,1)
29
30 class FileBrowser(Screen):
31         skin = """
32         <screen name="FileBrowser" position="100,100" size="520,376" title="DVD File Browser" >
33                 <widget name="filelist" position="0,0" size="520,376" scrollbarMode="showOnDemand" />
34         </screen>"""
35         def __init__(self, session, currDir = None, projectBrowser = False):
36                 Screen.__init__(self, session)
37                 self.projectBrowser = projectBrowser
38                 if not currDir:
39                         currDir = "/"
40
41                 if projectBrowser:
42                         self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(ddvdp\.xml)")
43                 else:
44                         self.filelist = FileList(currDir, matchingPattern = "(?i)^.*\.(jpeg|jpg|jpe|png|bmp)")
45                 self["filelist"] = self.filelist
46
47                 self["FilelistActions"] = ActionMap(["OkCancelActions"],
48                         {
49                                 "ok": self.ok,
50                                 "cancel": self.exit
51                         })
52
53         def ok(self):
54                 if self.filelist.canDescent():
55                         self.filelist.descent()
56                 else:
57                         ret = self["filelist"].getCurrentDirectory() + '/' + self["filelist"].getFilename()
58                         self.close(ret,self.projectBrowser)
59
60         def exit(self):
61                 self.close(None)
62
63
64 class TitleList(Screen):
65         skin = """
66                 <screen position="90,83" size="560,445" title="DVD Tool" >
67                     <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
68                     <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
69                     <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
70                     <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
71                     <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" />
72                     <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" />
73                     <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" />
74                     <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" />
75                     <widget source="title_label" render="Label" position="6,48" size="540,38" font="Regular;18" />
76                     <widget source="titles" render="Listbox" scrollbarMode="showOnDemand" position="10,86" size="540,312">
77                         <convert type="StaticMultiList" />
78                     </widget>
79                     <widget source="space_bar" render="Progress" position="10,410" size="540,26" borderWidth="1" backgroundColor="#254f7497" />
80                     <widget source="space_label" render="Label" position="40,414" size="480,22" zPosition="2" font="Regular;18" halign="center" transparent="1" foregroundColor="#000000" />
81                 </screen>"""
82
83         def __init__(self, session, project = None):
84                 Screen.__init__(self, session)
85                 
86                 self["titleactions"] = HelpableActionMap(self, "DVDTitleList",
87                         {
88                                 "addTitle": (self.addTitle, _("Add a new title"), _("Add title")),
89                                 "editTitle": (self.editTitle, _("Edit chapters of current title"), _("Edit title")),
90                                 "removeCurrentTitle": (self.removeCurrentTitle, _("Remove currently selected title"), _("Remove title")),
91                                 "saveProject": (self.saveProject, _("Save current project to disk"), _("Save")),
92                                 "burnProject": (self.burnProject, _("Burn DVD"), _("Burn DVD")),
93                         })
94
95                 self["MovieSelectionActions"] = HelpableActionMap(self, "MovieSelectionActions",
96                         {
97                                 "contextMenu": (self.showMenu, _("menu")),
98                         })
99
100                 self["key_red"] = StaticText(_("Add title"))
101                 self["key_green"] = StaticText(_("Edit title"))
102                 self["key_yellow"] = StaticText(_("Remove title"))
103                 self["key_blue"] = StaticText(_("Save"))
104
105                 self["title_label"] = StaticText()
106                 self["space_label"] = StaticText()
107                 self["space_bar"] = Progress()
108
109                 self["actions"] = ActionMap(["OkCancelActions"],
110                         {
111                                 "cancel": self.leave
112                         })
113
114                 #Action("addTitle", self.addTitle)
115                 
116                 if project is not None:
117                         self.project = project
118                 else:
119                         self.newProject()
120
121                 self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)])
122                 self.updateTitleList()
123                 self.updateCollectionName()
124                                 
125                 #self["addTitle"] = ActionButton("titleactions", "addTitle")
126                 #self["editTitle"] = ActionButton("titleactions", "editTitle")
127                 #self["removeCurrentTitle"] = ActionButton("titleactions", "removeCurrentTitle")
128                 #self["saveProject"] = ActionButton("titleactions", "saveProject")
129                 #self["burnProject"] = ActionButton("titleactions", "burnProject")
130                 
131         def showMenu(self):
132                 menu = []
133                 menu.append((_("Add a new title"), "addtitle"));
134                 menu.append((_("Remove title"), "removetitle"));
135                 menu.append((_("Edit chapters of current title"), "edittitle"));
136                 menu.append((_("Set collection name"), "setname"));
137                 menu.append((_("Set menu background"), "setbackground"));
138                 menu.append((_("Save current project to disk"), "save"));
139                 menu.append((_("Load saved project from disk"), "load"));
140                 menu.append((_("Preview menu"), "previewMenu"));
141                 menu.append((_("Burn DVD"), "burn"));
142                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title="", list=menu)
143
144         def menuCallback(self, choice):
145                 if choice is None:
146                         return
147
148                 if choice[1] == "removetitle":
149                         self.removeCurrentTitle()
150                 elif choice[1] == "addtitle":
151                         self.addTitle()
152                 elif choice[1] == "edittitle":
153                         self.editTitle()
154                 elif choice[1] == "setname":
155                         self.setName()
156                 elif choice[1] == "setbackground":
157                         self.showFileBrowser(False)
158                 elif choice[1] == "save":
159                         self.saveProject()
160                 elif choice[1] == "load":
161                         self.showFileBrowser(True)
162                 elif choice[1] == "previewMenu":
163                         self.previewMenu()
164                 elif choice[1] == "burn":
165                         self.burnProject()
166
167         def setName(self):
168                 self.session.openWithCallback(self.setNameCallback, InputBox, title=_("Set collection name"), text=self.project.name, maxSize=False, visible_width = 56)
169                 
170         def setNameCallback(self, name):
171                 if name is not None:
172                         self.project.name = name
173                         self.updateCollectionName()
174
175         def newProject(self):
176                 self.project = DVDProject.DVDProject()
177                 self.project.titles = [ ]
178                 self.project.session = self.session
179                 self.updateCollectionName()
180
181         def updateCollectionName(self):
182                 self["title_label"].text = _("Table of content for collection") + " \"" + self.project.name + "\":"
183
184         def addTitle(self):
185                 from Screens.MovieSelection import MovieSelection
186                 class MovieSelectionNoMenu(MovieSelection):
187                         def __init__(self, session):
188                                 MovieSelection.__init__(self, session)
189                                 self.skinName = "MovieSelection"
190
191                         def doContext(self):
192                                 print "context menu forbidden inside DVDBurn to prevent calling multiple instances"
193                                 
194                 self.session.openWithCallback(self.selectedSource, MovieSelectionNoMenu)
195
196         def selectedSource(self, source):
197                 if source is None:
198                         return None
199                 t = self.project.addService(source)
200                 self.editTitle(t, readOnly=True)
201
202         def removeCurrentTitle(self):
203                 title = self.getCurrentTitle()
204                 if title is not None:
205                         self.project.titles.remove(title)
206                         self.updateTitleList()
207
208         def saveProject(self):
209                 self.project.saveProject("/testProgs/dvd/")
210
211         def burnProject(self):
212                 self.project.waitboxref = self.project.session.open(WaitBox,self.burnProjectCB)
213
214         def burnProjectCB(self):
215                 import Process
216                 job = Process.Burn(self.session, self.project)
217                 from Screens.TaskView import JobView
218                 self.session.open(JobView, job)
219
220         def previewMenu(self):
221                 self.project.waitboxref = self.project.session.open(WaitBox,self.previewMenuCB)
222                 
223         def previewMenuCB(self):
224                 import Process
225                 job = Process.PreviewMenu(self.session, self.project)
226
227         def updateTitleList(self):
228                 res = [ ]
229                 totalsize = 0
230                 for title in self.project.titles:
231                         a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 10, 500, 50, 0, RT_HALIGN_LEFT, title.name)  ]
232                         res.append(a)
233                         totalsize += title.estimatedDiskspace
234                 self["titles"].list = res
235                 self.updateSize(totalsize)
236                 
237         def updateSize(self, totalsize):
238                 size = int((totalsize/1024)/1024)
239                 max_SL = 4370
240                 max_DL = 7950
241                 if size > max_DL:
242                         percent = 100 * size / float(max_DL)
243                         self["space_label"].text = "%d MB - " % size + _("exceeds dual layer medium!") + " (%.2f%% " % (100-percent) + _("free") + ")"
244                         self["space_bar"].value = int(percent)
245                 elif size > max_SL:
246                         percent = 100 * size / float(max_DL)
247                         self["space_label"].text = "%d MB  " % size + _("of a DUAL layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
248                         self["space_bar"].value = int(percent)
249                 elif size < max_SL:
250                         percent = 100 * size / float(max_SL)
251                         self["space_label"].text = "%d MB " % size + _("of a SINGLE layer medium used.") + " (%.2f%% " % (100-percent) + _("free") + ")"
252                         self["space_bar"].value = int(percent)
253
254         def getCurrentTitle(self):
255                 t = self["titles"].getCurrent()
256                 return t and t[0]
257
258         def editTitle(self, title = None, readOnly = False):
259                 t = title or self.getCurrentTitle()
260                 if t is not None:
261                         self.current_edit_title = t
262                         if readOnly:
263                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.CutlistReader, t)
264                         else:
265                                 self.session.openWithCallback(self.titleEditDone, TitleCutter.TitleCutter, t)
266
267         def titleEditDone(self, cutlist):
268                 t = self.current_edit_title
269                 t.cuesheet = cutlist
270                 t.produceFinalCuesheet()
271                 print "title edit of %s done, resulting cutlist:" % (t.source.toString()), t.cutlist, "chaptermarks:", t.chaptermarks
272                 self.updateTitleList()
273
274         def leave(self):
275                 self.close()
276
277         def showFileBrowser(self, projectBrowser=False):
278                 if projectBrowser:
279                         currDir = "/home/root"
280                 else:
281                         currDir = self.project.menubg
282                         if len(currDir) > 1:
283                                 currDir = (currDir.rstrip("/").rsplit("/",1))[0]
284                 self.session.openWithCallback(self.FileBrowserClosed, FileBrowser, currDir, projectBrowser)
285         
286         def FileBrowserClosed(self, path, projectBrowser=False):
287                 print "FileBrowserClosed", path, projectBrowser
288                 if projectBrowser:
289                         print "would load project", path
290                 else:
291                         self.project.menubg = path