mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
lv2: add registry caching
Use the plugin_cache extra data to avoid introspecting over and over again.
This commit is contained in:
parent
da0a3d95e7
commit
1c83ce7a96
7 changed files with 176 additions and 103 deletions
|
@ -33,7 +33,6 @@ gst-launch-1.0 calf-sourceforge-net-plugins-Organ event-in="C-3" name=s ! interl
|
|||
|
||||
|
||||
TODO
|
||||
* registry cache
|
||||
* support http://lv2plug.in/ns/lv2core/#CVPort
|
||||
- these ports need a buffer with the property value
|
||||
- we should sync, then fill the buffer and connect the port
|
||||
|
|
178
ext/lv2/gstlv2.c
178
ext/lv2/gstlv2.c
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "gstlv2.h"
|
||||
#include "gstlv2utils.h"
|
||||
|
||||
#include <gst/audio/audio-channels.h>
|
||||
#include <lv2/lv2plug.in/ns/ext/port-groups/port-groups.h>
|
||||
|
@ -52,24 +51,82 @@ GST_DEBUG_CATEGORY (lv2_debug);
|
|||
"/usr/local/lib/lv2" G_SEARCHPATH_SEPARATOR_S \
|
||||
LIBDIR "/lv2"
|
||||
|
||||
/* search the plugin path
|
||||
*/
|
||||
GstStructure *lv2_meta_all = NULL;
|
||||
|
||||
static void
|
||||
lv2_plugin_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
||||
{
|
||||
guint audio_in, audio_out;
|
||||
|
||||
gst_structure_get_uint (lv2_meta, "audio-in", &audio_in);
|
||||
gst_structure_get_uint (lv2_meta, "audio-out", &audio_out);
|
||||
|
||||
if (audio_in == 0) {
|
||||
gst_lv2_source_register_element (plugin, lv2_meta);
|
||||
} else {
|
||||
gst_lv2_filter_register_element (plugin, lv2_meta);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lv2_count_ports (const LilvPlugin * lv2plugin, guint * audio_in,
|
||||
guint * audio_out)
|
||||
{
|
||||
GHashTable *port_groups = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
guint i;
|
||||
|
||||
*audio_in = *audio_out = 0;
|
||||
for (i = 0; i < lilv_plugin_get_num_ports (lv2plugin); i++) {
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, i);
|
||||
|
||||
if (lilv_port_is_a (lv2plugin, port, audio_class)) {
|
||||
const gboolean is_input = lilv_port_is_a (lv2plugin, port, input_class);
|
||||
LilvNodes *lv2group = lilv_port_get (lv2plugin, port, group_pred);
|
||||
|
||||
if (lv2group) {
|
||||
const gchar *uri = lilv_node_as_uri (lv2group);
|
||||
|
||||
if (g_hash_table_contains (port_groups, uri))
|
||||
continue;
|
||||
|
||||
g_hash_table_add (port_groups, g_strdup (uri));
|
||||
lilv_node_free (lv2group);
|
||||
}
|
||||
|
||||
if (is_input)
|
||||
(*audio_in)++;
|
||||
else
|
||||
(*audio_out)++;
|
||||
}
|
||||
}
|
||||
g_hash_table_unref (port_groups);
|
||||
}
|
||||
|
||||
/* search the plugin path */
|
||||
static gboolean
|
||||
lv2_plugin_discover (GstPlugin * plugin)
|
||||
{
|
||||
guint j, num_sink_pads, num_src_pads;
|
||||
guint audio_in, audio_out;
|
||||
LilvIter *i;
|
||||
const LilvPlugins *plugins = lilv_world_get_all_plugins (world);
|
||||
|
||||
for (i = lilv_plugins_begin (plugins); !lilv_plugins_is_end (plugins, i);
|
||||
i = lilv_plugins_next (plugins, i)) {
|
||||
GstStructure *lv2_meta = NULL;
|
||||
GValue value = { 0, };
|
||||
const LilvPlugin *lv2plugin = lilv_plugins_get (plugins, i);
|
||||
const gchar *plugin_uri, *p;
|
||||
gchar *type_name;
|
||||
GHashTable *port_groups = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
|
||||
plugin_uri = lilv_node_as_uri (lilv_plugin_get_uri (lv2plugin));
|
||||
|
||||
/* check if we support the required host features */
|
||||
if (!gst_lv2_check_required_features (lv2plugin)) {
|
||||
GST_FIXME ("lv2 plugin %s needs host features", plugin_uri);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* construct the type name from plugin URI */
|
||||
if ((p = strstr (plugin_uri, "://"))) {
|
||||
/* cut off the protocol (e.g. http://) */
|
||||
|
@ -83,61 +140,47 @@ lv2_plugin_discover (GstPlugin * plugin)
|
|||
if (g_type_from_name (type_name))
|
||||
goto next;
|
||||
|
||||
/* check if we support the required host features */
|
||||
if (!gst_lv2_check_required_features (lv2plugin)) {
|
||||
GST_FIXME ("lv2 plugin %s needs host features", plugin_uri);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* check if this has any audio ports */
|
||||
num_sink_pads = num_src_pads = 0;
|
||||
for (j = 0; j < lilv_plugin_get_num_ports (lv2plugin); j++) {
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, j);
|
||||
lv2_count_ports (lv2plugin, &audio_in, &audio_out);
|
||||
|
||||
if (lilv_port_is_a (lv2plugin, port, audio_class)) {
|
||||
const gboolean is_input = lilv_port_is_a (lv2plugin, port, input_class);
|
||||
LilvNodes *lv2group = lilv_port_get (lv2plugin, port, group_pred);
|
||||
|
||||
if (lv2group) {
|
||||
const gchar *uri = lilv_node_as_uri (lv2group);
|
||||
|
||||
if (g_hash_table_contains (port_groups, uri))
|
||||
continue;
|
||||
|
||||
g_hash_table_add (port_groups, g_strdup (uri));
|
||||
lilv_node_free (lv2group);
|
||||
}
|
||||
|
||||
if (is_input)
|
||||
num_sink_pads++;
|
||||
else
|
||||
num_src_pads++;
|
||||
}
|
||||
}
|
||||
if (num_sink_pads == 0 && num_src_pads == 0) {
|
||||
GST_FIXME ("plugin %s has no pads", type_name);
|
||||
} else if (num_sink_pads == 0) {
|
||||
if (num_src_pads != 1) {
|
||||
if (audio_in == 0 && audio_out == 0) {
|
||||
GST_FIXME ("plugin %s has no audio pads", type_name);
|
||||
goto next;
|
||||
} else if (audio_in == 0) {
|
||||
if (audio_out != 1) {
|
||||
GST_FIXME ("plugin %s is not a GstBaseSrc (num_src_pads: %d)",
|
||||
type_name, num_src_pads);
|
||||
type_name, audio_out);
|
||||
goto next;
|
||||
}
|
||||
gst_lv2_source_register_element (plugin, type_name, (gpointer) lv2plugin);
|
||||
} else if (num_src_pads == 0) {
|
||||
} else if (audio_out == 0) {
|
||||
GST_FIXME ("plugin %s is a sink element (num_sink_pads: %d"
|
||||
" num_src_pads: %d)", type_name, num_sink_pads, num_src_pads);
|
||||
" num_src_pads: %d)", type_name, audio_in, audio_out);
|
||||
goto next;
|
||||
} else {
|
||||
if (num_sink_pads != 1 || num_src_pads != 1) {
|
||||
if (audio_in != 1 || audio_out != 1) {
|
||||
GST_FIXME ("plugin %s is not a GstAudioFilter (num_sink_pads: %d"
|
||||
" num_src_pads: %d)", type_name, num_sink_pads, num_src_pads);
|
||||
" num_src_pads: %d)", type_name, audio_in, audio_out);
|
||||
goto next;
|
||||
}
|
||||
gst_lv2_filter_register_element (plugin, type_name, (gpointer) lv2plugin);
|
||||
}
|
||||
|
||||
lv2_meta = gst_structure_new_empty ("lv2");
|
||||
gst_structure_set (lv2_meta,
|
||||
"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);
|
||||
|
||||
g_value_init (&value, GST_TYPE_STRUCTURE);
|
||||
g_value_set_boxed (&value, lv2_meta);
|
||||
gst_structure_set_value (lv2_meta_all, type_name, &value);
|
||||
g_value_unset (&value);
|
||||
|
||||
// don't free type_name
|
||||
continue;
|
||||
|
||||
next:
|
||||
g_free (type_name);
|
||||
g_hash_table_unref (port_groups);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -146,6 +189,9 @@ lv2_plugin_discover (GstPlugin * plugin)
|
|||
static gboolean
|
||||
plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
gint n = 0;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (lv2_debug, "lv2",
|
||||
GST_DEBUG_FG_GREEN | GST_DEBUG_BG_BLACK | GST_DEBUG_BOLD, "LV2");
|
||||
|
||||
|
@ -184,17 +230,47 @@ plugin_init (GstPlugin * plugin)
|
|||
gst_plugin_add_dependency_simple (plugin,
|
||||
"LV2_PATH", GST_LV2_DEFAULT_PATH, NULL, GST_PLUGIN_DEPENDENCY_FLAG_NONE);
|
||||
|
||||
descriptor_quark = g_quark_from_static_string ("lilv-plugin");
|
||||
|
||||
/* ensure GstAudioChannelPosition type is registered */
|
||||
if (!gst_audio_channel_position_get_type ())
|
||||
return FALSE;
|
||||
|
||||
if (!lv2_plugin_discover (plugin)) {
|
||||
GST_WARNING ("no lv2 plugins found, check LV2_PATH");
|
||||
lv2_meta_all = (GstStructure *) gst_plugin_get_cache_data (plugin);
|
||||
if (lv2_meta_all) {
|
||||
n = gst_structure_n_fields (lv2_meta_all);
|
||||
}
|
||||
GST_INFO_OBJECT (plugin, "%d entries in cache", n);
|
||||
if (!n) {
|
||||
lv2_meta_all = gst_structure_new_empty ("lv2");
|
||||
if ((res = lv2_plugin_discover (plugin))) {
|
||||
n = gst_structure_n_fields (lv2_meta_all);
|
||||
GST_INFO_OBJECT (plugin, "%d entries after scanning", n);
|
||||
gst_plugin_set_cache_data (plugin, lv2_meta_all);
|
||||
}
|
||||
} else {
|
||||
res = TRUE;
|
||||
}
|
||||
|
||||
if (n) {
|
||||
gint i;
|
||||
const gchar *name;
|
||||
const GValue *value;
|
||||
|
||||
GST_INFO_OBJECT (plugin, "register types");
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
name = gst_structure_nth_field_name (lv2_meta_all, i);
|
||||
value = gst_structure_get_value (lv2_meta_all, name);
|
||||
if (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE) {
|
||||
GstStructure *lv2_meta = g_value_get_boxed (value);
|
||||
|
||||
lv2_plugin_register_element (plugin, lv2_meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
GST_WARNING_OBJECT (plugin, "no lv2 plugins found, check LV2_PATH");
|
||||
}
|
||||
|
||||
/* we don't want to fail, even if there are no elements registered */
|
||||
return TRUE;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <lilv/lilv.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstlv2utils.h"
|
||||
|
||||
LilvWorld *world;
|
||||
LilvNode *audio_class;
|
||||
LilvNode *control_class;
|
||||
|
@ -50,12 +52,10 @@ LilvNode *center_right_role;
|
|||
LilvNode *side_left_role;
|
||||
LilvNode *side_right_role;
|
||||
|
||||
GQuark descriptor_quark;
|
||||
GstStructure *lv2_meta_all;
|
||||
|
||||
gboolean gst_lv2_filter_register_element (GstPlugin *plugin,
|
||||
const gchar *type_name,
|
||||
gpointer *lv2plugin);
|
||||
gboolean gst_lv2_source_register_element (GstPlugin *plugin,
|
||||
const gchar *type_name,
|
||||
gpointer *lv2plugin);
|
||||
void gst_lv2_filter_register_element (GstPlugin *plugin,
|
||||
GstStructure * lv2_meta);
|
||||
void gst_lv2_source_register_element (GstPlugin *plugin,
|
||||
GstStructure * lv2_meta);
|
||||
#endif /* __GST_LV2_H__ */
|
||||
|
|
|
@ -410,7 +410,7 @@ gst_lv2_filter_base_finalize (GstLV2FilterClass * lv2_class)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_lv2_filter_class_init (GstLV2FilterClass * klass, LilvPlugin * lv2plugin)
|
||||
gst_lv2_filter_class_init (GstLV2FilterClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstBaseTransformClass *transform_class = GST_BASE_TRANSFORM_CLASS (klass);
|
||||
|
@ -428,8 +428,6 @@ gst_lv2_filter_class_init (GstLV2FilterClass * klass, LilvPlugin * lv2plugin)
|
|||
transform_class->transform = gst_lv2_filter_transform;
|
||||
transform_class->transform_ip = gst_lv2_filter_transform_ip;
|
||||
|
||||
klass->lv2.plugin = lv2plugin;
|
||||
|
||||
gst_lv2_class_install_properties (&klass->lv2, gobject_class, 1);
|
||||
}
|
||||
|
||||
|
@ -442,34 +440,24 @@ gst_lv2_filter_init (GstLV2Filter * self, GstLV2FilterClass * klass)
|
|||
gst_base_transform_set_in_place (GST_BASE_TRANSFORM (self), TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_lv2_filter_register_element (GstPlugin * plugin, const gchar * type_name,
|
||||
gpointer * lv2plugin)
|
||||
void
|
||||
gst_lv2_filter_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
||||
{
|
||||
GType type;
|
||||
GTypeInfo typeinfo = {
|
||||
GTypeInfo info = {
|
||||
sizeof (GstLV2FilterClass),
|
||||
(GBaseInitFunc) gst_lv2_filter_base_init,
|
||||
(GBaseFinalizeFunc) gst_lv2_filter_base_finalize,
|
||||
(GClassInitFunc) gst_lv2_filter_class_init,
|
||||
NULL,
|
||||
lv2plugin,
|
||||
NULL,
|
||||
sizeof (GstLV2Filter),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_lv2_filter_init,
|
||||
};
|
||||
|
||||
/* create the type */
|
||||
type =
|
||||
g_type_register_static (GST_TYPE_AUDIO_FILTER, type_name, &typeinfo, 0);
|
||||
gst_lv2_register_element (plugin, GST_TYPE_AUDIO_FILTER, &info, lv2_meta);
|
||||
|
||||
if (!parent_class)
|
||||
parent_class = g_type_class_ref (GST_TYPE_AUDIO_FILTER);
|
||||
|
||||
|
||||
/* FIXME: not needed anymore when we can add pad templates, etc in class_init
|
||||
* as class_data contains the Descriptor too */
|
||||
g_type_set_qdata (type, descriptor_quark, lv2plugin);
|
||||
|
||||
return gst_element_register (plugin, type_name, GST_RANK_NONE, type);
|
||||
}
|
||||
|
|
|
@ -557,9 +557,8 @@ gst_lv2_source_base_finalize (GstLV2SourceClass * lv2_class)
|
|||
gst_lv2_class_finalize (&lv2_class->lv2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_lv2_source_class_init (GstLV2SourceClass * klass, LilvPlugin * lv2plugin)
|
||||
gst_lv2_source_class_init (GstLV2SourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstBaseSrcClass *src_class = (GstBaseSrcClass *) klass;
|
||||
|
@ -581,8 +580,6 @@ gst_lv2_source_class_init (GstLV2SourceClass * klass, LilvPlugin * lv2plugin)
|
|||
src_class->stop = gst_lv2_source_stop;
|
||||
src_class->fill = gst_lv2_source_fill;
|
||||
|
||||
klass->lv2.plugin = lv2plugin;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
GST_LV2_SOURCE_PROP_SAMPLES_PER_BUFFER,
|
||||
g_param_spec_int ("samplesperbuffer", "Samples per buffer",
|
||||
|
@ -629,33 +626,23 @@ gst_lv2_source_init (GstLV2Source * self, GstLV2SourceClass * klass)
|
|||
self->generate_samples_per_buffer = self->samples_per_buffer;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_lv2_source_register_element (GstPlugin * plugin, const gchar * type_name,
|
||||
gpointer * lv2plugin)
|
||||
void
|
||||
gst_lv2_source_register_element (GstPlugin * plugin, GstStructure * lv2_meta)
|
||||
{
|
||||
GType type;
|
||||
GTypeInfo typeinfo = {
|
||||
GTypeInfo info = {
|
||||
sizeof (GstLV2SourceClass),
|
||||
(GBaseInitFunc) gst_lv2_source_base_init,
|
||||
(GBaseFinalizeFunc) gst_lv2_source_base_finalize,
|
||||
(GClassInitFunc) gst_lv2_source_class_init,
|
||||
NULL,
|
||||
lv2plugin,
|
||||
NULL,
|
||||
sizeof (GstLV2Source),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_lv2_source_init,
|
||||
};
|
||||
|
||||
/* create the type */
|
||||
type = g_type_register_static (GST_TYPE_BASE_SRC, type_name, &typeinfo, 0);
|
||||
gst_lv2_register_element (plugin, GST_TYPE_BASE_SRC, &info, lv2_meta);
|
||||
|
||||
if (!parent_class)
|
||||
parent_class = g_type_class_ref (GST_TYPE_BASE_SRC);
|
||||
|
||||
|
||||
/* FIXME: not needed anymore when we can add pad templates, etc in class_init
|
||||
* as class_data contains the Descriptor too */
|
||||
g_type_set_qdata (type, descriptor_quark, lv2plugin);
|
||||
|
||||
return gst_element_register (plugin, type_name, GST_RANK_NONE, type);
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ static gchar *
|
|||
gst_lv2_class_get_param_name (GstLV2Class * klass, GObjectClass * object_class,
|
||||
const LilvPort * port)
|
||||
{
|
||||
LilvPlugin *lv2plugin = klass->plugin;
|
||||
const LilvPlugin *lv2plugin = klass->plugin;
|
||||
gchar *ret;
|
||||
|
||||
ret = g_strdup (lilv_node_as_string (lilv_port_get_symbol (lv2plugin, port)));
|
||||
|
@ -316,7 +316,7 @@ gst_lv2_class_get_param_name (GstLV2Class * klass, GObjectClass * object_class,
|
|||
static gchar *
|
||||
gst_lv2_class_get_param_nick (GstLV2Class * klass, const LilvPort * port)
|
||||
{
|
||||
LilvPlugin *lv2plugin = klass->plugin;
|
||||
const LilvPlugin *lv2plugin = klass->plugin;
|
||||
|
||||
return g_strdup (lilv_node_as_string (lilv_port_get_name (lv2plugin, port)));
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ static GParamSpec *
|
|||
gst_lv2_class_get_param_spec (GstLV2Class * klass, GObjectClass * object_class,
|
||||
gint portnum)
|
||||
{
|
||||
LilvPlugin *lv2plugin = klass->plugin;
|
||||
const LilvPlugin *lv2plugin = klass->plugin;
|
||||
const LilvPort *port = lilv_plugin_get_port_by_index (lv2plugin, portnum);
|
||||
LilvNode *lv2def, *lv2min, *lv2max;
|
||||
GParamSpec *ret;
|
||||
|
@ -415,7 +415,7 @@ void
|
|||
gst_lv2_element_class_set_metadata (GstLV2Class * lv2_class,
|
||||
GstElementClass * elem_class, const gchar * lv2_class_tags)
|
||||
{
|
||||
LilvPlugin *lv2plugin = lv2_class->plugin;
|
||||
const LilvPlugin *lv2plugin = lv2_class->plugin;
|
||||
LilvNode *val;
|
||||
const LilvPluginClass *lv2plugin_class;
|
||||
const LilvNode *cval;
|
||||
|
@ -454,16 +454,26 @@ gst_lv2_element_class_set_metadata (GstLV2Class * lv2_class,
|
|||
void
|
||||
gst_lv2_class_init (GstLV2Class * lv2_class, GType type)
|
||||
{
|
||||
LilvPlugin *lv2plugin;
|
||||
const GValue *value =
|
||||
gst_structure_get_value (lv2_meta_all, g_type_name (type));
|
||||
GstStructure *lv2_meta = g_value_get_boxed (value);
|
||||
const LilvPlugin *lv2plugin;
|
||||
/* FIXME Handle channels positionning
|
||||
* GstAudioChannelPosition position = GST_AUDIO_CHANNEL_POSITION_INVALID; */
|
||||
guint j, in_pad_index = 0, out_pad_index = 0;
|
||||
const LilvPlugins *plugins = lilv_world_get_all_plugins (world);
|
||||
LilvNode *plugin_uri;
|
||||
const gchar *element_uri;
|
||||
|
||||
GST_DEBUG ("LV2 initializing class");
|
||||
|
||||
lv2plugin = (LilvPlugin *) g_type_get_qdata (type, descriptor_quark);
|
||||
element_uri = gst_structure_get_string (lv2_meta, "element-uri");
|
||||
plugin_uri = lilv_new_uri (world, element_uri);
|
||||
g_assert (plugin_uri);
|
||||
lv2plugin = lilv_plugins_get_by_uri (plugins, plugin_uri);
|
||||
g_assert (lv2plugin);
|
||||
lv2_class->plugin = lv2plugin;
|
||||
lilv_node_free (plugin_uri);
|
||||
|
||||
lv2_class->in_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
|
||||
lv2_class->out_group.ports = g_array_new (FALSE, TRUE, sizeof (GstLV2Port));
|
||||
|
@ -541,3 +551,14 @@ 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));
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ struct _GstLV2Class
|
|||
{
|
||||
guint properties;
|
||||
|
||||
LilvPlugin *plugin;
|
||||
const LilvPlugin *plugin;
|
||||
|
||||
GstLV2Group in_group; /**< Array of GstLV2Group */
|
||||
GstLV2Group out_group; /**< Array of GstLV2Group */
|
||||
|
@ -106,6 +106,8 @@ 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