From 978df5d0ffb5006da9ae28ca875b0d8a725fd925 Mon Sep 17 00:00:00 2001 From: Vivia Nikolaidou Date: Thu, 23 Feb 2017 20:16:17 +0200 Subject: [PATCH] paramspecs: Add GstParamSpecArray for GST_TYPE_ARRAY typed properties These are mostly useful to get our automatic serialization/deserialization from strings and simple usage from gst-launch or similar. https://bugzilla.gnome.org/show_bug.cgi?id=777375 --- gst/gstparamspecs.c | 155 ++++++++++++++++++++++++++++++++++++++++++ gst/gstparamspecs.h | 28 ++++++++ win32/common/libgstreamer.def | 2 + 3 files changed, 185 insertions(+) diff --git a/gst/gstparamspecs.c b/gst/gstparamspecs.c index 14ae796..8fad46f 100644 --- a/gst/gstparamspecs.c +++ b/gst/gstparamspecs.c @@ -202,3 +202,158 @@ gst_param_spec_fraction (const gchar * name, const gchar * nick, return pspec; } + +static void +_gst_param_array_init (GParamSpec * pspec) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + + aspec->element_spec = NULL; +} + +static void +_gst_param_array_finalize (GParamSpec * pspec) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + GParamSpecClass *parent_class = + g_type_class_peek (g_type_parent (GST_TYPE_PARAM_ARRAY_LIST)); + + if (aspec->element_spec) { + g_param_spec_unref (aspec->element_spec); + aspec->element_spec = NULL; + } + + parent_class->finalize (pspec); +} + +static gboolean +_gst_param_array_validate (GParamSpec * pspec, GValue * value) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + + /* ensure array values validity against a present element spec */ + if (aspec->element_spec) { + GParamSpec *element_spec = aspec->element_spec; + guint i; + + for (i = 0; i < gst_value_array_get_size (value); i++) { + GValue *element = (GValue *) gst_value_array_get_value (value, i); + + /* need to fixup value type, or ensure that the array value is initialized at all */ + if (!g_value_type_compatible (G_VALUE_TYPE (element), + G_PARAM_SPEC_VALUE_TYPE (element_spec))) { + if (G_VALUE_TYPE (element) != 0) + g_value_unset (element); + g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec)); + g_param_value_set_default (element_spec, element); + return FALSE; + } + /* validate array value against element_spec */ + if (!g_param_value_validate (element_spec, element)) + return FALSE; + } + } + + return TRUE; +} + +static gint +_gst_param_array_values_cmp (GParamSpec * pspec, const GValue * value1, + const GValue * value2) +{ + GstParamSpecArray *aspec = GST_PARAM_SPEC_ARRAY_LIST (pspec); + guint size1, size2; + + if (!value1 || !value2) + return value2 ? -1 : value1 != value2; + + size1 = gst_value_array_get_size (value1); + size2 = gst_value_array_get_size (value2); + + if (size1 != size2) + return size1 < size2 ? -1 : 1; + else if (!aspec->element_spec) { + /* we need an element specification for comparisons, so there's not much + * to compare here, try to at least provide stable lesser/greater result + */ + return size1 < size2 ? -1 : size1 > size2; + } else { /* size1 == size2 */ + guint i; + + for (i = 0; i < size1; i++) { + const GValue *element1 = gst_value_array_get_value (value1, i); + const GValue *element2 = gst_value_array_get_value (value2, i); + gint cmp; + + /* need corresponding element types, provide stable result otherwise */ + if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2)) + return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1; + cmp = g_param_values_cmp (aspec->element_spec, element1, element2); + if (cmp) + return cmp; + } + return 0; + } +} + +GType +gst_param_spec_array_get_type (void) +{ + static GType type; /* 0 */ + + /* register GST_TYPE_PARAM_FRACTION */ + if (type == 0) { + static GParamSpecTypeInfo pspec_info = { + sizeof (GstParamSpecArray), /* instance_size */ + 0, /* n_preallocs */ + _gst_param_array_init, /* instance_init */ + G_TYPE_INVALID, /* value_type */ + _gst_param_array_finalize, /* finalize */ + NULL, /* value_set_default */ + _gst_param_array_validate, /* value_validate */ + _gst_param_array_values_cmp, /* values_cmp */ + }; + pspec_info.value_type = GST_TYPE_ARRAY; + type = g_param_type_register_static ("GstParamArray", &pspec_info); + } + return type; +} + +/** + * gst_param_spec_array: + * @name: canonical name of the property specified + * @nick: nick name for the property specified + * @blurb: description of the property specified + * @element_spec: GParamSpec of the array + * @flags: flags for the property specified + * + * This function creates a GstArray GParamSpec for use by objects/elements + * that want to expose properties of GstArray type. This function is + * typically * used in connection with g_object_class_install_property() in a + * GObjects's instance_init function. + * + * Returns: (transfer full): a newly created parameter specification + */ + +GParamSpec * +gst_param_spec_array (const gchar * name, + const gchar * nick, + const gchar * blurb, GParamSpec * element_spec, GParamFlags flags) +{ + GstParamSpecArray *aspec; + + if (element_spec) + g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL); + + aspec = g_param_spec_internal (GST_TYPE_PARAM_ARRAY_LIST, + name, nick, blurb, flags); + if (aspec == NULL) + return NULL; + + if (element_spec) { + aspec->element_spec = g_param_spec_ref (element_spec); + g_param_spec_sink (element_spec); + } + + return G_PARAM_SPEC (aspec); +} diff --git a/gst/gstparamspecs.h b/gst/gstparamspecs.h index 64377dc..8a326c0 100644 --- a/gst/gstparamspecs.h +++ b/gst/gstparamspecs.h @@ -75,14 +75,22 @@ G_BEGIN_DECLS #define GST_PARAM_SPEC_FRACTION(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GST_TYPE_PARAM_FRACTION, GstParamSpecFraction)) +#define GST_TYPE_PARAM_ARRAY_LIST (gst_param_spec_array_get_type ()) +#define GST_IS_PARAM_SPEC_ARRAY_LIST(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GST_TYPE_PARAM_ARRAY_LIST)) +#define GST_PARAM_SPEC_ARRAY_LIST(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GST_TYPE_PARAM_ARRAY_LIST, GstParamSpecArray)) + + /* --- get_type functions --- */ GType gst_param_spec_fraction_get_type (void); +GType gst_param_spec_array_get_type (void); + /* --- typedefs & structures --- */ typedef struct _GstParamSpecFraction GstParamSpecFraction; +typedef struct _GstParamSpecArray GstParamSpecArray; /** * GstParamSpecFraction: @@ -105,6 +113,20 @@ struct _GstParamSpecFraction { gint def_num, def_den; }; +/** + * GstParamSpecArray: + * @parent_instance: super class + * @value_array: the array of values + * + * A GParamSpec derived structure that contains the meta data for fractional + * properties. + */ +struct _GstParamSpecArray { + GParamSpec parent_instance; + + GParamSpec * element_spec; +}; + /* --- GParamSpec prototypes --- */ @@ -116,6 +138,12 @@ GParamSpec * gst_param_spec_fraction (const gchar * name, gint default_num, gint default_denom, GParamFlags flags) G_GNUC_MALLOC; +GParamSpec * gst_param_spec_array (const gchar * name, + const gchar * nick, + const gchar * blurb, + GParamSpec * element_spec, + GParamFlags flags) G_GNUC_MALLOC; + G_END_DECLS #endif /* __GST_PARAMSPECS_H__ */ diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 1f0fe3f..0e41531 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -966,6 +966,8 @@ EXPORTS gst_pad_template_pad_created gst_pad_unlink gst_pad_use_fixed_caps + gst_param_spec_array + gst_param_spec_array_get_type gst_param_spec_fraction gst_param_spec_fraction_get_type gst_parent_buffer_meta_api_get_type -- 2.7.4