1 /***************************************************************************
2 initeffects.cpp - description
5 copyright : (C) 2006 by Jean-Baptiste Mardelle
7 copyright : (C) 2008 Marco Gittler
8 email : g.marco@freenet.de
9 ***************************************************************************/
11 /***************************************************************************
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. *
18 ***************************************************************************/
28 #include <KStandardDirs>
30 #include "initeffects.h"
31 #include "kdenlivesettings.h"
32 #include "effectslist.h"
33 #include "effectstackedit.h"
34 #include "mainwindow.h"
36 initEffectsThumbnailer::initEffectsThumbnailer() {
40 void initEffectsThumbnailer::prepareThumbnailsCall(const QStringList& list) {
46 void initEffectsThumbnailer::run() {
47 foreach(const QString &entry, m_list) {
49 if (!entry.isEmpty() && (entry.endsWith(".png") || entry.endsWith(".pgm"))) {
50 if (!EffectStackEdit::iconCache.contains(entry)) {
53 EffectStackEdit::iconCache[entry] = pix.scaled(30, 30);
60 initEffectsThumbnailer initEffects::thumbnailer;
62 initEffects::initEffects() {
66 initEffects::~initEffects() {
70 Mlt::Repository *initEffects::parseEffectFiles() {
71 QStringList::Iterator more;
72 QStringList::Iterator it;
77 // Build effects. Retrieve the list of MLT's available effects first.
78 Mlt::Repository *repository = Mlt::Factory::init();
80 kDebug() << "Repository did not finish init " ;
83 Mlt::Properties *filters = repository->filters();
84 QStringList filtersList;
86 // Check for blacklisted effects
87 QString blacklist = KStandardDirs::locate("appdata", "blacklisted_effects.txt");
89 QFile file(blacklist);
90 QStringList blackListed;
92 if (file.open(QIODevice::ReadOnly)) {
93 QTextStream in(&file);
95 QString black = in.readLine().simplified();
96 if (!black.isEmpty() && !black.startsWith('#')) blackListed.append(black);
101 // Check for blacklisted transitions
102 blacklist = KStandardDirs::locate("appdata", "blacklisted_transitions.txt");
104 QFile file2(blacklist);
105 QStringList blackListedtransitions;
107 if (file2.open(QIODevice::ReadOnly)) {
108 QTextStream in(&file2);
109 while (!in.atEnd()) {
110 QString black = in.readLine().simplified();
111 if (!black.isEmpty() && !black.startsWith('#')) blackListedtransitions.append(black);
116 for (int i = 0 ; i < filters->count() ; i++) {
117 filtersList << filters->get_name(i);
120 // Build effects. check producers first.
122 Mlt::Properties *producers = repository->producers();
123 QStringList producersList;
124 for (int i = 0 ; i < producers->count() ; i++) {
125 producersList << producers->get_name(i);
130 Mlt::Properties *transitions = repository->transitions();
131 QStringList transitionsItemList;
132 for (int i = 0 ; i < transitions->count() ; i++) {
133 transitionsItemList << transitions->get_name(i);
137 foreach(const QString &trans, blackListedtransitions) {
138 if (transitionsItemList.contains(trans)) transitionsItemList.removeAll(trans);
140 fillTransitionsList(repository, &MainWindow::transitions, transitionsItemList);
142 KGlobal::dirs()->addResourceType("ladspa_plugin", 0, "lib/ladspa");
143 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib/ladspa");
144 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib/ladspa");
145 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/lib/ladspa");
146 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/local/lib/ladspa");
148 kDebug() << "// INIT EFFECT SEARCH" << endl;
150 QStringList direc = KGlobal::dirs()->findDirs("data", "kdenlive/effects");
153 for (more = direc.begin() ; more != direc.end() ; ++more) {
154 directory = QDir(*more);
157 fileList = directory.entryList(filter, QDir::Files);
158 for (it = fileList.begin() ; it != fileList.end() ; ++it) {
159 itemName = KUrl(*more + *it).path();
160 parseEffectFile(&MainWindow::customEffects, &MainWindow::audioEffects, &MainWindow::videoEffects, itemName, filtersList, producersList);
161 // kDebug()<<"// FOUND EFFECT FILE: "<<itemName<<endl;
165 foreach(const QString &effect, blackListed) {
166 if (filtersList.contains(effect)) filtersList.removeAll(effect);
169 foreach(const QString &filtername, filtersList) {
170 QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername);
172 MainWindow::videoEffects.append(doc.documentElement());
178 void initEffects::parseCustomEffectsFile() {
179 MainWindow::customEffects.clear();
180 QString path = KStandardDirs::locateLocal("appdata", "effects/", true);
181 QDir directory = QDir(path);
184 const QStringList fileList = directory.entryList(filter, QDir::Files);
186 foreach(const QString filename, fileList) {
187 itemName = KUrl(path + filename).path();
189 QFile file(itemName);
190 doc.setContent(&file, false);
192 QDomNodeList effects = doc.elementsByTagName("effect");
193 if (effects.count() != 1) {
194 kDebug() << "More than one effect in file " << itemName << ", NOT SUPPORTED YET";
196 QDomElement e = effects.item(0).toElement();
197 MainWindow::customEffects.append(e);
203 void initEffects::parseEffectFile(EffectsList *customEffectList, EffectsList *audioEffectList, EffectsList *videoEffectList, QString name, QStringList filtersList, QStringList producersList) {
206 doc.setContent(&file, false);
208 QDomElement documentElement = doc.documentElement();
209 QDomNodeList effects = doc.elementsByTagName("effect");
211 if (effects.count() == 0) {
212 kDebug() << "// EFFECT FILET: " << name << " IS BROKEN" << endl;
216 if (doc.elementsByTagName("effectgroup").item(0).toElement().tagName() == "effectgroup") {
217 groupName = documentElement.attribute("name", QString::null);
222 while (!effects.item(i).isNull()) {
223 documentElement = effects.item(i).toElement();
224 QString tag = documentElement.attribute("tag", QString::null);
225 bool ladspaOk = true;
226 if (tag == "ladspa") {
227 QString library = documentElement.attribute("library", QString::null);
228 if (KStandardDirs::locate("ladspa_plugin", library).isEmpty()) ladspaOk = false;
232 if ((filtersList.contains(tag) || producersList.contains(tag)) && ladspaOk) {
233 bool isAudioEffect = false;
234 QString type = documentElement.attribute("type", QString::null);
235 if (type == "audio") audioEffectList->append(documentElement);
236 else if (type == "custom") customEffectList->append(documentElement);
237 else videoEffectList->append(documentElement);
241 QDomNode n = documentElement.firstChild();
242 QString id, effectName, effectTag, paramType;
247 EffectParamDescFactory effectDescParamFactory;
248 EffectDesc *effect = NULL;
251 QDomNode namenode = documentElement.elementsByTagName("name").item(0);
252 if (!namenode.isNull()) effectName = i18n(namenode.toElement().text());
253 if (!groupName.isEmpty()) effectName.prepend("_" + groupName + "_");
255 QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
256 if (!propsnode.isNull()) {
257 QDomElement propselement = propsnode.toElement();
258 id = propselement.attribute("id", QString::null);
259 effectTag = propselement.attribute("tag", QString::null);
260 if (propselement.attribute("type", QString::null) == "audio") type = AUDIOEFFECT;
261 else if (propselement.attribute("type", QString::null) == "custom") type = CUSTOMEFFECT;
262 else type = VIDEOEFFECT;
265 QString effectDescription;
266 QDomNode descnode = documentElement.elementsByTagName("description").item(0);
267 if (!descnode.isNull()) effectDescription = descnode.toElement().text() + "<br />";
269 QString effectAuthor;
270 QDomNode authnode = documentElement.elementsByTagName("author").item(0);
271 if (!authnode.isNull()) effectAuthor = authnode.toElement().text() + "<br />";
273 if (effectName.isEmpty() || id.isEmpty() || effectTag.isEmpty()) return;
275 effect = new EffectDesc(effectName, id, effectTag, effectDescription, effectAuthor, type);
277 QDomNodeList paramList = documentElement.elementsByTagName("parameter");
278 if (paramList.count() == 0) {
279 QDomElement fixed = doc.createElement("parameter");
280 fixed.setAttribute("type", "fixed");
281 effect->addParameter(effectDescParamFactory.createParameter(fixed));
283 else for (int i = 0; i < paramList.count(); i++) {
284 QDomElement e = paramList.item(i).toElement();
287 QDomNamedNodeMap attrs = e.attributes();
290 while (!attrs.item(i).isNull()) {
291 QDomNode n = attrs.item(i);
292 value = n.nodeValue();
293 if (value.find("MAX_WIDTH") != -1)
294 value.replace("MAX_WIDTH", QString::number(KdenliveSettings::defaultwidth()));
295 if (value.find("MID_WIDTH") != -1)
296 value.replace("MID_WIDTH", QString::number(KdenliveSettings::defaultwidth() / 2));
297 if (value.find("MAX_HEIGHT") != -1)
298 value.replace("MAX_HEIGHT", QString::number(KdenliveSettings::defaultheight()));
299 if (value.find("MID_HEIGHT") != -1)
300 value.replace("MID_HEIGHT", QString::number(KdenliveSettings::defaultheight() / 2));
301 n.setNodeValue(value);
304 effect->addParameter(effectDescParamFactory.createParameter(e));
307 effectList->append(effect);
314 char* initEffects::ladspaEffectString(int ladspaId, QStringList params) {
315 if (ladspaId == 1433) //Pitch
316 return ladspaPitchEffectString(params);
317 else if (ladspaId == 1216) //Room Reverb
318 return ladspaRoomReverbEffectString(params);
319 else if (ladspaId == 1423) //Reverb
320 return ladspaReverbEffectString(params);
321 else if (ladspaId == 1901) //Reverb
322 return ladspaEqualizerEffectString(params);
324 kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
325 return (char *) "<jackrack></jackrack>";
330 void initEffects::ladspaEffectFile(const QString & fname, int ladspaId, QStringList params) {
334 filterString = ladspaPitchEffectString(params);
337 filterString = ladspaVinylEffectString(params);
339 case 1216 : //Room Reverb
340 filterString = ladspaRoomReverbEffectString(params);
343 filterString = ladspaReverbEffectString(params);
345 case 1195: //Declipper
346 filterString = ladspaDeclipEffectString(params);
349 filterString = ladspaEqualizerEffectString(params);
351 case 1913: // Limiter
352 filterString = ladspaLimiterEffectString(params);
354 case 1193: // Pitch Shifter
355 filterString = ladspaPitchShifterEffectString(params);
357 case 1417: // Rate Scaler
358 filterString = ladspaRateScalerEffectString(params);
361 filterString = ladspaPhaserEffectString(params);
364 kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
370 if (f.open(QIODevice::WriteOnly)) {
371 QTextStream stream(&f);
372 stream << filterString;
374 } else kDebug() << "++++++++++ ERROR CANNOT WRITE TO: " << KdenliveSettings::currenttmpfolder() + fname << endl;
378 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>";
381 char* initEffects::ladspaDeclipEffectString(QStringList) {
382 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());
386 char* initEffects::ladspaVocoderEffectString(QStringList params)
388 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]));
391 char* initEffects::ladspaVinylEffectString(QStringList params) {
392 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());
395 char* initEffects::ladspaPitchEffectString(QStringList params) {
396 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());
399 char* initEffects::ladspaRoomReverbEffectString(QStringList params) {
400 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());
403 char* initEffects::ladspaReverbEffectString(QStringList params) {
404 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());
407 char* initEffects::ladspaEqualizerEffectString(QStringList params) {
408 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());
411 char* initEffects::ladspaLimiterEffectString(QStringList params) {
412 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());
415 char* initEffects::ladspaPitchShifterEffectString(QStringList params) {
416 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());
419 char* initEffects::ladspaRateScalerEffectString(QStringList params) {
420 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());
423 char* initEffects::ladspaPhaserEffectString(QStringList params) {
424 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());
428 QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& type, const QString& filtername) {
431 Mlt::Properties *metadata = repository->metadata(filter_type, filtername.toAscii().data());
432 //kDebug() << filtername;
433 if (metadata && metadata->is_valid()) {
434 if (metadata->get("title") && metadata->get("identifier")) {
435 QDomElement eff = ret.createElement("effect");
436 eff.setAttribute("tag", metadata->get("identifier"));
437 eff.setAttribute("id", metadata->get("identifier"));
439 QDomElement name = ret.createElement("name");
440 name.appendChild(ret.createTextNode(metadata->get("title")));
442 QDomElement desc = ret.createElement("description");
443 desc.appendChild(ret.createTextNode(metadata->get("description")));
445 QDomElement author = ret.createElement("author");
446 author.appendChild(ret.createTextNode(metadata->get("creator")));
448 eff.appendChild(name);
449 eff.appendChild(author);
450 eff.appendChild(desc);
452 Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
453 for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
454 QDomElement params = ret.createElement("parameter");
456 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
458 params.setAttribute("name", paramdesc.get("identifier"));
460 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
461 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
462 if (QString(paramdesc.get("type")) == "integer")
463 params.setAttribute("type", "constant");
464 if (QString(paramdesc.get("type")) == "float") {
465 params.setAttribute("type", "constant");
466 params.setAttribute("factor", "1000");
467 if (paramdesc.get("maximum")) params.setAttribute("max", QString(paramdesc.get("maximum")).toFloat()*1000.0);
468 if (paramdesc.get("minimum")) params.setAttribute("min", QString(paramdesc.get("minimum")).toFloat()*1000.0);
470 if (QString(paramdesc.get("type")) == "boolean")
471 params.setAttribute("type", "bool");
472 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) != "geometry") {
473 params.setAttribute("type", "geometry");
474 params.setAttribute("format", paramdesc.get("format"));
476 if (!QString(paramdesc.get("format")).isEmpty() && QString(paramdesc.get("type")) == "geometry") {
477 params.setAttribute("type", "geometry");
478 //params.setAttribute("format", paramdesc.get("format"));
480 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
481 if (paramdesc.get("value")) {
482 params.setAttribute("value", paramdesc.get("value"));
484 params.setAttribute("value", paramdesc.get("default"));
488 QDomElement pname = ret.createElement("name");
489 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
490 params.appendChild(pname);
492 eff.appendChild(params);
494 ret.appendChild(eff);
498 QTextStream str(&outstr);
500 kDebug() << outstr;*/
504 void initEffects::fillTransitionsList(Mlt::Repository * repository, EffectsList* transitions, QStringList names) {
505 // remove transitions that are not implemented
506 int pos = names.indexOf("mix");
507 if (pos != -1) names.takeAt(pos);
508 pos = names.indexOf("region");
509 if (pos != -1) names.takeAt(pos);
510 foreach(const QString &name, names) {
512 QDomElement ktrans = ret.createElement("ktransition");
513 ret.appendChild(ktrans);
515 ktrans.setAttribute("tag", name);
516 QDomElement tname = ret.createElement("name");
518 QDomElement desc = ret.createElement("description");
520 QList<QDomElement> paramList;
521 Mlt::Properties *metadata = repository->metadata(transition_type, name.toAscii().data());
522 //kDebug() << filtername;
523 if (metadata && metadata->is_valid()) {
525 desc.appendChild(ret.createTextNode(metadata->get("description")));
527 Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
528 for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
529 QDomElement params = ret.createElement("parameter");
531 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
533 params.setAttribute("name", paramdesc.get("identifier"));
535 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
536 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
537 if (QString(paramdesc.get("type")) == "integer") {
538 params.setAttribute("type", "constant");
539 params.setAttribute("factor", "100");
541 if (QString(paramdesc.get("type")) == "boolean")
542 params.setAttribute("type", "bool");
543 if (!QString(paramdesc.get("format")).isEmpty()) {
544 params.setAttribute("type", "complex");
545 params.setAttribute("format", paramdesc.get("format"));
548 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
549 if (paramdesc.get("value")) {
550 params.setAttribute("value", paramdesc.get("value"));
552 params.setAttribute("value", paramdesc.get("default"));
556 QDomElement pname = ret.createElement("name");
557 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
558 params.appendChild(pname);
560 ktrans.appendChild(params);
563 ret.appendChild(ktrans);
564 if (metadata->get("title") && metadata->get("identifier")) {
565 ktrans.setAttribute("tag", name);
566 QDomElement tname = ret.createElement("name");
567 tname.appendChild(ret.createTextNode(metadata->get("title")));
568 ktrans.appendChild(tname);
571 //kDebug() << ret.toString();
573 if (name == "luma") {
575 tname.appendChild(ret.createTextNode("Luma"));
576 desc.appendChild(ret.createTextNode("Applies a luma transition between the current and next frames"));
578 QString path(mlt_environment("MLT_DATA"));
579 path.append("/lumas/").append(mlt_environment("MLT_NORMALISATION"));
580 Mlt::Properties entries;
581 mlt_properties_dir_list(entries.get_properties(), path.toAscii().data(), "*.*", 1);
582 kDebug() << path << entries.count();
584 //QStringList imagelist;
585 QString imagenamelist;
586 for (int i = 0;i < entries.count();i++) {
587 //if (!imagefiles.isEmpty()) // add empty entry too
588 imagefiles.append(",");
589 imagefiles.append(entries.get(i));
590 //imagelist << entries.get(i);
591 imagenamelist.append(",");
592 imagenamelist.append(KUrl(entries.get(i)).fileName());
594 paramList.append(quickParameterFill(ret, "Softness", "softness", "double", "0", "0", "100", "", "", "100"));
595 paramList.append(quickParameterFill(ret, "Invert", "invert", "bool", "0", "0", "1"));
596 paramList.append(quickParameterFill(ret, "ImageFile", "resource", "list", "", "", "", imagefiles, imagenamelist));
597 paramList.append(quickParameterFill(ret, "Reverse Transition", "reverse", "bool", "0", "0", "1"));
598 //thumbnailer.prepareThumbnailsCall(imagelist);
600 } else if (name == "composite") {
601 desc.appendChild(ret.createTextNode("A key-framable alpha-channel compositor for two frames."));
602 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry", "0%,0%:100%x100%:100", "-500;-500;-500;-500;0", "500;500;500;500;100"));
603 paramList.append(quickParameterFill(ret, "Distort", "distort", "bool", "1", "1", "1"));
604 tname.appendChild(ret.createTextNode("Composite"));
606 QDomElement ktrans1 = ret1.createElement("ktransition");
607 ret1.appendChild(ktrans1);
608 ktrans1.setAttribute("tag", name);
609 QDomElement tname1 = ret.createElement("name");
610 tname1.appendChild(ret1.createTextNode("PIP"));
612 } else if (name == "mix") {
613 tname.appendChild(ret.createTextNode("Mix"));
614 } else if (name == "affine") {
615 tname.appendChild(ret.createTextNode("Affine"));
616 paramList.append(quickParameterFill(ret, "Rotate Y", "rotate_y", "double", "0", "0", "360"));
617 paramList.append(quickParameterFill(ret, "Rotate X", "rotate_x", "double", "0", "0", "360"));
618 paramList.append(quickParameterFill(ret, "Rotate Z", "rotate_z", "double", "0", "0", "360"));
619 paramList.append(quickParameterFill(ret, "Fix Rotate Y", "fix_rotate_y", "double", "0", "0", "360"));
620 paramList.append(quickParameterFill(ret, "Fix Rotate X", "fix_rotate_x", "double", "0", "0", "360"));
621 paramList.append(quickParameterFill(ret, "Fix Rotate Z", "fix_rotate_z", "double", "0", "0", "360"));
622 paramList.append(quickParameterFill(ret, "Shear Y", "shear_y", "double", "0", "0", "360"));
623 paramList.append(quickParameterFill(ret, "Shear X", "shear_x", "double", "0", "0", "360"));
624 paramList.append(quickParameterFill(ret, "Shear Z", "shear_z", "double", "0", "0", "360"));
625 paramList.append(quickParameterFill(ret, "Fix Shear Y", "fix_shear_y", "double", "0", "0", "360"));
626 paramList.append(quickParameterFill(ret, "Fix Shear X", "fix_shear_x", "double", "0", "0", "360"));
627 paramList.append(quickParameterFill(ret, "Fix Shear Z", "fix_shear_z", "double", "0", "0", "360"));
628 paramList.append(quickParameterFill(ret, "Mirror", "mirror_off", "bool", "0", "0", "1"));
629 paramList.append(quickParameterFill(ret, "Repeat", "repeat_off", "bool", "0", "0", "1"));
630 paramList.append(quickParameterFill(ret, "Geometry", "geometry", "geometry", "0;0;100;100;100", "0;0;100;100;100", "0;0;100;100;100"));
631 tname.appendChild(ret.createTextNode("Composite"));
632 } else if (name == "region") {
633 tname.appendChild(ret.createTextNode("Region"));
639 ktrans.appendChild(tname);
640 ktrans.appendChild(desc);
642 foreach(const QDomElement &e, paramList) {
643 ktrans.appendChild(e);
647 transitions->append(ret.documentElement());
648 //kDebug() << "//// //// TRANSITON XML";
649 //kDebug() << ret.toString();
652 <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" />
656 QString wipetrans = "<ktransition tag=\"composite\" ><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>";
658 ret.setContent(wipetrans);
659 transitions->append(ret.documentElement());
662 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) {
663 QDomElement parameter = doc.createElement("parameter");
664 parameter.setAttribute("tag", tag);
665 parameter.setAttribute("default", def);
666 parameter.setAttribute("type", type);
667 parameter.setAttribute("name", tag);
668 parameter.setAttribute("max", max);
669 parameter.setAttribute("min", min);
671 parameter.setAttribute("paramlist", list);
672 if (!listdisplaynames.isEmpty())
673 parameter.setAttribute("paramlistdisplay", listdisplaynames);
674 if (!factor.isEmpty())
675 parameter.setAttribute("factor", factor);
676 if (!namedesc.isEmpty())
677 parameter.setAttribute("namedesc", namedesc);
678 if (!format.isEmpty())
679 parameter.setAttribute("format", format);
680 QDomElement pname = doc.createElement("name");
681 pname.appendChild(doc.createTextNode(name));
682 parameter.appendChild(pname);