summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Robillard <dave@drobilla.net>2009-08-14 18:08:56 -0400
committerDave Robillard <dave@drobilla.net>2009-08-14 18:08:56 -0400
commite937d82162aa78a7aa88874f0eb12c895fffd7b7 (patch)
treea370dd4cde5d798b9727c24d7d23838d0f3d1345
parent41f47a3d610a99ac7e3ed85f6ef3f5c130487c36 (diff)
downloadgst-plugins-bad-e937d82162aa78a7aa88874f0eb12c895fffd7b7.tar.gz
gst-plugins-bad-e937d82162aa78a7aa88874f0eb12c895fffd7b7.tar.bz2
gst-plugins-bad-e937d82162aa78a7aa88874f0eb12c895fffd7b7.zip
More tolerate port group support, plugin cleanup.
Gracefully handle plugins with illegal groups that contain no symbol by treating ports in that group normally (i.e. as if they weren't part of a group). The port groups spec mandates that groups have a valid unique symbol, but plugins aren't perfect... Make (conceptually) static plugin variables actually (C) static, and clean up SLV2 related things with a GCC shared library destructor, if GCC is in use.
-rw-r--r--ext/lv2/gstlv2.c136
1 files changed, 93 insertions, 43 deletions
diff --git a/ext/lv2/gstlv2.c b/ext/lv2/gstlv2.c
index 7c6e1c3b..ac4c9038 100644
--- a/ext/lv2/gstlv2.c
+++ b/ext/lv2/gstlv2.c
@@ -60,28 +60,28 @@ static void gst_lv2_cleanup (GstSignalProcessor * sigproc);
static void gst_lv2_process (GstSignalProcessor * sigproc, guint nframes);
static SLV2World world;
-SLV2Value audio_class;
-SLV2Value control_class;
-SLV2Value input_class;
-SLV2Value output_class;
-SLV2Value integer_prop;
-SLV2Value toggled_prop;
-SLV2Value in_place_broken_pred;
-SLV2Value in_group_pred;
-SLV2Value has_role_pred;
-SLV2Value lv2_symbol_pred;
-
-SLV2Value center_role;
-SLV2Value left_role;
-SLV2Value right_role;
-SLV2Value rear_center_role;
-SLV2Value rear_left_role;
-SLV2Value rear_right_role;
-SLV2Value lfe_role;
-SLV2Value center_left_role;
-SLV2Value center_right_role;
-SLV2Value side_left_role;
-SLV2Value side_right_role;
+static SLV2Value audio_class;
+static SLV2Value control_class;
+static SLV2Value input_class;
+static SLV2Value output_class;
+static SLV2Value integer_prop;
+static SLV2Value toggled_prop;
+static SLV2Value in_place_broken_pred;
+static SLV2Value in_group_pred;
+static SLV2Value has_role_pred;
+static SLV2Value lv2_symbol_pred;
+
+static SLV2Value center_role;
+static SLV2Value left_role;
+static SLV2Value right_role;
+static SLV2Value rear_center_role;
+static SLV2Value rear_left_role;
+static SLV2Value rear_right_role;
+static SLV2Value lfe_role;
+static SLV2Value center_left_role;
+static SLV2Value center_right_role;
+static SLV2Value side_left_role;
+static SLV2Value side_right_role;
static GstSignalProcessorClass *parent_class;
@@ -209,6 +209,7 @@ gst_lv2_base_init (gpointer g_class)
for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) {
const SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j);
const gboolean is_input = slv2_port_is_a (lv2plugin, port, input_class);
+ gboolean in_group = FALSE;
struct _GstLV2Port desc = { j, 0 };
values = slv2_port_get_value (lv2plugin, port, in_group_pred);
@@ -217,41 +218,58 @@ gst_lv2_base_init (gpointer g_class)
SLV2Value group_uri = slv2_values_get_at (values, 0);
GArray *groups = is_input ? klass->in_groups : klass->out_groups;
GstLV2Group *group = gst_lv2_class_find_group (groups, group_uri);
+ in_group = TRUE;
if (group == NULL) {
GstLV2Group g;
g.uri = slv2_value_duplicate (group_uri);
g.pad = is_input ? in_pad_index++ : out_pad_index++;
g.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
g.has_roles = TRUE;
+ g.symbol = NULL;
sub_values = slv2_plugin_get_value_for_subject (lv2plugin, group_uri,
lv2_symbol_pred);
- if (slv2_values_size (sub_values) > 0)
+ /* symbol is mandatory */
+ if (slv2_values_size (sub_values) > 0) {
g.symbol = slv2_value_duplicate (slv2_values_get_at (sub_values, 0));
- else
- g.symbol = NULL;
- slv2_values_free (sub_values);
-
- g_array_append_val (groups, g);
- group = &g_array_index (groups, GstLV2Group, groups->len - 1);
+ if (!gst_element_class_get_pad_template (element_class,
+ slv2_value_as_string (g.symbol))) {
+ g_array_append_val (groups, g);
+ group = &g_array_index (groups, GstLV2Group, groups->len - 1);
+ assert (group);
+ assert (slv2_value_equals (group->uri, group_uri));
+ } else {
+ GST_WARNING ("plugin %s has duplicate group symbol '%s'\n",
+ slv2_value_as_string (slv2_plugin_get_uri (lv2plugin)),
+ slv2_value_as_string (g.symbol));
+ in_group = FALSE;
+ }
+ } else {
+ GST_WARNING ("plugin %s has illegal group with no symbol\n",
+ slv2_value_as_string (slv2_plugin_get_uri (lv2plugin)));
+ in_group = FALSE;
+ }
}
- position = GST_AUDIO_CHANNEL_POSITION_INVALID;
- sub_values = slv2_port_get_value (lv2plugin, port, has_role_pred);
- if (slv2_values_size (sub_values) > 0) {
- SLV2Value role = slv2_values_get_at (sub_values, 0);
- position = gst_lv2_role_to_position (role);
+ if (in_group) {
+ position = GST_AUDIO_CHANNEL_POSITION_INVALID;
+ sub_values = slv2_port_get_value (lv2plugin, port, has_role_pred);
+ if (slv2_values_size (sub_values) > 0) {
+ SLV2Value role = slv2_values_get_at (sub_values, 0);
+ position = gst_lv2_role_to_position (role);
+ }
slv2_values_free (sub_values);
+ if (position != GST_AUDIO_CHANNEL_POSITION_INVALID) {
+ desc.position = position;
+ g_array_append_val (group->ports, desc);
+ } else {
+ in_group = FALSE;
+ }
}
- if (position != GST_AUDIO_CHANNEL_POSITION_INVALID) {
- desc.position = position;
- } else {
- group->has_roles = FALSE;
- }
-
- g_array_append_val (group->ports, desc);
+ }
- } else {
- /* port is not part of a group */
+ if (!in_group) {
+ /* port is not part of a group, or it is part of a group but that group
+ * is illegal so we just ignore it */
if (slv2_port_is_a (lv2plugin, port, audio_class)) {
desc.pad = is_input ? in_pad_index++ : out_pad_index++;
if (is_input)
@@ -788,6 +806,38 @@ plugin_init (GstPlugin * plugin)
return lv2_plugin_discover ();
}
+#ifdef __GNUC__
+__attribute__ ((destructor))
+#endif
+ static void plugin_cleanup (GstPlugin * plugin)
+{
+ slv2_value_free (audio_class);
+ slv2_value_free (control_class);
+ slv2_value_free (input_class);
+ slv2_value_free (output_class);
+
+ slv2_value_free (integer_prop);
+ slv2_value_free (toggled_prop);
+ slv2_value_free (in_place_broken_pred);
+ slv2_value_free (in_group_pred);
+ slv2_value_free (has_role_pred);
+ slv2_value_free (lv2_symbol_pred);
+
+ slv2_value_free (center_role);
+ slv2_value_free (left_role);
+ slv2_value_free (right_role);
+ slv2_value_free (rear_center_role);
+ slv2_value_free (rear_left_role);
+ slv2_value_free (rear_right_role);
+ slv2_value_free (lfe_role);
+ slv2_value_free (center_left_role);
+ slv2_value_free (center_right_role);
+ slv2_value_free (side_left_role);
+ slv2_value_free (side_right_role);
+
+ slv2_world_free (world);
+}
+
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
"lv2",