X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finiteffects.cpp;h=db081873ccf004a6591510126caa9857ace75135;hb=b6d6c25f1bd07f11a0ceaf32a3a5bcaeab367336;hp=0da445dd76c72233b077da59763bec654689cb8d;hpb=4359bf84c589b4cdd98c4591b1571fd8366cb112;p=kdenlive diff --git a/src/initeffects.cpp b/src/initeffects.cpp index 0da445dd..db081873 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 @@ -32,6 +31,8 @@ #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,29 +94,29 @@ 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(",")); - e.setAttribute("paramlist", imagefiles.join(",")); + e.setAttribute("paramlist", imagefiles.join(";")); break; } } 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(",")); - e.setAttribute("paramlist", imagefiles.join(",")); + e.setAttribute("paramlist", imagefiles.join(";")); break; } } } // 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; @@ -185,42 +192,18 @@ Mlt::Repository *initEffects::parseEffectFiles() // Fill transitions list. fillTransitionsList(repository, &MainWindow::transitions, transitionsItemList); - // Set the directories to look into for ladspa plugins. - KGlobal::dirs()->addResourceType("ladspa_plugin", 0, "lib/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/lib/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/local/lib/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib64/ladspa"); - KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib64/ladspa"); - - // Set the directories to look into for effects. - QStringList direc = KGlobal::dirs()->findDirs("appdata", "effects"); - - // Iterate through effects directories to parse all XML files. - for (more = direc.begin(); more != direc.end(); ++more) { - QDir directory(*more); - QStringList filter; - filter << "*.xml"; - fileList = directory.entryList(filter, QDir::Files); - for (it = fileList.begin(); it != fileList.end(); ++it) { - itemName = KUrl(*more + *it).path(); - parseEffectFile(&MainWindow::customEffects, - &MainWindow::audioEffects, - &MainWindow::videoEffects, - itemName, filtersList, producersList, repository); - } - } - // Remove blacklisted effects from the filters list. + QStringList mltFiltersList = filtersList; QFile file2(KStandardDirs::locate("appdata", "blacklisted_effects.txt")); if (file2.open(QIODevice::ReadOnly)) { QTextStream in(&file2); while (!in.atEnd()) { QString black = in.readLine().simplified(); if (!black.isEmpty() && !black.startsWith('#') && - filtersList.contains(black)) - filtersList.removeAll(black); + mltFiltersList.contains(black)) { + mltFiltersList.removeAll(black); + } + } file2.close(); } @@ -236,49 +219,91 @@ Mlt::Repository *initEffects::parseEffectFiles() */ QDomElement effectInfo; QMap effectsMap; - for (int i = 0; i < MainWindow::transitions.count(); ++i) { + QMap videoEffectsMap; + QMap audioEffectsMap; + + // Create transitions + 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(); - for (int i = 0; i < MainWindow::customEffects.count(); ++i) { + MainWindow::transitions.append(effect); + effectsMap.clear(); + // Create effects from MLT + foreach(const QString & filtername, mltFiltersList) { + QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername); + //WARNING: TEMPORARY FIX for empty MLT effects descriptions - disable effects without parameters - jbm 09-06-2011 + if (!doc.isNull() && doc.elementsByTagName("parameter").count() > 0) { + if (doc.documentElement().attribute("type") == "audio") { + if (doc.elementsByTagName("description").count() > 0) { + 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().firstChildElement("name").text().toLower().toUtf8().data(), doc.documentElement()); + } + } + } + else + videoEffectsMap.insert(doc.documentElement().firstChildElement("name").text().toLower().toUtf8().data(), doc.documentElement()); + } + } + + // Set the directories to look into for effects. + QStringList direc = KGlobal::dirs()->findDirs("appdata", "effects"); + // Iterate through effects directories to parse all XML files. + for (more = direc.begin(); more != direc.end(); ++more) { + QDir directory(*more); + QStringList filter; + filter << "*.xml"; + fileList = directory.entryList(filter, QDir::Files); + for (it = fileList.begin(); it != fileList.end(); ++it) { + itemName = KUrl(*more + *it).path(); + parseEffectFile(&MainWindow::customEffects, + &MainWindow::audioEffects, + &MainWindow::videoEffects, + itemName, filtersList, producersList, repository); + } + } + + // Create custom effects + 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) - MainWindow::customEffects.append(effect); + MainWindow::customEffects.append(effect); effectsMap.clear(); - for (int i = 0; i < MainWindow::audioEffects.count(); ++i) { + + // Create audio effects + max = MainWindow::audioEffects.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::audioEffects.at(i); - effectsMap.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, effectsMap) - MainWindow::audioEffects.append(effect); - effectsMap.clear(); - for (int i = 0; i < MainWindow::videoEffects.count(); ++i) { + foreach(const QDomElement & effect, audioEffectsMap) + MainWindow::audioEffects.append(effect); + + // Create video effects + max = MainWindow::videoEffects.count(); + for (int i = 0; i < max; ++i) { effectInfo = MainWindow::videoEffects.at(i); - effectsMap.insert(effectInfo.elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), effectInfo); - } - // Add remaining filters - foreach(const QString & filtername, filtersList) { - QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername); - if (!doc.isNull()) - effectsMap.insert(doc.documentElement().elementsByTagName("name").item(0).toElement().text().toLower().toUtf8().data(), doc.documentElement()); + videoEffectsMap.insert(effectInfo.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo); } MainWindow::videoEffects.clearList(); - foreach(const QDomElement & effect, effectsMap) { - if (effect.attribute("type") == "audio") - MainWindow::audioEffects.append(effect); - else - MainWindow::videoEffects.append(effect); - } - - return repository; + foreach(const QDomElement & effect, videoEffectsMap) + MainWindow::videoEffects.append(effect); } // static @@ -303,63 +328,102 @@ 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; } + 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")) { + // set a locale for that file + locale = QLocale(documentElement.attribute("LC_NUMERIC")); + if (locale.decimalPoint() != QLocale().decimalPoint()) { + needsLocaleConversion = true; + } + } + locale.setNumberOptions(QLocale::OmitGroupSeparator); + + if (needsLocaleConversion) { + // we need to convert all numbers to the system's locale (for example 0.5 -> 0,5) + QChar separator = QLocale().decimalPoint(); + QChar oldSeparator = locale.decimalPoint(); + QDomNodeList params = documentElement.elementsByTagName("parameter"); + for (int j = 0; j < params.count(); j++) { + QDomNamedNodeMap attrs = params.at(j).attributes(); + for (int k = 0; k < attrs.count(); k++) { + 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); + attrs.item(k).setNodeValue(newVal); + } + } + } + } + } + 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 - Mlt::Properties *metadata = repository->metadata(filter_type, tag.toUtf8().data()); - if (metadata && metadata->is_valid()) { - double version = metadata->get_double("version"); - if (documentElement.attribute("version").toDouble() > version) { - delete metadata; - return; - } + if (locale.toDouble(documentElement.attribute("version")) > version) { + return; } - delete metadata; } - - bool ladspaOk = true; - if (tag == "ladspa") { - QString library = documentElement.attribute("library", QString()); - if (KStandardDirs::locate("ladspa_plugin", library).isEmpty()) ladspaOk = false; + 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)) && ladspaOk) { + if (base.tagName() != "effectgroup" && (filtersList.contains(tag) || producersList.contains(tag))) { QString type = documentElement.attribute("type", QString()); if (type == "audio") audioEffectList->append(documentElement); @@ -368,213 +432,18 @@ 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); - }*/ } -} - -//static -const char* initEffects::ladspaEffectString(int ladspaId, QStringList params) -{ - if (ladspaId == 1433) //Pitch - return ladspaPitchEffectString(params); - else if (ladspaId == 1216) //Room Reverb - return ladspaRoomReverbEffectString(params); - else if (ladspaId == 1423) //Reverb - return ladspaReverbEffectString(params); - else if (ladspaId == 1901) //Reverb - return ladspaEqualizerEffectString(params); - else { - kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl; - return ""; - } -} - -//static -void initEffects::ladspaEffectFile(const QString & fname, int ladspaId, QStringList params) -{ - const char *filterString; - switch (ladspaId) { - case 1433: //Pitch - filterString = ladspaPitchEffectString(params); - break; - case 1905: //Vinyl - filterString = ladspaVinylEffectString(params); - break; - case 1216 : //Room Reverb - filterString = ladspaRoomReverbEffectString(params); - break; - case 1423: //Reverb - filterString = ladspaReverbEffectString(params); - break; - case 1195: //Declipper - filterString = ladspaDeclipEffectString(params); - break; - case 1901: //Reverb - filterString = ladspaEqualizerEffectString(params); - break; - case 1913: // Limiter - filterString = ladspaLimiterEffectString(params); - break; - case 1193: // Pitch Shifter - filterString = ladspaPitchShifterEffectString(params); - break; - case 1417: // Rate Scaler - filterString = ladspaRateScalerEffectString(params); - break; - case 1217: // Phaser - filterString = ladspaPhaserEffectString(params); - break; - case 1197: // 15 Band Equalizer - filterString = ladspaEqualizer15EffectString(params); - break; - default: - kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl; - return; - break; + 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); } - - QFile f(fname); - if (f.open(QIODevice::WriteOnly)) { - QTextStream stream(&f); - stream << filterString; - f.close(); - } else kDebug() << "++++++++++ ERROR CANNOT WRITE TO: " << KdenliveSettings::currenttmpfolder() + fname << endl; - delete [] filterString; -} - -const QString jackString = "248000"; - - -const char* initEffects::ladspaDeclipEffectString(QStringList) -{ - return qstrdup(QString(jackString + "1195truefalsetrue1.0000001.000000true").toUtf8()); -} - -/* -const char* initEffects::ladspaVocoderEffectString(QStringList params) -{ - return qstrdup( QString(jackString + "1441truefalsetrue1.0000001.000000truetrue0.0000000.000000true%1%1true%1%1true%1%1true%1%1true%2%2true%2%2true%2%2true%2%2true%3%3true%3%3true%3%3true%3%3true%4%4true%4%4true%4%4true%4%4").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3])); -}*/ - -const char* initEffects::ladspaVinylEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1905truefalsetrue1.0000001.000000%1%2%3%4%5").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]).arg(params[4]).toUtf8()); -} - -const char* initEffects::ladspaPitchEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1433truefalsetrue1.01.0truetrue%1%1true4.0000004.000000").arg(params[0]).toUtf8()); -} - -const char* initEffects::ladspaRoomReverbEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1216truefalsetrue1.0000001.000000truetrue%1%1true%2%2true%3%3true0.7500000.750000true-70.000000-70.000000true0.0000000.000000true-17.500000-17.500000").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8()); -} - -const char* initEffects::ladspaReverbEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1423true falsetrue 1.0000001.000000 truetrue%1 %1true%2%2true0.2500000.250000").arg(params[0]).arg(params[1]).toUtf8()); } -const char* initEffects::ladspaEqualizerEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1901true falsetrue 1.0000001.000000%1%2 %3").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8()); -} - -const char* initEffects::ladspaLimiterEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1913truefalsetrue1.0000001.000000%1%2%3").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8()); -} - -const char* initEffects::ladspaPitchShifterEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1193truefalsetrue1.0000001.000000truetrue%1%1").arg(params[0]).toUtf8()); -} - -const char* initEffects::ladspaRateScalerEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1417truefalsetrue1.0000001.000000truetrue%1%1").arg(params[0]).toUtf8()); -} - -const char* initEffects::ladspaPhaserEffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1217truefalsetrue1.0000001.000000truetrue%1%1true%2%2true%3%3true%4%4").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]).toUtf8()); -} -const char* initEffects::ladspaEqualizer15EffectString(QStringList params) -{ - return qstrdup(QString(jackString + "1197truefalsetrue1.0000001.000000truetrue%1%1true%2%2true%3%3true%4%4true%5%5true%6%6true%7%7true%8%8true%9%9true%10%10true%11%11true%12%12true%13%13true%14%14true%15%15").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]).arg(params[4]).arg(params[5]).arg(params[6]).arg(params[7]).arg(params[8]).arg(params[9]).arg(params[10]).arg(params[11]).arg(params[12]).arg(params[13]).arg(params[14]).toUtf8()); -} - - QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& /*type*/, const QString& filtername) { @@ -587,7 +456,7 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, QString id = metadata->get("identifier"); eff.setAttribute("tag", id); eff.setAttribute("id", id); - if (id.startsWith("ladspa")) eff.setAttribute("type", "audio"); + //kDebug()<<"Effect: "<get("title"))); @@ -598,36 +467,54 @@ 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) + kDebug()<get_data("parameters")); for (int j = 0; param_props.is_valid() && j < param_props.count(); j++) { 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")); - if (QString(paramdesc.get("type")) == "integer") - params.setAttribute("type", "constant"); - if (QString(paramdesc.get("type")) == "float") { + + QString paramType = paramdesc.get("type"); + + 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 params.setAttribute("decimals", "3"); } - if (QString(paramdesc.get("type")) == "boolean") + else if (paramType == "boolean") params.setAttribute("type", "bool"); - if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) != "geometry") { + else if (paramType == "geometry") { params.setAttribute("type", "geometry"); - params.setAttribute("format", paramdesc.get("format")); } - if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) == "geometry") { - params.setAttribute("type", "geometry"); - //params.setAttribute("format", paramdesc.get("format")); + else { + params.setAttribute("type", paramType); + if (!QString(paramdesc.get("format")).isEmpty()) params.setAttribute("format", paramdesc.get("format")); } if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default")); if (paramdesc.get("value")) { @@ -636,10 +523,15 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, params.setAttribute("value", paramdesc.get("default")); } - 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); } @@ -648,7 +540,7 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, } delete metadata; metadata = 0; - /* QString outstr; + /*QString outstr; QTextStream str(&outstr); ret.save(str, 2); kDebug() << outstr;*/ @@ -689,6 +581,10 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * path.addPath(fname); imagefiles.append(path.toLocalFile()); } + + //WARNING: this is a hack to get around temporary invalid metadata in MLT, 2nd of june 2011 JBM + QStringList customTransitions; + customTransitions << "composite" << "luma" << "affine" << "mix" << "region"; foreach(const QString & name, names) { QDomDocument ret; @@ -700,7 +596,8 @@ 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()); + 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")) @@ -741,8 +638,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 @@ -758,19 +653,19 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * paramList.append(quickParameterFill(ret, i18n("Softness"), "softness", "double", "0", "0", "100", "", "", "100")); paramList.append(quickParameterFill(ret, i18nc("@property: means that the image is inverted", "Invert"), "invert", "bool", "0", "0", "1")); - paramList.append(quickParameterFill(ret, i18n("Image File"), "resource", "list", "", "", "", imagefiles.join(","), imagenamelist.join(","))); + paramList.append(quickParameterFill(ret, i18n("Image File"), "resource", "list", "", "", "", imagefiles.join(";"), imagenamelist.join(","))); paramList.append(quickParameterFill(ret, i18n("Reverse Transition"), "reverse", "bool", "0", "0", "1")); //thumbnailer.prepareThumbnailsCall(imagelist); } else if (name == "composite") { ktrans.setAttribute("id", name); tname.appendChild(ret.createTextNode(i18n("Composite"))); desc.appendChild(ret.createTextNode(i18n("A key-framable alpha-channel compositor for two frames."))); - paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0%,0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100")); + paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0%/0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100")); paramList.append(quickParameterFill(ret, i18n("Alpha Channel Operation"), "operator", "list", "over", "", "", "over,and,or,xor", i18n("Over,And,Or,Xor"))); paramList.append(quickParameterFill(ret, i18n("Align"), "aligned", "bool", "1", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Fill"), "fill", "bool", "1", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Distort"), "distort", "bool", "0", "0", "1")); - paramList.append(quickParameterFill(ret, i18n("Wipe File"), "luma", "list", "", "", "", imagefiles.join(","), imagenamelist.join(","))); + paramList.append(quickParameterFill(ret, i18n("Wipe File"), "luma", "list", "", "", "", imagefiles.join(";"), imagenamelist.join(","))); paramList.append(quickParameterFill(ret, i18n("Wipe Softness"), "softness", "double", "0", "0", "100", "", "", "100")); paramList.append(quickParameterFill(ret, i18n("Wipe Invert"), "luma_invert", "bool", "0", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Force Progressive Rendering"), "progressive", "bool", "1", "0", "1")); @@ -792,17 +687,17 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * paramList.append(quickParameterFill(ret, i18n("Fix Shear Z"), "fix_shear_z", "double", "0", "0", "360"));*/ paramList.append(quickParameterFill(ret, "keyed", "keyed", "fixed", "1", "1", "1")); - paramList.append(quickParameterFill(ret, i18n("Geometry"), "geometry", "geometry", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "0,0,100%,100%,100%", "", "", "", "", "", "true")); - + 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") { @@ -810,12 +705,12 @@ void initEffects::fillTransitionsList(Mlt::Repository *repository, EffectsList * tname.appendChild(ret.createTextNode(i18n("Region"))); desc.appendChild(ret.createTextNode(i18n("Use alpha channel of another clip to create a transition."))); paramList.append(quickParameterFill(ret, i18n("Transparency clip"), "resource", "url", "", "", "", "", "", "")); - paramList.append(quickParameterFill(ret, i18n("Geometry"), "composite.geometry", "geometry", "0%,0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100")); + paramList.append(quickParameterFill(ret, i18n("Geometry"), "composite.geometry", "geometry", "0%/0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100")); paramList.append(quickParameterFill(ret, i18n("Alpha Channel Operation"), "composite.operator", "list", "over", "", "", "over,and,or,xor", i18n("Over,And,Or,Xor"))); paramList.append(quickParameterFill(ret, i18n("Align"), "composite.aligned", "bool", "1", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Fill"), "composite.fill", "bool", "1", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Distort"), "composite.distort", "bool", "0", "0", "1")); - paramList.append(quickParameterFill(ret, i18n("Wipe File"), "composite.luma", "list", "", "", "", imagefiles.join(","), imagenamelist.join(","))); + paramList.append(quickParameterFill(ret, i18n("Wipe File"), "composite.luma", "list", "", "", "", imagefiles.join(";"), imagenamelist.join(","))); paramList.append(quickParameterFill(ret, i18n("Wipe Softness"), "composite.softness", "double", "0", "0", "100", "", "", "100")); paramList.append(quickParameterFill(ret, i18n("Wipe Invert"), "composite.luma_invert", "bool", "0", "0", "1")); paramList.append(quickParameterFill(ret, i18n("Force Progressive Rendering"), "composite.progressive", "bool", "1", "0", "1")); @@ -824,7 +719,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(); @@ -845,7 +741,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); @@ -872,3 +768,5 @@ QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QS return parameter; } + +#include "initeffects.moc"