* Fix crash when deleting clip and audio thumb was being created

* Fix possible crashes in clip transcoding
* Fix user feedback on failed clip transcode
parent 096fad7b
......@@ -127,16 +127,31 @@ void ClipManager::requestThumbs(const QString id, QList <int> frames)
void ClipManager::stopThumbs(const QString &id)
{
if (m_requestedThumbs.isEmpty() || m_closing) return;
if (m_closing || (m_requestedThumbs.isEmpty() && m_audioThumbsQueue.isEmpty() && m_processingAudioThumbId != id)) return;
// Abort video thumbs for this clip
m_abortThumb = true;
m_thumbsThread.waitForFinished();
m_thumbsMutex.lock();
m_requestedThumbs.remove(id);
m_audioThumbsQueue.removeAll(id);
m_thumbsMutex.unlock();
m_abortThumb = false;
// Abort audio thumbs for this clip
if (m_processingAudioThumbId == id) {
m_abortAudioThumb = true;
m_audioThumbsThread.waitForFinished();
m_abortAudioThumb = false;
}
if (!m_thumbsThread.isRunning() && !m_requestedThumbs.isEmpty()) {
m_thumbsThread = QtConcurrent::run(this, &ClipManager::slotGetThumbs);
}
if (!m_audioThumbsThread.isRunning() && !m_audioThumbsQueue.isEmpty()) {
m_audioThumbsThread = QtConcurrent::run(this, &ClipManager::slotGetAudioThumbs);
}
}
void ClipManager::slotGetThumbs()
......@@ -207,9 +222,9 @@ void ClipManager::slotGetAudioThumbs()
mlt_audio_format audioFormat = mlt_audio_pcm;
while (!m_abortAudioThumb && !m_audioThumbsQueue.isEmpty()) {
m_thumbsMutex.lock();
QString clipId = m_audioThumbsQueue.takeFirst();
m_processingAudioThumbId = m_audioThumbsQueue.takeFirst();
m_thumbsMutex.unlock();
DocClipBase *clip = getClipById(clipId);
DocClipBase *clip = getClipById(m_processingAudioThumbId);
if (!clip || clip->audioThumbCreated()) continue;
KUrl url = clip->fileURL();
QString hash = clip->getClipHash();
......@@ -312,6 +327,7 @@ void ClipManager::slotGetAudioThumbs()
clip->updateAudioThumbnail(storeIn);
}
}
m_processingAudioThumbId.clear();
}
void ClipManager::setThumbsProgress(const QString &message, int progress)
......
......@@ -156,6 +156,8 @@ private: // Private attributes
QFuture<void> m_audioThumbsThread;
/** @brief If true, abort processing of audio thumbs. */
bool m_abortAudioThumb;
/** @brief The id of currently processed clip for audio thumbs creation. */
QString m_processingAudioThumbId;
signals:
void reloadClip(const QString &);
......
......@@ -32,6 +32,13 @@ ClipTranscode::ClipTranscode(KUrl::List urls, const QString &params, const QStri
setFont(KGlobalSettings::toolBarFont());
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
#if KDE_IS_VERSION(4,7,0)
m_infoMessage = new KMessageWidget;
QGridLayout *s = static_cast <QGridLayout*> (layout());
s->addWidget(m_infoMessage, 10, 0, 1, -1);
m_infoMessage->setCloseButtonVisible(false);
m_infoMessage->hide();
#endif
log_text->setHidden(true);
setWindowTitle(i18n("Transcode Clip"));
auto_add->setText(i18np("Add clip to project", "Add clips to project", m_urls.count()));
......@@ -94,6 +101,9 @@ ClipTranscode::~ClipTranscode()
if (m_transcodeProcess.state() != QProcess::NotRunning) {
m_transcodeProcess.close();
}
#if KDE_IS_VERSION(4,7,0)
delete m_infoMessage;
#endif
}
void ClipTranscode::slotStartTransCode()
......@@ -102,10 +112,15 @@ void ClipTranscode::slotStartTransCode()
return;
}
m_duration = 0;
m_destination.clear();
#if KDE_IS_VERSION(4,7,0)
m_infoMessage->animatedHide();
#endif
QStringList parameters;
QString destination;
QString params = ffmpeg_params->toPlainText().simplified();
if (urls_list->count() > 0) {
if (m_urls.count() > 0 && urls_list->count() > 0) {
// We are processing multiple clips
source_url->setUrl(m_urls.takeFirst());
destination = dest_url->url().path(KUrl::AddTrailingSlash) + source_url->url().fileName();
QList<QListWidgetItem *> matching = urls_list->findItems(source_url->url().path(), Qt::MatchExactly);
......@@ -118,19 +133,19 @@ void ClipTranscode::slotStartTransCode()
}
QString extension = params.section("%1", 1, 1).section(' ', 0, 0);
QString s_url = source_url->url().path();
parameters << "-i" << s_url;
if (QFile::exists(destination + extension)) {
if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", destination + extension)) == KMessageBox::No) return;
parameters << "-y";
}
foreach(QString s, params.split(' '))
parameters << s.replace("%1", destination);
parameters << s.replace("%1", destination);
buttonBox->button(QDialogButtonBox::Abort)->setText(i18n("Abort"));
//kDebug() << "/// FFMPEG ARGS: " << parameters;
m_destination = destination + extension;
m_transcodeProcess.start("ffmpeg", parameters);
source_url->setEnabled(false);
dest_url->setEnabled(false);
button_start->setEnabled(false);
}
......@@ -138,11 +153,11 @@ void ClipTranscode::slotStartTransCode()
void ClipTranscode::slotShowTranscodeInfo()
{
QString log = QString(m_transcodeProcess.readAll());
int progress;
if (m_duration == 0) {
if (log.contains("Duration:")) {
QString data = log.section("Duration:", 1, 1).section(',', 0, 0).simplified();
QStringList numbers = data.split(':');
if (numbers.size() < 3) return;
m_duration = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
log_text->setHidden(true);
job_progress->setHidden(false);
......@@ -153,16 +168,16 @@ void ClipTranscode::slotShowTranscodeInfo()
}
}
else if (log.contains("time=")) {
int progress;
QString time = log.section("time=", 1, 1).simplified().section(' ', 0, 0);
if (time.contains(':')) {
QStringList numbers = time.split(':');
if (numbers.size() < 3) return;
progress = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
}
else progress = (int) time.toDouble();
kDebug()<<"// PROGRESS: "<<progress<<", "<<m_duration;
job_progress->setValue((int) (100.0 * progress / m_duration));
}
//kDebug() << "//LOG: " << log;
log_text->setPlainText(log);
}
......@@ -170,8 +185,14 @@ void ClipTranscode::slotTranscodeFinished(int exitCode, QProcess::ExitStatus exi
{
buttonBox->button(QDialogButtonBox::Abort)->setText(i18n("Close"));
button_start->setEnabled(true);
source_url->setEnabled(true);
dest_url->setEnabled(true);
m_duration = 0;
if (QFileInfo(m_destination).size() <= 0) {
// Destination file does not exist, transcoding failed
exitCode = 1;
}
if (exitCode == 0 && exitStatus == QProcess::NormalExit) {
log_text->setHtml(log_text->toPlainText() + "<br /><b>" + i18n("Transcoding finished."));
if (auto_add->isChecked()) {
......@@ -188,11 +209,33 @@ void ClipTranscode::slotTranscodeFinished(int exitCode, QProcess::ExitStatus exi
slotStartTransCode();
return;
} else if (auto_close->isChecked()) accept();
else {
#if KDE_IS_VERSION(4,7,0)
m_infoMessage->setMessageType(KMessageWidget::Positive);
m_infoMessage->setText(i18n("Transcoding finished."));
m_infoMessage->animatedShow();
#else
log_text->setVisible(true);
#endif
}
} else {
#if KDE_IS_VERSION(4,7,0)
m_infoMessage->setMessageType(KMessageWidget::Warning);
m_infoMessage->setText(i18n("Transcoding FAILED!"));
m_infoMessage->animatedShow();
#else
log_text->setHtml(log_text->toPlainText() + "<br /><b>" + i18n("Transcoding FAILED!"));
#endif
log_text->setVisible(true);
}
m_transcodeProcess.close();
//Refill url list in case user wants to transcode to another format
if (urls_list->count() > 0) {
m_urls.clear();
for (int i = 0; i < urls_list->count(); i++)
m_urls << urls_list->item(i)->text();
}
}
void ClipTranscode::slotUpdateParams(int ix)
......
......@@ -25,6 +25,10 @@
#include "ui_cliptranscode_ui.h"
#include <KUrl>
#include <kdeversion.h>
#if KDE_IS_VERSION(4,7,0)
#include <KMessageWidget>
#endif
#include <QProcess>
......@@ -47,7 +51,13 @@ private:
QProcess m_transcodeProcess;
KUrl::List m_urls;
int m_duration;
/** @brief The path for destination transcoded file. */
QString m_destination;
#if KDE_IS_VERSION(4,7,0)
KMessageWidget *m_infoMessage;
#endif
signals:
void addClip(KUrl url);
};
......
......@@ -87,10 +87,17 @@ DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QStrin
if (!m_properties.contains("name")) m_properties.insert("name", url.fileName());
m_thumbProd = new KThumb(clipManager, url, m_id, m_properties.value("file_hash"));
// Setup timer to trigger audio thumbs creation
m_audioTimer.setSingleShot(true);
m_audioTimer.setInterval(800);
connect(&m_audioTimer, SIGNAL(timeout()), m_thumbProd, SLOT(slotCreateAudioThumbs()));
}
DocClipBase::~DocClipBase()
{
m_audioTimer.stop();
delete m_thumbProd;
qDeleteAll(m_toDeleteProducers);
m_toDeleteProducers.clear();
......@@ -1098,7 +1105,7 @@ bool DocClipBase::getAudioThumbs()
if (m_audioThumbCreated) {
return false;
}
QTimer::singleShot(800, m_thumbProd, SLOT(slotCreateAudioThumbs()));
m_audioTimer.start();
return true;
}
......
......@@ -240,6 +240,9 @@ private: // Private attributes
/** Try to make sure we don't delete a producer while using it */
QMutex m_producerMutex;
QMutex m_replaceMutex;
/** @brief This timer will trigger creation of audio thumbnails. */
QTimer m_audioTimer;
/** Create connections for audio thumbnails */
void slotRefreshProducer();
......
......@@ -248,6 +248,9 @@ RenderWidget::~RenderWidget()
m_view.scripts_list->clear();
delete m_jobsDelegate;
delete m_scriptsDelegate;
#if KDE_IS_VERSION(4,7,0)
delete m_infoMessage;
#endif
}
void RenderWidget::slotEditItem(QListWidgetItem *item)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment