diff -U 3 -H -b -d -r -N -- calf-old/configure.ac calf-master/configure.ac
--- calf-old/configure.ac	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/configure.ac	2013-09-02 17:49:30.605461117 +0100
@@ -19,6 +19,10 @@
 
 ############################################################################################
 # Set initial values of shell variables
+LADSPA_ENABLED="no"
+EXEC_GUI_ENABLED="no"
+DSSI_GUI_ENABLED="no"
+LV2_GTK_GUI_ENABLED="no"
 LV2_GUI_ENABLED="no"
 JACK_FOUND="no"
 JACK_ENABLED="no"
@@ -48,6 +52,10 @@
 AC_HEADER_STDC
 AC_CHECK_HEADERS([memory.h stdint.h stdlib.h string.h time.h math.h])
 
+AC_CHECK_HEADER(ladspa.h, LADSPA_FOUND="yes", LADSPA_FOUND="no")
+
+AC_CHECK_HEADER(dssi.h, DSSI_FOUND="yes", DSSI_FOUND="no")
+
 AC_CHECK_HEADER(expat.h, true, AC_MSG_ERROR([Expat XML library not found]))
 AC_CHECK_LIB(expat, XML_Parse, true, AC_MSG_ERROR([Expat XML library not found]))
 AC_CHECK_HEADER(fftw3.h, true, AC_MSG_ERROR([FFTW3 header (fftw3.h) not found]))
@@ -72,7 +80,7 @@
   PKG_CHECK_MODULES(JACK_MIDI_DEPS, jack >= 0.105.0, OLD_JACK="no", OLD_JACK="yes")
 fi
 
-PKG_CHECK_MODULES(LV2_DEPS, lv2core >= 6, LV2_FOUND="yes", LV2_FOUND="no")
+PKG_CHECK_MODULES(LV2_DEPS, lv2 >= 1, LV2_FOUND="yes", LV2_FOUND="no")
 
 PKG_CHECK_MODULES(LASH_DEPS, lash-1.0 >= 0.6.0,
   AC_CHECK_LIB([lash], [lash_client_is_being_restored], LASH_0_6_FOUND="yes", LASH_0_6_FOUND="no"),
@@ -87,10 +95,12 @@
 ############################################################################################
 # Assign initial values to feature control variables
 
+LADSPA_ENABLED=$LADSPA_FOUND
+DSSI_ENABLED=$DSSI_FOUND
 LV2_ENABLED=$LV2_FOUND
 LASH_ENABLED=$LASH_FOUND
 
-if test "$JACK_FOUND" = "yes" -o "$LV2_FOUND" = "yes"; then
+if test "$JACK_FOUND" = "yes" -o "$DSSI_FOUND" = "yes" -o "$LV2_FOUND" = "yes"; then
   PKG_CHECK_MODULES(GUI_DEPS, gtk+-2.0 >= 2.12.0 cairo >= 1.2.0,
     GUI_ENABLED="yes",
     GUI_ENABLED="no (GTK+ 2.12 and cairo 1.2 or newer required)"
@@ -99,6 +109,22 @@
 
 ############################################################################################
 # Look for settings and installed libraries to determine what to compile/install/use
+if test "$LADSPA_FOUND" = "yes"; then
+  AC_MSG_CHECKING([whether to allow LADSPA])
+  AC_ARG_WITH(ladspa,
+    AC_HELP_STRING([--without-ladspa],[disable LADSPA and DSSI interfaces]),
+      [if test "$withval" = "no"; then LADSPA_ENABLED="no"; DSSI_ENABLED="no"; fi],[])
+  AC_MSG_RESULT($LADSPA_ENABLED)
+fi
+
+if test "$DSSI_FOUND" = "yes"; then
+  AC_MSG_CHECKING([whether to allow DSSI])
+  AC_ARG_WITH(dssi,
+    AC_HELP_STRING([--without-dssi],[disable DSSI interface]),
+      [if test "$withval" = "no"; then DSSI_ENABLED="no"; fi],[])
+  AC_MSG_RESULT($DSSI_ENABLED)
+fi
+
 if test "$LV2_FOUND" = "yes"; then
   AC_MSG_CHECKING([whether to allow LV2])
   AC_ARG_WITH(lv2,
@@ -122,6 +148,13 @@
   [set_enable_experimental="no"])
 AC_MSG_RESULT($set_enable_experimental)
 
+AC_MSG_CHECKING([whether to enable old-style in-process GTK+ GUI])
+AC_ARG_ENABLE(in-process-lv2-gui,
+  AC_HELP_STRING([--enable-in-process-lv2-gui],[enable old-style in-process GTK+ GUI - not recommended!]),
+  [set_enable_gtk_gui="$enableval"],
+  [set_enable_gtk_gui="no"])
+AC_MSG_RESULT($set_enable_gtk_gui)
+
 AC_MSG_CHECKING([whether to enable debugging mode])
 AC_ARG_ENABLE(debug,
   AC_HELP_STRING([--enable-debug],[enable debug mode - slow!]),
@@ -143,8 +176,18 @@
   JACK_ENABLED="yes"
 fi
 
+if test "$GUI_ENABLED" = "yes" -a "$DSSI_ENABLED" = "yes"; then
+  DSSI_GUI_ENABLED="yes"
+  EXEC_GUI_ENABLED="yes"
+fi
+
 if test "$GUI_ENABLED" = "yes" -a "$LV2_ENABLED" = "yes"; then
   LV2_GUI_ENABLED="yes"
+  EXEC_GUI_ENABLED="yes"
+fi
+
+if test "$set_enable_gtk_gui" = "yes" -a "$LV2_ENABLED" = "yes" -a "$GUI_ENABLED" = "yes"; then
+  LV2_GTK_GUI_ENABLED="yes"
 fi
 
 if test "$set_enable_debug" = "yes"; then
@@ -159,16 +202,27 @@
 
 ############################################################################################
 # Create automake conditional symbols
+AM_CONDITIONAL(USE_DSSI, test "$DSSI_ENABLED" = "yes")
+AM_CONDITIONAL(USE_LADSPA, test "$LADSPA_ENABLED" = "yes")
 AM_CONDITIONAL(USE_JACK, test "$JACK_ENABLED" = "yes")
 AM_CONDITIONAL(USE_LV2, test "$LV2_ENABLED" = "yes")
 AM_CONDITIONAL(USE_GUI, test "$GUI_ENABLED" = "yes")
+AM_CONDITIONAL(USE_DSSI_GUI, test "$DSSI_GUI_ENABLED" = "yes")
+AM_CONDITIONAL(USE_EXEC_GUI, test "$EXEC_GUI_ENABLED" = "yes")
 AM_CONDITIONAL(USE_LV2_GUI, test "$LV2_GUI_ENABLED" = "yes")
+AM_CONDITIONAL(USE_LV2_GTK_GUI, test "$set_enable_gtk_gui" = "yes")
 AM_CONDITIONAL(USE_LASH, test "$LASH_ENABLED" = "yes")
 AM_CONDITIONAL(USE_LASH_0_6, test "$LASH_0_6_ENABLED" = "yes")
 AM_CONDITIONAL(USE_DEBUG, test "$set_enable_debug" = "yes")
 
 ############################################################################################
 # Create autoconf symbols for config.h
+if test "$LADSPA_ENABLED" = "yes"; then
+  AC_DEFINE(USE_LADSPA, 1, [LADSPA wrapper will be built])
+fi
+if test "$DSSI_ENABLED" = "yes"; then
+  AC_DEFINE(USE_DSSI, 1, [DSSI wrapper will be built])
+fi
 if test "$LV2_ENABLED" = "yes"; then
   AC_DEFINE(USE_LV2, 1, [LV2 wrapper will be built])
 fi
@@ -184,15 +238,48 @@
     AC_DEFINE(USE_LASH_0_6, 1, "Unstable LASH API is enabled")
   fi
 fi
+if test "$EXEC_GUI_ENABLED" = "yes"; then
+  AC_DEFINE(USE_EXEC_GUI, 1, [Out-of-process GTK+ GUI for LV2/DSSI will be built])
+fi
+if test "$DSSI_GUI_ENABLED" = "yes"; then
+  AC_DEFINE(USE_DSSI_GUI, 1, [GTK+ GUI executable will be used for DSSI])
+fi
 if test "$LV2_GUI_ENABLED" = "yes"; then
   AC_DEFINE(USE_LV2_GUI, 1, [GTK+ GUI executable will be used for LV2])
 fi
 if test "$set_enable_experimental" = "yes"; then
   AC_DEFINE([ENABLE_EXPERIMENTAL], [1], "Experimental features are enabled")
 fi
+if test "$set_enable_gtk_gui" = "yes"; then
+  AC_DEFINE([USE_LV2_GTK_GUI], [1], "In-process GTK+ LV2 GUI features is enabled")
+fi
 
 ############################################################################################
 # Output directories
+AC_MSG_CHECKING(where to install LADSPA plugins)
+AC_ARG_WITH(ladspa_dir,
+  AC_HELP_STRING([--with-ladspa-dir],[install LADSPA plugins to DIR (default=$prefix/lib/ladspa/)]),
+  ,
+  [with_ladspa_dir="$prefix/lib/ladspa/"])
+AC_MSG_RESULT($with_ladspa_dir)
+AC_SUBST(with_ladspa_dir)
+
+AC_MSG_CHECKING(where to install LADSPA RDF file)
+AC_ARG_WITH(ladspa_rdf_dir,
+  AC_HELP_STRING([--with-ladspa-rdf-dir],[install RDF file to DIR (default=$prefix/share/ladspa/rdf/)]),
+  ,
+  [with_ladspa_rdf_dir="$prefix/share/ladspa/rdf/"])
+AC_MSG_RESULT($with_ladspa_rdf_dir)
+AC_SUBST(with_ladspa_rdf_dir)
+
+AC_MSG_CHECKING(where to install DSSI plugins)
+AC_ARG_WITH(dssi_dir,
+  AC_HELP_STRING([--with-dssi-dir],[install DSSI plugins to DIR (default=$prefix/lib/dssi/)]),
+  ,
+  [with_dssi_dir="$prefix/lib/dssi/"])
+AC_MSG_RESULT($with_dssi_dir)
+AC_SUBST(with_dssi_dir)
+
 if test "$LV2_ENABLED" == "yes"; then
   AC_MSG_CHECKING(where to install LV2 plugins)
   AC_ARG_WITH(lv2_dir,
@@ -225,9 +312,14 @@
     Debug mode:                  $set_enable_debug
     With SSE:                    $set_enable_sse
     Experimental plugins:        $set_enable_experimental
+    LADSPA enabled:              $LADSPA_ENABLED
     Common GUI code:             $GUI_ENABLED
+    Out-of-process GUI code:     $EXEC_GUI_ENABLED
+    DSSI enabled:                $DSSI_ENABLED
+    DSSI GUI enabled:            $DSSI_GUI_ENABLED
     LV2 enabled:                 $LV2_ENABLED
-    LV2 GTK+ GUI enabled:        $LV2_GUI_ENABLED
+    LV2 in-process GUI enabled:  $LV2_GTK_GUI_ENABLED
+    LV2 GUI enabled:             $LV2_GUI_ENABLED
     JACK host enabled:           $JACK_ENABLED
     LASH enabled:                $LASH_ENABLED])
 if test "$LASH_ENABLED" = "yes"; then
diff -U 3 -H -b -d -r -N -- calf-old/src/Makefile.am calf-master/src/Makefile.am
--- calf-old/src/Makefile.am	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/Makefile.am	2012-12-31 00:14:37.000000000 +0000
@@ -4,6 +4,7 @@
 
 SUBDIRS = calf
 
+ladspadir = $(with_ladspa_dir)
 lv2dir = $(with_lv2_dir)/calf.lv2
 
 bin_PROGRAMS = 
@@ -11,6 +12,13 @@
 
 noinst_PROGRAMS = calfbenchmark
 pkglib_LTLIBRARIES = calf.la
+if USE_DSSI_GUI
+bin_PROGRAMS += calf_gtk
+endif
+if USE_LV2_GUI
+noinst_LTLIBRARIES += calflv2gui.la
+bin_PROGRAMS += calf_gtk
+endif
 
 AM_CXXFLAGS = -ffast-math -finline-limit=80 $(FLUIDSYNTH_DEPS_CFLAGS)
 
@@ -37,21 +45,28 @@
 calfbenchmark_SOURCES = benchmark.cpp
 calfbenchmark_LDADD = calf.la $(GLIB_DEPS_LIBS)
 
-calf_la_SOURCES = audio_fx.cpp metadata.cpp modules.cpp modules_comp.cpp modules_limit.cpp modules_dist.cpp modules_eq.cpp modules_mod.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp 
+if USE_EXEC_GUI
+calf_gtk_SOURCES = dssigui.cpp
+calf_gtk_LDADD = calf.la libcalfgui.la $(GLIB_DEPS_LIBS) $(GUI_DEPS_LIBS)
+calfbenchmark_CXXFLAGS = $(AM_CXXFLAGS) -DTEST_OSC
+calfbenchmark_LDADD += libcalfgui.la
+endif
+
+calf_la_SOURCES = audio_fx.cpp metadata.cpp modules.cpp modules_comp.cpp modules_limit.cpp modules_dist.cpp modules_eq.cpp modules_mod.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp 
 calf_la_LIBADD = $(FLUIDSYNTH_DEPS_LIBS) -lfftw3f
 if USE_DEBUG
 calf_la_LDFLAGS = -rpath $(pkglibdir) -avoid-version -module -lexpat -disable-static 
 else
-calf_la_LDFLAGS = -rpath $(pkglibdir) -avoid-version -module -lexpat -disable-static -export-symbols-regex "lv2_descriptor"  
+calf_la_LDFLAGS = -rpath $(pkglibdir) -avoid-version -module -lexpat -disable-static -export-symbols-regex "(ladspa_|lv2_|dssi_)descriptor"
 endif
 
-if USE_LV2_GUI
+if USE_LV2_GTK_GUI
 
 # Version WITH out-of-process GUI - links GTK+, UI controls etc.
 
 noinst_LTLIBRARIES += calflv2gui.la
 
-calflv2gui_la_SOURCES = gui.cpp gui_config.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp metadata.cpp giface.cpp plugin_gui_window.cpp preset.cpp preset_gui.cpp lv2gui.cpp osctl.cpp utils.cpp
+calflv2gui_la_SOURCES = gui.cpp gui_config.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp metadata.cpp giface.cpp plugin_gui_window.cpp preset.cpp preset_gui.cpp lv2gui.cpp osctl.cpp osctlnet.cpp utils.cpp
 
 if USE_DEBUG
 calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat $(GUI_DEPS_LIBS) -disable-static
@@ -59,10 +74,25 @@
 calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat -export-symbols-regex "lv2ui_descriptor" $(GUI_DEPS_LIBS) -disable-static
 endif
 
+else
+
+# Version WITHOUT out-of-process GUI - links GLib only
+
+if USE_LV2_GUI
+calflv2gui_la_SOURCES = metadata.cpp giface.cpp preset.cpp lv2gui.cpp osctl.cpp osctlnet.cpp utils.cpp
+
+if USE_DEBUG
+calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat $(GLIB_DEPS_LIBS) -disable-static
+else
+calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat -export-symbols-regex "lv2ui_descriptor" $(GLIB_DEPS_LIBS) -disable-static
+endif
+
+endif
+
 endif
 
 if USE_GUI
-libcalfgui_la_SOURCES = ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp gui.cpp gui_config.cpp gui_controls.cpp osctl.cpp plugin_gui_window.cpp preset_gui.cpp utils.cpp
+libcalfgui_la_SOURCES = ctl_curve.cpp ctl_keyboard.cpp ctl_knob.cpp ctl_led.cpp ctl_tube.cpp ctl_vumeter.cpp custom_ctl.cpp gui.cpp gui_config.cpp gui_controls.cpp osctl.cpp osctlnet.cpp osctl_glib.cpp plugin_gui_window.cpp preset_gui.cpp utils.cpp
 libcalfgui_la_LDFLAGS = -static -disable-shared -lexpat
 endif
 
@@ -75,9 +105,22 @@
 if USE_GUI
 	install -c -m 644 $(top_srcdir)/calf-gui.xml $(DESTDIR)$(pkgdatadir)
 endif
+if USE_LADSPA
+	install -d -m 755 $(DESTDIR)$(with_ladspa_dir)
+	install -d -m 755 $(DESTDIR)$(with_ladspa_rdf_dir)
+	ln -sf $(pkglibdir)/calf.so $(DESTDIR)$(with_ladspa_dir)/calf.so
+	$(top_builddir)/src/calfmakerdf > $(DESTDIR)$(with_ladspa_rdf_dir)/calf.rdf
+endif
+if USE_DSSI
+	install -d -m 755 $(DESTDIR)$(with_dssi_dir)
+	install -d -m 755 $(DESTDIR)$(with_dssi_dir)/calf
+	ln -sf $(pkglibdir)/calf.so $(DESTDIR)$(with_dssi_dir)/calf.so
+	ln -sf $(bindir)/calf_gtk $(DESTDIR)$(with_dssi_dir)/calf/calf_gtk
+endif
 if USE_LV2
 	install -d -m 755 $(DESTDIR)$(lv2dir)
 	ln -sf $(pkglibdir)/calf.so $(DESTDIR)$(lv2dir)/calf.so
+	ln -sf $(bindir)/calf_gtk $(DESTDIR)$(lv2dir)/calf_gtk
 if USE_LV2_GUI
 	install -c -m 755 $(top_builddir)/src/.libs/calflv2gui.so $(DESTDIR)$(lv2dir)/calflv2gui.so
 endif
@@ -90,6 +133,7 @@
 if USE_LV2
 if USE_LV2_GUI
 	rm -f $(DESTDIR)$(lv2dir)/calflv2gui.so
+	rm -f $(DESTDIR)$(lv2dir)/calf_gtk
 endif
 	rm -f $(DESTDIR)$(lv2dir)/calf.so
 	rm -f $(DESTDIR)$(lv2dir)/*.ttl
@@ -100,4 +144,15 @@
 endif
 	rm -f $(DESTDIR)$(pkgdatadir)/presets*.xml
 	rmdir $(DESTDIR)$(pkgdatadir) || true
-
+if USE_LADSPA
+	$(RM) -f $(DESTDIR)$(with_ladspa_dir)/calf.so
+	$(RM) -f $(DESTDIR)$(with_ladspa_rdf_dir)/calf.rdf
+	rmdir -p $(DESTDIR)$(with_ladspa_rdf_dir) || true
+endif
+if USE_DSSI
+	$(RM) -f $(DESTDIR)$(with_dssi_dir)/calf.so
+if USE_DSSI_GUI
+	$(RM) -f $(DESTDIR)$(with_dssi_dir)/calf/calf_gtk
+endif
+	rmdir -p $(DESTDIR)$(with_dssi_dir)/calf || true
+endif
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/Makefile.am calf-master/src/calf/Makefile.am
--- calf-old/src/calf/Makefile.am	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/Makefile.am	2013-09-02 17:58:26.962755728 +0100
@@ -2,12 +2,12 @@
     ctl_curve.h ctl_keyboard.h ctl_knob.h ctl_led.h ctl_tube.h ctl_vumeter.h \
     delay.h envelope.h fft.h fixed_point.h giface.h gtk_session_env.h gtk_main_win.h \
     gui.h gui_config.h gui_controls.h inertia.h jackhost.h \
-    host_session.h loudness.h \
-    lv2_data_access.h lv2_event.h lv2_external_ui.h \
-    lv2_state.h  lv2_progress.h lv2_ui.h lv2_uri_map.h lv2helpers.h lv2wrap.h \
+    host_session.h ladspa_wrap.h loudness.h \
+    lv2.h lv2_data_access.h lv2_event.h lv2_external_ui.h lv2_instance_access.h \
+    lv2_programs.h lv2_state.h lv2_ui.h lv2_uri_map.h lv2helpers.h lv2wrap.h \
     metadata.h modmatrix.h \
     modules.h modules_comp.h modules_dev.h modules_dist.h modules_eq.h modules_limit.h modules_mod.h modules_synths.h \
     modulelist.h \
-    multichorus.h onepole.h organ.h osc.h osctl.h plugin_tools.h preset.h \
+    multichorus.h onepole.h organ.h osc.h osctl.h osctlnet.h osctl_glib.h plugin_tools.h preset.h \
     preset_gui.h primitives.h session_mgr.h synth.h utils.h vumeter.h wave.h waveshaping.h wavetable.h
 
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/giface.h calf-master/src/calf/giface.h
--- calf-old/src/calf/giface.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/giface.h	2012-12-31 00:14:37.000000000 +0000
@@ -593,6 +593,9 @@
     void add_graphs(const calf_plugins::parameter_properties *props, int num_params);
     void update();
     ~dssi_feedback_sender();
+    
+    // always valid iface context
+    cairo_iface *_context;
 };
 #endif
 
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/ladspa_wrap.h calf-master/src/calf/ladspa_wrap.h
--- calf-old/src/calf/ladspa_wrap.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/ladspa_wrap.h	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,131 @@
+/* Calf DSP Library
+ * API wrappers for LADSPA/DSSI
+ *
+ * Copyright (C) 2007-2008 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __CALF_LADSPA_WRAP_H
+#define __CALF_LADSPA_WRAP_H
+
+#if USE_LADSPA
+
+#include <string.h>
+#include <ladspa.h>
+#if USE_DSSI
+#include <dssi.h>
+#endif
+#include "giface.h"
+#include "preset.h"
+
+namespace calf_plugins {
+
+struct ladspa_plugin_metadata_set;
+/// A template implementing plugin_ctl_iface for a given plugin
+struct ladspa_instance: public plugin_ctl_iface
+{
+    audio_module_iface *module;
+    const plugin_metadata_iface *metadata;
+    ladspa_plugin_metadata_set *ladspa;
+    bool activate_flag;
+    float **ins, **outs, **params;
+#if USE_DSSI
+    dssi_feedback_sender *feedback_sender;
+#endif
+    
+    ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate);
+    virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
+    virtual const phase_graph_iface *get_phase_graph_iface() const { return module->get_phase_graph_iface(); }
+    virtual float get_param_value(int param_no);
+    virtual void set_param_value(int param_no, float value);
+    virtual bool activate_preset(int bank, int program);
+    virtual char *configure(const char *key, const char *value);
+    virtual float get_level(unsigned int port) { return 0.f; }
+    virtual void execute(int cmd_no) {
+        module->execute(cmd_no);
+    }
+    virtual void send_configures(send_configure_iface *sci) { 
+        module->send_configures(sci);
+    }
+    virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); }
+    void run(unsigned long SampleCount);
+#if USE_DSSI
+    /// Utility function: handle MIDI event (only handles a subset in this version)
+    void process_dssi_event(snd_seq_event_t &event);
+    void run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount);
+#endif
+    virtual const plugin_metadata_iface *get_metadata_iface() const
+    {
+        return metadata;
+    }
+};
+
+/// Set of metadata produced by LADSPA wrapper for LADSPA-related purposes
+struct ladspa_plugin_metadata_set
+{
+    /// LADSPA descriptor
+    LADSPA_Descriptor descriptor;
+    /// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor)
+    LADSPA_Descriptor descriptor_for_dssi;
+#if USE_DSSI
+    /// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.)
+    DSSI_Descriptor dssi_descriptor;
+    DSSI_Program_Descriptor dssi_default_program;
+
+    std::vector<plugin_preset> *presets;
+    std::vector<DSSI_Program_Descriptor> *preset_descs;
+#endif
+    
+    int input_count, output_count, param_count;
+    const plugin_metadata_iface *metadata;
+    
+    ladspa_plugin_metadata_set();
+    void prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate));
+    void prepare_dssi();
+    ~ladspa_plugin_metadata_set();
+};
+
+/// A wrapper class for plugin class object (there is only one ladspa_wrapper singleton for many instances of the same plugin)
+template<class Module>
+struct ladspa_wrapper
+{
+    static ladspa_plugin_metadata_set output;
+    
+private:
+    ladspa_wrapper(const plugin_metadata_iface *md)
+    {
+        output.prepare(md, cb_instantiate);
+    }
+
+public:
+    /// LADSPA instantiation function (create a plugin instance)
+    static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)
+    {
+        return new ladspa_instance(new Module, &output, sample_rate);
+    }
+
+    /// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions
+    static ladspa_plugin_metadata_set &get() { 
+        static ladspa_wrapper instance(new typename Module::metadata_class);
+        return instance.output;
+    }
+};
+
+};
+
+#endif
+
+#endif
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2.h calf-master/src/calf/lv2.h
--- calf-old/src/calf/lv2.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/lv2.h	2013-03-29 07:05:19.000000000 +0000
@@ -0,0 +1,454 @@
+/*
+  LV2 - An audio plugin interface specification.
+  Copyright 2006-2012 Steve Harris, David Robillard.
+
+  Based on LADSPA, Copyright 2000-2002 Richard W.E. Furse,
+  Paul Barton-Davis, Stefan Westerfeld.
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+   @file lv2.h
+   API for the LV2 specification <http://lv2plug.in/ns/lv2core>.
+   Revision: 6.5
+*/
+
+#ifndef LV2_H_INCLUDED
+#define LV2_H_INCLUDED
+
+#include <stdint.h>
+
+#define LV2_CORE_URI    "http://lv2plug.in/ns/lv2core"
+#define LV2_CORE_PREFIX LV2_CORE_URI "#"
+
+#define LV2_CORE__AllpassPlugin      LV2_CORE_PREFIX "AllpassPlugin"
+#define LV2_CORE__AmplifierPlugin    LV2_CORE_PREFIX "AmplifierPlugin"
+#define LV2_CORE__AnalyserPlugin     LV2_CORE_PREFIX "AnalyserPlugin"
+#define LV2_CORE__AudioPort          LV2_CORE_PREFIX "AudioPort"
+#define LV2_CORE__BandpassPlugin     LV2_CORE_PREFIX "BandpassPlugin"
+#define LV2_CORE__CVPort             LV2_CORE_PREFIX "CVPort"
+#define LV2_CORE__ChorusPlugin       LV2_CORE_PREFIX "ChorusPlugin"
+#define LV2_CORE__CombPlugin         LV2_CORE_PREFIX "CombPlugin"
+#define LV2_CORE__CompressorPlugin   LV2_CORE_PREFIX "CompressorPlugin"
+#define LV2_CORE__ConstantPlugin     LV2_CORE_PREFIX "ConstantPlugin"
+#define LV2_CORE__ControlPort        LV2_CORE_PREFIX "ControlPort"
+#define LV2_CORE__ConverterPlugin    LV2_CORE_PREFIX "ConverterPlugin"
+#define LV2_CORE__DelayPlugin        LV2_CORE_PREFIX "DelayPlugin"
+#define LV2_CORE__DistortionPlugin   LV2_CORE_PREFIX "DistortionPlugin"
+#define LV2_CORE__DynamicsPlugin     LV2_CORE_PREFIX "DynamicsPlugin"
+#define LV2_CORE__EQPlugin           LV2_CORE_PREFIX "EQPlugin"
+#define LV2_CORE__EnvelopePlugin     LV2_CORE_PREFIX "EnvelopePlugin"
+#define LV2_CORE__ExpanderPlugin     LV2_CORE_PREFIX "ExpanderPlugin"
+#define LV2_CORE__ExtensionData      LV2_CORE_PREFIX "ExtensionData"
+#define LV2_CORE__Feature            LV2_CORE_PREFIX "Feature"
+#define LV2_CORE__FilterPlugin       LV2_CORE_PREFIX "FilterPlugin"
+#define LV2_CORE__FlangerPlugin      LV2_CORE_PREFIX "FlangerPlugin"
+#define LV2_CORE__FunctionPlugin     LV2_CORE_PREFIX "FunctionPlugin"
+#define LV2_CORE__GatePlugin         LV2_CORE_PREFIX "GatePlugin"
+#define LV2_CORE__GeneratorPlugin    LV2_CORE_PREFIX "GeneratorPlugin"
+#define LV2_CORE__HighpassPlugin     LV2_CORE_PREFIX "HighpassPlugin"
+#define LV2_CORE__InputPort          LV2_CORE_PREFIX "InputPort"
+#define LV2_CORE__InstrumentPlugin   LV2_CORE_PREFIX "InstrumentPlugin"
+#define LV2_CORE__LimiterPlugin      LV2_CORE_PREFIX "LimiterPlugin"
+#define LV2_CORE__LowpassPlugin      LV2_CORE_PREFIX "LowpassPlugin"
+#define LV2_CORE__MixerPlugin        LV2_CORE_PREFIX "MixerPlugin"
+#define LV2_CORE__ModulatorPlugin    LV2_CORE_PREFIX "ModulatorPlugin"
+#define LV2_CORE__MultiEQPlugin      LV2_CORE_PREFIX "MultiEQPlugin"
+#define LV2_CORE__OscillatorPlugin   LV2_CORE_PREFIX "OscillatorPlugin"
+#define LV2_CORE__OutputPort         LV2_CORE_PREFIX "OutputPort"
+#define LV2_CORE__ParaEQPlugin       LV2_CORE_PREFIX "ParaEQPlugin"
+#define LV2_CORE__PhaserPlugin       LV2_CORE_PREFIX "PhaserPlugin"
+#define LV2_CORE__PitchPlugin        LV2_CORE_PREFIX "PitchPlugin"
+#define LV2_CORE__Plugin             LV2_CORE_PREFIX "Plugin"
+#define LV2_CORE__PluginBase         LV2_CORE_PREFIX "PluginBase"
+#define LV2_CORE__Point              LV2_CORE_PREFIX "Point"
+#define LV2_CORE__Port               LV2_CORE_PREFIX "Port"
+#define LV2_CORE__PortProperty       LV2_CORE_PREFIX "PortProperty"
+#define LV2_CORE__Resource           LV2_CORE_PREFIX "Resource"
+#define LV2_CORE__ReverbPlugin       LV2_CORE_PREFIX "ReverbPlugin"
+#define LV2_CORE__ScalePoint         LV2_CORE_PREFIX "ScalePoint"
+#define LV2_CORE__SimulatorPlugin    LV2_CORE_PREFIX "SimulatorPlugin"
+#define LV2_CORE__SpatialPlugin      LV2_CORE_PREFIX "SpatialPlugin"
+#define LV2_CORE__Specification      LV2_CORE_PREFIX "Specification"
+#define LV2_CORE__SpectralPlugin     LV2_CORE_PREFIX "SpectralPlugin"
+#define LV2_CORE__UtilityPlugin      LV2_CORE_PREFIX "UtilityPlugin"
+#define LV2_CORE__WaveshaperPlugin   LV2_CORE_PREFIX "WaveshaperPlugin"
+#define LV2_CORE__appliesTo          LV2_CORE_PREFIX "appliesTo"
+#define LV2_CORE__binary             LV2_CORE_PREFIX "binary"
+#define LV2_CORE__connectionOptional LV2_CORE_PREFIX "connectionOptional"
+#define LV2_CORE__control            LV2_CORE_PREFIX "control"
+#define LV2_CORE__default            LV2_CORE_PREFIX "default"
+#define LV2_CORE__designation        LV2_CORE_PREFIX "designation"
+#define LV2_CORE__documentation      LV2_CORE_PREFIX "documentation"
+#define LV2_CORE__enumeration        LV2_CORE_PREFIX "enumeration"
+#define LV2_CORE__extensionData      LV2_CORE_PREFIX "extensionData"
+#define LV2_CORE__freeWheeling       LV2_CORE_PREFIX "freeWheeling"
+#define LV2_CORE__hardRTCapable      LV2_CORE_PREFIX "hardRTCapable"
+#define LV2_CORE__inPlaceBroken      LV2_CORE_PREFIX "inPlaceBroken"
+#define LV2_CORE__index              LV2_CORE_PREFIX "index"
+#define LV2_CORE__integer            LV2_CORE_PREFIX "integer"
+#define LV2_CORE__isLive             LV2_CORE_PREFIX "isLive"
+#define LV2_CORE__latency            LV2_CORE_PREFIX "latency"
+#define LV2_CORE__maximum            LV2_CORE_PREFIX "maximum"
+#define LV2_CORE__microVersion       LV2_CORE_PREFIX "microVersion"
+#define LV2_CORE__minimum            LV2_CORE_PREFIX "minimum"
+#define LV2_CORE__minorVersion       LV2_CORE_PREFIX "minorVersion"
+#define LV2_CORE__name               LV2_CORE_PREFIX "name"
+#define LV2_CORE__optionalFeature    LV2_CORE_PREFIX "optionalFeature"
+#define LV2_CORE__port               LV2_CORE_PREFIX "port"
+#define LV2_CORE__portProperty       LV2_CORE_PREFIX "portProperty"
+#define LV2_CORE__project            LV2_CORE_PREFIX "project"
+#define LV2_CORE__reportsLatency     LV2_CORE_PREFIX "reportsLatency"
+#define LV2_CORE__requiredFeature    LV2_CORE_PREFIX "requiredFeature"
+#define LV2_CORE__sampleRate         LV2_CORE_PREFIX "sampleRate"
+#define LV2_CORE__scalePoint         LV2_CORE_PREFIX "scalePoint"
+#define LV2_CORE__symbol             LV2_CORE_PREFIX "symbol"
+#define LV2_CORE__toggled            LV2_CORE_PREFIX "toggled"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+   Plugin Instance Handle.
+
+   This is a handle for one particular instance of a plugin.  It is valid to
+   compare to NULL (or 0 for C++) but otherwise the host MUST NOT attempt to
+   interpret it.
+*/
+typedef void * LV2_Handle;
+
+/**
+   Feature.
+
+   Features allow hosts to make additional functionality available to plugins
+   without requiring modification to the LV2 API.  Extensions may define new
+   features and specify the @ref URI and @ref data to be used if necessary.
+   Some features, such as lv2:isLive, do not require the host to pass data.
+*/
+typedef struct _LV2_Feature {
+	/**
+	   A globally unique, case-sensitive identifier (URI) for this feature.
+
+	   This MUST be a valid URI string as defined by RFC 3986.
+	*/
+	const char * URI;
+
+	/**
+	   Pointer to arbitrary data.
+
+	   The format of this data is defined by the extension which describes the
+	   feature with the given @ref URI.
+	*/
+	void * data;
+} LV2_Feature;
+
+/**
+   Plugin Descriptor.
+
+   This structure provides the core functions necessary to instantiate and use
+   a plugin.
+*/
+typedef struct _LV2_Descriptor {
+	/**
+	   A globally unique, case-sensitive identifier for this plugin.
+
+	   This MUST be a valid URI string as defined by RFC 3986.  All plugins with
+	   the same URI MUST be compatible to some degree, see
+	   http://lv2plug.in/ns/lv2core for details.
+	*/
+	const char * URI;
+
+	/**
+	   Instantiate the plugin.
+
+	   Note that instance initialisation should generally occur in activate()
+	   rather than here. If a host calls instantiate(), it MUST call cleanup()
+	   at some point in the future.
+
+	   @param descriptor Descriptor of the plugin to instantiate.
+
+	   @param sample_rate Sample rate, in Hz, for the new plugin instance.
+
+	   @param bundle_path Path to the LV2 bundle which contains this plugin
+	   binary. It MUST include the trailing directory separator (e.g. '/') so
+	   that simply appending a filename will yield the path to that file in the
+	   bundle.
+
+	   @param features A NULL terminated array of LV2_Feature structs which
+	   represent the features the host supports. Plugins may refuse to
+	   instantiate if required features are not found here. However, hosts MUST
+	   NOT use this as a discovery mechanism: instead, use the RDF data to
+	   determine which features are required and do not attempt to instantiate
+	   unsupported plugins at all. This parameter MUST NOT be NULL, i.e. a host
+	   that supports no features MUST pass a single element array containing
+	   NULL.
+
+	   @return A handle for the new plugin instance, or NULL if instantiation
+	   has failed.
+	*/
+	LV2_Handle (*instantiate)(const struct _LV2_Descriptor * descriptor,
+	                          double                         sample_rate,
+	                          const char *                   bundle_path,
+	                          const LV2_Feature *const *     features);
+
+	/**
+	   Connect a port on a plugin instance to a memory location.
+
+	   Plugin writers should be aware that the host may elect to use the same
+	   buffer for more than one port and even use the same buffer for both
+	   input and output (see lv2:inPlaceBroken in lv2.ttl).
+
+	   If the plugin has the feature lv2:hardRTCapable then there are various
+	   things that the plugin MUST NOT do within the connect_port() function;
+	   see lv2core.ttl for details.
+
+	   connect_port() MUST be called at least once for each port before run()
+	   is called, unless that port is lv2:connectionOptional. The plugin must
+	   pay careful attention to the block size passed to run() since the block
+	   allocated may only just be large enough to contain the data, and is not
+	   guaranteed to remain constant between run() calls.
+
+	   connect_port() may be called more than once for a plugin instance to
+	   allow the host to change the buffers that the plugin is reading or
+	   writing. These calls may be made before or after activate() or
+	   deactivate() calls.
+
+	   @param instance Plugin instance containing the port.
+
+	   @param port Index of the port to connect. The host MUST NOT try to
+	   connect a port index that is not defined in the plugin's RDF data. If
+	   it does, the plugin's behaviour is undefined (a crash is likely).
+
+	   @param data_location Pointer to data of the type defined by the port
+	   type in the plugin's RDF data (e.g. an array of float for an
+	   lv2:AudioPort). This pointer must be stored by the plugin instance and
+	   used to read/write data when run() is called. Data present at the time
+	   of the connect_port() call MUST NOT be considered meaningful.
+	*/
+	void (*connect_port)(LV2_Handle instance,
+	                     uint32_t   port,
+	                     void *     data_location);
+
+	/**
+	   Initialise a plugin instance and activate it for use.
+
+	   This is separated from instantiate() to aid real-time support and so
+	   that hosts can reinitialise a plugin instance by calling deactivate()
+	   and then activate(). In this case the plugin instance MUST reset all
+	   state information dependent on the history of the plugin instance except
+	   for any data locations provided by connect_port(). If there is nothing
+	   for activate() to do then this field may be NULL.
+
+	   When present, hosts MUST call this function once before run() is called
+	   for the first time. This call SHOULD be made as close to the run() call
+	   as possible and indicates to real-time plugins that they are now live,
+	   however plugins MUST NOT rely on a prompt call to run() after
+	   activate().
+
+	   The host MUST NOT call activate() again until deactivate() has been
+	   called first. If a host calls activate(), it MUST call deactivate() at
+	   some point in the future. Note that connect_port() may be called before
+	   or after activate().
+	*/
+	void (*activate)(LV2_Handle instance);
+
+	/**
+	   Run a plugin instance for a block.
+
+	   Note that if an activate() function exists then it must be called before
+	   run(). If deactivate() is called for a plugin instance then run() may
+	   not be called until activate() has been called again.
+
+	   If the plugin has the feature lv2:hardRTCapable then there are various
+	   things that the plugin MUST NOT do within the run() function (see
+	   lv2core.ttl for details).
+
+	   As a special case, when @p sample_count == 0, the plugin should update
+	   any output ports that represent a single instant in time (e.g. control
+	   ports, but not audio ports). This is particularly useful for latent
+	   plugins, which should update their latency output port so hosts can
+	   pre-roll plugins to compute latency. Plugins MUST NOT crash when
+	   @p sample_count == 0.
+
+	   @param instance Instance to be run.
+
+	   @param sample_count The block size (in samples) for which the plugin
+	   instance must run.
+	*/
+	void (*run)(LV2_Handle instance,
+	            uint32_t   sample_count);
+
+	/**
+	   Deactivate a plugin instance (counterpart to activate()).
+
+	   Hosts MUST deactivate all activated instances after they have been run()
+	   for the last time. This call SHOULD be made as close to the last run()
+	   call as possible and indicates to real-time plugins that they are no
+	   longer live, however plugins MUST NOT rely on prompt deactivation. If
+	   there is nothing for deactivate() to do then this field may be NULL
+
+	   Deactivation is not similar to pausing since the plugin instance will be
+	   reinitialised by activate(). However, deactivate() itself MUST NOT fully
+	   reset plugin state. For example, the host may deactivate a plugin, then
+	   store its state (using some extension to do so).
+
+	   Hosts MUST NOT call deactivate() unless activate() was previously
+	   called. Note that connect_port() may be called before or after
+	   deactivate().
+	*/
+	void (*deactivate)(LV2_Handle instance);
+
+	/**
+	   Clean up a plugin instance (counterpart to instantiate()).
+
+	   Once an instance of a plugin has been finished with it must be deleted
+	   using this function. The instance handle passed ceases to be valid after
+	   this call.
+
+	   If activate() was called for a plugin instance then a corresponding call
+	   to deactivate() MUST be made before cleanup() is called. Hosts MUST NOT
+	   call cleanup() unless instantiate() was previously called.
+	*/
+	void (*cleanup)(LV2_Handle instance);
+
+	/**
+	   Return additional plugin data defined by some extenion.
+
+	   A typical use of this facility is to return a struct containing function
+	   pointers to extend the LV2_Descriptor API.
+
+	   The actual type and meaning of the returned object MUST be specified
+	   precisely by the extension. This function MUST return NULL for any
+	   unsupported URI. If a plugin does not support any extension data, this
+	   field may be NULL.
+
+	   The host is never responsible for freeing the returned value.
+	*/
+	const void * (*extension_data)(const char * uri);
+} LV2_Descriptor;
+
+/**
+   Put this (LV2_SYMBOL_EXPORT) before any functions that are to be loaded
+   by the host as a symbol from the dynamic library.
+*/
+#ifdef _WIN32
+#    define LV2_SYMBOL_EXPORT __declspec(dllexport)
+#else
+#    define LV2_SYMBOL_EXPORT
+#endif
+
+/**
+   Prototype for plugin accessor function.
+
+   This is part of the old discovery API, which has been replaced due to being
+   inadequate for some plugins.  It is limited because the bundle path is not
+   available during discovery, and it relies on non-portable shared library
+   constructors/destructors.  However, this API is still supported and plugins
+   are not required to migrate.
+
+   Plugins are discovered by hosts using RDF data (not by loading libraries).
+   See http://lv2plug.in for details on the discovery process, though most
+   hosts should use an existing library to implement this functionality.
+
+   A plugin library MUST include a function called "lv2_descriptor" with this
+   prototype.  This function MUST have C-style linkage (if you are using C++
+   this is taken care of by the 'extern "C"' clause at the top of this file).
+
+   When it is time to load a plugin (designated by its URI), the host loads the
+   plugin's library, gets the lv2_descriptor() function from it, and uses this
+   function to find the LV2_Descriptor for the desired plugin.  Plugins are
+   accessed by index using values from 0 upwards.  This function MUST return
+   NULL for out of range indices, so the host can enumerate plugins by
+   increasing @p index until NULL is returned.
+
+   Note that @p index has no meaning, hosts MUST NOT depend on it remaining
+   consistent between loads of the plugin library.
+*/
+LV2_SYMBOL_EXPORT
+const LV2_Descriptor * lv2_descriptor(uint32_t index);
+
+/**
+   Type of the lv2_descriptor() function in a library (old discovery API).
+*/
+typedef const LV2_Descriptor *
+(*LV2_Descriptor_Function)(uint32_t index);
+
+/**
+   Handle for a library descriptor.
+*/
+typedef void* LV2_Lib_Handle;
+
+/**
+   Descriptor for a plugin library.
+
+   To access a plugin library, the host creates an LV2_Lib_Descriptor via the
+   lv2_lib_descriptor() function in the shared object.
+*/
+typedef struct {
+	/**
+	   Opaque library data which must be passed as the first parameter to all
+	   the methods of this struct.
+	*/
+	LV2_Lib_Handle handle;
+
+	/**
+	   The total size of this struct.  This allows for this struct to be
+	   expanded in the future if necessary.  This MUST be set by the library to
+	   sizeof(LV2_Lib_Descriptor).  The host MUST NOT access any fields of this
+	   struct beyond get_plugin() unless this field indicates they are present.
+	*/
+	uint32_t size;
+
+	/**
+	   Destroy this library descriptor and free all related resources.
+	*/
+	void (*cleanup)(LV2_Lib_Handle handle);
+
+	/**
+	   Plugin accessor.
+
+	   Plugins are accessed by index using values from 0 upwards.  Out of range
+	   indices MUST result in this function returning NULL, so the host can
+	   enumerate plugins by increasing @a index until NULL is returned.
+	*/
+	const LV2_Descriptor * (*get_plugin)(LV2_Lib_Handle handle,
+	                                     uint32_t       index);
+} LV2_Lib_Descriptor;
+
+/**
+   Prototype for library accessor function.
+
+   This is the entry point for a plugin library.  Hosts load this symbol from
+   the library and call this function to obtain a library descriptor which can
+   be used to access all the contained plugins.  The returned object must not
+   be destroyed (using LV2_Lib_Descriptor::cleanup()) until all plugins loaded
+   from that library have been destroyed.
+*/
+const LV2_Lib_Descriptor *
+lv2_lib_descriptor(const char *               bundle_path,
+                   const LV2_Feature *const * features);
+
+/**
+   Type of the lv2_lib_descriptor() function in an LV2 library.
+*/
+typedef const LV2_Lib_Descriptor *
+(*LV2_Lib_Descriptor_Function)(const char *               bundle_path,
+                               const LV2_Feature *const * features);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LV2_H_INCLUDED */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_data_access.h calf-master/src/calf/lv2_data_access.h
--- calf-old/src/calf/lv2_data_access.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_data_access.h	2013-08-14 06:04:48.000000000 +0100
@@ -1,59 +1,63 @@
-/* lv2_data_access.h - C header file for the LV2 Data Access extension.
- * Copyright (C) 2008 Dave Robillard <dave@drobilla.net>
- * 
- * This header is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This header 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
- */
+/*
+  LV2 Data Access Extension
+  Copyright 2008-2011 David Robillard <http://drobilla.net>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+   @file data-access.h
+   C header for the LV2 Extension Data extension
+   <http://lv2plug.in/ns/ext/data-access>.
+
+   This extension defines a method for (e.g.) plugin UIs to have (possibly
+   marshalled) access to the extension_data function on a plugin instance.
+*/
 
 #ifndef LV2_DATA_ACCESS_H
 #define LV2_DATA_ACCESS_H
 
 #define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-/** @file
- * This header defines the LV2 Extension Data extension with the URI
- * <http://lv2plug.in/ns/ext/data-access>.
- *
- * This extension defines a method for (e.g.) plugin UIs to have (possibly
- * marshalled) access to the extension_data function on a plugin instance.
- */
-	
+/**
+   The data field of the LV2_Feature for this extension.
 
-/** The data field of the LV2_Feature for this extension.
- *
- * To support this feature the host must pass an LV2_Feature struct to the
- * instantiate method with URI "http://lv2plug.in/ns/ext/data-access"
- * and data pointed to an instance of this struct.
- */
+   To support this feature the host must pass an LV2_Feature struct to the
+   instantiate method with URI "http://lv2plug.in/ns/ext/data-access"
+   and data pointed to an instance of this struct.
+*/
 typedef struct {
+	/**
+	   A pointer to a method the UI can call to get data (of a type specified
+	   by some other extension) from the plugin.
 	
-	/** A pointer to a method the UI can call to get data (of a type specified
-	 * by some other extension) from the plugin.
-	 *
-	 * This call never is never guaranteed to return anything, UIs should
-	 * degrade gracefully if direct access to the plugin data is not possible
-	 * (in which case this function will return NULL).
-	 *
-	 * This is for access to large data that can only possibly work if the UI
-	 * and plugin are running in the same process.  For all other things, use
-	 * the normal LV2 UI communication system.
+	   This call never is never guaranteed to return anything, UIs should
+	   degrade gracefully if direct access to the plugin data is not possible
+	   (in which case this function will return NULL).
+
+	   This is for access to large data that can only possibly work if the UI
+	   and plugin are running in the same process.  For all other things, use
+	   the normal LV2 UI communication system.
 	 */
 	const void* (*data_access)(const char* uri);
-
 } LV2_Extension_Data_Feature;
 
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
 
-#endif // LV2_DATA_ACCESS_H
-
+#endif  /* LV2_DATA_ACCESS_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_event.h calf-master/src/calf/lv2_event.h
--- calf-old/src/calf/lv2_event.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_event.h	2013-08-14 06:04:48.000000000 +0100
@@ -1,260 +1,294 @@
-/* lv2_event.h - C header file for the LV2 events extension.
- * 
- * Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
- * Copyright (C) 2008 Dave Robillard <dave@drobilla.net>
- * 
- * This header is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This header 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
- */
+/*
+  Copyright 2008-2011 David Robillard <http://drobilla.net>
+  Copyright 2006-2007 Lars Luthman <lars.luthman@gmail.com>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+   @file event.h
+   C API for the LV2 Event extension <http://lv2plug.in/ns/ext/event>.
+
+   This extension is a generic transport mechanism for time stamped events
+   of any type (e.g. MIDI, OSC, ramps, etc). Each port can transport mixed
+   events of any type; the type of events and timestamps are defined by a URI
+   which is mapped to an integer by the host for performance reasons.
+
+   This extension requires the host to support the LV2 URI Map extension.
+   Any host which supports this extension MUST guarantee that any call to
+   the LV2 URI Map uri_to_id function with the URI of this extension as the
+   'map' argument returns a value within the range of uint16_t.
+*/
 
 #ifndef LV2_EVENT_H
 #define LV2_EVENT_H
  
 #define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event"
+#define LV2_EVENT_PREFIX LV2_EVENT_URI "#"
+
+#define LV2_EVENT__Event              LV2_EVENT_PREFIX "Event"
+#define LV2_EVENT__EventPort          LV2_EVENT_PREFIX "EventPort"
+#define LV2_EVENT__FrameStamp         LV2_EVENT_PREFIX "FrameStamp"
+#define LV2_EVENT__TimeStamp          LV2_EVENT_PREFIX "TimeStamp"
+#define LV2_EVENT__generatesTimeStamp LV2_EVENT_PREFIX "generatesTimeStamp"
+#define LV2_EVENT__generic            LV2_EVENT_PREFIX "generic"
+#define LV2_EVENT__inheritsEvent      LV2_EVENT_PREFIX "inheritsEvent"
+#define LV2_EVENT__inheritsTimeStamp  LV2_EVENT_PREFIX "inheritsTimeStamp"
+#define LV2_EVENT__supportsEvent      LV2_EVENT_PREFIX "supportsEvent"
+#define LV2_EVENT__supportsTimeStamp  LV2_EVENT_PREFIX "supportsTimeStamp"
+
 #define LV2_EVENT_AUDIO_STAMP 0
 
 #include <stdint.h>
 
-/** @file
- * This header defines the code portion of the LV2 events extension with URI
- * <http://lv2plug.in/ns/ext/event> ('lv2ev').
- *
- * This extension is a generic transport mechanism for time stamped events
- * of any type (e.g. MIDI, OSC, ramps, etc).  Each port can transport mixed
- * events of any type; the type of events and timestamps are defined by a URI
- * which is mapped to an integer by the host for performance reasons.
- *
- * This extension requires the host to support the LV2 URI Map extension.
- * Any host which supports this extension MUST guarantee that any call to
- * the LV2 URI Map uri_to_id function with the URI of this extension as the
- * 'map' argument returns a value within the range of uint16_t.
- */
-
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-/** The best Pulses Per Quarter Note for tempo-based uint32_t timestmaps.
- * Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble
- * by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12.
- */
+/**
+   The best Pulses Per Quarter Note for tempo-based uint32_t timestamps.
+   Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble
+   by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12.
+*/
 static const uint32_t LV2_EVENT_PPQN = 3136573440U;
 
+/**
+   An LV2 event (header only).
 
-/** An LV2 event (header only).
- *
- * LV2 events are generic time-stamped containers for any type of event.
- * The type field defines the format of a given event's contents.
- *
- * This struct defines the header of an LV2 event.  An LV2 event is a single
- * chunk of POD (plain old data), usually contained in a flat buffer
- * (see LV2_EventBuffer below).  Unless a required feature says otherwise,
- * hosts may assume a deep copy of an LV2 event can be created safely
- * using a simple:
- *
- * memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size);  (or equivalent)
- */
-typedef struct {
+   LV2 events are generic time-stamped containers for any type of event.
+   The type field defines the format of a given event's contents.
 
-	/** The frames portion of timestamp.  The units used here can optionally be
-	 * set for a port (with the lv2ev:timeUnits property), otherwise this
-	 * is audio frames, corresponding to the sample_count parameter of the
-	 * LV2 run method (e.g. frame 0 is the first frame for that call to run).
+   This struct defines the header of an LV2 event. An LV2 event is a single
+   chunk of POD (plain old data), usually contained in a flat buffer (see
+   LV2_EventBuffer below). Unless a required feature says otherwise, hosts may
+   assume a deep copy of an LV2 event can be created safely using a simple:
+
+   memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size);  (or equivalent)
+*/
+typedef struct {
+	/**
+	   The frames portion of timestamp. The units used here can optionally be
+	   set for a port (with the lv2ev:timeUnits property), otherwise this is
+	   audio frames, corresponding to the sample_count parameter of the LV2 run
+	   method (e.g. frame 0 is the first frame for that call to run).
 	 */
 	uint32_t frames;
 
-	/** The sub-frames portion of timestamp.  The units used here can
-	 * optionally be set for a port (with the lv2ev:timeUnits property),
-	 * otherwise this is 1/(2^32) of an audio frame.
+	/**
+	   The sub-frames portion of timestamp. The units used here can optionally
+	   be set for a port (with the lv2ev:timeUnits property), otherwise this is
+	   1/(2^32) of an audio frame.
 	 */
 	uint32_t subframes;
 	
-	/** The type of this event, as a number which represents some URI
-	 * defining an event type.  This value MUST be some value previously
-	 * returned from a call to the uri_to_id function defined in the LV2
-	 * URI map extension (see lv2_uri_map.h).
-	 * There are special rules which must be followed depending on the type
-	 * of an event.  If the plugin recognizes an event type, the definition
-	 * of that event type will describe how to interpret the event, and
-	 * any required behaviour.  Otherwise, if the type is 0, this event is a
-	 * non-POD event and lv2_event_unref MUST be called if the event is
-	 * 'dropped' (see above).  Even if the plugin does not understand an event,
-	 * it may pass the event through to an output by simply copying (and NOT
-	 * calling lv2_event_unref).  These rules are designed to allow for generic
-	 * event handling plugins and large non-POD events, but with minimal hassle
-	 * on simple plugins that "don't care" about these more advanced features.
+	/**
+	   The type of this event, as a number which represents some URI
+	   defining an event type. This value MUST be some value previously
+	   returned from a call to the uri_to_id function defined in the LV2
+	   URI map extension (see lv2_uri_map.h).
+	   There are special rules which must be followed depending on the type
+	   of an event. If the plugin recognizes an event type, the definition
+	   of that event type will describe how to interpret the event, and
+	   any required behaviour. Otherwise, if the type is 0, this event is a
+	   non-POD event and lv2_event_unref MUST be called if the event is
+	   'dropped' (see above). Even if the plugin does not understand an event,
+	   it may pass the event through to an output by simply copying (and NOT
+	   calling lv2_event_unref). These rules are designed to allow for generic
+	   event handling plugins and large non-POD events, but with minimal hassle
+	   on simple plugins that "don't care" about these more advanced features.
 	 */
 	uint16_t type;
 
-	/** The size of the data portion of this event in bytes, which immediately
-	 * follows.  The header size (12 bytes) is not included in this value.
+	/**
+	   The size of the data portion of this event in bytes, which immediately
+	   follows. The header size (12 bytes) is not included in this value.
 	 */
 	uint16_t size;
 
 	/* size bytes of data follow here */
-
 } LV2_Event;
 
 
+/**
+   A buffer of LV2 events (header only).
 
-/** A buffer of LV2 events (header only).
- *
- * Like events (which this contains) an event buffer is a single chunk of POD:
- * the entire buffer (including contents) can be copied with a single memcpy.
- * The first contained event begins sizeof(LV2_EventBuffer) bytes after
- * the start of this struct.
- *
- * After this header, the buffer contains an event header (defined by struct
- * LV2_Event), followed by that event's contents (padded to 64 bits), followed by
- * another header, etc:
- *
- * |       |       |       |       |       |       |
- * | | | | | | | | | | | | | | | | | | | | | | | | |
- * |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ...
- */
-typedef struct {
+   Like events (which this contains) an event buffer is a single chunk of POD:
+   the entire buffer (including contents) can be copied with a single memcpy.
+   The first contained event begins sizeof(LV2_EventBuffer) bytes after the
+   start of this struct.
 	
-	/** The contents of the event buffer.  This may or may not reside in the
-	 * same block of memory as this header, plugins must not assume either.
-	 * The host guarantees this points to at least capacity bytes of allocated
-	 * memory (though only size bytes of that are valid events).
+   After this header, the buffer contains an event header (defined by struct
+   LV2_Event), followed by that event's contents (padded to 64 bits), followed
+   by another header, etc:
+
+   |       |       |       |       |       |       |
+   | | | | | | | | | | | | | | | | | | | | | | | | |
+   |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ...
+*/
+typedef struct {
+	/**
+	   The contents of the event buffer. This may or may not reside in the
+	   same block of memory as this header, plugins must not assume either.
+	   The host guarantees this points to at least capacity bytes of allocated
+	   memory (though only size bytes of that are valid events).
 	 */
 	uint8_t* data;
 
-	/** The size of this event header in bytes (including everything).
-	 *
-	 * This is to allow for extending this header in the future without
-	 * breaking binary compatibility.  Whenever this header is copied,
-	 * it MUST be done using this field (and NOT the sizeof this struct).
+	/**
+	   The size of this event header in bytes (including everything).
+
+	   This is to allow for extending this header in the future without
+	   breaking binary compatibility. Whenever this header is copied,
+	   it MUST be done using this field (and NOT the sizeof this struct).
 	 */
 	uint16_t header_size;
 
-	/** The type of the time stamps for events in this buffer.
-	 * As a special exception, '0' always means audio frames and subframes
-	 * (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate.
-	 * INPUTS: The host must set this field to the numeric ID of some URI
-	 *     defining the meaning of the frames/subframes fields of contained
-	 *     events (obtained by the LV2 URI Map uri_to_id function with the URI
-	 *     of this extension as the 'map' argument, see lv2_uri_map.h).
-	 *     The host must never pass a plugin a buffer which uses a stamp type
-	 *     the plugin does not 'understand'.  The value of this field must
-	 *     never change, except when connect_port is called on the input
-	 *     port, at which time the host MUST have set the stamp_type field to
-	 *     the value that will be used for all subsequent run calls.
-	 * OUTPUTS: The plugin may set this to any value that has been returned
-	 *     from uri_to_id with the URI of this extension for a 'map' argument.
-	 *     When connected to a buffer with connect_port, output ports MUST set
-	 *     this field to the type of time stamp they will be writing.  On any
-	 *     call to connect_port on an event input port, the plugin may change
-	 *     this field on any output port, it is the responsibility of the host
-	 *     to check if any of these values have changed and act accordingly.
+	/**
+	   The type of the time stamps for events in this buffer.
+	   As a special exception, '0' always means audio frames and subframes
+	   (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate.
+
+	   INPUTS: The host must set this field to the numeric ID of some URI
+	   defining the meaning of the frames/subframes fields of contained events
+	   (obtained by the LV2 URI Map uri_to_id function with the URI of this
+	   extension as the 'map' argument, see lv2_uri_map.h).  The host must
+	   never pass a plugin a buffer which uses a stamp type the plugin does not
+	   'understand'. The value of this field must never change, except when
+	   connect_port is called on the input port, at which time the host MUST
+	   have set the stamp_type field to the value that will be used for all
+	   subsequent run calls.
+
+	   OUTPUTS: The plugin may set this to any value that has been returned
+	   from uri_to_id with the URI of this extension for a 'map' argument.
+	   When connected to a buffer with connect_port, output ports MUST set this
+	   field to the type of time stamp they will be writing. On any call to
+	   connect_port on an event input port, the plugin may change this field on
+	   any output port, it is the responsibility of the host to check if any of
+	   these values have changed and act accordingly.
 	 */
 	uint16_t stamp_type;
 
-	/** The number of events in this buffer.
-	 * INPUTS: The host must set this field to the number of events
-	 *     contained in the data buffer before calling run().
-	 *     The plugin must not change this field.
-	 * OUTPUTS: The plugin must set this field to the number of events it
-	 *     has written to the buffer before returning from run().
-	 *     Any initial value should be ignored by the plugin.
+	/**
+	   The number of events in this buffer.
+
+	   INPUTS: The host must set this field to the number of events contained
+	   in the data buffer before calling run(). The plugin must not change
+	   this field.
+
+	   OUTPUTS: The plugin must set this field to the number of events it has
+	   written to the buffer before returning from run(). Any initial value
+	   should be ignored by the plugin.
 	 */
 	uint32_t event_count;
 
-	/** The size of the data buffer in bytes.
-	 * This is set by the host and must not be changed by the plugin.
-	 * The host is allowed to change this between run() calls.
+	/**
+	   The size of the data buffer in bytes.
+	   This is set by the host and must not be changed by the plugin.
+	   The host is allowed to change this between run() calls.
 	 */
 	uint32_t capacity;
 
-	/** The size of the initial portion of the data buffer containing data.
-	 * INPUTS: The host must set this field to the number of bytes used
-	 *     by all events it has written to the buffer (including headers)
-	 *     before calling the plugin's run().
-	 *     The plugin must not change this field.
-	 * OUTPUTS: The plugin must set this field to the number of bytes
-	 *     used by all events it has written to the buffer (including headers)
-	 *     before returning from run().
-	 *     Any initial value should be ignored by the plugin.
+	/**
+	   The size of the initial portion of the data buffer containing data.
+
+	   INPUTS: The host must set this field to the number of bytes used
+	   by all events it has written to the buffer (including headers)
+	   before calling the plugin's run().
+	   The plugin must not change this field.
+
+	   OUTPUTS: The plugin must set this field to the number of bytes
+	   used by all events it has written to the buffer (including headers)
+	   before returning from run().
+	   Any initial value should be ignored by the plugin.
 	 */
 	uint32_t size;
-
 } LV2_Event_Buffer;
 
 
-/** Opaque pointer to host data. */
+/**
+   Opaque pointer to host data.
+*/
 typedef void* LV2_Event_Callback_Data;
 
 
-/** The data field of the LV2_Feature for this extension.
- *
- * To support this feature the host must pass an LV2_Feature struct to the
- * plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event"
- * and data pointed to an instance of this struct.
- */
+/**
+   Non-POD events feature.
+
+   To support this feature the host must pass an LV2_Feature struct to the
+   plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event"
+   and data pointed to an instance of this struct.  Note this feature
+   is not mandatory to support the event extension.
+*/
 typedef struct {
+	/**
+	   Opaque pointer to host data.
 	
-	/** Opaque pointer to host data.
-	 *
-	 * The plugin MUST pass this to any call to functions in this struct.
-	 * Otherwise, it must not be interpreted in any way.
+	   The plugin MUST pass this to any call to functions in this struct.
+	   Otherwise, it must not be interpreted in any way.
 	 */
 	LV2_Event_Callback_Data callback_data;
 	
-	/** Take a reference to a non-POD event.
-	 *
-	 * If a plugin receives an event with type 0, it means the event is a
-	 * pointer to some object in memory and not a flat sequence of bytes
-	 * in the buffer.  When receiving a non-POD event, the plugin already
-	 * has an implicit reference to the event.  If the event is stored AND
-	 * passed to an output, lv2_event_ref MUST be called on that event.
-	 * If the event is only stored OR passed through, this is not necessary
-	 * (as the plugin already has 1 implicit reference).
-	 *
-	 * @param event An event received at an input that will not be copied to
-	 *              an output or stored in any way.
-	 * @param context The calling context.  (Like event types) this is a mapped
-	 *                URI, see lv2_context.h. Simple plugin with just a run()
-	 *                method should pass 0 here (the ID of the 'standard' LV2
-	 *                run context).  The host guarantees that this function is
-	 *                realtime safe iff @a context is realtime safe.
-	 *
-	 * PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
+	/**
+	   Take a reference to a non-POD event.
+
+	   If a plugin receives an event with type 0, it means the event is a
+	   pointer to some object in memory and not a flat sequence of bytes
+	   in the buffer. When receiving a non-POD event, the plugin already
+	   has an implicit reference to the event. If the event is stored AND
+	   passed to an output, lv2_event_ref MUST be called on that event.
+	   If the event is only stored OR passed through, this is not necessary
+	   (as the plugin already has 1 implicit reference).
+
+	   @param event An event received at an input that will not be copied to
+	   an output or stored in any way.
+
+	   @param context The calling context. Like event types, this is a mapped
+	   URI, see lv2_context.h. Simple plugin with just a run() method should
+	   pass 0 here (the ID of the 'standard' LV2 run context). The host
+	   guarantees that this function is realtime safe iff @a context is
+	   realtime safe.
+
+	   PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
 	 */
 	uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data,
 	                          LV2_Event*              event);
 	
-	/** Drop a reference to a non-POD event.
-	 *
-	 * If a plugin receives an event with type 0, it means the event is a
-	 * pointer to some object in memory and not a flat sequence of bytes
-	 * in the buffer.  If the plugin does not pass the event through to
-	 * an output or store it internally somehow, it MUST call this function
-	 * on the event (more information on using non-POD events below).
-	 *
-	 * @param event An event received at an input that will not be copied to
-	 *              an output or stored in any way.
-	 * @param context The calling context.  (Like event types) this is a mapped
-	 *                URI, see lv2_context.h. Simple plugin with just a run()
-	 *                method should pass 0 here (the ID of the 'standard' LV2
-	 *                run context).  The host guarantees that this function is
-	 *                realtime safe iff @a context is realtime safe.
-	 *
-	 * PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
+	/**
+	   Drop a reference to a non-POD event.
+
+	   If a plugin receives an event with type 0, it means the event is a
+	   pointer to some object in memory and not a flat sequence of bytes
+	   in the buffer. If the plugin does not pass the event through to
+	   an output or store it internally somehow, it MUST call this function
+	   on the event (more information on using non-POD events below).
+
+	   @param event An event received at an input that will not be copied to an
+	   output or stored in any way.
+
+	   @param context The calling context. Like event types, this is a mapped
+	   URI, see lv2_context.h. Simple plugin with just a run() method should
+	   pass 0 here (the ID of the 'standard' LV2 run context). The host
+	   guarantees that this function is realtime safe iff @a context is
+	   realtime safe.
+
+	   PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS.
 	 */
 	uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data,
 	                            LV2_Event*              event);
-
 } LV2_Event_Feature;
 
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
 
-#endif // LV2_EVENT_H
-
+#endif /* LV2_EVENT_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_external_ui.h calf-master/src/calf/lv2_external_ui.h
--- calf-old/src/calf/lv2_external_ui.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_external_ui.h	2013-09-02 17:48:24.478287821 +0100
@@ -1,73 +1,81 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- *  This work is in public domain.
- *
- *  This file 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.
- *
- *  If you have questions, contact Nedko Arnaudov <nedko@arnaudov.name> or
- *  ask in #lad channel, FreeNode IRC network.
- *
- *****************************************************************************/
+/*
+  LV2 External UI extension
+  This work is in public domain.
 
-#ifndef LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED
-#define LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED
+  This file 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.
 
-/** UI extension suitable for out-of-process UIs */
-#define LV2_EXTERNAL_UI_URI "http://lv2plug.in/ns/extensions/ui#external"
+  If you have questions, contact Filipe Coelho (aka falkTX) <falktx@falktx.com>
+  or ask in #lad channel, FreeNode IRC network.
+*/
+
+/**
+   @file lv2_external_ui.h
+   C header for the LV2 External UI extension <http://kxstudio.sf.net/ns/lv2ext/external-ui>.
+*/
+
+#ifndef LV2_EXTERNAL_UI_H
+#define LV2_EXTERNAL_UI_H
+
+#include "lv2_ui.h"
+
+#define LV2_EXTERNAL_UI_URI     "http://kxstudio.sf.net/ns/lv2ext/external-ui"
+#define LV2_EXTERNAL_UI_PREFIX  LV2_EXTERNAL_UI_URI "#"
+
+#define LV2_EXTERNAL_UI__Host   LV2_EXTERNAL_UI_PREFIX "Host"
+#define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget"
+
+/** This extension used to be defined by a lv2plug.in URI */
+#define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-#if 0
-} /* Adjust editor indent */
-#endif
 
 /**
- * When LV2_EXTERNAL_UI_URI UI is instantiated, the returned
- * LV2UI_Widget handle must be cast to pointer to struct lv2_external_ui.
+ * When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned
+ * LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget.
  * UI is created in invisible state.
  */
-struct lv2_external_ui
-{
+typedef struct _LV2_External_UI_Widget {
   /**
    * Host calls this function regulary. UI library implementing the
    * callback may do IPC or redraw the UI.
    *
    * @param _this_ the UI context
    */
-  void (* run)(struct lv2_external_ui * _this_);
+  void (*run)(struct _LV2_External_UI_Widget * _this_);
 
   /**
    * Host calls this function to make the plugin UI visible.
    *
    * @param _this_ the UI context
    */
-  void (* show)(struct lv2_external_ui * _this_);
+  void (*show)(struct _LV2_External_UI_Widget * _this_);
 
   /**
    * Host calls this function to make the plugin UI invisible again.
    *
    * @param _this_ the UI context
    */
-  void (* hide)(struct lv2_external_ui * _this_);
-};
+  void (*hide)(struct _LV2_External_UI_Widget * _this_);
+
+} LV2_External_UI_Widget;
 
 #define LV2_EXTERNAL_UI_RUN(ptr) (ptr)->run(ptr)
 #define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr)
 #define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr)
 
 /**
- * On UI instantiation, host must supply LV2_EXTERNAL_UI_URI
- * feature. LV2_Feature::data must be pointer to struct lv2_external_ui_host. */
-struct lv2_external_ui_host
-{
+ * On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature.
+ * LV2_Feature::data must be pointer to LV2_External_UI_Host.
+ */
+typedef struct _LV2_External_UI_Host {
   /**
    * Callback that plugin UI will call
    * when UI (GUI window) is closed by user.
-   * This callback wil; be called during execution of lv2_external_ui::run()
+   * This callback will be called during execution of LV2_External_UI_Widget::run()
    * (i.e. not from background thread).
    *
    * After this callback is called, UI is defunct. Host must call
@@ -77,7 +85,7 @@
    * @param controller Host context associated with plugin UI, as
    * supplied to LV2UI_Descriptor::instantiate()
    */
-  void (* ui_closed)(LV2UI_Controller controller);
+  void (*ui_closed)(LV2UI_Controller controller);
 
   /**
    * Optional (may be NULL) "user friendly" identifier which the UI
@@ -89,13 +97,11 @@
    * LV2UI_Descriptor::instantiate()
    */
   const char * plugin_human_id;
-};
 
-#if 0
-{ /* Adjust editor indent */
-#endif
+} LV2_External_UI_Host;
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
-#endif /* #ifndef LV2_EXTERNAL_UI_H__5AFE09A5_0FB7_47AF_924E_2AF0F8DE8873__INCLUDED */
+#endif /* LV2_EXTERNAL_UI_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_instance_access.h calf-master/src/calf/lv2_instance_access.h
--- calf-old/src/calf/lv2_instance_access.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/lv2_instance_access.h	2013-03-29 07:07:57.000000000 +0000
@@ -0,0 +1,37 @@
+/*
+  LV2 Instance Access Extension
+  Copyright 2008-2012 David Robillard <http://drobilla.net>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef LV2_INSTANCE_ACCESS_H
+#define LV2_INSTANCE_ACCESS_H
+
+#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access"
+
+/**
+   @file instance-access.h
+   C header for the LV2 Instance Access extension
+   <http://lv2plug.in/ns/ext/instance-access>.
+ 
+   This extension defines a method for (e.g.) plugin UIs to get a direct
+   handle to an LV2 plugin instance (LV2_Handle), if possible.
+ 
+   To support this feature the host must pass an LV2_Feature struct to the
+   UI instantiate method with URI "http://lv2plug.in/ns/ext/instance-access"
+   and data pointed directly to the LV2_Handle of the plugin instance.
+*/
+
+#endif  /* LV2_INSTANCE_ACCESS_H */
+
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_programs.h calf-master/src/calf/lv2_programs.h
--- calf-old/src/calf/lv2_programs.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/lv2_programs.h	2013-09-02 17:48:17.068380457 +0100
@@ -0,0 +1,174 @@
+/*
+  LV2 Programs Extension
+  Copyright 2012 Filipe Coelho <falktx@falktx.com>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+   @file lv2_programs.h
+   C header for the LV2 programs extension <http://kxstudio.sf.net/ns/lv2ext/programs>.
+*/
+
+#ifndef LV2_PROGRAMS_H
+#define LV2_PROGRAMS_H
+
+#include "lv2.h"
+#include "lv2_ui.h"
+
+#define LV2_PROGRAMS_URI    "http://kxstudio.sf.net/ns/lv2ext/programs"
+#define LV2_PROGRAMS_PREFIX LV2_PROGRAMS_URI "#"
+
+#define LV2_PROGRAMS__Host        LV2_PROGRAMS_PREFIX "Host"
+#define LV2_PROGRAMS__Interface   LV2_PROGRAMS_PREFIX "Interface"
+#define LV2_PROGRAMS__UIInterface LV2_PROGRAMS_PREFIX "UIInterface"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* LV2_Programs_Handle;
+
+typedef struct _LV2_Program_Descriptor {
+
+    /** Bank number for this program. Note that this extension does not
+        support MIDI-style separation of bank LSB and MSB values. There is
+        no restriction on the set of available banks: the numbers do not
+        need to be contiguous, there does not need to be a bank 0, etc. */
+    uint32_t bank;
+
+    /** Program number (unique within its bank) for this program. There is
+        no restriction on the set of available programs: the numbers do not
+        need to be contiguous, there does not need to be a program 0, etc. */
+    uint32_t program;
+
+    /** Name of the program. */
+    const char * name;
+
+} LV2_Program_Descriptor;
+
+/**
+   Programs extension, plugin data.
+
+   When the plugin's extension_data is called with argument LV2_PROGRAMS__Interface,
+   the plugin MUST return an LV2_Programs_Instance structure, which remains valid
+   for the lifetime of the plugin.
+*/
+typedef struct _LV2_Programs_Interface {
+    /**
+     * get_program()
+     *
+     * This member is a function pointer that provides a description
+     * of a program (named preset sound) available on this plugin.
+     *
+     * The index argument is an index into the plugin's list of
+     * programs, not a program number as represented by the Program
+     * field of the LV2_Program_Descriptor. (This distinction is
+     * needed to support plugins that use non-contiguous program or
+     * bank numbers.)
+     *
+     * This function returns a LV2_Program_Descriptor pointer that is
+     * guaranteed to be valid only until the next call to get_program
+     * or deactivate, on the same plugin instance. This function must
+     * return NULL if passed an index argument out of range, so that
+     * the host can use it to query the number of programs as well as
+     * their properties.
+     */
+    const LV2_Program_Descriptor *(*get_program)(LV2_Handle handle,
+                                                 uint32_t index);
+
+    /**
+     * select_program()
+     *
+     * This member is a function pointer that selects a new program
+     * for this plugin. The program change should take effect
+     * immediately at the start of the next run() call. (This
+     * means that a host providing the capability of changing programs
+     * between any two notes on a track must vary the block size so as
+     * to place the program change at the right place. A host that
+     * wanted to avoid this would probably just instantiate a plugin
+     * for each program.)
+     *
+     * Plugins should ignore a select_program() call with an invalid
+     * bank or program.
+     *
+     * A plugin is not required to select any particular default
+     * program on activate(): it's the host's duty to set a program
+     * explicitly.
+     *
+     * A plugin is permitted to re-write the values of its input
+     * control ports when select_program is called. The host should
+     * re-read the input control port values and update its own
+     * records appropriately. (This is the only circumstance in which
+     * a LV2 plugin is allowed to modify its own control-input ports.)
+     */
+    void (*select_program)(LV2_Handle handle,
+                           uint32_t bank,
+                           uint32_t program);
+
+} LV2_Programs_Interface;
+
+/**
+   Programs extension, UI data.
+
+   When the UI's extension_data is called with argument LV2_PROGRAMS__UIInterface,
+   the UI MUST return an LV2_Programs_UI_Interface structure, which remains valid
+   for the lifetime of the UI.
+*/
+typedef struct _LV2_Programs_UI_Interface {
+    /**
+     * select_program()
+     *
+     * This is exactly the same as select_program in LV2_Programs_Instance,
+     * but this struct relates to the UI instead of the plugin.
+     *
+     * When called, UIs should update their state to match the selected program.
+     */
+    void (*select_program)(LV2UI_Handle handle,
+                           uint32_t bank,
+                           uint32_t program);
+
+} LV2_Programs_UI_Interface;
+
+/**
+    Feature data for LV2_PROGRAMS__Host.
+*/
+typedef struct _LV2_Programs_Host {
+    /**
+     *  Opaque host data.
+     */
+    LV2_Programs_Handle handle;
+
+    /**
+     * program_changed()
+     *
+     * Tell the host to reload a plugin's program.
+     * Parameter handle MUST be the 'handle' member of this struct.
+     * Parameter index is program index to change.
+     * When index is -1, host should reload all the programs.
+     *
+     * The plugin MUST NEVER call this function on a RT context or during run().
+     *
+     * NOTE: This call is to inform the host about a program's bank, program or name change.
+     *       It DOES NOT change the current selected program.
+     */
+    void (*program_changed)(LV2_Programs_Handle handle,
+                            int32_t index);
+
+} LV2_Programs_Host;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_PROGRAMS_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_progress.h calf-master/src/calf/lv2_progress.h
--- calf-old/src/calf/lv2_progress.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_progress.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,85 +0,0 @@
-/* -*- Mode: C ; c-basic-offset: 2 -*- */
-/*****************************************************************************
- *
- *  This work is in public domain.
- *
- *  This file 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.
- *
- *  Author of this extension is Nedko Arnaudov <nedko@arnaudov.name>
- *
- *  Several people helped improving the extension:
- *   * Krzysztof Foltman <wdev@foltman.com>
- *   * Dave Robillard <dave@drobilla.net>
- *
- *  If you have questions ask in the #lv2 or #lad channel,
- *  FreeNode IRC network or use the lv2 mailing list.
- *
- *****************************************************************************/
-
-#ifndef LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED
-#define LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED
-
-/**
- * @file lv2_progress.h
- * @brief LV2 progress notification extension definition
- *
- * @par Purpose and scope
- * The purpose of this extension is to prevent thread (often the main one)
- * freeze for plugins doing intensive computations during instantiation.
- * Host may want to display progress bar of some sort and if it is using
- * GUI toolkit event loop, to dispatch queued events.
- *
- * @par
- * Using this extension for reporting progress of other lengthy operations
- * is possible and encouraged but not subject of this extension alone.
- * It is probably not good idea to call progress callback from plugin created
- * thread nor it is good idea to call it from a LV2 audio class function.
- * Any extension that wants to work in conjuction with progress extension
- * must define thread context semantics for calling the progress callback.
- *
- * @par Plugin instantiation progress usage
- * Plugin calls the host provided callback on regular basis during
- * instantiation. One second between calls is good target. Everything between
- * half second and two seconds should provide enough motion so user does
- * not get "the thing froze" impression.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#if 0
-} /* Adjust editor indent */
-#endif
-
-/** URI for the plugin progress feature */
-#define LV2_PROGRESS_URI "http://lv2plug.in/ns/dev/progress"
-
-/** @brief host feature structure */
-typedef struct _LV2_Progress
-{
-  /** to be supplied as first parameter of progress() callback  */
-  void * context;
-
-  /**
-   * This function is called by plugin to notify host about progress of a
-   * lengthy operation.
-   *
-   * @param context Host context
-   * @param progress Progress, from 0.0 to 100.0
-   * @param message Optional (may be NULL) string describing current operation.
-   * If called once with non-NULL message, subsequent calls will NULL message
-   * mean that host will reuse the previous message.
-   */
-  void (*progress)(void * context, float progress, const char * message);
-} LV2_Progress;
-
-#if 0
-{ /* Adjust editor indent */
-#endif
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* #ifndef LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_state.h calf-master/src/calf/lv2_state.h
--- calf-old/src/calf/lv2_state.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_state.h	2013-03-29 07:11:22.000000000 +0000
@@ -26,13 +26,14 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+#include "lv2.h"
 
 #define LV2_STATE_URI    "http://lv2plug.in/ns/ext/state"
 #define LV2_STATE_PREFIX LV2_STATE_URI "#"
 
 #define LV2_STATE__State     LV2_STATE_PREFIX "State"
 #define LV2_STATE__interface LV2_STATE_PREFIX "interface"
+#define LV2_STATE__loadDefaultState LV2_STATE_PREFIX "loadDefaultState"
 #define LV2_STATE__makePath  LV2_STATE_PREFIX "makePath"
 #define LV2_STATE__mapPath   LV2_STATE_PREFIX "mapPath"
 #define LV2_STATE__state     LV2_STATE_PREFIX "state"
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_ui.h calf-master/src/calf/lv2_ui.h
--- calf-old/src/calf/lv2_ui.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_ui.h	2013-03-29 07:11:15.000000000 +0000
@@ -1,253 +1,164 @@
-/************************************************************************
- *
- * In-process UI extension for LV2
- *
- * Copyright (C) 2006-2008 Lars Luthman <lars.luthman@gmail.com>
- * 
- * Based on lv2.h, which was
- *
- * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, 
- *                         Stefan Westerfeld
- * Copyright (C) 2006 Steve Harris, Dave Robillard.
- *
- * This header is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2.1 of the License,
- * or (at your option) any later version.
- *
- * This header 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
- * USA.
- *
- ***********************************************************************/
-
-/** @file
-    This extension defines an interface that can be used in LV2 plugins and
-    hosts to create UIs for plugins. The UIs are plugins that reside in
-    shared object files in an LV2 bundle and are referenced in the RDF data
-    using the triples (Turtle shown)
-<pre>    
-    @@prefix uiext: <http://lv2plug.in/ns/extensions/ui#> .
-    <http://my.plugin>    uiext:ui     <http://my.pluginui> .
-    <http://my.plugin>    a            uiext:GtkUI .
-    <http://my.pluginui>  uiext:binary <myui.so> .
-</pre>
-    where <http://my.plugin> is the URI of the plugin, <http://my.pluginui> is
-    the URI of the plugin UI and <myui.so> is the relative URI to the shared 
-    object file. While it is possible to have the plugin UI and the plugin in 
-    the same shared object file it is probably a good idea to keep them 
-    separate so that hosts that don't want UIs don't have to load the UI code.
-    A UI MUST specify its class in the RDF data. In this case the class is
-    uiext:GtkUI, which is the only class defined by this extension.
-    
-    (Note: the prefix above is used throughout this file for the same URI)
-    
-    It's entirely possible to have multiple UIs for the same plugin, or to have
-    the UI for a plugin in a different bundle from the actual plugin - this
-    way people other than the plugin author can write plugin UIs independently
-    without editing the original plugin bundle.
-    
-    Note that the process that loads the shared object file containing the UI
-    code and the process that loads the shared object file containing the 
-    actual plugin implementation does not have to be the same. There are many
-    valid reasons for having the plugin and the UI in different processes, or
-    even on different machines. This means that you can _not_ use singletons
-    and global variables and expect them to refer to the same objects in the
-    UI and the actual plugin. The function callback interface defined in this
-    header is all you can expect to work.
-    
-    Since the LV2 specification itself allows for extensions that may add 
-    new types of data and configuration parameters that plugin authors may 
-    want to control with a UI, this extension allows for meta-extensions that
-    can extend the interface between the UI and the host. These extensions
-    mirror the extensions used for plugins - there are required and optional
-    "features" that you declare in the RDF data for the UI as
-<pre>    
-    <http://my.pluginui> uiext:requiredFeature <http://my.feature> .
-    <http://my.pluginui> uiext:optionalFeature <http://my.feature> .
-</pre>
-    These predicates have the same semantics as lv2:requiredFeature and 
-    lv2:optionalFeature - if a UI is declaring a feature as required, the
-    host is NOT allowed to load it unless it supports that feature, and if it
-    does support a feature (required or optional) it MUST pass that feature's
-    URI and any additional data (specified by the meta-extension that defines
-    the feature) to the UI's instantiate() function.
-    
-    These features may be used to specify how to pass data between the UI
-    and the plugin port buffers - see LV2UI_Write_Function for details.
-    
-    There are two features defined in this extension that hosts may want to
-    implement:
-<pre>
-    uiext:makeResident
-    uiext:makeSONameResident
-</pre>
-    If the first feature, @c uiext:makeResident, is required by a UI the host
-    MUST never unload the shared library containing the UI implementation 
-    during the lifetime of the host process (e.g. never calling dlclose() on
-    Linux). This feature may be needed by e.g. a uiext:GtkUI that registers
-    its own Glib types using g_type_register_static() - if it gets unloaded
-    and then loaded again the type registration will break, since there is no 
-    way to unregister the types when the library is unloaded.
-
-    The second feature, @c uiext:makeSONameResident, is ELF specific
-    and if it is required by an UI the UI should also list a number of 
-    SO names (shared object names) for libraries that the UI shared object
-    depends on and that may not be unloaded during the lifetime of the host
-    process, using the predicate @c uiext:residentSONames, like this:
-<pre>
-    <http://my.pluginui> uiext:residentSONames "libgtkmm-2.4.so.1", "libfoo.so.0"
-</pre>
-    The host MUST then make sure that the shared libraries with the given ELF
-    SO names are not unloaded when the plugin UI is, but stay loaded during
-    the entire lifetime of the host process. On Linux this can be accomplished
-    by calling dlopen() on the shared library file with that SO name and never
-    calling a matching dlclose(). However, if a plugin UI requires the 
-    @c uiext:makeSONameResident feature, it MUST always be safe for the host to
-    just never unload the shared object containing the UI implementation, i.e.
-    act as if the UI required the @c uiext:makeResident feature instead. Thus
-    the host only needs to find the shared library files corresponding to the
-    given SO names if it wants to save RAM by unloading the UI shared object 
-    file when it is no longer needed.
+/*
+  LV2 UI Extension
+  Copyright 2009-2012 David Robillard <d@drobilla.net>
+  Copyright 2006-2011 Lars Luthman <lars.luthman@gmail.com>
     
-    UIs written to this specification do not need to be threadsafe - the 
-    functions defined below may only be called in the same thread as the UI
-    main loop is running in.
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
     
-    Note that this UI extension is NOT a lv2:Feature. There is no way for a 
-    plugin to know whether the host that loads it supports UIs or not, and 
-    the plugin must ALWAYS work without the UI (although it may be rather 
-    useless unless it has been configured using the UI in a previous session).
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
     
-    A UI does not have to be a graphical widget, it could just as well be a
-    server listening for OSC input or an interface to some sort of hardware
-    device, depending on the RDF class of the UI.
+/**
+   @file ui.h
+   C header for the LV2 UI extension <http://lv2plug.in/ns/extensions/ui>.
 */
 
 #ifndef LV2_UI_H
 #define LV2_UI_H
 
-#include <lv2.h>
+#include <stdint.h>
+
+#include "lv2.h"
 
 #define LV2_UI_URI "http://lv2plug.in/ns/extensions/ui"
+#define LV2_UI_PREFIX LV2_UI_URI "#"
+
+#define LV2_UI__CocoaUI          LV2_UI_PREFIX "CocoaUI"
+#define LV2_UI__Gtk3UI           LV2_UI_PREFIX "Gtk3UI"
+#define LV2_UI__GtkUI            LV2_UI_PREFIX "GtkUI"
+#define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification"
+#define LV2_UI__Qt4UI            LV2_UI_PREFIX "Qt4UI"
+#define LV2_UI__UI               LV2_UI_PREFIX "UI"
+#define LV2_UI__WindowsUI        LV2_UI_PREFIX "WindowsUI"
+#define LV2_UI__X11UI            LV2_UI_PREFIX "X11UI"
+#define LV2_UI__binary           LV2_UI_PREFIX "binary"
+#define LV2_UI__fixedSize        LV2_UI_PREFIX "fixedSize"
+#define LV2_UI__idleInterface    LV2_UI_PREFIX "idleInterface"
+#define LV2_UI__noUserResize     LV2_UI_PREFIX "noUserResize"
+#define LV2_UI__notifyType       LV2_UI_PREFIX "notifyType"
+#define LV2_UI__parent           LV2_UI_PREFIX "parent"
+#define LV2_UI__plugin           LV2_UI_PREFIX "plugin"
+#define LV2_UI__portIndex        LV2_UI_PREFIX "portIndex"
+#define LV2_UI__portMap          LV2_UI_PREFIX "portMap"
+#define LV2_UI__portNotification LV2_UI_PREFIX "portNotification"
+#define LV2_UI__portSubscribe    LV2_UI_PREFIX "portSubscribe"
+#define LV2_UI__resize           LV2_UI_PREFIX "resize"
+#define LV2_UI__touch            LV2_UI_PREFIX "touch"
+#define LV2_UI__ui               LV2_UI_PREFIX "ui"
 
+/**
+   The index returned by LV2_UI_Port_Port::port_index() for unknown ports.
+*/
+#define LV2UI_INVALID_PORT_INDEX ((uint32_t)-1)
 
 #ifdef __cplusplus
 extern "C" {
+#else
+#    include <stdbool.h>
 #endif
 
+/**
+   A pointer to some widget or other type of UI handle.
 
-/** A pointer to some widget or other type of UI handle.
-    The actual type is defined by the type URI of the UI, e.g. if 
-    "<http://example.org/someui> a uiext:GtkUI", this is a pointer
-    to a GtkWidget compatible with GTK+ 2.0 and the UI can expect the GTK+
-    main loop to be running during the entire lifetime of all instances of that
-    UI. All the functionality provided by this extension is toolkit 
-    independent, the host only needs to pass the necessary callbacks and 
-    display the widget, if possible. Plugins may have several UIs, in various
-    toolkits, but uiext:GtkUI is the only type that is defined in this 
-    extension. */
+   The actual type is defined by the type of the UI.
+*/
 typedef void* LV2UI_Widget;
 
+/**
+   A pointer to an instance of a UI.
 
-/** A pointer to some host data required to instantiate a UI.
-    Like the type of the widget, the actual type of this pointer is defined by
-    the type URI of the UI.  Hosts can use this to pass toolkit specific data
-    to a UI it needs to instantiate (type map, drawing context, etc). For the
-    uiext:GtkUI type this should be NULL. */
-typedef void* LV2UI_Host_Data;
-        
-  
-/** This handle indicates a particular instance of a UI.
-    It is valid to compare this to NULL (0 for C++) but otherwise the 
-    host MUST not attempt to interpret it. The UI plugin may use it to 
-    reference internal instance data. */
+   It is valid to compare this to NULL (0 for C++) but otherwise the host MUST
+   not attempt to interpret it.  The UI plugin may use it to reference internal
+   instance data.
+*/
 typedef void* LV2UI_Handle;
 
+/**
+   A pointer to a controller provided by the host.
 
-/** This handle indicates a particular plugin instance, provided by the host.
-    It is valid to compare this to NULL (0 for C++) but otherwise the 
-    UI plugin MUST not attempt to interpret it. The host may use it to 
-    reference internal plugin instance data. */
+   It is valid to compare this to NULL (0 for C++) but otherwise the UI plugin
+   MUST NOT attempt to interpret it.  The host may use it to reference internal
+   instance data.
+*/
 typedef void* LV2UI_Controller;
 
+/**
+   A pointer to opaque data for a feature.
+*/
+typedef void* LV2UI_Feature_Handle;
 
-/** This is the type of the host-provided function that the UI can use to
-    send data to a plugin's input ports. The @c buffer parameter must point
-    to a block of data, @c buffer_size bytes large. The contents of this buffer
-    will depend on the class of the port it's being sent to, and the transfer
-    mechanism specified for that port class. 
-    
-    Transfer mechanisms are Features and may be defined in meta-extensions. 
-    They specify how to translate the data buffers passed to this function 
-    to input data for the plugin ports. If a UI wishes to write data to an 
-    input port, it must list a transfer mechanism Feature for that port's 
-    class as an optional or required feature (depending on whether the UI 
-    will work without being able to write to that port or not). The only 
-    exception is ports of the class lv2:ControlPort, for which @c buffer_size
-    should always be 4 and the buffer should always contain a single IEEE-754
-    float.
+/**
+   The type of the host-provided function that the UI can use to
+   send data to a plugin's input ports.
     
-    The UI MUST NOT try to write to a port for which there is no specified
-    transfer mechanism, or to an output port. The UI is responsible for 
-    allocating the buffer and deallocating it after the call. A function 
-    pointer of this type will be provided to the UI by the host in the 
-    instantiate() function. 
+   The @p buffer parameter must point to a block of data, @c buffer_size bytes
+   large.  The format of this data and how the host should use it is defined by
+   the @p port_protocol.  This buffer is owned by the UI and is only valid for
+   the duration of this call.
 
-    An UI may list multiple transfer mechanisms for the same port type.
-    To tell the host which mechanism is to be used, it passes an integer ID
-    for the mechanism in the @c format parameter. This ID is retrieved from
-    a URI-to-integer mapping function provided by the host, using the URI Map 
-    feature <http://lv2plug.in/ns/ext/uri-map> with the map URI 
-    "http://lv2plug.in/ns/extensions/ui". Thus a UI that requires transfer
-    mechanism features MUST also require the URI Map feature. A @c format
-    value of 0 is a special case that always means that the buffer should
-    be interpreted as a single IEEE-754 float, and may only be written to 
-    a control port.
+   The @p port_protocol parameter should either be 0 or the URID for a
+   ui:PortProtocol.  If it is 0, the protocol is implicitly ui:floatProtocol,
+   the port must be an lv2:ControlPort input, @c buffer must point to a single
+   float value, and @c buffer_size must be sizeof(float).
     
-    An UI MUST NOT pass a @c format parameter value (except 0) that has not
-    been returned by the host-provided URI mapping function for a 
-    host-supported transfer mechanism feature URI.
+   The UI SHOULD NOT use a PortProtocol not supported by the host (i.e. one not
+   passed by the host as a feature), but the host MUST gracefully ignore any
+   port_protocol it does not understand.
 */
 typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller,
                                      uint32_t         port_index,
                                      uint32_t         buffer_size,
-                                     uint32_t         format,
+                                     uint32_t         port_protocol,
                                      const void*      buffer);
 
+/**
+   The implementation of a UI.
 
-/** */
+   A pointer to an object of this type is returned by the lv2ui_descriptor()
+   function.
+*/
 typedef struct _LV2UI_Descriptor {
-  
-  /** The URI for this UI (not for the plugin it controls). */
+	/**
+	   The URI for this UI (not for the plugin it controls).
+	*/
   const char* URI;
   
-  /** Create a new UI object and return a handle to it. This function works
+	/**
+	   Create a new UI object and return a handle to it.  This function works
       similarly to the instantiate() member in LV2_Descriptor.
       
       @param descriptor The descriptor for the UI that you want to instantiate.
+
       @param plugin_uri The URI of the plugin that this UI will control.
+
       @param bundle_path The path to the bundle containing the RDF data file
-                         that references this shared object file, including the
-                         trailing '/'.
-      @param write_function A function provided by the host that the UI can
-                            use to send data to the plugin's input ports.
+	   that references this shared object file, including the trailing '/'.
+
+	   @param write_function A function provided by the host that the UI can use
+	   to send data to the plugin's input ports.
+
       @param controller A handle for the plugin instance that should be passed
-                        as the first parameter of @c write_function.
-      @param widget     A pointer to an LV2UI_Widget. The UI will write a
-                        widget pointer to this location (what type of widget 
-                        depends on the RDF class of the UI) that will be the
-                        main UI widget.
-      @param features   An array of LV2_Feature pointers. The host must pass
-                        all feature URIs that it and the plugin supports and any
-                        additional data, just like in the LV2 plugin 
-                        instantiate() function.
+	   as the first parameter of @p write_function.
+
+	   @param widget A pointer to an LV2UI_Widget.  The UI will write a widget
+	   pointer to this location (what type of widget depends on the RDF class of
+	   the UI) that will be the main UI widget.
+
+	   @param features An array of LV2_Feature pointers.  The host must pass all
+	   feature URIs that it and the UI supports and any additional data, just
+	   like in the LV2 plugin instantiate() function.  Note that UI features and
+	   plugin features are NOT necessarily the same, they just share the same
+	   data structure - this will probably not be the same array as the one the
+	   plugin host passes to a plugin.
+
   */
   LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor,
                               const char*                     plugin_uri,
@@ -258,55 +169,34 @@
                               const LV2_Feature* const*       features);
 
   
-  /** Destroy the UI object and the associated widget. The host must not try
+	/**
+	   Destroy the UI object and the associated widget. The host must not try
       to access the widget after calling this function.
    */
   void (*cleanup)(LV2UI_Handle ui);
   
-  /** Tell the UI that something interesting has happened at a plugin port.
+	/**
+	   Tell the UI that something interesting has happened at a plugin port.
+
       What is interesting and how it is written to the buffer passed to this
-      function is defined by  transfer mechanism extensions (see 
-      LV2UI_Write_Function). The only exception is ports of the class 
-      lv2:ControlPort, for which this function should be called
-      when the port value changes (it does not have to be called for every 
-      single change if the host's UI thread has problems keeping up with 
-      the thread the plugin is running in), @c buffer_size should be 4 and the 
-      buffer should contain a single IEEE-754 float. In this case the @c format
-      parameter should be 0.
+	   function is defined by the @p format parameter, which has the same
+	   meaning as in LV2UI_Write_Function.  The only exception is ports of the
+	   class lv2:ControlPort, for which this function should be called when the
+	   port value changes (it does not have to be called for every single change
+	   if the host's UI thread has problems keeping up with the thread the
+	   plugin is running in), @p buffer_size should be 4, the buffer should
+	   contain a single IEEE-754 float, and @p format should be 0.
       
       By default, the host should only call this function for input ports of
-      the lv2:ControlPort class. However, the default setting can be modified
-      by using the following URIs in the UI's RDF data:
-      <pre>
-      uiext:portNotification
-      uiext:noPortNotification
-      uiext:plugin
-      uiext:portIndex
-      </pre>
-      For example, if you want the UI with uri 
-      <code><http://my.pluginui></code> for the plugin with URI 
-      <code><http://my.plugin></code> to get notified when the value of the 
-      output control port with index 4 changes, you would use the following 
-      in the RDF for your UI:
-      <pre>
-      <http://my.pluginui> uiext:portNotification [ uiext:plugin <http://my.plugin> ;
-                                                      uiext:portIndex 4 ] .
-      </pre>
-      and similarly with <code>uiext:noPortNotification</code> if you wanted
-      to prevent notifications for a port for which it would be on by default 
-      otherwise. The UI is not allowed to request notifications for ports
-      for which no transfer mechanism is specified, if it does it should be
-      considered broken and the host should not load it.
+	   the lv2:ControlPort class.  However, this can be modified by using
+	   ui:portNotification in the UI data, or the ui:portSubscribe feature.
       
-      The @c buffer is only valid during the time of this function call, so if 
+	   The @p buffer is only valid during the time of this function call, so if
       the UI wants to keep it for later use it has to copy the contents to an
       internal buffer.
       
       This member may be set to NULL if the UI is not interested in any 
       port events.
-      
-      The @c format parameter is used to specify the format of the buffer 
-      contents, with the same restrictions as in LV2_Write_Function.
   */
   void (*port_event)(LV2UI_Handle ui,
                      uint32_t     port_index,
@@ -314,44 +204,204 @@
                      uint32_t     format,
                      const void*  buffer);
   
-  /** Returns a data structure associated with an extension URI, for example
-      a struct containing additional function pointers. Avoid returning
-      function pointers directly since standard C++ has no valid way of
-      casting a void* to a function pointer. This member may be set to NULL
-      if the UI is not interested in supporting any extensions. This is similar
-      to the extension_data() member in LV2_Descriptor.
+	/**
+	   Return a data structure associated with an extension URI, for example
+	   a struct containing additional function pointers.
+
+	   Avoid returning function pointers directly since standard C/C++ has no
+	   valid way of casting a void* to a function pointer. This member may be set
+	   to NULL if the UI is not interested in supporting any extensions. This is
+	   similar to the extension_data() member in LV2_Descriptor.
   */
   const void* (*extension_data)(const char*  uri);
-
 } LV2UI_Descriptor;
 
+/**
+   UI Resize Feature (LV2_UI__resize)
+
+   This structure may be used in two ways: as a feature passed by the host via
+   LV2UI_Descriptor::instantiate(), or as extension data provided by a UI via
+   LV2UI_Descriptor::extension_data()).
+*/
+typedef struct _LV2UI_Resize {
+	/**
+	   Pointer to opaque data which must be passed to ui_resize().
+	*/
+	LV2UI_Feature_Handle handle;
+
+	/**
+	   Request or advertise a size change.
 
+	   When this struct is provided by the host, the UI may call this
+	   function to inform the host about the size of the UI.
 
-/** A plugin UI programmer must include a function called "lv2ui_descriptor"
-    with the following function prototype within the shared object
-    file. This function will have C-style linkage (if you are using
-    C++ this is taken care of by the 'extern "C"' clause at the top of
-    the file). This function will be accessed by the UI host using the 
-    @c dlsym() function and called to get a LV2UI_UIDescriptor for the
-    wanted plugin.
+	   When this struct is provided by the UI, the host may call this
+	   function to notify the UI that it should change its size accordingly.
+
+	   @return 0 on success.
+	*/
+	int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height);
+} LV2UI_Resize;
+
+/**
+   Port Map Feature (LV2_UI__portMap).
+
+   This feature can be used by the UI to get the index for a port with the
+   given symbol.  This makes it possible to implement and distribute a UI
+   separately from the plugin (since symbol is a guaranteed stable port
+   identifier while index is not).
+*/
+typedef struct _LV2UI_Port_Map {
+	/**
+	   Pointer to opaque data which must be passed to ui_resize().
+	*/
+	LV2UI_Feature_Handle handle;
+
+	/**
+	   Get the index for the port with the given @p symbol.
+
+	   @return The index of the port, or LV2_UI_INVALID_PORT_INDEX if no such
+	   port is found.
+	*/
+	uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol);
+} LV2UI_Port_Map;
+
+/**
+   Port subscription feature (LV2_UI__portSubscribe);
+*/
+typedef struct _LV2UI_Port_Subscribe {
+	/**
+	   Pointer to opaque data which must be passed to ui_resize().
+	*/
+	LV2UI_Feature_Handle handle;
+
+	/**
+	   Subscribe to updates for a port.
+
+	   This means that the host will call the UI's port_event() function when
+	   the port value changes (as defined by protocol).
+
+	   Calling this function with the same @p port_index and @p port_protocol
+	   as an already active subscription has no effect.
+
+	   @param handle The handle field of this struct.
+	   @param port_index The index of the port.
+	   @param port_protocol The URID of the ui:PortProtocol.
+	   @param features Features for this subscription.
+	   @return 0 on success.
+	*/
+	uint32_t (*subscribe)(LV2UI_Feature_Handle      handle,
+	                      uint32_t                  port_index,
+	                      uint32_t                  port_protocol,
+	                      const LV2_Feature* const* features);
+
+	/**
+	   Unsubscribe from updates for a port.
+
+	   This means that the host will cease calling calling port_event() when
+	   the port value changes.
+
+	   Calling this function with a @p port_index and @p port_protocol that
+	   does not refer to an active port subscription has no effect.
+
+	   @param handle The handle field of this struct.
+	   @param port_index The index of the port.
+	   @param port_protocol The URID of the ui:PortProtocol.
+	   @param features Features for this subscription.
+	   @return 0 on success.
+	*/
+	uint32_t (*unsubscribe)(LV2UI_Feature_Handle      handle,
+	                        uint32_t                  port_index,
+	                        uint32_t                  port_protocol,
+	                        const LV2_Feature* const* features);
+} LV2UI_Port_Subscribe;
+
+/**
+   A feature to notify the host the user has grabbed a UI control.
+*/
+typedef struct _LV2UI_Touch {
+	/**
+	   Pointer to opaque data which must be passed to ui_resize().
+	*/
+	LV2UI_Feature_Handle handle;
+
+	/**
+	   Notify the host that a control has been grabbed or released.
+
+	   @param handle The handle field of this struct.
+	   @param port_index The index of the port associated with the control.
+	   @param grabbed If true, the control has been grabbed, otherwise the
+	   control has been released.
+	*/
+	void (*touch)(LV2UI_Feature_Handle handle,
+	              uint32_t             port_index,
+	              bool                 grabbed);
+} LV2UI_Touch;
+
+/**
+   UI Idle Feature (LV2_UI__idle)
+
+   This feature is an addition to the UI API that provides a callback for the
+   host to call rapidly, e.g. to drive the idle callback of a toolkit.
+*/
+typedef struct _LV2UI_Idle_Interface {
+	/**
+	   Run a single iteration of the UI's idle loop.
+
+	   This will be called "frequently" in the UI thread at a rate appropriate
+	   for a toolkit main loop.  There are no precise timing guarantees.
+
+	   @return 0 on success, or anything else to stop being called.
+	*/
+	int (*idle)(LV2UI_Handle ui);
+} LV2UI_Idle_Interface;
+
+/**
+   Peak data for a slice of time, the update format for ui:peakProtocol.
+*/
+typedef struct _LV2UI_Peak_Data {
+	/**
+	   The start of the measurement period.  This is just a running counter
+	   that is only meaningful in comparison to previous values and must not be
+	   interpreted as an absolute time.
+	*/
+	uint32_t period_start;
+
+	/**
+	   The size of the measurement period, in the same units as period_start.
+	*/
+	uint32_t period_size;
+
+	/**
+	   The peak value for the measurement period. This should be the maximal
+	   value for abs(sample) over all the samples in the period.
+	*/
+	float peak;
+} LV2UI_Peak_Data;
+
+/**
+   A plugin UI programmer must include a function called "lv2ui_descriptor"
+   with the following function prototype within the shared object file.  This
+   function will have C-style linkage (if you are using C++ this is taken care
+   of by the 'extern "C"' clause at the top of the file).  This function is
+   loaded from the library by the UI host and called to get a
+   LV2UI_Descriptor for the wanted plugin.
     
     Just like lv2_descriptor(), this function takes an index parameter. The
     index should only be used for enumeration and not as any sort of ID number -
     the host should just iterate from 0 and upwards until the function returns
-    NULL, or a descriptor with an URI matching the one the host is looking for
-    is returned.
+   NULL or a descriptor with an URI matching the one the host is looking for.
 */
