aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Effect/ladspa
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2009-12-05 22:59:14 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2009-12-05 22:59:14 +0000
commita5cee8c56f06bc4d5a1cbf5b63f310583f9e876b (patch)
tree6809d2a6c5e86583e61faf38173d660f24cabd53 /src/plugins/Effect/ladspa
parentcdb0e21d40b77292b0125d729ad17d64226fd169 (diff)
downloadqmmp-a5cee8c56f06bc4d5a1cbf5b63f310583f9e876b.tar.gz
qmmp-a5cee8c56f06bc4d5a1cbf5b63f310583f9e876b.tar.bz2
qmmp-a5cee8c56f06bc4d5a1cbf5b63f310583f9e876b.zip
prepare for ladspa support
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@1421 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Effect/ladspa')
-rw-r--r--src/plugins/Effect/ladspa/effectladspafactory.cpp59
-rw-r--r--src/plugins/Effect/ladspa/effectladspafactory.h44
-rw-r--r--src/plugins/Effect/ladspa/ladspa.pro42
-rw-r--r--src/plugins/Effect/ladspa/ladspaplugin.cpp532
-rw-r--r--src/plugins/Effect/ladspa/ladspaplugin.h95
-rw-r--r--src/plugins/Effect/ladspa/settingsdialog.cpp95
-rw-r--r--src/plugins/Effect/ladspa/settingsdialog.h53
-rw-r--r--src/plugins/Effect/ladspa/settingsdialog.ui139
8 files changed, 1059 insertions, 0 deletions
diff --git a/src/plugins/Effect/ladspa/effectladspafactory.cpp b/src/plugins/Effect/ladspa/effectladspafactory.cpp
new file mode 100644
index 000000000..c2536969b
--- /dev/null
+++ b/src/plugins/Effect/ladspa/effectladspafactory.cpp
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QtGui>
+#include <qmmp/qmmp.h>
+#include "effectladspafactory.h"
+#include "settingsdialog.h"
+#include "ladspaplugin.h"
+
+const EffectProperties EffectLADSPAFactory::properties() const
+{
+ EffectProperties properties;
+ properties.name = tr("LADSPA Plugin");
+ properties.shortName = "ladspa";
+ properties.hasSettings = TRUE;
+ properties.hasAbout = TRUE;
+ return properties;
+}
+
+Effect *EffectLADSPAFactory::create(QObject *parent)
+{
+ return new LADSPAHost(parent);
+}
+
+void EffectLADSPAFactory::showSettings(QWidget *parent)
+{
+ SettingsDialog *s = new SettingsDialog(parent);
+ s->show();
+}
+
+void EffectLADSPAFactory::showAbout(QWidget *parent)
+{}
+
+QTranslator *EffectLADSPAFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = Qmmp::systemLanguageID();
+ translator->load(QString(":/ladspa_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN2(ladspa,EffectLADSPAFactory)
diff --git a/src/plugins/Effect/ladspa/effectladspafactory.h b/src/plugins/Effect/ladspa/effectladspafactory.h
new file mode 100644
index 000000000..9a9c5f184
--- /dev/null
+++ b/src/plugins/Effect/ladspa/effectladspafactory.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef EFFECTLADSPAFACTORY_H
+#define EFFECTLADSPAFACTORY_H
+
+#include <QObject>
+#include <qmmp/effectfactory.h>
+#include <qmmp/effect.h>
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class EffectLADSPAFactory : public QObject, public EffectFactory
+{
+Q_OBJECT
+Q_INTERFACES(EffectFactory);
+
+public:
+ const EffectProperties properties() const;
+ Effect *create(QObject *parent);
+ void showSettings(QWidget *parent);
+ void showAbout(QWidget *parent);
+ QTranslator *createTranslator(QObject *parent);
+};
+
+
+#endif
diff --git a/src/plugins/Effect/ladspa/ladspa.pro b/src/plugins/Effect/ladspa/ladspa.pro
new file mode 100644
index 000000000..1eb686c53
--- /dev/null
+++ b/src/plugins/Effect/ladspa/ladspa.pro
@@ -0,0 +1,42 @@
+include(../../plugins.pri)
+
+HEADERS += ladspaplugin.h \
+ effectladspafactory.h \
+ settingsdialog.h
+
+SOURCES += ladspaplugin.cpp \
+ effectladspafactory.cpp \
+ settingsdialog.cpp
+
+TARGET =$$PLUGINS_PREFIX/Effect/ladspa
+QMAKE_CLEAN =$$PLUGINS_PREFIX/Effect/libladspa.so
+INCLUDEPATH += ../../../
+CONFIG += release \
+warn_on \
+plugin \
+link_pkgconfig
+
+TEMPLATE = lib
+QMAKE_LIBDIR += ../../../../lib
+LIBS += -lqmmp -L/usr/lib -I/usr/include
+
+TRANSLATIONS = translations/ladspa_plugin_cs.ts \
+ translations/ladspa_plugin_de.ts \
+ translations/ladspa_plugin_zh_CN.ts \
+ translations/ladspa_plugin_zh_TW.ts \
+ translations/ladspa_plugin_uk_UA.ts \
+ translations/ladspa_plugin_pl.ts \
+ translations/ladspa_plugin_ru.ts \
+ translations/ladspa_plugin_it.ts \
+ translations/ladspa_plugin_tr.ts \
+ translations/ladspa_plugin_lt.ts
+#RESOURCES = translations/translations.qrc
+
+isEmpty(LIB_DIR){
+ LIB_DIR = /lib
+}
+target.path = $$LIB_DIR/qmmp/Effect
+INSTALLS += target
+
+
+FORMS += settingsdialog.ui
diff --git a/src/plugins/Effect/ladspa/ladspaplugin.cpp b/src/plugins/Effect/ladspa/ladspaplugin.cpp
new file mode 100644
index 000000000..6af867bd3
--- /dev/null
+++ b/src/plugins/Effect/ladspa/ladspaplugin.cpp
@@ -0,0 +1,532 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Ilya Kotov *
+ * <forkotov02@hotmail.ru> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QSettings>
+#include <QByteArray>
+#include <QDir>
+#include <QFileInfo>
+#include <QVBoxLayout>
+#include <math.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <qmmp/qmmp.h>
+#include "ladspaplugin.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#undef CLAMP
+#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+LADSPAHost *LADSPAHost::m_instance = 0;
+
+LADSPAHost::LADSPAHost(QObject* parent) : Effect(parent)
+{
+ m_instance = this;
+ findAllPlugins();
+}
+
+LADSPAHost::~LADSPAHost()
+{
+ m_instance = 0;
+ foreach(LADSPAEffect *instance, m_effects)
+ {
+ unload(instance);
+ }
+}
+
+ulong LADSPAHost::process(char *in_data, const ulong size, char **out_data)
+{
+ applyEffect((qint16 *) in_data, size);
+ memcpy(*out_data, in_data, size);
+ return size;
+}
+
+void LADSPAHost::configure(quint32 freq, int chan, int res)
+{
+ Effect::configure(freq, chan, res);
+}
+
+LADSPAHost* LADSPAHost::instance()
+{
+ return m_instance;
+}
+
+QList <LADSPAPlugin *> LADSPAHost::plugins()
+{
+ return m_plugins;
+}
+
+QList <LADSPAEffect *> LADSPAHost::runningPlugins()
+{
+ return m_effects;
+}
+
+/*!!!!*/
+void LADSPAHost::findAllPlugins()
+{
+ while(!m_plugins.isEmpty()) /* empty list */
+ delete m_plugins.takeFirst();
+
+ QString ladspa_path = qgetenv("LADSPA_PATH");
+ QStringList directories;
+
+ if (ladspa_path.isEmpty())
+ {
+ /* Fallback, look in obvious places */
+ directories << "/usr/lib/ladspa";
+ directories << "/usr/local/lib/ladspa";
+ }
+ else
+ directories = ladspa_path.split(':');
+ foreach(QString dir, directories)
+ findPlugins(dir);
+}
+
+LADSPAEffect *LADSPAHost::load(const QString &filename, long int num)
+{
+ LADSPA_Descriptor_Function descriptor_fn;
+ LADSPAEffect *instance = new LADSPAEffect;
+
+ instance->fileName = filename;
+ instance->library = dlopen(qPrintable(filename), RTLD_NOW);
+ instance->handle = 0;
+ instance->handle2 = 0;
+ if (!instance->library)
+ {
+ delete instance;
+ return 0;
+ }
+ descriptor_fn = (LADSPA_Descriptor_Function) dlsym(instance->library, "ladspa_descriptor");
+ if (!descriptor_fn)
+ {
+ dlclose(instance->library);
+ delete instance;
+ return 0;
+ }
+ instance->descriptor = descriptor_fn(num);
+
+ return instance;
+}
+
+void LADSPAHost::unload(LADSPAEffect *instance)
+{
+ const LADSPA_Descriptor *descriptor = instance->descriptor;
+
+ if (instance->handle)
+ {
+ if (descriptor->deactivate)
+ descriptor->deactivate(instance->handle);
+ descriptor->cleanup(instance->handle);
+ instance->handle = 0;
+ }
+ if (instance->handle2)
+ {
+ if (descriptor->deactivate)
+ descriptor->deactivate(instance->handle2);
+ descriptor->cleanup(instance->handle2);
+ instance->handle2 = 0;
+ }
+
+ if (instance->library)
+ {
+ dlclose(instance->library);
+ instance->library = 0;
+ }
+ m_effects.removeAll(instance);
+ delete instance;
+}
+
+void LADSPAHost::bootPlugin(LADSPAEffect *instance)
+{
+ const LADSPA_Descriptor *descriptor = instance->descriptor;
+
+ instance->handle = descriptor->instantiate(descriptor, (int)sampleRate());
+ if (channels() > 1 && !instance->stereo)
+ {
+ /* Create an additional instance */
+ instance->handle2 = descriptor->instantiate(descriptor, (int)sampleRate());
+ }
+
+ portAssign(instance);
+
+ if (descriptor->activate)
+ {
+ descriptor->activate(instance->handle);
+ if (instance->handle2)
+ descriptor->activate(instance->handle2);
+ }
+}
+
+int LADSPAHost::applyEffect(qint16 *d, int length)
+{
+ qint16 *raw16 = d;
+ LADSPAEffect *instance;
+ int k;
+ int nch = channels();
+
+ if (m_effects.isEmpty())
+ return length;
+
+ if (nch == 1)
+ {
+ for (k = 0; k < length / 2; ++k)
+ m_left[k] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f);
+ foreach(instance, m_effects)
+ {
+ if (instance->handle)
+ instance->descriptor->run(instance->handle, length / 2);
+ }
+ for (k = 0; k < length / 2; ++k)
+ raw16[k] = CLAMP((int)(m_left[k] * 32768.0f), -32768, 32767);
+ }
+ else
+ {
+ for (k = 0; k < length / 2; k += 2)
+ {
+ m_left[k/2] = ((LADSPA_Data) raw16[k]) * (1.0f / 32768.0f);
+ m_right[(k+1)/2] = ((LADSPA_Data) raw16[k+1]) * (1.0f / 32768.0f);
+ }
+ foreach(instance, m_effects)
+ {
+ if (instance->handle)
+ instance->descriptor->run(instance->handle, length/4);
+ if (instance->handle2)
+ instance->descriptor->run(instance->handle2, length/4);
+ }
+ for (k = 0; k < length / 2; k += 2)
+ {
+ raw16[k] = CLAMP((int)(m_left[k/2] * 32768.0f), -32768, 32767);
+ raw16[k+1] = CLAMP((int)(m_right[(k+1)/2] * 32768.0f), -32768, 32767);
+
+ }
+ }
+ return length;
+}
+
+void LADSPAHost::portAssign(LADSPAEffect *instance)
+{
+ unsigned long port;
+ unsigned long inputs = 0, outputs = 0;
+ const LADSPA_Descriptor *plugin = instance->descriptor;
+
+ for (port = 0; port < plugin->PortCount; ++port)
+ {
+ if (LADSPA_IS_PORT_CONTROL(plugin->PortDescriptors[port]))
+ {
+ if (port < MAX_KNOBS)
+ {
+ plugin->connect_port(instance->handle, port, &(instance->knobs[port]));
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, &(instance->knobs[port]));
+ }
+ else
+ {
+ plugin->connect_port(instance->handle, port, m_trash);
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, m_trash);
+ }
+
+ }
+ else if (LADSPA_IS_PORT_AUDIO(plugin->PortDescriptors[port]))
+ {
+
+ if (LADSPA_IS_PORT_INPUT(plugin->PortDescriptors[port]))
+ {
+ if (inputs == 0)
+ {
+ plugin->connect_port(instance->handle, port, m_left);
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, m_right);
+ }
+ else if (inputs == 1 && instance->stereo)
+ {
+ plugin->connect_port(instance->handle, port, m_right);
+ }
+ else
+ {
+ plugin->connect_port(instance->handle, port, m_trash);
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, m_trash);
+ }
+ inputs++;
+
+ }
+ else if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[port]))
+ {
+ if (outputs == 0)
+ {
+ plugin->connect_port(instance->handle, port, m_left);
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, m_right);
+ }
+ else if (outputs == 1 && instance->stereo)
+ {
+ plugin->connect_port(instance->handle, port, m_right);
+ }
+ else
+ {
+ plugin->connect_port(instance->handle, port, m_trash);
+ if (instance->handle2)
+ plugin->connect_port(instance->handle2, port, m_trash);
+ }
+ outputs++;
+ }
+ }
+ }
+}
+
+void LADSPAHost::findPlugins(const QString &path_entry)
+{
+ LADSPAPlugin *plugin;
+ void *library = 0;
+ //char *lib_name;
+ LADSPA_Descriptor_Function descriptor_fn;
+ const LADSPA_Descriptor *descriptor;
+ long int k;
+ unsigned long int port, input, output;
+
+ QDir dir (path_entry);
+ dir.setFilter(QDir::Files | QDir::Hidden);
+ dir.setSorting(QDir::Name);
+ QFileInfoList files = dir.entryInfoList((QStringList() << "*.so"));
+
+ foreach(QFileInfo file, files)
+ {
+ library = dlopen(qPrintable(file.absoluteFilePath ()), RTLD_LAZY);
+ if (library == 0)
+ {
+ continue;
+ }
+ descriptor_fn = (LADSPA_Descriptor_Function) dlsym(library, "ladspa_descriptor");
+ if (descriptor_fn == 0)
+ {
+ dlclose(library);
+ continue;
+ }
+
+ for (k = 0;; ++k)
+ {
+ descriptor = descriptor_fn(k);
+ if (descriptor == 0)
+ {
+ break;
+ }
+ plugin = new LADSPAPlugin;
+ plugin->name = strdup(descriptor->Name);
+ plugin->fileName = file.absoluteFilePath ();
+ plugin->id = k;
+ plugin->unique_id = descriptor->UniqueID;
+ for (input = output = port = 0; port < descriptor->PortCount; ++port)
+ {
+ if (LADSPA_IS_PORT_AUDIO(descriptor->PortDescriptors[port]))
+ {
+ if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[port]))
+ input++;
+ if (LADSPA_IS_PORT_OUTPUT(descriptor->PortDescriptors[port]))
+ output++;
+ }
+ else if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[port]))
+ {
+ }
+ }
+ plugin->stereo = (input >= 2 && output >= 2);
+ m_plugins.append(plugin);
+ }
+ dlclose(library);
+ }
+}
+
+LADSPAEffect *LADSPAHost::addPlugin(LADSPAPlugin *plugin)
+{
+ if (!plugin)
+ return 0;
+ LADSPAEffect *instance;
+ if (!(instance = load(plugin->fileName, plugin->id)))
+ return 0;
+ instance->stereo = plugin->stereo;
+ if (channels() && sampleRate())
+ bootPlugin(instance);
+ draw_plugin(instance);
+ m_effects.append(instance);
+ return instance;
+}
+
+void LADSPAHost::draw_plugin(LADSPAEffect * instance)
+{
+ const LADSPA_Descriptor *plugin = instance->descriptor;
+ const LADSPA_PortRangeHint *hints = plugin->PortRangeHints;
+ LADSPA_Data fact, min, max, step, start;
+ int dp;
+ unsigned long k;
+ bool no_ui = TRUE;
+ //GtkWidget *widget, *vbox, *hbox;
+ //GtkObject *adjustment;
+
+ /*if (instance->window != NULL)
+ {
+ /* Just show window */
+ /*gtk_widget_show(instance->window);
+ return;
+ }*/
+
+ //instance->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ //gtk_window_set_title(GTK_WINDOW(instance->window), plugin->Name);
+
+ //vbox = gtk_vbox_new(FALSE, 3);
+
+ for (k = 0; k < MAX_KNOBS && k < plugin->PortCount; ++k)
+ {
+ if (!LADSPA_IS_PORT_CONTROL(plugin->PortDescriptors[k]))
+ continue;
+ no_ui = FALSE;
+ //hbox = gtk_hbox_new(FALSE, 3);
+ //widget = gtk_label_new(plugin->PortNames[k]);
+ //gtk_container_add(GTK_CONTAINER(hbox), widget);
+
+ if (LADSPA_IS_HINT_TOGGLED(hints[k].HintDescriptor))
+ {
+ /*widget = gtk_toggle_button_new_with_label("Press");
+ g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(toggled), &(instance->knobs[k]));
+ gtk_container_add(GTK_CONTAINER(hbox), widget);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);*/
+ continue;
+ }
+
+ if (LADSPA_IS_HINT_SAMPLE_RATE(hints[k].HintDescriptor))
+ fact = sampleRate();
+ else
+ fact = 1.0f;
+
+ if (LADSPA_IS_HINT_BOUNDED_BELOW(hints[k].HintDescriptor))
+ min = hints[k].LowerBound * fact;
+ else
+ min = -10000.0f;
+
+ if (LADSPA_IS_HINT_BOUNDED_ABOVE(hints[k].HintDescriptor))
+ max = hints[k].UpperBound * fact;
+ else
+ max = 10000.0f;
+
+ /* infinity */
+ if (10000.0f <= max - min)
+ {
+ dp = 1;
+ step = 5.0f;
+
+ /* 100.0 ... lots */
+ }
+ else if (100.0f < max - min)
+ {
+ dp = 0;
+ step = 5.0f;
+
+ /* 10.0 ... 100.0 */
+ }
+ else if (10.0f < max - min)
+ {
+ dp = 1;
+ step = 0.5f;
+
+ /* 1.0 ... 10.0 */
+ }
+ else if (1.0f < max - min)
+ {
+ dp = 2;
+ step = 0.05f;
+
+ /* 0.0 ... 1.0 */
+ }
+ else
+ {
+ dp = 3;
+ step = 0.005f;
+ }
+
+ if (LADSPA_IS_HINT_INTEGER(hints[k].HintDescriptor))
+ {
+ dp = 0;
+ if (step < 1.0f)
+ step = 1.0f;
+ }
+
+ if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hints[k].HintDescriptor))
+ start = min;
+ else if (LADSPA_IS_HINT_DEFAULT_LOW(hints[k].HintDescriptor))
+ start = min * 0.75f + max * 0.25f;
+ else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hints[k].HintDescriptor))
+ start = min * 0.5f + max * 0.5f;
+ else if (LADSPA_IS_HINT_DEFAULT_HIGH(hints[k].HintDescriptor))
+ start = min * 0.25f + max * 0.75f;
+ else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hints[k].HintDescriptor))
+ start = max;
+ else if (LADSPA_IS_HINT_DEFAULT_0(hints[k].HintDescriptor))
+ start = 0.0f;
+ else if (LADSPA_IS_HINT_DEFAULT_1(hints[k].HintDescriptor))
+ start = 1.0f;
+ else if (LADSPA_IS_HINT_DEFAULT_100(hints[k].HintDescriptor))
+ start = 100.0f;
+ else if (LADSPA_IS_HINT_DEFAULT_440(hints[k].HintDescriptor))
+ start = 440.0f;
+ else if (LADSPA_IS_HINT_INTEGER(hints[k].HintDescriptor))
+ start = min;
+ else if (max >= 0.0f && min <= 0.0f)
+ start = 0.0f;
+ else
+ start = min * 0.5f + max * 0.5f;
+
+ instance->knobs[k] = start;
+ //adjustment = gtk_adjustment_new(start, min, max, step, step * 10.0, 0.0);
+ //instance->adjustments[k] = GTK_ADJUSTMENT(adjustment);
+ //widget = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), step, dp);
+ if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[k]))
+ {
+ //gtk_widget_set_sensitive(widget, FALSE);
+ }
+ else
+ {
+ //g_signal_connect(adjustment, "value-changed", G_CALLBACK(value_changed), &(instance->knobs[k]));
+ }
+ /*gtk_container_add(GTK_CONTAINER(hbox), widget);
+ widget = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
+ gtk_scale_set_digits(GTK_SCALE(widget), dp);
+ if (LADSPA_IS_PORT_OUTPUT(plugin->PortDescriptors[k]))
+ {
+ gtk_widget_set_sensitive(widget, FALSE);
+ }
+ gtk_container_add(GTK_CONTAINER(hbox), widget);
+
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);*/
+ }
+
+ /*if (no_ui)
+ {
+ widget = gtk_label_new(_("This LADSPA plugin has no user controls"));
+ gtk_container_add(GTK_CONTAINER(vbox), widget);
+ }
+
+ instance->timeout = gtk_timeout_add(100, update_instance, instance);
+
+ gtk_container_add(GTK_CONTAINER(instance->window), vbox);
+
+ g_signal_connect(G_OBJECT(instance->window), "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ gtk_widget_show_all(instance->window);*/
+}
diff --git a/src/plugins/Effect/ladspa/ladspaplugin.h b/src/plugins/Effect/ladspa/ladspaplugin.h
new file mode 100644
index 000000000..4d6c726c9
--- /dev/null
+++ b/src/plugins/Effect/ladspa/ladspaplugin.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef LADSPAPLUGIN_H
+#define LADSPAPLUGIN_H
+
+#include <QMutex>
+#include <QList>
+#include <QSlider>
+#include <qmmp/effect.h>
+#include <ladspa.h>
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+
+#define MAX_SAMPLES 8192
+#define MAX_KNOBS 64
+
+
+class LADSPAPlugin
+{
+public:
+ QString name;
+ QString fileName;
+ long id;
+ long unique_id;
+ bool stereo;
+};
+
+class LADSPAEffect
+{
+public:
+ void *library;
+ QString fileName;
+ bool stereo;
+ const LADSPA_Descriptor *descriptor;
+ LADSPA_Handle handle; /* left or mono */
+ LADSPA_Handle handle2; /* right stereo */
+ LADSPA_Data knobs[MAX_KNOBS];
+};
+
+
+class LADSPAHost : public Effect
+{
+ Q_OBJECT
+public:
+ LADSPAHost(QObject *parent = 0);
+
+ virtual ~LADSPAHost();
+
+ ulong process(char *in_data, const ulong size, char **out_data);
+ void configure(quint32 freq, int chan, int res);
+ QList <LADSPAPlugin *> plugins();
+ QList <LADSPAEffect *> runningPlugins();
+ LADSPAEffect *addPlugin(LADSPAPlugin * plugin);
+ void unload(LADSPAEffect *instance);
+
+ static LADSPAHost* instance();
+
+private:
+ int applyEffect(qint16 *d, int length);
+
+ void bootPlugin(LADSPAEffect *instance);
+ void findAllPlugins();
+ void findPlugins(const QString &path);
+ LADSPAEffect *load(const QString &path, long num);
+ void portAssign(LADSPAEffect *instance);
+ void draw_plugin(LADSPAEffect *instance);
+
+ QList <LADSPAPlugin *> m_plugins;
+ QList <LADSPAEffect *> m_effects;
+
+ LADSPA_Data m_left[MAX_SAMPLES], m_right[MAX_SAMPLES], m_trash[MAX_SAMPLES];
+
+ static LADSPAHost *m_instance;
+};
+
+#endif
diff --git a/src/plugins/Effect/ladspa/settingsdialog.cpp b/src/plugins/Effect/ladspa/settingsdialog.cpp
new file mode 100644
index 000000000..34f1714ed
--- /dev/null
+++ b/src/plugins/Effect/ladspa/settingsdialog.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+
+#include <QSettings>
+#include <QApplication>
+#include <QStyle>
+#include <QStandardItemModel>
+#include <qmmp/qmmp.h>
+#include "ladspaplugin.h"
+#include "settingsdialog.h"
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ ui.setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose, TRUE);
+ ui.loadButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowRight));
+ ui.unloadButton->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowLeft));
+
+ m_model = new QStandardItemModel(0, 2, this);
+ m_model->setHeaderData(0, Qt::Horizontal, tr("UID"));
+ m_model->setHeaderData(1, Qt::Horizontal, tr("Name"));
+ ui.pluginsTreeView->setModel(m_model);
+
+
+ m_created = FALSE;
+ if(!LADSPAHost::instance())
+ {
+ new LADSPAHost();
+ m_created = TRUE;
+ }
+
+ QList <LADSPAPlugin *> plugin_list = LADSPAHost::instance()->plugins();
+
+ for(int i = 0; i < plugin_list.size(); ++i)
+ {
+ m_model->insertRow(i);
+ m_model->setData(m_model->index(i, 0), (uint) plugin_list[i]->unique_id);
+ m_model->setData(m_model->index(i, 1), plugin_list[i]->name);
+ }
+ updateRunningPlugins();
+}
+
+SettingsDialog::~SettingsDialog()
+{
+ if(m_created)
+ delete LADSPAHost::instance();
+}
+
+void SettingsDialog::on_loadButton_clicked()
+{
+ LADSPAHost *l = LADSPAHost::instance();
+ QModelIndex index = ui.pluginsTreeView->currentIndex ();
+ if(index.isValid())
+ {
+ l->addPlugin(l->plugins().at(index.row()));
+ updateRunningPlugins();
+ }
+}
+
+void SettingsDialog::on_unloadButton_clicked()
+{
+
+}
+
+void SettingsDialog::accept()
+{
+ QDialog::accept();
+}
+
+void SettingsDialog::updateRunningPlugins()
+{
+ ui.runningListWidget->clear();
+ QList <LADSPAEffect *> plugin_list = LADSPAHost::instance()->runningPlugins();
+
+ for(int i = 0; i < plugin_list.size(); ++i)
+ ui.runningListWidget->addItem(plugin_list[i]->descriptor->Name);
+}
diff --git a/src/plugins/Effect/ladspa/settingsdialog.h b/src/plugins/Effect/ladspa/settingsdialog.h
new file mode 100644
index 000000000..055019978
--- /dev/null
+++ b/src/plugins/Effect/ladspa/settingsdialog.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2008 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef SETTINGSDIALOG_H
+#define SETTINGSDIALOG_H
+
+#include <QDialog>
+#include "ui_settingsdialog.h"
+
+class QStandardItemModel;
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class SettingsDialog : public QDialog
+{
+Q_OBJECT
+public:
+ SettingsDialog(QWidget *parent = 0);
+
+ ~SettingsDialog();
+
+public slots:
+ virtual void accept();
+
+private slots:
+ void on_loadButton_clicked();
+ void on_unloadButton_clicked();
+
+private:
+ void updateRunningPlugins();
+ Ui::SettingsDialog ui;
+ QStandardItemModel *m_model;
+ bool m_created;
+};
+
+#endif
diff --git a/src/plugins/Effect/ladspa/settingsdialog.ui b/src/plugins/Effect/ladspa/settingsdialog.ui
new file mode 100644
index 000000000..38a2d6b28
--- /dev/null
+++ b/src/plugins/Effect/ladspa/settingsdialog.ui
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>427</width>
+ <height>406</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>BS2B Plugin Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item row="0" column="1">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>124</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="1">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>123</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="0" colspan="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>343</width>
+ <height>23</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="4" column="3">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" rowspan="4">
+ <widget class="QTreeView" name="pluginsTreeView">
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QToolButton" name="loadButton">
+ <property name="text">
+ <string>&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QToolButton" name="unloadButton">
+ <property name="text">
+ <string>&lt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" rowspan="4" colspan="2">
+ <widget class="QListWidget" name="runningListWidget"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>270</x>
+ <y>76</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>91</x>
+ <y>88</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>SettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>326</x>
+ <y>78</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>139</x>
+ <y>60</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>