mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 17:18:15 +00:00
lv2: support for loading presets
Detect if plugins can do presets. Lazily read a list of presets and add support for loading.
This commit is contained in:
parent
6b511fdcd1
commit
e9a2c4f1e1
7 changed files with 362 additions and 35 deletions
|
@ -34,8 +34,7 @@ gst-launch-1.0 calf-sourceforge-net-plugins-Organ event-in="C-3" name=s ! interl
|
|||
|
||||
|
||||
TODO
|
||||
* support presets
|
||||
for pl in $(lv2ls); do if test "$(lv2info "$pl" | grep -A1 "Presets:" | tail -n1)" != ""; then echo "$pl"; fi; done
|
||||
* make filters gap-aware
|
||||
* support more host features
|
||||
GST_DEBUG="lv2:4" GST_DEBUG_FILE=/tmp/gst.log gst-inspect lv2
|
||||
grep -o "needs host feature: .*$" /tmp/gst.log | sort | uniq -c | sort -n
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <gst/audio/audio-channels.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/port-groups/port-groups.h>
|
||||
#include "lv2/lv2plug.in/ns/ext/event/event.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/state/state.h"
|
||||
|
||||
GST_DEBUG_CATEGORY (lv2_debug);
|
||||
#define GST_CAT_DEFAULT lv2_debug
|
||||
|
@ -71,13 +73,13 @@ lv2_plugin_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
|||
|
||||
static void
|
||||
lv2_count_ports (const LilvPlugin * lv2plugin, guint * audio_in,
|
||||
guint * audio_out)
|
||||
guint * audio_out, guint * control)
|
||||
{
|
||||
GHashTable *port_groups = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
guint i;
|
||||
|
||||
*audio_in = *audio_out = 0;
|
||||
*audio_in = *audio_out = *control = 0;
|
||||
for (i = 0; i < lilv_plugin_get_num_ports (lv2plugin); i++) {
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, i);
|
||||
|
||||
|
@ -99,6 +101,9 @@ lv2_count_ports (const LilvPlugin * lv2plugin, guint * audio_in,
|
|||
(*audio_in)++;
|
||||
else
|
||||
(*audio_out)++;
|
||||
} else if (lilv_port_is_a (lv2plugin, port, control_class) ||
|
||||
lilv_port_is_a (lv2plugin, port, cv_class)) {
|
||||
(*control)++;
|
||||
}
|
||||
}
|
||||
g_hash_table_unref (port_groups);
|
||||
|
@ -108,7 +113,7 @@ lv2_count_ports (const LilvPlugin * lv2plugin, guint * audio_in,
|
|||
static gboolean
|
||||
lv2_plugin_discover (GstPlugin * plugin)
|
||||
{
|
||||
guint audio_in, audio_out;
|
||||
guint audio_in, audio_out, control;
|
||||
LilvIter *i;
|
||||
const LilvPlugins *plugins = lilv_world_get_all_plugins (world);
|
||||
|
||||
|
@ -119,6 +124,7 @@ lv2_plugin_discover (GstPlugin * plugin)
|
|||
const LilvPlugin *lv2plugin = lilv_plugins_get (plugins, i);
|
||||
const gchar *plugin_uri, *p;
|
||||
gchar *type_name;
|
||||
gboolean can_do_presets;
|
||||
|
||||
plugin_uri = lilv_node_as_uri (lilv_plugin_get_uri (lv2plugin));
|
||||
|
||||
|
@ -142,7 +148,7 @@ lv2_plugin_discover (GstPlugin * plugin)
|
|||
goto next;
|
||||
|
||||
/* check if this has any audio ports */
|
||||
lv2_count_ports (lv2plugin, &audio_in, &audio_out);
|
||||
lv2_count_ports (lv2plugin, &audio_in, &audio_out, &control);
|
||||
|
||||
if (audio_in == 0 && audio_out == 0) {
|
||||
GST_FIXME ("plugin %s has no audio pads", type_name);
|
||||
|
@ -165,12 +171,19 @@ lv2_plugin_discover (GstPlugin * plugin)
|
|||
}
|
||||
}
|
||||
|
||||
lv2_meta = gst_structure_new_empty ("lv2");
|
||||
gst_structure_set (lv2_meta,
|
||||
/* check supported extensions */
|
||||
can_do_presets = lilv_plugin_has_extension_data (lv2plugin, state_iface)
|
||||
|| lilv_plugin_has_feature (lv2plugin, state_uri)
|
||||
|| (control > 0);
|
||||
GST_INFO ("plugin %s can%s do presets", type_name,
|
||||
(can_do_presets ? "" : "'t"));
|
||||
|
||||
lv2_meta = gst_structure_new ("lv2",
|
||||
"element-uri", G_TYPE_STRING, plugin_uri,
|
||||
"element-type-name", G_TYPE_STRING, type_name,
|
||||
"audio-in", G_TYPE_UINT, audio_in,
|
||||
"audio-out", G_TYPE_UINT, audio_out, NULL);
|
||||
"audio-out", G_TYPE_UINT, audio_out,
|
||||
"can-do-presets", G_TYPE_BOOLEAN, can_do_presets, NULL);
|
||||
|
||||
g_value_init (&value, GST_TYPE_STRUCTURE);
|
||||
g_value_set_boxed (&value, lv2_meta);
|
||||
|
@ -198,6 +211,7 @@ plugin_init (GstPlugin * plugin)
|
|||
|
||||
world = lilv_world_new ();
|
||||
lilv_world_load_all (world);
|
||||
gst_lv2_host_init ();
|
||||
|
||||
/* have been added after lilv-0.22.0, which is the last release */
|
||||
#ifndef LILV_URI_ATOM_PORT
|
||||
|
@ -214,6 +228,9 @@ plugin_init (GstPlugin * plugin)
|
|||
event_class = lilv_new_uri (world, LILV_URI_EVENT_PORT);
|
||||
input_class = lilv_new_uri (world, LILV_URI_INPUT_PORT);
|
||||
output_class = lilv_new_uri (world, LILV_URI_OUTPUT_PORT);
|
||||
preset_class = lilv_new_uri (world, LV2_PRESETS__Preset);
|
||||
state_iface = lilv_new_uri (world, LV2_STATE__interface);
|
||||
state_uri = lilv_new_uri (world, LV2_STATE_URI);
|
||||
|
||||
integer_prop = lilv_new_uri (world, LV2_CORE__integer);
|
||||
toggled_prop = lilv_new_uri (world, LV2_CORE__toggled);
|
||||
|
@ -222,6 +239,7 @@ plugin_init (GstPlugin * plugin)
|
|||
optional_pred = lilv_new_uri (world, LV2_CORE__optionalFeature);
|
||||
group_pred = lilv_new_uri (world, LV2_PORT_GROUPS__group);
|
||||
supports_event_pred = lilv_new_uri (world, LV2_EVENT__supportsEvent);
|
||||
label_pred = lilv_new_uri (world, LILV_NS_RDFS "label");
|
||||
|
||||
center_role = lilv_new_uri (world, LV2_PORT_GROUPS__center);
|
||||
left_role = lilv_new_uri (world, LV2_PORT_GROUPS__left);
|
||||
|
@ -296,6 +314,9 @@ __attribute__ ((destructor))
|
|||
lilv_node_free (event_class);
|
||||
lilv_node_free (input_class);
|
||||
lilv_node_free (output_class);
|
||||
lilv_node_free (preset_class);
|
||||
lilv_node_free (state_iface);
|
||||
lilv_node_free (state_uri);
|
||||
|
||||
lilv_node_free (integer_prop);
|
||||
lilv_node_free (toggled_prop);
|
||||
|
@ -304,6 +325,7 @@ __attribute__ ((destructor))
|
|||
lilv_node_free (optional_pred);
|
||||
lilv_node_free (group_pred);
|
||||
lilv_node_free (supports_event_pred);
|
||||
lilv_node_free (label_pred);
|
||||
|
||||
lilv_node_free (center_role);
|
||||
lilv_node_free (left_role);
|
||||
|
|
|
@ -36,6 +36,10 @@ LilvNode *cv_class;
|
|||
LilvNode *event_class;
|
||||
LilvNode *input_class;
|
||||
LilvNode *output_class;
|
||||
LilvNode *preset_class;
|
||||
LilvNode *state_iface;
|
||||
LilvNode *state_uri;
|
||||
|
||||
LilvNode *integer_prop;
|
||||
LilvNode *toggled_prop;
|
||||
LilvNode *designation_pred;
|
||||
|
@ -43,6 +47,7 @@ LilvNode *in_place_broken_pred;
|
|||
LilvNode *optional_pred;
|
||||
LilvNode *group_pred;
|
||||
LilvNode *supports_event_pred;
|
||||
LilvNode *label_pred;
|
||||
|
||||
LilvNode *center_role;
|
||||
LilvNode *left_role;
|
||||
|
|
|
@ -70,6 +70,73 @@ struct _GstLV2FilterClass
|
|||
|
||||
static GstAudioFilter *parent_class = NULL;
|
||||
|
||||
/* preset interface */
|
||||
|
||||
static gchar **
|
||||
gst_lv2_filter_get_preset_names (GstPreset * preset)
|
||||
{
|
||||
GstLV2Filter *self = (GstLV2Filter *) preset;
|
||||
|
||||
return gst_lv2_get_preset_names (&self->lv2, (GstObject *) self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_load_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
GstLV2Filter *self = (GstLV2Filter *) preset;
|
||||
|
||||
return gst_lv2_load_preset (&self->lv2, (GstObject *) self, name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_save_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_rename_preset (GstPreset * preset, const gchar * old_name,
|
||||
const gchar * new_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_delete_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_set_meta (GstPreset * preset, const gchar * name,
|
||||
const gchar * tag, const gchar * value)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_filter_get_meta (GstPreset * preset, const gchar * name,
|
||||
const gchar * tag, gchar ** value)
|
||||
{
|
||||
*value = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_lv2_filter_preset_interface_init (gpointer g_iface, gpointer iface_data)
|
||||
{
|
||||
GstPresetInterface *iface = g_iface;
|
||||
|
||||
iface->get_preset_names = gst_lv2_filter_get_preset_names;
|
||||
iface->load_preset = gst_lv2_filter_load_preset;
|
||||
iface->save_preset = gst_lv2_filter_save_preset;
|
||||
iface->rename_preset = gst_lv2_filter_rename_preset;
|
||||
iface->delete_preset = gst_lv2_filter_delete_preset;
|
||||
iface->set_meta = gst_lv2_filter_set_meta;
|
||||
iface->get_meta = gst_lv2_filter_get_meta;
|
||||
}
|
||||
|
||||
|
||||
/* GObject vmethods implementation */
|
||||
static void
|
||||
gst_lv2_filter_set_property (GObject * object, guint prop_id,
|
||||
|
@ -472,9 +539,25 @@ gst_lv2_filter_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
|||
0,
|
||||
(GInstanceInitFunc) gst_lv2_filter_init,
|
||||
};
|
||||
const gchar *type_name =
|
||||
gst_structure_get_string (lv2_meta, "element-type-name");
|
||||
GType element_type =
|
||||
g_type_register_static (GST_TYPE_AUDIO_FILTER, type_name, &info, 0);
|
||||
gboolean can_do_presets;
|
||||
|
||||
/* create the type */
|
||||
gst_lv2_register_element (plugin, GST_TYPE_AUDIO_FILTER, &info, lv2_meta);
|
||||
/* register interfaces */
|
||||
gst_structure_get_boolean (lv2_meta, "can-do-presets", &can_do_presets);
|
||||
if (can_do_presets) {
|
||||
const GInterfaceInfo preset_interface_info = {
|
||||
(GInterfaceInitFunc) gst_lv2_filter_preset_interface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
g_type_add_interface_static (element_type, GST_TYPE_PRESET,
|
||||
&preset_interface_info);
|
||||
}
|
||||
|
||||
gst_element_register (plugin, type_name, GST_RANK_NONE, element_type);
|
||||
|
||||
if (!parent_class)
|
||||
parent_class = g_type_class_ref (GST_TYPE_AUDIO_FILTER);
|
||||
|
|
|
@ -87,6 +87,73 @@ enum
|
|||
|
||||
static GstBaseSrc *parent_class = NULL;
|
||||
|
||||
/* preset interface */
|
||||
|
||||
static gchar **
|
||||
gst_lv2_source_get_preset_names (GstPreset * preset)
|
||||
{
|
||||
GstLV2Source *self = (GstLV2Source *) preset;
|
||||
|
||||
return gst_lv2_get_preset_names (&self->lv2, (GstObject *) self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_load_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
GstLV2Source *self = (GstLV2Source *) preset;
|
||||
|
||||
return gst_lv2_load_preset (&self->lv2, (GstObject *) self, name);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_save_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_rename_preset (GstPreset * preset, const gchar * old_name,
|
||||
const gchar * new_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_delete_preset (GstPreset * preset, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_set_meta (GstPreset * preset, const gchar * name,
|
||||
const gchar * tag, const gchar * value)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_lv2_source_get_meta (GstPreset * preset, const gchar * name,
|
||||
const gchar * tag, gchar ** value)
|
||||
{
|
||||
*value = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_lv2_source_preset_interface_init (gpointer g_iface, gpointer iface_data)
|
||||
{
|
||||
GstPresetInterface *iface = g_iface;
|
||||
|
||||
iface->get_preset_names = gst_lv2_source_get_preset_names;
|
||||
iface->load_preset = gst_lv2_source_load_preset;
|
||||
iface->save_preset = gst_lv2_source_save_preset;
|
||||
iface->rename_preset = gst_lv2_source_rename_preset;
|
||||
iface->delete_preset = gst_lv2_source_delete_preset;
|
||||
iface->set_meta = gst_lv2_source_set_meta;
|
||||
iface->get_meta = gst_lv2_source_get_meta;
|
||||
}
|
||||
|
||||
|
||||
/* GstBasesrc vmethods implementation */
|
||||
|
||||
static gboolean
|
||||
|
@ -658,8 +725,26 @@ gst_lv2_source_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
|||
0,
|
||||
(GInstanceInitFunc) gst_lv2_source_init,
|
||||
};
|
||||
const gchar *type_name =
|
||||
gst_structure_get_string (lv2_meta, "element-type-name");
|
||||
GType element_type =
|
||||
g_type_register_static (GST_TYPE_BASE_SRC, type_name, &info, 0);
|
||||
gboolean can_do_presets;
|
||||
|
||||
gst_lv2_register_element (plugin, GST_TYPE_BASE_SRC, &info, lv2_meta);
|
||||
/* register interfaces */
|
||||
gst_structure_get_boolean (lv2_meta, "can-do-presets", &can_do_presets);
|
||||
if (can_do_presets) {
|
||||
const GInterfaceInfo preset_interface_info = {
|
||||
(GInterfaceInitFunc) gst_lv2_source_preset_interface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
g_type_add_interface_static (element_type, GST_TYPE_PRESET,
|
||||
&preset_interface_info);
|
||||
}
|
||||
|
||||
gst_element_register (plugin, type_name, GST_RANK_NONE, element_type);
|
||||
|
||||
if (!parent_class)
|
||||
parent_class = g_type_class_ref (GST_TYPE_BASE_SRC);
|
||||
|
|
|
@ -28,7 +28,10 @@
|
|||
#include "gstlv2.h"
|
||||
#include "gstlv2utils.h"
|
||||
|
||||
#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
|
||||
#include <lv2/lv2plug.in/ns/ext/log/log.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/state/state.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (lv2_debug);
|
||||
|
@ -133,6 +136,134 @@ gst_lv2_check_required_features (const LilvPlugin * lv2plugin)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static LV2_Atom_Forge forge;
|
||||
|
||||
void
|
||||
gst_lv2_host_init (void)
|
||||
{
|
||||
lv2_atom_forge_init (&forge, &lv2_map);
|
||||
}
|
||||
|
||||
/* preset interface */
|
||||
|
||||
gchar **
|
||||
gst_lv2_get_preset_names (GstLV2 * lv2, GstObject * obj)
|
||||
{
|
||||
/* lazily scan for presets when first called */
|
||||
if (!lv2->presets) {
|
||||
LilvNodes *presets;
|
||||
|
||||
if ((presets = lilv_plugin_get_related (lv2->klass->plugin, preset_class))) {
|
||||
LilvIter *j;
|
||||
|
||||
lv2->presets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) lilv_node_free);
|
||||
|
||||
for (j = lilv_nodes_begin (presets);
|
||||
!lilv_nodes_is_end (presets, j); j = lilv_nodes_next (presets, j)) {
|
||||
const LilvNode *preset = lilv_nodes_get (presets, j);
|
||||
LilvNodes *titles;
|
||||
|
||||
lilv_world_load_resource (world, preset);
|
||||
titles = lilv_world_find_nodes (world, preset, label_pred, NULL);
|
||||
if (titles) {
|
||||
const LilvNode *title = lilv_nodes_get_first (titles);
|
||||
g_hash_table_insert (lv2->presets,
|
||||
g_strdup (lilv_node_as_string (title)),
|
||||
lilv_node_duplicate (preset));
|
||||
lilv_nodes_free (titles);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (obj, "plugin has preset '%s' without rdfs:label",
|
||||
lilv_node_as_string (preset));
|
||||
}
|
||||
}
|
||||
lilv_nodes_free (presets);
|
||||
}
|
||||
}
|
||||
if (lv2->presets) {
|
||||
GList *node, *keys = g_hash_table_get_keys (lv2->presets);
|
||||
gchar **names = g_new0 (gchar *, g_hash_table_size (lv2->presets) + 1);
|
||||
gint i = 0;
|
||||
|
||||
for (node = keys; node; node = g_list_next (node)) {
|
||||
names[i++] = g_strdup (node->data);
|
||||
}
|
||||
g_list_free (keys);
|
||||
return names;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_port_value (const char *port_symbol, void *data, const void *value,
|
||||
uint32_t size, uint32_t type)
|
||||
{
|
||||
gpointer *user_data = (gpointer *) data;
|
||||
GstLV2Class *klass = user_data[0];
|
||||
GstObject *obj = user_data[1];
|
||||
gchar *prop_name = g_hash_table_lookup (klass->sym_to_name, port_symbol);
|
||||
gfloat fvalue;
|
||||
|
||||
if (!prop_name) {
|
||||
GST_WARNING_OBJECT (obj, "Preset port '%s' is missing", port_symbol);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == forge.Float) {
|
||||
fvalue = *(const gfloat *) value;
|
||||
} else if (type == forge.Double) {
|
||||
fvalue = *(const gdouble *) value;
|
||||
} else if (type == forge.Int) {
|
||||
fvalue = *(const gint32 *) value;
|
||||
} else if (type == forge.Long) {
|
||||
fvalue = *(const gint64 *) value;
|
||||
} else {
|
||||
GST_WARNING_OBJECT (obj, "Preset '%s' value has bad type '%s'",
|
||||
port_symbol, lv2_unmap.unmap (lv2_unmap.handle, type));
|
||||
return;
|
||||
}
|
||||
g_object_set (obj, prop_name, fvalue, NULL);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gst_lv2_load_preset (GstLV2 * lv2, GstObject * obj, const gchar * name)
|
||||
{
|
||||
LilvNode *preset = g_hash_table_lookup (lv2->presets, name);
|
||||
LilvState *state = lilv_state_new_from_world (world, &lv2_map, preset);
|
||||
gpointer user_data[] = { lv2->klass, obj };
|
||||
|
||||
GST_INFO_OBJECT (obj, "loading preset <%s>", lilv_node_as_string (preset));
|
||||
|
||||
lilv_state_restore (state, lv2->instance, set_port_value,
|
||||
(gpointer) user_data, 0, NULL);
|
||||
|
||||
lilv_state_free (state);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
gboolean
|
||||
gst_lv2_save_preset (GstLV2 * lv2, GstObject * obj, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_lv2_rename_preset (GstLV2 * lv2, GstObject * obj,
|
||||
const gchar * old_name, const gchar * new_name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_lv2_delete_preset (GstLV2 * lv2, GstObject * obj, const gchar * name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* api helpers */
|
||||
|
||||
void
|
||||
|
@ -150,6 +281,9 @@ gst_lv2_init (GstLV2 * lv2, GstLV2Class * lv2_class)
|
|||
void
|
||||
gst_lv2_finalize (GstLV2 * lv2)
|
||||
{
|
||||
if (lv2->presets) {
|
||||
g_hash_table_destroy (lv2->presets);
|
||||
}
|
||||
g_free (lv2->ports.control.in);
|
||||
g_free (lv2->ports.control.out);
|
||||
}
|
||||
|
@ -301,12 +435,9 @@ gst_lv2_object_get_property (GstLV2 * lv2, GObject * object,
|
|||
|
||||
static gchar *
|
||||
gst_lv2_class_get_param_name (GstLV2Class * klass, GObjectClass * object_class,
|
||||
const LilvPort * port)
|
||||
const gchar * port_symbol)
|
||||
{
|
||||
const LilvPlugin *lv2plugin = klass->plugin;
|
||||
gchar *ret;
|
||||
|
||||
ret = g_strdup (lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port)));
|
||||
gchar *ret = g_strdup (port_symbol);
|
||||
|
||||
/* this is the same thing that param_spec_* will do */
|
||||
g_strcanon (ret, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
|
||||
|
@ -331,9 +462,7 @@ gst_lv2_class_get_param_name (GstLV2Class * klass, GObjectClass * object_class,
|
|||
ret = nret;
|
||||
}
|
||||
|
||||
GST_DEBUG ("built property name '%s' from port name '%s'", ret,
|
||||
lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port)));
|
||||
|
||||
GST_DEBUG ("built property name '%s' from port name '%s'", ret, port_symbol);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -364,9 +493,11 @@ gst_lv2_class_get_param_spec (GstLV2Class * klass, GObjectClass * object_class,
|
|||
gint perms;
|
||||
gfloat lower = 0.0f, upper = 1.0f, def = 0.0f;
|
||||
GType enum_type = G_TYPE_INVALID;
|
||||
const gchar *port_symbol =
|
||||
lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port));
|
||||
|
||||
nick = gst_lv2_class_get_param_nick (klass, port);
|
||||
name = gst_lv2_class_get_param_name (klass, object_class, port);
|
||||
name = gst_lv2_class_get_param_name (klass, object_class, port_symbol);
|
||||
|
||||
GST_DEBUG ("%s trying port %s : %s",
|
||||
lilv_node_as_string (lilv_plugin_get_uri (lv2plugin)), name, nick);
|
||||
|
@ -480,6 +611,10 @@ gst_lv2_class_get_param_spec (GstLV2Class * klass, GObjectClass * object_class,
|
|||
ret = g_param_spec_float (name, nick, nick, lower, upper, def, perms);
|
||||
|
||||
done:
|
||||
// build a map of (port_symbol to ret->name) for extensions
|
||||
g_hash_table_insert (klass->sym_to_name, (gchar *) port_symbol,
|
||||
(gchar *) ret->name);
|
||||
|
||||
g_free (name);
|
||||
g_free (nick);
|
||||
|
||||
|
@ -572,6 +707,8 @@ gst_lv2_class_init (GstLV2Class * lv2_class, GType type)
|
|||
lv2_class->plugin = lv2plugin;
|
||||
lilv_node_free (plugin_uri);
|
||||
|
||||
lv2_class->sym_to_name = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
lv2_class->in_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
|
||||
lv2_class->out_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
|
||||
lv2_class->control_in_ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
|
||||
|
@ -692,6 +829,8 @@ gst_lv2_class_finalize (GstLV2Class * lv2_class)
|
|||
{
|
||||
GST_DEBUG ("LV2 finalizing class");
|
||||
|
||||
g_hash_table_destroy (lv2_class->sym_to_name);
|
||||
|
||||
g_array_free (lv2_class->in_group.ports, TRUE);
|
||||
lv2_class->in_group.ports = NULL;
|
||||
g_array_free (lv2_class->out_group.ports, TRUE);
|
||||
|
@ -701,14 +840,3 @@ gst_lv2_class_finalize (GstLV2Class * lv2_class)
|
|||
g_array_free (lv2_class->control_out_ports, TRUE);
|
||||
lv2_class->control_out_ports = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gst_lv2_register_element (GstPlugin * plugin, GType parent_type,
|
||||
const GTypeInfo * info, GstStructure * lv2_meta)
|
||||
{
|
||||
const gchar *type_name =
|
||||
gst_structure_get_string (lv2_meta, "element-type-name");
|
||||
|
||||
gst_element_register (plugin, type_name, GST_RANK_NONE,
|
||||
g_type_register_static (parent_type, type_name, info, 0));
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ struct _GstLV2
|
|||
GstLV2Class *klass;
|
||||
|
||||
LilvInstance *instance;
|
||||
GHashTable *presets;
|
||||
|
||||
gboolean activated;
|
||||
unsigned long rate;
|
||||
|
@ -88,6 +89,7 @@ struct _GstLV2Class
|
|||
guint properties;
|
||||
|
||||
const LilvPlugin *plugin;
|
||||
GHashTable *sym_to_name;
|
||||
|
||||
gint num_control_in, num_control_out;
|
||||
gint num_cv_in, num_cv_out;
|
||||
|
@ -98,7 +100,12 @@ struct _GstLV2Class
|
|||
GArray *control_out_ports; /**< Array of GstLV2Port */
|
||||
};
|
||||
|
||||
gboolean gst_lv2_check_required_features (const LilvPlugin *lv2plugin);
|
||||
gboolean gst_lv2_check_required_features (const LilvPlugin * lv2plugin);
|
||||
|
||||
void gst_lv2_host_init (void);
|
||||
|
||||
gchar **gst_lv2_get_preset_names (GstLV2 * lv2, GstObject * obj);
|
||||
gboolean gst_lv2_load_preset (GstLV2 * lv2, GstObject * obj, const gchar * name);
|
||||
|
||||
void gst_lv2_init (GstLV2 * lv2, GstLV2Class * lv2_class);
|
||||
void gst_lv2_finalize (GstLV2 * lv2);
|
||||
|
@ -119,8 +126,6 @@ void gst_lv2_element_class_set_metadata (GstLV2Class * lv2_class,
|
|||
void gst_lv2_class_init (GstLV2Class * lv2_class, GType type);
|
||||
void gst_lv2_class_finalize (GstLV2Class * lv2_class);
|
||||
|
||||
void gst_lv2_register_element (GstPlugin * plugin, GType parent_type,
|
||||
const GTypeInfo * info, GstStructure * lv2_meta);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_LV2_UTILS_H__ */
|
||||
|
|
Loading…
Reference in a new issue