Hello community, here is the log from the commit of package kdenlive for openSUSE:Factory checked in at 2016-06-25 02:01:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kdenlive (Old) and /work/SRC/openSUSE:Factory/.kdenlive.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kdenlive" Changes: -------- --- /work/SRC/openSUSE:Factory/kdenlive/kdenlive.changes 2016-05-29 03:09:46.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kdenlive.new/kdenlive.changes 2016-06-25 02:01:22.000000000 +0200 @@ -1,0 +2,8 @@ +Fri Jun 10 17:55:36 UTC 2016 - tittiatc...@gmail.com + +- Update to KDE Applications 16.04.2 + * KDE Applications 16.04.2 + * https://www.kde.org/announcements/announce-applications-16.04.2.php + + +------------------------------------------------------------------- Old: ---- kdenlive-16.04.1.tar.xz New: ---- kdenlive-16.04.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kdenlive.spec ++++++ --- /var/tmp/diff_new_pack.XXwRot/_old 2016-06-25 02:01:23.000000000 +0200 +++ /var/tmp/diff_new_pack.XXwRot/_new 2016-06-25 02:01:23.000000000 +0200 @@ -19,13 +19,13 @@ %define mlt_version 0.9.6 Name: kdenlive -Version: 16.04.1 +Version: 16.04.2 Release: 0 Summary: Non-linear video editor License: GPL-3.0+ Group: Productivity/Multimedia/Video/Editors and Convertors Url: http://www.kdenlive.org/ -Source0: http://download.kde.org/stable/applications/16.04.1/src/%{name}-%{version}.tar.xz +Source0: http://download.kde.org/stable/applications/16.04.2/src/%{name}-%{version}.tar.xz Patch1: use-mlt_datadir.patch BuildRequires: desktop-file-utils BuildRequires: fdupes ++++++ kdenlive-16.04.1.tar.xz -> kdenlive-16.04.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/CMakeLists.txt new/kdenlive-16.04.2/CMakeLists.txt --- old/kdenlive-16.04.1/CMakeLists.txt 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/CMakeLists.txt 2016-06-09 19:50:38.000000000 +0200 @@ -6,7 +6,7 @@ # KDE Application Version, managed by release script set (KDE_APPLICATIONS_VERSION_MAJOR "16") set (KDE_APPLICATIONS_VERSION_MINOR "04") -set (KDE_APPLICATIONS_VERSION_MICRO "1") +set (KDE_APPLICATIONS_VERSION_MICRO "2") set(KDENLIVE_VERSION ${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}) cmake_minimum_required(VERSION 2.8.12) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/bin.cpp new/kdenlive-16.04.2/src/bin/bin.cpp --- old/kdenlive-16.04.1/src/bin/bin.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/bin.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -176,7 +176,7 @@ bg = scheme.background(KColorScheme::ActiveBackground).color(); fg = scheme.foreground(KColorScheme::ActiveText).color(); style.append(QStringLiteral("\nQPushButton:hover {margin:3px;padding:2px;background-color: rgb(%1, %2, %3);border-radius: 4px;border: none;color: rgb(%4, %5, %6)}").arg(bg.red()).arg(bg.green()).arg(bg.blue()).arg(fg.red()).arg(fg.green()).arg(fg.blue())); - + return style; } @@ -1354,6 +1354,7 @@ m_showDate->setChecked(!view->isColumnHidden(1)); m_showDesc->setChecked(!view->isColumnHidden(2)); connect(view->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(slotSaveHeaders())); + connect(view->header(), SIGNAL(sectionClicked(int)), this, SLOT(slotSaveHeaders())); connect(view, SIGNAL(focusView()), this, SLOT(slotGotFocus())); } else if (m_listType == BinIconView) { @@ -2861,9 +2862,13 @@ QString titlepath = m_doc->projectFolder().path() + QDir::separator() + "titles/"; TitleWidget dia_ui(QUrl(), m_doc->timecode(), titlepath, pCore->monitorManager()->projectMonitor()->render, pCore->window()); connect(&dia_ui, SIGNAL(requestBackgroundFrame()), pCore->monitorManager()->projectMonitor(), SLOT(slotGetCurrentImage())); + if (!path.isEmpty()) { + dia_ui.loadTitle(QUrl::fromLocalFile(path)); + } else { QDomDocument doc; doc.setContent(clip->getProducerProperty(QStringLiteral("xmldata"))); dia_ui.setXml(doc); + } if (dia_ui.exec() == QDialog::Accepted) { QMap <QString, QString> newprops; newprops.insert(QStringLiteral("xmldata"), dia_ui.xml().toString()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/generators/generators.cpp new/kdenlive-16.04.2/src/bin/generators/generators.cpp --- old/kdenlive-16.04.1/src/bin/generators/generators.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/generators/generators.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -166,10 +166,12 @@ return getSavedClip(url.path()); } } + Mlt::Tractor trac(*m_producer->profile()); m_producer->set("length", m_timePos->getValue()); m_producer->set_in_and_out(0, m_timePos->getValue() - 1); + trac.set_track(*m_producer, 0); Mlt::Consumer c(*m_producer->profile(), "xml", url.path().toUtf8().constData()); - c.connect(*m_producer); + c.connect(trac); c.run(); return url; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/projectclip.cpp new/kdenlive-16.04.2/src/bin/projectclip.cpp --- old/kdenlive-16.04.1/src/bin/projectclip.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/projectclip.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -919,6 +919,8 @@ void ProjectClip::slotCreateAudioThumbs() { QMutexLocker lock(&m_audioMutex); + if (m_audioThumbsProcess.state() != QProcess::NotRunning) + return; Mlt::Producer *prod = originalProducer(); if (!prod || !prod->is_valid()) return; AudioStreamInfo *audioInfo = m_controller->audioInfo(); @@ -948,6 +950,7 @@ updateAudioThumbnail(audioLevels); return; } + bool jobFinished = false; if (KdenliveSettings::ffmpegaudiothumbnails() && m_type != Playlist) { QStringList args; @@ -962,6 +965,8 @@ channelFiles << channelTmpfile; } args << QStringLiteral("-i") << QUrl::fromLocalFile(prod->get("resource")).path(); + // Output progress info + args << QStringLiteral("-progress") << QStringLiteral("/dev/stdout"); bool isFFmpeg = KdenliveSettings::ffmpegpath().contains("ffmpeg"); @@ -995,82 +1000,83 @@ } } emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWaiting, 0); - QProcess audioThumbsProcess; - connect(this, SIGNAL(doAbortAudioThumbs()), &audioThumbsProcess, SLOT(kill()), Qt::DirectConnection); - audioThumbsProcess.start(KdenliveSettings::ffmpegpath(), args); + connect(this, SIGNAL(doAbortAudioThumbs()), &m_audioThumbsProcess, SLOT(kill()), Qt::DirectConnection); + connect(&m_audioThumbsProcess, &QProcess::readyReadStandardOutput, this, &ProjectClip::updateFfmpegProgress); + m_audioThumbsProcess.start(KdenliveSettings::ffmpegpath(), args); bool ffmpegError = false; - if (!audioThumbsProcess.waitForStarted()) { + if (!m_audioThumbsProcess.waitForStarted()) { ffmpegError = true; } - audioThumbsProcess.waitForFinished(); + m_audioThumbsProcess.waitForFinished(-1); if (m_abortAudioThumb) { emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0); m_abortAudioThumb = false; return; } - if (ffmpegError || audioThumbsProcess.exitStatus() == QProcess::CrashExit) { - emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0); - bin()->emitMessage(i18n("Crash in %1 - creating audio thumbnails", KdenliveSettings::ffmpegpath()), ErrorMessage); - return; - } - int dataSize = 0; - QList <const qint16*> rawChannels; - QList <QByteArray> sourceChannels; - QList<qint16> data2; - for (int i = 0; i < channelFiles.count(); i++) { - channelFiles[i]->open(); - QByteArray res = channelFiles[i]->readAll(); - channelFiles[i]->close(); - if (dataSize == 0) { - dataSize = res.size(); - } - if (res.isEmpty() || res.size() != dataSize) { - // Something went wrong, abort - emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0); - bin()->emitMessage(i18n("Error reading audio thumbnail"), ErrorMessage); - return; - } - rawChannels << (const qint16*) res.constData(); - // We need to keep res2 alive or rawChannels data will die - sourceChannels << res; - } - int progress = 0; - QList <long> channelsData; - double offset = (double) dataSize / (2.0 * lengthInFrames); - int intraOffset = 1; - if (offset > 1000) { - intraOffset = offset / 60; - } else if (offset > 250) { - intraOffset = offset / 10; - } - double factor = 800.0 / 32768; - for (int i = 0; i < lengthInFrames; i++) { - channelsData.clear(); - for (int k = 0; k < rawChannels.count(); k++) { - channelsData << 0; - } - int pos = (int) (i * offset); - int steps = 0; - for (int j = 0; j < (int) offset && (pos + j < dataSize); j += intraOffset) { - steps ++; + if (!ffmpegError && m_audioThumbsProcess.exitStatus() != QProcess::CrashExit) { + int dataSize = 0; + QList <const qint16*> rawChannels; + QList <QByteArray> sourceChannels; + QList<qint16> data2; + for (int i = 0; i < channelFiles.count(); i++) { + channelFiles[i]->open(); + QByteArray res = channelFiles[i]->readAll(); + channelFiles[i]->close(); + if (dataSize == 0) { + dataSize = res.size(); + } + if (res.isEmpty() || res.size() != dataSize) { + // Something went wrong, abort + emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0); + bin()->emitMessage(i18n("Error reading audio thumbnail"), ErrorMessage); + return; + } + rawChannels << (const qint16*) res.constData(); + // We need to keep res2 alive or rawChannels data will die + sourceChannels << res; + } + int progress = 0; + QList <long> channelsData; + double offset = (double) dataSize / (2.0 * lengthInFrames); + int intraOffset = 1; + if (offset > 1000) { + intraOffset = offset / 60; + } else if (offset > 250) { + intraOffset = offset / 10; + } + double factor = 800.0 / 32768; + for (int i = 0; i < lengthInFrames; i++) { + channelsData.clear(); for (int k = 0; k < rawChannels.count(); k++) { - channelsData[k] += abs(rawChannels[k][pos + j]); + channelsData << 0; } - - } - for (int k = 0; k < channelsData.count(); k++) { - if (steps) channelsData[k] /= steps; - audioLevels << channelsData[k] * factor; - } - int p = i * 100 / lengthInFrames; - if (p != progress) { - emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, p); - progress = p; + int pos = (int) (i * offset); + int steps = 0; + for (int j = 0; j < (int) offset && (pos + j < dataSize); j += intraOffset) { + steps ++; + for (int k = 0; k < rawChannels.count(); k++) { + channelsData[k] += abs(rawChannels[k][pos + j]); + } + } + for (int k = 0; k < channelsData.count(); k++) { + if (steps) channelsData[k] /= steps; + audioLevels << channelsData[k] * factor; + } + int p = 50 + (i * 50 / lengthInFrames); + if (p != progress) { + emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, p); + progress = p; + } + if (m_abortAudioThumb) break; } - if (m_abortAudioThumb) break; + jobFinished = true; + } else { + bin()->emitMessage(i18n("Failed to create FFmpeg audio thumbnails, using MLT"), ErrorMessage); } - } else { + } + if (!jobFinished && !m_abortAudioThumb) { + // MLT audio thumbs: slower but safer QString service = prod->get("mlt_service"); if (service == QLatin1String("avformat-novalidate")) service = QStringLiteral("avformat"); @@ -1148,6 +1154,18 @@ m_abortAudioThumb = false; } +void ProjectClip::updateFfmpegProgress() +{ + QString result = m_audioThumbsProcess.readAllStandardOutput(); + QStringList lines = result.split('\n'); + foreach(const QString & data, lines) { + if (data.startsWith(QStringLiteral("out_time_ms"))) { + long ms = data.section(QLatin1Char('='), 1).toLong(); + emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, (int) (ms / duration().ms() / 20)); + } + } +} + bool ProjectClip::isTransparent() const { if (m_type == Text) return true; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/projectclip.h new/kdenlive-16.04.2/src/bin/projectclip.h --- old/kdenlive-16.04.1/src/bin/projectclip.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/projectclip.h 2016-06-09 19:50:38.000000000 +0200 @@ -236,6 +236,7 @@ QUrl m_temporaryUrl; ClipType m_type; Mlt::Producer *m_thumbsProducer; + QProcess m_audioThumbsProcess; QMutex m_producerMutex; QMutex m_thumbMutex; QMutex m_audioMutex; @@ -244,6 +245,9 @@ const QString geometryWithOffset(const QString &data, int offset); void doExtractImage(); +private slots: + void updateFfmpegProgress(); + signals: void gotAudioData(); void refreshPropertiesPanel(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/projectsortproxymodel.cpp new/kdenlive-16.04.2/src/bin/projectsortproxymodel.cpp --- old/kdenlive-16.04.1/src/bin/projectsortproxymodel.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/projectsortproxymodel.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -28,6 +28,7 @@ ProjectSortProxyModel::ProjectSortProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { + m_collator.setNumericMode(true); m_selection = new QItemSelectionModel(this); connect(m_selection, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(onCurrentRowChanged(QItemSelection,QItemSelection))); setDynamicSortFilter(true); @@ -95,7 +96,7 @@ if (leftData.type() == QVariant::DateTime) { return leftData.toDateTime() < rightData.toDateTime(); } - return QSortFilterProxyModel::lessThan(right, left); + return m_collator.compare(leftData.toString(), rightData.toString()) < 0; } if (sortOrder() == Qt::AscendingOrder) return leftType < rightType; return leftType > rightType; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/bin/projectsortproxymodel.h new/kdenlive-16.04.2/src/bin/projectsortproxymodel.h --- old/kdenlive-16.04.1/src/bin/projectsortproxymodel.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/bin/projectsortproxymodel.h 2016-06-09 19:50:38.000000000 +0200 @@ -23,6 +23,7 @@ #define PROJECTSORTPROXYMODEL_H #include <QSortFilterProxyModel> +#include <QCollator> class QItemSelectionModel; @@ -61,6 +62,7 @@ private: QItemSelectionModel*m_selection; QString m_searchString; + QCollator m_collator; signals: /** @brief Emitted when the row changes, used to prepare action for selected item */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/definitions.cpp new/kdenlive-16.04.2/src/definitions.cpp --- old/kdenlive-16.04.1/src/definitions.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/definitions.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -115,6 +115,12 @@ return frame_rate_num * 100 / frame_rate_den == point.frame_rate_num * 100 / point.frame_rate_den; } +bool MltVideoProfile::isValid() const +{ + return (frame_rate_den > 0 && sample_aspect_den > 0 && display_aspect_den > 0 && width > 0); +} + + const QVariantList MltVideoProfile::toList() const { QVariantList result; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/definitions.h new/kdenlive-16.04.2/src/definitions.h --- old/kdenlive-16.04.1/src/definitions.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/definitions.h 2016-06-09 19:50:38.000000000 +0200 @@ -249,6 +249,7 @@ bool operator!=(const MltVideoProfile &other) const; /** @brief Returns true if both profiles have same fps, and can be mixed with the xml producer */ bool isCompatible(const MltVideoProfile &point) const; + bool isValid() const; const QVariantList toList() const; const QString descriptiveString(); }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/dialogs/clipcreationdialog.cpp new/kdenlive-16.04.2/src/dialogs/clipcreationdialog.cpp --- old/kdenlive-16.04.1/src/dialogs/clipcreationdialog.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/dialogs/clipcreationdialog.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -64,7 +64,7 @@ mimeTypes << QStringLiteral("audio/x-flac") << QStringLiteral("audio/x-matroska") << QStringLiteral("audio/mp4") << QStringLiteral("audio/mpeg") << QStringLiteral("audio/x-mp3") << QStringLiteral("audio/ogg") << QStringLiteral("audio/x-wav") << QStringLiteral("audio/x-aiff") << QStringLiteral("audio/aiff") << QStringLiteral("application/ogg") << QStringLiteral("application/mxf") << QStringLiteral("application/x-shockwave-flash") << QStringLiteral("audio/ac3"); // Image mimes - mimeTypes << QStringLiteral("image/gif") << QStringLiteral("image/jpeg") << QStringLiteral("image/png") << QStringLiteral("image/x-tga") << QStringLiteral("image/x-bmp") << QStringLiteral("image/svg+xml") << QStringLiteral("image/tiff") << QStringLiteral("image/x-xcf") << QStringLiteral("image/x-xcf-gimp") << QStringLiteral("image/x-vnd.adobe.photoshop") << QStringLiteral("image/x-pcx") << QStringLiteral("image/x-exr") << QStringLiteral("image/x-portable-pixmap"); + mimeTypes << QStringLiteral("image/gif") << QStringLiteral("image/jpeg") << QStringLiteral("image/png") << QStringLiteral("image/x-tga") << QStringLiteral("image/x-bmp") << QStringLiteral("image/svg+xml") << QStringLiteral("image/tiff") << QStringLiteral("image/x-xcf") << QStringLiteral("image/x-xcf-gimp") << QStringLiteral("image/x-vnd.adobe.photoshop") << QStringLiteral("image/x-pcx") << QStringLiteral("image/x-exr") << QStringLiteral("image/x-portable-pixmap") << QStringLiteral("application/x-krita"); QMimeDatabase db; QStringList allExtensions; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/dialogs/profilesdialog.cpp new/kdenlive-16.04.2/src/dialogs/profilesdialog.cpp --- old/kdenlive-16.04.1/src/dialogs/profilesdialog.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/dialogs/profilesdialog.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -325,12 +325,11 @@ QString path; bool isCustom = false; if (name.contains('/')) isCustom = true; - if (!isCustom) { // List the Mlt profiles QDir mltDir(KdenliveSettings::mltpath()); - profilesFiles = mltDir.entryList(profilesFilter, QDir::Files); - if (profilesFiles.contains(name)) path = mltDir.absoluteFilePath(name); + if (mltDir.exists(name)) + path = mltDir.absoluteFilePath(name); } if (isCustom || path.isEmpty()) { path = name; @@ -425,6 +424,8 @@ QStringList profilesFiles = mltDir.entryList(profilesFilter, QDir::Files); for (int i = 0; i < profilesFiles.size(); ++i) { MltVideoProfile test = getProfileFromPath(mltDir.absoluteFilePath(profilesFiles.at(i)), profilesFiles.at(i)); + if (!test.isValid()) + continue; if (test == profile) { return profilesFiles.at(i); } @@ -433,10 +434,13 @@ // Check custom profiles QStringList customProfiles = QStandardPaths::locateAll(QStandardPaths::DataLocation, QStringLiteral("profiles/"), QStandardPaths::LocateDirectory); for (int i = 0; i < customProfiles.size(); ++i) { - profilesFiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files); + QDir customDir(customProfiles.at(i)); + profilesFiles = customDir.entryList(profilesFilter, QDir::Files); for (int j = 0; j < profilesFiles.size(); ++j) { - QString path = customProfiles.at(i) + profilesFiles.at(j); + QString path = customDir.absoluteFilePath(profilesFiles.at(j)); MltVideoProfile test = getProfileFromPath(path, path); + if (!test.isValid()) + continue; if (test == profile) { return path; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/dialogs/renderwidget.cpp new/kdenlive-16.04.2/src/dialogs/renderwidget.cpp --- old/kdenlive-16.04.1/src/dialogs/renderwidget.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/dialogs/renderwidget.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -1763,21 +1763,38 @@ } QStringList profiles = root.entryList(QDir::Files, QDir::Name); foreach(const QString &prof, profiles) { - KConfig config(root.absoluteFilePath(prof), KConfig::SimpleConfig ); - KConfigGroup group = config.group(QByteArray()); - QString extension = group.readEntry("meta.preset.extension"); - QString note = group.readEntry("meta.preset.note"); - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(prof)); - item->setData(0, GroupRole, groupName); - item->setData(0, ExtensionRole, extension); - item->setData(0, RenderRole, "avformat"); + QTreeWidgetItem *item = loadFromMltPreset(groupName, root.absoluteFilePath(prof), prof); + if (!item) + continue; item->setData(0, ParamsRole, QString("properties=stills/" + prof)); - if (!note.isEmpty()) item->setToolTip(0, note); + groupItem->addChild(item); + } + // Add GIF as image sequence + root.cdUp(); + QTreeWidgetItem *item = loadFromMltPreset(groupName, root.absoluteFilePath(QStringLiteral("GIF")), QStringLiteral("GIF")); + if (item) { + item->setData(0, ParamsRole, QString("properties=GIF")); groupItem->addChild(item); } } } +QTreeWidgetItem *RenderWidget::loadFromMltPreset(const QString groupName, const QString path, const QString profileName) +{ + KConfig config(path, KConfig::SimpleConfig); + KConfigGroup group = config.group(QByteArray()); + QString extension = group.readEntry("meta.preset.extension"); + QString note = group.readEntry("meta.preset.note"); + if (extension.isEmpty()) + return NULL; + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(profileName)); + item->setData(0, GroupRole, groupName); + item->setData(0, ExtensionRole, extension); + item->setData(0, RenderRole, "avformat"); + if (!note.isEmpty()) item->setToolTip(0, note); + return item; +} + void RenderWidget::parseFile(const QString &exportFile, bool editable) { QDomDocument doc; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/dialogs/renderwidget.h new/kdenlive-16.04.2/src/dialogs/renderwidget.h --- old/kdenlive-16.04.1/src/dialogs/renderwidget.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/dialogs/renderwidget.h 2016-06-09 19:50:38.000000000 +0200 @@ -208,6 +208,8 @@ void startRendering(RenderJobItem *item); bool saveProfile(QDomElement newprofile); void errorMessage(const QString &message); + /** @brief Create a rendering profile from MLT preset. */ + QTreeWidgetItem *loadFromMltPreset(const QString groupName, const QString path, const QString profileName); signals: void abortProcess(const QString &url); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/doc/kdenlivedoc.cpp new/kdenlive-16.04.2/src/doc/kdenlivedoc.cpp --- old/kdenlive-16.04.1/src/doc/kdenlivedoc.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/doc/kdenlivedoc.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -356,6 +356,8 @@ QDomElement blk = doc.createElement(QStringLiteral("producer")); blk.setAttribute(QStringLiteral("in"), 0); blk.setAttribute(QStringLiteral("out"), 500); + blk.setAttribute(QStringLiteral("aspect_ratio"), 1); + blk.setAttribute(QStringLiteral("set.test_audio"), 0); blk.setAttribute(QStringLiteral("id"), QStringLiteral("black")); QDomElement property = doc.createElement(QStringLiteral("property")); @@ -1501,9 +1503,15 @@ path = dir.absoluteFilePath(path); } m_projectFolder = QUrl::fromLocalFile(path); - list = m_document.elementsByTagName(QStringLiteral("profile")); - if (!list.isEmpty()) { - m_profile = ProfilesDialog::getVideoProfileFromXml(list.at(0).toElement()); + QString profile = m_documentProperties.value(QStringLiteral("profile")); + if (!profile.isEmpty()) + m_profile = ProfilesDialog::getVideoProfile(profile); + if (!m_profile.isValid()) { + // try to find matching profile from MLT profile properties + list = m_document.elementsByTagName(QStringLiteral("profile")); + if (!list.isEmpty()) { + m_profile = ProfilesDialog::getVideoProfileFromXml(list.at(0).toElement()); + } } updateProjectProfile(false); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/effectslist/initeffects.cpp new/kdenlive-16.04.2/src/effectslist/initeffects.cpp --- old/kdenlive-16.04.1/src/effectslist/initeffects.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/effectslist/initeffects.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -156,12 +156,14 @@ for (int i = 0; i < max; ++i) consumersList << consumers->get_name(i); delete consumers; - if (consumersList.contains(QStringLiteral("rtaudio"))) { + movit = true; + // Seems like with latest changes, SDL works fine with movit + /*if (consumersList.contains(QStringLiteral("rtaudio"))) { // enable movit GPU effects / display. Currently, Movit crashes with sdl_audio, // So enable only when rtaudio is available movit = true; } - else KdenliveSettings::setGpu_accel(false); + else KdenliveSettings::setGpu_accel(false);*/ } else KdenliveSettings::setGpu_accel(false); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/mainwindow.cpp new/kdenlive-16.04.2/src/mainwindow.cpp --- old/kdenlive-16.04.1/src/mainwindow.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/mainwindow.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -718,6 +718,11 @@ loadDockActions(); loadClipActions(); pCore->bin()->rebuildMenu(); + QMenu *monitorOverlay = static_cast<QMenu*>(factory()->container(QStringLiteral("monitor_config_overlay"), this)); + if (monitorOverlay) { + m_projectMonitor->setupMenu(static_cast<QMenu*>(factory()->container(QStringLiteral("monitor_go"), this)), monitorOverlay, m_playZone, m_loopZone, NULL, m_loopClip); + m_clipMonitor->setupMenu(static_cast<QMenu*>(factory()->container(QStringLiteral("monitor_go"), this)), monitorOverlay, m_playZone, m_loopZone, static_cast<QMenu*>(factory()->container(QStringLiteral("marker_menu"), this))); + } } void MainWindow::slotReloadEffects() @@ -2727,7 +2732,6 @@ unplugActionList(QStringLiteral("add_effect")); plugActionList(QStringLiteral("add_effect"), m_effectsMenu->actions()); - QList <QAction *>clipJobActions = getExtraActions("clipjobs"); unplugActionList("clip_jobs"); plugActionList("clip_jobs", clipJobActions); @@ -2755,7 +2759,7 @@ sortedList.sort(Qt::CaseInsensitive); foreach(const QString &text, sortedList) { orderedList << sorted.value(text); - } + } unplugActionList( "dock_actions" ); plugActionList( "dock_actions", orderedList); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/glwidget.cpp new/kdenlive-16.04.2/src/monitor/glwidget.cpp --- old/kdenlive-16.04.1/src/monitor/glwidget.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/glwidget.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -139,16 +139,16 @@ void GLWidget::showEvent(QShowEvent * event) { QQuickView::showEvent(event); - initializeGL(); + //initializeGL(); } void GLWidget::initializeGL() { - if (m_isInitialized || !isVisible() || !openglContext()) return; + //if (m_isInitialized || !isVisible() || !openglContext()) return; if (!m_offscreenSurface.isValid()) { m_offscreenSurface.setFormat(openglContext()->format()); m_offscreenSurface.create(); - openglContext()->makeCurrent(this); + //openglContext()->makeCurrent(this); } initializeOpenGLFunctions(); qDebug() << "OpenGL vendor: " << QString::fromUtf8((const char*) glGetString(GL_VENDOR)); @@ -478,7 +478,7 @@ if (!m_fbo || m_fbo->size() != QSize(fullWidth, fullHeight)) { delete m_fbo; QOpenGLFramebufferObjectFormat fmt; - fmt.setSamples(0); + fmt.setSamples(1); fmt.setInternalTextureFormat(GL_RGB); //GL_RGBA32F); // which one is the fastest ? m_fbo = new QOpenGLFramebufferObject(fullWidth, fullHeight, fmt); //GL_TEXTURE_2D); } @@ -919,7 +919,8 @@ delete m_consumer; } // Force rtaudio backend for movit, because with SDL it crashes on stop/start - QString audioBackend = m_glslManager == NULL ? KdenliveSettings::audiobackend() : QStringLiteral("rtaudio"); + //QString audioBackend = m_glslManager == NULL ? KdenliveSettings::audiobackend() : QStringLiteral("rtaudio"); + QString audioBackend = KdenliveSettings::audiobackend(); if (serviceName.isEmpty() || serviceName != audioBackend) { m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, audioBackend.toUtf8().constData()); if (m_consumer->is_valid()) @@ -1268,13 +1269,13 @@ mlt_image_format format = mlt_image_yuv420p; frame.get_image(format, width, height); // Save this frame for future use and to keep a reference to the GL Texture. - m_frame = SharedFrame(frame); + m_displayFrame = SharedFrame(frame); if (m_context->isValid()) { m_context->makeCurrent(m_surface); // Upload each plane of YUV to a texture. QOpenGLFunctions* f = m_context->functions(); - uploadTextures(m_context, m_frame, m_renderTexture); + uploadTextures(m_context, m_displayFrame, m_renderTexture); f->glBindTexture(GL_TEXTURE_2D, 0); check_error(f); f->glFinish(); @@ -1286,7 +1287,7 @@ // The frame is now done being modified and can be shared with the rest // of the application. - emit frameDisplayed(m_frame); + emit frameDisplayed(m_displayFrame); if (sendAudioForAnalysis) { // TODO: use mlt audiospectrum filter @@ -1313,7 +1314,7 @@ void FrameRenderer::showGLFrame(Mlt::Frame frame) { - if (m_context->isValid()) { + if (m_context && m_context->isValid()) { int width = 0; int height = 0; @@ -1350,7 +1351,8 @@ // The frame is now done being modified and can be shared with the rest // of the application. - emit frameDisplayed(m_frame); + qSwap(m_frame, m_displayFrame); + emit frameDisplayed(m_displayFrame); if (sendAudioForAnalysis) { // TODO: use mlt audiospectrum filter @@ -1396,7 +1398,8 @@ // The frame is now done being modified and can be shared with the rest // of the application. - emit frameDisplayed(m_frame); + qSwap(m_frame, m_displayFrame); + emit frameDisplayed(m_displayFrame); } m_semaphore.release(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/glwidget.h new/kdenlive-16.04.2/src/monitor/glwidget.h --- old/kdenlive-16.04.1/src/monitor/glwidget.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/glwidget.h 2016-06-09 19:50:38.000000000 +0200 @@ -231,6 +231,7 @@ private: QSemaphore m_semaphore; SharedFrame m_frame; + SharedFrame m_displayFrame; QOpenGLContext* m_context; QSurface* m_surface; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/monitor.cpp new/kdenlive-16.04.2/src/monitor/monitor.cpp --- old/kdenlive-16.04.1/src/monitor/monitor.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/monitor.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -407,6 +407,8 @@ void Monitor::setupMenu(QMenu *goMenu, QMenu *overlayMenu, QAction *playZone, QAction *loopZone, QMenu *markerMenu, QAction *loopClip) { + if (m_contextMenu) + delete m_contextMenu; m_contextMenu = new QMenu(this); m_contextMenu->addMenu(m_playMenu); if (goMenu) @@ -1057,21 +1059,23 @@ slotActivateMonitor(); if (speed == 0) { double currentspeed = render->playSpeed(); - if (currentspeed >= 0) render->play(-1); + if (currentspeed >= 0) + speed = -1; else switch((int) currentspeed) { case -1: - render->play(-2); + speed = -2; break; case -2: - render->play(-3); + speed = -3; break; case -3: - render->play(-5); + speed = -5; break; default: - render->play(-8); + speed = -8; } - } else render->play(speed); + } + render->switchPlay(true, speed); m_playAction->setActive(true); } @@ -1080,23 +1084,22 @@ slotActivateMonitor(); if (speed == 0) { double currentspeed = render->playSpeed(); - if (currentspeed <= 0) render->play(1); + if (currentspeed <= 0) speed = 1; else switch((int) currentspeed) { case 1: - render->play(2); + speed = 2; break; case 2: - render->play(3); + speed = 3; break; case 3: - render->play(5); + speed = 5; break; default: - render->play(8); + speed = 8; } - } else { - render->play(speed); } + render->switchPlay(true, speed); m_playAction->setActive(true); } @@ -1191,7 +1194,7 @@ { if (render == NULL) return; slotActivateMonitor(); - render->pause(); + render->switchPlay(false); m_playAction->setActive(false); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/monitormanager.cpp new/kdenlive-16.04.2/src/monitor/monitormanager.cpp --- old/kdenlive-16.04.1/src/monitor/monitormanager.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/monitormanager.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -529,3 +529,4 @@ m_projectMonitor->slotSetZoneEnd(); } } + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/monitormanager.h new/kdenlive-16.04.2/src/monitor/monitormanager.h --- old/kdenlive-16.04.1/src/monitor/monitormanager.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/monitormanager.h 2016-06-09 19:50:38.000000000 +0200 @@ -92,7 +92,7 @@ void slotZoneEnd(); void slotSetInPoint(); void slotSetOutPoint(); - + /** @brief Switch current monitor to fullscreen. */ void slotSwitchFullscreen(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/monitor/scopes/monitoraudiolevel.cpp new/kdenlive-16.04.2/src/monitor/scopes/monitoraudiolevel.cpp --- old/kdenlive-16.04.1/src/monitor/scopes/monitoraudiolevel.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/monitor/scopes/monitoraudiolevel.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -31,6 +31,7 @@ #include <QVBoxLayout> #include <QFont> #include <QDebug> +#include <math.h> const double log_factor = 1.0 / log10(1.0/127); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/project/jobs/filterjob.cpp new/kdenlive-16.04.2/src/project/jobs/filterjob.cpp --- old/kdenlive-16.04.1/src/project/jobs/filterjob.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/project/jobs/filterjob.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -86,8 +86,7 @@ jobs.insert(clip, job); } return jobs; - } - if (filterName == QLatin1String("motion_est")) { + } else if (filterName == QLatin1String("motion_est")) { // Show config dialog QPointer<QDialog> d = new QDialog(QApplication::activeWindow()); Ui::SceneCutDialog_UI ui; @@ -176,8 +175,7 @@ jobs.insert(clip, job); } return jobs; - } - if (filterName == QLatin1String("vidstab")) { + } else if (filterName == QLatin1String("vidstab") || filterName == QLatin1String("videostab2") || filterName == QLatin1String("videostab")) { // vidstab QPointer<ClipStabilize> d = new ClipStabilize(sources, filterName); if (d->exec() == QDialog::Accepted) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/renderer.cpp new/kdenlive-16.04.2/src/renderer.cpp --- old/kdenlive-16.04.1/src/renderer.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/renderer.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -81,6 +81,8 @@ m_blackClip = new Mlt::Producer(*m_qmlView->profile(), "colour:black"); m_blackClip->set("id", "black"); m_blackClip->set("mlt_type", "producer"); + m_blackClip->set("aspect_ratio", 1); + m_blackClip->set("set.test_audio", 0); m_mltProducer = m_blackClip->cut(0, 1); m_qmlView->setProducer(m_mltProducer); m_mltConsumer = qmlView->consumer(); @@ -689,7 +691,7 @@ m_isRefreshing = false; } -void Render::pause() +/*void Render::pause() { requestedSeekPosition = SEEK_INACTIVE; if (!m_mltProducer || !m_mltConsumer || !m_isActive) @@ -697,14 +699,14 @@ m_mltProducer->set_speed(0.0); //if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop(); //m_mltProducer->seek(m_mltConsumer->position()); -} +}*/ void Render::setActiveMonitor() { if (!m_isActive) emit activateMonitor(m_name); } -void Render::switchPlay(bool play) +void Render::switchPlay(bool play, double speed) { QMutexLocker locker(&m_mutex); requestedSeekPosition = SEEK_INACTIVE; @@ -712,6 +714,7 @@ return; if (m_isZoneMode) resetZoneMode(); if (play) { + double currentSpeed = m_mltProducer->get_speed(); if (m_name == Kdenlive::ClipMonitor && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0); if (m_mltConsumer->get_int("real_time") != m_qmlView->realTime()) { m_mltConsumer->set("real_time", m_qmlView->realTime()); @@ -722,10 +725,14 @@ m_mltConsumer->stop(); } } - m_mltConsumer->start(); - m_isRefreshing = true; - m_mltConsumer->set("refresh", 1); - m_mltProducer->set_speed(1.0); + if (currentSpeed == 0) { + m_mltConsumer->start(); + m_isRefreshing = true; + m_mltConsumer->set("refresh", 1); + } else { + m_mltConsumer->purge(); + } + m_mltProducer->set_speed(speed); } else { m_mltConsumer->purge(); m_mltProducer->set_speed(0.0); @@ -744,15 +751,21 @@ double current_speed = m_mltProducer->get_speed(); if (current_speed == speed) return; if (m_isZoneMode) resetZoneMode(); - // if (speed == 0.0) m_mltProducer->set("out", m_mltProducer->get_length() - 1); - m_mltProducer->set_speed(speed); - if (m_mltConsumer->is_stopped() && speed != 0) { - m_mltConsumer->start(); + if (speed != 0 && m_mltConsumer->get_int("real_time") != m_qmlView->realTime()) { + m_mltConsumer->set("real_time", m_qmlView->realTime()); + m_mltConsumer->set("buffer", 25); + m_mltConsumer->set("prefill", 1); + // Changes to real_time require a consumer restart if running. + if (!m_mltConsumer->is_stopped()) { + m_mltConsumer->stop(); + } } - if (current_speed == 0 && speed != 0) { + if (current_speed == 0) { + m_mltConsumer->start(); m_isRefreshing = true; m_mltConsumer->set("refresh", 1); } + m_mltProducer->set_speed(speed); } void Render::play(const GenTime & startTime) @@ -2076,7 +2089,7 @@ } //Updates all transitions -QList <TransitionInfo> Render::mltInsertTrack(int ix, const QString &name, bool videoTrack) +QList <TransitionInfo> Render::mltInsertTrack(int ix, const QString &name, bool videoTrack, int lowestVideoTrack) { QList <TransitionInfo> transitionInfos; // Track add / delete was only added recently in MLT (pre 0.9.8 release). @@ -2095,8 +2108,21 @@ blockSignals(true); service.lock(); Mlt::Tractor tractor(service); + // Find available track name + QStringList trackNames; + for (int i = 0; i < tractor.count(); i++) { + QScopedPointer<Mlt::Producer> track(tractor.track(i)); + trackNames << track->get("id"); + } + QString newName = QStringLiteral("playlist0"); + int i = 1; + while (trackNames.contains(newName)) { + newName = QString("playlist%1").arg(i); + i++; + } Mlt::Playlist playlist(*service.profile()); playlist.set("kdenlive:track_name", name.toUtf8().constData()); + playlist.set("id", newName.toUtf8().constData()); int ct = tractor.count(); if (ix > ct) { //qDebug() << "// ERROR, TRYING TO insert TRACK " << ix << ", max: " << ct; @@ -2113,62 +2139,6 @@ tractor.refresh(); Mlt::Field *field = tractor.field(); - // Move transitions - /*mlt_service serv = m_mltProducer->parent().get_service(); - mlt_service nextservice = mlt_service_get_producer(serv); - mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice); - QString mlt_type = mlt_properties_get(properties, "mlt_type"); - QString resource = mlt_properties_get(properties, "mlt_service"); - QList <Mlt::Transition *> trList; - - while (mlt_type == "transition") { - if (resource != "mix") { - Mlt::Transition transition((mlt_transition) nextservice); - nextservice = mlt_service_producer(nextservice); - int currentbTrack = transition.get_b_track(); - int currentaTrack = transition.get_a_track(); - bool trackChanged = false; - bool forceTransitionTrack = false; - if (currentbTrack >= ix) { - if (currentbTrack == ix && currentaTrack < ix) forceTransitionTrack = true; - currentbTrack++; - trackChanged = true; - } - if (currentaTrack >= ix) { - currentaTrack++; - trackChanged = true; - } - //qDebug()<<"// Newtrans: "<<currentaTrack<<"/"<<currentbTrack; - - // disconnect all transitions - Mlt::Properties trans_props(transition.get_properties()); - Mlt::Transition *cp = new Mlt::Transition(*m_qmlView->profile(), transition.get("mlt_service")); - Mlt::Properties new_trans_props(cp->get_properties()); - cloneProperties(new_trans_props, trans_props); - //new_trans_props.inherit(trans_props); - - if (trackChanged) { - // Transition track needs to be adjusted - cp->set("a_track", currentaTrack); - cp->set("b_track", currentbTrack); - // Check if transition track was changed and needs to be forced - if (forceTransitionTrack) cp->set("force_track", 1); - TransitionInfo trInfo; - trInfo.startPos = GenTime(transition.get_in(), m_fps); - trInfo.a_track = currentaTrack; - trInfo.b_track = currentbTrack; - trInfo.forceTrack = cp->get_int("force_track"); - transitionInfos.append(trInfo); - } - trList.append(cp); - field->disconnect_service(transition); - } - else nextservice = mlt_service_producer(nextservice); - if (nextservice == NULL) break; - properties = MLT_SERVICE_PROPERTIES(nextservice); - mlt_type = mlt_properties_get(properties, "mlt_type"); - resource = mlt_properties_get(properties, "mlt_service"); - }*/ // Add audio mix transition to last track Mlt::Transition mix(*m_qmlView->profile(), "mix"); @@ -2180,14 +2150,17 @@ field->plant_transition(mix, 0, ix); if (videoTrack) { - Mlt::Transition composite(*m_qmlView->profile(), KdenliveSettings::gpu_accel() ? "movit.overlay" : "frei0r.cairoblend"); - if (composite.is_valid()) { - composite.set("a_track", ix - 1); - composite.set("b_track", ix); - composite.set("internal_added", 237); - field->plant_transition(composite, ix - 1, ix); - } - //mltPlantTransition(field, composite, ct-1, ct); + if (ix <= lowestVideoTrack) { + // Track was inserted as lowest video track, it should not have a composite, but previous lowest should + ix = lowestVideoTrack + 1; + } + Mlt::Transition composite(*m_qmlView->profile(), KdenliveSettings::gpu_accel() ? "movit.overlay" : "frei0r.cairoblend"); + if (composite.is_valid()) { + composite.set("a_track", ix - 1); + composite.set("b_track", ix); + composite.set("internal_added", 237); + field->plant_transition(composite, ix - 1, ix); + } } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/renderer.h new/kdenlive-16.04.2/src/renderer.h --- old/kdenlive-16.04.1/src/renderer.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/renderer.h 2016-06-09 19:50:38.000000000 +0200 @@ -138,8 +138,7 @@ * The speed is relative to normal playback, e.g. 1.0 is normal speed, 0.0 * is paused, -1.0 means play backwards. It does not specify start/stop */ void play(double speed); - void switchPlay(bool play); - void pause(); + void switchPlay(bool play, double speed = 1.0); /** @brief Stops playing. * @param startTime time to seek to */ @@ -230,7 +229,7 @@ void mltMoveEffect(int track, const GenTime &position, int oldPos, int newPos); void mltMoveTrackEffect(int track, int oldPos, int newPos); - QList <TransitionInfo> mltInsertTrack(int ix, const QString &name, bool videoTrack); + QList <TransitionInfo> mltInsertTrack(int ix, const QString &name, bool videoTrack, int lowestVideoTrack); //const QList <Mlt::Producer *> producersList(); void setDropFrames(bool show); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/clipitem.cpp new/kdenlive-16.04.2/src/timeline/clipitem.cpp --- old/kdenlive-16.04.1/src/timeline/clipitem.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/clipitem.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -954,7 +954,7 @@ const double scale = projectScene()->scale().x(); double maximumOffset = 8 / scale; if (isSelected() || (parentItem() && parentItem()->isSelected())) { - int kf = m_keyframeView.mouseOverKeyFrames(rect(), pos, maximumOffset, scale); + int kf = m_keyframeView.mouseOverKeyFrames(rect(), pos, scale); if (kf != -1) { return KeyFrame; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/customtrackview.cpp new/kdenlive-16.04.2/src/timeline/customtrackview.cpp --- old/kdenlive-16.04.1/src/timeline/customtrackview.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/customtrackview.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -602,7 +602,7 @@ m_scrollTimer.stop(); } } else if (m_moveOpMode == ResizeStart) { - m_document->renderer()->pause(); + m_document->renderer()->switchPlay(false); if (!m_controlModifier && m_dragItem->type() == AVWidget && m_dragItem->parentItem() && m_dragItem->parentItem() != m_selectionGroup) { AbstractGroupItem *parent = static_cast <AbstractGroupItem *>(m_dragItem->parentItem()); if (parent) @@ -615,7 +615,7 @@ QString offset = m_document->timecode().getDisplayTimecode(m_dragItem->cropStart() - m_dragItemInfo.cropStart, KdenliveSettings::frametimecode()); emit displayMessage(i18n("Crop from start:") + ' ' + crop + ' ' + i18n("Duration:") + ' ' + duration + ' ' + i18n("Offset:") + ' ' + offset, InformationMessage); } else if (m_moveOpMode == ResizeEnd) { - m_document->renderer()->pause(); + m_document->renderer()->switchPlay(false); if (!m_controlModifier && m_dragItem->type() == AVWidget && m_dragItem->parentItem() && m_dragItem->parentItem() != m_selectionGroup) { AbstractGroupItem *parent = static_cast <AbstractGroupItem *>(m_dragItem->parentItem()); if (parent) { @@ -888,7 +888,7 @@ } if (m_tool != RazorTool) activateMonitor(); else if (m_document->renderer()->isPlaying()) { - m_document->renderer()->pause(); + m_document->renderer()->switchPlay(false); return; } } @@ -1065,7 +1065,7 @@ if (m_dragItem->type() == TransitionWidget) { emit displayMessage(i18n("Cannot cut a transition"), ErrorMessage); } else { - m_document->renderer()->pause(); + m_document->renderer()->switchPlay(false); if (m_dragItem->parentItem() && m_dragItem->parentItem() != m_selectionGroup) { razorGroup(static_cast<AbstractGroupItem*>(m_dragItem->parentItem()), cutPos); } else { @@ -3201,6 +3201,7 @@ if (ix == -1 || ix > m_timeline->tracksCount()) { ix = m_timeline->tracksCount() + 1; } + int lowestVideoTrack = m_timeline->getLowestVideoTrack(); // Prepare groups for reload QDomDocument doc; @@ -3227,7 +3228,7 @@ } // insert track in MLT's playlist - transitionInfos = m_document->renderer()->mltInsertTrack(ix, type.trackName, type.type == VideoTrack); + transitionInfos = m_document->renderer()->mltInsertTrack(ix, type.trackName, type.type == VideoTrack, lowestVideoTrack); Mlt::Tractor *tractor = m_document->renderer()->lockService(); // When adding a track, MLT sometimes incorrectly updates transition's tracks if (ix < m_timeline->tracksCount()) { @@ -3242,6 +3243,8 @@ m_document->renderer()->unlockService(tractor); // Reload timeline and m_tracks structure from MLT's playlist reloadTimeline(); + // Check we have correct audio mix + m_timeline->fixAudioMixing(); loadGroups(groups); } @@ -3322,9 +3325,12 @@ // Delete track in MLT playlist tractor->remove_track(ix); + // Make sure lowest video track has no composite m_timeline->updateComposites(); m_document->renderer()->unlockService(tractor); reloadTimeline(); + // Check we have correct audio mix + m_timeline->fixAudioMixing(); loadGroups(groups); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/headertrack.cpp new/kdenlive-16.04.2/src/timeline/headertrack.cpp --- old/kdenlive-16.04.1/src/timeline/headertrack.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/headertrack.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -120,6 +120,8 @@ } else if (event->type() == QEvent::MouseButtonDblClick) { // Allow editing on double click track_number->setEnabled(true); + track_number->setFocus(Qt::MouseFocusReason); + event->accept(); } return QWidget::eventFilter(obj, event); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/keyframeview.cpp new/kdenlive-16.04.2/src/timeline/keyframeview.cpp --- old/kdenlive-16.04.1/src/timeline/keyframeview.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/keyframeview.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -22,6 +22,7 @@ #include <QPainter> #include <QAction> +#include <QApplication> #include "klocalizedstring.h" @@ -462,11 +463,11 @@ } -int KeyframeView::mouseOverKeyFrames(QRectF br, QPointF pos, double maxOffset, double scale) +int KeyframeView::mouseOverKeyFrames(QRectF br, QPointF pos, double scale) { if (m_keyframeType == NoKeyframe) return -1; - pos.setX((pos.x() - m_offset)*scale); + pos.setX((pos.x() - m_offset) * scale); int previousEdit = activeKeyframe; for(int i = 0; i < m_keyAnim.key_count(); ++i) { int key = m_keyAnim.key_get_frame(i); @@ -475,10 +476,10 @@ } double value = m_keyProperties.anim_get_double(m_inTimeline.toUtf8().constData(), key, duration - m_offset); QPointF p = keyframeMap(br, key, value); - p.setX(p.x()*scale); + p.setX(p.x() * scale); if (m_keyframeType == GeometryKeyframe) p.setY(br.bottom() - br.height() / 2); - if ((pos - p).manhattanLength() < maxOffset) { + if ((pos - p).manhattanLength() <= m_handleSize / 2) { //TODO /*setToolTip('[' + QString::number((GenTime(key, m_fps) - cropStart()).seconds(), 'f', 2) + i18n("seconds") + ", " + QString::number(value, 'f', 1) + ']');*/ @@ -487,9 +488,10 @@ updateKeyframes(); } return key; - } /*else if (p.x() > pos.x() + maxOffset) { + } + if (p.x() > pos.x()) { break; - }*/ + } } //setToolTip(QString()); activeKeyframe = -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/keyframeview.h new/kdenlive-16.04.2/src/timeline/keyframeview.h --- old/kdenlive-16.04.1/src/timeline/keyframeview.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/keyframeview.h 2016-06-09 19:50:38.000000000 +0200 @@ -89,7 +89,7 @@ void drawKeyFrames(QRectF br, int length, bool active, QPainter *painter, const QTransform &transformation); /** @brief Draw the x, y, w, h channels of an animated geometry */ void drawKeyFrameChannels(QRectF br, int in, int out, QPainter *painter, QList <QPoint> maximas, int limitKeyframes, QColor textColor); - int mouseOverKeyFrames(QRectF br, QPointF pos, double maxOffset, double scale); + int mouseOverKeyFrames(QRectF br, QPointF pos, double scale); void showMenu(QWidget *parent, QPoint pos); QAction *parseKeyframeActions(QList <QAction *>actions); static QString cutAnimation(const QString &animation, int start, int duration, int fullduration, bool doCut = true); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/timeline.cpp new/kdenlive-16.04.2/src/timeline/timeline.cpp --- old/kdenlive-16.04.1/src/timeline/timeline.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/timeline.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -775,10 +775,11 @@ int Timeline::getLowestVideoTrack() { - for (int i = 1; i < m_tracks.count(); ++i) { - if (track(i)->type == VideoTrack) { + for (int i = 1; i < m_tractor->count(); ++i) { + QScopedPointer<Mlt::Producer> track(m_tractor->track(i)); + Mlt::Playlist playlist(*track); + if (playlist.get_int("kdenlive:audio_track") != 1) return i; - } } return -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/timeline.h new/kdenlive-16.04.2/src/timeline/timeline.h --- old/kdenlive-16.04.1/src/timeline/timeline.h 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/timeline.h 2016-06-09 19:50:38.000000000 +0200 @@ -149,6 +149,8 @@ void connectOverlayTrack(bool enable); /** @brief Update composite transitions's tracks */ void updateComposites(); + /** @brief find lowest video track in timeline. */ + int getLowestVideoTrack(); protected: void keyPressEvent(QKeyEvent * event); @@ -197,8 +199,6 @@ void adjustparameterValue(QDomNodeList clipeffectparams, const QString ¶mname, const QString ¶mvalue); /** @brief Enable/disable track actions depending on number of tracks */ void refreshTrackActions(); - /** @brief find lowest video track in timeline. */ - int getLowestVideoTrack(); private slots: void slotSwitchTrackComposite(int trackIndex, bool enable); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/timeline/transitionhandler.cpp new/kdenlive-16.04.2/src/timeline/transitionhandler.cpp --- old/kdenlive-16.04.1/src/timeline/transitionhandler.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/timeline/transitionhandler.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -518,6 +518,7 @@ QList <Mlt::Transition *>composites; QList <int> disabled; QScopedPointer<Mlt::Service> service(m_tractor->field()); + Mlt::Field *field = m_tractor->field(); // Get the list of composite transitions while (service && service->is_valid()) { if (service->type() == transition_type) { @@ -539,6 +540,11 @@ for (int i = 0; i < composites.count(); i++) { Mlt::Transition *tr = composites.at(i); int bTrack = tr->get_int("b_track"); + if (bTrack == lowestVideoTrack) { + // Disable lowest video track transition + field->disconnect_service(*tr); + continue; + } if (disabled.contains(bTrack)) { // transition disabled, pass continue; @@ -551,5 +557,6 @@ } tr->set("a_track", aTrack); } + delete field; qDeleteAll(composites); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/titler/titledocument.cpp new/kdenlive-16.04.2/src/titler/titledocument.cpp --- old/kdenlive-16.04.1/src/titler/titledocument.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/titler/titledocument.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -229,7 +229,7 @@ cursor.select(QTextCursor::Document); QColor fontcolor = cursor.charFormat().foreground().color(); content.setAttribute(QStringLiteral("font-color"), colorToString(fontcolor)); - if (!t->data(TitleDocument::OutlineWidth).isNull()) content.setAttribute(QStringLiteral("font-outline"), QString::number(t->data(TitleDocument::OutlineWidth).toInt())); + if (!t->data(TitleDocument::OutlineWidth).isNull()) content.setAttribute(QStringLiteral("font-outline"), QString::number(t->data(TitleDocument::OutlineWidth).toDouble())); if (!t->data(TitleDocument::OutlineColor).isNull()) { QVariant variant = t->data(TitleDocument::OutlineColor); QColor outlineColor = variant.value<QColor>(); @@ -382,7 +382,6 @@ int maxZValue = 0; if (titles.size()) { - QDomNodeList items = titles.item(0).childNodes(); for (int i = 0; i < items.count(); ++i) { QGraphicsItem *gitem = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kdenlive-16.04.1/src/titler/titlewidget.cpp new/kdenlive-16.04.2/src/titler/titlewidget.cpp --- old/kdenlive-16.04.1/src/titler/titlewidget.cpp 2016-05-02 00:32:52.000000000 +0200 +++ new/kdenlive-16.04.2/src/titler/titlewidget.cpp 2016-06-09 19:50:38.000000000 +0200 @@ -1833,6 +1833,9 @@ if (!url.isValid()) url = QFileDialog::getOpenFileUrl(this, i18n("Load Title"), QUrl(m_projectTitlePath), i18n("Kdenlive title (*.kdenlivetitle)")); if (url.isValid()) { QList<QGraphicsItem *> items = m_scene->items(); + items.removeAll(m_frameBorder); + items.removeAll(m_frameBackground); + items.removeAll(m_frameImage); for (int i = 0; i < items.size(); ++i) { if (items.at(i)->zValue() > -1000) delete items.at(i); }