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