summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/lv2/README18
-rw-r--r--ext/lv2/gstlv2.c175
-rw-r--r--ext/lv2/gstlv2.h20
3 files changed, 119 insertions, 94 deletions
diff --git a/ext/lv2/README b/ext/lv2/README
new file mode 100644
index 00000000..d1431b77
--- /dev/null
+++ b/ext/lv2/README
@@ -0,0 +1,18 @@
+Gst-LV2 Quickstart
+
+Dependencies:
+
+SLV2 0.6.* <http://drobilla.net/software/slv2>
+
+Which in turn depends on:
+
+librdf (redland) >= 1.0.6 <http://librdf.org>
+
+
+Example Pipeline:
+
+Requires swh-lv2 <http://plugin.org.uk/releases/>
+
+gst-launch-0.10 -v filesrc location=/usr/share/sounds/login.wav ! wavparse ! audioconvert ! http---plugin-org-uk-swh-plugins-djFlanger ! audioconvert ! alsasink
+
+(A longer wav will be a better example)
diff --git a/ext/lv2/gstlv2.c b/ext/lv2/gstlv2.c
index 5d05f603..533d9d47 100644
--- a/ext/lv2/gstlv2.c
+++ b/ext/lv2/gstlv2.c
@@ -24,6 +24,7 @@
#endif
#include <string.h>
#include <math.h>
+#include <glib.h>
#include <gst/audio/audio.h>
#include <gst/controller/gstcontroller.h>
@@ -59,6 +60,13 @@ static GstPlugin *gst_lv2_plugin;
GST_DEBUG_CATEGORY_STATIC (lv2_debug);
#define GST_CAT_DEFAULT lv2_debug
+static gint
+gst_lv2_value_cmp (gconstpointer a, gconstpointer b)
+{
+ if (slv2_value_equals ((SLV2Value) a, (SLV2Value) b))
+ return 0;
+ return 1;
+}
static void
gst_lv2_base_init (gpointer g_class)
@@ -68,7 +76,8 @@ gst_lv2_base_init (gpointer g_class)
GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class);
GstElementDetails *details;
SLV2Plugin lv2plugin;
- SLV2Value val;
+ SLV2Value val, pred;
+ SLV2Values values;
guint j, audio_in_count, audio_out_count, control_in_count, control_out_count;
gchar *klass_tags;
@@ -149,36 +158,64 @@ gst_lv2_base_init (gpointer g_class)
g_free (details->author);
g_free (details);
- klass->audio_in_portnums = g_new0 (gint, gsp_class->num_audio_in);
- klass->audio_out_portnums = g_new0 (gint, gsp_class->num_audio_out);
- klass->control_in_portnums = g_new0 (gint, gsp_class->num_control_in);
- klass->control_out_portnums = g_new0 (gint, gsp_class->num_control_out);
+ klass->groups = NULL;
+
+ klass->audio_in_ports = g_new0 (struct _GstLV2Port, gsp_class->num_audio_in);
+ klass->audio_out_ports =
+ g_new0 (struct _GstLV2Port, gsp_class->num_audio_out);
+ klass->control_in_ports =
+ g_new0 (struct _GstLV2Port, gsp_class->num_control_in);
+ klass->control_out_ports =
+ g_new0 (struct _GstLV2Port, gsp_class->num_control_out);
audio_in_count = audio_out_count = control_in_count = control_out_count = 0;
+ pred = slv2_value_new_uri (world,
+ "http://lv2plug.in/ns/dev/port-groups#inGroup");
+
for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) {
SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j);
gboolean is_input = slv2_port_is_a (lv2plugin, port, input_class);
+ struct _GstLV2Port *desc = NULL;
if (slv2_port_is_a (lv2plugin, port, audio_class)) {
if (is_input)
- klass->audio_in_portnums[audio_in_count++] = j;
+ desc = &klass->audio_in_ports[audio_in_count++];
else
- klass->audio_out_portnums[audio_out_count++] = j;
+ desc = &klass->audio_out_ports[audio_out_count++];
} else if (slv2_port_is_a (lv2plugin, port, control_class)) {
if (is_input)
- klass->control_in_portnums[control_in_count++] = j;
+ desc = &klass->control_in_ports[control_in_count++];
else
- klass->control_out_portnums[control_out_count++] = j;
+ desc = &klass->control_out_ports[control_out_count++];
+ } else {
+ /* unknown port type */
+ continue;
+ }
+ desc->index = j;
+ values = slv2_port_get_value (lv2plugin, port, pred);
+ if (slv2_values_size (values) > 0) {
+ SLV2Value v = slv2_values_get_at (values, 0);
+ desc->group = v;
+ if (!g_slist_find_custom (klass->groups, v, gst_lv2_value_cmp)) {
+ klass->groups =
+ g_slist_prepend (klass->groups, slv2_value_duplicate (v));
+ }
}
+ slv2_values_free (values);
}
+ slv2_value_free (pred);
+
g_assert (audio_in_count == gsp_class->num_audio_in);
g_assert (audio_out_count == gsp_class->num_audio_out);
g_assert (control_in_count == gsp_class->num_control_in);
g_assert (control_out_count == gsp_class->num_control_out);
- /*if (!LV2_IS_INPLACE_BROKEN (desc->Properties))
- GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass); */
+ pred = slv2_value_new_uri (world,
+ "http://lv2plug.in/ns/lv2core#inPlaceBroken");
+ if (!slv2_plugin_has_feature (lv2plugin, pred))
+ GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass);
+ slv2_value_free (pred);
klass->plugin = lv2plugin;
}
@@ -274,7 +311,7 @@ gst_lv2_class_init (GstLV2Class * klass, SLV2Plugin lv2plugin)
for (i = 0; i < gsp_class->num_control_in; i++) {
GParamSpec *p;
- p = gst_lv2_class_get_param_spec (klass, klass->control_in_portnums[i]);
+ p = gst_lv2_class_get_param_spec (klass, klass->control_in_ports[i].index);
/* properties have an offset of 1 */
g_object_class_install_property (G_OBJECT_CLASS (klass), i + 1, p);
@@ -283,7 +320,7 @@ gst_lv2_class_init (GstLV2Class * klass, SLV2Plugin lv2plugin)
for (i = 0; i < gsp_class->num_control_out; i++) {
GParamSpec *p;
- p = gst_lv2_class_get_param_spec (klass, klass->control_out_portnums[i]);
+ p = gst_lv2_class_get_param_spec (klass, klass->control_out_ports[i].index);
/* properties have an offset of 1, and we already added num_control_in */
g_object_class_install_property (G_OBJECT_CLASS (klass),
@@ -294,19 +331,15 @@ gst_lv2_class_init (GstLV2Class * klass, SLV2Plugin lv2plugin)
static void
gst_lv2_init (GstLV2 * lv2, GstLV2Class * klass)
{
-#if 0
lv2->plugin = klass->plugin;
lv2->instance = NULL;
lv2->activated = FALSE;
- lv2->inplace_broken = LV2_IS_INPLACE_BROKEN (lv2->descriptor->Properties);
-#endif
}
static void
gst_lv2_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec)
{
-#if 0
GstSignalProcessor *gsp;
GstSignalProcessorClass *gsp_class;
@@ -322,7 +355,7 @@ gst_lv2_set_property (GObject * object, guint prop_id, const GValue * value,
/* now see what type it is */
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:
- gsp->control_in[prop_id] = g_value_get_boolean (value) ? 1.f : 0.f;
+ gsp->control_in[prop_id] = g_value_get_boolean (value) ? 0.0f : 1.0f;
break;
case G_TYPE_INT:
gsp->control_in[prop_id] = g_value_get_int (value);
@@ -333,14 +366,12 @@ gst_lv2_set_property (GObject * object, guint prop_id, const GValue * value,
default:
g_assert_not_reached ();
}
-#endif
}
static void
gst_lv2_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
-#if 0
GstSignalProcessor *gsp;
GstSignalProcessorClass *gsp_class;
gfloat *controls;
@@ -363,7 +394,7 @@ gst_lv2_get_property (GObject * object, guint prop_id, GValue * value,
/* now see what type it is */
switch (pspec->value_type) {
case G_TYPE_BOOLEAN:
- g_value_set_boolean (value, controls[prop_id] > 0.5);
+ g_value_set_boolean (value, controls[prop_id] > 0.0f);
break;
case G_TYPE_INT:
g_value_set_int (value, CLAMP (controls[prop_id], G_MININT, G_MAXINT));
@@ -374,64 +405,52 @@ gst_lv2_get_property (GObject * object, guint prop_id, GValue * value,
default:
g_return_if_reached ();
}
-#endif
}
static gboolean
gst_lv2_setup (GstSignalProcessor * gsp, guint sample_rate)
{
-#if 0
- GstLV2 *ladspa;
+ GstLV2 *lv2;
GstLV2Class *oclass;
GstSignalProcessorClass *gsp_class;
- LV2_Descriptor *desc;
int i;
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp);
- ladspa = (GstLV2 *) gsp;
+ lv2 = (GstLV2 *) gsp;
oclass = (GstLV2Class *) gsp_class;
- desc = ladspa->descriptor;
- g_return_val_if_fail (ladspa->handle == NULL, FALSE);
- g_return_val_if_fail (ladspa->activated == FALSE, FALSE);
+ g_return_val_if_fail (lv2->activated == FALSE, FALSE);
- GST_DEBUG_OBJECT (ladspa, "instantiating the plugin at %d Hz", sample_rate);
+ GST_DEBUG_OBJECT (lv2, "instantiating the plugin at %d Hz", sample_rate);
- ladspa->handle = desc->instantiate (desc, sample_rate);
+ lv2->instance = slv2_plugin_instantiate (oclass->plugin, sample_rate, NULL);
- g_return_val_if_fail (ladspa->handle != NULL, FALSE);
+ g_return_val_if_fail (lv2->instance != NULL, FALSE);
/* connect the control ports */
for (i = 0; i < gsp_class->num_control_in; i++)
- desc->connect_port (ladspa->handle,
- oclass->control_in_portnums[i], &(gsp->control_in[i]));
+ slv2_instance_connect_port (lv2->instance,
+ oclass->control_in_ports[i].index, &(gsp->control_in[i]));
for (i = 0; i < gsp_class->num_control_out; i++)
- desc->connect_port (ladspa->handle,
- oclass->control_out_portnums[i], &(gsp->control_out[i]));
-#endif
+ slv2_instance_connect_port (lv2->instance,
+ oclass->control_out_ports[i].index, &(gsp->control_out[i]));
+
return TRUE;
}
static gboolean
gst_lv2_start (GstSignalProcessor * gsp)
{
-#if 0
- GstLV2 *ladspa;
- LV2_Descriptor *desc;
-
- ladspa = (GstLV2 *) gsp;
- desc = ladspa->descriptor;
+ GstLV2 *lv2 = (GstLV2 *) gsp;
- g_return_val_if_fail (ladspa->activated == FALSE, FALSE);
- g_return_val_if_fail (ladspa->handle != NULL, FALSE);
+ g_return_val_if_fail (lv2->activated == FALSE, FALSE);
+ g_return_val_if_fail (lv2->instance != NULL, FALSE);
- GST_DEBUG_OBJECT (ladspa, "activating");
+ GST_DEBUG_OBJECT (lv2, "activating");
- if (desc->activate)
- desc->activate (ladspa->handle);
+ slv2_instance_activate (lv2->instance);
- ladspa->activated = TRUE;
-#endif
+ lv2->activated = TRUE;
return TRUE;
}
@@ -439,71 +458,53 @@ gst_lv2_start (GstSignalProcessor * gsp)
static void
gst_lv2_stop (GstSignalProcessor * gsp)
{
-#if 0
- GstLV2 *ladspa;
- LV2_Descriptor *desc;
+ GstLV2 *lv2 = (GstLV2 *) gsp;
- ladspa = (GstLV2 *) gsp;
- desc = ladspa->descriptor;
+ g_return_if_fail (lv2->activated == TRUE);
+ g_return_if_fail (lv2->instance != NULL);
- g_return_if_fail (ladspa->activated == TRUE);
- g_return_if_fail (ladspa->handle != NULL);
+ GST_DEBUG_OBJECT (lv2, "deactivating");
- GST_DEBUG_OBJECT (ladspa, "deactivating");
+ slv2_instance_deactivate (lv2->instance);
- if (desc->activate)
- desc->activate (ladspa->handle);
-
- ladspa->activated = FALSE;
-#endif
+ lv2->activated = FALSE;
}
static void
gst_lv2_cleanup (GstSignalProcessor * gsp)
{
-#if 0
- GstLV2 *ladspa;
- LV2_Descriptor *desc;
-
- ladspa = (GstLV2 *) gsp;
- desc = ladspa->descriptor;
+ GstLV2 *lv2 = (GstLV2 *) gsp;
- g_return_if_fail (ladspa->activated == FALSE);
- g_return_if_fail (ladspa->handle != NULL);
+ g_return_if_fail (lv2->activated == FALSE);
+ g_return_if_fail (lv2->instance != NULL);
- GST_DEBUG_OBJECT (ladspa, "cleaning up");
+ GST_DEBUG_OBJECT (lv2, "cleaning up");
- if (desc->cleanup)
- desc->cleanup (ladspa->handle);
+ slv2_instance_free (lv2->instance);
- ladspa->handle = NULL;
-#endif
+ lv2->instance = NULL;
}
static void
gst_lv2_process (GstSignalProcessor * gsp, guint nframes)
{
-#if 0
GstSignalProcessorClass *gsp_class;
- GstLV2 *ladspa;
+ GstLV2 *lv2;
GstLV2Class *oclass;
- LV2_Descriptor *desc;
guint i;
gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp);
- ladspa = (GstLV2 *) gsp;
+ lv2 = (GstLV2 *) gsp;
oclass = (GstLV2Class *) gsp_class;
- desc = ladspa->descriptor;
for (i = 0; i < gsp_class->num_audio_in; i++)
- desc->connect_port (ladspa->handle, oclass->audio_in_portnums[i],
- gsp->audio_in[i]);
+ slv2_instance_connect_port (lv2->instance,
+ oclass->audio_in_ports[i].index, gsp->audio_in[i]);
for (i = 0; i < gsp_class->num_audio_out; i++)
- desc->connect_port (ladspa->handle, oclass->audio_out_portnums[i],
- gsp->audio_out[i]);
+ slv2_instance_connect_port (lv2->instance,
+ oclass->audio_out_ports[i].index, gsp->audio_out[i]);
- desc->run (ladspa->handle, nframes);
-#endif
+ slv2_instance_run (lv2->instance, nframes);
}
/* search the plugin path
diff --git a/ext/lv2/gstlv2.h b/ext/lv2/gstlv2.h
index 389c03d1..836f1a0b 100644
--- a/ext/lv2/gstlv2.h
+++ b/ext/lv2/gstlv2.h
@@ -51,11 +51,15 @@ typedef struct _GstLV2Class GstLV2Class;
struct _GstLV2 {
GstSignalProcessor parent;
- SLV2Plugin *plugin;
- SLV2Instance *instance;
+ SLV2Plugin plugin;
+ SLV2Instance instance;
gboolean activated;
- gboolean inplace_broken;
+};
+
+struct _GstLV2Port {
+ gint index;
+ SLV2Value group;
};
struct _GstLV2Class {
@@ -63,10 +67,12 @@ struct _GstLV2Class {
SLV2Plugin plugin;
- gint *audio_in_portnums;
- gint *audio_out_portnums;
- gint *control_in_portnums;
- gint *control_out_portnums;
+ GSList *groups;
+
+ struct _GstLV2Port *audio_in_ports;
+ struct _GstLV2Port *audio_out_ports;
+ struct _GstLV2Port *control_in_ports;
+ struct _GstLV2Port *control_out_ports;
};