+LV2_SYMBOL_EXPORT
 const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index);
 
-
-/** This is the type of the lv2ui_descriptor() function. */
+/**
+   The type of the lv2ui_descriptor() function.
+*/
 typedef const LV2UI_Descriptor* (*LV2UI_DescriptorFunction)(uint32_t index);
 
-
-
 #ifdef __cplusplus
 }
 #endif
 
-
-#endif
+#endif /* LV2_UI_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2_uri_map.h calf-master/src/calf/lv2_uri_map.h
--- calf-old/src/calf/lv2_uri_map.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2_uri_map.h	2013-08-14 06:04:48.000000000 +0100
@@ -1,21 +1,31 @@
-/* lv2_uri_map.h - C header file for the LV2 URI Map extension.
- * 
- * Copyright (C) 2008 Dave Robillard <dave@drobilla.net>
- * 
- * This header is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This header 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 Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this header; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
- */
+/*
+  Copyright 2008-2011 David Robillard <http://drobilla.net>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+   @file
+   C header for the LV2 URI Map extension <http://lv2plug.in/ns/ext/uri-map>.
+
+   This extension defines a simple mechanism for plugins to map URIs to
+   integers, usually for performance reasons (e.g. processing events typed by
+   URIs in real time). The expected use case is for plugins to map URIs to
+   integers for things they 'understand' at instantiation time, and store those
+   values for use in the audio thread without doing any string comparison.
+   This allows the extensibility of RDF with the performance of integers (or
+   centrally defined enumerations).
+*/
 
 #ifndef LV2_URI_MAP_H
 #define LV2_URI_MAP_H
