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