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