@@ -24,65 +34,65 @@
 
 #include <stdint.h>
 
-/** @file
- * This header defines the LV2 URI Map extension with the URI
- * <http://lv2plug.in/ns/ext/uri-map> (preferred prefix 'lv2urimap').
- *
- * This extension defines a simple mechanism for plugins to map URIs to
- * integers, usually for performance reasons (e.g. processing events
- * typed by URIs in real time).  The expected use case is for plugins to
- * map URIs to integers for things they 'understand' at instantiation time,
- * and store those values for use in the audio thread without doing any string
- * comparison.  This allows the extensibility of RDF with the performance of
- * integers (or centrally defined enumerations).
- */
-	
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-/** Opaque pointer to host data. */
+/**
+   Opaque pointer to host data.
+*/
 typedef void* LV2_URI_Map_Callback_Data;
 
+/**
+   URI Map Feature.
 
-/** The data field of the LV2_Feature for this extension.
- *
- * To support this feature the host must pass an LV2_Feature struct to the
- * plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-map"
- * and data pointed to an instance of this struct.
- */
+   To support this feature the host must pass an LV2_Feature struct to the
+   plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-map"
+   and data pointed to an instance of this struct.
+*/
 typedef struct {
+	/**
+	   Opaque pointer to host data.
 	
-	/** Opaque pointer to host data.
-	 *
-	 * The plugin MUST pass this to any call to functions in this struct.
-	 * Otherwise, it must not be interpreted in any way.
+	   The plugin MUST pass this to any call to functions in this struct.
+	   Otherwise, it must not be interpreted in any way.
 	 */
 	LV2_URI_Map_Callback_Data callback_data;
 	
-	/** Get the numeric ID of a URI from the host.
-	 *
-	 * @param callback_data Must be the callback_data member of this struct.
-	 * @param map The 'context' of this URI.  Certain extensions may define a
-	 *        URI that must be passed here with certain restrictions on the
-	 *        return value (e.g. limited range).  This value may be NULL if
-	 *        the plugin needs an ID for a URI in general.
-	 * @param uri The URI to be mapped to an integer ID.
-	 *
-	 * This function is referentially transparent - any number of calls with
-	 * the same arguments is guaranteed to return the same value over the life
-	 * of a plugin instance (though the same URI may return different values
-	 * with a different map parameter).  However, this function is not
-	 * necessarily very fast: plugins should cache any IDs they might need in
-	 * performance critical situations.
-	 * The return value 0 is reserved and means an ID for that URI could not
-	 * be created for whatever reason.  Extensions may define more precisely
-	 * what this means, but in general plugins should gracefully handle 0
-	 * and consider whatever they wanted the URI for "unsupported".
+	/**
+	   Get the numeric ID of a URI from the host.
+
+	   @param callback_data Must be the callback_data member of this struct.
+	   @param map The 'context' of this URI. Certain extensions may define a
+	   URI that must be passed here with certain restrictions on the return
+	   value (e.g. limited range). This value may be NULL if the plugin needs
+	   an ID for a URI in general. Extensions SHOULD NOT define a context
+	   unless there is a specific need to do so, e.g. to restrict the range of
+	   the returned value.
+	   @param uri The URI to be mapped to an integer ID.
+
+	   This function is referentially transparent; any number of calls with the
+	   same arguments is guaranteed to return the same value over the life of a
+	   plugin instance (though the same URI may return different values with a
+	   different map parameter). However, this function is not necessarily very
+	   fast: plugins SHOULD cache any IDs they might need in performance
+	   critical situations.
+
+	   The return value 0 is reserved and indicates that an ID for that URI
+	   could not be created for whatever reason. Extensions MAY define more
+	   precisely what this means in a certain context, but in general plugins
+	   SHOULD handle this situation as gracefully as possible. However, hosts
+	   SHOULD NOT return 0 from this function in non-exceptional circumstances
+	   (e.g. the URI map SHOULD be dynamic). Hosts that statically support only
+	   a fixed set of URIs should not expect plugins to function correctly.
 	 */
 	uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data,
 	                      const char*               map,
 	                      const char*               uri);
