]> git.sesse.net Git - kdenlive/blob - src/initeffects.cpp
some small updates
[kdenlive] / src / initeffects.cpp
1 /***************************************************************************
2                           initeffects.cpp  -  description
3                              -------------------
4     begin                :  Jul 2006
5     copyright            : (C) 2006 by Jean-Baptiste Mardelle
6     email                : jb@ader.ch
7     copyright            : (C) 2008 Marco Gittler
8     email                : g.marco@freenet.de
9  ***************************************************************************/
10
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19
20
21 #include <QFile>
22 #include <qregexp.h>
23 #include <QDir>
24 #include <QIcon>
25
26 #include <KDebug>
27 #include <kglobal.h>
28 #include <KStandardDirs>
29
30 #include "initeffects.h"
31 #include "kdenlivesettings.h"
32 #include "effectslist.h"
33 #include "effectstackedit.h"
34
35 initEffectsThumbnailer::initEffectsThumbnailer() {
36
37 }
38
39 void initEffectsThumbnailer::prepareThumbnailsCall(const QStringList& list) {
40     m_list = list;
41     start();
42     kDebug() << "done";
43 }
44
45 void initEffectsThumbnailer::run() {
46     foreach(QString entry, m_list) {
47         kDebug() << entry;
48         if (!entry.isEmpty() && (entry.endsWith(".png") || entry.endsWith(".pgm"))) {
49             if (!EffectStackEdit::iconCache.contains(entry)) {
50                 QImage pix(entry);
51                 //if (!pix.isNull())
52                 EffectStackEdit::iconCache[entry] = pix.scaled(30, 30);
53                 kDebug() << "stored";
54             }
55         }
56     }
57 }
58
59 initEffectsThumbnailer initEffects::thumbnailer;
60
61 initEffects::initEffects() {
62
63 }
64
65 initEffects::~initEffects() {
66 }
67
68 //static
69 Mlt::Repository *initEffects::parseEffectFiles(EffectsList *audioEffectList, EffectsList *videoEffectList, EffectsList* transitionsList) {
70     QStringList::Iterator more;
71     QStringList::Iterator it;
72     QStringList fileList;
73     QString itemName;
74
75
76     // Build effects. Retrieve the list of MLT's available effects first.
77     Mlt::Repository *repository = Mlt::Factory::init();
78     if (!repository) {
79         kDebug() << "Repository did not finish init " ;
80         return NULL;
81     }
82     Mlt::Properties *filters = repository->filters();
83     QStringList filtersList;
84
85     for (int i = 0 ; i < filters->count() ; i++) {
86         filtersList << filters->get_name(i);
87     }
88
89     // Build effects. check producers first.
90
91     Mlt::Properties *producers = repository->producers();
92     QStringList producersList;
93     for (int i = 0 ; i < producers->count() ; i++) {
94         producersList << producers->get_name(i);
95     }
96     delete filters;
97     delete producers;
98
99     Mlt::Properties *transitions = repository->transitions();
100     QStringList transitionsItemList;
101     for (int i = 0 ; i < transitions->count() ; i++) {
102         transitionsItemList << transitions->get_name(i);
103     }
104     delete transitions;
105     fillTransitionsList(repository, transitionsList, transitionsItemList);
106
107     KGlobal::dirs()->addResourceType("ladspa_plugin", 0, "lib/ladspa");
108     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib/ladspa");
109     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib/ladspa");
110     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/lib/ladspa");
111     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/local/lib/ladspa");
112
113     kDebug() << "//  INIT EFFECT SEARCH" << endl;
114
115     QStringList direc = KGlobal::dirs()->findDirs("data", "kdenlive/effects");
116
117     QDir directory;
118     for (more = direc.begin() ; more != direc.end() ; ++more) {
119         directory = QDir(*more);
120         fileList = directory.entryList(QDir::Files);
121         for (it = fileList.begin() ; it != fileList.end() ; ++it) {
122             itemName = KUrl(*more + *it).path();
123             parseEffectFile(audioEffectList, videoEffectList, itemName, filtersList, producersList);
124             // kDebug()<<"//  FOUND EFFECT FILE: "<<itemName<<endl;
125         }
126     }
127     foreach(QString filtername, filtersList) {
128         QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername);
129         if (!doc.isNull())
130             videoEffectList->append(doc.documentElement());
131     }
132     return repository;
133 }
134
135 // static
136 void initEffects::parseEffectFile(EffectsList *audioEffectList, EffectsList *videoEffectList, QString name, QStringList filtersList, QStringList producersList) {
137     QDomDocument doc;
138     QFile file(name);
139     doc.setContent(&file, false);
140     QDomElement documentElement = doc.documentElement();
141     QDomNodeList effects = doc.elementsByTagName("effect");
142
143     if (effects.count() == 0) {
144         kDebug() << "// EFFECT FILET: " << name << " IS BROKEN" << endl;
145         return;
146     }
147     QString groupName;
148     if (doc.elementsByTagName("effectgroup").item(0).toElement().tagName() == "effectgroup") {
149         groupName = documentElement.attribute("name", QString::null);
150     }
151
152     int i = 0;
153
154     while (!effects.item(i).isNull()) {
155         documentElement = effects.item(i).toElement();
156         QString tag = documentElement.attribute("tag", QString::null);
157         bool ladspaOk = true;
158         if (tag == "ladspa") {
159             QString library = documentElement.attribute("library", QString::null);
160             if (KStandardDirs::locate("ladspa_plugin", library).isEmpty()) ladspaOk = false;
161         }
162
163         // Parse effect file
164         if ((filtersList.contains(tag) || producersList.contains(tag)) && ladspaOk) {
165             bool isAudioEffect = false;
166             QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
167             if (!propsnode.isNull()) {
168                 QDomElement propselement = propsnode.toElement();
169 //     id = propselement.attribute("id", QString::null);
170 //     effectTag = propselement.attribute("tag", QString::null);
171                 if (propselement.attribute("type", QString::null) == "audio") isAudioEffect = true;
172                 //else if (propselement.attribute("type", QString::null) == "custom") type = CUSTOMEFFECT;
173                 //else type = VIDEOEFFECT;
174             }
175             if (isAudioEffect) audioEffectList->append(documentElement);
176             else videoEffectList->append(documentElement);
177         }
178
179         /*
180              QDomNode n = documentElement.firstChild();
181          QString id, effectName, effectTag, paramType;
182          int paramCount = 0;
183          EFFECTTYPE type;
184
185                 // Create Effect
186                 EffectParamDescFactory effectDescParamFactory;
187                 EffectDesc *effect = NULL;
188
189          // parse effect file
190          QDomNode namenode = documentElement.elementsByTagName("name").item(0);
191          if (!namenode.isNull()) effectName = i18n(namenode.toElement().text());
192          if (!groupName.isEmpty()) effectName.prepend("_" + groupName + "_");
193
194          QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
195          if (!propsnode.isNull()) {
196              QDomElement propselement = propsnode.toElement();
197              id = propselement.attribute("id", QString::null);
198              effectTag = propselement.attribute("tag", QString::null);
199              if (propselement.attribute("type", QString::null) == "audio") type = AUDIOEFFECT;
200              else if (propselement.attribute("type", QString::null) == "custom") type = CUSTOMEFFECT;
201              else type = VIDEOEFFECT;
202          }
203
204          QString effectDescription;
205          QDomNode descnode = documentElement.elementsByTagName("description").item(0);
206          if (!descnode.isNull()) effectDescription = descnode.toElement().text() + "<br />";
207
208          QString effectAuthor;
209          QDomNode authnode = documentElement.elementsByTagName("author").item(0);
210          if (!authnode.isNull()) effectAuthor = authnode.toElement().text() + "<br />";
211
212          if (effectName.isEmpty() || id.isEmpty() || effectTag.isEmpty()) return;
213
214          effect = new EffectDesc(effectName, id, effectTag, effectDescription, effectAuthor, type);
215
216          QDomNodeList paramList = documentElement.elementsByTagName("parameter");
217          if (paramList.count() == 0) {
218              QDomElement fixed = doc.createElement("parameter");
219              fixed.setAttribute("type", "fixed");
220              effect->addParameter(effectDescParamFactory.createParameter(fixed));
221          }
222          else for (int i = 0; i < paramList.count(); i++) {
223              QDomElement e = paramList.item(i).toElement();
224              if (!e.isNull()) {
225           paramCount++;
226            QDomNamedNodeMap attrs = e.attributes();
227           int i = 0;
228           QString value;
229           while (!attrs.item(i).isNull()) {
230               QDomNode n = attrs.item(i);
231               value = n.nodeValue();
232               if (value.find("MAX_WIDTH") != -1)
233            value.replace("MAX_WIDTH", QString::number(KdenliveSettings::defaultwidth()));
234               if (value.find("MID_WIDTH") != -1)
235            value.replace("MID_WIDTH", QString::number(KdenliveSettings::defaultwidth() / 2));
236               if (value.find("MAX_HEIGHT") != -1)
237            value.replace("MAX_HEIGHT", QString::number(KdenliveSettings::defaultheight()));
238               if (value.find("MID_HEIGHT") != -1)
239            value.replace("MID_HEIGHT", QString::number(KdenliveSettings::defaultheight() / 2));
240               n.setNodeValue(value);
241               i++;
242           }
243           effect->addParameter(effectDescParamFactory.createParameter(e));
244              }
245          }
246                 effectList->append(effect);
247          }*/
248         i++;
249     }
250 }
251
252 //static
253 char* initEffects::ladspaEffectString(int ladspaId, QStringList params) {
254     if (ladspaId == 1433)  //Pitch
255         return ladspaPitchEffectString(params);
256     else if (ladspaId == 1216)  //Room Reverb
257         return ladspaRoomReverbEffectString(params);
258     else if (ladspaId == 1423)  //Reverb
259         return ladspaReverbEffectString(params);
260     else if (ladspaId == 1901)  //Reverb
261         return ladspaEqualizerEffectString(params);
262     else {
263         kDebug() << "++++++++++  ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
264         return("<jackrack></jackrack>");
265     }
266 }
267
268 //static
269 void initEffects::ladspaEffectFile(const QString & fname, int ladspaId, QStringList params) {
270     char *filterString;
271     switch (ladspaId) {
272     case 1433: //Pitch
273         filterString = ladspaPitchEffectString(params);
274         break;
275     case 1905: //Vinyl
276         filterString = ladspaVinylEffectString(params);
277         break;
278     case 1216 : //Room Reverb
279         filterString = ladspaRoomReverbEffectString(params);
280         break;
281     case 1423: //Reverb
282         filterString = ladspaReverbEffectString(params);
283         break;
284     case 1195: //Declipper
285         filterString = ladspaDeclipEffectString(params);
286         break;
287     case 1901:  //Reverb
288         filterString = ladspaEqualizerEffectString(params);
289         break;
290     case 1913: // Limiter
291         filterString = ladspaLimiterEffectString(params);
292         break;
293     case 1193: // Pitch Shifter
294         filterString = ladspaPitchShifterEffectString(params);
295         break;
296     case 1417: // Rate Scaler
297         filterString = ladspaRateScalerEffectString(params);
298         break;
299     case 1217: // Phaser
300         filterString = ladspaPhaserEffectString(params);
301         break;
302     default:
303         kDebug() << "++++++++++  ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
304         return;
305         break;
306     }
307
308     QFile f(fname);
309     if (f.open(QIODevice::WriteOnly)) {
310         QTextStream stream(&f);
311         stream << filterString;
312         f.close();
313     } else kDebug() << "++++++++++  ERROR CANNOT WRITE TO: " << KdenliveSettings::currenttmpfolder() +  fname << endl;
314     delete filterString;
315 }
316
317 QString jackString = "<?xml version=\"1.0\"?><!DOCTYPE jackrack SYSTEM \"http://purge.bash.sh/~rah/jack_rack_1.2.dtd\"><jackrack><channels>2</channels><samplerate>48000</samplerate><plugin><id>";
318
319
320 char* initEffects::ladspaDeclipEffectString(QStringList) {
321     return qstrdup(QString(jackString + "1195</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall></plugin></jackrack>").toUtf8());
322 }
323
324 /*
325 char* initEffects::ladspaVocoderEffectString(QStringList params)
326 {
327  return qstrdup( QString(jackString + "1441</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>0.000000</value><value>0.000000</value></controlrow><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>%4</value><value>%4</value></controlrow><controlrow><lock>true</lock><value>%4</value><value>%4</value></controlrow><controlrow><lock>true</lock><value>%4</value><value>%4</value></controlrow><controlrow><lock>true</lock><value>%4</value><value>%4</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]));
328 }*/
329
330 char* initEffects::ladspaVinylEffectString(QStringList params) {
331     return qstrdup(QString(jackString + "1905</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><controlrow><value>%1</value></controlrow><controlrow><value>%2</value></controlrow><controlrow><value>%3</value></controlrow><controlrow><value>%4</value></controlrow><controlrow><value>%5</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]).arg(params[4]).toUtf8());
332 }
333
334 char* initEffects::ladspaPitchEffectString(QStringList params) {
335     return qstrdup(QString(jackString + "1433</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.0</value><value>1.0</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>4.000000</value><value>4.000000</value></controlrow></plugin></jackrack>").arg(params[0]).toUtf8());
336 }
337
338 char* initEffects::ladspaRoomReverbEffectString(QStringList params) {
339     return qstrdup(QString(jackString + "1216</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>0.750000</value><value>0.750000</value></controlrow><controlrow><lock>true</lock><value>-70.000000</value><value>-70.000000</value></controlrow><controlrow><lock>true</lock><value>0.000000</value><value>0.000000</value></controlrow><controlrow><lock>true</lock><value>-17.500000</value><value>-17.500000</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8());
340 }
341
342 char* initEffects::ladspaReverbEffectString(QStringList params) {
343     return qstrdup(QString(jackString + "1423</id><enabled>true</enabled>  <wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked>    <wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values>    <lockall>true</lockall><controlrow><lock>true</lock><value>%1</value>      <value>%1</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>0.250000</value><value>0.250000</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).toUtf8());
344 }
345
346 char* initEffects::ladspaEqualizerEffectString(QStringList params) {
347     return qstrdup(QString(jackString + "1901</id><enabled>true</enabled>    <wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked>    <wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><controlrow><value>%1</value></controlrow><controlrow><value>%2</value></controlrow>    <controlrow><value>%3</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8());
348 }
349
350 char* initEffects::ladspaLimiterEffectString(QStringList params) {
351     return qstrdup(QString(jackString + "1913</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><controlrow><value>%1</value></controlrow><controlrow><value>%2</value></controlrow><controlrow><value>%3</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).toUtf8());
352 }
353
354 char* initEffects::ladspaPitchShifterEffectString(QStringList params) {
355     return qstrdup(QString(jackString + "1193</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow></plugin></jackrack>").arg(params[0]).toUtf8());
356 }
357
358 char* initEffects::ladspaRateScalerEffectString(QStringList params) {
359     return qstrdup(QString(jackString + "1417</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow></plugin></jackrack>").arg(params[0]).toUtf8());
360 }
361
362 char* initEffects::ladspaPhaserEffectString(QStringList params) {
363     return qstrdup(QString(jackString + "1217</id><enabled>true</enabled><wet_dry_enabled>false</wet_dry_enabled><wet_dry_locked>true</wet_dry_locked><wet_dry_values><value>1.000000</value><value>1.000000</value></wet_dry_values><lockall>true</lockall><controlrow><lock>true</lock><value>%1</value><value>%1</value></controlrow><controlrow><lock>true</lock><value>%2</value><value>%2</value></controlrow><controlrow><lock>true</lock><value>%3</value><value>%3</value></controlrow><controlrow><lock>true</lock><value>%4</value><value>%4</value></controlrow></plugin></jackrack>").arg(params[0]).arg(params[1]).arg(params[2]).arg(params[3]).toUtf8());
364 }
365
366
367 QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& type, const QString& filtername) {
368
369     QDomDocument ret;
370     Mlt::Properties *metadata = repository->metadata(filter_type, filtername.toAscii().data());
371     //kDebug() << filtername;
372     if (metadata && metadata->is_valid()) {
373         if (metadata->get("title") && metadata->get("identifier")) {
374             QDomElement eff = ret.createElement("effect");
375             eff.setAttribute("tag", metadata->get("identifier"));
376
377             QDomElement name = ret.createElement("name");
378             name.appendChild(ret.createTextNode(metadata->get("title")));
379
380             QDomElement desc = ret.createElement("description");
381             desc.appendChild(ret.createTextNode(metadata->get("description")));
382
383             QDomElement author = ret.createElement("author");
384             author.appendChild(ret.createTextNode(metadata->get("creator")));
385
386             QDomElement prop = ret.createElement("properties");
387             prop.setAttribute("id", metadata->get("identifier"));
388             prop.setAttribute("tag", metadata->get("identifier"));
389             eff.appendChild(name);
390             eff.appendChild(author);
391             eff.appendChild(desc);
392             eff.appendChild(prop);
393
394             Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
395             for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
396                 QDomElement params = ret.createElement("parameter");
397
398                 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
399
400                 params.setAttribute("name", paramdesc.get("identifier"));
401
402                 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
403                 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
404                 if (QString(paramdesc.get("type")) == "integer")
405                     params.setAttribute("type", "constant");
406                 if (QString(paramdesc.get("type")) == "boolean")
407                     params.setAttribute("type", "bool");
408                 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) != "geometry") {
409                     params.setAttribute("type", "complex");
410                     params.setAttribute("format", paramdesc.get("format"));
411                 }
412                 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) == "geometry") {
413                     params.setAttribute("type", "geometry");
414                     //params.setAttribute("format", paramdesc.get("format"));
415                 }
416                 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
417                 if (paramdesc.get("value")) {
418                     params.setAttribute("value", paramdesc.get("value"));
419                 } else {
420                     params.setAttribute("value", paramdesc.get("default"));
421                 }
422
423
424                 QDomElement pname = ret.createElement("name");
425                 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
426                 params.appendChild(pname);
427
428                 eff.appendChild(params);
429             }
430             ret.appendChild(eff);
431         }
432     }
433     /* QString outstr;
434      QTextStream str(&outstr);
435      ret.save(str, 2);
436      kDebug() << outstr;*/
437     return ret;
438 }
439
440 void initEffects::fillTransitionsList(Mlt::Repository * repository, EffectsList* transitions, QStringList names) {
441     foreach(QString name, names) {
442         QDomDocument ret;
443         QDomElement ktrans = ret.createElement("ktransition");
444         ret.appendChild(ktrans);
445         ktrans.setAttribute("tag", name);
446         QDomElement tname = ret.createElement("name");
447         QList<QDomElement> paramList;
448         Mlt::Properties *metadata = repository->metadata(transition_type, name.toAscii().data());
449         //kDebug() << filtername;
450         if (metadata && metadata->is_valid()) {
451             Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
452             for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
453                 QDomElement params = ret.createElement("parameter");
454
455                 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
456
457                 params.setAttribute("name", paramdesc.get("identifier"));
458
459                 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
460                 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
461                 if (QString(paramdesc.get("type")) == "integer") {
462                     params.setAttribute("type", "constant");
463                     params.setAttribute("factor", "100");
464                 }
465                 if (QString(paramdesc.get("type")) == "boolean")
466                     params.setAttribute("type", "bool");
467                 if (!QString(paramdesc.get("format")).isEmpty()) {
468                     params.setAttribute("type", "complex");
469                     params.setAttribute("format", paramdesc.get("format"));
470
471                 }
472                 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
473                 if (paramdesc.get("value")) {
474                     params.setAttribute("value", paramdesc.get("value"));
475                 } else {
476                     params.setAttribute("value", paramdesc.get("default"));
477                 }
478
479
480                 QDomElement pname = ret.createElement("name");
481                 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
482                 params.appendChild(pname);
483
484                 ktrans.appendChild(params);
485             }
486
487             ret.appendChild(ktrans);
488             if (metadata->get("title") && metadata->get("identifier")) {
489                 ktrans.setAttribute("tag", name);
490                 QDomElement tname = ret.createElement("name");
491                 tname.appendChild(ret.createTextNode(metadata->get("title")));
492                 ktrans.appendChild(tname);
493             }
494
495             //kDebug() << ret.toString();
496         } else {
497
498
499             if (name == "luma") {
500
501                 tname.appendChild(ret.createTextNode("Luma"));
502
503                 QString path(mlt_environment("MLT_DATA"));
504                 path.append("/lumas/").append(mlt_environment("MLT_NORMALISATION"));
505                 Mlt::Properties entries;
506                 mlt_properties_dir_list(entries.get_properties(), path.toAscii().data(), "*.*", 1);
507                 kDebug() << path << entries.count();
508                 QString imagefiles;
509                 QStringList imagelist;
510                 for (int i = 0;i < entries.count();i++) {
511                     //if (!imagefiles.isEmpty()) // add empty entry too
512                     imagefiles.append(",");
513                     imagefiles.append(entries.get(i));
514                     imagelist << entries.get(i);
515                 }
516                 paramList.append(quickParameterFill(ret, "Softness", "softness", "double", "0", "0", "100", "", "100"));
517                 paramList.append(quickParameterFill(ret, "Invert", "invert", "bool", "0", "0", "1"));
518                 paramList.append(quickParameterFill(ret, "ImageFile", "resource", "list", "", "", "", imagefiles));
519                 //thumbnailer.prepareThumbnailsCall(imagelist);
520
521             } else if (name == "composite") {
522                 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry", "0;0;100;100;100", "0;0;100;100;100", "0;0;100;100;100"));
523                 tname.appendChild(ret.createTextNode("Composite"));
524
525                 QDomDocument ret1;
526                 QDomElement ktrans1 = ret1.createElement("ktransition");
527                 ret1.appendChild(ktrans1);
528                 ktrans1.setAttribute("tag", name);
529                 QDomElement tname1 = ret.createElement("name");
530                 tname1.appendChild(ret1.createTextNode("PIP"));
531
532             } else if (name == "mix") {
533                 tname.appendChild(ret.createTextNode("Mix"));
534             } else if (name == "affine") {
535                 tname.appendChild(ret.createTextNode("Affine"));
536                 paramList.append(quickParameterFill(ret, "Rotate Y", "rotate_y", "double", "0", "0", "360"));
537                 paramList.append(quickParameterFill(ret, "Rotate X", "rotate_x", "double", "0", "0", "360"));
538                 paramList.append(quickParameterFill(ret, "Rotate Z", "rotate_z", "double", "0", "0", "360"));
539                 paramList.append(quickParameterFill(ret, "Fix Rotate Y", "fix_rotate_y", "double", "0", "0", "360"));
540                 paramList.append(quickParameterFill(ret, "Fix Rotate X", "fix_rotate_x", "double", "0", "0", "360"));
541                 paramList.append(quickParameterFill(ret, "Fix Rotate Z", "fix_rotate_z", "double", "0", "0", "360"));
542                 paramList.append(quickParameterFill(ret, "Shear Y", "shear_y", "double", "0", "0", "360"));
543                 paramList.append(quickParameterFill(ret, "Shear X", "shear_x", "double", "0", "0", "360"));
544                 paramList.append(quickParameterFill(ret, "Shear Z", "shear_z", "double", "0", "0", "360"));
545                 paramList.append(quickParameterFill(ret, "Fix Shear Y", "fix_shear_y", "double", "0", "0", "360"));
546                 paramList.append(quickParameterFill(ret, "Fix Shear X", "fix_shear_x", "double", "0", "0", "360"));
547                 paramList.append(quickParameterFill(ret, "Fix Shear Z", "fix_shear_z", "double", "0", "0", "360"));
548                 paramList.append(quickParameterFill(ret, "Mirror", "mirror_off", "bool", "0", "0", "1"));
549                 paramList.append(quickParameterFill(ret, "Repeat", "repeat_off", "bool", "0", "0", "1"));
550                 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry",  "0;0;100;100;100", "0;0;100;100;100", "0;0;100;100;100"));
551                 tname.appendChild(ret.createTextNode("Composite"));
552             } else if (name == "region") {
553                 tname.appendChild(ret.createTextNode("Region"));
554             }
555
556
557         }
558         paramList.append(quickParameterFill(ret, "Reverse Transition", "reverse", "bool", "1", "0", "1"));
559         ktrans.appendChild(tname);
560
561         foreach(QDomElement e, paramList) {
562             ktrans.appendChild(e);
563         }
564
565
566         transitions->append(ret.documentElement());
567         /*
568
569          <transition fill="1" in="11" a_track="1" out="73" mlt_service="luma" b_track="2" softness="0" resource="/home/marco/Projekte/kdenlive/install_cmake/share/apps/kdenlive/pgm/PAL/square2.pgm" />
570         */
571     }
572 }
573 QDomElement initEffects::quickParameterFill(QDomDocument & doc, QString name, QString tag, QString type, QString def, QString min, QString max, QString list, QString factor, QString namedesc, QString format) {
574     QDomElement parameter = doc.createElement("parameter");
575     parameter.setAttribute("tag", tag);
576     parameter.setAttribute("default", def);
577     parameter.setAttribute("type", type);
578     parameter.setAttribute("name", tag);
579     parameter.setAttribute("max", max);
580     parameter.setAttribute("min", min);
581     if (!list.isEmpty())
582         parameter.setAttribute("paramlist", list);
583     if (!factor.isEmpty())
584         parameter.setAttribute("factor", factor);
585     if (!namedesc.isEmpty())
586         parameter.setAttribute("namedesc", namedesc);
587     if (!format.isEmpty())
588         parameter.setAttribute("format", format);
589     QDomElement pname = doc.createElement("name");
590     pname.appendChild(doc.createTextNode(name));
591     parameter.appendChild(pname);
592
593     return parameter;
594 }