]> git.sesse.net Git - kdenlive/blob - src/projecttree/cutclipjob.cpp
Introduce MLT clip analysis, can now be used for getting auto normalize data in sox...
[kdenlive] / src / projecttree / cutclipjob.cpp
1 /***************************************************************************
2  *                                                                         *
3  *   Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
19  ***************************************************************************/
20
21 #include "cutclipjob.h"
22 #include "kdenlivesettings.h"
23 #include "kdenlivedoc.h"
24
25 #include <KDebug>
26 #include <KLocale>
27
28 CutClipJob::CutClipJob(CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(CUTJOB, cType, id, parameters)
29 {
30     jobStatus = JOBWAITING;
31     m_dest = parameters.at(0);
32     m_src = parameters.at(1);
33     m_start = parameters.at(2);
34     m_end = parameters.at(3);
35     if (m_start.isEmpty()) {
36         // this is a transcoding job
37         description = i18n("Transcode clip");
38     }
39     else description = i18n("Cut clip");
40     m_jobDuration = parameters.at(4).toInt();
41     addClipToProject = parameters.at(5).toInt();
42     replaceClip = false;
43     if (parameters.count() == 7) m_cutExtraParams = parameters.at(6).simplified();
44 }
45
46 void CutClipJob::startJob()
47 {
48     // Special case: playlist clips (.mlt or .kdenlive project files)
49     if (clipType == AV || clipType == AUDIO || clipType == VIDEO) {
50         QStringList parameters;
51         parameters << "-i" << m_src;
52         if (!m_start.isEmpty())
53             parameters << "-ss" << m_start <<"-t" << m_end;
54         if (!m_cutExtraParams.isEmpty()) {
55             foreach(const QString &s, m_cutExtraParams.split(' '))
56                 parameters << s;
57         }
58
59         // Make sure we don't block when proxy file already exists
60         parameters << "-y";
61         parameters << m_dest;
62         m_jobProcess = new QProcess;
63         m_jobProcess->setProcessChannelMode(QProcess::MergedChannels);
64         kDebug()<<"// STARTING CIUT JOS: "<<parameters;
65         m_jobProcess->start("ffmpeg", parameters);
66         m_jobProcess->waitForStarted();
67         while (m_jobProcess->state() != QProcess::NotRunning) {
68             processLogInfo();
69             if (jobStatus == JOBABORTED) {
70                 m_jobProcess->close();
71                 m_jobProcess->waitForFinished();
72                 QFile::remove(m_dest);
73             }
74             m_jobProcess->waitForFinished(400);
75         }
76         
77         if (jobStatus != JOBABORTED) {
78             int result = m_jobProcess->exitStatus();
79             if (result == QProcess::NormalExit) {
80                 if (QFileInfo(m_dest).size() == 0) {
81                     // File was not created
82                     processLogInfo();
83                     m_errorMessage.append(i18n("Failed to create file."));
84                     setStatus(JOBCRASHED);
85                 }
86                 else setStatus(JOBDONE);
87             }
88             else if (result == QProcess::CrashExit) {
89                 // Proxy process crashed
90                 QFile::remove(m_dest);
91                 setStatus(JOBCRASHED);
92             }
93         }
94         delete m_jobProcess;
95         return;
96     }
97     else m_errorMessage = i18n("Cannot process this clip type.");
98     setStatus(JOBCRASHED);
99     return;
100 }
101
102 void CutClipJob::processLogInfo()
103 {
104     if (!m_jobProcess || m_jobDuration == 0 || jobStatus == JOBABORTED) return;
105     QString log = m_jobProcess->readAll();
106     if (!log.isEmpty()) m_errorMessage.append(log + '\n');
107     int progress;
108     // Parse FFmpeg output
109     if (log.contains("frame=")) {
110         progress = log.section("frame=", 1, 1).simplified().section(' ', 0, 0).toInt();
111         emit jobProgress(m_clipId, (int) (100.0 * progress / m_jobDuration), jobType);
112     }
113     else if (log.contains("time=")) {
114         QString time = log.section("time=", 1, 1).simplified().section(' ', 0, 0);
115         if (time.contains(':')) {
116             QStringList numbers = time.split(':');
117             progress = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
118         }
119         else progress = (int) time.toDouble();
120         emit jobProgress(m_clipId, (int) (100.0 * progress / m_jobDuration), jobType);
121     }
122 }
123
124 CutClipJob::~CutClipJob()
125 {
126 }
127
128 const QString CutClipJob::destination() const
129 {
130     return m_dest;
131 }
132
133 stringMap CutClipJob::cancelProperties()
134 {
135     QMap <QString, QString> props;
136     return props;
137 }
138
139 const QString CutClipJob::statusMessage()
140 {
141     QString statusInfo;
142     switch (jobStatus) {
143         case JOBWORKING:
144             if (m_start.isEmpty()) statusInfo = i18n("Transcoding clip");
145             else statusInfo = i18n("Extracting clip cut");
146             break;
147         case JOBWAITING:
148             if (m_start.isEmpty()) statusInfo = i18n("Waiting - transcode clip");
149             else statusInfo = i18n("Waiting - cut clip");
150             break;
151         default:
152             break;
153     }
154     return statusInfo;
155 }
156
157 bool CutClipJob::isExclusive()
158 {
159     return false;
160 }
161