]> git.sesse.net Git - kdenlive/blobdiff - src/initeffects.cpp
Integrate with the required MLT hooks for getting Movit to work.
[kdenlive] / src / initeffects.cpp
index a388b11394a7ab463d6e3d33fb6e1636eff79c99..a8c8046609441cc56b0e590ddbc4b89860e1f400 100644 (file)
@@ -20,7 +20,6 @@
 #include "initeffects.h"
 #include "kdenlivesettings.h"
 #include "effectslist.h"
-#include "effectstackedit.h"
 #include "mainwindow.h"
 
 #include <KDebug>
 #include <KStandardDirs>
 
 #include <QFile>
-#include <qregexp.h>
+#include <QRegExp>
 #include <QDir>
 #include <QIcon>
 
+#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 <QString, QString> effectids)
+QDomDocument initEffects::getUsedCustomEffects(const QMap <QString, QString>& effectids)
 {
     QMapIterator<QString, QString> i(effectids);
     int ix;
@@ -134,7 +135,7 @@ QDomDocument initEffects::getUsedCustomEffects(QMap <QString, QString> 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<QString, QDomElement> 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.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);
@@ -235,7 +244,9 @@ Mlt::Repository *initEffects::parseEffectFiles()
                     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 {
+                       audioEffectsMap.insert(doc.documentElement().firstChildElement("name").text().toLower().toUtf8().data(), doc.documentElement());
+                   }
                 }
             }
             else
@@ -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.firstChildElement("name").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,7 +286,8 @@ 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.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo);
     }
@@ -280,15 +296,14 @@ Mlt::Repository *initEffects::parseEffectFiles()
         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.firstChildElement("name").text().toLower().toUtf8().data(), effectInfo);
     }
     MainWindow::videoEffects.clearList();
     foreach(const QDomElement & effect, videoEffectsMap)
         MainWindow::videoEffects.append(effect);
-
-    return repository;
 }
 
 // static
@@ -313,32 +328,41 @@ 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.firstChildElement("name").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;
-    QDomNodeList effects = doc.elementsByTagName("effect");
+    QDomNodeList effects;
+    QDomElement base = doc.documentElement();
+    effects = doc.elementsByTagName("effect");
 
     if (effects.count() == 0) {
         kDebug() << "Effect broken: " << name;
@@ -367,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);
@@ -399,7 +423,7 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
         }
 
         // 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);
@@ -409,6 +433,15 @@ void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *au
                 videoEffectList->append(documentElement);
         }
     }
+    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);
+    }
 }
 
 QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& /*type*/, const QString& filtername)
@@ -444,7 +477,7 @@ QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository,
 
             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()<<tags.get_name(i)<<"="<<tags.get(i);*/
 
             Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
@@ -452,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
@@ -486,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);
             }
@@ -550,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")));
@@ -591,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
@@ -643,16 +688,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") {
@@ -674,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();
@@ -695,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);
@@ -722,3 +768,5 @@ QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QS
 
     return parameter;
 }
+
+#include "initeffects.moc"