-
 } LV2_URI_Map_Feature;
 
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-#endif // LV2_URI_MAP_H
-
+#endif /* LV2_URI_MAP_H */
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/lv2wrap.h calf-master/src/calf/lv2wrap.h
--- calf-old/src/calf/lv2wrap.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/lv2wrap.h	2013-09-02 17:44:33.575174507 +0100
@@ -27,9 +27,10 @@
 #include <vector>
 #include <lv2.h>
 #include <calf/giface.h>
+#include <calf/preset.h>
 #include <calf/lv2_event.h>
 #include <calf/lv2_state.h>
-#include <calf/lv2_progress.h>
+#include <calf/lv2_programs.h>
 #include <calf/lv2_uri_map.h>
 #include <string.h>
 
@@ -49,6 +50,9 @@
     float **ins, **outs, **params;
     int out_count;
     int real_param_count;
+    std::vector<plugin_preset> *presets;
+    std::vector<LV2_Program_Descriptor> *preset_descs;
+
     lv2_instance(audio_module_iface *_module)
     {
         module = _module;
@@ -64,6 +68,22 @@
 
         srate_to_set = 44100;
         set_srate = true;
+        
+        presets = NULL;
+        preset_descs = NULL;
+    }
+    ~lv2_instance()
+    {
+        if (presets)
+        {
+            presets->clear();
+            delete presets;
+        }
+        if (preset_descs)
+        {
+            preset_descs->clear();
+            delete preset_descs;
+        }
     }
     /// This, and not Module::post_instantiate, is actually called by lv2_wrapper class
     void post_instantiate()
@@ -71,6 +91,30 @@
         if (progress_report_feature)
             module->set_progress_report_iface(this);
         module->post_instantiate();
+
+        presets = new std::vector<plugin_preset>;
+        preset_descs = new std::vector<LV2_Program_Descriptor>;
+
+        preset_list plist_tmp, plist;
+        plist.load_defaults(true);
+        plist_tmp.load_defaults(false);
+        plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
+
+        int pos = 1;
+        const char* label = metadata->get_label();
+
+        for (unsigned int i = 0; i < plist.presets.size(); i++)
+        {
+            plugin_preset &pp = plist.presets[i];
+            if (strcasecmp(pp.plugin.c_str(), label))
+                continue;
+            LV2_Program_Descriptor pd;
+            pd.bank = pos >> 7;
+            pd.program = pos++;
+            pd.name = pp.name.c_str();
+            preset_descs->push_back(pd);
+            presets->push_back(pp);
+        }
     }
     virtual bool activate_preset(int bank, int program) { 
         return false;
@@ -185,6 +229,8 @@
     static LV2_Descriptor descriptor;
     static LV2_Calf_Descriptor calf_descriptor;
     static LV2_State_Interface state_iface;
+    static LV2_Programs_Interface programs_iface;
+    static LV2_Program_Descriptor lv2_default_program;
     std::string uri;
     
     lv2_wrapper()
@@ -202,6 +248,11 @@
         state_iface.save = cb_state_save;
         state_iface.restore = cb_state_restore;
         calf_descriptor.get_pci = cb_get_pci;
+        programs_iface.get_program = cb_get_program;
+        programs_iface.select_program = cb_select_program;
+        lv2_default_program.bank = 0;
+        lv2_default_program.program = 0;
+        lv2_default_program.name = "default";
     }
 
     static void cb_connect(LV2_Handle Instance, uint32_t port, void *DataLocation)
@@ -298,6 +349,8 @@
             return &calf_descriptor;
         if (!strcmp(URI, LV2_STATE__interface))
             return &state_iface;
+        if (!strcmp(URI, LV2_PROGRAMS__Interface))
+            return &programs_iface;
         return NULL;
     }
     static LV2_State_Status cb_state_save(
@@ -345,6 +398,31 @@
         inst->impl_restore(retrieve, callback_data);
         return LV2_STATE_SUCCESS;
     }
+    static const LV2_Program_Descriptor* cb_get_program(LV2_Handle Instance, uint32_t index)
+    {
+        instance *const inst = (instance *)Instance;
+        if (index > inst->presets->size())
+            return NULL;
+        if (index)
+            return &(*inst->preset_descs)[index - 1];
+        return &lv2_default_program;
+    }
+    static void cb_select_program(LV2_Handle Instance, uint32_t bank, uint32_t program)
+    {
+        instance *const inst = (instance *)Instance;
+        unsigned int no = (bank << 7) + program - 1;
+        if (no == -1U) {
+            int rpc = inst->real_param_count;
+            for (int i =0 ; i < rpc; i++)
+                *inst->params[i] = inst->metadata->get_param_props(i)->def_value;
+            return;
+        }
+        if (no >= inst->presets->size())
+            return;
+        plugin_preset &p = (*inst->presets)[no];
+        // printf("activating preset %s\n", p.name.c_str());
+        p.activate(inst);
+    }
     
     static lv2_wrapper &get() { 
         static lv2_wrapper *instance = new lv2_wrapper;
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/modulelist.h calf-master/src/calf/modulelist.h
--- calf-old/src/calf/modulelist.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/modulelist.h	2012-12-31 00:14:37.000000000 +0000
@@ -30,7 +30,7 @@
     PER_MODULE_ITEM(analyzer, false, "analyzer")
 #ifdef ENABLE_EXPERIMENTAL
     PER_MODULE_ITEM(fluidsynth, true, "fluidsynth")
-    PER_MODULE_ITEM(wavetable, true, "wavetable")
+    //PER_MODULE_ITEM(wavetable, true, "wavetable")
 #endif
 #undef PER_MODULE_ITEM
 #endif
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/modules_synths.h calf-master/src/calf/modules_synths.h
--- calf-old/src/calf/modules_synths.h	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/calf/modules_synths.h	2012-12-31 00:14:37.000000000 +0000
@@ -185,7 +185,7 @@
 
 };
 
