<!DOCTYPE kpartgui>
-<effect tag="volume">
+<effect tag="volume" id="volume">
<name>Volume</name>
<description>Adjust audio volume with keyframes</description>
<author>Dan Dennedy</author>
return m_selectedEffect;
}
+void ClipItem::initEffect(QDomElement effect) {
+ // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
+ // not be changed
+ if (effect.attribute("kdenlive_ix").toInt() == 0)
+ effect.setAttribute("kdenlive_ix", QString::number(effectsCounter()));
+ // init keyframes if required
+ QDomNodeList params = effect.elementsByTagName("parameter");
+ for (int i = 0; i < params.count(); i++) {
+ QDomElement e = params.item(i).toElement();
+ if (!e.isNull() && e.attribute("type") == "keyframe") {
+ double max = e.attribute("max").toDouble();
+ double min = e.attribute("min").toDouble();
+ double def = e.attribute("default").toDouble();
+ double factor = e.attribute("factor", "1").toDouble();
+
+ // Effect has a keyframe type parameter, we need to set the values
+ if (e.attribute("keyframes").isEmpty()) {
+ // no keyframes defined, set up 2 keyframes (start and end) with default value.
+ e.setAttribute("keyframes", QString::number(m_cropStart.frames(m_fps)) + ":" + QString::number(100 * def / (max - min)) + ";" + QString::number((m_cropStart + m_cropDuration).frames(m_fps)) + ":" + QString::number(100 * def / (max - min)));
+ //kDebug() << "///// EFFECT KEYFRAMES INITED: " << e.attribute("keyframes");
+ break;
+ }
+ }
+ }
+}
+
void ClipItem::setSelectedEffect(int ix) {
//if (ix == m_selectedEffect) return;
QDomElement e = params.item(i).toElement();
if (!e.isNull() && e.attribute("type") == "keyframe") {
m_keyframes.clear();
- int max = e.attribute("max").toInt();
- int min = e.attribute("min").toInt();
- int def = e.attribute("default").toInt();
+ double max = e.attribute("max").toDouble();
+ double min = e.attribute("min").toDouble();
+ double def = e.attribute("default").toDouble();
double factor = e.attribute("factor", "1").toDouble();
// Effect has a keyframe type parameter, we need to set the values
- if (e.attribute("keyframes").isEmpty()) {
+ /*if (e.attribute("keyframes").isEmpty()) {
// no keyframes defined, set up 2 keyframes (start and end) with default value.
m_keyframes[m_cropStart.frames(m_fps)] = 100 * def / (max - min);
m_keyframes[(m_cropStart + m_cropDuration).frames(m_fps)] = 100 * def / (max - min);
- } else {
- // parse keyframes
- QStringList keyframes = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
- foreach(QString str, keyframes) {
- int pos = str.section(":", 0, 0).toInt();
- double val = str.section(":", 1, 1).toDouble();
- m_keyframes[pos] = val;
- }
+ e.setAttribute("keyframes", QString::number(m_cropStart.frames(m_fps)) + ":" + QString::number(100 * def / (max - min)) + ";" + QString::number((m_cropStart + m_cropDuration).frames(m_fps)) + ":" + QString::number(100 * def / (max - min)));
+ } else {*/
+ // parse keyframes
+ QStringList keyframes = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
+ foreach(QString str, keyframes) {
+ int pos = str.section(":", 0, 0).toInt();
+ double val = str.section(":", 1, 1).toDouble();
+ m_keyframes[pos] = val;
+ //}
}
update();
return;
for (int i = 0; i < params.count(); i++) {
QDomElement e = params.item(i).toElement();
if (!e.isNull()) {
- double f = e.attribute("factor", "1").toDouble();
+ 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");
+ }
+
+ double f = e.attribute("factor", "1").toDouble();
+
if (f == 1) {
effectParams[e.attribute("name")] = e.attribute("value");
// check if it is a fade effect
void updateKeyframeEffect();
QDomElement selectedEffect();
int selectedEffectIndex() const;
+ void initEffect(QDomElement effect);
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
ClipItem *item = (ClipItem *)itemList.at(i);
- // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
- // not be changed
- if (effect.attribute("kdenlive_ix").toInt() == 0)
- effect.setAttribute("kdenlive_ix", QString::number(item->effectsCounter()));
+ item->initEffect(effect);
AddEffectCommand *command = new AddEffectCommand(this, m_tracksList.count() - item->track(), item->startPos(), effect, true);
m_commandStack->push(command);
}
return info;
}
+bool EffectsList::hasKeyFrames(QDomElement effect) {
+ QDomNodeList params = effect.elementsByTagName("parameter");
+ for (int i = 0; i < params.count(); i++) {
+ QDomElement e = params.item(i).toElement();
+ if (e.attribute("type") == "keyframe") return true;
+ }
+ return false;
+}
+
// static
void EffectsList::setParameter(QDomElement effect, QString name, QString value) {
QDomNodeList params = effect.elementsByTagName("parameter");
QStringList effectNames();
QString getInfo(QString effectName);
QMap <QString, QString> effect(const QString & name);
-
+ static bool hasKeyFrames(QDomElement effect);
static void setParameter(QDomElement effect, QString name, QString value);
};
if (!kfr.isEmpty()) {
QStringList keyFrames = kfr.split(";", QString::SkipEmptyParts);
kDebug() << "// ADDING KEYFRAME EFFECT: " << args.value("keyframes");
- char *starttag = decodedString(args.value("starttag"));
+ char *starttag = decodedString(args.value("starttag", "start"));
char *endtag = decodedString(args.value("endtag", "end"));
kDebug() << "// ADDING KEYFRAME TAGS: " << starttag << ", " << endtag;
int duration = clip->get_playtime();
- int max = args.value("max").toInt();
- int min = args.value("min").toInt();
+ 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");
- int offset = 0;
+ args.remove("min");
+ args.remove("max");
+ args.remove("factor");
+ int offset = 0;
for (int i = 0; i < keyFrames.size() - 1; ++i) {
Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, filterTag);
filter->set("kdenlive_id", filterId);
filter->set(starttag, QString::number((min + y1 * (max - min) / 100.0) / factor).toUtf8().data());
filter->set(endtag, QString::number((min + y2 * (max - min) / 100.0) / factor).toUtf8().data());
clipService.attach(*filter);
- offset = 1;
+ offset = 1;
}
delete[] starttag;
delete[] endtag;
QDomElement e = params.item(i).toElement();
if (!e.isNull() && e.attribute("tag") == paramName) {
if (e.attribute("type") == "double") {
- QString factor = e.attribute("factor");
- if (!factor.isEmpty()) {
+ QString factor = e.attribute("factor", "1");
+ if (factor != "1") {
double val = paramValue.toDouble() * factor.toDouble();
paramValue = QString::number(val);
}
for (QDomNode n2 = elem.firstChild(); !n2.isNull(); n2 = n2.nextSibling()) {
QDomElement effect = n2.toElement();
if (effect.tagName() == "filter") {
+ kDebug() << " * * * * * * * * * * ** CLIP EFF FND * * * * * * * * * * *";
// add effect to clip
QString effecttag;
QString effectid;
QDomElement effectparam = n3.toElement();
if (effectparam.attribute("name") == "tag") {
effecttag = effectparam.text();
- }
- if (effectparam.attribute("name") == "kdenlive_id") {
+ } else if (effectparam.attribute("name") == "kdenlive_id") {
effectid = effectparam.text();
- }
- if (effectparam.attribute("name") == "kdenlive_ix") {
+ } else if (effectparam.attribute("name") == "kdenlive_ix") {
effectindex = effectparam.text();
}
}
clipeffect.setAttribute("kdenlive_ix", effectindex);
QDomNodeList clipeffectparams = clipeffect.childNodes();
+ if (MainWindow::videoEffects.hasKeyFrames(clipeffect)) {
+ kDebug() << " * * * * * * * * * * ** CLIP EFF WITH KFR FND * * * * * * * * * * *";
+ // effect is key-framable, read all effects to retrieve keyframes
+ double min;
+ double max;
+ double factor;
+ QString starttag;
+ QString endtag;
+ QDomNodeList params = clipeffect.elementsByTagName("parameter");
+ for (int i = 0; i < params.count(); i++) {
+ QDomElement e = params.item(i).toElement();
+ if (e.attribute("type") == "keyframe") {
+ starttag = e.attribute("starttag", "start");
+ endtag = e.attribute("endtag", "end");
+ min = e.attribute("min").toDouble();
+ max = e.attribute("max").toDouble();
+ factor = e.attribute("factor", "1").toDouble();
+ break;
+ }
+ }
+ QString keyframes;
+ int effectin = effect.attribute("in").toInt();
+ int effectout = effect.attribute("out").toInt();
+ double startvalue;
+ double endvalue;
+ for (QDomNode n3 = effect.firstChild(); !n3.isNull(); n3 = n3.nextSibling()) {
+ // parse effect parameters
+ QDomElement effectparam = n3.toElement();
+ if (effectparam.attribute("name") == starttag)
+ startvalue = effectparam.text().toDouble() * factor / (max - min) * 100;
+ if (effectparam.attribute("name") == endtag)
+ endvalue = effectparam.text().toDouble() * factor / (max - min) * 100;
+ }
+ // add first keyframe
+ keyframes.append(QString::number(in + effectin) + ":" + QString::number(startvalue) + ";" + QString::number(in + effectout) + ":" + QString::number(endvalue) + ";");
+ QDomNode lastParsedEffect;
+ n2 = n2.nextSibling();
+ bool continueParsing = true;
+ for (; !n2.isNull() && continueParsing; n2 = n2.nextSibling()) {
+ // parse all effects
+ QDomElement kfreffect = n2.toElement();
+ int effectout = kfreffect.attribute("out").toInt();
+
+ for (QDomNode n4 = kfreffect.firstChild(); !n4.isNull(); n4 = n4.nextSibling()) {
+ // parse effect parameters
+ QDomElement subeffectparam = n4.toElement();
+ if (subeffectparam.attribute("name") == "kdenlive_ix" && subeffectparam.text() != effectindex) {
+ //We are not in the same effect, stop parsing
+ lastParsedEffect = n2.previousSibling();
+ continueParsing = false;
+ break;
+ } else if (subeffectparam.attribute("name") == endtag) {
+ endvalue = subeffectparam.text().toDouble() * factor / (max - min) * 100;
+ break;
+ }
+ }
+ if (continueParsing) keyframes.append(QString::number(in + effectout) + ":" + QString::number(endvalue) + ";");
+ }
+
+ params = clipeffect.elementsByTagName("parameter");
+ for (int i = 0; i < params.count(); i++) {
+ QDomElement e = params.item(i).toElement();
+ if (e.attribute("type") == "keyframe") e.setAttribute("keyframes", keyframes);
+ }
+ if (!continueParsing) {
+ n2 = lastParsedEffect;
+ }
+ }
+
// adjust effect parameters
for (QDomNode n3 = effect.firstChild(); !n3.isNull(); n3 = n3.nextSibling()) {
// parse effect parameters