Embedded LV2 GTK GUI support.

git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3678 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2008-08-09 00:49:07 +00:00
parent a35abc0528
commit daf91bc21d
10 changed files with 262 additions and 9 deletions

View file

@ -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',

View file

@ -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']])

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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

View file

@ -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)")
@ -247,6 +255,30 @@ PluginUIWindow::app_activated (bool yn)
#endif
}
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)
{

View file

@ -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

View file

@ -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;
};

View file

@ -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 ();
@ -856,8 +859,13 @@ PluginInsert::type ()
#ifdef HAVE_AUDIOUNITS
} 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;
}

View file

@ -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()