From: Jean-Baptiste Mardelle Date: Sun, 4 Dec 2011 13:38:40 +0000 (+0100) Subject: * Fix crash when deleting clip and audio thumb was being created X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=d49a300ddcb728d616a8c72c52f095551cc7100f;p=kdenlive * Fix crash when deleting clip and audio thumb was being created * Fix possible crashes in clip transcoding * Fix user feedback on failed clip transcode --- diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index 58d6beda..43aa3227 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -127,16 +127,31 @@ void ClipManager::requestThumbs(const QString id, QList 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) diff --git a/src/clipmanager.h b/src/clipmanager.h index 008560f5..169341a0 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -156,6 +156,8 @@ private: // Private attributes QFuture 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 &); diff --git a/src/cliptranscode.cpp b/src/cliptranscode.cpp index 8dbf6df4..8f64c75e 100644 --- a/src/cliptranscode.cpp +++ b/src/cliptranscode.cpp @@ -32,6 +32,13 @@ ClipTranscode::ClipTranscode(KUrl::List urls, const QString ¶ms, 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 (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 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: "<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() + "
" + 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() + "
" + 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) diff --git a/src/cliptranscode.h b/src/cliptranscode.h index 84f2f784..8de1db82 100644 --- a/src/cliptranscode.h +++ b/src/cliptranscode.h @@ -25,6 +25,10 @@ #include "ui_cliptranscode_ui.h" #include +#include +#if KDE_IS_VERSION(4,7,0) +#include +#endif #include @@ -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); }; diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index 65593166..d5fc2db9 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -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; } diff --git a/src/docclipbase.h b/src/docclipbase.h index 6adbd2a2..8e0f6ac4 100644 --- a/src/docclipbase.h +++ b/src/docclipbase.h @@ -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(); diff --git a/src/renderwidget.cpp b/src/renderwidget.cpp index 24132878..ddab9192 100644 --- a/src/renderwidget.cpp +++ b/src/renderwidget.cpp @@ -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)