summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-09 00:49:07 +0000
committerDavid Robillard <d@drobilla.net>2008-08-09 00:49:07 +0000
commitdaf91bc21def66a2d4a875bb1c32c8cb6fcf176b (patch)
treee9c98e981d0b03d540ff1b805ebcd9f9961816bd
parenta35abc05287a6fd8e1e91f24aa4f829201d0e4e1 (diff)
Embedded LV2 GTK GUI support.
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3678 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--SConstruct6
-rw-r--r--gtk2_ardour/SConscript5
-rw-r--r--gtk2_ardour/lv2_plugin_ui.cc113
-rw-r--r--gtk2_ardour/lv2_plugin_ui.h76
-rw-r--r--gtk2_ardour/plugin_selector.cc4
-rw-r--r--gtk2_ardour/plugin_ui.cc32
-rw-r--r--gtk2_ardour/plugin_ui.h1
-rw-r--r--libs/ardour/ardour/lv2_plugin.h7
-rw-r--r--libs/ardour/insert.cc8
-rw-r--r--libs/ardour/lv2_plugin.cc19
10 files changed, 262 insertions, 9 deletions
diff --git a/SConstruct b/SConstruct
index 169742e7a8..634e3373ac 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1072,9 +1072,9 @@ if env['SYSLIBS']:
# libraries['flowcanvas'] = LibraryInfo(LIBS='flowcanvas', LIBPATH='#/libs/flowcanvas', CPPPATH='#libs/flowcanvas')
libraries['soundtouch'] = LibraryInfo()
- #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
- # Comment the previous line and uncomment this for Debian:
- libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
+ libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs soundtouch-1.0')
+ # Comment the previous line and uncomment this for old versions of Debian:
+ #libraries['soundtouch'].ParseConfig ('pkg-config --cflags --libs libSoundTouch')
libraries['appleutility'] = LibraryInfo(LIBS='libappleutility',
LIBPATH='#libs/appleutility',
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index 8b7bdfe637..1b34f8aead 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -283,8 +283,11 @@ if env['VST']:
extra_sources += vst_files
gtkardour.Append (CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst")
+lv2_files = [ 'lv2_plugin_ui.cc' ]
+
if env['LV2']:
- gtkardour.Append (CCFLAGS="-DHAVE_SLV2")
+ extra_sources += lv2_files
+ gtkardour.Append (CCFLAGS="-DHAVE_LV2")
gtkardour.Merge ([libraries['slv2']])
diff --git a/gtk2_ardour/lv2_plugin_ui.cc b/gtk2_ardour/lv2_plugin_ui.cc
new file mode 100644
index 0000000000..7df1dbfe85
--- /dev/null
+++ b/gtk2_ardour/lv2_plugin_ui.cc
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Dave Robillard
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <ardour/insert.h>
+#include <ardour/lv2_plugin.h>
+
+#include "lv2_plugin_ui.h"
+
+using namespace Gtk;
+using namespace ARDOUR;
+using namespace PBD;
+
+void
+LV2PluginUI::lv2_ui_write(LV2UI_Controller controller,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer)
+{
+ LV2PluginUI* me = (LV2PluginUI*)controller;
+ if (*(float*)buffer != me->_values[port_index])
+ me->_lv2->set_parameter(port_index, *(float*)buffer);
+}
+
+void
+LV2PluginUI::parameter_changed (uint32_t port_index, float val)
+{
+ if (val != _values[port_index]) {
+ const LV2UI_Descriptor* ui_desc = slv2_ui_instance_get_descriptor(_inst);
+ LV2UI_Handle ui_handle = slv2_ui_instance_get_handle(_inst);
+ if (ui_desc->port_event)
+ ui_desc->port_event(ui_handle, port_index, 4, 0, &val);
+ _values[port_index] = val;
+ }
+}
+
+LV2PluginUI::LV2PluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<LV2Plugin> lv2p)
+ : PlugUIBase (pi)
+ , _lv2(lv2p)
+{
+ _inst = slv2_ui_instantiate(
+ _lv2->slv2_plugin(), _lv2->slv2_ui(), LV2PluginUI::lv2_ui_write, this,
+ /* FEATURES */ NULL);
+
+ GtkWidget* c_widget = (GtkWidget*)slv2_ui_instance_get_widget(_inst);
+ _gui_widget = Glib::wrap(c_widget);
+ _gui_widget->show_all();
+ pack_start(*_gui_widget, true, true);
+
+ uint32_t num_ports = slv2_plugin_get_num_ports(lv2p->slv2_plugin());
+ _values = new float[num_ports];
+ for (uint32_t i = 0; i < num_ports; ++i) {
+ bool ok;
+ _values[i] = lv2p->nth_parameter(i, ok);
+ if (ok)
+ lv2_ui_write(this, i, 4, /* FIXME: format */0, &_values[i]);
+ }
+
+ _lv2->ParameterChanged.connect(mem_fun(*this, &LV2PluginUI::parameter_changed));
+}
+
+LV2PluginUI::~LV2PluginUI ()
+{
+ delete[] _values;
+ // plugin destructor destroys the GUI
+}
+
+int
+LV2PluginUI::get_preferred_height ()
+{
+ Gtk::Requisition r = size_request();
+ return r.height;
+}
+
+int
+LV2PluginUI::get_preferred_width ()
+{
+ Gtk::Requisition r = size_request();
+ return r.width;
+}
+
+int
+LV2PluginUI::package (Gtk::Window& win)
+{
+ /* forward configure events to plugin window */
+ win.signal_configure_event().connect (mem_fun (*this, &LV2PluginUI::configure_handler));
+ return 0;
+}
+
+bool
+LV2PluginUI::configure_handler (GdkEventConfigure* ev)
+{
+ cout << "CONFIGURE" << endl;
+ return false;
+}
+
diff --git a/gtk2_ardour/lv2_plugin_ui.h b/gtk2_ardour/lv2_plugin_ui.h
new file mode 100644
index 0000000000..5946d8bd77
--- /dev/null
+++ b/gtk2_ardour/lv2_plugin_ui.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2008 Paul Davis
+ Author: Dave Robillard
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_lv2_plugin_ui_h__
+#define __ardour_lv2_plugin_ui_h__
+
+#include <vector>
+#include <map>
+#include <list>
+
+#include <sigc++/signal.h>
+#include <gtkmm/widget.h>
+
+#include <ardour_dialog.h>
+#include <ardour/types.h>
+#include "plugin_ui.h"
+
+#ifdef HAVE_LV2
+
+namespace ARDOUR {
+ class PluginInsert;
+ class LV2Plugin;
+}
+
+class LV2PluginUI : public PlugUIBase, public Gtk::VBox
+{
+ public:
+ LV2PluginUI (boost::shared_ptr<ARDOUR::PluginInsert>, boost::shared_ptr<ARDOUR::LV2Plugin>);
+ ~LV2PluginUI ();
+
+ gint get_preferred_height ();
+ gint get_preferred_width ();
+ bool start_updating(GdkEventAny*) {return false;}
+ bool stop_updating(GdkEventAny*) {return false;}
+
+ int package (Gtk::Window&);
+
+ private:
+ boost::shared_ptr<ARDOUR::LV2Plugin> _lv2;
+
+ Gtk::Widget* _gui_widget;
+ SLV2UIInstance _inst;
+ float* _values;
+
+ static void lv2_ui_write(
+ LV2UI_Controller controller,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer);
+
+ void parameter_changed(uint32_t, float);
+ bool configure_handler (GdkEventConfigure*);
+ void save_plugin_setting ();
+};
+#endif // HAVE_LV2
+
+#endif /* __ardour_lv2_plugin_ui_h__ */
+
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 0435e1e95f..67a78645e0 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -306,7 +306,7 @@ PluginSelector::ladspa_refiller (const std::string& filterstr)
void
PluginSelector::lv2_refiller (const std::string& filterstr)
{
-#ifdef HAVE_SLV2
+#ifdef HAVE_LV2
refiller (manager->lv2_plugin_info(), filterstr, "LV2");
#endif
}
@@ -512,7 +512,7 @@ PluginSelector::plugin_menu()
#ifdef HAVE_AUDIOUNITS
all_plugs.insert (all_plugs.end(), manager->au_plugin_info().begin(), manager->au_plugin_info().end());
#endif
-#ifdef HAVE_SLV2
+#ifdef HAVE_LV2
all_plugs.insert (all_plugs.end(), manager->lv2_plugin_info().begin(), manager->lv2_plugin_info().end());
#endif
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index 7d000d3a45..4918523af3 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -42,6 +42,10 @@
#ifdef VST_SUPPORT
#include <ardour/vst_plugin.h>
#endif
+#ifdef HAVE_LV2
+#include <ardour/lv2_plugin.h>
+#include "lv2_plugin_ui.h"
+#endif
#include <lrdf.h>
@@ -83,6 +87,10 @@ PluginUIWindow::PluginUIWindow (Gtk::Window* win, boost::shared_ptr<PluginInsert
error << _("Eh? LADSPA plugins don't have editors!") << endmsg;
break;
+ case ARDOUR::LV2:
+ have_gui = create_lv2_editor (insert);
+ break;
+
default:
#ifndef VST_SUPPORT
error << _("unknown type of editor-supplying plugin (note: no VST support in this version of ardour)")
@@ -248,6 +256,30 @@ PluginUIWindow::app_activated (bool yn)
}
bool
+PluginUIWindow::create_lv2_editor(boost::shared_ptr<PluginInsert> insert)
+{
+#ifndef HAVE_LV2
+ return false;
+#else
+
+ boost::shared_ptr<LV2Plugin> vp;
+
+ if ((vp = boost::dynamic_pointer_cast<LV2Plugin> (insert->plugin())) == 0) {
+ error << _("create_lv2_editor called on non-LV2 plugin") << endmsg;
+ throw failed_constructor ();
+ } else {
+ LV2PluginUI* lpu = new LV2PluginUI (insert, vp);
+ _pluginui = lpu;
+ add (*lpu);
+ lpu->package (*this);
+ }
+
+ non_gtk_gui = false;
+ return true;
+#endif
+}
+
+bool
PluginUIWindow::on_key_press_event (GdkEventKey* event)
{
if (non_gtk_gui) {
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
index b23b747639..4f0d92c21c 100644
--- a/gtk2_ardour/plugin_ui.h
+++ b/gtk2_ardour/plugin_ui.h
@@ -231,6 +231,7 @@ class PluginUIWindow : public Gtk::Window
bool create_vst_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
bool create_audiounit_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
+ bool create_lv2_editor (boost::shared_ptr<ARDOUR::PluginInsert>);
};
#ifdef VST_SUPPORT
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 852d277bfc..8d58c7024d 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -61,6 +61,7 @@ class LV2Plugin : public ARDOUR::Plugin
uint32_t nth_parameter (uint32_t port, bool& ok) const;
SLV2Plugin slv2_plugin() { return _plugin; }
+ SLV2UI slv2_ui() { return _ui; }
SLV2Port slv2_port(uint32_t i) { return slv2_plugin_get_port_by_index(_plugin, i); }
std::set<uint32_t> automatable() const;
@@ -103,14 +104,13 @@ class LV2Plugin : public ARDOUR::Plugin
int set_state(const XMLNode& node);
bool save_preset(std::string name);
- bool has_editor() const { return false; }
+ bool has_editor() const;
- int require_output_streams (uint32_t);
-
private:
void* _module;
LV2World& _world;
SLV2Plugin _plugin;
+ SLV2UI _ui;
SLV2Value _name;
SLV2Value _author;
SLV2Instance _instance;
@@ -146,6 +146,7 @@ struct LV2World {
SLV2Value integer;
SLV2Value toggled;
SLV2Value srate;
+ SLV2Value gtk_gui;
};
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc
index 75f428aeb4..9af73e9a7d 100644
--- a/libs/ardour/insert.cc
+++ b/libs/ardour/insert.cc
@@ -844,6 +844,9 @@ PluginInsert::type ()
#ifdef HAVE_AUDIOUNITS
boost::shared_ptr<AUPlugin> ap;
#endif
+#ifdef HAVE_LV2
+ boost::shared_ptr<LV2Plugin> lv2p;
+#endif
PluginPtr other = plugin ();
@@ -857,7 +860,12 @@ PluginInsert::type ()
} else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
return ARDOUR::AudioUnit;
#endif
+#ifdef HAVE_LV2
+ } else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
+ return ARDOUR::LV2;
+#endif
} else {
+ error << "Unknown plugin type" << endmsg;
/* NOT REACHED */
return (ARDOUR::PluginType) 0;
}
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 015c47e317..028d0c5b45 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -68,6 +68,7 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, nframes_t rate)
{
_world = world;
_plugin = plugin;
+ _ui = NULL;
_control_data = 0;
_shadow_data = 0;
_latency_control_port = 0;
@@ -124,6 +125,17 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, nframes_t rate)
_defaults[i] = 0.0f;
}
}
+
+ SLV2UIs uis = slv2_plugin_get_uis(_plugin);
+ if (slv2_uis_size(uis) > 0) {
+ for (unsigned i=0; i < slv2_uis_size(uis); ++i) {
+ SLV2UI ui = slv2_uis_get_at(uis, i);
+ if (slv2_ui_is_a(ui, _world.gtk_gui)) {
+ _ui = ui;
+ break;
+ }
+ }
+ }
Plugin::setup_controls ();
@@ -243,6 +255,12 @@ LV2Plugin::save_preset (string name)
{
return Plugin::save_preset (name, "lv2");
}
+
+bool
+LV2Plugin::has_editor() const
+{
+ return (_ui != NULL);
+}
int
LV2Plugin::set_state(const XMLNode& node)
@@ -505,6 +523,7 @@ LV2World::LV2World()
integer = slv2_value_new_uri(world, SLV2_NAMESPACE_LV2 "integer");
toggled = slv2_value_new_uri(world, SLV2_NAMESPACE_LV2 "toggled");
srate = slv2_value_new_uri(world, SLV2_NAMESPACE_LV2 "sampleRate");
+ gtk_gui = slv2_value_new_uri(world, "http://lv2plug.in/ns/extensions/ui#GtkUI");
}
LV2World::~LV2World()