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 ***************************************************************************/
27 #include <KStandardDirs>
29 #include "initeffects.h"
31 initEffects::initEffects() {
34 initEffects::~initEffects() {
38 Mlt::Repository *initEffects::parseEffectFiles(EffectsList *audioEffectList, EffectsList *videoEffectList) {
39 QStringList::Iterator more;
40 QStringList::Iterator it;
45 // Build effects. Retrieve the list of MLT's available effects first.
46 Mlt::Repository *repository = Mlt::Factory::init();
48 kDebug() << "Repository did not finish init " ;
51 Mlt::Properties *filters = repository->filters();
52 QStringList filtersList;
54 for (int i = 0 ; i < filters->count() ; i++) {
55 filtersList << filters->get_name(i);
58 // Build effects. check producers first.
60 Mlt::Properties *producers = repository->producers();
61 QStringList producersList;
62 for (int i = 0 ; i < producers->count() ; i++) {
63 producersList << producers->get_name(i);
68 KGlobal::dirs()->addResourceType("ladspa_plugin", 0, "lib/ladspa");
69 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/lib/ladspa");
70 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/usr/local/lib/ladspa");
71 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/lib/ladspa");
72 KGlobal::dirs()->addResourceDir("ladspa_plugin", "/opt/local/lib/ladspa");
74 kDebug() << "// INIT EFFECT SEARCH" << endl;
76 QStringList direc = KGlobal::dirs()->findDirs("data", "kdenlive/effects");
79 for (more = direc.begin() ; more != direc.end() ; ++more) {
80 directory = QDir(*more);
81 fileList = directory.entryList(QDir::Files);
82 for (it = fileList.begin() ; it != fileList.end() ; ++it) {
83 itemName = KUrl(*more + *it).path();
84 parseEffectFile(audioEffectList, videoEffectList, itemName, filtersList, producersList);
85 // kDebug()<<"// FOUND EFFECT FILE: "<<itemName<<endl;
88 foreach(QString filtername, filtersList) {
89 QDomDocument doc = createDescriptionFromMlt(repository, "filters", filtername);
91 videoEffectList->append(doc.documentElement());
97 void initEffects::parseEffectFile(EffectsList *audioEffectList, EffectsList *videoEffectList, QString name, QStringList filtersList, QStringList producersList) {
100 doc.setContent(&file, false);
101 QDomElement documentElement = doc.documentElement();
102 QDomNodeList effects = doc.elementsByTagName("effect");
104 if (effects.count() == 0) {
105 kDebug() << "// EFFECT FILET: " << name << " IS BROKEN" << endl;
109 if (doc.elementsByTagName("effectgroup").item(0).toElement().tagName() == "effectgroup") {
110 groupName = documentElement.attribute("name", QString::null);
115 while (!effects.item(i).isNull()) {
116 documentElement = effects.item(i).toElement();
117 QString tag = documentElement.attribute("tag", QString::null);
118 bool ladspaOk = true;
119 if (tag == "ladspa") {
120 QString library = documentElement.attribute("library", QString::null);
121 if (KStandardDirs::locate("ladspa_plugin", library).isEmpty()) ladspaOk = false;
125 if ((filtersList.contains(tag) || producersList.contains(tag)) && ladspaOk) {
126 bool isAudioEffect = false;
127 QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
128 if (!propsnode.isNull()) {
129 QDomElement propselement = propsnode.toElement();
130 // id = propselement.attribute("id", QString::null);
131 // effectTag = propselement.attribute("tag", QString::null);
132 if (propselement.attribute("type", QString::null) == "audio") isAudioEffect = true;
133 //else if (propselement.attribute("type", QString::null) == "custom") type = CUSTOMEFFECT;
134 //else type = VIDEOEFFECT;
136 if (isAudioEffect) audioEffectList->append(documentElement);
137 else videoEffectList->append(documentElement);
141 QDomNode n = documentElement.firstChild();
142 QString id, effectName, effectTag, paramType;
147 EffectParamDescFactory effectDescParamFactory;
148 EffectDesc *effect = NULL;
151 QDomNode namenode = documentElement.elementsByTagName("name").item(0);
152 if (!namenode.isNull()) effectName = i18n(namenode.toElement().text());
153 if (!groupName.isEmpty()) effectName.prepend("_" + groupName + "_");
155 QDomNode propsnode = documentElement.elementsByTagName("properties").item(0);
156 if (!propsnode.isNull()) {
157 QDomElement propselement = propsnode.toElement();
158 id = propselement.attribute("id", QString::null);
159 effectTag = propselement.attribute("tag", QString::null);
160 if (propselement.attribute("type", QString::null) == "audio") type = AUDIOEFFECT;
161 else if (propselement.attribute("type", QString::null) == "custom") type = CUSTOMEFFECT;
162 else type = VIDEOEFFECT;
165 QString effectDescription;
166 QDomNode descnode = documentElement.elementsByTagName("description").item(0);
167 if (!descnode.isNull()) effectDescription = descnode.toElement().text() + "<br />";
169 QString effectAuthor;
170 QDomNode authnode = documentElement.elementsByTagName("author").item(0);
171 if (!authnode.isNull()) effectAuthor = authnode.toElement().text() + "<br />";
173 if (effectName.isEmpty() || id.isEmpty() || effectTag.isEmpty()) return;
175 effect = new EffectDesc(effectName, id, effectTag, effectDescription, effectAuthor, type);
177 QDomNodeList paramList = documentElement.elementsByTagName("parameter");
178 if (paramList.count() == 0) {
179 QDomElement fixed = doc.createElement("parameter");
180 fixed.setAttribute("type", "fixed");
181 effect->addParameter(effectDescParamFactory.createParameter(fixed));
183 else for (int i = 0; i < paramList.count(); i++) {
184 QDomElement e = paramList.item(i).toElement();
187 QDomNamedNodeMap attrs = e.attributes();
190 while (!attrs.item(i).isNull()) {
191 QDomNode n = attrs.item(i);
192 value = n.nodeValue();
193 if (value.find("MAX_WIDTH") != -1)
194 value.replace("MAX_WIDTH", QString::number(KdenliveSettings::defaultwidth()));
195 if (value.find("MID_WIDTH") != -1)
196 value.replace("MID_WIDTH", QString::number(KdenliveSettings::defaultwidth() / 2));
197 if (value.find("MAX_HEIGHT") != -1)
198 value.replace("MAX_HEIGHT", QString::number(KdenliveSettings::defaultheight()));
199 if (value.find("MID_HEIGHT") != -1)
200 value.replace("MID_HEIGHT", QString::number(KdenliveSettings::defaultheight() / 2));
201 n.setNodeValue(value);
204 effect->addParameter(effectDescParamFactory.createParameter(e));
207 effectList->append(effect);
214 char* initEffects::ladspaEffectString(int ladspaId, QStringList params) {
215 if (ladspaId == 1433) //Pitch
216 return ladspaPitchEffectString(params);
217 else if (ladspaId == 1216) //Room Reverb
218 return ladspaRoomReverbEffectString(params);
219 else if (ladspaId == 1423) //Reverb
220 return ladspaReverbEffectString(params);
221 else if (ladspaId == 1901) //Reverb
222 return ladspaEqualizerEffectString(params);
224 kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
225 return("<jackrack></jackrack>");
230 void initEffects::ladspaEffectFile(const QString & fname, int ladspaId, QStringList params) {
234 filterString = ladspaPitchEffectString(params);
237 filterString = ladspaVinylEffectString(params);
239 case 1216 : //Room Reverb
240 filterString = ladspaRoomReverbEffectString(params);
243 filterString = ladspaReverbEffectString(params);
245 case 1195: //Declipper
246 filterString = ladspaDeclipEffectString(params);
249 filterString = ladspaEqualizerEffectString(params);
251 case 1913: // Limiter
252 filterString = ladspaLimiterEffectString(params);
254 case 1193: // Pitch Shifter
255 filterString = ladspaPitchShifterEffectString(params);
257 case 1417: // Rate Scaler
258 filterString = ladspaRateScalerEffectString(params);
261 filterString = ladspaPhaserEffectString(params);
264 kDebug() << "++++++++++ ASKING FOR UNKNOWN LADSPA EFFECT: " << ladspaId << endl;
270 if (f.open(QIODevice::WriteOnly)) {
271 QTextStream stream(&f);
272 stream << filterString;
274 } else kDebug() << "++++++++++ ERROR CANNOT WRITE TO: " << KdenliveSettings::currenttmpfolder() + fname << endl;
278 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>";
281 char* initEffects::ladspaDeclipEffectString(QStringList) {
282 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());
286 char* initEffects::ladspaVocoderEffectString(QStringList params)
288 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]));
291 char* initEffects::ladspaVinylEffectString(QStringList params) {
292 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());
295 char* initEffects::ladspaPitchEffectString(QStringList params) {
296 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());
299 char* initEffects::ladspaRoomReverbEffectString(QStringList params) {
300 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());
303 char* initEffects::ladspaReverbEffectString(QStringList params) {
304 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());
307 char* initEffects::ladspaEqualizerEffectString(QStringList params) {
308 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());
311 char* initEffects::ladspaLimiterEffectString(QStringList params) {
312 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());
315 char* initEffects::ladspaPitchShifterEffectString(QStringList params) {
316 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());
319 char* initEffects::ladspaRateScalerEffectString(QStringList params) {
320 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());
323 char* initEffects::ladspaPhaserEffectString(QStringList params) {
324 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());
328 QDomDocument initEffects::createDescriptionFromMlt(Mlt::Repository* repository, const QString& type, const QString& filtername) {
331 Mlt::Properties *metadata = repository->metadata(filter_type, filtername.toAscii().data());
332 kDebug() << filtername;
333 if (metadata && metadata->is_valid()) {
334 if (metadata->get("title") && metadata->get("identifier")) {
335 QDomElement eff = ret.createElement("effect");
336 eff.setAttribute("tag", metadata->get("identifier"));
338 QDomElement name = ret.createElement("name");
339 name.appendChild(ret.createTextNode(metadata->get("title")));
341 QDomElement desc = ret.createElement("description");
342 desc.appendChild(ret.createTextNode(metadata->get("description")));
344 QDomElement author = ret.createElement("author");
345 author.appendChild(ret.createTextNode(metadata->get("creator")));
347 QDomElement prop = ret.createElement("properties");
348 prop.setAttribute("id", metadata->get("identifier"));
349 prop.setAttribute("tag", metadata->get("identifier"));
350 eff.appendChild(name);
351 eff.appendChild(author);
352 eff.appendChild(desc);
353 eff.appendChild(prop);
355 Mlt::Properties param_props((mlt_properties) metadata->get_data("parameters"));
356 for (int j = 0; param_props.is_valid() && j < param_props.count();j++) {
357 QDomElement params = ret.createElement("parameter");
359 Mlt::Properties paramdesc((mlt_properties) param_props.get_data(param_props.get_name(j)));
361 params.setAttribute("name", paramdesc.get("identifier"));
363 if (paramdesc.get("maximum")) params.setAttribute("max", paramdesc.get("maximum"));
364 if (paramdesc.get("minimum")) params.setAttribute("min", paramdesc.get("minimum"));
365 if (QString(paramdesc.get("type")) == "integer")
366 params.setAttribute("type", "constant");
367 if (QString(paramdesc.get("type")) == "boolean")
368 params.setAttribute("type", "bool");
369 if (!QString(paramdesc.get("format")).isEmpty()) {
370 params.setAttribute("type", "complex");
371 params.setAttribute("format", paramdesc.get("format"));
373 if (paramdesc.get("default")) params.setAttribute("default", paramdesc.get("default"));
374 if (paramdesc.get("value")) {
375 params.setAttribute("value", paramdesc.get("value"));
377 params.setAttribute("value", paramdesc.get("default"));
381 QDomElement pname = ret.createElement("name");
382 pname.appendChild(ret.createTextNode(paramdesc.get("title")));
383 params.appendChild(pname);
385 eff.appendChild(params);
387 ret.appendChild(eff);
391 QTextStream str(&outstr);