-#if ENABLE_EXPERIMENTAL
+#if 0 // ENABLE_EXPERIMENTAL
     
 #include "wavetable.h"
 
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/osctl_glib.h calf-master/src/calf/osctl_glib.h
--- calf-old/src/calf/osctl_glib.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/osctl_glib.h	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,46 @@
+/* Calf DSP Library
+ * Open Sound Control UDP server support
+ *
+ * Copyright (C) 2007-2009 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __CALF_OSCTLGLIB_H
+#define __CALF_OSCTLGLIB_H
+
+#include <glib.h>
+#include "osctlnet.h"
+
+namespace osctl
+{
+    
+/// Glib main loop based implementation of OSC server.
+struct osc_glib_server: public osc_server
+{
+    GIOChannel *ioch;
+    
+    osc_glib_server() : ioch(NULL) {}
+    
+    virtual void on_bind();
+    
+    static gboolean on_data(GIOChannel *channel, GIOCondition cond, void *obj);
+    ~osc_glib_server();
+};
+
+};
+
+#endif
diff -U 3 -H -b -d -r -N -- calf-old/src/calf/osctlnet.h calf-master/src/calf/osctlnet.h
--- calf-old/src/calf/osctlnet.h	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/calf/osctlnet.h	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,71 @@
+/* Calf DSP Library
+ * Open Sound Control UDP support
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CALF_OSCTLNET_H
+#define __CALF_OSCTLNET_H
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <calf/osctl.h>
+
+namespace osctl
+{
+    
+struct osc_socket
+{
+    int socket, srcid;
+    std::string prefix;
+
+    osc_socket() : socket(-1), srcid(0) {}
+    void bind(const char *hostaddr = "0.0.0.0", int port = 0);
+    std::string get_url() const;
+    virtual void on_bind() {}
+    virtual ~osc_socket();
+};
+
+struct osc_client: public osc_socket
+{
+    sockaddr_in addr;
+    
+    void set_addr(const char *hostaddr, int port);
+    void set_url(const char *url);
+    bool send(const std::string &address, osctl::osc_typed_strstream &stream);
+    bool send(const std::string &address);
+};
+
+/// Base implementation for OSC server - requires the interfacing code
+/// to poll periodically for messages. Alternatively, one can use
+/// osc_glib_server that hooks into glib main loop.
+struct osc_server: public osc_socket
+{
+    osc_message_dump<osc_strstream, std::ostream> dump;
+    osc_message_sink<osc_strstream> *sink;
+    
+    osc_server() : dump(std::cout), sink(&dump) {}
+    
+    void read_from_socket();
+    void parse_message(const char *buffer, int len);    
+    ~osc_server();
+};
+
+};
+
+#endif
diff -U 3 -H -b -d -r -N -- calf-old/src/dssigui.cpp calf-master/src/dssigui.cpp
--- calf-old/src/dssigui.cpp	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/dssigui.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,686 @@
+/* Calf DSP Library utility application.
+ * DSSI GUI application.
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <calf/giface.h>
+#include <calf/gui.h>
+#include <calf/osctl_glib.h>
+#include <calf/preset.h>
+#include <getopt.h>
+
+using namespace std;
+using namespace dsp;
+using namespace calf_plugins;
+using namespace osctl;
+
+#define debug_printf(...)
+
+struct cairo_params
+{
+    enum { HAS_COLOR = 1, HAS_WIDTH = 2 };
+    uint32_t flags;
+    float r, g, b, a;
+    float line_width;
+    
+    cairo_params()
+    : flags(0)
+    , r(0.f)
+    , g(0.f)
+    , b(0.f)
+    , a(1.f)
+    , line_width(1)
+    {
+    }
+};
+
+struct graph_item: public cairo_params
+{
+    float data[128];
+    int mode;
+
+    graph_item(int mode_)
+      : mode(mode_) {}
+};
+
+struct dot_item: public cairo_params
+{
+    float x, y;
+    int32_t size;
+};
+
+struct gridline_item: public cairo_params
+{
+    float pos;
+    int32_t vertical;
+    std::string text;
+};
+
+struct param_line_graphs
+{
+    vector<graph_item *> graphs;
+    vector<dot_item *> dots;
+    vector<gridline_item *> gridlines;
+    
+    void clear();
+};
+
+void param_line_graphs::clear()
+{
+    for (size_t i = 0; i < graphs.size(); i++)
+        delete graphs[i];
+    graphs.clear();
+
+    for (size_t i = 0; i < dots.size(); i++)
+        delete dots[i];
+    dots.clear();
+
+    for (size_t i = 0; i < gridlines.size(); i++)
+        delete gridlines[i];
+    gridlines.clear();
+
+}
+
+struct plugin_proxy: public plugin_ctl_iface, public line_graph_iface, public phase_graph_iface
+{
+    osc_client *client;
+    bool send_osc;
+    plugin_gui *gui;
+    map<string, string> cfg_vars;
+    int param_count;
+    float *params;
+    map<int, param_line_graphs> graphs;
+    bool update_graphs;
+    const plugin_metadata_iface *metadata;
+    vector<string> new_status;
+    uint32_t new_status_serial;
+    bool is_lv2;
+
+    plugin_proxy(const plugin_metadata_iface *md, bool _is_lv2)
+    {
+        new_status_serial = 0;
+        metadata = md;
+        client = NULL;
+        send_osc = false;
+        update_graphs = true;
+        gui = NULL;
+        param_count = md->get_param_count();
+        params = new float[param_count];
+        for (int i = 0; i < param_count; i++)
+            params[i] = metadata->get_param_props(i)->def_value;
+        is_lv2 = _is_lv2;
+    }
+    virtual float get_param_value(int param_no) {
+        if (param_no < 0 || param_no >= param_count)
+            return 0;
+        return params[param_no];
+    }
+    virtual void set_param_value(int param_no, float value) {
+        if (param_no < 0 || param_no >= param_count)
+            return;
+        update_graphs = true;
+        params[param_no] = value;
+        if (send_osc)
+        {
+            osc_inline_typed_strstream str;
+            str << (uint32_t)(param_no + metadata->get_param_port_offset()) << value;
+            client->send("/control", str);
+        }
+    }
+    virtual bool activate_preset(int bank, int program) { 
+        if (send_osc) {
+            osc_inline_typed_strstream str;
+            str << (uint32_t)(bank) << (uint32_t)(program);
+            client->send("/program", str);
+            return false;
+        }
+        return false;
+    }
+    virtual float get_level(unsigned int port) { return 0.f; }
+    virtual void execute(int command_no) { 
+        if (send_osc) {
+            stringstream ss;
+            ss << command_no;
+            
+            osc_inline_typed_strstream str;
+            str << "ExecCommand" << ss.str();
+            client->send("/configure", str);
+            
+            str.clear();
+            str << "ExecCommand" << "";
+            client->send("/configure", str);
+        }
+    }
+    char *configure(const char *key, const char *value) { 
+        // do not store temporary vars in presets
+        osc_inline_typed_strstream str;
+        if (value)
+        {
+            if (strncmp(key, "OSC:", 4))
+                cfg_vars[key] = value;
+            str << key << value;
+        }
+        else
+            str << key;
+        client->send("/configure", str);
+        return NULL;
+    }
+    void send_configures(send_configure_iface *sci) { 
+        for (map<string, string>::iterator i = cfg_vars.begin(); i != cfg_vars.end(); i++)
+            sci->send_configure(i->first.c_str(), i->second.c_str());
+    }
+    virtual int send_status_updates(send_updates_iface *sui, int last_serial)
+    {
+        if ((int)new_status_serial != last_serial)
+        {
+            for (size_t i = 0; i < (new_status.size() & ~1); i += 2)
+            {
+                sui->send_status(new_status[i].c_str(), new_status[i + 1].c_str());
+            }
+            return new_status_serial;
+        }
+        if (!is_lv2)
+        {
+            osc_inline_typed_strstream str;
+            str << "OSC:SEND_STATUS" << calf_utils::i2s(last_serial);
+            client->send("/configure", str);
+            return last_serial;
+        }
+        else
+        {
+            osc_inline_typed_strstream str;
+            str << (uint32_t)last_serial;
+            client->send("/send_status", str);
+            return last_serial;
+        }
+    }
+    virtual const line_graph_iface *get_line_graph_iface() const { return this; }
+    virtual const phase_graph_iface *get_phase_graph_iface() const { return this; }
+    virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context, int *mode) const;
+    virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
+    virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+    void update_cairo_context(cairo_iface *context, cairo_params &item) const;
+    virtual const plugin_metadata_iface *get_metadata_iface() const { return metadata; }
+};
+
+bool plugin_proxy::get_graph(int index, int subindex, float *data, int points, cairo_iface *context, int *mode) const
+{
+    if (!graphs.count(index))
+        return false;
+    const param_line_graphs &g = graphs.find(index)->second;
+    if (subindex < (int)g.graphs.size())
+    {
+        *mode = g.graphs[subindex]->mode;
+        float *sdata = g.graphs[subindex]->data;
+        for (int i = 0; i < points; i++) {
+            float pos = i * 127.0 / points;
+            int ipos = i * 127 / points;
+            data[i] = sdata[ipos] + (sdata[ipos + 1] - sdata[ipos]) * (pos-ipos);
+        }
+        update_cairo_context(context, *g.graphs[subindex]);
+        return true;
+    }
+    return false;
+}
+
+bool plugin_proxy::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
+{
+    if (!graphs.count(index))
+        return false;
+    const param_line_graphs &g = graphs.find(index)->second;
+    if (subindex < (int)g.dots.size())
+    {
+        dot_item &item = *g.dots[subindex];
+        x = item.x;
+        y = item.y;
+        size = item.size;
+        update_cairo_context(context, item);
+        return true;
+    }
+    return false;
+}
+
+bool plugin_proxy::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+    if (!graphs.count(index))
+        return false;
+    const param_line_graphs &g = graphs.find(index)->second;
+    if (subindex < (int)g.gridlines.size())
+    {
+        gridline_item &item = *g.gridlines[subindex];
+        pos = item.pos;
+        vertical = item.vertical != 0;
+        legend = item.text;
+        update_cairo_context(context, item);
+        return true;
+    }
+    return false;
+}
+
+void plugin_proxy::update_cairo_context(cairo_iface *context, cairo_params &item) const
+{
+    if (item.flags & cairo_params::HAS_COLOR)
+        context->set_source_rgba(item.r, item.g, item.b, item.a);
+    if (item.flags & cairo_params::HAS_WIDTH)
+        context->set_line_width(item.line_width);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+GMainLoop *mainloop;
+
+static bool osc_debug = false;
+
+struct dssi_osc_server: public osc_glib_server, public osc_message_sink<osc_strstream>, public gui_environment
+{
+    plugin_proxy *plugin;
+    plugin_gui_window *window;
+    string effect_name, title;
+    osc_client cli;
+    bool in_program, enable_dump;
+    vector<plugin_preset> presets;
+    /// Timeout callback source ID
+    int source_id;
+    bool osc_link_active;
+    /// If we're communicating with the LV2 external UI bridge, use a slightly different protocol
+    bool is_lv2;
+    
+    dssi_osc_server()
+    : plugin(NULL)
+    , window(new plugin_gui_window(this, NULL))
+    {
+        sink = this;
+        source_id = 0;
+        osc_link_active = false;
+        is_lv2 = false;
+    }
+    
+    void set_plugin(const char *arg)
+    {
+        const plugin_metadata_iface *pmi = plugin_registry::instance().get_by_id(arg);
+        if (!pmi)
+        {
+            pmi = plugin_registry::instance().get_by_uri(arg);
+            if (pmi)
+                is_lv2 = true;
+        }
+        if (!pmi)
+        {
+            fprintf(stderr, "Unknown plugin: %s\n", arg);
+            exit(1);
+        }
+        effect_name = pmi->get_id();
+        plugin = new plugin_proxy(pmi, is_lv2);
+    }
+    
+    static void on_destroy(GtkWindow *window, dssi_osc_server *self)
+    {
+        debug_printf("on_destroy, have to send \"exiting\"\n");
+        bool result = self->cli.send("/exiting");
+        debug_printf("result = %d\n", result ? 1 : 0);
+        g_main_loop_quit(mainloop);
+        // eliminate a warning with empty debug_printf
+        result = false;
+    }
+    
+    void create_window()
+    {
+        plugin->client = &cli;
+        plugin->send_osc = true;
+        conditions.insert("dssi");
+        conditions.insert("configure");
+        conditions.insert("directlink");
+        window->create(plugin, title.c_str(), effect_name.c_str());
+        plugin->gui = window->gui;
+        gtk_signal_connect(GTK_OBJECT(window->toplevel), "destroy", G_CALLBACK(on_destroy), this);
+        vector<plugin_preset> tmp_presets;
+        get_builtin_presets().get_for_plugin(presets, effect_name.c_str());
+        get_user_presets().get_for_plugin(tmp_presets, effect_name.c_str());
+        presets.insert(presets.end(), tmp_presets.begin(), tmp_presets.end());
+        source_id = g_timeout_add_full(G_PRIORITY_LOW, 1000/30, on_idle, this, NULL);
+    }
+    
+    static gboolean on_idle(void *self)
+    {
+        dssi_osc_server *self_ptr = (dssi_osc_server *)(self);
+        if (self_ptr->osc_link_active)
+            self_ptr->send_osc_update();
+        return TRUE;
+    }
+    
+    void set_osc_update(bool enabled);
+    void send_osc_update();
+    
+    virtual void receive_osc_message(std::string address, std::string args, osc_strstream &buffer);
+    void unmarshal_line_graph(osc_strstream &buffer);
+};
+
+void dssi_osc_server::set_osc_update(bool enabled)
+{
+    if (is_lv2)
+    {
+        osc_inline_typed_strstream data;
+        data << ((uint32_t)(enabled ? 1 : 0));
+        cli.send("/enable_updates", data);
+    }
+    else
+    {
+        osc_link_active = enabled;
+        osc_inline_typed_strstream data;
+        data << "OSC:FEEDBACK_URI";
+        data << (enabled ? get_url() : "");
+        cli.send("/configure", data);
+    }
+}
+
+void dssi_osc_server::send_osc_update()
+{
+    // LV2 is updating via run() callback in the external UI library, so this is not needed
+    if (is_lv2)
+        return;
+    
+    static int serial_no = 0;
+    osc_inline_typed_strstream data;
+    data << "OSC:UPDATE";
+    data << calf_utils::i2s(serial_no++);
+    cli.send("/configure", data);
+}
+
+void dssi_osc_server::unmarshal_line_graph(osc_strstream &buffer)
+{
+    uint32_t cmd;
+    
+    do {
+        buffer >> cmd;
+        if (cmd == LGI_GRAPH)
+        {
+            uint32_t param;
+            buffer >> param;
+            param_line_graphs &graphs = plugin->graphs[param];
+            
+            graphs.clear();
+            cairo_params params;
+
+            do {
+                buffer >> cmd;
+                if (cmd == LGI_SET_RGBA)
+                {
+                    params.flags |= cairo_params::HAS_COLOR;
+                    buffer >> params.r >> params.g >> params.b >> params.a;
+                }
+                else
+                if (cmd == LGI_SET_WIDTH)
+                {
+                    params.flags |= cairo_params::HAS_WIDTH;
+                    buffer >> params.line_width;
+                }
+                else
+                if (cmd == LGI_SUBGRAPH)
+                {
+                    uint32_t mode;
+                    buffer >> mode;
+                    buffer >> param; // ignore number of points
+                    graph_item *gi = new graph_item(mode);
+                    (cairo_params &)*gi = params;
+                    for (int i = 0; i < 128; i++)
+                        buffer >> gi->data[i];
+                    graphs.graphs.push_back(gi);
+                    params.flags = 0;
+                }
+                else
+                if (cmd == LGI_DOT)
+                {
+                    dot_item *di = new dot_item;
+                    (cairo_params &)*di = params;
+                    buffer >> di->x >> di->y >> di->size;
+                    graphs.dots.push_back(di);
+                    params.flags = 0;
+                }
+                else
+                if (cmd == LGI_LEGEND)
+                {
+                    gridline_item *li = new gridline_item;
+                    (cairo_params &)*li = params;
+                    buffer >> li->pos >> li->vertical >> li->text;
+                    graphs.gridlines.push_back(li);
+                    params.flags = 0;
+                }
+                else
+                    break;
+            } while(1);
+            
+        }
+        else
+            break;
+    } while(1);
+}
+
+void dssi_osc_server::receive_osc_message(std::string address, std::string args, osc_strstream &buffer)
+{
+    if (osc_debug)
+        dump.receive_osc_message(address, args, buffer);
+    if (address == prefix + "/update" && args == "s")
+    {
+        string str;
+        buffer >> str;
+        debug_printf("UPDATE: %s\n", str.c_str());
+        set_osc_update(true);
+        send_osc_update();
+        return;
+    }
+    else if (address == prefix + "/quit")
+    {
+        set_osc_update(false);
+        debug_printf("QUIT\n");
+        g_main_loop_quit(mainloop);
+        return;
+    }
+    else if (address == prefix + "/configure"&& args == "ss")
+    {
+        string key, value;
+        buffer >> key >> value;
+        // do not store temporary vars in presets
+        if (strncmp(key.c_str(), "OSC:", 4))
+            plugin->cfg_vars[key] = value;
+        // XXXKF perhaps this should be queued !
+        window->gui->refresh();
+        return;
+    }
+    else if (address == prefix + "/program"&& args == "ii")
+    {
+        uint32_t bank, program;
+        
+        buffer >> bank >> program;
+        
+        unsigned int nr = bank * 128 + program;
+        debug_printf("PROGRAM %d\n", nr);
+        if (nr == 0)
+        {
+            bool sosc = plugin->send_osc;
+            plugin->send_osc = false;
+            int count = plugin->metadata->get_param_count();
+            for (int i =0 ; i < count; i++)
+                plugin->set_param_value(i, plugin->metadata->get_param_props(i)->def_value);
+            plugin->send_osc = sosc;
+            window->gui->refresh();
+            // special handling for default preset
+            return;
+        }
+        nr--;
+        if (nr >= presets.size())
+            return;
+        bool sosc = plugin->send_osc;
+        plugin->send_osc = false;
+        presets[nr].activate(plugin);
+        plugin->send_osc = sosc;
+        window->gui->refresh();
+        
+        // cli.send("/update", data);
+        return;
+    }
+    else if (address == prefix + "/control" && args == "if")
+    {
+        uint32_t port;
+        float val;
+        
+        buffer >> port >> val;
+        
+        int idx = port - plugin->metadata->get_param_port_offset();
+        debug_printf("CONTROL %d %f\n", idx, val);
+        bool sosc = plugin->send_osc;
+        plugin->send_osc = false;
+        window->gui->set_param_value(idx, val);
+        plugin->send_osc = sosc;
+        if (plugin->metadata->get_param_props(idx)->flags & PF_PROP_GRAPH)
+            plugin->update_graphs = true;
+        return;
+    }
+    else if (address == prefix + "/show")
+    {
+        set_osc_update(true);
+
+        gtk_widget_show(GTK_WIDGET(window->toplevel));
+        return;
+    }
+    else if (address == prefix + "/hide")
+    {
+        set_osc_update(false);
+
+        gtk_widget_hide(GTK_WIDGET(window->toplevel));
+        return;
+    }
+    else if (address == prefix + "/lineGraph")
+    {
+        unmarshal_line_graph(buffer);
+        if (plugin->update_graphs) {
+            // updates graphs that are only redrawn on startup and parameter changes
+            // (the OSC message may come a while after the parameter has been changed,
+            // so the redraw triggered by parameter change usually shows stale values)
+            window->gui->refresh();
+            plugin->update_graphs = false;
+        }
+        return;
+    }
+    else if (address == prefix + "/status_data" && (args.length() & 1) && args[args.length() - 1] == 'i')
+    {
+        int len = (int)args.length();
+        plugin->new_status.clear();
+        
+        for (int pos = 0; pos < len - 2; pos += 2)
+        {
+            if (args[pos] == 's' && args[pos+1] == 's')
+            {
+                string key, value;
+                buffer >> key >> value;
+                plugin->new_status.push_back(key);
+                plugin->new_status.push_back(value);
+            }
+        }
+        buffer >> plugin->new_status_serial;
+        return;
+    }
+    else
+        printf("Unknown OSC address: %s\n", address.c_str());
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+void help(char *argv[])
+{
+    printf("GTK+ user interface for Calf DSSI plugins\nSyntax: %s [--help] [--version] <osc-url> <so-file> <plugin-label> <instance-name>\n", argv[0]);
+}
+
+static struct option long_options[] = {
+    {"help", 0, 0, 'h'},
+    {"version", 0, 0, 'v'},
+    {"debug", 0, 0, 'd'},
+    {0,0,0,0},
+};
+
+int main(int argc, char *argv[])
+{
+    char *debug_var = getenv("OSC_DEBUG");
+    if (debug_var && atoi(debug_var))
+        osc_debug = true;
+    
+    gtk_rc_add_default_file(PKGLIBDIR "calf.rc");
+    gtk_init(&argc, &argv);
+    while(1) {
+        int option_index;
+        int c = getopt_long(argc, argv, "dhv", long_options, &option_index);
+        if (c == -1)
+            break;
+        switch(c) {
+            case 'd':
+                osc_debug = true;
+                break;
+            case 'h':
+                help(argv);
+                return 0;
+            case 'v':
+                printf("%s\n", PACKAGE_STRING);
+                return 0;
+        }
+    }
+    if (argc - optind != 4)
+    {
+        help(argv);
+        exit(0);
+    }
+
+    try {
+        get_builtin_presets().load_defaults(true);
+        get_user_presets().load_defaults(false);
+    }
+    catch(calf_plugins::preset_exception &e)
+    {
+        fprintf(stderr, "Error while loading presets: %s\n", e.what());
+        exit(1);
+    }
+
+    dssi_osc_server srv;
+    srv.set_plugin(argv[optind + 2]);
+    srv.prefix = "/dssi/"+string(argv[optind + 1]) + "/" + srv.effect_name;
+    srv.title = argv[optind + 3];
+    
+    srv.bind();
+    srv.create_window();
+    
+    mainloop = g_main_loop_new(NULL, FALSE);
+
+    srv.cli.bind();
+    srv.cli.set_url(argv[optind]);
+    
+    debug_printf("URI = %s\n", srv.get_url().c_str());
+    
+    osc_inline_typed_strstream data;
+    data << srv.get_url();
+    if (!srv.cli.send("/update", data))
+    {
+        g_error("Could not send the initial update message via OSC to %s", argv[optind]);
+        return 1;
+    }
+    
+    g_main_loop_run(mainloop);
+    if (srv.source_id)
+        g_source_remove(srv.source_id);
+
+    srv.set_osc_update(false);
+    debug_printf("exited\n");
+    
+    return 0;
+}
diff -U 3 -H -b -d -r -N -- calf-old/src/giface.cpp calf-master/src/giface.cpp
--- calf-old/src/giface.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/giface.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -21,6 +21,7 @@
 #include <config.h>
 #include <limits.h>
 #include <calf/giface.h>
+#include <calf/osctlnet.h>
 #include <calf/utils.h>
 
 using namespace std;
@@ -382,6 +383,118 @@
 ///////////////////////////////////////////////////////////////////////////////////////
 
 #if USE_EXEC_GUI
+struct osc_cairo_control: public cairo_iface
+{
+    osctl::osc_inline_typed_strstream os;
+    
+    osc_cairo_control() {}
+    virtual void set_source_rgba(float r, float g, float b, float a = 1.f)
+    {
+        os << (uint32_t)LGI_SET_RGBA << r << g << b << a;
+    }
+    virtual void set_line_width(float width)
+    {
+        os << (uint32_t)LGI_SET_WIDTH << width;
+    }
+};
+
+static void serialize_graphs(osc_cairo_control *cairoctl, osctl::osc_inline_typed_strstream &os, const line_graph_iface *graph, std::vector<int> &params)
+{
+    for (size_t i = 0; i < params.size(); i++)
+    {
+        int index = params[i];
+        os << (uint32_t)LGI_GRAPH;
+        os << (uint32_t)index;
+        for (int j = 0; ; j++)
+        {
+            int mode = 0;
+            float data[128];
+            if (graph->get_graph(index, j, data, 128, cairoctl, &mode))
+            {
+                os << (uint32_t)LGI_SUBGRAPH;
+                os << (uint32_t)mode;
+                os << (uint32_t)128;
+                for (int p = 0; p < 128; p++)
+                    os << data[p];
+            }
+            else
+                break;
+        }
+        for (int j = 0; ; j++)
+        {
+            float x, y;
+            int size = 3;
+            if (graph->get_dot(index, j, x, y, size, cairoctl))
+                os << (uint32_t)LGI_DOT << x << y << (uint32_t)size;
+            else
+                break;
+        }
+        for (int j = 0; ; j++)
+        {
+            float pos = 0;
+            bool vertical = false;
+            string legend;
+            if (graph->get_gridline(index, j, pos, vertical, legend, cairoctl))
+                os << (uint32_t)LGI_LEGEND << pos << (uint32_t)(vertical ? 1 : 0) << legend;
+            else
+                break;
+        }
+        os << (uint32_t)LGI_END_ITEM;
+    }
+    os << (uint32_t)LGI_END;
+}
+
+calf_plugins::dssi_feedback_sender::dssi_feedback_sender(const char *URI, const line_graph_iface *_graph)
+{
+    graph = _graph;
+    is_client_shared = false;
+    client = new osctl::osc_client;
+    client->bind("0.0.0.0", 0);
+    client->set_url(URI);
+    _context = NULL;
+}
+
+calf_plugins::dssi_feedback_sender::dssi_feedback_sender(osctl::osc_client *_client, const line_graph_iface *_graph)
+{
+    graph = _graph;
+    client = _client;
+    is_client_shared = true;
+    _context = NULL;
+}
+
+void calf_plugins::dssi_feedback_sender::add_graphs(const calf_plugins::parameter_properties *props, int num_params)
+{
+    for (int i = 0; i < num_params; i++)
+    {
+        if (props[i].flags & PF_PROP_GRAPH)
+            indices.push_back(i);
+    }
+}
+
+void calf_plugins::dssi_feedback_sender::update()
+{
+    if (graph)
+    {
+        osc_cairo_control* cairoctl;
+        if (_context)
+        {
+            cairoctl = (osc_cairo_control*)_context;
+            cairoctl->os.clear();
+        }
+        else
+            cairoctl = new osc_cairo_control();
+        serialize_graphs(cairoctl, cairoctl->os, graph, indices);
+        client->send("/lineGraph", cairoctl->os);
+    }
+}
+
+calf_plugins::dssi_feedback_sender::~dssi_feedback_sender()
+{
+    if (_context)
+        delete (osc_cairo_control*)_context;
+    if (!is_client_shared)
+        delete client;
+}
 
 table_via_configure::table_via_configure()
 {
diff -U 3 -H -b -d -r -N -- calf-old/src/lv2gui.cpp calf-master/src/lv2gui.cpp
--- calf-old/src/lv2gui.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/lv2gui.cpp	2013-09-02 18:21:42.448309758 +0100
@@ -18,20 +18,27 @@
  * Boston, MA  02110-1301  USA
  */
 #include <sys/wait.h>
