Commit a33bd84d authored by Luigi Toscano's avatar Luigi Toscano

Merge remote-tracking branch 'origin/Applications/17.12'

parents 9ca1cd57 92b88c61
......@@ -115,12 +115,14 @@ if(KF5DocTools_FOUND)
add_subdirectory(doc)
endif()
#add_subdirectory(plugins)
ecm_optional_add_subdirectory(po)
add_subdirectory(renderer)
add_subdirectory(src)
add_subdirectory(thumbnailer)
#add_subdirectory(testingArea)
ki18n_install(po)
if (KF5DocTools_FOUND)
kdoctools_install(po)
endif()
install( FILES kdenlive.categories DESTINATION ${KDE_INSTALL_CONFDIR} )
......
......@@ -4,8 +4,9 @@ DNxHD=vcodec=dnxhd vb=145000k acodec=pcm_s16le threads=%threads;mov
MPEG=qscale=4 ab=192k vcodec=mpeg2video acodec=mp2 threads=%threads;mpg
[proxy]
x264=-vf scale=640:-2 -g 5 -crf 25 -ab 128k -vcodec libx264 -acodec libvorbis -preset veryfast;mov
MPEG=-vf scale=640:-2 -g 5 -qscale 6 -ab 128k -vcodec mpeg2video -acodec mp2;mpg
x264=-vf scale=960:-2 -g 1 -bf 0 -vb 0 -crf 20 -vcodec libx264 -ab 128k -acodec aac -preset veryfast;mov
MPEG2=-vf scale=960:-2 -g 1 -bf 0 -vb 0 -qscale 6 -ab 128k -vcodec mpeg2video -acodec ac3;mpg
MJPEG=-vf yadif,scale=960:-2 -qscale 3 -vcodec mjpeg -acodec pcm_s16le;mkv
[screengrab]
X264 mute=-crf 25 -vcodec libx264 -preset veryfast -threads 0;mov
......
......@@ -238,6 +238,9 @@
<li xml:lang="zh-TW">基本 DVD 精靈</li>
</ul>
</description>
<releases>
<release date="2018-01-07" version="17.12.1"/>
</releases>
<url type="homepage">https://kdenlive.org/</url>
<url type="bugtracker">https://bugs.kde.org</url>
<url type="help">https://userbase.kde.org/Kdenlive/Manual</url>
......
......@@ -43,7 +43,7 @@ Name[x-test]=xxKdenlivexx
Name[zh_CN]=Kdenlive
Name[zh_TW]=Kdenlive
GenericName=Video Editor
GenericName[ar]=محرّر فيديوهات
GenericName[ar]=محرّر الفيديوهات
GenericName[bs]=Video uređivač
GenericName[ca]=Editor de vídeo
GenericName[ca@valencia]=Editor de vídeo
......
......@@ -2617,7 +2617,7 @@ void Bin::slotEffectDropped(QString id, QDomElement effect)
m_doc->commandStack()->push(command);
}
void Bin::slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEffect, int ix, bool refreshStack)
void Bin::slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEffect, int ix, bool refreshStack, bool updateClip)
{
if (id.isEmpty()) {
id = m_monitor->activeClipId();
......@@ -2625,7 +2625,7 @@ void Bin::slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEff
if (id.isEmpty()) {
return;
}
UpdateBinEffectCommand *command = new UpdateBinEffectCommand(this, id, oldEffect, newEffect, ix, refreshStack);
UpdateBinEffectCommand *command = new UpdateBinEffectCommand(this, id, oldEffect, newEffect, ix, refreshStack, updateClip);
m_doc->commandStack()->push(command);
}
......@@ -2728,14 +2728,16 @@ void Bin::addEffect(const QString &id, QDomElement &effect)
m_monitor->refreshMonitorIfActive();
}
void Bin::updateEffect(const QString &id, QDomElement &effect, int ix, bool refreshStackWidget)
void Bin::updateEffect(const QString &id, QDomElement &effect, int ix, bool refreshStackWidget, bool updateClip)
{
ProjectClip *currentItem = m_rootFolder->clip(id);
if (!currentItem) {
return;
}
currentItem->updateEffect(m_monitor->profileInfo(), effect, ix, refreshStackWidget);
m_monitor->refreshMonitorIfActive();
currentItem->updateEffect(m_monitor->profileInfo(), effect, ix, refreshStackWidget, updateClip);
if (updateClip) {
m_monitor->refreshMonitorIfActive();
}
}
void Bin::changeEffectState(const QString &id, const QList<int> &indexes, bool disable, bool refreshStack)
......@@ -3260,7 +3262,7 @@ void Bin::slotGotFilterJobResults(const QString &id, int startPos, int track, co
EffectsList::setParameter(newEffect, i.key(), i.value());
++i;
}
ctl->updateEffect(pCore->monitorManager()->projectMonitor()->profileInfo(), newEffect, effect.attribute(QStringLiteral("kdenlive_ix")).toInt());
ctl->updateEffect(pCore->monitorManager()->projectMonitor()->profileInfo(), newEffect, effect.attribute(QStringLiteral("kdenlive_ix")).toInt(), true);
emit masterClipUpdated(ctl, m_monitor);
// TODO use undo / redo for bin clip edit effect
/*EditEffectCommand *command = new EditEffectCommand(this, clip->track(), clip->startPos(), effect, newEffect, clip->selectedEffectIndex(), true, true);
......
......@@ -301,7 +301,7 @@ public:
/** @brief Add an effect to a bin clip. */
void addEffect(const QString &id, QDomElement &effect);
/** @brief Update a bin clip effect. */
void updateEffect(const QString &id, QDomElement &effect, int ix, bool refreshStackWidget);
void updateEffect(const QString &id, QDomElement &effect, int ix, bool refreshStackWidget, bool updateClip);
void changeEffectState(const QString &id, const QList<int> &indexes, bool disable, bool refreshStack);
/** @brief Edit an effect settings to a bin clip. */
void editMasterEffect(ClipController *ctl);
......@@ -370,7 +370,7 @@ private slots:
void slotItemDropped(const QStringList &ids, const QModelIndex &parent);
void slotItemDropped(const QList<QUrl> &urls, const QModelIndex &parent);
void slotEffectDropped(const QString &effect, const QModelIndex &parent);
void slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEffect, int ix, bool refreshStack = false);
void slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEffect, int ix, bool refreshStack = false, bool updateClip = true);
void slotChangeEffectState(QString id, const QList<int> &indexes, bool disable);
void slotItemEdited(const QModelIndex &, const QModelIndex &, const QVector<int> &);
void slotAddUrl(const QString &url, int folderId, const QMap<QString, QString> &data = QMap<QString, QString>());
......
......@@ -154,26 +154,27 @@ void RemoveBinEffectCommand::redo()
m_bin->removeEffect(m_clipId, m_effect);
}
UpdateBinEffectCommand::UpdateBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &oldEffect, QDomElement &newEffect, int ix, bool refreshStack, QUndoCommand *parent) :
UpdateBinEffectCommand::UpdateBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &oldEffect, QDomElement &newEffect, int ix, bool refreshStack, bool updateClip, QUndoCommand *parent) :
QUndoCommand(parent),
m_bin(bin),
m_clipId(clipId),
m_oldEffect(oldEffect),
m_newEffect(newEffect),
m_ix(ix),
m_refreshStack(refreshStack)
m_refreshStack(refreshStack),
m_updateClip(updateClip)
{
setText(i18n("Edit Bin Effect"));
}
// virtual
void UpdateBinEffectCommand::undo()
{
m_bin->updateEffect(m_clipId, m_oldEffect, m_ix, m_refreshStack);
m_bin->updateEffect(m_clipId, m_oldEffect, m_ix, m_refreshStack, m_updateClip);
}
// virtual
void UpdateBinEffectCommand::redo()
{
m_bin->updateEffect(m_clipId, m_newEffect, m_ix, m_refreshStack);
m_bin->updateEffect(m_clipId, m_newEffect, m_ix, m_refreshStack, m_updateClip);
m_refreshStack = true;
}
......
......@@ -106,7 +106,7 @@ private:
class UpdateBinEffectCommand : public QUndoCommand
{
public:
explicit UpdateBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &oldEffect, QDomElement &newEffect, int ix, bool refreshStack, QUndoCommand *parent = nullptr);
explicit UpdateBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &oldEffect, QDomElement &newEffect, int ix, bool refreshStack, bool updateClip, QUndoCommand *parent = nullptr);
void undo() Q_DECL_OVERRIDE;
void redo() Q_DECL_OVERRIDE;
private:
......@@ -116,6 +116,7 @@ private:
QDomElement m_newEffect;
int m_ix;
bool m_refreshStack;
bool m_updateClip;
};
class ChangeMasterEffectStateCommand : public QUndoCommand
......
......@@ -104,7 +104,9 @@ ProjectClip::~ProjectClip()
// controller is deleted in bincontroller
abortAudioThumbs();
bin()->slotAbortAudioThumb(m_id, duration().ms());
QMutexLocker audioLock(&m_audioMutex);
if (m_controller) {
QMutexLocker locker(&m_controller->producerMutex);
}
m_thumbMutex.lock();
m_requestedThumbs.clear();
m_thumbMutex.unlock();
......@@ -399,13 +401,13 @@ Mlt::Producer *ProjectClip::originalProducer()
Mlt::Producer *ProjectClip::thumbProducer()
{
QMutexLocker locker(&m_producerMutex);
if (m_thumbsProducer) {
return m_thumbsProducer;
}
if (!m_controller || m_controller->clipType() == Unknown) {
return nullptr;
}
QMutexLocker locker(&m_controller->producerMutex);
Mlt::Producer prod = m_controller->originalProducer();
if (!prod.is_valid()) {
return nullptr;
......@@ -845,9 +847,9 @@ void ProjectClip::addEffect(const ProfileInfo &pInfo, QDomElement &effect)
bin()->emitItemUpdated(this);
}
void ProjectClip::updateEffect(const ProfileInfo &pInfo, QDomElement &effect, int ix, bool refreshStack)
void ProjectClip::updateEffect(const ProfileInfo &pInfo, QDomElement &effect, int ix, bool refreshStack, bool updateClip)
{
m_controller->updateEffect(pInfo, effect, ix);
m_controller->updateEffect(pInfo, effect, ix, updateClip);
if (refreshStack) {
bin()->updateMasterEffect(m_controller);
}
......@@ -1023,7 +1025,10 @@ const QString ProjectClip::getAudioThumbPath(AudioStreamInfo *audioInfo)
void ProjectClip::slotCreateAudioThumbs()
{
QMutexLocker lock(&m_audioMutex);
if (!m_controller) {
return;
}
QMutexLocker locker(&m_controller->producerMutex);
Mlt::Producer *prod = originalProducer();
if (!prod || !prod->is_valid()) {
return;
......
......@@ -193,7 +193,7 @@ public:
void addMarkers(QList<CommentedTime> &markers);
/** @brief Add an effect to bin clip. */
void addEffect(const ProfileInfo &pInfo, QDomElement &effect);
void updateEffect(const ProfileInfo &pInfo, QDomElement &effect, int ix, bool refreshStack);
void updateEffect(const ProfileInfo &pInfo, QDomElement &effect, int ix, bool refreshStack, bool updateClip);
void removeEffect(int ix);
/** @brief Create audio thumbnail for this clip. */
void createAudioThumbs();
......@@ -241,7 +241,6 @@ private:
QMutex m_producerMutex;
QMutex m_thumbMutex;
QMutex m_intraThumbMutex;
QMutex m_audioMutex;
QFuture <void> m_thumbThread;
QList<int> m_requestedThumbs;
QFuture <void> m_intraThread;
......
......@@ -92,7 +92,7 @@ bool MltDeviceCapture::buildConsumer(const QString &profileName)
}
qputenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1");
// OpenGL monitor
m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_audio");
m_mltConsumer = new Mlt::Consumer(*m_mltProfile, KdenliveSettings::audiobackend().toUtf8().constData());
m_mltConsumer->set("preview_off", 1);
m_mltConsumer->set("preview_format", mlt_image_rgb24);
m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show);
......@@ -396,7 +396,7 @@ bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &pa
qputenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1");
// OpenGL monitor
previewProps->set("mlt_service", "sdl_audio");
previewProps->set("mlt_service", KdenliveSettings::audiobackend().toUtf8().constData());
previewProps->set("preview_off", 1);
previewProps->set("preview_format", mlt_image_rgb24);
previewProps->set("terminate_on_pause", 0);
......
......@@ -547,7 +547,7 @@ void KdenliveSettingsDialog::initDevices()
KdenliveSettings::setV4l_alsadevice(ix);
}
m_configSdl.kcfg_audio_backend->addItem(i18n("SDL"), "sdl_audio");
m_configSdl.kcfg_audio_backend->addItem(i18n("SDL"), KdenliveSettings::sdlAudioBackend());
m_configSdl.kcfg_audio_backend->addItem(i18n("RtAudio"), "rtaudio");
if (!KdenliveSettings::audiobackend().isEmpty()) {
......@@ -555,7 +555,7 @@ void KdenliveSettingsDialog::initDevices()
m_configSdl.kcfg_audio_backend->setCurrentIndex(ix);
KdenliveSettings::setAudio_backend(ix);
}
m_configSdl.group_sdl->setEnabled(KdenliveSettings::audiobackend() == QLatin1String("sdl_audio"));
m_configSdl.group_sdl->setEnabled(KdenliveSettings::audiobackend().startsWith(QLatin1String("sdl")));
loadCurrentV4lProfileInfo();
}
......@@ -926,7 +926,7 @@ void KdenliveSettingsDialog::slotCheckAlsaDriver()
void KdenliveSettingsDialog::slotCheckAudioBackend()
{
QString value = m_configSdl.kcfg_audio_backend->itemData(m_configSdl.kcfg_audio_backend->currentIndex()).toString();
m_configSdl.group_sdl->setEnabled(value == QLatin1String("sdl_audio"));
m_configSdl.group_sdl->setEnabled(value.startsWith(QLatin1String("sdl_audio")));
}
void KdenliveSettingsDialog::loadTranscodeProfiles()
......
......@@ -252,7 +252,7 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, const
connect(m_view.export_audio, &QCheckBox::stateChanged, this, &RenderWidget::slotUpdateAudioLabel);
m_view.export_audio->setCheckState(Qt::PartiallyChecked);
checkCodecs();
parseProfiles();
parseScriptFiles();
m_view.running_jobs->setUniformRowHeights(false);
......@@ -337,7 +337,6 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, const
if (!interface || (!interface->isServiceRegistered(QStringLiteral("org.kde.ksmserver")) && !interface->isServiceRegistered(QStringLiteral("org.gnome.SessionManager")))) {
m_view.shutdown->setEnabled(false);
}
checkCodecs();
refreshView();
focusFirstVisibleItem();
adjustSize();
......
......@@ -391,7 +391,18 @@ void Wizard::checkMltComponents()
}
delete consumers;
if (!consumersItemList.contains(QStringLiteral("sdl")) && !consumersItemList.contains(QStringLiteral("rtaudio"))) {
if (consumersItemList.contains(QStringLiteral("sdl2"))) {
// MLT >= 6.6.0 and SDL2 module
KdenliveSettings::setSdlAudioBackend(QStringLiteral("sdl2_audio"));
KdenliveSettings::setAudiobackend(QStringLiteral("sdl2_audio"));
} else if (consumersItemList.contains(QStringLiteral("sdl"))) {
// MLT < 6.6.0
KdenliveSettings::setSdlAudioBackend(QStringLiteral("sdl_audio"));
KdenliveSettings::setAudiobackend(QStringLiteral("sdl_audio"));
} else if (consumersItemList.contains(QStringLiteral("rtaudio"))) {
KdenliveSettings::setSdlAudioBackend(QStringLiteral("sdl2_audio"));
KdenliveSettings::setAudiobackend(QStringLiteral("rtaudio"));
} else {
// SDL module
m_errors.append(i18n("<li>Missing MLT module: <b>sdl</b> or <b>rtaudio</b><br/>required for audio output</li>"));
m_systemCheckIsOk = false;
......
......@@ -450,7 +450,7 @@ void CollapsibleEffect::updateCollapsedState()
QString info = m_info.toString();
if (info != m_effect.attribute(QStringLiteral("kdenlive_info"))) {
m_effect.setAttribute(QStringLiteral("kdenlive_info"), info);
emit parameterChanged(m_original_effect, m_effect, effectIndex());
emit parameterChanged(m_original_effect, m_effect, effectIndex(), false);
}
}
......
......@@ -141,7 +141,7 @@ protected:
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
signals:
void parameterChanged(const QDomElement &, const QDomElement &, int);
void parameterChanged(const QDomElement &, const QDomElement &, int, bool update = true);
void syncEffectsPos(int);
void effectStateChanged(bool, int ix, MonitorSceneType effectNeedsMonitorScene);
void deleteEffect(const QDomElement &);
......
......@@ -776,16 +776,16 @@ CollapsibleEffect *EffectStackView2::getEffectByIndex(int ix)
return nullptr;
}
void EffectStackView2::slotUpdateEffectParams(const QDomElement &old, const QDomElement &e, int ix)
void EffectStackView2::slotUpdateEffectParams(const QDomElement &old, const QDomElement &e, int ix, bool update)
{
if (m_status == TIMELINE_TRACK) {
emit updateEffect(nullptr, m_trackindex, old, e, ix, false);
emit updateEffect(nullptr, m_trackindex, old, e, ix, false, update);
} else if (m_status == TIMELINE_CLIP && m_clipref) {
emit updateEffect(m_clipref, -1, old, e, ix, false);
emit updateEffect(m_clipref, -1, old, e, ix, false, update);
// Make sure the changed effect is currently displayed
slotSetCurrentEffect(ix);
} else if (m_status == MASTER_CLIP) {
emit updateMasterEffect(m_masterclipref->clipId(), old, e, ix);
emit updateMasterEffect(m_masterclipref->clipId(), old, e, ix, false, update);
}
m_scrollTimer.start();
}
......
......@@ -196,7 +196,7 @@ private slots:
/** @brief Checks whether the monitor scene has to be displayed. */
void slotCheckMonitorPosition(int renderPos);
void slotUpdateEffectParams(const QDomElement &old, const QDomElement &e, int ix);
void slotUpdateEffectParams(const QDomElement &old, const QDomElement &e, int ix, bool update);
/** @brief Move an effect in the stack.
* @param indexes The list of effect index in the stack
......@@ -261,9 +261,9 @@ signals:
void removeMasterEffect(const QString &id, const QDomElement &);
void addMasterEffect(const QString &id, const QDomElement &);
/** Parameters for an effect changed, update the filter in timeline */
void updateEffect(ClipItem *, int, const QDomElement &, const QDomElement &, int, bool);
void updateEffect(ClipItem *, int, const QDomElement &, const QDomElement &, int, bool refreshStack, bool updateClip = true);
/** Parameters for an effect changed, update the filter in timeline */
void updateMasterEffect(QString, const QDomElement &, const QDomElement &, int ix,bool refreshStack = false);
void updateMasterEffect(QString, const QDomElement &, const QDomElement &, int ix,bool refreshStack = false, bool updateClip = true);
/** An effect in stack was moved, we need to regenerate
all effects for this clip in the playlist */
void refreshEffectStack(ClipItem *);
......
......@@ -134,7 +134,7 @@ private:
bool m_conditionParameter;
signals:
void parameterChanged(const QDomElement &, const QDomElement &, int);
void parameterChanged(const QDomElement &, const QDomElement &, int, bool update = true);
void syncEffectsPos(int);
void disableCurrentFilter(bool);
void checkMonitorPosition(int);
......
......@@ -281,6 +281,11 @@
<default>false</default>
</entry>
<entry name="sdlAudioBackend" type="String">
<label>Detected audio backend.</label>
<default></default>
</entry>
<entry name="audio_backend" type="Int">
<label>Audio backend index used for sound output.</label>
<default>0</default>
......@@ -288,7 +293,7 @@
<entry name="audiobackend" type="String">
<label>Audio backend used for sound output.</label>
<default>sdl_audio</default>
<default></default>
</entry>
<entry name="audio_driver" type="UInt">
......
......@@ -67,7 +67,9 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
app.setApplicationName(QStringLiteral("kdenlive"));
app.setOrganizationDomain(QStringLiteral("kde.org"));
#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
app.setDesktopFileName(QStringLiteral("org.kde.kdenlive"));
#endif
app.setWindowIcon(QIcon(QStringLiteral(":/pics/kdenlive.png")));
KLocalizedString::setApplicationDomain("kdenlive");
KSharedConfigPtr config = KSharedConfig::openConfig();
......
......@@ -180,14 +180,17 @@ void MainWindow::init(const QString &MltPath, const QUrl &Url, const QString &cl
} else if (availableStyles.contains(QStringLiteral("fusion"), Qt::CaseInsensitive)) {
KdenliveSettings::setWidgetstyle(QStringLiteral("Fusion"));
}
} else {
KdenliveSettings::setWidgetstyle(QStringLiteral("Default"));
}
}
// Add default style action
QAction *defaultStyle = new QAction(i18n("Default"), stylesGroup);
defaultStyle->setData(QStringLiteral("Default"));
defaultStyle->setCheckable(true);
stylesAction->addAction(defaultStyle);
if (KdenliveSettings::widgetstyle().isEmpty()) {
if (KdenliveSettings::widgetstyle() == QLatin1String("Default") || KdenliveSettings::widgetstyle().isEmpty()) {
defaultStyle->setChecked(true);
}
......@@ -323,7 +326,7 @@ void MainWindow::init(const QString &MltPath, const QUrl &Url, const QString &cl
connect(pCore->bin(), &Bin::masterClipSelected, m_effectStack, &EffectStackView2::slotMasterClipItemSelected);
connect(pCore->bin(), &Bin::masterClipUpdated, m_effectStack, &EffectStackView2::slotRefreshMasterClipEffects);
connect(m_effectStack, SIGNAL(addMasterEffect(QString, QDomElement)), pCore->bin(), SLOT(slotEffectDropped(QString, QDomElement)));
connect(m_effectStack, SIGNAL(updateMasterEffect(QString,QDomElement,QDomElement,int,bool)), pCore->bin(), SLOT(slotUpdateEffect(QString,QDomElement,QDomElement,int,bool)));
connect(m_effectStack, SIGNAL(updateMasterEffect(QString,QDomElement,QDomElement,int,bool,bool)), pCore->bin(), SLOT(slotUpdateEffect(QString,QDomElement,QDomElement,int,bool,bool)));
connect(m_effectStack, SIGNAL(changeMasterEffectState(QString, QList<int>, bool)), pCore->bin(), SLOT(slotChangeEffectState(QString, QList<int>, bool)));
connect(m_effectStack, &EffectStackView2::removeMasterEffect, pCore->bin(), &Bin::slotDeleteEffect);
connect(m_effectStack, SIGNAL(changeEffectPosition(QString, QList<int>, int)), pCore->bin(), SLOT(slotMoveEffect(QString, QList<int>, int)));
......@@ -1635,7 +1638,7 @@ bool MainWindow::readOptions()
}
bool firstRun = false;
KConfigGroup initialGroup(config, "version");
if (!initialGroup.exists()) {
if (!initialGroup.exists() || KdenliveSettings::sdlAudioBackend().isEmpty()) {
// First run, check if user is on a KDE Desktop
firstRun = true;
// this is our first run, show Wizard
......
......@@ -251,7 +251,7 @@ void ClipController::updateProducer(const QString &id, Mlt::Producer *producer)
{
//TODO replace all track producers
Q_UNUSED(id)
QMutexLocker locker(&producerMutex);
Mlt::Properties passProperties;
// Keep track of necessary properties
QString proxy = producer->get("kdenlive:proxy");
......@@ -784,7 +784,7 @@ void ClipController::changeEffectState(const QList<int> &indexes, bool disable)
m_binController->updateTrackProducer(clipId());
}
void ClipController::updateEffect(const ProfileInfo &pInfo, const QDomElement &e, int ix)
void ClipController::updateEffect(const ProfileInfo &pInfo, const QDomElement &e, int ix, bool updateClip)
{
QString tag = e.attribute(QStringLiteral("id"));
if (tag == QLatin1String("autotrack_rectangle") || tag.startsWith(QLatin1String("ladspa")) || tag == QLatin1String("sox")) {
......@@ -813,7 +813,9 @@ void ClipController::updateEffect(const ProfileInfo &pInfo, const QDomElement &e
}
service.unlock();
}
m_binController->updateTrackProducer(clipId());
if (updateClip) {
m_binController->updateTrackProducer(clipId());
}
//slotRefreshTracks();
}
......
......@@ -60,6 +60,8 @@ public:
explicit ClipController(BinController *bincontroller);
virtual ~ClipController();
QMutex producerMutex;
/** @brief Returns true if the master producer is valid */
bool isValid();
......@@ -172,7 +174,7 @@ public:
EffectsList effectList();
/** @brief Enable/disable an effect. */
void changeEffectState(const QList<int> &indexes, bool disable);
void updateEffect(const ProfileInfo &pInfo, const QDomElement &e, int ix);
void updateEffect(const ProfileInfo &pInfo, const QDomElement &e, int ix, bool updateClip);
/** @brief Returns true if the bin clip has effects */
bool hasEffects() const;
/** @brief Returns info about clip audio */
......
......@@ -893,7 +893,7 @@ int GLWidget::reconfigureMulti(const QString &params, const QString &path, Mlt::
m_consumer->set("0.real_time", 0);
m_consumer->set("0.volume", (double)volume / 100);
if (serviceName == QLatin1String("sdl_audio")) {
if (serviceName.startsWith(QLatin1String("sdl"))) {
#ifdef Q_OS_WIN
m_consumer->set("0.audio_buffer", 2048);
#else
......@@ -963,18 +963,42 @@ int GLWidget::reconfigure(Mlt::Profile *profile)
//QString audioBackend = m_glslManager == nullptr ? KdenliveSettings::audiobackend() : QStringLiteral("rtaudio");
QString audioBackend = KdenliveSettings::audiobackend();
if (serviceName.isEmpty() || serviceName != audioBackend) {
m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, audioBackend.toUtf8().constData());
m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, audioBackend.toLatin1().constData());
if (m_consumer->is_valid()) {
serviceName = audioBackend;
setProperty("mlt_service", serviceName);
} else {
// Fallback
serviceName = QStringLiteral("sdl_audio");
// Warning, audio backend unavailable on system
delete m_consumer;
m_consumer = nullptr;
QStringList backends = {"sdl2_audio", "sdl_audio", "rtaudio"};
for (const QString &bk : backends) {
if (bk == audioBackend) {
// Already tested
continue;
}
m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, bk.toLatin1().constData());
if (m_consumer->is_valid()) {
if (audioBackend == KdenliveSettings::sdlAudioBackend()) {
// switch sdl audio backend
KdenliveSettings::setSdlAudioBackend(bk);
}
qDebug()<<"++++++++\nSwitching audio backend to: "<<bk<<"\n++++++++++";
KdenliveSettings::setAudiobackend(bk);
serviceName = bk;
setProperty("mlt_service", serviceName);
break;
} else {
delete m_consumer;
m_consumer = nullptr;
}
}
if (!m_consumer) {
qWarning() << "WARNING, NO AUDIO BACKEND FOUND";
return -1;
}
}
delete m_consumer;
m_consumer = nullptr;
setProperty("mlt_service", serviceName);
}
m_consumer = new Mlt::FilteredConsumer(*m_monitorProfile, serviceName.toLatin1().constData());
delete m_threadStartEvent;
m_threadStartEvent = nullptr;
delete m_threadStopEvent;
......@@ -1019,7 +1043,7 @@ int GLWidget::reconfigure(Mlt::Profile *profile)
}
int volume = KdenliveSettings::volume();
if (serviceName == QLatin1String("sdl_audio")) {
if (serviceName.startsWith(QLatin1String("sdl"))) {
QString audioDevice = KdenliveSettings::audiodevicename();
if (!audioDevice.isEmpty()) {
m_consumer->set("audio_device", audioDevice.toUtf8().constData());
......
......@@ -84,7 +84,12 @@ void ProxyJob::startJob()
width = 640;
}
int height = width / display_ratio;
// Make sure we get an even height
height += height % 2;
mltParameters << QStringLiteral("s=%1x%2").arg(width).arg(height);
if (t.contains(QStringLiteral("yadif"))) {
mltParameters << QStringLiteral("progressive=1");
}
continue;
} else {
t.replace(QLatin1Char(' '), QLatin1String("="));
......@@ -118,9 +123,9 @@ void ProxyJob::startJob()
// Images are scaled to profile size.
//TODO: Make it be configurable?
if (i.width() > i.height()) {
proxy = i.scaledToWidth(m_renderWidth);
proxy = i.scaledToWidth(960);
} else {
proxy = i.scaledToHeight(m_renderHeight);
proxy = i.scaledToHeight(540);
}
if (m_exif > 1) {
// Rotate image according to exif data
......
......@@ -750,7 +750,7 @@ void Render::switchPlay(bool play, double speed)
}
if (play) {
double currentSpeed = m_mltProducer->get_speed();
if (m_name == Kdenlive::ClipMonitor && m_mltConsumer->position() == m_mltProducer->get_out()) {
if (m_name == Kdenlive::ClipMonitor && m_mltConsumer->position() == m_mltProducer->get_out() && speed > 0) {
m_mltProducer->seek(0);
}
if (m_mltConsumer->get_int("real_time") != m_qmlView->realTime()) {
......@@ -767,6 +767,7 @@ void Render::switchPlay(bool play, double speed)
m_isRefreshing = true;
m_mltConsumer->set("refresh", 1);
} else {
m_mltProducer->seek(m_mltConsumer->position() + 1);
m_mltConsumer->purge();