summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/gst/gstreamer-sections.txt4
-rw-r--r--gst/gststructure.c247
-rw-r--r--gst/gststructure.h15
-rw-r--r--tests/check/gst/gststructure.c103
-rw-r--r--win32/common/libgstreamer.def4
5 files changed, 373 insertions, 0 deletions
diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt
index 048d24fed8..df5fb4cc10 100644
--- a/docs/gst/gstreamer-sections.txt
+++ b/docs/gst/gstreamer-sections.txt
@@ -2012,8 +2012,12 @@ gst_structure_get_name
gst_structure_has_name
gst_structure_set_name
gst_structure_get_name_id
+gst_structure_id_get
+gst_structure_id_get_valist
gst_structure_id_get_value
gst_structure_id_set_value
+gst_structure_get
+gst_structure_get_valist
gst_structure_get_value
gst_structure_set_value
gst_structure_set
diff --git a/gst/gststructure.c b/gst/gststructure.c
index 8962321827..e446b7fbf7 100644
--- a/gst/gststructure.c
+++ b/gst/gststructure.c
@@ -2342,3 +2342,250 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
return FALSE;
}
+
+/* our very own version of G_VALUE_LCOPY that allows NULL return locations
+ * (useful for message parsing functions where the return location is user
+ * supplied and the user may pass NULL if the value isn't of interest) */
+#define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname) \
+G_STMT_START { \
+ const GValue *_value = (value); \
+ guint _flags = (flags); \
+ GType _value_type = G_VALUE_TYPE (_value); \
+ GTypeValueTable *_vtable = g_type_value_table_peek (_value_type); \
+ gchar *_lcopy_format = _vtable->lcopy_format; \
+ GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, }; \
+ guint _n_values = 0; \
+ \
+ while (*_lcopy_format != '\0') { \
+ g_assert (*_lcopy_format == G_VALUE_COLLECT_POINTER); \
+ _cvalues[_n_values++].v_pointer = va_arg ((var_args), gpointer); \
+ _lcopy_format++; \
+ } \
+ if (_n_values == 2 && !!_cvalues[0].v_pointer != !!_cvalues[1].v_pointer) { \
+ *(__error) = g_strdup_printf ("either all or none of the return " \
+ "locations for field '%s' need to be NULL", fieldname); \
+ } else if (_cvalues[0].v_pointer != NULL) { \
+ *(__error) = _vtable->lcopy_value (_value, _n_values, _cvalues, _flags); \
+ } \
+} G_STMT_END
+
+/**
+ * gst_structure_get_valist:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @valist: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * valist-variant of gst_structure_get(). Look at the documentation of
+ * gst_structure_get() for more details.
+ *
+ * Returns: TRUE, or FALSE if there was a problem reading any of the fields
+ *
+ * Since: 0.10.24
+ */
+gboolean
+gst_structure_get_valist (GstStructure * structure,
+ const char *first_fieldname, va_list args)
+{
+ const char *field_name;
+ GType expected_type = G_TYPE_INVALID;
+
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+ g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+ field_name = first_fieldname;
+ while (field_name) {
+ const GValue *val = NULL;
+ gchar *err = NULL;
+
+ expected_type = va_arg (args, GType);
+
+ val = gst_structure_get_value (structure, field_name);
+
+ if (val == NULL)
+ goto no_such_field;
+
+ if (G_VALUE_TYPE (val) != expected_type)
+ goto wrong_type;
+
+ GST_VALUE_LCOPY (val, args, 0, &err, field_name);
+ if (err) {
+ g_warning ("%s: %s", G_STRFUNC, err);
+ g_free (err);
+ return FALSE;
+ }
+
+ field_name = va_arg (args, const gchar *);
+ }
+
+ return TRUE;
+
+/* ERRORS */
+no_such_field:
+ {
+ GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
+ field_name, structure);
+ return FALSE;
+ }
+wrong_type:
+ {
+ GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
+ "field was of type '%s': %" GST_PTR_FORMAT, field_name,
+ GST_STR_NULL (g_type_name (expected_type)),
+ G_VALUE_TYPE_NAME (gst_structure_get_value (structure, field_name)),
+ structure);
+ return FALSE;
+ }
+}
+
+/**
+ * gst_structure_id_get_valist:
+ * @structure: a #GstStructure
+ * @first_field_id: the quark of the first field to read
+ * @valist: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * valist-variant of gst_structure_id_get(). Look at the documentation of
+ * gst_structure_id_get() for more details.
+ *
+ * Returns: TRUE, or FALSE if there was a problem reading any of the fields
+ *
+ * Since: 0.10.24
+ */
+gboolean
+gst_structure_id_get_valist (GstStructure * structure, GQuark first_field_id,
+ va_list args)
+{
+ GQuark field_id;
+ GType expected_type = G_TYPE_INVALID;
+
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+ g_return_val_if_fail (first_field_id != 0, FALSE);
+
+ field_id = first_field_id;
+ while (field_id) {
+ const GValue *val = NULL;
+ gchar *err = NULL;
+
+ expected_type = va_arg (args, GType);
+
+ val = gst_structure_id_get_value (structure, field_id);
+
+ if (val == NULL)
+ goto no_such_field;
+
+ if (G_VALUE_TYPE (val) != expected_type)
+ goto wrong_type;
+
+ GST_VALUE_LCOPY (val, args, 0, &err, g_quark_to_string (field_id));
+ if (err) {
+ g_warning ("%s: %s", G_STRFUNC, err);
+ g_free (err);
+ return FALSE;
+ }
+
+ field_id = va_arg (args, GQuark);
+ }
+
+ return TRUE;
+
+/* ERRORS */
+no_such_field:
+ {
+ GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
+ GST_STR_NULL (g_quark_to_string (field_id)), structure);
+ return FALSE;
+ }
+wrong_type:
+ {
+ GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
+ "field was of type '%s': %" GST_PTR_FORMAT,
+ g_quark_to_string (field_id),
+ GST_STR_NULL (g_type_name (expected_type)),
+ G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)),
+ structure);
+ return FALSE;
+ }
+}
+
+/**
+ * gst_structure_get:
+ * @structure: a #GstStructure
+ * @first_fieldname: the name of the first field to read
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * Variable arguments should be in the form field name, field type
+ * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
+ * The last variable argument should be NULL.
+ *
+ * For refcounted (mini)objects you will acquire your own reference which
+ * you must release with a suitable _unref() when no longer needed. For
+ * strings and boxed types you will acquire a copy which you will need to
+ * release with either g_free() or the suiteable function for the boxed type.
+ *
+ * Returns: FALSE if there was a problem reading any of the fields (e.g.
+ * because the field requested did not exist, or was of a type other
+ * than the type specified), otherwise TRUE.
+ *
+ * Since: 0.10.24
+ */
+gboolean
+gst_structure_get (GstStructure * structure, const char *first_fieldname, ...)
+{
+ gboolean ret;
+ va_list args;
+
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+ g_return_val_if_fail (first_fieldname != NULL, FALSE);
+
+ va_start (args, first_fieldname);
+ ret = gst_structure_get_valist (structure, first_fieldname, args);
+ va_end (args);
+
+ return ret;
+}
+
+/**
+ * gst_structure_id_get:
+ * @structure: a #GstStructure
+ * @first_field_id: the quark of the first field to read
+ * @...: variable arguments
+ *
+ * Parses the variable arguments and reads fields from @structure accordingly.
+ * Variable arguments should be in the form field id quark, field type
+ * (as a GType), pointer(s) to a variable(s) to hold the return value(s).
+ * The last variable argument should be NULL (technically it should be a
+ * 0 quark, but we require NULL so compilers that support it can check for
+ * the NULL terminator and warn if it's not there).
+ *
+ * This function is just like gst_structure_get() only that it is slightly
+ * more efficient since it saves the string-to-quark lookup in the global
+ * quark hashtable.
+ *
+ * For refcounted (mini)objects you will acquire your own reference which
+ * you must release with a suitable _unref() when no longer needed. For
+ * strings and boxed types you will acquire a copy which you will need to
+ * release with either g_free() or the suiteable function for the boxed type.
+ *
+ * Returns: FALSE if there was a problem reading any of the fields (e.g.
+ * because the field requested did not exist, or was of a type other
+ * than the type specified), otherwise TRUE.
+ *
+ * Since: 0.10.24
+ */
+gboolean
+gst_structure_id_get (GstStructure * structure, GQuark first_field_id, ...)
+{
+ gboolean ret;
+ va_list args;
+
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
+ g_return_val_if_fail (first_field_id != 0, FALSE);
+
+ va_start (args, first_field_id);
+ ret = gst_structure_id_get_valist (structure, first_field_id, args);
+ va_end (args);
+
+ return ret;
+}
diff --git a/gst/gststructure.h b/gst/gststructure.h
index ecefea284c..aa3aa5d6b5 100644
--- a/gst/gststructure.h
+++ b/gst/gststructure.h
@@ -132,6 +132,21 @@ void gst_structure_id_set_valist (GstStructure
GQuark fieldname,
va_list varargs);
+gboolean gst_structure_get_valist (GstStructure *structure,
+ const char *first_fieldname,
+ va_list args);
+
+gboolean gst_structure_get (GstStructure *structure,
+ const char *first_fieldname,
+ ...) G_GNUC_NULL_TERMINATED;
+
+gboolean gst_structure_id_get_valist (GstStructure *structure,
+ GQuark first_field_id,
+ va_list args);
+
+gboolean gst_structure_id_get (GstStructure *structure,
+ GQuark first_field_id,
+ ...) G_GNUC_NULL_TERMINATED;
G_CONST_RETURN GValue * gst_structure_id_get_value (const GstStructure *structure,
GQuark field);
diff --git a/tests/check/gst/gststructure.c b/tests/check/gst/gststructure.c
index 3d84057e00..bd126cf22b 100644
--- a/tests/check/gst/gststructure.c
+++ b/tests/check/gst/gststructure.c
@@ -433,6 +433,108 @@ GST_START_TEST (test_empty_string_fields)
GST_END_TEST;
+GST_START_TEST (test_vararg_getters)
+{
+ GstStructure *s;
+ GstBuffer *buf, *buf2;
+ gboolean ret;
+ GstCaps *caps, *caps2;
+ gdouble d;
+ gint64 i64;
+ gchar *c;
+ gint i, num, denom;
+
+ buf = gst_buffer_new_and_alloc (3);
+ GST_BUFFER_DATA (buf)[0] = 0xf0;
+ GST_BUFFER_DATA (buf)[1] = 0x66;
+ GST_BUFFER_DATA (buf)[2] = 0x0d;
+
+ caps = gst_caps_new_simple ("video/x-foo", NULL);
+
+ s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
+ G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
+ GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99),
+ "double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14,
+ NULL);
+
+ /* first the plain one */
+ ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string",
+ G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf",
+ GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int",
+ G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL);
+
+ fail_unless (ret);
+ fail_unless_equals_string (c, "Hello World!");
+ fail_unless_equals_int (i, 12345678);
+ fail_unless_equals_float (d, G_MAXDOUBLE);
+ fail_unless_equals_int (num, 39);
+ fail_unless_equals_int (denom, 14);
+ fail_unless (i64 == -99);
+ fail_unless (caps == caps2);
+ fail_unless (buf == buf2);
+
+ /* expected failures */
+ ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL));
+ fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double",
+ G_TYPE_FLOAT, &d, NULL));
+ fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble",
+ G_TYPE_DOUBLE, &d, NULL));
+
+ g_free (c);
+ c = NULL;
+ gst_caps_unref (caps2);
+ caps2 = NULL;
+ gst_buffer_unref (buf2);
+ buf2 = NULL;
+
+ /* and now the _id variant */
+ ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
+ G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
+ &c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2,
+ g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2,
+ g_quark_from_static_string ("int"), G_TYPE_INT, &i,
+ g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL);
+
+ fail_unless (ret);
+ fail_unless_equals_string (c, "Hello World!");
+ fail_unless_equals_int (i, 12345678);
+ fail_unless_equals_float (d, G_MAXDOUBLE);
+ fail_unless (i64 == -99);
+ fail_unless (caps == caps2);
+ fail_unless (buf == buf2);
+
+ /* expected failures */
+ ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
+ fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
+ G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT,
+ &d, NULL));
+ fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
+ G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE,
+ &d, NULL));
+
+ g_free (c);
+ gst_caps_unref (caps2);
+ gst_buffer_unref (buf2);
+
+ /* finally make sure NULL as return location is handled gracefully */
+ ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
+ G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf",
+ GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION,
+ NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL);
+
+ ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
+ &denom, NULL));
+ ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
+ NULL, NULL));
+
+ /* clean up */
+ gst_caps_unref (caps);
+ gst_buffer_unref (buf);
+ gst_structure_free (s);
+}
+
+GST_END_TEST;
+
static Suite *
gst_structure_suite (void)
{
@@ -451,6 +553,7 @@ gst_structure_suite (void)
tcase_add_test (tc_chain, test_structure_nested);
tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
tcase_add_test (tc_chain, test_empty_string_fields);
+ tcase_add_test (tc_chain, test_vararg_getters);
return s;
}
diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def
index 006ad95943..7abab529b5 100644
--- a/win32/common/libgstreamer.def
+++ b/win32/common/libgstreamer.def
@@ -866,6 +866,7 @@ EXPORTS
gst_structure_foreach
gst_structure_free
gst_structure_from_string
+ gst_structure_get
gst_structure_get_boolean
gst_structure_get_clock_time
gst_structure_get_date
@@ -880,11 +881,14 @@ EXPORTS
gst_structure_get_string
gst_structure_get_type
gst_structure_get_uint
+ gst_structure_get_valist
gst_structure_get_value
gst_structure_has_field
gst_structure_has_field_typed
gst_structure_has_name
gst_structure_id_empty_new
+ gst_structure_id_get
+ gst_structure_id_get_valist
gst_structure_id_get_value
gst_structure_id_new
gst_structure_id_set