+#include <unistd.h>
 #include "config.h"
+#if USE_LV2_GTK_GUI
 #include <calf/gui.h>
+#endif
 #include <calf/giface.h>
 #include <calf/lv2_data_access.h>
+#include <calf/lv2_instance_access.h>
 #include <calf/lv2_ui.h>
 #include <calf/lv2_uri_map.h>
 #include <calf/lv2_external_ui.h>
+#include <calf/lv2_programs.h>
 #include <calf/lv2helpers.h>
+#include <calf/osctlnet.h>
 #include <calf/utils.h>
 #include <glib.h>
 
 using namespace std;
 using namespace calf_plugins;
 using namespace calf_utils;
+using namespace osctl;
 
 struct LV2_Calf_Descriptor {
     plugin_ctl_iface *(*get_pci)(LV2_Handle Instance);
@@ -56,7 +63,7 @@
     /// URI map feature
     LV2_URI_Map_Feature *uri_map;
     /// External UI host feature (must be set when instantiating external UI plugins)
-    lv2_external_ui_host *ext_ui_host;
+    LV2_External_UI_Host *ext_ui_host;
     
     /// Instance pointer - usually NULL unless the host supports instance-access extension
     plugin_ctl_iface *instance;
@@ -122,17 +129,17 @@
     }
     for (int i = 0; features[i]; i++)
     {
-        if (!strcmp(features[i]->URI, "http://lv2plug.in/ns/ext/instance-access"))
+        if (!strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI))
         {
             instance_handle = features[i]->data;
         }
-        else if (!strcmp(features[i]->URI, "http://lv2plug.in/ns/ext/data-access"))
+        else if (!strcmp(features[i]->URI, LV2_DATA_ACCESS_URI))
         {
             data_access = (LV2_Extension_Data_Feature *)features[i]->data;
         }
-        else if (!strcmp(features[i]->URI, LV2_EXTERNAL_UI_URI))
+        else if (!strcmp(features[i]->URI, LV2_EXTERNAL_UI__Host))
         {
-            ext_ui_host = (lv2_external_ui_host *)features[i]->data;
+            ext_ui_host = (LV2_External_UI_Host *)features[i]->data;
         }
     }
     resolve_instance();
@@ -196,6 +203,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
+#if USE_LV2_GTK_GUI
 /// Plugin controller that uses LV2 host with help of instance/data access to remotely
 /// control a plugin from the GUI
 struct lv2_plugin_proxy: public plugin_ctl_iface, public plugin_proxy_base, public gui_environment
@@ -229,11 +237,6 @@
         send_float_to_host(param_no, value);
     }
     
-    virtual bool activate_preset(int bank, int program)
-    {
-        return false;
-    }
-    
     /// Override for a method in plugin_ctl_iface - trivial delegation to base class
     virtual char *configure(const char *key, const char *value) { return plugin_proxy_base::configure(key, value); }
     
@@ -332,11 +335,304 @@
 
 const void *gui_extension(const char *uri)
 {
+    printf("gui_extension %s\n", uri);
+    return NULL;
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+class ext_plugin_gui: public LV2_External_UI_Widget, public plugin_proxy_base, public osc_message_sink<osc_strstream>, public send_updates_iface
+{
+public:
+    GPid child_pid;
+    osc_server srv;
+    osc_client cli;
+    bool confirmed;
+    string prefix;
+    dssi_feedback_sender *feedback_sender;
+    bool enable_graph_updates;
+    osc_inline_typed_strstream status_data;
+
+    ext_plugin_gui(const plugin_metadata_iface *metadata, LV2UI_Write_Function wf, LV2UI_Controller c, const LV2_Feature* const* f);
+
+    bool initialise();
+
+    void show_impl();
+    void hide_impl();
+    void run_impl();
+    void port_event_impl(uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer);
+
+    bool activate_preset(int bank, int program)
+    {
+        if (confirmed) {
+            osc_inline_typed_strstream str;
+            str << (uint32_t)(bank) << (uint32_t)(program);
+            cli.send("/program", str);
+            return false;
+        }
+        return false;
+    }
+
+    virtual void send_status(const char *key, const char *value);
+    virtual void receive_osc_message(std::string address, std::string args, osc_strstream &buffer);
+    virtual ~ext_plugin_gui();
+        
+private:
+    static void show_(LV2_External_UI_Widget *h) { ((ext_plugin_gui *)(h))->show_impl(); }
+    static void hide_(LV2_External_UI_Widget *h) { ((ext_plugin_gui *)(h))->hide_impl(); }
+    static void run_(LV2_External_UI_Widget *h) { ((ext_plugin_gui *)(h))->run_impl(); }
+};
+
+ext_plugin_gui::ext_plugin_gui(const plugin_metadata_iface *metadata, LV2UI_Write_Function wf, LV2UI_Controller c, const LV2_Feature* const* f)
+: plugin_proxy_base(metadata, wf, c, f)
+{
+    confirmed = false;
+    feedback_sender = NULL;
+    
+    show = show_;
+    hide = hide_;
+    run = run_;
+}
+
+bool ext_plugin_gui::initialise()
+{
+    if (ext_ui_host == NULL)
+        return false;
+    
+    srv.sink = this;
+    srv.bind("127.0.0.1");
+    
+    return true;
+}
+
+void ext_plugin_gui::show_impl()
+{
+    struct osc_configure_sender: public send_configure_iface
+    {
+        osc_client &cli;
+        
+        osc_configure_sender(osc_client &c)
+        : cli(c)
+        {
+        }
+        
+        virtual void send_configure(const char *key, const char *value)
+        {
+            osc_inline_typed_strstream data;
+            data << key;
+            data << value;
+            cli.send("/configure", data);
+        }
+    };
+
+    osc_configure_sender sender(cli);
+    
+    if (instance)
+        instance->send_configures(&sender);
+    
+    cli.send("/show");
+}
+
+void ext_plugin_gui::hide_impl()
+{
+    cli.send("/hide");
+}
+
+void ext_plugin_gui::send_status(const char *key, const char *value)
+{
+    status_data << key << value;
+}
+
+void ext_plugin_gui::port_event_impl(uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer)
+{
+    assert(confirmed);
+    assert(port >= (uint32_t)param_offset);
+    if (port >= (uint32_t)param_offset)
+    {
+        int param = port - param_offset;
+        if (!sends[param])
+            return;
+        TempSendSetter _a_(sends[param], false);
+        if (format == 0)
+        {
+            osc_inline_typed_strstream data;
+            data << port; 
+            data << *(float *)buffer;
+            cli.send("/control", data);
+        }
+    }
+}
+
+void ext_plugin_gui::run_impl()
+{
+    srv.read_from_socket();
+    if (waitpid(child_pid, NULL, WNOHANG) != 0)
+    {
+        ext_ui_host->ui_closed(controller);
+        return;
+    }
+    if (feedback_sender && enable_graph_updates)
+        feedback_sender->update();
+}
+
+void ext_plugin_gui::receive_osc_message(std::string address, std::string args, osc_strstream &buffer)
+{
+    if (address == "/bridge/update" && args == "s")
+    {
+        if (confirmed)
+        {
+            g_warning("Update message already received, ignoring");
+            return;
+        }
+        string url;
+        buffer >> url;
+        cli.bind();
+        cli.set_url(url.c_str());
+        if (get_line_graph_iface())
+        {
+            feedback_sender = new dssi_feedback_sender(&cli, get_line_graph_iface());
+            feedback_sender->add_graphs(plugin_metadata->get_param_props(0), param_count);
+        }
+        confirmed = true;
+    }
+    else
+    if (address == "/bridge/control" && args == "if")
+    {
+        int port;
+        float value;
+        buffer >> port >> value;
+        assert(port >= param_offset);
+        send_float_to_host(port - param_offset, value);
+    }
+    else
+    if (address == "/bridge/enable_updates" && args == "i")
+    {
+        int updates;
+        buffer >> updates;
+        enable_graph_updates = updates != 0;
+        if (enable_graph_updates && feedback_sender)
+            feedback_sender->update();
+    }
+    else
+    if (address == "/bridge/configure" && (args == "s" || args == "ss"))
+    {
+        string key, value;
+        buffer >> key;
+        if (args == "ss")
+        {
+            buffer >> value;
+            plugin_proxy_base::configure(key.c_str(), value.c_str());
+        }
+        else
+            plugin_proxy_base::configure(key.c_str(), NULL);
+    }
+    else
+    if (address == "/bridge/send_status" && args == "i")
+    {
+        if (instance)
+        {
+            int serial;
+            buffer >> serial;
+
+            status_data.clear();
+            status_data << (uint32_t)instance->send_status_updates(this, serial);
+            cli.send("/status_data", status_data);
+        }
+    }
+    else
+        srv.dump.receive_osc_message(address, args, buffer);
+}
+
+ext_plugin_gui::~ext_plugin_gui()
+{
+    if (confirmed)
+    {
+        cli.send("/quit");
+    }
+    if (feedback_sender)
+        delete feedback_sender;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+LV2UI_Handle extgui_instantiate(const struct _LV2UI_Descriptor* descriptor,
+                          const char*                     plugin_uri,
+                          const char*                     bundle_path,
+                          LV2UI_Write_Function            write_function,
+                          LV2UI_Controller                controller,
+                          LV2UI_Widget*                   widget,
+                          const LV2_Feature* const*       features)
+{
+    const plugin_metadata_iface *plugin_metadata = plugin_registry::instance().get_by_uri(plugin_uri);
+    if (!plugin_metadata)
+        return false;
+    
+    ext_plugin_gui *ui = new ext_plugin_gui(plugin_metadata, write_function, controller, features);
+    if (!ui->initialise())
+        return NULL;
+    
+    string url = ui->srv.get_url() + "/bridge";
+    const gchar *argv[] = { "./calf_gtk", url.c_str(), "calf.so", plugin_uri, (ui->ext_ui_host->plugin_human_id ? ui->ext_ui_host->plugin_human_id : "Unknown"), NULL };
+    GError *error = NULL;
+    if (g_spawn_async(bundle_path, (gchar **)argv, NULL, (GSpawnFlags)G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &ui->child_pid, &error))
+    {
+        // wait for the sign of life from the GUI
+        while(!ui->confirmed && waitpid(ui->child_pid, NULL, WNOHANG) == 0)
+        {
+            printf("Waiting for the GUI to open\n");
+            ui->srv.read_from_socket();
+            usleep(500000);
+        }
+        
+        if (ui->confirmed)
+        {
+            *(LV2_External_UI_Widget **)widget = ui;
+            ui->enable_all_sends();
+            return (LV2UI_Handle)ui;
+        }
+        else
+        {
+            g_warning("The GUI exited before establishing contact with the host");
+            return NULL;
+        }
+    }
+    else
+    {
+        g_warning("%s", error->message);
+        return NULL;
+    }
+}
+
+void extgui_cleanup(LV2UI_Handle handle)
+{
+    ext_plugin_gui *gui = (ext_plugin_gui *)handle;
+    delete gui;
+}
+
+void extgui_port_event(LV2UI_Handle handle, uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer)
+{
+    ((ext_plugin_gui *)handle)->port_event_impl(port, buffer_size, format, buffer);;
+}
+
+void extgui_select_program(LV2UI_Handle handle, uint32_t bank, uint32_t program)
+{
+    ((ext_plugin_gui *)handle)->activate_preset(bank, program);
+}
+
+const void *extgui_extension(const char *uri)
+{
+    printf("extgui_extension %s\n", uri);
+    static LV2_Programs_UI_Interface uiProgramsExt = { extgui_select_program };
+    if (strcmp(uri, LV2_PROGRAMS__UIInterface) == 0)
+        return &uiProgramsExt;
     return NULL;
 }
 
 const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
 {
+#if USE_LV2_GTK_GUI
     static LV2UI_Descriptor gtkgui;
     gtkgui.URI = "http://calf.sourceforge.net/plugins/gui/gtk2-gui";
     gtkgui.instantiate = gui_instantiate;
@@ -345,7 +641,15 @@
     gtkgui.extension_data = gui_extension;
     if (!index--)
         return &gtkgui;
+#endif
+    static LV2UI_Descriptor extgui;
+    extgui.URI = "http://calf.sourceforge.net/plugins/gui/ext-gui";
+    extgui.instantiate = extgui_instantiate;
+    extgui.cleanup = extgui_cleanup;
+    extgui.port_event = extgui_port_event;
+    extgui.extension_data = extgui_extension;
+    if (!index--)
+        return &extgui;
     
     return NULL;
 }
-
diff -U 3 -H -b -d -r -N -- calf-old/src/makerdf.cpp calf-master/src/makerdf.cpp
--- calf-old/src/makerdf.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/makerdf.cpp	2013-09-02 18:18:52.409435537 +0100
@@ -22,8 +22,10 @@
 #include <calf/preset.h>
 #include <calf/utils.h>
 #if USE_LV2
-#include <lv2.h>
+#include <calf/lv2.h>
 #include <calf/lv2_event.h>
+#include <calf/lv2_external_ui.h>
+#include <calf/lv2_programs.h>
 #include <calf/lv2_state.h>
 #include <calf/lv2_uri_map.h>
 #endif
@@ -54,6 +56,118 @@
     return f;
 }
 
+#if USE_LADSPA
+
+static std::string unit_to_string(const parameter_properties &props)
+{
+    uint32_t flags = props.flags & PF_UNITMASK;
+    
+    switch(flags) {
+        case PF_UNIT_DB:
+            return "ladspa:hasUnit=\"&ladspa;dB\" ";
+        case PF_UNIT_COEF:
+            return "ladspa:hasUnit=\"&ladspa;coef\" ";
+        case PF_UNIT_HZ:
+            return "ladspa:hasUnit=\"&ladspa;Hz\" ";
+        case PF_UNIT_SEC:
+            return "ladspa:hasUnit=\"&ladspa;seconds\" ";
+        case PF_UNIT_MSEC:
+            return "ladspa:hasUnit=\"&ladspa;milliseconds\" ";
+        default:
+            return string();
+    }
+}
+
+static std::string scale_to_string(const parameter_properties &props)
+{
+    if ((props.flags & PF_TYPEMASK) != PF_ENUM) {
+        return "/";
+    }
+    string tmp = "><ladspa:hasScale><ladspa:Scale>\n";
+    for (int i = (int)props.min; i <= (int)props.max; i++) {
+        tmp += "          <ladspa:hasPoint><ladspa:Point rdf:value=\""+i2s(i)+"\" ladspa:hasLabel=\""+props.choices[(int)(i - props.min)]+"\" /></ladspa:hasPoint>\n";
+    }
+    return tmp+"        </ladspa:Scale></ladspa:hasScale></ladspa:InputControlPort";
+}
+
+std::string generate_ladspa_rdf(const ladspa_plugin_info &info, const parameter_properties *params, const char *param_names[], unsigned int count,
+                                       unsigned int ctl_ofs)
+{
+    string rdf;
+    string plugin_id = "&ladspa;" + i2s(info.unique_id);
+    string plugin_type = string(info.plugin_type); 
+    
+    rdf += "  <ladspa:" + plugin_type + " rdf:about=\"" + plugin_id + "\">\n";
+    rdf += "    <dc:creator>" + xml_escape(info.maker) + "</dc:creator>\n";
+    rdf += "    <dc:title>" + xml_escape(info.name) + "</dc:title>\n";
+    
+    for (unsigned int i = 0; i < count; i++) {
+        rdf += 
+            "    <ladspa:hasPort>\n"
+            "      <ladspa:" + string(params[i].flags & PF_PROP_OUTPUT ? "Output" : "Input") 
+            + "ControlPort rdf:about=\"" + plugin_id + "."+i2s(ctl_ofs + i)+"\" "
+            + unit_to_string(params[i]) +
+            "ladspa:hasLabel=\"" + params[i].short_name + "\" "
+            + scale_to_string(params[i]) + 
+            ">\n"
+            "    </ladspa:hasPort>\n";
+    }
+    rdf += "    <ladspa:hasSetting>\n"
+        "      <ladspa:Default>\n";
+    for (unsigned int i = 0; i < count; i++) {
+        rdf += 
+            "        <ladspa:hasPortValue>\n"
+            "           <ladspa:PortValue rdf:value=\"" + f2s(params[i].def_value) + "\">\n"
+            "             <ladspa:forPort rdf:resource=\"" + plugin_id + "." + i2s(ctl_ofs + i) + "\"/>\n"
+            "           </ladspa:PortValue>\n"
+            "        </ladspa:hasPortValue>\n";
+    }
+    rdf += "      </ladspa:Default>\n"
+        "    </ladspa:hasSetting>\n";
+
+    rdf += "  </ladspa:" + plugin_type + ">\n";
+    return rdf;
+}
+
+void make_rdf()
+{
+    string rdf;
+    rdf = 
+        "<?xml version='1.0' encoding='ISO-8859-1'?>\n"
+        "<!DOCTYPE rdf:RDF [\n"
+        "  <!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n"
+        "  <!ENTITY rdfs 'http://www.w3.org/2000/01/rdf-schema#'>\n"
+        "  <!ENTITY dc 'http://purl.org/dc/elements/1.1/'>\n"
+        "  <!ENTITY ladspa 'http://ladspa.org/ontology#'>\n"
+        "]>\n";
+    
+    rdf += "<rdf:RDF xmlns:rdf=\"&rdf;\" xmlns:rdfs=\"&rdfs;\" xmlns:dc=\"&dc;\" xmlns:ladspa=\"&ladspa;\">\n";
+
+    const plugin_registry::plugin_vector &plugins = plugin_registry::instance().get_all();
+    set<int> used_ids;
+    for (unsigned int i = 0; i < plugins.size(); i++)
+    {
+        const plugin_metadata_iface *p = plugins[i];
+        const ladspa_plugin_info &info = p->get_plugin_info();
+        
+        if(used_ids.count(info.unique_id))
+        {
+            fprintf(stderr, "ERROR: Duplicate ID %d in plugin %s\n", info.unique_id, info.name);
+            assert(0);
+        }
+        used_ids.insert(info.unique_id);
+
+        if (!p->requires_midi()) {
+            rdf += generate_ladspa_rdf(info, p->get_param_props(0), p->get_port_names(), p->get_param_count(), p->get_param_port_offset());
+        }
+        delete p;
+    }    
+    rdf += "</rdf:RDF>\n";
+    
+    printf("%s\n", rdf.c_str());
+}
+#endif
+
 #if USE_LV2
 static void add_port(string &ports, const char *symbol, const char *name, const char *direction, int pidx, const char *type = "lv2:AudioPort", bool optional = false)
 {
@@ -230,11 +344,19 @@
     string gui_header;
     
 #if USE_LV2_GUI
+#if USE_LV2_GTK_GUI
     string gtkgui_uri = "<http://calf.sourceforge.net/plugins/gui/gtk2-gui>";
     gui_header = gtkgui_uri + "\n"
         "    a uiext:GtkUI ;\n"
         "    uiext:binary <calflv2gui.so> ;\n"
-        "    uiext:requiredFeature uiext:makeResident .\n"
+        "    lv2:optionalFeature uiext:noUserResize .\n"
+        "\n"
+    ;
+#endif
+    string extgui_uri = "<http://calf.sourceforge.net/plugins/gui/ext-gui>";
+    gui_header += extgui_uri + "\n"
+        "    a <" LV2_EXTERNAL_UI__Widget "> ;\n"
+        "    uiext:binary <calflv2gui.so> .\n"
         "\n"
     ;
 #endif
@@ -259,7 +381,10 @@
             if (props.flags & PF_PROP_OUTPUT)
             {
                 string portnot = " uiext:portNotification [\n    uiext:plugin " + uri + " ;\n    uiext:portIndex " + i2s(j) + "\n] .\n\n";
+#if USE_LV2_GTK_GUI
                 ttl += gtkgui_uri + portnot;
+#endif
+                ttl += extgui_uri + portnot;
             }
         }
 #endif
@@ -289,7 +414,17 @@
         ttl += "    doap:maintainer [ foaf:name \""+string(lpi.maker)+"\" ; ] ;\n";
 
 #if USE_LV2_GUI
+#if USE_LV2_GTK_GUI
+        if (strcasecmp(lpi.label, "analyzer") != 0)
+        {
+            ttl += "    uiext:ui <http://calf.sourceforge.net/plugins/gui/ext-gui> ,\n";
+            ttl += "             <http://calf.sourceforge.net/plugins/gui/gtk2-gui> ;\n";
+        }
+        else
         ttl += "    uiext:ui <http://calf.sourceforge.net/plugins/gui/gtk2-gui> ;\n";
+#else
+        ttl += "    uiext:ui <http://calf.sourceforge.net/plugins/gui/ext-gui> ;\n";
+#endif
         ttl += "    lv2:optionalFeature <http://lv2plug.in/ns/ext/instance-access> ;\n";
         ttl += "    lv2:optionalFeature <http://lv2plug.in/ns/ext/data-access> ;\n";
 #endif
@@ -310,6 +445,8 @@
             }
         }
         
+        ttl += "    lv2:extensionData <" LV2_PROGRAMS__Interface "> ;\n";
+
         if (pi->get_configure_vars())
         {
             ttl += "    lv2:extensionData <" LV2_STATE__interface "> ;\n";
@@ -389,7 +526,9 @@
         string uri = "<http://calf.sourceforge.net/factory_presets#"
             + pr.plugin + "_" + pr.get_safe_name()
             + ">";
-        ttl += string("<" + plugin_uri_prefix + ilm->second + "> lv2p:hasPreset\n    " + uri + " .\n");
+        ttl += uri + " a lv2p:Preset ;\n"
+            + "    lv2:appliesTo <" + plugin_uri_prefix + ilm->second + "> ;\n"
+            + "    rdfs:seeAlso <presets-" + ilm->second + ".ttl> .\n";
         
         presets_ttl += uri + 
             " a lv2p:Preset ;\n"
@@ -426,11 +565,7 @@
             + string(plugins[i]->get_plugin_info().label)
 	        + "> a lv2:Plugin ;\n    dct:replaces <urn:ladspa:"
 	        + i2s(plugins[i]->get_plugin_info().unique_id) + "> ;\n    "
-	        + "lv2:binary <calf.so> ; rdfs:seeAlso <" + label + ".ttl> ";
-        if (preset_data.count(label))
-            ttl += ", <presets-" + label + ".ttl>";
-        ttl += ".\n";
-        
+            + "lv2:binary <calf.so> ; rdfs:seeAlso <" + label + ".ttl> .\n";
     }
     FILE *f = open_and_check(path_prefix+"manifest.ttl");
     fprintf(f, "%s\n", ttl.c_str());
