1 from Components.Task import Task, Job, job_manager, DiskspacePrecondition, Condition
4 def __init__(self, job, inputfile, cutlist):
5 Task.__init__(self, job, "Demux video into ES")
7 self.global_preconditions.append(DiskspacePrecondition(4*1024*1024))
8 self.setTool("/opt/bin/projectx")
9 self.cutfile = self.job.workspace + "/cut.Xcl"
10 self.generated_files = [ ]
11 self.cutlist = cutlist
17 self.args += [inputfile, "-demux", "-out", self.job.workspace, "-cut", self.job.workspace + "/" + self.cutfile ]
22 def processOutputLine(self, line):
24 MSG_NEW_FILE = "---> new File: "
25 MSG_PROGRESS = "[PROGRESS] "
27 if line.startswith(MSG_NEW_FILE):
28 file = line[len(MSG_NEW_FILE):]
31 self.haveNewFile(file)
32 elif line.startswith(MSG_PROGRESS):
33 progress = line[len(MSG_PROGRESS):]
34 self.haveProgress(progress)
36 def haveNewFile(self, file):
37 print "PRODUCED FILE [%s]" % file
38 self.generated_files.append(file)
40 def haveProgress(self, progress):
41 print "PROGRESS [%s]" % progress
42 MSG_CHECK = "check & synchronize audio file"
44 if progress == "preparing collection(s)...":
46 elif progress[:len(MSG_CHECK)] == MSG_CHECK:
50 print "have progress:", progress
52 p = p - 1 + self.prog_state * 100
59 def writeCutfile(self):
60 f = open(self.cutfile, "w")
61 f.write("CollectionPanel.CutMode=4\n")
62 for p in self.cutlist:
70 f.write("%02d:%02d:%02d\n" % (h, m, s))
73 def cleanup(self, failed):
76 for f in self.generated_files:
79 class MplexTask(Task):
80 def __init__(self, job, outputfile, demux_task):
81 Task.__init__(self, job, "Mux ES into PS")
84 self.demux_task = demux_task
85 self.setTool("/usr/bin/mplex")
86 self.args += ["-f8", "-o", self.job.workspace + "/" + outputfile, "-v1"]
89 self.args += self.demux_task.generated_files
91 class RemoveESFiles(Task):
92 def __init__(self, job, demux_task):
93 Task.__init__(self, job, "Remove temp. files")
94 self.demux_task = demux_task
95 self.setTool("/bin/rm")
99 self.args += self.demux_task.generated_files
100 self.args += [self.demux_task.cutfile]
102 class DVDAuthorTask(Task):
103 def __init__(self, job, inputfiles, chapterlist):
104 Task.__init__(self, job, "dvdauthor")
107 self.setTool("/usr/bin/dvdauthor")
108 chapterargs = "--chapters=" + ','.join(["%d:%02d:%02d.%03d" % (p / (90000 * 3600), p % (90000 * 3600) / (90000 * 60), p % (90000 * 60) / 90000, (p % 90000) / 90) for p in chapterlist])
109 self.args += ["-t", chapterargs, "-o", self.job.workspace + "/dvd", "-f"] + inputfiles
111 class RemovePSFile(Task):
112 def __init__(self, job, psfile):
113 Task.__init__(self, job, "Remove temp. files")
114 self.setTool("/bin/rm")
115 self.args += ["-f", psfile]
117 class DVDAuthorFinalTask(Task):
118 def __init__(self, job):
119 Task.__init__(self, job, "dvdauthor finalize")
120 self.setTool("/usr/bin/dvdauthor")
121 self.args += ["-T", "-o", self.job.workspace + "/dvd"]
123 class BurnTaskPostcondition(Condition):
124 def check(self, task):
125 return task.error is None
127 def getErrorMessage(self, task):
129 task.ERROR_MEDIA: ("Medium is not a writeable DVD!"),
130 task.ERROR_SIZE: ("Content does not fit on DVD!"),
131 task.ERROR_WRITE_FAILED: ("Write failed!"),
132 task.ERROR_DVDROM: ("No (supported) DVDROM found!"),
133 task.ERROR_UNKNOWN: ("An unknown error occured!")
136 class BurnTask(Task):
137 ERROR_MEDIA, ERROR_SIZE, ERROR_WRITE_FAILED, ERROR_DVDROM, ERROR_UNKNOWN = range(5)
138 def __init__(self, job):
139 Task.__init__(self, job, "burn")
142 self.end = 120 # 100 for writing, 10 for buffer flush, 10 for closing disc
143 self.postconditions.append(BurnTaskPostcondition())
144 self.setTool("/bin/growisofs")
145 self.args += ["-dvd-video", "-dvd-compat", "-Z", "/dev/cdroms/cdrom0", "-V", "Dreambox_DVD", "-use-the-force-luke=dummy", self.job.workspace + "/dvd"]
150 def processOutputLine(self, line):
152 print "[GROWISOFS] %s" % line
153 if line[8:14] == "done, ":
154 self.progress = float(line[:6])
155 print "progress:", self.progress
156 elif line.find("flushing cache") != -1:
158 elif line.find("closing disc") != -1:
160 elif line.startswith(":-["):
161 if line.find("ASC=30h") != -1:
162 self.error = self.ERROR_MEDIA
164 self.error = self.ERROR_UNKNOWN
165 print "BurnTask: unknown error %s" % line
166 elif line.startswith(":-("):
167 if line.find("No space left on device") != -1:
168 self.error = self.ERROR_SIZE
169 elif line.find("write failed") != -1:
170 self.error = self.ERROR_WRITE_FAILED
171 elif line.find("unable to open64(\"/dev/cdroms/cdrom0\",O_RDONLY): No such file or directory") != -1: # fixme
172 self.error = self.ERROR_DVDROM
173 elif line.find("media is not recognized as recordable DVD") != -1:
174 self.error = self.ERROR_MEDIA
176 self.error = self.ERROR_UNKNOWN
177 print "BurnTask: unknown error %s" % line
179 class RemoveDVDFolder(Task):
180 def __init__(self, job):
181 Task.__init__(self, job, "Remove temp. files")
182 self.setTool("/bin/rm")
183 self.args += ["-rf", self.job.workspace]
186 def __init__(self, cue):
187 Job.__init__(self, "DVD Burn")
189 from time import strftime
190 from Tools.Directories import SCOPE_HDD, resolveFilename, createDir
191 new_workspace = resolveFilename(SCOPE_HDD) + "tmp/" + strftime("%Y%m%d%H%M%S")
192 createDir(new_workspace)
193 self.workspace = new_workspace
194 self.fromDescription(self.createDescription())
196 def fromDescription(self, description):
197 nr_titles = int(description["nr_titles"])
199 for i in range(nr_titles):
200 inputfile = description["inputfile%d" % i]
201 cutlist_entries = description["cutlist%d_entries" % i]
203 for j in range(cutlist_entries):
204 cutlist.append(int(description["cutlist%d_%d" % (i, j)]))
206 chapterlist_entries = description["chapterlist%d_entries" % i]
208 for j in range(chapterlist_entries):
209 chapterlist.append(int(description["chapterlist%d_%d" % (i, j)]))
211 demux = DemuxTask(self, inputfile = inputfile, cutlist = cutlist)
213 title_filename = self.workspace + "/dvd_title_%d.mpg" % i
215 MplexTask(self, "dvd_title_%d.mpg" % i, demux)
216 RemoveESFiles(self, demux)
217 DVDAuthorTask(self, [title_filename], chapterlist = chapterlist)
218 RemovePSFile(self, title_filename)
219 DVDAuthorFinalTask(self)
221 RemoveDVDFolder(self)
223 def createDescription(self):
224 # self.cue is a list of titles, with
225 # each title being a tuple of
227 # a list of cutpoints (in,out)
228 # a list of chaptermarks
229 # we turn this into a flat dict with
230 # nr_titles = the number of titles,
231 # cutlist%d_entries = the number of cutlist entries for title i,
232 # cutlist%d_%d = cutlist entry j for title i,
233 # chapterlist%d_entries = the number of chapters for title i,
234 # chapterlist%d_%d = chapter j for title i
235 res = { "nr_titles": len(self.cue) }
236 for i in range(len(self.cue)):
238 res["inputfile%d" % i] = c[0]
239 res["cutlist%d_entries" % i] = len(c[1])
240 for j in range(len(c[1])):
241 res["cutlist%d_%d" % (i,j)] = c[1][j]
243 res["chapterlist%d_entries" % i] = len(c[2])
244 for j in range(len(c[2])):
245 res["chapterlist%d_%d" % (i,j)] = c[2][j]
248 def Burn(session, cue):
249 print "burning cuesheet!"
251 job_manager.AddJob(j)