X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finiteffects.cpp;h=a9dd406bf302b2489c558395a4a98d60f8c330df;hb=f3e4009355bff682d8e0494e188abb539874541f;hp=36d060815467db3546a9922f5e4cc1ff71924930;hpb=e8d7fcdcf399fe74a40a14db5d989d774e6f1d09;p=kdenlive diff --git a/src/initeffects.cpp b/src/initeffects.cpp index 36d06081..a9dd406b 100644 --- a/src/initeffects.cpp +++ b/src/initeffects.cpp @@ -20,7 +20,6 @@ #include "initeffects.h" #include "kdenlivesettings.h" #include "effectslist.h" -#include "effectstackedit.h" #include "mainwindow.h" #include @@ -28,10 +27,12 @@ #include #include -#include +#include #include #include +#include "locale.h" + initEffectsThumbnailer::initEffectsThumbnailer() : QThread() { @@ -49,10 +50,10 @@ void initEffectsThumbnailer::run() foreach(const QString & entry, m_list) { kDebug() << entry; if (!entry.isEmpty() && (entry.endsWith(".png") || entry.endsWith(".pgm"))) { - if (!EffectStackEdit::iconCache.contains(entry)) { + if (!MainWindow::m_lumacache.contains(entry)) { QImage pix(entry); //if (!pix.isNull()) - EffectStackEdit::iconCache[entry] = pix.scaled(30, 30); + MainWindow::m_lumacache.insert(entry, pix.scaled(30, 30, Qt::KeepAspectRatio, Qt::SmoothTransformation)); kDebug() << "stored"; } } @@ -93,7 +94,7 @@ void initEffects::refreshLumas() } QDomElement lumaTransition = MainWindow::transitions.getEffectByTag("luma", "luma"); QDomNodeList params = lumaTransition.elementsByTagName("parameter"); - for (int i = 0; i < params.count(); i++) { + for (int i = 0; i < params.count(); ++i) { QDomElement e = params.item(i).toElement(); if (e.attribute("tag") == "resource") { e.setAttribute("paramlistdisplay", imagenamelist.join(",")); @@ -104,7 +105,7 @@ void initEffects::refreshLumas() QDomElement compositeTransition = MainWindow::transitions.getEffectByTag("composite", "composite"); params = compositeTransition.elementsByTagName("parameter"); - for (int i = 0; i < params.count(); i++) { + for (int i = 0; i < params.count(); ++i) { QDomElement e = params.item(i).toElement(); if (e.attribute("tag") == "luma") { e.setAttribute("paramlistdisplay", imagenamelist.join(",")); @@ -115,7 +116,7 @@ void initEffects::refreshLumas() } // static -QDomDocument initEffects::getUsedCustomEffects(QMap effectids) +QDomDocument initEffects::getUsedCustomEffects(const QMap & effectids) { QMapIterator i(effectids); int ix; @@ -134,7 +135,7 @@ QDomDocument initEffects::getUsedCustomEffects(QMap effectids } //static -Mlt::Repository *initEffects::parseEffectFiles() +void initEffects::parseEffectFiles(const QString &locale) { QStringList::Iterator more; QStringList::Iterator it; @@ -144,20 +145,25 @@ Mlt::Repository *initEffects::parseEffectFiles() Mlt::Repository *repository = Mlt::Factory::init(); if (!repository) { kDebug() << "Repository didn't finish initialisation" ; - return NULL; + return; } + // Warning: Mlt::Factory::init() resets the locale to the default system value, make sure we keep correct locale + if (!locale.isEmpty()) setlocale(LC_NUMERIC, locale.toUtf8().constData()); + // Retrieve the list of MLT's available effects. Mlt::Properties *filters = repository->filters(); QStringList filtersList; - for (int i = 0; i < filters->count(); ++i) + int max = filters->count(); + for (int i = 0; i < max; ++i) filtersList << filters->get_name(i); delete filters; // Retrieve the list of available producers. Mlt::Properties *producers = repository->producers(); QStringList producersList; - for (int i = 0; i < producers->count(); ++i) + max = producers->count(); + for (int i = 0; i < max; ++i) producersList << producers->get_name(i); KdenliveSettings::setProducerslist(producersList); delete producers; @@ -165,7 +171,8 @@ Mlt::Repository *initEffects::parseEffectFiles() // Retrieve the list of available transitions. Mlt::Properties *transitions = repository->transitions(); QStringList transitionsItemList; - for (int i = 0; i < transitions->count(); ++i) + max = transitions->count(); + for (int i = 0; i < max; ++i) transitionsItemList << transitions->get_name(i); delete transitions; @@ -193,8 +200,10 @@ Mlt::Repository *initEffects::parseEffectFiles() while (!in.atEnd()) { QString black = in.readLine().simplified(); if (!black.isEmpty() && !black.startsWith('#') && - mltFiltersList.contains(black)) + mltFiltersList.contains(black)) { mltFiltersList.removeAll(black); + } + } file2.close(); } @@ -214,15 +223,15 @@ Mlt::Repository *initEffects::parseEffectFiles() QMap audioEffectsMap; // Create transitions - for (int i = 0; i < MainWindow::transitions.count(); ++i) { + max = MainWindow::transitions.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::transitions.at(i); - effectsMap.insert(effectInfo.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), effectInfo); + effectsMap.insert(effectInfo.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo); } MainWindow::transitions.clearList(); foreach(const QDomElement & effect, effectsMap) MainWindow::transitions.append(effect); - effectsMap.clear(); - + effectsMap.clear(); // Create effects from MLT foreach(const QString & filtername, mltFiltersList) { QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername); @@ -230,16 +239,18 @@ Mlt::Repository *initEffects::parseEffectFiles() if (!doc.isNull() && doc.elementsByTagName("parameter").count() > 0) { if (doc.documentElement().attribute("type") == "audio") { if (doc.elementsByTagName("description").count() > 0) { - QString desc = doc.documentElement().elementsByTagName("description").item(0).toElement().text(); + QString desc = doc.documentElement().firstChildElement("description").text(); //WARNING: TEMPORARY FIX for unusable MLT SOX parameters description if (desc.startsWith("Process audio using a SoX")) { // Remove MLT's SOX generated effects since the parameters properties are unusable for us } - else audioEffectsMap.insert(doc.documentElement().elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), doc.documentElement()); + else { + audioEffectsMap.insert(doc.documentElement().firstChildElement("name").text().toLower().toUtf8().data(), doc.documentElement()); + } } } else - videoEffectsMap.insert(doc.documentElement().elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), doc.documentElement()); + videoEffectsMap.insert(doc.documentElement().firstChildElement("name").text().toLower().toUtf8().data(), doc.documentElement()); } } @@ -261,9 +272,13 @@ Mlt::Repository *initEffects::parseEffectFiles() } // Create custom effects - for (int i = 0; i < MainWindow::customEffects.count(); ++i) { + max = MainWindow::customEffects.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::customEffects.at(i); - effectsMap.insert(effectInfo.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), effectInfo); + if (effectInfo.tagName() == "effectgroup") { + effectsMap.insert(effectInfo.attribute("name").toUtf8().data(), effectInfo); + } + else effectsMap.insert(effectInfo.firstChildElement("name").text().toUtf8().data(), effectInfo); } MainWindow::customEffects.clearList(); foreach(const QDomElement & effect, effectsMap) @@ -271,24 +286,24 @@ Mlt::Repository *initEffects::parseEffectFiles() effectsMap.clear(); // Create audio effects - for (int i = 0; i < MainWindow::audioEffects.count(); ++i) { + max = MainWindow::audioEffects.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::audioEffects.at(i); - audioEffectsMap.insert(effectInfo.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), effectInfo); + audioEffectsMap.insert(effectInfo.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo); } MainWindow::audioEffects.clearList(); foreach(const QDomElement & effect, audioEffectsMap) MainWindow::audioEffects.append(effect); // Create video effects - for (int i = 0; i < MainWindow::videoEffects.count(); ++i) { + max = MainWindow::videoEffects.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::videoEffects.at(i); - videoEffectsMap.insert(effectInfo.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), effectInfo); + videoEffectsMap.insert(effectInfo.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo); } MainWindow::videoEffects.clearList(); foreach(const QDomElement & effect, videoEffectsMap) MainWindow::videoEffects.append(effect); - - return repository; } // static @@ -313,40 +328,50 @@ void initEffects::parseCustomEffectsFile() QDomDocument doc; QDomNodeList effects; QDomElement e; + int unknownGroupCount = 0; foreach(const QString & filename, fileList) { QString itemName = KUrl(path + filename).path(); QFile file(itemName); doc.setContent(&file, false); file.close(); - effects = doc.elementsByTagName("effect"); - if (effects.count() != 1) { - kDebug() << "More than one effect in file " << itemName << ", not supported yet"; - } else { - e = effects.item(0).toElement(); - effectsMap.insert(e.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), e); + QDomElement base = doc.documentElement(); + if (base.tagName() == "effectgroup") { + QString groupName = base.attribute("name"); + if (groupName.isEmpty()) { + groupName = i18n("Group %1", unknownGroupCount); + base.setAttribute("name", groupName); + unknownGroupCount++; + } + effectsMap.insert(groupName.toLower().toUtf8().data(), base); + } else if (base.tagName() == "effect") { + effectsMap.insert(base.firstChildElement("name").text().toLower().toUtf8().data(), base); } + else kDebug() << "Unsupported effect file: " << itemName; } foreach(const QDomElement & effect, effectsMap) - MainWindow::customEffects.append(effect); + MainWindow::customEffects.append(effect); } // static -void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *audioEffectList, EffectsList *videoEffectList, QString name, QStringList filtersList, QStringList producersList, Mlt::Repository *repository) +void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *audioEffectList, EffectsList *videoEffectList, const QString &name, QStringList filtersList, QStringList producersList, Mlt::Repository *repository) { QDomDocument doc; QFile file(name); doc.setContent(&file, false); file.close(); - QDomElement documentElement = doc.documentElement(); - QDomNodeList effects = doc.elementsByTagName("effect"); + QDomElement documentElement; + QDomNodeList effects; + QDomElement base = doc.documentElement(); + effects = doc.elementsByTagName("effect"); if (effects.count() == 0) { kDebug() << "Effect broken: " << name; return; } - QLocale locale; + bool needsLocaleConversion = false; for (int i = 0; !effects.item(i).isNull(); ++i) { + QLocale locale; documentElement = effects.item(i).toElement(); QString tag = documentElement.attribute("tag", QString()); if (documentElement.hasAttribute("LC_NUMERIC")) { @@ -356,18 +381,7 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au needsLocaleConversion = true; } } - if (documentElement.hasAttribute("version")) { - // a specific version of the filter is required - Mlt::Properties *metadata = repository->metadata(filter_type, tag.toUtf8().data()); - if (metadata && metadata->is_valid()) { - double version = metadata->get_double("version"); - if (locale.toDouble(documentElement.attribute("version")) > version) { - delete metadata; - return; - } - } - delete metadata; - } + locale.setNumberOptions(QLocale::OmitGroupSeparator); if (needsLocaleConversion) { // we need to convert all numbers to the system's locale (for example 0.5 -> 0,5) @@ -377,8 +391,8 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au for (int j = 0; j < params.count(); j++) { QDomNamedNodeMap attrs = params.at(j).attributes(); for (int k = 0; k < attrs.count(); k++) { - QString name = attrs.item(k).nodeName(); - if (name != "type" && name != "name") { + QString nodeName = attrs.item(k).nodeName(); + if (nodeName != "type" && nodeName != "name") { QString val = attrs.item(k).nodeValue(); if (val.contains(oldSeparator)) { QString newVal = val.replace(oldSeparator, separator); @@ -389,8 +403,27 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au } } + double version = -1; + Mlt::Properties *metadata = repository->metadata(filter_type, tag.toUtf8().data()); + if (metadata && metadata->is_valid()) { + version = metadata->get_double("version"); + } + if (metadata) delete metadata; + if (documentElement.hasAttribute("version")) { + // a specific version of the filter is required + if (locale.toDouble(documentElement.attribute("version")) > version) { + return; + } + } + if (version > -1) { + // Add version info to XML + QDomNode versionNode = doc.createElement("version"); + versionNode.appendChild(doc.createTextNode(QLocale().toString(version))); + documentElement.appendChild(versionNode); + } + // Parse effect information. - if ((filtersList.contains(tag) || producersList.contains(tag))) { + if (base.tagName() != "effectgroup" && (filtersList.contains(tag) || producersList.contains(tag))) { QString type = documentElement.attribute("type", QString()); if (type == "audio") audioEffectList->append(documentElement); @@ -399,76 +432,15 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au else videoEffectList->append(documentElement); } - - /* - QDomNode n = documentElement.firstChild(); - QString id, effectName, effectTag, paramType; - int paramCount = 0; - EFFECTTYPE type; - - // Create Effect - EffectParamDescFactory effectDescParamFactory; - EffectDesc *effect = NULL; - - // parse effect file - QDomNode namenode = documentElement.elementsByTagName("name").item(0); - if (!namenode.isNull()) effectName = i18n(namenode.toElement().text()); - if (!groupName.isEmpty()) effectName.prepend("_" + groupName + "_"); - - QDomNode propsnode = documentElement.elementsByTagName("properties").item(0); - if (!propsnode.isNull()) { - QDomElement propselement = propsnode.toElement(); - id = propselement.attribute("id", QString()); - effectTag = propselement.attribute("tag", QString()); - if (propselement.attribute("type", QString()) == "audio") type = AUDIOEFFECT; - else if (propselement.attribute("type", QString()) == "custom") type = CUSTOMEFFECT; - else type = VIDEOEFFECT; - } - - QString effectDescription; - QDomNode descnode = documentElement.elementsByTagName("description").item(0); - if (!descnode.isNull()) effectDescription = descnode.toElement().text() + "
"; - - QString effectAuthor; - QDomNode authnode = documentElement.elementsByTagName("author").item(0); - if (!authnode.isNull()) effectAuthor = authnode.toElement().text() + "
"; - - if (effectName.isEmpty() || id.isEmpty() || effectTag.isEmpty()) return; - - effect = new EffectDesc(effectName, id, effectTag, effectDescription, effectAuthor, type); - - QDomNodeList paramList = documentElement.elementsByTagName("parameter"); - if (paramList.count() == 0) { - QDomElement fixed = doc.createElement("parameter"); - fixed.setAttribute("type", "fixed"); - effect->addParameter(effectDescParamFactory.createParameter(fixed)); - } - else for (int i = 0; i < paramList.count(); i++) { - QDomElement e = paramList.item(i).toElement(); - if (!e.isNull()) { - paramCount++; - QDomNamedNodeMap attrs = e.attributes(); - int i = 0; - QString value; - while (!attrs.item(i).isNull()) { - QDomNode n = attrs.item(i); - value = n.nodeValue(); - if (value.find("MAX_WIDTH") != -1) - value.replace("MAX_WIDTH", QString::number(KdenliveSettings::defaultwidth())); - if (value.find("MID_WIDTH") != -1) - value.replace("MID_WIDTH", QString::number(KdenliveSettings::defaultwidth() / 2)); - if (value.find("MAX_HEIGHT") != -1) - value.replace("MAX_HEIGHT", QString::number(KdenliveSettings::defaultheight())); - if (value.find("MID_HEIGHT") != -1) - value.replace("MID_HEIGHT", QString::number(KdenliveSettings::defaultheight() / 2)); - n.setNodeValue(value); - i++; - } - effect->addParameter(effectDescParamFactory.createParameter(e)); - } - } - effectList->append(effect); - }*/ + } + if (base.tagName() == "effectgroup") { + QString type = base.attribute("type", QString()); + if (type == "audio") + audioEffectList->append(base); + else if (type == "custom") + customEffectList->append(base); + else + videoEffectList->append(base); } } @@ -495,13 +467,17 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, QDomElement author = ret.createElement("author"); author.appendChild(ret.createTextNode(metadata->get("creator"))); + QDomElement version = ret.createElement("version"); + version.appendChild(ret.createTextNode(metadata->get("version"))); + eff.appendChild(name); eff.appendChild(author); eff.appendChild(desc); + eff.appendChild(version); Mlt::Properties tags((mlt_properties) metadata->get_data("tags")); if (QString(tags.get(0)) == "Audio") eff.setAttribute("type", "audio"); - /*for (int i = 0; i < tags.count(); i++) + /*for (int i = 0; i < tags.count(); ++i) kDebug()<get_data("parameters")); @@ -509,16 +485,23 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, QDomElement params = ret.createElement("parameter"); Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j))); - params.setAttribute("name", paramdesc.get("identifier")); + if (params.attribute("name") == "argument") { + // This parameter has to be given as attribute when using command line, do not show it in Kdenlive + continue; + } if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum")); if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum")); QString paramType = paramdesc.get("type"); - if (paramType == "integer") - params.setAttribute("type", "constant"); + if (paramType == "integer") { + if (params.attribute("min") == "0" && params.attribute("max") == "1") + params.setAttribute("type", "bool"); + else params.setAttribute("type", "constant"); + + } else if (paramType == "float") { params.setAttribute("type", "constant"); // param type is float, set default decimals to 3 @@ -543,6 +526,12 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, QDomElement pname = ret.createElement("name"); pname.appendChild(ret.createTextNode(paramdesc.get("title"))); params.appendChild(pname); + + if (paramdesc.get("description")) { + QDomElement desc = ret.createElement("comment"); + desc.appendChild(ret.createTextNode(paramdesc.get("description"))); + params.appendChild(desc); + } eff.appendChild(params); } @@ -607,8 +596,9 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * QDomElement desc = ret.createElement("description"); ktrans.appendChild(tname); ktrans.appendChild(desc); - Mlt::Properties *metadata = repository->metadata(transition_type, name.toUtf8().data()); - if (!customTransitions.contains(name) && metadata && metadata->is_valid()) { + Mlt::Properties *metadata = NULL; + if (!customTransitions.contains(name)) metadata = repository->metadata(transition_type, name.toUtf8().data()); + if (metadata && metadata->is_valid()) { // If possible, set name and description. if (metadata->get("title") && metadata->get("identifier")) tname.appendChild(ret.createTextNode(metadata->get("title"))); @@ -627,8 +617,12 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum")); if (QString(paramdesc.get("type")) == "integer") { - params.setAttribute("type", "constant"); - params.setAttribute("factor", "100"); + if (params.attribute("min") == "0" && params.attribute("max") == "1") + params.setAttribute("type", "bool"); + else { + params.setAttribute("type", "constant"); + params.setAttribute("factor", "100"); + } } if (QString(paramdesc.get("type")) == "boolean") params.setAttribute("type", "bool"); @@ -648,8 +642,6 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * params.appendChild(pname); ktrans.appendChild(params); } - delete metadata; - metadata = 0; } else { /* * Check for Kdenlive installed luma files, add empty string at @@ -700,16 +692,16 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * paramList.append(quickParameterFill(ret, "keyed", "keyed", "fixed", "1", "1", "1")); paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0/0:100%x100%:100%", "0/0:100%x100%:100%", "0/0:100%x100%:100%", "", "", "", "", "", "true")); - + paramList.append(quickParameterFill(ret, i18n("Distort"), "distort", "bool", "0", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Rotate X"), "rotate_x", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); paramList.append(quickParameterFill(ret, i18n("Rotate Z"), "rotate_z", "addedgeometry", "0", "-1800", "1800", QString(), QString(), "10")); /*paramList.append(quickParameterFill(ret, i18n("Rotate Y"), "rotate_y", "simplekeyframe", "0", "-1800", "1800", QString(), QString(), "10")); paramList.append(quickParameterFill(ret, i18n("Rotate Z"), "rotate_z", "simplekeyframe", "0", "-1800", "1800", QString(), QString(), "10"));*/ - paramList.append(quickParameterFill(ret, i18n("Fix Shear Y"), "fix_shear_y", "double", "0", "0", "360")); - paramList.append(quickParameterFill(ret, i18n("Fix Shear X"), "fix_shear_x", "double", "0", "0", "360")); - paramList.append(quickParameterFill(ret, i18n("Fix Shear Z"), "fix_shear_z", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Fix Shear Y"), "shear_y", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Fix Shear X"), "shear_x", "double", "0", "0", "360")); + paramList.append(quickParameterFill(ret, i18n("Fix Shear Z"), "shear_z", "double", "0", "0", "360")); } else if (name == "mix") { tname.appendChild(ret.createTextNode(i18n("Mix"))); } else if (name == "region") { @@ -731,7 +723,8 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * foreach(const QDomElement & e, paramList) ktrans.appendChild(e); } - + delete metadata; + metadata = 0; // Add the transition to the global list. transitions->append(ret.documentElement()); //kDebug() << ret.toString(); @@ -752,7 +745,7 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * transitions->append(ret.documentElement());*/ } -QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QString tag, QString type, QString def, QString min, QString max, QString list, QString listdisplaynames, QString factor, QString namedesc, QString format, QString opacity) +QDomElement initEffects::quickParameterFill(QDomDocument & doc, const QString &name, const QString &tag, const QString &type, const QString &def, const QString &min, const QString &max, const QString &list, const QString &listdisplaynames, const QString &factor, const QString &namedesc, const QString &format, const QString &opacity) { QDomElement parameter = doc.createElement("parameter"); parameter.setAttribute("tag", tag); @@ -779,3 +772,5 @@ QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QS return parameter; } + +#include "initeffects.moc"