From dc7c415e20b76b4f1ac90054ab2ad976b8e7dec0 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sun, 28 Dec 2008 15:30:40 +0000 Subject: [PATCH] Make sox effects work again, part of bug: http://www.kdenlive.org:80/mantis/view.php?id=499 svn path=/branches/KDE4/; revision=2837 --- src/clipitem.cpp | 81 ++++++++++++++++++++++--------------- src/clipitem.h | 4 +- src/customtrackview.cpp | 21 +++++----- src/definitions.h | 49 ++++++++++++++++++++++ src/renderer.cpp | 90 +++++++++++++++++++++++++---------------- src/renderer.h | 4 +- src/trackview.cpp | 6 ++- 7 files changed, 171 insertions(+), 84 deletions(-) diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 259f6cb5..f7832403 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -139,6 +139,7 @@ void ClipItem::initEffect(QDomElement effect) { QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { QDomElement e = params.item(i).toElement(); + kDebug() << "// inint eff: " << e.attribute("name"); if (!e.isNull() && e.attribute("type") == "keyframe") { QString def = e.attribute("default"); // Effect has a keyframe type parameter, we need to set the values @@ -1114,38 +1115,46 @@ void ClipItem::setEffectAt(int ix, QDomElement effect) { } } -QHash ClipItem::addEffect(QDomElement effect, bool animate) { - QHash effectParams; +EffectsParameterList ClipItem::addEffect(QDomElement effect, bool animate) { + bool needRepaint = false; /*QDomDocument doc; doc.appendChild(doc.importNode(effect, true)); kDebug() << "/////// CLIP ADD EFFECT: " << doc.toString();*/ m_effectList.append(effect); - effectParams["tag"] = effect.attribute("tag"); + + EffectsParameterList parameters; + parameters.addParam("tag", effect.attribute("tag")); + parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix")); + + QString state = effect.attribute("disabled"); + if (!state.isEmpty()) { + parameters.addParam("disabled", state); + } + QString effectId = effect.attribute("id"); if (effectId.isEmpty()) effectId = effect.attribute("tag"); - effectParams["id"] = effectId; - effectParams["kdenlive_ix"] = effect.attribute("kdenlive_ix"); - QString state = effect.attribute("disabled"); - if (!state.isEmpty()) effectParams["disabled"] = state; + parameters.addParam("id", effectId); + QDomNodeList params = effect.elementsByTagName("parameter"); int fade = 0; for (int i = 0; i < params.count(); i++) { QDomElement e = params.item(i).toElement(); if (!e.isNull()) { if (e.attribute("type") == "keyframe") { - effectParams["keyframes"] = e.attribute("keyframes"); - effectParams["min"] = e.attribute("min"); - effectParams["max"] = e.attribute("max"); - effectParams["factor"] = e.attribute("factor", "1"); - effectParams["starttag"] = e.attribute("starttag", "start"); - effectParams["endtag"] = e.attribute("endtag", "end"); + parameters.addParam("keyframes", e.attribute("keyframes")); + parameters.addParam("max", e.attribute("max")); + parameters.addParam("min", e.attribute("min")); + parameters.addParam("factor", e.attribute("factor", "1")); + parameters.addParam("starttag", e.attribute("starttag", "start")); + parameters.addParam("endtag", e.attribute("endtag", "end")); } double f = e.attribute("factor", "1").toDouble(); if (f == 1) { - effectParams[e.attribute("name")] = e.attribute("value"); + parameters.addParam(e.attribute("name"), e.attribute("value")); + // check if it is a fade effect if (effectId == "fadein") { needRepaint = true; @@ -1157,7 +1166,7 @@ QHash ClipItem::addEffect(QDomElement effect, bool animate) { else if (e.attribute("name") == "in") fade += e.attribute("value").toInt(); } } else { - effectParams[e.attribute("name")] = QString::number(e.attribute("value").toDouble() / f); + parameters.addParam(e.attribute("name"), QString::number(e.attribute("value").toDouble() / f)); } } } @@ -1176,28 +1185,32 @@ QHash ClipItem::addEffect(QDomElement effect, bool animate) { m_selectedEffect = 0; setSelectedEffect(m_selectedEffect); } - return effectParams; + return parameters; } -QHash ClipItem::getEffectArgs(QDomElement effect) { - QHash effectParams; - effectParams["tag"] = effect.attribute("tag"); - effectParams["kdenlive_ix"] = effect.attribute("kdenlive_ix"); - effectParams["id"] = effect.attribute("id"); +EffectsParameterList ClipItem::getEffectArgs(QDomElement effect) { + EffectsParameterList parameters; + parameters.addParam("tag", effect.attribute("tag")); + parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix")); + parameters.addParam("id", effect.attribute("id")); + QString state = effect.attribute("disabled"); - if (!state.isEmpty()) effectParams["disabled"] = state; + if (!state.isEmpty()) { + parameters.addParam("disabled", state); + } + QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { QDomElement e = params.item(i).toElement(); //kDebug() << "/ / / /SENDING EFFECT PARAM: " << e.attribute("type") << ", NAME_ " << e.attribute("tag"); if (e.attribute("type") == "keyframe") { kDebug() << "/ / / /SENDING KEYFR EFFECT TYPE"; - effectParams["keyframes"] = e.attribute("keyframes"); - effectParams["max"] = e.attribute("max"); - effectParams["min"] = e.attribute("min"); - effectParams["factor"] = e.attribute("factor", "1"); - effectParams["starttag"] = e.attribute("starttag", "start"); - effectParams["endtag"] = e.attribute("endtag", "end"); + parameters.addParam("keyframes", e.attribute("keyframes")); + parameters.addParam("max", e.attribute("max")); + parameters.addParam("min", e.attribute("min")); + parameters.addParam("factor", e.attribute("factor", "1")); + parameters.addParam("starttag", e.attribute("starttag", "start")); + parameters.addParam("endtag", e.attribute("endtag", "end")); } else if (e.attribute("namedesc").contains(";")) { QString format = e.attribute("format"); QStringList separators = format.split("%d", QString::SkipEmptyParts); @@ -1210,14 +1223,16 @@ QHash ClipItem::getEffectArgs(QDomElement effect) { txtNeu << separators[i]; txtNeu << (int)(values[i+1].toDouble()); } - effectParams["start"] = neu; + parameters.addParam("start", neu); } else { - if (e.attribute("factor", "1") != "1") - effectParams[e.attribute("name")] = QString::number(e.attribute("value").toDouble() / e.attribute("factor").toDouble()); - else effectParams[e.attribute("name")] = e.attribute("value"); + if (e.attribute("factor", "1") != "1") { + parameters.addParam(e.attribute("name"), QString::number(e.attribute("value").toDouble() / e.attribute("factor").toDouble())); + } else { + parameters.addParam(e.attribute("name"), e.attribute("value")); + } } } - return effectParams; + return parameters; } void ClipItem::deleteEffect(QString index) { diff --git a/src/clipitem.h b/src/clipitem.h index 98bd1c01..580cf346 100644 --- a/src/clipitem.h +++ b/src/clipitem.h @@ -61,9 +61,9 @@ public: /** Give a string list of the clip's effect names */ QStringList effectNames(); /** Add an effect to the clip and return the parameters that will be passed to Mlt */ - QHash addEffect(QDomElement effect, bool animate = true); + EffectsParameterList addEffect(QDomElement effect, bool animate = true); /** Get the effect parameters that will be passed to Mlt */ - QHash getEffectArgs(QDomElement effect); + EffectsParameterList getEffectArgs(QDomElement effect); /** Delete effect with id index */ void deleteEffect(QString index); /** return the number of effects in that clip */ diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 85c646a2..651dd3f7 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -975,8 +975,7 @@ void CustomTrackView::slotRefreshEffects(ClipItem *clip) { void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect) { ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track); if (clip) { - QHash effectParams = clip->addEffect(effect); - if (!m_document->renderer()->mltAddEffect(track, pos, effectParams)) + if (!m_document->renderer()->mltAddEffect(track, pos, clip->addEffect(effect))) emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage); emit clipItemSelected(clip); } else emit displayMessage(i18n("Cannot find clip to add effect"), ErrorMessage); @@ -1024,15 +1023,15 @@ void CustomTrackView::slotDeleteEffect(ClipItem *clip, QDomElement effect) { void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect, int ix, bool triggeredByUser) { ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track); if (clip) { - QHash effectParams = clip->getEffectArgs(effect); + EffectsParameterList effectParams = clip->getEffectArgs(effect); // check if we are trying to reset a keyframe effect - if (effectParams.contains("keyframes") && effectParams.value("keyframes").isEmpty()) { + if (effectParams.hasParam("keyframes") && effectParams.paramValue("keyframes").isEmpty()) { clip->initEffect(effect); clip->setEffectAt(ix, effect); effectParams = clip->getEffectArgs(effect); } - if (effectParams.value("disabled") == "1") { - if (m_document->renderer()->mltRemoveEffect(track, pos, effectParams.value("kdenlive_ix"))) { + if (effectParams.paramValue("disabled") == "1") { + if (m_document->renderer()->mltRemoveEffect(track, pos, effectParams.paramValue("kdenlive_ix"))) { kDebug() << "////// DISABLING EFFECT: " << index << ", CURRENTLA: " << clip->selectedEffectIndex(); } else emit displayMessage(i18n("Problem deleting effect"), ErrorMessage); } else if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - clip->track(), clip->startPos(), effectParams)) @@ -1046,11 +1045,11 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect, i if (effect.attribute("tag") == "volume") { // A fade effect was modified, update the clip if (effect.attribute("id") == "fadein") { - int pos = effectParams.value("out").toInt() - effectParams.value("in").toInt(); + int pos = effectParams.paramValue("out").toInt() - effectParams.paramValue("in").toInt(); clip->setFadeIn(pos); } if (effect.attribute("id") == "fadeout") { - int pos = effectParams.value("out").toInt() - effectParams.value("in").toInt(); + int pos = effectParams.paramValue("out").toInt() - effectParams.paramValue("in").toInt(); clip->setFadeOut(pos); } @@ -2476,8 +2475,7 @@ void CustomTrackView::updateClipFade(ClipItem * item, bool updateFadeOut) { end += start; EffectsList::setParameter(oldeffect, "in", QString::number(start)); EffectsList::setParameter(oldeffect, "out", QString::number(end)); - QHash effectParams = item->getEffectArgs(oldeffect); - if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), effectParams)) + if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), item->getEffectArgs(oldeffect))) emit displayMessage(i18n("Problem editing effect"), ErrorMessage); // if fade effect is displayed, update the effect edit widget with new clip duration if (item->isSelected() && effectPos == item->selectedEffectIndex()) emit clipItemSelected(item, effectPos); @@ -2498,8 +2496,7 @@ void CustomTrackView::updateClipFade(ClipItem * item, bool updateFadeOut) { start = end - start; EffectsList::setParameter(oldeffect, "in", QString::number(start)); EffectsList::setParameter(oldeffect, "out", QString::number(end)); - QHash effectParams = item->getEffectArgs(oldeffect); - if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), effectParams)) + if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), item->getEffectArgs(oldeffect))) emit displayMessage(i18n("Problem editing effect"), ErrorMessage); // if fade effect is displayed, update the effect edit widget with new clip duration if (item->isSelected() && effectPos == item->selectedEffectIndex()) emit clipItemSelected(item, effectPos); diff --git a/src/definitions.h b/src/definitions.h index 56cfc369..69c3c702 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -79,6 +79,55 @@ struct MltVideoProfile { int display_aspect_den; }; + +class EffectParameter { +public: + EffectParameter(const QString name, const QString value): m_name(name), m_value(value) {} + QString name() const { + return m_name; + } + QString value() const { + return m_value; + } + void setValue(const QString value) { + m_value = value; + } + +private: + QString m_name; + QString m_value; +}; + +/** Use our own list for effect parameters so that they are not sorted in any ways, because + some effects like sox need a precise order +*/ +class EffectsParameterList: public QList < EffectParameter > { +public: + EffectsParameterList(): QList < EffectParameter >() {} + bool hasParam(const QString name) const { + for (int i = 0; i < size(); i++) + if (at(i).name() == name) return true; + return false; + } + QString paramValue(const QString name, QString defaultValue = QString()) const { + for (int i = 0; i < size(); i++) { + if (at(i).name() == name) return at(i).value(); + } + return defaultValue; + } + void addParam(const QString &name, const QString &value) { + if (name.isEmpty()) return; + append(EffectParameter(name, value)); + } + void removeParam(const QString name) { + for (int i = 0; i < size(); i++) + if (at(i).name() == name) { + removeAt(i); + break; + } + } +}; + class CommentedTime { public: CommentedTime(): t(GenTime(0)) {} diff --git a/src/renderer.cpp b/src/renderer.cpp index 9cafacb9..db3e7ac1 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -1720,7 +1720,7 @@ bool Render::mltRemoveEffect(int track, GenTime position, QString index, bool do } -bool Render::mltAddEffect(int track, GenTime position, QHash args, bool doRefresh) { +bool Render::mltAddEffect(int track, GenTime position, EffectsParameterList params, bool doRefresh) { Mlt::Service service(m_mltProducer->parent().get_service()); @@ -1737,7 +1737,7 @@ bool Render::mltAddEffect(int track, GenTime position, QHash // temporarily remove all effects after insert point QList filtersList; - const int filter_ix = QString(args.value("kdenlive_ix")).toInt(); + const int filter_ix = params.paramValue("kdenlive_ix").toInt(); int ct = 0; Mlt::Filter *filter = clipService.filter(ct); while (filter) { @@ -1749,30 +1749,30 @@ bool Render::mltAddEffect(int track, GenTime position, QHash } // create filter - QString tag = args.value("tag"); + QString tag = params.paramValue("tag"); kDebug() << " / / INSERTING EFFECT: " << tag; if (tag.startsWith("ladspa")) tag = "ladspa"; char *filterTag = decodedString(tag); - char *filterId = decodedString(args.value("id")); + char *filterId = decodedString(params.paramValue("id")); QHash::Iterator it; - QString kfr = args.value("keyframes"); + QString kfr = params.paramValue("keyframes"); if (!kfr.isEmpty()) { QStringList keyFrames = kfr.split(";", QString::SkipEmptyParts); - kDebug() << "// ADDING KEYFRAME EFFECT: " << args.value("keyframes"); - char *starttag = decodedString(args.value("starttag", "start")); - char *endtag = decodedString(args.value("endtag", "end")); + kDebug() << "// ADDING KEYFRAME EFFECT: " << params.paramValue("keyframes"); + char *starttag = decodedString(params.paramValue("starttag", "start")); + char *endtag = decodedString(params.paramValue("endtag", "end")); kDebug() << "// ADDING KEYFRAME TAGS: " << starttag << ", " << endtag; int duration = clip->get_playtime(); - double max = args.value("max").toDouble(); - double min = args.value("min").toDouble(); - double factor = args.value("factor", "1").toDouble(); - args.remove("starttag"); - args.remove("endtag"); - args.remove("keyframes"); - args.remove("min"); - args.remove("max"); - args.remove("factor"); + double max = params.paramValue("max").toDouble(); + double min = params.paramValue("min").toDouble(); + double factor = params.paramValue("factor", "1").toDouble(); + params.removeParam("starttag"); + params.removeParam("endtag"); + params.removeParam("keyframes"); + params.removeParam("min"); + params.removeParam("max"); + params.removeParam("factor"); int offset = 0; for (int i = 0; i < keyFrames.size() - 1; ++i) { Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, filterTag); @@ -1783,9 +1783,10 @@ bool Render::mltAddEffect(int track, GenTime position, QHash int x2 = keyFrames.at(i + 1).section(":", 0, 0).toInt(); double y2 = keyFrames.at(i + 1).section(":", 1, 1).toDouble(); if (x2 == -1) x2 = duration; - for (it = args.begin(); it != args.end(); ++it) { - char *name = decodedString(it.key()); - char *value = decodedString(it.value()); + + for (int j = 0; j < params.count(); j++) { + char *name = decodedString(params.at(j).name()); + char *value = decodedString(params.at(j).value()); filter->set(name, value); delete[] name; delete[] value; @@ -1812,13 +1813,34 @@ bool Render::mltAddEffect(int track, GenTime position, QHash return false; } - for (it = args.begin(); it != args.end(); ++it) { - char *name = decodedString(it.key()); - char *value = decodedString(it.value()); + params.removeParam("kdenlive_id"); + + for (int j = 0; j < params.count(); j++) { + char *name = decodedString(params.at(j).name()); + char *value = decodedString(params.at(j).value()); filter->set(name, value); delete[] name; delete[] value; } + + if (tag == "sox") { + QString effectArgs = params.paramValue("id").section('_', 1); + + params.removeParam("id"); + params.removeParam("kdenlive_ix"); + params.removeParam("tag"); + params.removeParam("disabled"); + + for (int j = 0; j < params.count(); j++) { + effectArgs.append(' ' + params.at(j).value()); + } + kDebug() << "SOX EFFECTS: " << effectArgs.simplified(); + char *value = decodedString(effectArgs.simplified()); + filter->set("effect", value); + delete[] value; + } + + // attach filter to the clip clipService.attach(*filter); } @@ -1835,14 +1857,14 @@ bool Render::mltAddEffect(int track, GenTime position, QHash return true; } -bool Render::mltEditEffect(int track, GenTime position, QHash args) { - QString index = args.value("kdenlive_ix"); - QString tag = args.value("tag"); - QHash::Iterator it = args.begin(); - if (!args.value("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") { +bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList params) { + QString index = params.paramValue("kdenlive_ix"); + QString tag = params.paramValue("tag"); + + if (!params.paramValue("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") { // This is a keyframe effect, to edit it, we remove it and re-add it. mltRemoveEffect(track, position, index); - bool success = mltAddEffect(track, position, args); + bool success = mltAddEffect(track, position, params); return success; } @@ -1883,7 +1905,7 @@ bool Render::mltEditEffect(int track, GenTime position, QHash } else ct++; filter = clipService.filter(ct); } - bool success = mltAddEffect(track, position, args); + bool success = mltAddEffect(track, position, params); for (int i = 0; i < filtersList.count(); i++) { clipService.attach(*(filtersList.at(i))); @@ -1893,14 +1915,14 @@ bool Render::mltEditEffect(int track, GenTime position, QHash return success; } - for (it = args.begin(); it != args.end(); ++it) { - kDebug() << " / / EDITING EFFECT ARGS: " << it.key() << ": " << it.value(); - char *name = decodedString(it.key()); - char *value = decodedString(it.value()); + for (int j = 0; j < params.count(); j++) { + char *name = decodedString(params.at(j).name()); + char *value = decodedString(params.at(j).value()); filter->set(name, value); delete[] name; delete[] value; } + m_isBlocked = false; refresh(); return true; diff --git a/src/renderer.h b/src/renderer.h index af212b73..217eb79b 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -158,8 +158,8 @@ Q_OBJECT public: bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod); bool mltRemoveClip(int track, GenTime position); bool mltRemoveEffect(int track, GenTime position, QString index, bool doRefresh = true); - bool mltAddEffect(int track, GenTime position, QHash args, bool doRefresh = true); - bool mltEditEffect(int track, GenTime position, QHash args); + bool mltAddEffect(int track, GenTime position, EffectsParameterList params, bool doRefresh = true); + bool mltEditEffect(int track, GenTime position, EffectsParameterList params); void mltMoveEffect(int track, GenTime position, int oldPos, int newPos); void mltChangeTrackState(int track, bool mute, bool blind); void mltMoveTransition(QString type, int startTrack, int newTrack, int newTransitionTrack, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut); diff --git a/src/trackview.cpp b/src/trackview.cpp index d87a0d7b..e5e920d5 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -513,12 +513,16 @@ int TrackView::slotAddProjectTrack(int ix, QDomElement xml) { QString paramname = effectparam.attribute("name"); QString paramvalue = effectparam.text(); + // try to find this parameter in the effect xml QDomElement e; for (int k = 0; k < clipeffectparams.count(); k++) { e = clipeffectparams.item(k).toElement(); if (!e.isNull() && e.tagName() == "parameter" && e.attribute("name") == paramname) { - e.setAttribute("value", paramvalue); + double factor = e.attribute("factor", "1").toDouble(); + if (factor != 1) { + e.setAttribute("value", paramvalue.toDouble() * factor); + } else e.setAttribute("value", paramvalue); break; } } -- 2.39.2