@@ -579,7 +714,7 @@
         switch(c) {
             case 'h':
             case '?':
-                printf("LV2 TTL / XML GUI generator for Calf plugin pack\nSyntax: %s [--help] [--version] [--mode rdf|ttl|gui] [--path <path>]\n", argv[0]);
+                printf("LADSPA RDF / LV2 TTL / XML GUI generator for Calf plugin pack\nSyntax: %s [--help] [--version] [--mode rdf|ttl|gui] [--path <path>]\n", argv[0]);
                 return 0;
             case 'v':
                 printf("%s\n", PACKAGE_STRING);
@@ -606,6 +741,10 @@
     if (false)
     {
     }
+#if USE_LADSPA
+    else if (mode == "rdf")
+        make_rdf();
+#endif
 #if USE_LV2
     else if (mode == "ttl")
         make_ttl(path_prefix);
diff -U 3 -H -b -d -r -N -- calf-old/src/metadata.cpp calf-master/src/metadata.cpp
--- calf-old/src/metadata.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/metadata.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -754,7 +754,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(equalizer5band) = { 0x8511, "Equalizer5Band", "Calf Equalizer 5 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
+CALF_PLUGIN_INFO(equalizer5band) = { 0x8511, "eq5", "Calf Equalizer 5 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EQPlugin" };
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -774,7 +774,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(equalizer8band) = { 0x8512, "Equalizer8Band", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
+CALF_PLUGIN_INFO(equalizer8band) = { 0x8512, "eq8", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EQPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -796,7 +796,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(equalizer12band) = { 0x8513, "Equalizer12Band", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
+CALF_PLUGIN_INFO(equalizer12band) = { 0x8513, "eq12", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EQPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -816,7 +816,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(pulsator) = { 0x8514, "Pulsator", "Calf Pulsator", "Markus Schmidt", calf_plugins::calf_copyright_info, "ModulationPlugin" };
+CALF_PLUGIN_INFO(pulsator) = { 0x8514, "Pulsator", "Calf Pulsator", "Markus Schmidt", calf_plugins::calf_copyright_info, "ModulatorPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -933,7 +933,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(mono) = { 0x8589, "MonoInput", "Calf Mono Input", "Markus Schmidt", calf_plugins::calf_copyright_info, "Utility" };
+CALF_PLUGIN_INFO(mono) = { 0x8589, "mono", "Calf Mono Input", "Markus Schmidt", calf_plugins::calf_copyright_info, "UtilityPlugin" };
 
 
 ////////////////////////////////////////////////////////////////////////////
@@ -979,7 +979,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(stereo) = { 0x8588, "StereoTools", "Calf Stereo Tools", "Markus Schmidt", calf_plugins::calf_copyright_info, "Utility" };
+CALF_PLUGIN_INFO(stereo) = { 0x8588, "stereo", "Calf Stereo Tools", "Markus Schmidt", calf_plugins::calf_copyright_info, "UtilityPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -1020,7 +1020,7 @@
     {}
 };
 
-CALF_PLUGIN_INFO(analyzer) = { 0x8588, "Analyzer", "Calf Analyzer", "Christian Holschuh / Markus Schmidt", calf_plugins::calf_copyright_info, "Analyzer" };
+CALF_PLUGIN_INFO(analyzer) = { 0x8587, "Analyzer", "Calf Analyzer", "Christian Holschuh / Markus Schmidt", calf_plugins::calf_copyright_info, "UtilityPlugin" };
 
 
 
diff -U 3 -H -b -d -r -N -- calf-old/src/modules.cpp calf-master/src/modules.cpp
--- calf-old/src/modules.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/modules.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -1754,6 +1754,8 @@
     // 2: boxes (little things on the values position
     // 3: centered bars (0dB is centered in y direction)
     
+    if (mode) {
+
     if (_param_mode > 3 and _param_mode < 6) {
         // centered viewing modes like stereo image and stereo difference
         if(!*params[param_analyzer_view]) {
@@ -1785,6 +1787,7 @@
         // draw lines
         *mode = 0;
     }
+    } // if (mode)
     ____analyzer_sanitize = 0;
     return true;
 }
diff -U 3 -H -b -d -r -N -- calf-old/src/osctl_glib.cpp calf-master/src/osctl_glib.cpp
--- calf-old/src/osctl_glib.cpp	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/osctl_glib.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,44 @@
+/* Calf DSP Library
+ * Open Sound Control UDP server support
+ *
+ * Copyright (C) 2007-2009 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#include <calf/osctl_glib.h>
+
+using namespace osctl;
+using namespace std;
+
+void osc_glib_server::on_bind()
+{    
+    ioch = g_io_channel_unix_new(socket);
+    srcid = g_io_add_watch(ioch, G_IO_IN, on_data, this);
+}
+
+gboolean osc_glib_server::on_data(GIOChannel *channel, GIOCondition cond, void *obj)
+{
+    osc_server *self = (osc_server *)obj;
+    self->read_from_socket();
+    return TRUE;
+}
+
+osc_glib_server::~osc_glib_server()
+{
+    if (ioch)
+        g_source_remove(srcid);
+}
diff -U 3 -H -b -d -r -N -- calf-old/src/osctlnet.cpp calf-master/src/osctlnet.cpp
--- calf-old/src/osctlnet.cpp	1970-01-01 01:00:00.000000000 +0100
+++ calf-master/src/osctlnet.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -0,0 +1,167 @@
+/* Calf DSP Library
+ * Open Sound Control UDP support
+ *
+ * Copyright (C) 2007-2009 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+#include <calf/osctl.h>
+#include <calf/osctlnet.h>
+#include <assert.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+#include <sstream>
+#include <stdio.h>
+#include <unistd.h>
+using namespace osctl;
+using namespace std;
+
+void osc_socket::bind(const char *hostaddr, int port)
+{
+    socket = ::socket(PF_INET, SOCK_DGRAM, 0);
+    if (socket < 0)
+        throw osc_net_exception("socket");
+    
+    sockaddr_in sadr;
+    memset(&sadr, 0, sizeof(sadr));
+    sadr.sin_family = AF_INET;
+    sadr.sin_port = htons(port);
+    inet_aton(hostaddr, &sadr.sin_addr);
+    if (::bind(socket, (sockaddr *)&sadr, sizeof(sadr)) < 0)
+        throw osc_net_exception("bind");
+    on_bind();
+}
+
+std::string osc_socket::get_url() const
+{
+    sockaddr_in sadr;
+    socklen_t len = sizeof(sadr);
+    if (getsockname(socket, (sockaddr *)&sadr, &len) < 0)
+        throw osc_net_exception("getsockname");
+    
+    char name[INET_ADDRSTRLEN], buf[32];
+    
+    inet_ntop(AF_INET, &sadr.sin_addr, name, INET_ADDRSTRLEN);
+    sprintf(buf, "%d", ntohs(sadr.sin_port));
+    
+    return string("osc.udp://") + name + ":" + buf + prefix;
+}
+
+osc_socket::~osc_socket()
+{
+    close(socket);
+}
+
+//////////////////////////////////////////////////////////////
+
+void osc_client::set_addr(const char *hostaddr, int port)
+{
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    inet_aton(hostaddr, &addr.sin_addr);
+}
+
+void osc_client::set_url(const char *url)
+{
+    const char *orig_url = url;
+    if (strncmp(url, "osc.udp://", 10))
+        throw osc_net_bad_address(url);
+    url += 10;
+    
+    const char *pos = strchr(url, ':');
+    const char *pos2 = strchr(url, '/');
+    if (!pos || !pos2)
+        throw osc_net_bad_address(orig_url);
+    
+    // XXXKF perhaps there is a default port for osc.udp?
+    if (pos2 - pos < 0)
+        throw osc_net_bad_address(orig_url);
+    
+    string hostname = string(url, pos - url);
+    int port = atoi(pos + 1);
+    prefix = string(pos2);
+    printf("hostname %s port %d\n", hostname.c_str(), port);
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+
+    hostent *he = gethostbyname(hostname.c_str());
+    if (!he)
+        throw osc_net_dns_exception("gethostbyname");
+    
+    addr.sin_addr = *(struct in_addr *)he->h_addr;
+}
+
+bool osc_client::send(const std::string &address, osctl::osc_typed_strstream &stream)
+{
+    std::string type_tag = "," + stream.type_buffer->data;
+    osc_inline_strstream hdr;
+    hdr << prefix + address << "," + stream.type_buffer->data;
+    string str = hdr.data + stream.buffer.data;
+    
+    // printf("sending %s\n", str.buffer.c_str());
+
+    return ::sendto(socket, str.data(), str.length(), 0, (sockaddr *)&addr, sizeof(addr)) == (int)str.length();
+}
+
+bool osc_client::send(const std::string &address)
+{
+    osc_inline_strstream hdr;
+    hdr << prefix + address << ",";
+    
+    return ::sendto(socket, hdr.data.data(), hdr.data.length(), 0, (sockaddr *)&addr, sizeof(addr)) == (int)hdr.data.length();
+}
+
+void osc_server::parse_message(const char *buffer, int len)
+{
+    osctl::string_buffer buf(string(buffer, len));
+    osc_strstream str(buf);
+    string address, type_tag;
+    str >> address;
+    str >> type_tag;
+    // cout << "Address " << address << " type tag " << type_tag << endl << flush;
+    if (!address.empty() && address[0] == '/'
+      &&!type_tag.empty() && type_tag[0] == ',')
+    {
+        sink->receive_osc_message(address, type_tag.substr(1), str);
+    }
+}
+
+void osc_server::read_from_socket()
+{
+    do {
+        char buf[65536];
+        int len = recv(socket, buf, 65536, MSG_DONTWAIT);
+        if (len > 0)
+        {
+            if (buf[0] == '/')
+            {
+                parse_message(buf, len);
+            }
+            if (buf[0] == '#')
+            {
+                // XXXKF bundles are not supported yet
+            }
+        }
+        else
+            break;
+    } while(1);
+}
+
+osc_server::~osc_server()
+{
+}
diff -U 3 -H -b -d -r -N -- calf-old/src/plugin.cpp calf-master/src/plugin.cpp
--- calf-old/src/plugin.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/plugin.cpp	2013-09-02 18:23:31.366948088 +0100
@@ -19,6 +19,7 @@
  * Boston, MA  02110-1301  USA
  */
 #include <config.h>
+#include <calf/ladspa_wrap.h>
 #include <calf/lv2wrap.h>
 #include <calf/modules.h>
 #include <calf/modules_comp.h>
@@ -29,8 +30,451 @@
 #include <calf/modules_mod.h>
 #include <calf/modules_synths.h>
 #include <calf/organ.h>
+#include <calf/osctlnet.h>
 
 using namespace calf_plugins;
+using namespace osctl;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if USE_LADSPA
+
+ladspa_instance::ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate)
+{
+    module = _module;
+    metadata = module->get_metadata_iface();
+    ladspa = _ladspa;
+    
+    module->get_port_arrays(ins, outs, params);
+    
+    activate_flag = true;
+#if USE_DSSI
+    feedback_sender = NULL;
+#endif
+
+    module->set_sample_rate(sample_rate);
+    module->post_instantiate();
+}
+
+float ladspa_instance::get_param_value(int param_no)
+{
+    // XXXKF hack
+    if (param_no >= ladspa->param_count)
+        return 0;
+    return *params[param_no];
+}
+
+void ladspa_instance::set_param_value(int param_no, float value)
+{
+    // XXXKF hack
+    if (param_no >= ladspa->param_count)
+        return;
+    *params[param_no] = value;
+}
+
+bool ladspa_instance::activate_preset(int bank, int program)
+{
+    return false;
+}
+
+/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
+void ladspa_instance::run(unsigned long SampleCount)
+{
+    if (activate_flag)
+    {
+        module->activate();
+        activate_flag = false;
+    }
+    module->params_changed();
+    module->process_slice(0, SampleCount);
+}
+
+#if USE_DSSI
+
+void ladspa_instance::run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount)
+{
+    if (activate_flag)
+    {
+        module->activate();
+        activate_flag = false;
+    }
+    module->params_changed();
+    
+    uint32_t offset = 0;
+    for (uint32_t e = 0; e < EventCount; e++)
+    {
+        uint32_t timestamp = Events[e].time.tick;
+        if (timestamp != offset)
+            module->process_slice(offset, timestamp);
+        process_dssi_event(Events[e]);
+        offset = timestamp;
+    }
+    if (offset != SampleCount)
+        module->process_slice(offset, SampleCount);
+}
+
+#endif
+
+char *ladspa_instance::configure(const char *key, const char *value)
+{
+#if USE_DSSI_GUI
+    if (!strcmp(key, "OSC:FEEDBACK_URI"))
+    {
+        const line_graph_iface *lgi = dynamic_cast<const line_graph_iface *>(metadata);
+        //if (!lgi)
+        //    return NULL;
+        if (*value)
+        {
+            if (feedback_sender) {
+                delete feedback_sender;
+                feedback_sender = NULL;
+            }
+            feedback_sender = new dssi_feedback_sender(value, lgi);
+            feedback_sender->add_graphs(metadata->get_param_props(0), metadata->get_param_count());
+        }
+        else
+        {
+            if (feedback_sender) {
+                delete feedback_sender;
+                feedback_sender = NULL;
+            }
+        }
+        return NULL;
+    }
+    else 
+    if (!strcmp(key, "OSC:UPDATE"))
+    {
+        if (feedback_sender)
+            feedback_sender->update();
+        return NULL;
+    }
+    else 
+    if (!strcmp(key, "OSC:SEND_STATUS"))
+    {
+        if (!feedback_sender)
+            return NULL;
+        struct status_gatherer: public send_updates_iface
+        {
+            osc_inline_typed_strstream str;            
+            void send_status(const char *key, const char *value)
+            {
+                str << key << value;
+            }
+        } sg;
+        int serial = atoi(value);
+        serial = module->send_status_updates(&sg, serial);
+        sg.str << (uint32_t)serial;
+        feedback_sender->client->send("/status_data", sg.str);
+        return NULL;
+    }
+    else
+#endif
+    if (!strcmp(key, "ExecCommand"))
+    {
+        if (*value)
+        {
+            execute(atoi(value));
+        }
+        return NULL;
+    }
+    return module->configure(key, value);
+}
+
+template<class Module>
+ladspa_plugin_metadata_set ladspa_wrapper<Module>::output;
+
+#if USE_DSSI
+
+/// Utility function: handle MIDI event (only handles a subset in this version)
+void ladspa_instance::process_dssi_event(snd_seq_event_t &event)
+{
+    switch(event.type) {
+        case SND_SEQ_EVENT_NOTEON:
+            module->note_on(event.data.note.channel, event.data.note.note, event.data.note.velocity);
+            break;
+        case SND_SEQ_EVENT_NOTEOFF:
+            module->note_off(event.data.note.channel, event.data.note.note, event.data.note.velocity);
+            break;
+        case SND_SEQ_EVENT_PGMCHANGE:
+            module->program_change(event.data.control.channel, event.data.control.value);
+            break;
+        case SND_SEQ_EVENT_CONTROLLER:
+            module->control_change(event.data.control.channel, event.data.control.param, event.data.control.value);
+            break;
+        case SND_SEQ_EVENT_PITCHBEND:
+            module->pitch_bend(event.data.control.channel, event.data.control.value);
+            break;
+        case SND_SEQ_EVENT_CHANPRESS:
+            module->channel_pressure(event.data.control.channel, event.data.control.value);
+            break;
+    }
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// LADSPA callbacks
+
+/// LADSPA activate function (note that at this moment the ports are not set)
+static void cb_activate(LADSPA_Handle Instance)
+{
+    ((ladspa_instance *)(Instance))->activate_flag = true;
+}
+
+/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
+static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
+    ((ladspa_instance *)(Instance))->run(SampleCount);
+}
+
+/// LADSPA port connection function
+static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation)
+{
+    ladspa_instance *const mod = (ladspa_instance *)Instance;
+    
+    int first_out = mod->ladspa->input_count;
+    int first_param = first_out + mod->ladspa->output_count;
+    int ladspa_port_count = first_param + mod->ladspa->param_count;
+    
+    if ((int)port < first_out)
+        mod->ins[port] = DataLocation;
+    else if ((int)port < first_param)
+        mod->outs[port - first_out] = DataLocation;
+    else if ((int)port < ladspa_port_count) {
+        int i = port - first_param;
+        mod->params[i] = DataLocation;
+        *mod->params[i] = mod->metadata->get_param_props(i)->def_value;
+    }
+}
+
+
+/// LADSPA deactivate function
+static void cb_deactivate(LADSPA_Handle Instance) {
+    ((ladspa_instance *)(Instance))->module->deactivate();
+}
+
+/// LADSPA cleanup (delete instance) function
+static void cb_cleanup(LADSPA_Handle Instance) {
+    delete ((ladspa_instance *)(Instance));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// DSSI callbacks
+
+#if USE_DSSI
+/// DSSI "run synth" function, same as run() except it allows for event delivery
+static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount, 
+        snd_seq_event_t *Events, unsigned long EventCount) {
+    ((ladspa_instance *)(Instance))->run_synth(SampleCount, Events, EventCount);
+}
+
+/// DSSI configure function (named properties)
+static char *cb_configure(LADSPA_Handle Instance,
+                   const char *Key,
+                   const char *Value)
+{
+    return ((ladspa_instance *)(Instance))->configure(Key, Value);
+}
+
+/// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset
+static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index)
+{
+    ladspa_plugin_metadata_set *ladspa = ((ladspa_instance *)(Instance))->ladspa;
+    if (index > ladspa->presets->size())
+        return NULL;
+    if (index)
+        return &(*ladspa->preset_descs)[index - 1];
+    return &ladspa->dssi_default_program;
+}
+
+/// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset
+static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program)
+{
+    ladspa_instance *mod = (ladspa_instance *)Instance;
+    ladspa_plugin_metadata_set *ladspa = mod->ladspa;
+    unsigned int no = (Bank << 7) + Program - 1;
+    // printf("no = %d presets = %p:%d\n", no, presets, presets->size());
+    if (no == -1U) {
+        int rpc = ladspa->param_count;
+        for (int i =0 ; i < rpc; i++)
+            *mod->params[i] = mod->metadata->get_param_props(i)->def_value;
+        return;
+    }
+    if (no >= ladspa->presets->size())
+        return;
+    plugin_preset &p = (*ladspa->presets)[no];
+    // printf("activating preset %s\n", p.name.c_str());
+    p.activate(mod);
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ladspa_plugin_metadata_set::ladspa_plugin_metadata_set()
+{
+    metadata = NULL;
+    memset(&descriptor, 0, sizeof(descriptor));
+
+#if USE_DSSI
+    presets = NULL;
+    preset_descs = NULL;
+    memset(&descriptor_for_dssi, 0, sizeof(descriptor_for_dssi));
+    memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
+#endif
+}
+
+void ladspa_plugin_metadata_set::prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate))
+{
+    metadata = md;
+    
+    input_count = md->get_input_count();
+    output_count = md->get_output_count();
+    param_count = md->get_param_count(); // XXXKF ladspa_instance<Module>::real_param_count();
+    
+    const ladspa_plugin_info &plugin_info = md->get_plugin_info();
+    descriptor.UniqueID = plugin_info.unique_id;
+    descriptor.Label = plugin_info.label;
+    descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str());
+    descriptor.Maker = plugin_info.maker;
+    descriptor.Copyright = plugin_info.copyright;
+    descriptor.Properties = md->is_rt_capable() ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0;
+    descriptor.PortCount = input_count + output_count + param_count;
+    descriptor.PortNames = new char *[descriptor.PortCount];
+    descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount];
+    descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount];
+    int i;
+    for (i = 0; i < input_count + output_count; i++)
+    {
+        LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
+        ((int *)descriptor.PortDescriptors)[i] = i < input_count ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
+                                              : LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
+        prh.HintDescriptor = 0;
+        ((const char **)descriptor.PortNames)[i] = md->get_port_names()[i];
+    }
+    for (; i < input_count + output_count + param_count; i++)
+    {
+        LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
+        const parameter_properties &pp = *md->get_param_props(i - input_count - output_count);
+        ((int *)descriptor.PortDescriptors)[i] = 
+            LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT);
+        prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW;
+        ((const char **)descriptor.PortNames)[i] = pp.name;
+        prh.LowerBound = pp.min;
+        prh.UpperBound = pp.max;
+        switch(pp.flags & PF_TYPEMASK) {
+            case PF_BOOL: 
+                prh.HintDescriptor |= LADSPA_HINT_TOGGLED;
+                prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW);
+                break;
+            case PF_INT: 
+            case PF_ENUM: 
+                prh.HintDescriptor |= LADSPA_HINT_INTEGER;
+                break;
+            default: {
+                int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min));
+                if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG)
+                    defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min));
+                if (defpt < 12)
+                    prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
+                else if (defpt < 37)
+                    prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
+                else if (defpt < 63)
+                    prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
+                else if (defpt < 88)
+                    prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
+                else
+                    prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
+            }
+        }
+        if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) {
+            prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK;
+            if (pp.def_value == 1)
+                prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1;
+            else if (pp.def_value == 100)
+                prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100;
+            else if (pp.def_value == 440)
+                prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440;
+            else
+                prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0;
+        }
+        switch(pp.flags & PF_SCALEMASK) {
+            case PF_SCALE_LOG:
+                prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
+                break;
+        }
+    }
+    descriptor.ImplementationData = this;
+    descriptor.instantiate = cb_instantiate;
+    descriptor.connect_port = cb_connect;
+    descriptor.activate = cb_activate;
+    descriptor.run = cb_run;
+    descriptor.run_adding = NULL;
+    descriptor.set_run_adding_gain = NULL;
+    descriptor.deactivate = cb_deactivate;
+    descriptor.cleanup = cb_cleanup;
+    prepare_dssi();
+}
+
+void ladspa_plugin_metadata_set::prepare_dssi()
+{
+#if USE_DSSI
+    const ladspa_plugin_info &plugin_info = metadata->get_plugin_info();
+    memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor));
+    descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str());
+    memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
+    dssi_descriptor.DSSI_API_Version = 1;
+    dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi;
+    dssi_descriptor.configure = cb_configure;
+    dssi_descriptor.get_program = cb_get_program;
+    dssi_descriptor.select_program = cb_select_program;
+    if (metadata->get_midi())
+        dssi_descriptor.run_synth = cb_run_synth;
+    
+    presets = new std::vector<plugin_preset>;
+    preset_descs = new std::vector<DSSI_Program_Descriptor>;
+
+    preset_list plist_tmp, plist;
+    plist.load_defaults(true);
+    plist_tmp.load_defaults(false);
+    plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
+    
+    // XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label
+    // if I forget about this, I'll be in a deep trouble
+    dssi_default_program.Bank = 0;
+    dssi_default_program.Program = 0;
+    dssi_default_program.Name = "default";
+
+    int pos = 1;
+    for (unsigned int i = 0; i < plist.presets.size(); i++)
+    {
+        plugin_preset &pp = plist.presets[i];
+        if (strcasecmp(pp.plugin.c_str(), descriptor.Label))
+            continue;
+        DSSI_Program_Descriptor pd;
+        pd.Bank = pos >> 7;
+        pd.Program = pos++;
+        pd.Name = pp.name.c_str();
+        preset_descs->push_back(pd);
+        presets->push_back(pp);
+    }
+#endif
+}
+
+ladspa_plugin_metadata_set::~ladspa_plugin_metadata_set()
+{
+    delete []descriptor.PortNames;
+    delete []descriptor.PortDescriptors;
+    delete []descriptor.PortRangeHints;
+#if USE_DSSI
+    if (presets)
+        presets->clear();
+    if (preset_descs)
+        preset_descs->clear();
+    delete presets;
+    delete preset_descs;
+#endif
+}
+
+#endif
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -39,6 +483,8 @@
 template<class Module> LV2_Descriptor calf_plugins::lv2_wrapper<Module>::descriptor;
 template<class Module> LV2_Calf_Descriptor calf_plugins::lv2_wrapper<Module>::calf_descriptor;
 template<class Module> LV2_State_Interface calf_plugins::lv2_wrapper<Module>::state_iface;
+template<class Module> LV2_Programs_Interface calf_plugins::lv2_wrapper<Module>::programs_iface;
+template<class Module> LV2_Program_Descriptor calf_plugins::lv2_wrapper<Module>::lv2_default_program;
 
 extern "C" {
 
@@ -53,6 +499,37 @@
 
 #endif
 
+#if USE_LADSPA
+extern "C" {
+
+const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
+{
+    // Analyzer useless on LADSPA
+    if (Index == 28) return NULL;
+    #define PER_MODULE_ITEM(name, isSynth, jackname) if (!isSynth && !(Index--)) return &ladspa_wrapper<name##_audio_module>::get().descriptor;
+    #include <calf/modulelist.h>
+    return NULL;
+}
+
+};
+
+#if USE_DSSI
+extern "C" {
+
+const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
+{
+    // Analyzer not implemented in external-ui
+    if (Index == 28) return NULL;
+    #define PER_MODULE_ITEM(name, isSynth, jackname) if (!(Index--)) return &calf_plugins::ladspa_wrapper<name##_audio_module>::get().dssi_descriptor;
+    #include <calf/modulelist.h>
+    return NULL;
+}
+
+};
+#endif
+
+#endif
+
 #if USE_JACK
 
 extern "C" {
diff -U 3 -H -b -d -r -N -- calf-old/src/wavetable.cpp calf-master/src/wavetable.cpp
--- calf-old/src/wavetable.cpp	2012-10-21 16:24:24.000000000 +0100
+++ calf-master/src/wavetable.cpp	2012-12-31 00:14:37.000000000 +0000
@@ -21,7 +21,7 @@
 
 #include <config.h>
 
-#if ENABLE_EXPERIMENTAL
+#if 0 // ENABLE_EXPERIMENTAL
     
 #include <calf/giface.h>
 #include <calf/modules_synths.h>
