]> git.sesse.net Git - kdenlive/blob - src/dvdwizard.cpp
Krazy fixes: cleanup all headers
[kdenlive] / src / dvdwizard.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20
21 #include "dvdwizard.h"
22 #include "kdenlivesettings.h"
23 #include "profilesdialog.h"
24
25 #include <KStandardDirs>
26 #include <KLocale>
27 #include <KFileDialog>
28 #include <kmimetype.h>
29 #include <KIO/NetAccess>
30 #include <KMessageBox>
31
32 #include <QFile>
33 #include <QApplication>
34 #include <QTimer>
35 #include <QDomDocument>
36
37
38 DvdWizard::DvdWizard(const QString &url, const QString &profile, QWidget *parent): QWizard(parent), m_profile(profile) {
39     //setPixmap(QWizard::WatermarkPixmap, QPixmap(KStandardDirs::locate("appdata", "banner.png")));
40     setAttribute(Qt::WA_DeleteOnClose);
41     m_pageVob = new DvdWizardVob(this);
42     m_pageVob->setTitle(i18n("Select Files For Your DVD"));
43     addPage(m_pageVob);
44
45     if (!url.isEmpty()) m_pageVob->setUrl(url);
46
47     m_pageMenu = new DvdWizardMenu(m_profile, this);
48     m_pageMenu->setTitle(i18n("Create DVD Menu"));
49     addPage(m_pageMenu);
50
51
52     QWizardPage *page3 = new QWizardPage;
53     page3->setTitle(i18n("DVD Image"));
54     m_iso.setupUi(page3);
55     m_iso.tmp_folder->setPath(KdenliveSettings::currenttmpfolder());
56     m_iso.iso_image->setPath(QDir::homePath() + "/untitled.iso");
57     m_iso.iso_image->setFilter("*.iso");
58     m_iso.iso_image->fileDialog()->setOperationMode(KFileDialog::Saving);
59     addPage(page3);
60
61     QWizardPage *page4 = new QWizardPage;
62     page4->setTitle(i18n("Creating DVD Image"));
63     m_status.setupUi(page4);
64     addPage(page4);
65
66     connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotPageChanged(int)));
67
68 //    connect(m_standard.button_all, SIGNAL(toggled(bool)), this, SLOT(slotCheckStandard()));
69 }
70
71 DvdWizard::~DvdWizard() {
72     // m_menuFile.remove();
73 }
74
75
76 void DvdWizard::slotPageChanged(int page) {
77     kDebug() << "// PAGE CHGD: " << page;
78     if (page == 1) {
79         m_pageMenu->setTargets(m_pageVob->selectedUrls());
80     } else if (page == 2) {
81         m_pageMenu->buttonsInfo();
82     } else if (page == 3) {
83         // clear job icons
84         for (int i = 0; i < m_status.job_progress->count(); i++)
85             m_status.job_progress->item(i)->setIcon(KIcon());
86         QString warnMessage;
87         if (KIO::NetAccess::exists(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), KIO::NetAccess::SourceSide, this))
88             warnMessage.append(i18n("Folder %1 already exists. Overwrite ?<br />", m_iso.tmp_folder->url().path() + "/DVD"));
89         if (KIO::NetAccess::exists(KUrl(m_iso.iso_image->url().path()), KIO::NetAccess::SourceSide, this))
90             warnMessage.append(i18n("Image file %1 already exists. Overwrite ?", m_iso.iso_image->url().path()));
91
92         if (!warnMessage.isEmpty() && KMessageBox::questionYesNo(this, warnMessage) == KMessageBox::No) {
93             back();
94         } else {
95             KIO::NetAccess::del(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
96             QTimer::singleShot(300, this, SLOT(generateDvd()));
97         }
98     }
99 }
100
101
102
103 void DvdWizard::generateDvd() {
104     KTemporaryFile temp1;
105     temp1.setSuffix(".png");
106     //temp1.setAutoRemove(false);
107     temp1.open();
108
109     KTemporaryFile temp2;
110     temp2.setSuffix(".png");
111     //temp2.setAutoRemove(false);
112     temp2.open();
113
114     KTemporaryFile temp3;
115     temp3.setSuffix(".png");
116     //temp3.setAutoRemove(false);
117     temp3.open();
118
119     KTemporaryFile temp4;
120     temp4.setSuffix(".png");
121     //temp4.setAutoRemove(false);
122     temp4.open();
123
124     KTemporaryFile temp5;
125     temp5.setSuffix(".vob");
126     //temp5.setAutoRemove(false);
127     temp5.open();
128
129     KTemporaryFile temp6;
130     temp6.setSuffix(".xml");
131     //temp6.setAutoRemove(false);
132     temp6.open();
133
134     m_menuFile.setSuffix(".mpg");
135     m_menuFile.setAutoRemove(false);
136     m_menuFile.open();
137
138     m_authorFile.setSuffix(".xml");
139     m_authorFile.setAutoRemove(false);
140     m_authorFile.open();
141
142     QListWidgetItem *images =  m_status.job_progress->item(0);
143     images->setIcon(KIcon("system-run"));
144     qApp->processEvents();
145     QMap <int, QRect> buttons = m_pageMenu->buttonsInfo();
146     QStringList buttonsTarget;
147
148     if (m_pageMenu->createMenu()) {
149         m_pageMenu->createButtonImages(temp1.fileName(), temp2.fileName(), temp3.fileName());
150         m_pageMenu->createBackgroundImage(temp4.fileName());
151
152
153         images->setIcon(KIcon("dialog-ok"));
154
155         kDebug() << "/// STARTING MLT VOB CREATION";
156         if (!m_pageMenu->menuMovie()) {
157             // create menu vob file
158             QListWidgetItem *vobitem =  m_status.job_progress->item(1);
159             vobitem->setIcon(KIcon("system-run"));
160             qApp->processEvents();
161
162             QStringList args;
163             args.append("-profile");
164             if (m_pageMenu->isPalMenu()) args.append("dv_pal");
165             else  args.append("dv_ntsc");
166             args.append(temp4.fileName());
167             args.append("in=0");
168             args.append("out=100");
169             args << "-consumer" << "avformat:" + temp5.fileName();
170             if (m_pageMenu->isPalMenu()) {
171                 args << "f=dvd" << "vcodec=mpeg2video" << "acodec=ac3" << "b=5000k" << "maxrate=8000k" << "minrate=0" << "bufsize=1835008" << "mux_packet_s=2048" << "mux_rate=10080000" << "ab=192k" << "ar=48000" << "s=720x576" << "g=15" << "me_range=63" << "trellis=1" << "profile=dv_pal";
172             } else {
173                 args << "f=dvd" << "vcodec=mpeg2video" << "acodec=ac3" << "b=6000k" << "maxrate=9000k" << "minrate=0" << "bufsize=1835008" << "mux_packet_s=2048" << "mux_rate=10080000" << "ab=192k" << "ar=48000" << "s=720x480" << "g=18" << "me_range=63" << "trellis=1" << "profile=dv_ntsc";
174             }
175
176             kDebug() << "MLT ARGS: " << args;
177             QProcess renderbg;
178             renderbg.start("inigo", args);
179             if (renderbg.waitForFinished()) {
180                 if (renderbg.exitStatus() == QProcess::CrashExit) {
181                     kDebug() << "/// RENDERING MENU vob crashed";
182                     vobitem->setIcon(KIcon("dialog-close"));
183                     return;
184                 }
185             } else {
186                 kDebug() << "/// RENDERING MENU vob timed out";
187                 vobitem->setIcon(KIcon("dialog-close"));
188                 return;
189             }
190             vobitem->setIcon(KIcon("dialog-ok"));
191         }
192         kDebug() << "/// STARTING SPUMUX";
193
194         // create xml spumux file
195         QListWidgetItem *spuitem =  m_status.job_progress->item(2);
196         spuitem->setIcon(KIcon("system-run"));
197         qApp->processEvents();
198         QDomDocument doc;
199         QDomElement sub = doc.createElement("subpictures");
200         doc.appendChild(sub);
201         QDomElement stream = doc.createElement("stream");
202         sub.appendChild(stream);
203         QDomElement spu = doc.createElement("spu");
204         stream.appendChild(spu);
205         spu.setAttribute("force", "yes");
206         spu.setAttribute("start", "00:00:00.00");
207         spu.setAttribute("image", temp1.fileName());
208         spu.setAttribute("select", temp2.fileName());
209         spu.setAttribute("highlight", temp3.fileName());
210         /*spu.setAttribute("autooutline", "infer");
211         spu.setAttribute("outlinewidth", "12");
212         spu.setAttribute("autoorder", "rows");*/
213
214         int max = buttons.count() - 1;
215         int i = 0;
216         QMapIterator<int, QRect> it(buttons);
217         while (it.hasNext()) {
218             it.next();
219             QDomElement but = doc.createElement("button");
220             but.setAttribute("name", 'b' + QString::number(i));
221             if (i < max) but.setAttribute("down", 'b' + QString::number(i + 1));
222             else but.setAttribute("down", "b0");
223             if (i > 0) but.setAttribute("up", 'b' + QString::number(i - 1));
224             else but.setAttribute("up", 'b' + QString::number(max));
225             QRect r = it.value();
226             int target = it.key();
227             // TODO: solve play all button
228             if (target == 0) target = 1;
229             buttonsTarget.append(QString::number(target));
230             but.setAttribute("x0", QString::number(r.x()));
231             but.setAttribute("y0", QString::number(r.y()));
232             but.setAttribute("x1", QString::number(r.right()));
233             but.setAttribute("y1", QString::number(r.bottom()));
234             spu.appendChild(but);
235             i++;
236         }
237
238         kDebug() << "///// SPU: ";
239         kDebug() << doc.toString();
240
241         QFile data(temp6.fileName());
242         if (data.open(QFile::WriteOnly)) {
243             QTextStream out(&data);
244             out << doc.toString();
245         }
246         data.close();
247
248         kDebug() << " SPUMUX DATA: " << doc.toString();
249
250         QStringList args;
251         args.append(temp6.fileName());
252         kDebug() << "SPM ARGS: " << args << temp5.fileName() << m_menuFile.fileName();
253
254         QProcess spumux;
255
256         if (m_pageMenu->menuMovie()) spumux.setStandardInputFile(m_pageMenu->menuMoviePath());
257         else spumux.setStandardInputFile(temp5.fileName());
258         spumux.setStandardOutputFile(m_menuFile.fileName());
259         spumux.start("spumux", args);
260         spumux.setProcessChannelMode(QProcess::MergedChannels);
261         if (spumux.waitForFinished()) {
262             kDebug() << QString(spumux.readAll()).simplified();
263             if (spumux.exitStatus() == QProcess::CrashExit) {
264                 kDebug() << "/// RENDERING SPUMUX MENU crashed";
265                 spuitem->setIcon(KIcon("dialog-close"));
266                 return;
267             }
268         } else {
269             kDebug() << "/// RENDERING SPUMUX MENU timed out";
270             spuitem->setIcon(KIcon("dialog-close"));
271             return;
272         }
273
274         spuitem->setIcon(KIcon("dialog-ok"));
275         kDebug() << "/// DONE: " << m_menuFile.fileName();
276     }
277
278     // create dvdauthor xml
279     QListWidgetItem *authitem =  m_status.job_progress->item(3);
280     authitem->setIcon(KIcon("system-run"));
281     qApp->processEvents();
282     KIO::NetAccess::mkdir(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
283
284     QDomDocument dvddoc;
285     QDomElement auth = dvddoc.createElement("dvdauthor");
286     auth.setAttribute("dest", m_iso.tmp_folder->url().path() + "/DVD");
287     dvddoc.appendChild(auth);
288     QDomElement vmgm = dvddoc.createElement("vmgm");
289     auth.appendChild(vmgm);
290
291     if (m_pageMenu->createMenu() && !m_pageVob->introMovie().isEmpty()) {
292         // intro movie
293         QDomElement menus = dvddoc.createElement("menus");
294         vmgm.appendChild(menus);
295         QDomElement pgc = dvddoc.createElement("pgc");
296         pgc.setAttribute("entry", "title");
297         menus.appendChild(pgc);
298         QDomElement menuvob = dvddoc.createElement("vob");
299         menuvob.setAttribute("file", m_pageVob->introMovie());
300         pgc.appendChild(menuvob);
301         QDomElement post = dvddoc.createElement("post");
302         QDomText call = dvddoc.createTextNode("jump titleset 1 menu;");
303         post.appendChild(call);
304         pgc.appendChild(post);
305     }
306     QDomElement titleset = dvddoc.createElement("titleset");
307     auth.appendChild(titleset);
308
309     if (m_pageMenu->createMenu()) {
310
311         // DVD main menu
312         QDomElement menus = dvddoc.createElement("menus");
313         titleset.appendChild(menus);
314         QDomElement pgc = dvddoc.createElement("pgc");
315         pgc.setAttribute("entry", "root");
316         menus.appendChild(pgc);
317         for (int i = 0; i < buttons.count(); i++) {
318             QDomElement button = dvddoc.createElement("button");
319             button.setAttribute("name", 'b' + QString::number(i));
320             QDomText nametext = dvddoc.createTextNode("jump title " + buttonsTarget.at(i) + ';');
321             button.appendChild(nametext);
322             pgc.appendChild(button);
323         }
324         QDomElement menuvob = dvddoc.createElement("vob");
325         menuvob.setAttribute("file", m_menuFile.fileName());
326         menuvob.setAttribute("pause", "inf");
327         pgc.appendChild(menuvob);
328     }
329
330     QDomElement titles = dvddoc.createElement("titles");
331     titleset.appendChild(titles);
332
333     QStringList voburls = m_pageVob->selectedUrls();
334
335     QDomElement pgc2 = dvddoc.createElement("pgc");
336     titles.appendChild(pgc2);
337     if (m_pageMenu->createMenu()) {
338         QDomElement post = dvddoc.createElement("post");
339         QDomText call = dvddoc.createTextNode("call menu;");
340         post.appendChild(call);
341         pgc2.appendChild(post);
342     }
343
344
345     for (int i = 0; i < voburls.count(); i++) {
346         if (!voburls.at(i).isEmpty()) {
347             // Add vob entry
348             QDomElement vob = dvddoc.createElement("vob");
349             vob.setAttribute("file", voburls.at(i));
350             pgc2.appendChild(vob);
351         }
352     }
353
354     /*
355         // create one pgc for each video
356         for (int i = 0; i < voburls.count(); i++) {
357             if (!voburls.at(i).isEmpty()) {
358                 // Add vob entry
359
360          QDomElement pgc2 = dvddoc.createElement("pgc");
361          titles.appendChild(pgc2);
362          if (m_pageMenu->createMenu()) {
363       QDomElement post = dvddoc.createElement("post");
364       QDomText call = dvddoc.createTextNode("call vmgm menu 1;");
365       post.appendChild(call);
366       pgc2.appendChild(post);
367          }
368
369                 QDomElement vob = dvddoc.createElement("vob");
370                 vob.setAttribute("file", voburls.at(i));
371                 pgc2.appendChild(vob);
372             }
373         }
374     */
375     QFile data2(m_authorFile.fileName());
376     if (data2.open(QFile::WriteOnly)) {
377         QTextStream out(&data2);
378         out << dvddoc.toString();
379     }
380     data2.close();
381
382
383     QStringList args;
384     args << "-x" << m_authorFile.fileName();
385     kDebug() << "// DVDAUTH ARGS: " << args;
386     QProcess *dvdauth = new QProcess(this);
387     connect(dvdauth, SIGNAL(finished(int , QProcess::ExitStatus)), this, SLOT(slotRenderFinished(int, QProcess::ExitStatus)));
388     dvdauth->setProcessChannelMode(QProcess::MergedChannels);
389     dvdauth->start("dvdauthor", args);
390
391 }
392
393 void DvdWizard::slotRenderFinished(int exitCode, QProcess::ExitStatus status) {
394     QListWidgetItem *authitem =  m_status.job_progress->item(3);
395     if (status == QProcess::CrashExit) {
396         kDebug() << "DVDAuthor process crashed";
397         authitem->setIcon(KIcon("dialog-close"));
398         return;
399     }
400     authitem->setIcon(KIcon("dialog-ok"));
401     qApp->processEvents();
402     QStringList args;
403     args << "-dvd-video" << "-v" << "-o" << m_iso.iso_image->url().path() << m_iso.tmp_folder->url().path() + "/DVD";
404     QProcess *mkiso = new QProcess(this);
405     connect(mkiso, SIGNAL(finished(int , QProcess::ExitStatus)), this, SLOT(slotIsoFinished(int, QProcess::ExitStatus)));
406     mkiso->setProcessChannelMode(QProcess::MergedChannels);
407     QListWidgetItem *isoitem =  m_status.job_progress->item(4);
408     isoitem->setIcon(KIcon("system-run"));
409     mkiso->start("mkisofs", args);
410
411 }
412
413 void DvdWizard::slotIsoFinished(int exitCode, QProcess::ExitStatus status) {
414     QListWidgetItem *isoitem =  m_status.job_progress->item(4);
415     if (status == QProcess::CrashExit) {
416         m_authorFile.remove();
417         m_menuFile.remove();
418         KIO::NetAccess::del(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
419         kDebug() << "Iso process crashed";
420         isoitem->setIcon(KIcon("dialog-close"));
421         return;
422     }
423     isoitem->setIcon(KIcon("dialog-ok"));
424     kDebug() << "ISO IMAGE " << m_iso.iso_image->url().path() << " Successfully created";
425     m_authorFile.remove();
426     m_menuFile.remove();
427     KIO::NetAccess::del(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
428     KMessageBox::information(this, i18n("DVD iso image %1 successfully created.", m_iso.iso_image->url().path()));
429
430 }
431
432