]> git.sesse.net Git - kdenlive/blob - src/initeffects.cpp
Krazy fixes: cleanup all headers
[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 #include "initeffects.h"
21 #include "kdenlivesettings.h"
22 #include "effectslist.h"
23 #include "effectstackedit.h"
24 #include "mainwindow.h"
25
26 #include <KDebug>
27 #include <kglobal.h>
28 #include <KStandardDirs>
29
30 #include <QFile>
31 #include <qregexp.h>
32 #include <QDir>
33 #include <QIcon>
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(const 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
69 // static
70 void initEffects::refreshLumas() {
71
72     // Check for Kdenlive installed luma files
73     QStringList imagenamelist;
74     QStringList imagefiles;
75     QStringList filters;
76     filters << "*.pgm" << "*.png";
77
78     QStringList customLumas = KGlobal::dirs()->findDirs("appdata", "lumas");
79     foreach(const QString &folder, customLumas) {
80         QStringList filesnames = QDir(folder).entryList(filters, QDir::Files);
81         foreach(const QString &fname, filesnames) {
82             imagenamelist.append(fname);
83             imagefiles.append(folder + '/' + fname);
84         }
85     }
86
87     // Check for MLT lumas
88     QString folder = mlt_environment("MLT_DATA");
89     folder.append("/lumas/").append(mlt_environment("MLT_NORMALISATION"));
90     QDir lumafolder(folder);
91     QStringList filesnames = lumafolder.entryList(filters, QDir::Files);
92     foreach(const QString &fname, filesnames) {
93         imagenamelist.append(fname);
94         imagefiles.append(folder + '/' + fname);
95     }
96     QDomElement lumaTransition = MainWindow::transitions.getEffectByTag("luma", QString());
97     QDomNodeList params = lumaTransition.elementsByTagName("parameter");
98     for (int i = 0; i < params.count(); i++) {
99         QDomElement e = params.item(i).toElement();
100         if (e.attribute("tag") == "resource") {
101             e.setAttribute("paramlistdisplay", imagenamelist.join(","));
102             e.setAttribute("paramlist", imagefiles.join(","));
103             break;
104         }
105     }
106
107
108 }
109
110 //static
111 Mlt::Repository *initEffects::parseEffectFiles() {
112     QStringList::Iterator more;
113     QStringList::Iterator it;
114     QStringList fileList;
115     QString itemName;
116
117
118     // Build effects. Retrieve the list of MLT's available effects first.
119     Mlt::Repository *repository = Mlt::Factory::init();
120     if (!repository) {
121         kDebug() << "Repository did not finish init " ;
122         return NULL;
123     }
124     Mlt::Properties *filters = repository->filters();
125     QStringList filtersList;
126
127     // Check for blacklisted effects
128     QString blacklist = KStandardDirs::locate("appdata", "blacklisted_effects.txt");
129
130     QFile file(blacklist);
131     QStringList blackListed;
132
133     if (file.open(QIODevice::ReadOnly)) {
134         QTextStream in(&file);
135         while (!in.atEnd()) {
136             QString black = in.readLine().simplified();
137             if (!black.isEmpty() && !black.startsWith('#')) blackListed.append(black);
138         }
139     }
140     file.close();
141
142     // Check for blacklisted transitions
143     blacklist = KStandardDirs::locate("appdata", "blacklisted_transitions.txt");
144
145     QFile file2(blacklist);
146     QStringList blackListedtransitions;
147
148     if (file2.open(QIODevice::ReadOnly)) {
149         QTextStream in(&file2);
150         while (!in.atEnd()) {
151             QString black = in.readLine().simplified();
152             if (!black.isEmpty() && !black.startsWith('#')) blackListedtransitions.append(black);
153         }
154     }
155     file2.close();
156
157     for (int i = 0 ; i < filters->count() ; i++) {
158         filtersList << filters->get_name(i);
159     }
160
161     // Build effects. check producers first.
162
163     Mlt::Properties *producers = repository->producers();
164     QStringList producersList;
165     for (int i = 0 ; i < producers->count() ; i++) {
166         producersList << producers->get_name(i);
167     }
168     delete filters;
169     delete producers;
170
171     Mlt::Properties *transitions = repository->transitions();
172     QStringList transitionsItemList;
173     for (int i = 0 ; i < transitions->count() ; i++) {
174         transitionsItemList << transitions->get_name(i);
175     }
176     delete transitions;
177
178     foreach(const QString &trans, blackListedtransitions) {
179         if (transitionsItemList.contains(trans)) transitionsItemList.removeAll(trans);
180     }
181     fillTransitionsList(repository, &MainWindow::transitions, transitionsItemList);
182
183     KGlobal::dirs()->addResourceType("ladspa_plugin", 0, "lib/ladspa");
184     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib/ladspa");
185     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib/ladspa");
186     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/lib/ladspa");
187     KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/local/lib/ladspa");
188
189     kDebug() << "//  INIT EFFECT SEARCH" << endl;
190
191     QStringList direc = KGlobal::dirs()->findDirs("data", "kdenlive/effects");
192
193     QDir directory;
194     for (more = direc.begin() ; more != direc.end() ; ++more) {
195         directory = QDir(*more);
196         QStringList filter;
197         filter << "*.xml";
198         fileList = directory.entryList(filter, QDir::Files);
199         for (it = fileList.begin() ; it != fileList.end() ; ++it) {
200             itemName = KUrl(*more + *it).path();
201             parseEffectFile(&MainWindow::customEffects, &MainWindow::audioEffects, &MainWindow::videoEffects, itemName, filtersList, producersList);
202             // kDebug()<<"//  FOUND EFFECT FILE: "<<itemName<<endl;
203         }
204     }
205
206     foreach(const QString &effect, blackListed) {
207         if (filtersList.contains(effect)) filtersList.removeAll(effect);
208     }
209
210     foreach(const QString &filtername, filtersList) {
211         QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername);
212         if (!doc.isNull())
213             MainWindow::videoEffects.append(doc.documentElement());
214     }
215     return repository;
216 }
217
218 // static
219 void initEffects::parseCustomEffectsFile() {
220     MainWindow::customEffects.clear();
221     QString path = KStandardDirs::locateLocal("appdata", "effects/", true);
222     QDir directory = QDir(path);
223     QStringList filter;
224     filter << "*.xml";
225     const QStringList fileList = directory.entryList(filter, QDir::Files);
226     QString itemName;
227     foreach(const QString &filename, fileList) {
228         itemName = KUrl(path + filename).path();
229         QDomDocument doc;
230         QFile file(itemName);
231         doc.setContent(&file, false);
232         file.close();
233         QDomNodeList effects = doc.elementsByTagName("effect");
234         if (effects.count() != 1) {
235             kDebug() << "More than one effect in file " << itemName << ", NOT SUPPORTED YET";
236         } else {
237             QDomElement e = effects.item(0).toElement();
238             MainWindow::customEffects.append(e);
239         }
240     }
241 }
242
243 // static
244 void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *audioEffectList, EffectsList *videoEffectList, QString name, QStringList filtersList, QStringList producersList) {
245     QDomDocument doc;
246     QFile file(name);
247     doc.setContent(&file, false);
248     file.close();
249     QDomElement documentElement = doc.documentElement();
250     QDomNodeList effects = doc.elementsByTagName("effect");
251
252     if (effects.count() == 0) {
253         kDebug() << "// EFFECT FILET: " << name << " IS BROKEN" << endl;
254         return;
255     }
256     QString groupName;
257     if (doc.elementsByTagName("effectgroup").item(0).toElement().tagName() == "effectgroup") {
258         groupName = documentElement.attribute("name", QString());
259     }
260
261     int i = 0;
262
263     while (!effects.item(i).isNull()) {
264         documentElement = effects.item(i).toElement();
265         QString tag = documentElement.attribute("tag", QString());
266         bool ladspaOk = true;
267         if (tag == "ladspa") {
268             QString library = documentElement.attribute("library", QString());
269             if (KStandardDirs::locate("ladspa_plugin", library).isEmpty()) ladspaOk = false;
270         }
271
272         // Parse effect file
273         if ((filtersList.contains(tag) || producersList.contains(tag)) && ladspaOk) {
274             bool isAudioEffect = false;
275             QString type = documentElement.attribute("type", QString());
276             if (type == "audio") audioEffectList->append(documentElement);
277             else if (type == "custom") customEffectList->append(documentElement);
278             else videoEffectList->append(documentElement);
279         }
280
281         /*
282              QDomNode n = documentElement.firstChild();
283          QString id, effectName, effectTag, paramType;
284          int paramCount = 0;
285          EFFECTTYPE type;
286
287                 // Create Effect
288                 EffectParamDescFactory effectDescParamFactory;
289                 EffectDesc *effect = NULL;
290
291          // parse effect file
292          QDomNode namenode = documentElement.elementsByTagName("name").item(0);
293          if (!namenode.isNull()) effectName = i18n(namenode.toElement().text());
294          if (!groupName.isEmpty()) effectName.prepend("_" + groupName + "_");
295
296          QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
297          if (!propsnode.isNull()) {
298              QDomElement propselement = propsnode.toElement();
299              id = propselement.attribute("id", QString());
300              effectTag = propselement.attribute("tag", QString());
301              if (propselement.attribute("type", QString()) == "audio") type = AUDIOEFFECT;
302              else if (propselement.attribute("type", QString()) == "custom") type = CUSTOMEFFECT;
303              else type = VIDEOEFFECT;
304          }
305
306          QString effectDescription;
307          QDomNode descnode = documentElement.elementsByTagName("description").item(0);
308          if (!descnode.isNull()) effectDescription = descnode.toElement().text() + "<br />";
309
310          QString effectAuthor;
311          QDomNode authnode = documentElement.elementsByTagName("author").item(0);
312          if (!authnode.isNull()) effectAuthor = authnode.toElement().text() + "<br />";
313
314          if (effectName.isEmpty() || id.isEmpty() || effectTag.isEmpty()) return;
315
316          effect = new EffectDesc(effectName, id, effectTag, effectDescription, effectAuthor, type);
317
318          QDomNodeList paramList = documentElement.elementsByTagName("parameter");
319          if (paramList.count() == 0) {
320              QDomElement fixed = doc.createElement("parameter");
321              fixed.setAttribute("type", "fixed");
322              effect->addParameter(effectDescParamFactory.createParameter(fixed));
323          }
324          else for (int i = 0; i < paramList.count(); i++) {
325              QDomElement e = paramList.item(i).toElement();
326              if (!e.isNull()) {
327           paramCount++;
328            QDomNamedNodeMap attrs = e.attributes();
329           int i = 0;
330           QString value;
331           while (!attrs.item(i).isNull()) {
332               QDomNode n = attrs.item(i);
333               value = n.nodeValue();
334               if (value.find("MAX_WIDTH") != -1)
335            value.replace("MAX_WIDTH", QString::number(KdenliveSettings::defaultwidth()));
336               if (value.find("MID_WIDTH") != -1)
337            value.replace("MID_WIDTH", QString::number(KdenliveSettings::defaultwidth() / 2));
338               if (value.find("MAX_HEIGHT") != -1)
339            value.replace("MAX_HEIGHT", QString::number(KdenliveSettings::defaultheight()));
340               if (value.find("MID_HEIGHT") != -1)
341            value.replace("MID_HEIGHT", QString::number(KdenliveSettings::defaultheight() / 2));
342               n.setNodeValue(value);
343               i++;
344           }
345           effect->addParameter(effectDescParamFactory.createParameter(e));
346              }
347          }
348                 effectList->append(effect);
349          }*/
350         i++;
351     }
352 }
353
354 //static
355 char* initEffects::ladspaEffectString(int ladspaId, QStringList params) {
356     if (ladspaId == 1433)  //Pitch
357         return ladspaPitchEffectString(params);
358     else if (ladspaId == 1216)  //Room Reverb
359         return ladspaRoomReverbEffectString(params);
360     else if (ladspaId == 1423)  //Reverb
361         return ladspaReverbEffectString(params);
362     else if (ladspaId == 1901)  //Reverb
363         return ladspaEqualizerEffectString(params);
364     else {
365         kDebug() << "++++++++++  ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
366         return (char *) "<jackrack></jackrack>";
367     }
368 }
369
370 //static
371 void initEffects::ladspaEffectFile(const QString & fname, int ladspaId, QStringList params) {
372     char *filterString;
373     switch (ladspaId) {
374     case 1433: //Pitch
375         filterString = ladspaPitchEffectString(params);
376         break;
377     case 1905: //Vinyl
378         filterString = ladspaVinylEffectString(params);
379         break;
380     case 1216 : //Room Reverb
381         filterString = ladspaRoomReverbEffectString(params);
382         break;
383     case 1423: //Reverb
384         filterString = ladspaReverbEffectString(params);
385         break;
386     case 1195: //Declipper
387         filterString = ladspaDeclipEffectString(params);
388         break;
389     case 1901:  //Reverb
390         filterString = ladspaEqualizerEffectString(params);
391         break;
392     case 1913: // Limiter
393         filterString = ladspaLimiterEffectString(params);
394         break;
395     case 1193: // Pitch Shifter
396         filterString = ladspaPitchShifterEffectString(params);
397         break;
398     case 1417: // Rate Scaler
399         filterString = ladspaRateScalerEffectString(params);
400         break;
401     case 1217: // Phaser
402         filterString = ladspaPhaserEffectString(params);
403         break;
404     default:
405         kDebug() << "++++++++++  ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
406         return;
407         break;
408     }
409
410     QFile f(fname);
411     if (f.open(QIODevice::WriteOnly)) {
412         QTextStream stream(&f);
413         stream << filterString;
414         f.close();
415     } else kDebug() << "++++++++++  ERROR CANNOT WRITE TO: " << KdenliveSettings::currenttmpfolder() +  fname << endl;
416     delete filterString;
417 }
418
419 const 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>";
420
421
422 char* initEffects::ladspaDeclipEffectString(QStringList) {
423     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());
424 }
425
426 /*
427 char* initEffects::ladspaVocoderEffectString(QStringList params)
428 {
429  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]));
430 }*/
431
432 char* initEffects::ladspaVinylEffectString(QStringList params) {
433     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());
434 }
435
436 char* initEffects::ladspaPitchEffectString(QStringList params) {
437     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());
438 }
439
440 char* initEffects::ladspaRoomReverbEffectString(QStringList params) {
441     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());
442 }
443
444 char* initEffects::ladspaReverbEffectString(QStringList params) {
445     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());
446 }
447
448 char* initEffects::ladspaEqualizerEffectString(QStringList params) {
449     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());
450 }
451
452 char* initEffects::ladspaLimiterEffectString(QStringList params) {
453     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());
454 }
455
456 char* initEffects::ladspaPitchShifterEffectString(QStringList params) {
457     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());
458 }
459
460 char* initEffects::ladspaRateScalerEffectString(QStringList params) {
461     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());
462 }
463
464 char* initEffects::ladspaPhaserEffectString(QStringList params) {
465     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());
466 }
467
468
469 QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& type, const QString& filtername) {
470
471     QDomDocument ret;
472     Mlt::Properties *metadata = repository->metadata(filter_type, filtername.toAscii().data());
473     //kDebug() << filtername;
474     if (metadata && metadata->is_valid()) {
475         if (metadata->get("title") && metadata->get("identifier")) {
476             QDomElement eff = ret.createElement("effect");
477             eff.setAttribute("tag", metadata->get("identifier"));
478             eff.setAttribute("id", metadata->get("identifier"));
479
480             QDomElement name = ret.createElement("name");
481             name.appendChild(ret.createTextNode(metadata->get("title")));
482
483             QDomElement desc = ret.createElement("description");
484             desc.appendChild(ret.createTextNode(metadata->get("description")));
485
486             QDomElement author = ret.createElement("author");
487             author.appendChild(ret.createTextNode(metadata->get("creator")));
488
489             eff.appendChild(name);
490             eff.appendChild(author);
491             eff.appendChild(desc);
492
493             Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
494             for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
495                 QDomElement params = ret.createElement("parameter");
496
497                 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
498
499                 params.setAttribute("name", paramdesc.get("identifier"));
500
501                 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
502                 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
503                 if (QString(paramdesc.get("type")) == "integer")
504                     params.setAttribute("type", "constant");
505                 if (QString(paramdesc.get("type")) == "float") {
506                     params.setAttribute("type", "constant");
507                     params.setAttribute("factor", "1000");
508                     if (paramdesc.get("maximum")) params.setAttribute("max", QString(paramdesc.get("maximum")).toFloat()*1000.0);
509                     if (paramdesc.get("minimum")) params.setAttribute("min", QString(paramdesc.get("minimum")).toFloat()*1000.0);
510                 }
511                 if (QString(paramdesc.get("type")) == "boolean")
512                     params.setAttribute("type", "bool");
513                 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) != "geometry") {
514                     params.setAttribute("type", "geometry");
515                     params.setAttribute("format", paramdesc.get("format"));
516                 }
517                 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) == "geometry") {
518                     params.setAttribute("type", "geometry");
519                     //params.setAttribute("format", paramdesc.get("format"));
520                 }
521                 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
522                 if (paramdesc.get("value")) {
523                     params.setAttribute("value", paramdesc.get("value"));
524                 } else {
525                     params.setAttribute("value", paramdesc.get("default"));
526                 }
527
528
529                 QDomElement pname = ret.createElement("name");
530                 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
531                 params.appendChild(pname);
532
533                 eff.appendChild(params);
534             }
535             ret.appendChild(eff);
536         }
537     }
538     /* QString outstr;
539      QTextStream str(&outstr);
540      ret.save(str, 2);
541      kDebug() << outstr;*/
542     return ret;
543 }
544
545 void initEffects::fillTransitionsList(Mlt::Repository * repository, EffectsList* transitions, QStringList names) {
546     // remove transitions that are not implemented
547     int pos = names.indexOf("mix");
548     if (pos != -1) names.takeAt(pos);
549     pos = names.indexOf("region");
550     if (pos != -1) names.takeAt(pos);
551     foreach(const QString &name, names) {
552         QDomDocument ret;
553         QDomElement ktrans = ret.createElement("ktransition");
554         ret.appendChild(ktrans);
555
556         ktrans.setAttribute("tag", name);
557         QDomElement tname = ret.createElement("name");
558
559         QDomElement desc = ret.createElement("description");
560
561         QList<QDomElement> paramList;
562         Mlt::Properties *metadata = repository->metadata(transition_type, name.toAscii().data());
563         //kDebug() << filtername;
564         if (metadata && metadata->is_valid()) {
565
566             desc.appendChild(ret.createTextNode(metadata->get("description")));
567
568             Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
569             for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
570                 QDomElement params = ret.createElement("parameter");
571
572                 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
573
574                 params.setAttribute("name", paramdesc.get("identifier"));
575
576                 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
577                 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
578                 if (QString(paramdesc.get("type")) == "integer") {
579                     params.setAttribute("type", "constant");
580                     params.setAttribute("factor", "100");
581                 }
582                 if (QString(paramdesc.get("type")) == "boolean")
583                     params.setAttribute("type", "bool");
584                 if (!QString(paramdesc.get("format")).isEmpty()) {
585                     params.setAttribute("type", "complex");
586                     params.setAttribute("format", paramdesc.get("format"));
587
588                 }
589                 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
590                 if (paramdesc.get("value")) {
591                     params.setAttribute("value", paramdesc.get("value"));
592                 } else {
593                     params.setAttribute("value", paramdesc.get("default"));
594                 }
595
596
597                 QDomElement pname = ret.createElement("name");
598                 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
599                 params.appendChild(pname);
600
601                 ktrans.appendChild(params);
602             }
603
604             ret.appendChild(ktrans);
605             if (metadata->get("title") && metadata->get("identifier")) {
606                 ktrans.setAttribute("tag", name);
607                 QDomElement tname = ret.createElement("name");
608                 tname.appendChild(ret.createTextNode(metadata->get("title")));
609                 ktrans.appendChild(tname);
610             }
611
612             //kDebug() << ret.toString();
613         } else {
614             if (name == "luma") {
615
616                 tname.appendChild(ret.createTextNode("Luma"));
617                 desc.appendChild(ret.createTextNode("Applies a luma transition between the current and next frames"));
618
619                 // Check for Kdenlive installed luma files
620                 QStringList imagenamelist;
621                 QStringList imagefiles;
622                 QStringList filters;
623                 filters << "*.pgm" << "*.png";
624
625                 QStringList customLumas = KGlobal::dirs()->findDirs("appdata", "lumas");
626                 foreach(const QString &folder, customLumas) {
627                     QStringList filesnames = QDir(folder).entryList(filters, QDir::Files);
628                     foreach(const QString &fname, filesnames) {
629                         imagenamelist.append(fname);
630                         imagefiles.append(folder + '/' + fname);
631                     }
632                 }
633
634                 // Check for MLT lumas
635                 QString folder = mlt_environment("MLT_DATA");
636                 folder.append("/lumas/").append(mlt_environment("MLT_NORMALISATION"));
637                 QDir lumafolder(folder);
638                 QStringList filesnames = lumafolder.entryList(filters, QDir::Files);
639                 foreach(const QString &fname, filesnames) {
640                     imagenamelist.append(fname);
641                     imagefiles.append(folder + '/' + fname);
642                 }
643
644                 paramList.append(quickParameterFill(ret, "Softness", "softness", "double", "0", "0", "100", "", "", "100"));
645                 paramList.append(quickParameterFill(ret, "Invert", "invert", "bool", "0", "0", "1"));
646                 paramList.append(quickParameterFill(ret, "ImageFile", "resource", "list", "", "", "", imagefiles.join(","), imagenamelist.join(",")));
647                 paramList.append(quickParameterFill(ret, "Reverse Transition", "reverse", "bool", "0", "0", "1"));
648                 //thumbnailer.prepareThumbnailsCall(imagelist);
649
650             } else if (name == "composite") {
651                 desc.appendChild(ret.createTextNode("A key-framable alpha-channel compositor for two frames."));
652                 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry", "0%,0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100"));
653                 paramList.append(quickParameterFill(ret, "Distort", "distort", "bool", "1", "1", "1"));
654                 tname.appendChild(ret.createTextNode("Composite"));
655                 ktrans.setAttribute("id", "composite");
656                 /*QDomDocument ret1;
657                 QDomElement ktrans1 = ret1.createElement("ktransition");
658                 ret1.appendChild(ktrans1);
659                 ktrans1.setAttribute("tag", name);
660                 QDomElement tname1 = ret.createElement("name");
661                 tname1.appendChild(ret1.createTextNode("PIP"));*/
662
663             } else if (name == "mix") {
664                 tname.appendChild(ret.createTextNode("Mix"));
665             } else if (name == "affine") {
666                 tname.appendChild(ret.createTextNode("Affine"));
667                 paramList.append(quickParameterFill(ret, "Rotate Y", "rotate_y", "double", "0", "0", "360"));
668                 paramList.append(quickParameterFill(ret, "Rotate X", "rotate_x", "double", "0", "0", "360"));
669                 paramList.append(quickParameterFill(ret, "Rotate Z", "rotate_z", "double", "0", "0", "360"));
670                 paramList.append(quickParameterFill(ret, "Fix Rotate Y", "fix_rotate_y", "double", "0", "0", "360"));
671                 paramList.append(quickParameterFill(ret, "Fix Rotate X", "fix_rotate_x", "double", "0", "0", "360"));
672                 paramList.append(quickParameterFill(ret, "Fix Rotate Z", "fix_rotate_z", "double", "0", "0", "360"));
673                 paramList.append(quickParameterFill(ret, "Shear Y", "shear_y", "double", "0", "0", "360"));
674                 paramList.append(quickParameterFill(ret, "Shear X", "shear_x", "double", "0", "0", "360"));
675                 paramList.append(quickParameterFill(ret, "Shear Z", "shear_z", "double", "0", "0", "360"));
676                 paramList.append(quickParameterFill(ret, "Fix Shear Y", "fix_shear_y", "double", "0", "0", "360"));
677                 paramList.append(quickParameterFill(ret, "Fix Shear X", "fix_shear_x", "double", "0", "0", "360"));
678                 paramList.append(quickParameterFill(ret, "Fix Shear Z", "fix_shear_z", "double", "0", "0", "360"));
679                 paramList.append(quickParameterFill(ret, "Mirror", "mirror_off", "bool", "0", "0", "1"));
680                 paramList.append(quickParameterFill(ret, "Repeat", "repeat_off", "bool", "0", "0", "1"));
681                 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry",  "0;0;100;100;100", "0;0;100;100;100", "0;0;100;100;100"));
682                 tname.appendChild(ret.createTextNode("Composite"));
683             } else if (name == "region") {
684                 tname.appendChild(ret.createTextNode("Region"));
685             }
686
687
688         }
689
690         ktrans.appendChild(tname);
691         ktrans.appendChild(desc);
692
693         foreach(const QDomElement &e, paramList) {
694             ktrans.appendChild(e);
695         }
696
697
698         transitions->append(ret.documentElement());
699         //kDebug() << "//// ////  TRANSITON XML";
700         // kDebug() << ret.toString();
701         /*
702
703          <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" />
704         */
705     }
706
707     QString wipetrans = "<ktransition tag=\"composite\" id=\"wipe\"><name>Wipe</name><description>Slide image from one side to another</description><parameter tag=\"geometry\" type=\"wipe\" default=\"-100%,0%:100%x100%;-1=0%,0%:100%x100%\" name=\"geometry\"><name>Direction</name>                                               </parameter><parameter tag=\"aligned\" default=\"0\" type=\"bool\" name=\"aligned\" ><name>Align</name></parameter></ktransition>";
708     QDomDocument ret;
709     ret.setContent(wipetrans);
710     transitions->append(ret.documentElement());
711
712     QString alphatrans = "<ktransition tag=\"composite\" id=\"alphatransparency\" ><name>Alpha transparency</name><description>Make alpha channel transparent</description><parameter tag=\"geometry\" type=\"fixed\" default=\"0%,0%:100%x100%\" name=\"geometry\"><name>Direction</name></parameter><parameter tag=\"fill\" default=\"0\" type=\"bool\" name=\"fill\" ><name>Rescale</name></parameter><parameter tag=\"aligned\" default=\"0\" type=\"bool\" name=\"aligned\" ><name>Align</name></parameter></ktransition>";
713     QDomDocument ret2;
714     ret2.setContent(alphatrans);
715     transitions->append(ret2.documentElement());
716 }
717
718 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) {
719     QDomElement parameter = doc.createElement("parameter");
720     parameter.setAttribute("tag", tag);
721     parameter.setAttribute("default", def);
722     parameter.setAttribute("type", type);
723     parameter.setAttribute("name", tag);
724     parameter.setAttribute("max", max);
725     parameter.setAttribute("min", min);
726     if (!list.isEmpty())
727         parameter.setAttribute("paramlist", list);
728     if (!listdisplaynames.isEmpty())
729         parameter.setAttribute("paramlistdisplay", listdisplaynames);
730     if (!factor.isEmpty())
731         parameter.setAttribute("factor", factor);
732     if (!namedesc.isEmpty())
733         parameter.setAttribute("namedesc", namedesc);
734     if (!format.isEmpty())
735         parameter.setAttribute("format", format);
736     QDomElement pname = doc.createElement("name");
737     pname.appendChild(doc.createTextNode(name));
738     parameter.appendChild(pname);
739
740     return parameter;
741 }