2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 * @short_description: GValue implementations specific
26 * GValue implementations specific to GStreamer.
28 * Note that operations on the same #GValue from multiple threads may lead to
29 * undefined behaviour.
32 /* Suppress warnings for GValueAraray */
33 #define GLIB_DISABLE_DEPRECATION_WARNINGS
44 #include "gst_private.h"
45 #include "glib-compat-private.h"
47 #include <gobject/gvaluecollector.h>
51 * @dest: a #GValue for the result
52 * @value1: a #GValue operand
53 * @value2: a #GValue operand
55 * Used by gst_value_union() to perform unification for a specific #GValue
56 * type. Register a new implementation with gst_value_register_union_func().
58 * Returns: %TRUE if a union was successful
60 typedef gboolean (*GstValueUnionFunc) (GValue * dest,
61 const GValue * value1, const GValue * value2);
63 /* GstValueIntersectFunc:
64 * @dest: (out caller-allocates): a #GValue for the result
65 * @value1: a #GValue operand
66 * @value2: a #GValue operand
68 * Used by gst_value_intersect() to perform intersection for a specific #GValue
69 * type. If the intersection is non-empty, the result is
70 * placed in @dest and %TRUE is returned. If the intersection is
71 * empty, @dest is unmodified and %FALSE is returned.
72 * Register a new implementation with gst_value_register_intersect_func().
74 * Returns: %TRUE if the values can intersect
76 typedef gboolean (*GstValueIntersectFunc) (GValue * dest,
77 const GValue * value1, const GValue * value2);
79 /* GstValueSubtractFunc:
80 * @dest: (out caller-allocates): a #GValue for the result
81 * @minuend: a #GValue operand
82 * @subtrahend: a #GValue operand
84 * Used by gst_value_subtract() to perform subtraction for a specific #GValue
85 * type. Register a new implementation with gst_value_register_subtract_func().
87 * Returns: %TRUE if the subtraction is not empty
89 typedef gboolean (*GstValueSubtractFunc) (GValue * dest,
90 const GValue * minuend, const GValue * subtrahend);
92 static void gst_value_register_union_func (GType type1,
93 GType type2, GstValueUnionFunc func);
94 static void gst_value_register_intersect_func (GType type1,
95 GType type2, GstValueIntersectFunc func);
96 static void gst_value_register_subtract_func (GType minuend_type,
97 GType subtrahend_type, GstValueSubtractFunc func);
99 static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after,
100 GValue * value, GType type);
101 static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after,
102 GValue * value, GType type);
104 typedef struct _GstValueUnionInfo GstValueUnionInfo;
105 struct _GstValueUnionInfo
109 GstValueUnionFunc func;
112 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
113 struct _GstValueIntersectInfo
117 GstValueIntersectFunc func;
120 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
121 struct _GstValueSubtractInfo
125 GstValueSubtractFunc func;
128 struct _GstFlagSetClass
131 GType flags_type; /* Type of the GFlags this flagset carries (can be 0) */
134 typedef struct _GstFlagSetClass GstFlagSetClass;
136 typedef struct _GstValueAbbreviation GstValueAbbreviation;
138 struct _GstValueAbbreviation
140 const gchar *type_name;
144 #define FUNDAMENTAL_TYPE_ID_MAX \
145 (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
146 #define FUNDAMENTAL_TYPE_ID(type) \
147 ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
149 #define VALUE_LIST_ARRAY(v) ((GArray *) (v)->data[0].v_pointer)
150 #define VALUE_LIST_SIZE(v) (VALUE_LIST_ARRAY(v)->len)
151 #define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index (VALUE_LIST_ARRAY(v), GValue, (index)))
153 static GArray *gst_value_table;
154 static GHashTable *gst_value_hash;
155 static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1];
156 static GArray *gst_value_union_funcs;
157 static GArray *gst_value_intersect_funcs;
158 static GArray *gst_value_subtract_funcs;
160 /* Forward declarations */
161 static gchar *gst_value_serialize_fraction (const GValue * value);
163 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
164 static gint gst_value_compare_with_func (const GValue * value1,
165 const GValue * value2, GstValueCompareFunc compare);
167 static gchar *gst_string_wrap (const gchar * s);
168 static gchar *gst_string_unwrap (const gchar * s);
170 static void gst_value_move (GValue * dest, GValue * src);
171 static void _gst_value_list_append_and_take_value (GValue * value,
172 GValue * append_value);
173 static void _gst_value_array_append_and_take_value (GValue * value,
174 GValue * append_value);
176 static inline GstValueTable *
177 gst_value_hash_lookup_type (GType type)
179 if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type)))
180 return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)];
182 return g_hash_table_lookup (gst_value_hash, (gpointer) type);
186 gst_value_hash_add_type (GType type, const GstValueTable * table)
188 if (G_TYPE_IS_FUNDAMENTAL (type))
189 gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table;
191 g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table);
198 /* two helper functions to serialize/stringify any type of list
199 * regular lists are done with { }, arrays with < >
202 _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin,
203 const gchar * end, gboolean print_type)
206 GArray *array = value->data[0].v_pointer;
210 guint alen = array->len;
212 /* estimate minimum string length to minimise re-allocs in GString */
213 s = g_string_sized_new (2 + (6 * alen) + 2);
214 g_string_append (s, begin);
215 for (i = 0; i < alen; i++) {
216 v = &g_array_index (array, GValue, i);
217 s_val = gst_value_serialize (v);
220 g_string_append_c (s, '(');
221 g_string_append (s, _priv_gst_value_gtype_to_abbr (G_VALUE_TYPE (v)));
222 g_string_append_c (s, ')');
224 g_string_append (s, s_val);
227 g_string_append_len (s, ", ", 2);
230 GST_WARNING ("Could not serialize list/array value of type '%s'",
231 G_VALUE_TYPE_NAME (v));
234 g_string_append (s, end);
235 return g_string_free (s, FALSE);
239 gst_value_transform_any_list_string (const GValue * src_value,
240 GValue * dest_value, const gchar * begin, const gchar * end)
249 array = src_value->data[0].v_pointer;
252 /* estimate minimum string length to minimise re-allocs in GString */
253 s = g_string_sized_new (2 + (10 * alen) + 2);
254 g_string_append (s, begin);
255 for (i = 0; i < alen; i++) {
256 list_value = &g_array_index (array, GValue, i);
259 g_string_append_len (s, ", ", 2);
261 list_s = g_strdup_value_contents (list_value);
262 g_string_append (s, list_s);
265 g_string_append (s, end);
267 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
271 _gst_value_serialize_g_value_array (const GValue * value, const gchar * begin,
275 GValueArray *array = value->data[0].v_pointer;
279 guint alen = array->n_values;
281 /* estimate minimum string length to minimise re-allocs in GString */
282 s = g_string_sized_new (2 + (6 * alen) + 2);
283 g_string_append (s, begin);
284 for (i = 0; i < alen; i++) {
285 v = g_value_array_get_nth (array, i);
286 s_val = gst_value_serialize (v);
288 g_string_append (s, s_val);
291 g_string_append_len (s, ", ", 2);
294 GST_WARNING ("Could not serialize list/array value of type '%s'",
295 G_VALUE_TYPE_NAME (v));
298 g_string_append (s, end);
299 return g_string_free (s, FALSE);
303 _gst_value_transform_g_value_array_string (const GValue * src_value,
304 GValue * dest_value, const gchar * begin, const gchar * end)
313 array = src_value->data[0].v_pointer;
314 alen = array->n_values;
316 /* estimate minimum string length to minimise re-allocs in GString */
317 s = g_string_sized_new (2 + (10 * alen) + 2);
318 g_string_append (s, begin);
319 for (i = 0; i < alen; i++) {
320 list_value = g_value_array_get_nth (array, i);
323 g_string_append_len (s, ", ", 2);
325 list_s = g_strdup_value_contents (list_value);
326 g_string_append (s, list_s);
329 g_string_append (s, end);
331 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
335 * helper function to see if a type is fixed. Is used internally here and
336 * there. Do not export, since it doesn't work for types where the content
337 * decides the fixedness (e.g. GST_TYPE_ARRAY).
340 gst_type_is_fixed (GType type)
342 /* the basic int, string, double types */
343 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
346 /* our fundamental types that are certainly not fixed */
347 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
348 type == GST_TYPE_INT64_RANGE ||
349 type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE ||
350 type == GST_TYPE_STRUCTURE) {
353 /* other (boxed) types that are fixed */
354 if (type == GST_TYPE_BUFFER) {
358 if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
359 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
366 /* GValue functions usable for both regular lists and arrays */
368 gst_value_init_list_or_array (GValue * value)
370 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
374 copy_garray_of_gstvalue (const GArray * src)
380 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
381 g_array_set_size (dest, len);
382 for (i = 0; i < len; i++) {
383 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
384 &g_array_index (src, GValue, i));
391 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
393 dest_value->data[0].v_pointer =
394 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
398 gst_value_free_list_or_array (GValue * value)
401 GArray *src = (GArray *) value->data[0].v_pointer;
404 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
405 for (i = 0; i < len; i++) {
406 g_value_unset (&g_array_index (src, GValue, i));
408 g_array_free (src, TRUE);
413 gst_value_list_or_array_peek_pointer (const GValue * value)
415 return value->data[0].v_pointer;
419 gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
420 GTypeCValue * collect_values, guint collect_flags)
422 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
423 value->data[0].v_pointer = collect_values[0].v_pointer;
424 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
426 value->data[0].v_pointer =
427 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
433 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
434 GTypeCValue * collect_values, guint collect_flags)
436 GArray **dest = collect_values[0].v_pointer;
439 return g_strdup_printf ("value location for `%s' passed as NULL",
440 G_VALUE_TYPE_NAME (value));
441 if (!value->data[0].v_pointer)
442 return g_strdup_printf ("invalid value given for `%s'",
443 G_VALUE_TYPE_NAME (value));
444 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
445 *dest = (GArray *) value->data[0].v_pointer;
447 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
453 gst_value_list_or_array_get_basic_type (const GValue * value, GType * type)
455 if (G_UNLIKELY (value == NULL))
458 if (GST_VALUE_HOLDS_LIST (value)) {
459 if (VALUE_LIST_SIZE (value) == 0)
461 return gst_value_list_or_array_get_basic_type (VALUE_LIST_GET_VALUE (value,
464 if (GST_VALUE_HOLDS_ARRAY (value)) {
465 const GArray *array = (const GArray *) value->data[0].v_pointer;
468 return gst_value_list_or_array_get_basic_type (&g_array_index (array,
472 *type = G_VALUE_TYPE (value);
477 #define IS_RANGE_COMPAT(type1,type2,t1,t2) \
478 (((t1) == (type1) && (t2) == (type2)) || ((t2) == (type1) && (t1) == (type2)))
481 gst_value_list_or_array_are_compatible (const GValue * value1,
482 const GValue * value2)
484 GType basic_type1, basic_type2;
486 /* empty or same type is OK */
487 if (!gst_value_list_or_array_get_basic_type (value1, &basic_type1) ||
488 !gst_value_list_or_array_get_basic_type (value2, &basic_type2) ||
489 basic_type1 == basic_type2)
492 /* ranges are distinct types for each bound type... */
493 if (IS_RANGE_COMPAT (G_TYPE_INT, GST_TYPE_INT_RANGE, basic_type1,
496 if (IS_RANGE_COMPAT (G_TYPE_INT64, GST_TYPE_INT64_RANGE, basic_type1,
499 if (IS_RANGE_COMPAT (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, basic_type1,
502 if (IS_RANGE_COMPAT (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, basic_type1,
510 _gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
512 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
513 memset (append_value, 0, sizeof (GValue));
517 * gst_value_list_append_and_take_value:
518 * @value: a #GValue of type #GST_TYPE_LIST
519 * @append_value: (transfer full): the value to append
521 * Appends @append_value to the GstValueList in @value.
526 gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
528 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
529 g_return_if_fail (G_IS_VALUE (append_value));
530 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
533 _gst_value_list_append_and_take_value (value, append_value);
537 * gst_value_list_append_value:
538 * @value: a #GValue of type #GST_TYPE_LIST
539 * @append_value: (transfer none): the value to append
541 * Appends @append_value to the GstValueList in @value.
544 gst_value_list_append_value (GValue * value, const GValue * append_value)
548 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
549 g_return_if_fail (G_IS_VALUE (append_value));
550 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
553 gst_value_init_and_copy (&val, append_value);
554 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
558 * gst_value_list_prepend_value:
559 * @value: a #GValue of type #GST_TYPE_LIST
560 * @prepend_value: the value to prepend
562 * Prepends @prepend_value to the GstValueList in @value.
565 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
569 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
570 g_return_if_fail (G_IS_VALUE (prepend_value));
571 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
574 gst_value_init_and_copy (&val, prepend_value);
575 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
579 * gst_value_list_concat:
580 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
584 * Concatenates copies of @value1 and @value2 into a list. Values that are not
585 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
586 * @dest will be initialized to the type #GST_TYPE_LIST.
589 gst_value_list_concat (GValue * dest, const GValue * value1,
590 const GValue * value2)
592 guint i, value1_length, value2_length;
595 g_return_if_fail (dest != NULL);
596 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
597 g_return_if_fail (G_IS_VALUE (value1));
598 g_return_if_fail (G_IS_VALUE (value2));
599 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
602 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
604 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
605 g_value_init (dest, GST_TYPE_LIST);
606 array = (GArray *) dest->data[0].v_pointer;
607 g_array_set_size (array, value1_length + value2_length);
609 if (GST_VALUE_HOLDS_LIST (value1)) {
610 for (i = 0; i < value1_length; i++) {
611 gst_value_init_and_copy (&g_array_index (array, GValue, i),
612 VALUE_LIST_GET_VALUE (value1, i));
615 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
618 if (GST_VALUE_HOLDS_LIST (value2)) {
619 for (i = 0; i < value2_length; i++) {
620 gst_value_init_and_copy (&g_array_index (array, GValue,
621 i + value1_length), VALUE_LIST_GET_VALUE (value2, i));
624 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
629 /* same as gst_value_list_concat() but takes ownership of GValues */
631 gst_value_list_concat_and_take_values (GValue * dest, GValue * val1,
634 guint i, val1_length, val2_length;
635 gboolean val1_is_list;
636 gboolean val2_is_list;
639 g_assert (dest != NULL);
640 g_assert (G_VALUE_TYPE (dest) == 0);
641 g_assert (G_IS_VALUE (val1));
642 g_assert (G_IS_VALUE (val2));
643 g_assert (gst_value_list_or_array_are_compatible (val1, val2));
645 val1_is_list = GST_VALUE_HOLDS_LIST (val1);
646 val1_length = (val1_is_list ? VALUE_LIST_SIZE (val1) : 1);
648 val2_is_list = GST_VALUE_HOLDS_LIST (val2);
649 val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1);
651 g_value_init (dest, GST_TYPE_LIST);
652 array = (GArray *) dest->data[0].v_pointer;
653 g_array_set_size (array, val1_length + val2_length);
656 for (i = 0; i < val1_length; i++) {
657 g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i);
659 g_array_set_size (VALUE_LIST_ARRAY (val1), 0);
660 g_value_unset (val1);
662 g_array_index (array, GValue, 0) = *val1;
663 G_VALUE_TYPE (val1) = G_TYPE_INVALID;
667 for (i = 0; i < val2_length; i++) {
668 const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i);
669 g_array_index (array, GValue, i + val1_length) = *v2;
671 g_array_set_size (VALUE_LIST_ARRAY (val2), 0);
672 g_value_unset (val2);
674 g_array_index (array, GValue, val1_length) = *val2;
675 G_VALUE_TYPE (val2) = G_TYPE_INVALID;
680 * gst_value_list_merge:
681 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
685 * Merges copies of @value1 and @value2. Values that are not
686 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
688 * The result will be put into @dest and will either be a list that will not
689 * contain any duplicates, or a non-list type (if @value1 and @value2
693 gst_value_list_merge (GValue * dest, const GValue * value1,
694 const GValue * value2)
696 guint i, j, k, value1_length, value2_length, skipped;
701 g_return_if_fail (dest != NULL);
702 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
703 g_return_if_fail (G_IS_VALUE (value1));
704 g_return_if_fail (G_IS_VALUE (value2));
705 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
708 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
710 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
711 g_value_init (dest, GST_TYPE_LIST);
712 array = (GArray *) dest->data[0].v_pointer;
713 g_array_set_size (array, value1_length + value2_length);
715 if (GST_VALUE_HOLDS_LIST (value1)) {
716 for (i = 0; i < value1_length; i++) {
717 gst_value_init_and_copy (&g_array_index (array, GValue, i),
718 VALUE_LIST_GET_VALUE (value1, i));
721 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
726 if (GST_VALUE_HOLDS_LIST (value2)) {
727 for (i = 0; i < value2_length; i++) {
729 src = VALUE_LIST_GET_VALUE (value2, i);
730 for (k = 0; k < value1_length; k++) {
731 if (gst_value_compare (&g_array_index (array, GValue, k),
732 src) == GST_VALUE_EQUAL) {
739 gst_value_init_and_copy (&g_array_index (array, GValue, j), src);
745 for (k = 0; k < value1_length; k++) {
746 if (gst_value_compare (&g_array_index (array, GValue, k),
747 value2) == GST_VALUE_EQUAL) {
754 gst_value_init_and_copy (&g_array_index (array, GValue, j), value2);
758 guint new_size = value1_length + (value2_length - skipped);
762 g_array_set_size (array, new_size);
766 /* size is 1, take single value in list and make it new dest */
767 single_dest = g_array_index (array, GValue, 0);
769 /* clean up old value allocations: must set array size to 0, because
770 * allocated values are not inited meaning g_value_unset() will not
772 g_array_set_size (array, 0);
773 g_value_unset (dest);
775 /* the single value is our new result */
782 * gst_value_list_get_size:
783 * @value: a #GValue of type #GST_TYPE_LIST
785 * Gets the number of values contained in @value.
787 * Returns: the number of values
790 gst_value_list_get_size (const GValue * value)
792 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
794 return ((GArray *) value->data[0].v_pointer)->len;
798 * gst_value_list_get_value:
799 * @value: a #GValue of type #GST_TYPE_LIST
800 * @index: index of value to get from the list
802 * Gets the value that is a member of the list contained in @value and
803 * has the index @index.
805 * Returns: (transfer none): the value at the given index
808 gst_value_list_get_value (const GValue * value, guint index)
810 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
811 g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL);
813 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
818 * gst_value_array_append_value:
819 * @value: a #GValue of type #GST_TYPE_ARRAY
820 * @append_value: the value to append
822 * Appends @append_value to the GstValueArray in @value.
825 gst_value_array_append_value (GValue * value, const GValue * append_value)
829 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
830 g_return_if_fail (G_IS_VALUE (append_value));
831 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
834 gst_value_init_and_copy (&val, append_value);
835 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
839 _gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
841 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
842 memset (append_value, 0, sizeof (GValue));
846 * gst_value_array_append_and_take_value:
847 * @value: a #GValue of type #GST_TYPE_ARRAY
848 * @append_value: (transfer full): the value to append
850 * Appends @append_value to the GstValueArray in @value.
855 gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
857 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
858 g_return_if_fail (G_IS_VALUE (append_value));
859 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
862 _gst_value_array_append_and_take_value (value, append_value);
866 * gst_value_array_prepend_value:
867 * @value: a #GValue of type #GST_TYPE_ARRAY
868 * @prepend_value: the value to prepend
870 * Prepends @prepend_value to the GstValueArray in @value.
873 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
877 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
878 g_return_if_fail (G_IS_VALUE (prepend_value));
879 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
882 gst_value_init_and_copy (&val, prepend_value);
883 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
887 * gst_value_array_get_size:
888 * @value: a #GValue of type #GST_TYPE_ARRAY
890 * Gets the number of values contained in @value.
892 * Returns: the number of values
895 gst_value_array_get_size (const GValue * value)
897 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
899 return ((GArray *) value->data[0].v_pointer)->len;
903 * gst_value_array_get_value:
904 * @value: a #GValue of type #GST_TYPE_ARRAY
905 * @index: index of value to get from the array
907 * Gets the value that is a member of the array contained in @value and
908 * has the index @index.
910 * Returns: (transfer none): the value at the given index
913 gst_value_array_get_value (const GValue * value, guint index)
915 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
916 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
918 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
923 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
925 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
929 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
931 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
935 gst_value_transform_g_value_array_string (const GValue * src_value,
938 _gst_value_transform_g_value_array_string (src_value, dest_value, "< ", " >");
941 /* Do an unordered compare of the contents of a list */
943 gst_value_compare_value_list (const GValue * value1, const GValue * value2)
946 GArray *array1 = value1->data[0].v_pointer;
947 GArray *array2 = value2->data[0].v_pointer;
952 GstValueCompareFunc compare;
954 /* get length and do initial length check. */
956 if (len != array2->len)
957 return GST_VALUE_UNORDERED;
959 /* place to mark removed value indices of array2 */
960 removed = g_newa (guint8, len);
961 memset (removed, 0, len);
964 /* loop over array1, all items should be in array2. When we find an
965 * item in array2, remove it from array2 by marking it as removed */
966 for (i = 0; i < len; i++) {
967 v1 = &g_array_index (array1, GValue, i);
968 if ((compare = gst_value_get_compare_func (v1))) {
969 for (j = 0; j < len; j++) {
970 /* item is removed, we can skip it */
973 v2 = &g_array_index (array2, GValue, j);
974 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
975 /* mark item as removed now that we found it in array2 and
976 * decrement the number of remaining items in array2. */
982 /* item in array1 and not in array2, UNORDERED */
984 return GST_VALUE_UNORDERED;
986 return GST_VALUE_UNORDERED;
988 /* if not all items were removed, array2 contained something not in array1 */
990 return GST_VALUE_UNORDERED;
992 /* arrays are equal */
993 return GST_VALUE_EQUAL;
996 /* Perform an ordered comparison of the contents of an array */
998 gst_value_compare_value_array (const GValue * value1, const GValue * value2)
1001 GArray *array1 = value1->data[0].v_pointer;
1002 GArray *array2 = value2->data[0].v_pointer;
1003 guint len = array1->len;
1007 if (len != array2->len)
1008 return GST_VALUE_UNORDERED;
1010 for (i = 0; i < len; i++) {
1011 v1 = &g_array_index (array1, GValue, i);
1012 v2 = &g_array_index (array2, GValue, i);
1013 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1014 return GST_VALUE_UNORDERED;
1017 return GST_VALUE_EQUAL;
1021 gst_value_compare_g_value_array (const GValue * value1, const GValue * value2)
1024 GValueArray *array1 = value1->data[0].v_pointer;
1025 GValueArray *array2 = value2->data[0].v_pointer;
1026 guint len = array1->n_values;
1030 if (len != array2->n_values)
1031 return GST_VALUE_UNORDERED;
1033 for (i = 0; i < len; i++) {
1034 v1 = g_value_array_get_nth (array1, i);
1035 v2 = g_value_array_get_nth (array2, i);
1036 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1037 return GST_VALUE_UNORDERED;
1040 return GST_VALUE_EQUAL;
1044 gst_value_serialize_value_list (const GValue * value)
1046 return _priv_gst_value_serialize_any_list (value, "{ ", " }", TRUE);
1050 gst_value_deserialize_value_list (GValue * dest, const gchar * s)
1052 gchar *s2 = (gchar *) s;
1053 return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID);
1057 gst_value_serialize_value_array (const GValue * value)
1059 return _priv_gst_value_serialize_any_list (value, "< ", " >", TRUE);
1063 gst_value_deserialize_value_array (GValue * dest, const gchar * s)
1065 gchar *s2 = (gchar *) s;
1066 return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID);
1070 gst_value_serialize_g_value_array (const GValue * value)
1072 return _gst_value_serialize_g_value_array (value, "< ", " >");
1076 gst_value_deserialize_g_value_array (GValue * dest, const gchar * s)
1078 g_warning ("gst_value_deserialize_g_value_array: unimplemented");
1085 * Values in the range are defined as any value greater or equal
1086 * to min*step, AND lesser or equal to max*step.
1087 * For step == 1, this falls back to the traditional range semantics.
1089 * data[0] = (min << 32) | (max)
1094 #define INT_RANGE_MIN(v) ((gint) (((v)->data[0].v_uint64) >> 32))
1095 #define INT_RANGE_MAX(v) ((gint) (((v)->data[0].v_uint64) & 0xffffffff))
1096 #define INT_RANGE_STEP(v) ((v)->data[1].v_int)
1099 gst_value_init_int_range (GValue * value)
1101 G_STATIC_ASSERT (sizeof (gint) <= 2 * sizeof (guint64));
1103 value->data[0].v_uint64 = 0;
1104 value->data[1].v_int = 1;
1108 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
1110 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
1111 dest_value->data[1].v_int = src_value->data[1].v_int;
1115 gst_value_collect_int_range (GValue * value, guint n_collect_values,
1116 GTypeCValue * collect_values, guint collect_flags)
1118 if (n_collect_values != 2)
1119 return g_strdup_printf ("not enough value locations for `%s' passed",
1120 G_VALUE_TYPE_NAME (value));
1121 if (collect_values[0].v_int >= collect_values[1].v_int)
1122 return g_strdup_printf ("range start is not smaller than end for `%s'",
1123 G_VALUE_TYPE_NAME (value));
1125 gst_value_set_int_range_step (value, collect_values[0].v_int,
1126 collect_values[1].v_int, 1);
1132 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
1133 GTypeCValue * collect_values, guint collect_flags)
1135 guint32 *int_range_start = collect_values[0].v_pointer;
1136 guint32 *int_range_end = collect_values[1].v_pointer;
1138 if (!int_range_start)
1139 return g_strdup_printf ("start value location for `%s' passed as NULL",
1140 G_VALUE_TYPE_NAME (value));
1142 return g_strdup_printf ("end value location for `%s' passed as NULL",
1143 G_VALUE_TYPE_NAME (value));
1145 *int_range_start = INT_RANGE_MIN (value);
1146 *int_range_end = INT_RANGE_MAX (value);
1152 * gst_value_set_int_range_step:
1153 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1154 * @start: the start of the range
1155 * @end: the end of the range
1156 * @step: the step of the range
1158 * Sets @value to the range specified by @start, @end and @step.
1161 gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step)
1163 guint64 sstart, sstop;
1165 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
1166 g_return_if_fail (start < end);
1167 g_return_if_fail (step > 0);
1168 g_return_if_fail (start % step == 0);
1169 g_return_if_fail (end % step == 0);
1171 sstart = (guint) (start / step);
1172 sstop = (guint) (end / step);
1173 value->data[0].v_uint64 = (sstart << 32) | sstop;
1174 value->data[1].v_int = step;
1178 * gst_value_set_int_range:
1179 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1180 * @start: the start of the range
1181 * @end: the end of the range
1183 * Sets @value to the range specified by @start and @end.
1186 gst_value_set_int_range (GValue * value, gint start, gint end)
1188 gst_value_set_int_range_step (value, start, end, 1);
1192 * gst_value_get_int_range_min:
1193 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1195 * Gets the minimum of the range specified by @value.
1197 * Returns: the minimum of the range
1200 gst_value_get_int_range_min (const GValue * value)
1202 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1204 return INT_RANGE_MIN (value) * INT_RANGE_STEP (value);
1208 * gst_value_get_int_range_max:
1209 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1211 * Gets the maximum of the range specified by @value.
1213 * Returns: the maximum of the range
1216 gst_value_get_int_range_max (const GValue * value)
1218 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1220 return INT_RANGE_MAX (value) * INT_RANGE_STEP (value);
1224 * gst_value_get_int_range_step:
1225 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1227 * Gets the step of the range specified by @value.
1229 * Returns: the step of the range
1232 gst_value_get_int_range_step (const GValue * value)
1234 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1236 return INT_RANGE_STEP (value);
1240 gst_value_transform_int_range_string (const GValue * src_value,
1241 GValue * dest_value)
1243 if (INT_RANGE_STEP (src_value) == 1)
1244 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
1245 INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value));
1247 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]",
1248 INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value),
1249 INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value),
1250 INT_RANGE_STEP (src_value));
1254 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
1256 /* calculate the number of values in each range */
1257 gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1;
1258 gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1;
1260 /* they must be equal */
1262 return GST_VALUE_UNORDERED;
1264 /* if empty, equal */
1266 return GST_VALUE_EQUAL;
1268 /* if more than one value, then it is only equal if the step is equal
1269 and bounds lie on the same value */
1271 if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
1272 INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) &&
1273 INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) {
1274 return GST_VALUE_EQUAL;
1276 return GST_VALUE_UNORDERED;
1278 /* if just one, only if the value is equal */
1279 if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2))
1280 return GST_VALUE_EQUAL;
1281 return GST_VALUE_UNORDERED;
1286 gst_value_serialize_int_range (const GValue * value)
1288 if (INT_RANGE_STEP (value) == 1)
1289 return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value),
1290 INT_RANGE_MAX (value));
1292 return g_strdup_printf ("[ %d, %d, %d ]",
1293 INT_RANGE_MIN (value) * INT_RANGE_STEP (value),
1294 INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value));
1298 gst_value_deserialize_int_range (GValue * dest, const gchar * s)
1300 g_warning ("unimplemented");
1307 * Values in the range are defined as any value greater or equal
1308 * to min*step, AND lesser or equal to max*step.
1309 * For step == 1, this falls back to the traditional range semantics.
1312 #define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0])
1313 #define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1])
1314 #define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2])
1317 gst_value_init_int64_range (GValue * value)
1319 gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64));
1320 value->data[0].v_pointer = vals;
1321 INT64_RANGE_MIN (value) = 0;
1322 INT64_RANGE_MAX (value) = 0;
1323 INT64_RANGE_STEP (value) = 1;
1327 gst_value_free_int64_range (GValue * value)
1329 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1330 g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer);
1331 value->data[0].v_pointer = NULL;
1335 gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value)
1337 gint64 *vals = (gint64 *) dest_value->data[0].v_pointer;
1338 gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer;
1341 gst_value_init_int64_range (dest_value);
1344 if (src_vals != NULL) {
1345 INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value);
1346 INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value);
1347 INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value);
1352 gst_value_collect_int64_range (GValue * value, guint n_collect_values,
1353 GTypeCValue * collect_values, guint collect_flags)
1355 gint64 *vals = value->data[0].v_pointer;
1357 if (n_collect_values != 2)
1358 return g_strdup_printf ("not enough value locations for `%s' passed",
1359 G_VALUE_TYPE_NAME (value));
1360 if (collect_values[0].v_int64 >= collect_values[1].v_int64)
1361 return g_strdup_printf ("range start is not smaller than end for `%s'",
1362 G_VALUE_TYPE_NAME (value));
1365 gst_value_init_int64_range (value);
1368 gst_value_set_int64_range_step (value, collect_values[0].v_int64,
1369 collect_values[1].v_int64, 1);
1375 gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
1376 GTypeCValue * collect_values, guint collect_flags)
1378 guint64 *int_range_start = collect_values[0].v_pointer;
1379 guint64 *int_range_end = collect_values[1].v_pointer;
1380 guint64 *int_range_step = collect_values[2].v_pointer;
1381 gint64 *vals = (gint64 *) value->data[0].v_pointer;
1383 if (!int_range_start)
1384 return g_strdup_printf ("start value location for `%s' passed as NULL",
1385 G_VALUE_TYPE_NAME (value));
1387 return g_strdup_printf ("end value location for `%s' passed as NULL",
1388 G_VALUE_TYPE_NAME (value));
1389 if (!int_range_step)
1390 return g_strdup_printf ("step value location for `%s' passed as NULL",
1391 G_VALUE_TYPE_NAME (value));
1393 if (G_UNLIKELY (vals == NULL)) {
1394 return g_strdup_printf ("Uninitialised `%s' passed",
1395 G_VALUE_TYPE_NAME (value));
1398 *int_range_start = INT64_RANGE_MIN (value);
1399 *int_range_end = INT64_RANGE_MAX (value);
1400 *int_range_step = INT64_RANGE_STEP (value);
1406 * gst_value_set_int64_range_step:
1407 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1408 * @start: the start of the range
1409 * @end: the end of the range
1410 * @step: the step of the range
1412 * Sets @value to the range specified by @start, @end and @step.
1415 gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end,
1418 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1419 g_return_if_fail (start < end);
1420 g_return_if_fail (step > 0);
1421 g_return_if_fail (start % step == 0);
1422 g_return_if_fail (end % step == 0);
1424 INT64_RANGE_MIN (value) = start / step;
1425 INT64_RANGE_MAX (value) = end / step;
1426 INT64_RANGE_STEP (value) = step;
1430 * gst_value_set_int64_range:
1431 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1432 * @start: the start of the range
1433 * @end: the end of the range
1435 * Sets @value to the range specified by @start and @end.
1438 gst_value_set_int64_range (GValue * value, gint64 start, gint64 end)
1440 gst_value_set_int64_range_step (value, start, end, 1);
1444 * gst_value_get_int64_range_min:
1445 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1447 * Gets the minimum of the range specified by @value.
1449 * Returns: the minimum of the range
1452 gst_value_get_int64_range_min (const GValue * value)
1454 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1456 return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value);
1460 * gst_value_get_int64_range_max:
1461 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1463 * Gets the maximum of the range specified by @value.
1465 * Returns: the maximum of the range
1468 gst_value_get_int64_range_max (const GValue * value)
1470 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1472 return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value);
1476 * gst_value_get_int64_range_step:
1477 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1479 * Gets the step of the range specified by @value.
1481 * Returns: the step of the range
1484 gst_value_get_int64_range_step (const GValue * value)
1486 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1488 return INT64_RANGE_STEP (value);
1492 gst_value_transform_int64_range_string (const GValue * src_value,
1493 GValue * dest_value)
1495 if (INT64_RANGE_STEP (src_value) == 1)
1496 dest_value->data[0].v_pointer =
1497 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]",
1498 INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value));
1500 dest_value->data[0].v_pointer =
1501 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT
1502 ",%" G_GINT64_FORMAT "]",
1503 INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value),
1504 INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value),
1505 INT64_RANGE_STEP (src_value));
1509 gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
1511 /* calculate the number of values in each range */
1512 gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1;
1513 gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1;
1515 /* they must be equal */
1517 return GST_VALUE_UNORDERED;
1519 /* if empty, equal */
1521 return GST_VALUE_EQUAL;
1523 /* if more than one value, then it is only equal if the step is equal
1524 and bounds lie on the same value */
1526 if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
1527 INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) &&
1528 INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) {
1529 return GST_VALUE_EQUAL;
1531 return GST_VALUE_UNORDERED;
1533 /* if just one, only if the value is equal */
1534 if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2))
1535 return GST_VALUE_EQUAL;
1536 return GST_VALUE_UNORDERED;
1541 gst_value_serialize_int64_range (const GValue * value)
1543 if (INT64_RANGE_STEP (value) == 1)
1544 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]",
1545 INT64_RANGE_MIN (value), INT64_RANGE_MAX (value));
1547 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %"
1548 G_GINT64_FORMAT " ]",
1549 INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value),
1550 INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value),
1551 INT64_RANGE_STEP (value));
1555 gst_value_deserialize_int64_range (GValue * dest, const gchar * s)
1557 g_warning ("unimplemented");
1566 gst_value_init_double_range (GValue * value)
1568 value->data[0].v_double = 0;
1569 value->data[1].v_double = 0;
1573 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
1575 dest_value->data[0].v_double = src_value->data[0].v_double;
1576 dest_value->data[1].v_double = src_value->data[1].v_double;
1580 gst_value_collect_double_range (GValue * value, guint n_collect_values,
1581 GTypeCValue * collect_values, guint collect_flags)
1583 if (n_collect_values != 2)
1584 return g_strdup_printf ("not enough value locations for `%s' passed",
1585 G_VALUE_TYPE_NAME (value));
1586 if (collect_values[0].v_double >= collect_values[1].v_double)
1587 return g_strdup_printf ("range start is not smaller than end for `%s'",
1588 G_VALUE_TYPE_NAME (value));
1590 value->data[0].v_double = collect_values[0].v_double;
1591 value->data[1].v_double = collect_values[1].v_double;
1597 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
1598 GTypeCValue * collect_values, guint collect_flags)
1600 gdouble *double_range_start = collect_values[0].v_pointer;
1601 gdouble *double_range_end = collect_values[1].v_pointer;
1603 if (!double_range_start)
1604 return g_strdup_printf ("start value location for `%s' passed as NULL",
1605 G_VALUE_TYPE_NAME (value));
1606 if (!double_range_end)
1607 return g_strdup_printf ("end value location for `%s' passed as NULL",
1608 G_VALUE_TYPE_NAME (value));
1610 *double_range_start = value->data[0].v_double;
1611 *double_range_end = value->data[1].v_double;
1617 * gst_value_set_double_range:
1618 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1619 * @start: the start of the range
1620 * @end: the end of the range
1622 * Sets @value to the range specified by @start and @end.
1625 gst_value_set_double_range (GValue * value, gdouble start, gdouble end)
1627 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
1628 g_return_if_fail (start < end);
1630 value->data[0].v_double = start;
1631 value->data[1].v_double = end;
1635 * gst_value_get_double_range_min:
1636 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1638 * Gets the minimum of the range specified by @value.
1640 * Returns: the minimum of the range
1643 gst_value_get_double_range_min (const GValue * value)
1645 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1647 return value->data[0].v_double;
1651 * gst_value_get_double_range_max:
1652 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1654 * Gets the maximum of the range specified by @value.
1656 * Returns: the maximum of the range
1659 gst_value_get_double_range_max (const GValue * value)
1661 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1663 return value->data[1].v_double;
1667 gst_value_transform_double_range_string (const GValue * src_value,
1668 GValue * dest_value)
1670 gchar s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
1672 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
1673 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
1674 src_value->data[0].v_double),
1675 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
1676 src_value->data[1].v_double));
1680 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
1682 if (value2->data[0].v_double == value1->data[0].v_double &&
1683 value2->data[1].v_double == value1->data[1].v_double)
1684 return GST_VALUE_EQUAL;
1685 return GST_VALUE_UNORDERED;
1689 gst_value_serialize_double_range (const GValue * value)
1691 gchar d1[G_ASCII_DTOSTR_BUF_SIZE];
1692 gchar d2[G_ASCII_DTOSTR_BUF_SIZE];
1694 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1695 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
1696 return g_strdup_printf ("[ %s, %s ]", d1, d2);
1700 gst_value_deserialize_double_range (GValue * dest, const gchar * s)
1702 g_warning ("unimplemented");
1711 gst_value_init_fraction_range (GValue * value)
1716 ftype = GST_TYPE_FRACTION;
1718 value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
1719 g_value_init (&vals[0], ftype);
1720 g_value_init (&vals[1], ftype);
1724 gst_value_free_fraction_range (GValue * value)
1726 GValue *vals = (GValue *) value->data[0].v_pointer;
1729 /* we know the two values contain fractions without internal allocs */
1730 /* g_value_unset (&vals[0]); */
1731 /* g_value_unset (&vals[1]); */
1732 g_slice_free1 (2 * sizeof (GValue), vals);
1733 value->data[0].v_pointer = NULL;
1738 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value)
1740 GValue *vals = (GValue *) dest_value->data[0].v_pointer;
1741 GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
1744 gst_value_init_fraction_range (dest_value);
1745 vals = dest_value->data[0].v_pointer;
1747 if (src_vals != NULL) {
1748 g_value_copy (&src_vals[0], &vals[0]);
1749 g_value_copy (&src_vals[1], &vals[1]);
1754 gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
1755 GTypeCValue * collect_values, guint collect_flags)
1757 GValue *vals = (GValue *) value->data[0].v_pointer;
1759 if (n_collect_values != 4)
1760 return g_strdup_printf ("not enough value locations for `%s' passed",
1761 G_VALUE_TYPE_NAME (value));
1762 if (collect_values[1].v_int == 0)
1763 return g_strdup_printf ("passed '0' as first denominator for `%s'",
1764 G_VALUE_TYPE_NAME (value));
1765 if (collect_values[3].v_int == 0)
1766 return g_strdup_printf ("passed '0' as second denominator for `%s'",
1767 G_VALUE_TYPE_NAME (value));
1768 if (gst_util_fraction_compare (collect_values[0].v_int,
1769 collect_values[1].v_int, collect_values[2].v_int,
1770 collect_values[3].v_int) >= 0)
1771 return g_strdup_printf ("range start is not smaller than end for `%s'",
1772 G_VALUE_TYPE_NAME (value));
1775 gst_value_init_fraction_range (value);
1776 vals = value->data[0].v_pointer;
1779 gst_value_set_fraction (&vals[0], collect_values[0].v_int,
1780 collect_values[1].v_int);
1781 gst_value_set_fraction (&vals[1], collect_values[2].v_int,
1782 collect_values[3].v_int);
1788 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
1789 GTypeCValue * collect_values, guint collect_flags)
1792 gint *dest_values[4];
1793 GValue *vals = (GValue *) value->data[0].v_pointer;
1795 if (G_UNLIKELY (n_collect_values != 4))
1796 return g_strdup_printf ("not enough value locations for `%s' passed",
1797 G_VALUE_TYPE_NAME (value));
1799 for (i = 0; i < 4; i++) {
1800 if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
1801 return g_strdup_printf ("value location for `%s' passed as NULL",
1802 G_VALUE_TYPE_NAME (value));
1804 dest_values[i] = collect_values[i].v_pointer;
1807 if (G_UNLIKELY (vals == NULL)) {
1808 return g_strdup_printf ("Uninitialised `%s' passed",
1809 G_VALUE_TYPE_NAME (value));
1812 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
1813 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
1814 dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
1815 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
1820 * gst_value_set_fraction_range:
1821 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1822 * @start: the start of the range (a GST_TYPE_FRACTION GValue)
1823 * @end: the end of the range (a GST_TYPE_FRACTION GValue)
1825 * Sets @value to the range specified by @start and @end.
1828 gst_value_set_fraction_range (GValue * value, const GValue * start,
1833 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
1834 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start));
1835 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end));
1836 g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int,
1837 start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0);
1839 vals = (GValue *) value->data[0].v_pointer;
1841 gst_value_init_fraction_range (value);
1842 vals = value->data[0].v_pointer;
1844 g_value_copy (start, &vals[0]);
1845 g_value_copy (end, &vals[1]);
1849 * gst_value_set_fraction_range_full:
1850 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1851 * @numerator_start: the numerator start of the range
1852 * @denominator_start: the denominator start of the range
1853 * @numerator_end: the numerator end of the range
1854 * @denominator_end: the denominator end of the range
1856 * Sets @value to the range specified by @numerator_start/@denominator_start
1857 * and @numerator_end/@denominator_end.
1860 gst_value_set_fraction_range_full (GValue * value,
1861 gint numerator_start, gint denominator_start,
1862 gint numerator_end, gint denominator_end)
1864 GValue start = { 0 };
1867 g_return_if_fail (value != NULL);
1868 g_return_if_fail (denominator_start != 0);
1869 g_return_if_fail (denominator_end != 0);
1870 g_return_if_fail (gst_util_fraction_compare (numerator_start,
1871 denominator_start, numerator_end, denominator_end) < 0);
1873 g_value_init (&start, GST_TYPE_FRACTION);
1874 g_value_init (&end, GST_TYPE_FRACTION);
1876 gst_value_set_fraction (&start, numerator_start, denominator_start);
1877 gst_value_set_fraction (&end, numerator_end, denominator_end);
1878 gst_value_set_fraction_range (value, &start, &end);
1880 /* we know the two values contain fractions without internal allocs */
1881 /* g_value_unset (&start); */
1882 /* g_value_unset (&end); */
1885 /* FIXME 2.0: Don't leak the internal representation of fraction
1886 * ranges but instead return the numerator and denominator
1888 * This would allow to store fraction ranges as
1889 * data[0] = (min_n << 32) | (min_d)
1890 * data[1] = (max_n << 32) | (max_d)
1891 * without requiring an additional allocation for each value.
1895 * gst_value_get_fraction_range_min:
1896 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1898 * Gets the minimum of the range specified by @value.
1900 * Returns: the minimum of the range
1903 gst_value_get_fraction_range_min (const GValue * value)
1907 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1909 vals = (GValue *) value->data[0].v_pointer;
1918 * gst_value_get_fraction_range_max:
1919 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1921 * Gets the maximum of the range specified by @value.
1923 * Returns: the maximum of the range
1926 gst_value_get_fraction_range_max (const GValue * value)
1930 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1932 vals = (GValue *) value->data[0].v_pointer;
1941 gst_value_serialize_fraction_range (const GValue * value)
1943 GValue *vals = (GValue *) value->data[0].v_pointer;
1947 retval = g_strdup ("[ 0/1, 0/1 ]");
1951 start = gst_value_serialize_fraction (&vals[0]);
1952 end = gst_value_serialize_fraction (&vals[1]);
1954 retval = g_strdup_printf ("[ %s, %s ]", start, end);
1963 gst_value_transform_fraction_range_string (const GValue * src_value,
1964 GValue * dest_value)
1966 dest_value->data[0].v_pointer =
1967 gst_value_serialize_fraction_range (src_value);
1971 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
1973 GValue *vals1, *vals2;
1974 GstValueCompareFunc compare;
1976 if (value2->data[0].v_pointer == value1->data[0].v_pointer)
1977 return GST_VALUE_EQUAL; /* Only possible if both are NULL */
1979 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL)
1980 return GST_VALUE_UNORDERED;
1982 vals1 = (GValue *) value1->data[0].v_pointer;
1983 vals2 = (GValue *) value2->data[0].v_pointer;
1984 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
1985 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
1987 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
1989 return GST_VALUE_EQUAL;
1991 return GST_VALUE_UNORDERED;
1995 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s)
1997 g_warning ("unimplemented");
2006 * gst_value_set_caps:
2007 * @value: a GValue initialized to GST_TYPE_CAPS
2008 * @caps: (transfer none): the caps to set the value to
2010 * Sets the contents of @value to @caps. A reference to the
2011 * provided @caps will be taken by the @value.
2014 gst_value_set_caps (GValue * value, const GstCaps * caps)
2016 g_return_if_fail (G_IS_VALUE (value));
2017 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
2018 g_return_if_fail (caps == NULL || GST_IS_CAPS (caps));
2020 g_value_set_boxed (value, caps);
2024 * gst_value_get_caps:
2025 * @value: a GValue initialized to GST_TYPE_CAPS
2027 * Gets the contents of @value. The reference count of the returned
2028 * #GstCaps will not be modified, therefore the caller must take one
2029 * before getting rid of the @value.
2031 * Returns: (transfer none): the contents of @value
2034 gst_value_get_caps (const GValue * value)
2036 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2037 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
2039 return (GstCaps *) g_value_get_boxed (value);
2043 gst_value_compare_caps (const GValue * value1, const GValue * value2)
2045 GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1));
2046 GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2));
2048 if (gst_caps_is_equal (caps1, caps2))
2049 return GST_VALUE_EQUAL;
2050 return GST_VALUE_UNORDERED;
2054 gst_value_serialize_caps (const GValue * value)
2056 GstCaps *caps = g_value_get_boxed (value);
2057 return priv_gst_string_take_and_wrap (gst_caps_to_string (caps));
2061 gst_value_deserialize_caps (GValue * dest, const gchar * s)
2066 caps = gst_caps_from_string (s);
2068 gchar *str = gst_string_unwrap (s);
2070 if (G_UNLIKELY (!str))
2073 caps = gst_caps_from_string (str);
2078 g_value_take_boxed (dest, caps);
2084 /********************************************
2085 * Serialization/deserialization of GValues *
2086 ********************************************/
2088 static GstValueAbbreviation *
2089 _priv_gst_value_get_abbrs (gint * n_abbrs)
2091 static GstValueAbbreviation *abbrs = NULL;
2092 static volatile gsize num = 0;
2094 if (g_once_init_enter (&num)) {
2095 /* dynamically generate the array */
2097 GstValueAbbreviation dyn_abbrs[] = {
2102 {"uint", G_TYPE_UINT}
2106 {"float", G_TYPE_FLOAT}
2110 {"double", G_TYPE_DOUBLE}
2112 {"d", G_TYPE_DOUBLE}
2114 {"buffer", GST_TYPE_BUFFER}
2116 {"fraction", GST_TYPE_FRACTION}
2118 {"boolean", G_TYPE_BOOLEAN}
2120 {"bool", G_TYPE_BOOLEAN}
2122 {"b", G_TYPE_BOOLEAN}
2124 {"string", G_TYPE_STRING}
2126 {"str", G_TYPE_STRING}
2128 {"s", G_TYPE_STRING}
2130 {"structure", GST_TYPE_STRUCTURE}
2132 {"date", G_TYPE_DATE}
2134 {"datetime", GST_TYPE_DATE_TIME}
2136 {"bitmask", GST_TYPE_BITMASK}
2138 {"flagset", GST_TYPE_FLAG_SET}
2140 {"sample", GST_TYPE_SAMPLE}
2142 {"taglist", GST_TYPE_TAG_LIST}
2144 {"type", G_TYPE_GTYPE}
2146 {"array", GST_TYPE_ARRAY}
2148 {"list", GST_TYPE_LIST}
2150 _num = G_N_ELEMENTS (dyn_abbrs);
2151 /* permanently allocate and copy the array now */
2152 abbrs = g_new0 (GstValueAbbreviation, _num);
2153 memcpy (abbrs, dyn_abbrs, sizeof (GstValueAbbreviation) * _num);
2154 g_once_init_leave (&num, _num);
2161 /* given a type_name that could be a type abbreviation or a registered GType,
2162 * return a matching GType */
2164 _priv_gst_value_gtype_from_abbr (const char *type_name)
2167 GstValueAbbreviation *abbrs;
2171 g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2173 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2175 for (i = 0; i < n_abbrs; i++) {
2176 if (strcmp (type_name, abbrs[i].type_name) == 0) {
2177 return abbrs[i].type;
2181 /* this is the fallback */
2182 ret = g_type_from_name (type_name);
2183 /* If not found, try it as a dynamic type */
2184 if (G_UNLIKELY (ret == 0))
2185 ret = gst_dynamic_type_factory_load (type_name);
2191 _priv_gst_value_gtype_to_abbr (GType type)
2194 GstValueAbbreviation *abbrs;
2197 g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
2199 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2201 for (i = 0; i < n_abbrs; i++) {
2202 if (type == abbrs[i].type) {
2203 return abbrs[i].type_name;
2207 return g_type_name (type);
2211 * _priv_gst_value_parse_string:
2212 * @s: string to parse
2213 * @end: out-pointer to char behind end of string
2214 * @next: out-pointer to start of unread data
2215 * @unescape: @TRUE if the substring is escaped.
2217 * Find the end of a sub-string. If end == next, the string will not be
2218 * null-terminated. In all other cases it will be.
2220 * Note: This function modifies the string in @s (if unescape == @TRUE).
2222 * Returns: @TRUE if a sub-string was found and @FALSE if the string is not
2226 _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next,
2235 int ret = _priv_gst_value_parse_simple_string (s, end);
2241 /* Find the closing quotes */
2246 if (G_UNLIKELY (*s == 0))
2248 if (G_UNLIKELY (*s == '\\')) {
2250 if (G_UNLIKELY (*s == 0))
2261 if (G_UNLIKELY (*s == 0))
2263 if (G_UNLIKELY (*s == '\\')) {
2265 if (G_UNLIKELY (*s == 0))
2281 _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
2284 GValue value1 = { 0 };
2285 GValue value2 = { 0 };
2286 GValue value3 = { 0 };
2288 gboolean ret, have_step = FALSE;
2294 ret = _priv_gst_value_parse_value (s, &s, &value1, type);
2298 while (g_ascii_isspace (*s))
2305 while (g_ascii_isspace (*s))
2308 ret = _priv_gst_value_parse_value (s, &s, &value2, type);
2312 while (g_ascii_isspace (*s))
2315 /* optional step for int and int64 */
2316 if (G_VALUE_TYPE (&value1) == G_TYPE_INT
2317 || G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2321 while (g_ascii_isspace (*s))
2324 ret = _priv_gst_value_parse_value (s, &s, &value3, type);
2328 while (g_ascii_isspace (*s))
2339 if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
2341 if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
2344 if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
2345 range_type = GST_TYPE_DOUBLE_RANGE;
2346 g_value_init (value, range_type);
2347 gst_value_set_double_range (value,
2348 gst_g_value_get_double_unchecked (&value1),
2349 gst_g_value_get_double_unchecked (&value2));
2350 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
2351 range_type = GST_TYPE_INT_RANGE;
2352 g_value_init (value, range_type);
2354 gst_value_set_int_range_step (value,
2355 gst_g_value_get_int_unchecked (&value1),
2356 gst_g_value_get_int_unchecked (&value2),
2357 gst_g_value_get_int_unchecked (&value3));
2359 gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
2360 gst_g_value_get_int_unchecked (&value2));
2361 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2362 range_type = GST_TYPE_INT64_RANGE;
2363 g_value_init (value, range_type);
2365 gst_value_set_int64_range_step (value,
2366 gst_g_value_get_int64_unchecked (&value1),
2367 gst_g_value_get_int64_unchecked (&value2),
2368 gst_g_value_get_int64_unchecked (&value3));
2370 gst_value_set_int64_range (value,
2371 gst_g_value_get_int64_unchecked (&value1),
2372 gst_g_value_get_int64_unchecked (&value2));
2373 } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
2374 range_type = GST_TYPE_FRACTION_RANGE;
2375 g_value_init (value, range_type);
2376 gst_value_set_fraction_range (value, &value1, &value2);
2386 _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
2387 GType type, char begin, char end)
2389 GValue list_value = { 0 };
2393 array = g_value_peek_pointer (value);
2399 while (g_ascii_isspace (*s))
2407 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2411 g_array_append_val (array, list_value);
2413 while (g_ascii_isspace (*s))
2421 while (g_ascii_isspace (*s))
2424 memset (&list_value, 0, sizeof (list_value));
2425 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2429 g_array_append_val (array, list_value);
2430 while (g_ascii_isspace (*s))
2441 _priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value,
2444 return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}');
2448 _priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value,
2451 return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>');
2455 _priv_gst_value_parse_simple_string (gchar * str, gchar ** end)
2459 while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
2469 _priv_gst_value_parse_value (gchar * str,
2470 gchar ** after, GValue * value, GType default_type)
2479 GType type = default_type;
2482 while (g_ascii_isspace (*s))
2485 /* check if there's a (type_name) 'cast' */
2489 while (g_ascii_isspace (*s))
2492 if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &type_end)))
2495 while (g_ascii_isspace (*s))
2497 if (G_UNLIKELY (*s != ')'))
2500 while (g_ascii_isspace (*s))
2505 type = _priv_gst_value_gtype_from_abbr (type_name);
2506 GST_DEBUG ("trying type name '%s'", type_name);
2509 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2510 GST_WARNING ("invalid type");
2515 while (g_ascii_isspace (*s))
2518 ret = _priv_gst_value_parse_range (s, &s, value, type);
2519 } else if (*s == '{') {
2520 g_value_init (value, GST_TYPE_LIST);
2521 ret = _priv_gst_value_parse_list (s, &s, value, type);
2522 } else if (*s == '<') {
2523 g_value_init (value, GST_TYPE_ARRAY);
2524 ret = _priv_gst_value_parse_array (s, &s, value, type);
2528 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2530 { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
2531 G_TYPE_BOOLEAN, G_TYPE_STRING
2535 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE)))
2537 /* Set NULL terminator for deserialization */
2541 for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
2542 g_value_init (value, try_types[i]);
2543 ret = gst_value_deserialize (value, value_s);
2546 g_value_unset (value);
2549 g_value_init (value, type);
2551 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s,
2552 (type != G_TYPE_STRING))))
2554 /* Set NULL terminator for deserialization */
2558 ret = gst_value_deserialize (value, value_s);
2559 if (G_UNLIKELY (!ret))
2560 g_value_unset (value);
2575 gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
2577 GstSegment *seg = g_value_get_boxed (value);
2581 s = gst_structure_new ("GstSegment",
2582 "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
2583 "rate", G_TYPE_DOUBLE, seg->rate,
2584 "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
2585 "format", GST_TYPE_FORMAT, seg->format,
2586 "base", G_TYPE_UINT64, seg->base,
2587 "offset", G_TYPE_UINT64, seg->offset,
2588 "start", G_TYPE_UINT64, seg->start,
2589 "stop", G_TYPE_UINT64, seg->stop,
2590 "time", G_TYPE_UINT64, seg->time,
2591 "position", G_TYPE_UINT64, seg->position,
2592 "duration", G_TYPE_UINT64, seg->duration, NULL);
2593 t = gst_structure_to_string (s);
2595 res = g_strdup_printf ("\"%s\"", t);
2600 gst_structure_free (s);
2606 gst_value_serialize_segment (const GValue * value)
2608 return gst_value_serialize_segment_internal (value, TRUE);
2612 gst_value_deserialize_segment (GValue * dest, const gchar * s)
2618 str = gst_structure_from_string (s, NULL);
2622 res = gst_structure_get (str,
2623 "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags,
2624 "rate", G_TYPE_DOUBLE, &seg.rate,
2625 "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
2626 "format", GST_TYPE_FORMAT, &seg.format,
2627 "base", G_TYPE_UINT64, &seg.base,
2628 "offset", G_TYPE_UINT64, &seg.offset,
2629 "start", G_TYPE_UINT64, &seg.start,
2630 "stop", G_TYPE_UINT64, &seg.stop,
2631 "time", G_TYPE_UINT64, &seg.time,
2632 "position", G_TYPE_UINT64, &seg.position,
2633 "duration", G_TYPE_UINT64, &seg.duration, NULL);
2634 gst_structure_free (str);
2637 g_value_set_boxed (dest, &seg);
2647 * gst_value_set_structure:
2648 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2649 * @structure: the structure to set the value to
2651 * Sets the contents of @value to @structure.
2654 gst_value_set_structure (GValue * value, const GstStructure * structure)
2656 g_return_if_fail (G_IS_VALUE (value));
2657 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE);
2658 g_return_if_fail (structure == NULL || GST_IS_STRUCTURE (structure));
2660 g_value_set_boxed (value, structure);
2664 * gst_value_get_structure:
2665 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2667 * Gets the contents of @value.
2669 * Returns: (transfer none): the contents of @value
2671 const GstStructure *
2672 gst_value_get_structure (const GValue * value)
2674 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2675 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL);
2677 return (GstStructure *) g_value_get_boxed (value);
2681 gst_value_serialize_structure (const GValue * value)
2683 GstStructure *structure = g_value_get_boxed (value);
2685 return priv_gst_string_take_and_wrap (gst_structure_to_string (structure));
2689 gst_value_deserialize_structure (GValue * dest, const gchar * s)
2691 GstStructure *structure;
2694 structure = gst_structure_from_string (s, NULL);
2696 gchar *str = gst_string_unwrap (s);
2698 if (G_UNLIKELY (!str))
2701 structure = gst_structure_from_string (str, NULL);
2705 if (G_LIKELY (structure)) {
2706 g_value_take_boxed (dest, structure);
2713 gst_value_compare_structure (const GValue * value1, const GValue * value2)
2715 GstStructure *structure1 = GST_STRUCTURE (g_value_get_boxed (value1));
2716 GstStructure *structure2 = GST_STRUCTURE (g_value_get_boxed (value2));
2718 if (gst_structure_is_equal (structure1, structure2))
2719 return GST_VALUE_EQUAL;
2721 return GST_VALUE_UNORDERED;
2724 /*******************
2726 *******************/
2729 * gst_value_set_caps_features:
2730 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2731 * @features: the features to set the value to
2733 * Sets the contents of @value to @features.
2736 gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features)
2738 g_return_if_fail (G_IS_VALUE (value));
2739 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES);
2740 g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features));
2742 g_value_set_boxed (value, features);
2746 * gst_value_get_caps_features:
2747 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2749 * Gets the contents of @value.
2751 * Returns: (transfer none): the contents of @value
2753 const GstCapsFeatures *
2754 gst_value_get_caps_features (const GValue * value)
2756 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2757 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL);
2759 return (GstCapsFeatures *) g_value_get_boxed (value);
2763 gst_value_serialize_caps_features (const GValue * value)
2765 GstCapsFeatures *features = g_value_get_boxed (value);
2767 return priv_gst_string_take_and_wrap (gst_caps_features_to_string (features));
2771 gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
2773 GstCapsFeatures *features;
2776 features = gst_caps_features_from_string (s);
2778 gchar *str = gst_string_unwrap (s);
2780 if (G_UNLIKELY (!str))
2783 features = gst_caps_features_from_string (str);
2787 if (G_LIKELY (features)) {
2788 g_value_take_boxed (dest, features);
2798 gst_value_compare_tag_list (const GValue * value1, const GValue * value2)
2800 GstTagList *taglist1 = GST_TAG_LIST (g_value_get_boxed (value1));
2801 GstTagList *taglist2 = GST_TAG_LIST (g_value_get_boxed (value2));
2803 if (gst_tag_list_is_equal (taglist1, taglist2))
2804 return GST_VALUE_EQUAL;
2805 return GST_VALUE_UNORDERED;
2809 gst_value_deserialize_tag_list (GValue * dest, const gchar * s)
2811 GstTagList *taglist;
2814 taglist = gst_tag_list_new_from_string (s);
2816 gchar *str = gst_string_unwrap (s);
2818 if (G_UNLIKELY (!str))
2821 taglist = gst_tag_list_new_from_string (str);
2825 if (G_LIKELY (taglist != NULL)) {
2826 g_value_take_boxed (dest, taglist);
2833 gst_value_serialize_tag_list (const GValue * value)
2835 GstTagList *taglist = g_value_get_boxed (value);
2837 return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist));
2846 compare_buffer (GstBuffer * buf1, GstBuffer * buf2)
2849 GstMapInfo info1, info2;
2853 return GST_VALUE_EQUAL;
2855 size1 = gst_buffer_get_size (buf1);
2856 size2 = gst_buffer_get_size (buf2);
2859 return GST_VALUE_UNORDERED;
2862 return GST_VALUE_EQUAL;
2864 if (!gst_buffer_map (buf1, &info1, GST_MAP_READ))
2865 return GST_VALUE_UNORDERED;
2867 if (!gst_buffer_map (buf2, &info2, GST_MAP_READ)) {
2868 gst_buffer_unmap (buf1, &info1);
2869 return GST_VALUE_UNORDERED;
2872 mret = memcmp (info1.data, info2.data, info1.size);
2874 result = GST_VALUE_EQUAL;
2876 result = GST_VALUE_LESS_THAN;
2878 result = GST_VALUE_GREATER_THAN;
2880 gst_buffer_unmap (buf1, &info1);
2881 gst_buffer_unmap (buf2, &info2);
2887 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
2889 GstBuffer *buf1 = gst_value_get_buffer (value1);
2890 GstBuffer *buf2 = gst_value_get_buffer (value2);
2892 return compare_buffer (buf1, buf2);
2896 gst_value_serialize_buffer (const GValue * value)
2904 buffer = gst_value_get_buffer (value);
2908 if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
2913 string = g_malloc (info.size * 2 + 1);
2914 for (i = 0; i < info.size; i++) {
2915 sprintf (string + i * 2, "%02x", data[i]);
2917 string[info.size * 2] = 0;
2919 gst_buffer_unmap (buffer, &info);
2925 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
2938 buffer = gst_buffer_new_allocate (NULL, len / 2, NULL);
2939 if (!gst_buffer_map (buffer, &info, GST_MAP_WRITE))
2943 for (i = 0; i < len / 2; i++) {
2944 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
2947 ts[0] = s[i * 2 + 0];
2948 ts[1] = s[i * 2 + 1];
2951 data[i] = (guint8) strtoul (ts, NULL, 16);
2953 gst_buffer_unmap (buffer, &info);
2955 gst_value_take_buffer (dest, buffer);
2970 gst_buffer_unref (buffer);
2971 gst_buffer_unmap (buffer, &info);
2980 /* This function is mostly used for comparing image/buffer tags in taglists */
2982 gst_value_compare_sample (const GValue * value1, const GValue * value2)
2984 GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1));
2985 GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2));
2987 /* FIXME: should we take into account anything else such as caps? */
2988 return compare_buffer (buf1, buf2);
2992 gst_value_serialize_sample (const GValue * value)
2994 const GstStructure *info_structure;
2995 GstSegment *segment;
2999 GValue val = { 0, };
3000 gchar *info_str, *caps_str, *tmp;
3001 gchar *buf_str, *seg_str, *s;
3003 sample = g_value_get_boxed (value);
3005 buffer = gst_sample_get_buffer (sample);
3007 g_value_init (&val, GST_TYPE_BUFFER);
3008 g_value_set_boxed (&val, buffer);
3009 buf_str = gst_value_serialize_buffer (&val);
3010 g_value_unset (&val);
3012 buf_str = g_strdup ("None");
3015 caps = gst_sample_get_caps (sample);
3017 tmp = gst_caps_to_string (caps);
3018 caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3019 g_strdelimit (caps_str, "=", '_');
3022 caps_str = g_strdup ("None");
3025 segment = gst_sample_get_segment (sample);
3027 g_value_init (&val, GST_TYPE_SEGMENT);
3028 g_value_set_boxed (&val, segment);
3029 tmp = gst_value_serialize_segment_internal (&val, FALSE);
3030 seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3031 g_strdelimit (seg_str, "=", '_');
3033 g_value_unset (&val);
3035 seg_str = g_strdup ("None");
3038 info_structure = gst_sample_get_info (sample);
3039 if (info_structure) {
3040 tmp = gst_structure_to_string (info_structure);
3041 info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3042 g_strdelimit (info_str, "=", '_');
3045 info_str = g_strdup ("None");
3048 s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL);
3058 gst_value_deserialize_sample (GValue * dest, const gchar * s)
3060 GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT;
3063 GstCaps *caps = NULL;
3064 gboolean ret = FALSE;
3069 GST_TRACE ("deserialize '%s'", s);
3071 fields = g_strsplit (s, ":", -1);
3072 len = g_strv_length (fields);
3076 g_value_init (&bval, GST_TYPE_BUFFER);
3077 g_value_init (&sval, GST_TYPE_SEGMENT);
3079 if (!gst_value_deserialize_buffer (&bval, fields[0]))
3082 if (strcmp (fields[1], "None") != 0) {
3083 g_strdelimit (fields[1], "_", '=');
3084 g_base64_decode_inplace (fields[1], &outlen);
3085 GST_TRACE ("caps : %s", fields[1]);
3086 caps = gst_caps_from_string (fields[1]);
3091 if (strcmp (fields[2], "None") != 0) {
3092 g_strdelimit (fields[2], "_", '=');
3093 g_base64_decode_inplace (fields[2], &outlen);
3094 GST_TRACE ("segment : %s", fields[2]);
3095 if (!gst_value_deserialize_segment (&sval, fields[2]))
3099 if (strcmp (fields[3], "None") != 0) {
3100 g_strdelimit (fields[3], "_", '=');
3101 g_base64_decode_inplace (fields[3], &outlen);
3102 GST_TRACE ("info : %s", fields[3]);
3103 info = gst_structure_from_string (fields[3], NULL);
3110 sample = gst_sample_new (gst_value_get_buffer (&bval), caps,
3111 g_value_get_boxed (&sval), info);
3113 g_value_take_boxed (dest, sample);
3119 gst_caps_unref (caps);
3120 g_value_unset (&bval);
3121 g_value_unset (&sval);
3125 g_strfreev (fields);
3135 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
3137 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
3138 return GST_VALUE_EQUAL;
3139 return GST_VALUE_UNORDERED;
3143 gst_value_serialize_boolean (const GValue * value)
3145 if (value->data[0].v_int) {
3146 return g_strdup ("true");
3148 return g_strdup ("false");
3152 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
3154 gboolean ret = FALSE;
3156 if (g_ascii_strcasecmp (s, "true") == 0 ||
3157 g_ascii_strcasecmp (s, "yes") == 0 ||
3158 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
3159 g_value_set_boolean (dest, TRUE);
3161 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
3162 g_ascii_strcasecmp (s, "no") == 0 ||
3163 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
3164 g_value_set_boolean (dest, FALSE);
3171 #define CREATE_SERIALIZATION_START(_type,_macro) \
3173 gst_value_compare_ ## _type \
3174 (const GValue * value1, const GValue * value2) \
3176 g ## _type val1 = g_value_get_ ## _type (value1); \
3177 g ## _type val2 = g_value_get_ ## _type (value2); \
3179 return GST_VALUE_GREATER_THAN; \
3181 return GST_VALUE_LESS_THAN; \
3182 return GST_VALUE_EQUAL; \
3186 gst_value_serialize_ ## _type (const GValue * value) \
3188 GValue val = { 0, }; \
3189 g_value_init (&val, G_TYPE_STRING); \
3190 if (!g_value_transform (value, &val)) \
3191 g_assert_not_reached (); \
3192 /* NO_COPY_MADNESS!!! */ \
3193 return (char *) g_value_get_string (&val); \
3196 /* deserialize the given s into to as a gint64.
3197 * check if the result is actually storeable in the given size number of
3201 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
3202 gint64 min, gint64 max, gint size)
3204 gboolean ret = FALSE;
3209 *to = g_ascii_strtoull (s, &end, 0);
3210 /* a range error is a definitive no-no */
3211 if (errno == ERANGE) {
3218 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
3219 *to = G_LITTLE_ENDIAN;
3221 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
3224 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
3227 } else if (g_ascii_strcasecmp (s, "min") == 0) {
3230 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3236 /* by definition, a gint64 fits into a gint64; so ignore those */
3237 if (size != sizeof (mask)) {
3239 /* for positive numbers, we create a mask of 1's outside of the range
3240 * and 0's inside the range. An and will thus keep only 1 bits
3241 * outside of the range */
3242 mask <<= (size * 8);
3243 if ((mask & *to) != 0) {
3247 /* for negative numbers, we do a 2's complement version */
3248 mask <<= ((size * 8) - 1);
3249 if ((mask & *to) != mask) {
3258 #define CREATE_SERIALIZATION(_type,_macro) \
3259 CREATE_SERIALIZATION_START(_type,_macro) \
3262 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3266 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
3267 G_MAX ## _macro, sizeof (g ## _type))) { \
3268 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
3275 #define CREATE_USERIALIZATION(_type,_macro) \
3276 CREATE_SERIALIZATION_START(_type,_macro) \
3279 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3283 gboolean ret = FALSE; \
3286 x = g_ascii_strtoull (s, &end, 0); \
3287 /* a range error is a definitive no-no */ \
3288 if (errno == ERANGE) { \
3291 /* the cast ensures the range check later on makes sense */ \
3292 x = (g ## _type) x; \
3296 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
3297 x = G_LITTLE_ENDIAN; \
3299 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
3302 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
3305 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
3308 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
3309 x = G_MAX ## _macro; \
3314 if (x > G_MAX ## _macro) { \
3317 g_value_set_ ## _type (dest, x); \
3323 CREATE_SERIALIZATION (int, INT);
3324 CREATE_SERIALIZATION (int64, INT64);
3325 CREATE_SERIALIZATION (long, LONG);
3327 CREATE_USERIALIZATION (uint, UINT);
3328 CREATE_USERIALIZATION (uint64, UINT64);
3329 CREATE_USERIALIZATION (ulong, ULONG);
3331 /* FIXME 2.0: remove this again, plugins shouldn't have uchar properties */
3333 #define G_MAXUCHAR 255
3335 CREATE_USERIALIZATION (uchar, UCHAR);
3341 gst_value_compare_double (const GValue * value1, const GValue * value2)
3343 if (value1->data[0].v_double > value2->data[0].v_double)
3344 return GST_VALUE_GREATER_THAN;
3345 if (value1->data[0].v_double < value2->data[0].v_double)
3346 return GST_VALUE_LESS_THAN;
3347 if (value1->data[0].v_double == value2->data[0].v_double)
3348 return GST_VALUE_EQUAL;
3349 return GST_VALUE_UNORDERED;
3353 gst_value_serialize_double (const GValue * value)
3355 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3357 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
3358 return g_strdup (d);
3362 gst_value_deserialize_double (GValue * dest, const gchar * s)
3365 gboolean ret = FALSE;
3368 x = g_ascii_strtod (s, &end);
3372 if (g_ascii_strcasecmp (s, "min") == 0) {
3375 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3381 g_value_set_double (dest, x);
3391 gst_value_compare_float (const GValue * value1, const GValue * value2)
3393 if (value1->data[0].v_float > value2->data[0].v_float)
3394 return GST_VALUE_GREATER_THAN;
3395 if (value1->data[0].v_float < value2->data[0].v_float)
3396 return GST_VALUE_LESS_THAN;
3397 if (value1->data[0].v_float == value2->data[0].v_float)
3398 return GST_VALUE_EQUAL;
3399 return GST_VALUE_UNORDERED;
3403 gst_value_serialize_float (const GValue * value)
3405 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3407 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
3408 return g_strdup (d);
3412 gst_value_deserialize_float (GValue * dest, const gchar * s)
3415 gboolean ret = FALSE;
3418 x = g_ascii_strtod (s, &end);
3422 if (g_ascii_strcasecmp (s, "min") == 0) {
3425 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3430 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
3433 g_value_set_float (dest, (float) x);
3443 gst_value_compare_string (const GValue * value1, const GValue * value2)
3445 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
3446 /* if only one is NULL, no match - otherwise both NULL == EQUAL */
3447 if (value1->data[0].v_pointer != value2->data[0].v_pointer)
3448 return GST_VALUE_UNORDERED;
3450 gint x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
3453 return GST_VALUE_LESS_THAN;
3455 return GST_VALUE_GREATER_THAN;
3458 return GST_VALUE_EQUAL;
3462 gst_string_measure_wrapping (const gchar * s)
3465 gboolean wrap = FALSE;
3467 if (G_UNLIKELY (s == NULL))
3470 /* Special case: the actual string NULL needs wrapping */
3471 if (G_UNLIKELY (strcmp (s, "NULL") == 0))
3476 if (GST_ASCII_IS_STRING (*s)) {
3478 } else if (*s < 0x20 || *s >= 0x7f) {
3488 /* Wrap the string if we found something that needs
3489 * wrapping, or the empty string (len == 0) */
3490 return (wrap || len == 0) ? len : -1;
3494 gst_string_wrap_inner (const gchar * s, gint len)
3498 e = d = g_malloc (len + 3);
3502 if (GST_ASCII_IS_STRING (*s)) {
3504 } else if (*s < 0x20 || *s >= 0x7f) {
3506 *e++ = '0' + ((*(guchar *) s) >> 6);
3507 *e++ = '0' + (((*s) >> 3) & 0x7);
3508 *e++ = '0' + ((*s++) & 0x7);
3517 g_assert (e - d <= len + 3);
3521 /* Do string wrapping/escaping */
3523 gst_string_wrap (const gchar * s)
3525 gint len = gst_string_measure_wrapping (s);
3527 if (G_LIKELY (len < 0))
3528 return g_strdup (s);
3530 return gst_string_wrap_inner (s, len);
3533 /* Same as above, but take ownership of the string */
3535 priv_gst_string_take_and_wrap (gchar * s)
3538 gint len = gst_string_measure_wrapping (s);
3540 if (G_LIKELY (len < 0))
3543 out = gst_string_wrap_inner (s, len);
3550 * This function takes a string delimited with double quotes (")
3551 * and unescapes any \xxx octal numbers.
3553 * If sequences of \y are found where y is not in the range of
3554 * 0->3, y is copied unescaped.
3556 * If \xyy is found where x is an octal number but y is not, an
3557 * error is encountered and %NULL is returned.
3559 * the input string must be \0 terminated.
3562 gst_string_unwrap (const gchar * s)
3565 gchar *read, *write;
3567 /* NULL string returns NULL */
3571 /* strings not starting with " are invalid */
3575 /* make copy of original string to hold the result. This
3576 * string will always be smaller than the original */
3581 /* need to move to the next position as we parsed the " */
3585 if (GST_ASCII_IS_STRING (*read)) {
3586 /* normal chars are just copied */
3588 } else if (*read == '"') {
3589 /* quote marks end of string */
3591 } else if (*read == '\\') {
3592 /* got an escape char, move to next position to read a tripplet
3593 * of octal numbers */
3595 /* is the next char a possible first octal number? */
3596 if (*read >= '0' && *read <= '3') {
3597 /* parse other 2 numbers, if one of them is not in the range of
3598 * an octal number, we error. We also catch the case where a zero
3599 * byte is found here. */
3600 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
3603 /* now convert the octal number to a byte again. */
3604 *write++ = ((read[0] - '0') << 6) +
3605 ((read[1] - '0') << 3) + (read[2] - '0');
3609 /* if we run into a \0 here, we definitely won't get a quote later */
3613 /* else copy \X sequence */
3617 /* weird character, error */
3621 /* if the string is not ending in " and zero terminated, we error */
3622 if (*read != '"' || read[1] != '\0')
3625 /* null terminate result string and return */
3635 gst_value_serialize_string (const GValue * value)
3637 return gst_string_wrap (value->data[0].v_pointer);
3641 gst_value_deserialize_string (GValue * dest, const gchar * s)
3643 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
3644 g_value_set_string (dest, NULL);
3646 } else if (G_LIKELY (*s != '"' || s[strlen (s) - 1] != '"')) {
3647 if (!g_utf8_validate (s, -1, NULL))
3649 g_value_set_string (dest, s);
3652 /* strings delimited with double quotes should be unwrapped */
3653 gchar *str = gst_string_unwrap (s);
3654 if (G_UNLIKELY (!str))
3656 g_value_take_string (dest, str);
3667 gst_value_compare_enum (const GValue * value1, const GValue * value2)
3669 GEnumValue *en1, *en2;
3670 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3671 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3673 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3674 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3675 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
3676 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
3677 g_type_class_unref (klass1);
3678 g_type_class_unref (klass2);
3679 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
3680 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
3681 if (en1->value < en2->value)
3682 return GST_VALUE_LESS_THAN;
3683 if (en1->value > en2->value)
3684 return GST_VALUE_GREATER_THAN;
3686 return GST_VALUE_EQUAL;
3690 gst_value_serialize_enum (const GValue * value)
3693 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
3695 g_return_val_if_fail (klass, NULL);
3696 en = g_enum_get_value (klass, g_value_get_enum (value));
3697 g_type_class_unref (klass);
3699 /* might be one of the custom formats registered later */
3700 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) {
3701 const GstFormatDefinition *format_def;
3703 format_def = gst_format_get_details ((GstFormat) g_value_get_enum (value));
3704 g_return_val_if_fail (format_def != NULL, NULL);
3705 return g_strdup (format_def->description);
3708 g_return_val_if_fail (en, NULL);
3709 return g_strdup (en->value_name);
3713 gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value,
3716 const GstFormatDefinition *format_def =
3717 g_value_get_pointer (format_def_value);
3719 if (g_ascii_strcasecmp (s, format_def->nick) == 0)
3722 return g_ascii_strcasecmp (s, format_def->description);
3726 gst_value_deserialize_enum (GValue * dest, const gchar * s)
3729 gchar *endptr = NULL;
3730 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3732 g_return_val_if_fail (klass, FALSE);
3733 if (!(en = g_enum_get_value_by_name (klass, s))) {
3734 if (!(en = g_enum_get_value_by_nick (klass, s))) {
3735 gint i = strtol (s, &endptr, 0);
3737 if (endptr && *endptr == '\0') {
3738 en = g_enum_get_value (klass, i);
3742 g_type_class_unref (klass);
3744 /* might be one of the custom formats registered later */
3745 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
3746 GValue res = { 0, };
3747 const GstFormatDefinition *format_def;
3751 iter = gst_format_iterate_definitions ();
3753 found = gst_iterator_find_custom (iter,
3754 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
3757 format_def = g_value_get_pointer (&res);
3758 g_return_val_if_fail (format_def != NULL, FALSE);
3759 g_value_set_enum (dest, (gint) format_def->value);
3760 g_value_unset (&res);
3762 gst_iterator_free (iter);
3766 /* enum name/nick not found */
3770 g_value_set_enum (dest, en->value);
3778 /* we just compare the value here */
3780 gst_value_compare_gflags (const GValue * value1, const GValue * value2)
3783 GFlagsClass *klass1 =
3784 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3785 GFlagsClass *klass2 =
3786 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3788 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3789 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3790 fl1 = g_value_get_flags (value1);
3791 fl2 = g_value_get_flags (value2);
3792 g_type_class_unref (klass1);
3793 g_type_class_unref (klass2);
3795 return GST_VALUE_LESS_THAN;
3797 return GST_VALUE_GREATER_THAN;
3799 return GST_VALUE_EQUAL;
3802 /* the different flags are serialized separated with a + */
3804 gst_value_serialize_gflags (const GValue * value)
3808 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
3809 gchar *result, *tmp;
3810 gboolean first = TRUE;
3812 g_return_val_if_fail (klass, NULL);
3814 flags = g_value_get_flags (value);
3816 /* if no flags are set, try to serialize to the _NONE string */
3818 fl = g_flags_get_first_value (klass, flags);
3820 return g_strdup (fl->value_name);
3822 return g_strdup ("0");
3825 /* some flags are set, so serialize one by one */
3826 result = g_strdup ("");
3828 fl = g_flags_get_first_value (klass, flags);
3830 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
3836 flags &= ~fl->value;
3839 g_type_class_unref (klass);
3845 gst_value_gflags_str_to_flags (GFlagsClass * klass, const gchar * s,
3846 guint * out_flags, guint * out_mask)
3850 const gchar *pos = NULL;
3852 gchar *cur_str, *endptr;
3857 g_return_val_if_fail (klass, FALSE);
3859 /* split into parts delimited with + or / and
3860 * compose the set of flags and mask. */
3864 goto done; /* Empty string, nothing to do */
3866 /* As a special case if the first char isn't a delimiter, assume
3867 * it's a '+' - for GFlags strings, which don't start with a
3868 * delimiter, while GFlagSet always will */
3869 if (*pos == '/' || *pos == '+') {
3877 /* Find the next delimiter */
3879 while (*next != '\0' && *next != '+' && *next != '/')
3881 cur_str = g_strndup (pos, next - pos);
3883 if ((fl = g_flags_get_value_by_name (klass, cur_str)))
3885 else if ((fl = g_flags_get_value_by_nick (klass, cur_str)))
3888 val = strtoul (cur_str, &endptr, 0);
3889 /* direct numeric value */
3890 if (endptr == NULL || *endptr != '\0') {
3892 return FALSE; /* Invalid numeric or string we can't convert */
3899 if (delimiter == '+')
3903 /* Advance to the next delimiter */
3907 } while (delimiter != '\0');
3920 gst_value_deserialize_gflags (GValue * dest, const gchar * s)
3922 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3923 gboolean res = FALSE;
3926 if (gst_value_gflags_str_to_flags (klass, s, &flags, NULL)) {
3927 g_value_set_flags (dest, flags);
3931 g_type_class_unref (klass);
3941 gst_value_compare_gtype (const GValue * value1, const GValue * value2)
3943 if (value1->data[0].v_pointer == value2->data[0].v_pointer)
3944 return GST_VALUE_EQUAL;
3945 return GST_VALUE_UNORDERED;
3949 gst_value_serialize_gtype (const GValue * value)
3951 return g_strdup (g_type_name (g_value_get_gtype (value)));
3955 gst_value_deserialize_gtype (GValue * dest, const gchar * s)
3957 GType t = g_type_from_name (s);
3958 gboolean ret = TRUE;
3960 if (t == G_TYPE_INVALID)
3963 g_value_set_gtype (dest, t);
3973 gst_value_is_subset_int_range_int_range (const GValue * value1,
3974 const GValue * value2)
3978 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE);
3979 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE);
3981 if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) <
3982 INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2))
3984 if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) >
3985 INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2))
3988 if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) {
3989 if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) %
3990 INT_RANGE_STEP (value1))
3996 gst_util_greatest_common_divisor (INT_RANGE_STEP (value1),
3997 INT_RANGE_STEP (value2));
3998 if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2)))
4005 gst_value_is_subset_int64_range_int64_range (const GValue * value1,
4006 const GValue * value2)
4010 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE);
4011 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE);
4013 if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2))
4015 if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2))
4018 if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) {
4019 if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) %
4020 INT64_RANGE_STEP (value1))
4026 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1),
4027 INT64_RANGE_STEP (value2));
4028 if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2)))
4034 /* A flag set is a subset of another if the superset allows the
4035 * flags of the subset */
4037 gst_value_is_subset_flagset_flagset (const GValue * value1,
4038 const GValue * value2)
4043 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value1), FALSE);
4044 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value2), FALSE);
4046 f1 = value1->data[0].v_uint;
4047 f2 = value2->data[0].v_uint;
4049 m1 = value1->data[1].v_uint;
4050 m2 = value2->data[1].v_uint;
4052 /* Not a subset if masked bits of superset disagree */
4053 if ((f1 & m1) != (f2 & (m1 & m2)))
4060 gst_value_is_subset_structure_structure (const GValue * value1,
4061 const GValue * value2)
4063 const GstStructure *s1, *s2;
4065 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value1), FALSE);
4066 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value2), FALSE);
4068 s1 = gst_value_get_structure (value1);
4069 s2 = gst_value_get_structure (value2);
4071 return gst_structure_is_subset (s1, s2);
4075 * gst_value_is_subset:
4076 * @value1: a #GValue
4077 * @value2: a #GValue
4079 * Check that @value1 is a subset of @value2.
4081 * Return: %TRUE is @value1 is a subset of @value2
4084 gst_value_is_subset (const GValue * value1, const GValue * value2)
4086 /* special case for int/int64 ranges, since we cannot compute
4087 the difference for those when they have different steps,
4088 and it's actually a lot simpler to compute whether a range
4089 is a subset of another. */
4090 if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) {
4091 return gst_value_is_subset_int_range_int_range (value1, value2);
4092 } else if (GST_VALUE_HOLDS_INT64_RANGE (value1)
4093 && GST_VALUE_HOLDS_INT64_RANGE (value2)) {
4094 return gst_value_is_subset_int64_range_int64_range (value1, value2);
4095 } else if (GST_VALUE_HOLDS_FLAG_SET (value1) &&
4096 GST_VALUE_HOLDS_FLAG_SET (value2)) {
4097 return gst_value_is_subset_flagset_flagset (value1, value2);
4098 } else if (GST_VALUE_HOLDS_STRUCTURE (value1)
4099 && GST_VALUE_HOLDS_STRUCTURE (value2)) {
4100 return gst_value_is_subset_structure_structure (value1, value2);
4108 * -> 1 - [1,2] = empty
4112 * -> [1,2] - [1,3] = empty
4116 * -> {1,3} - {1,2} = 3
4119 * First caps subtraction needs to return a non-empty set, second
4120 * subtractions needs to give en empty set.
4121 * Both substractions are switched below, as it's faster that way.
4123 if (!gst_value_subtract (NULL, value1, value2)) {
4124 if (gst_value_subtract (NULL, value2, value1)) {
4136 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
4137 const GValue * src2)
4139 gint v = src1->data[0].v_int;
4141 /* check if it's already in the range */
4142 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v &&
4143 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v &&
4144 v % INT_RANGE_STEP (src2) == 0) {
4146 gst_value_init_and_copy (dest, src2);
4150 /* check if it extends the range */
4151 if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) {
4154 (guint) ((INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2));
4155 guint64 new_max = (guint) (INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
4157 gst_value_init_and_copy (dest, src2);
4158 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4162 if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) {
4164 guint64 new_min = (guint) (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
4166 (guint) ((INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2));
4168 gst_value_init_and_copy (dest, src2);
4169 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4178 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
4179 const GValue * src2)
4181 /* We can union in several special cases:
4182 1 - one is a subset of another
4183 2 - same step and not disjoint
4184 3 - different step, at least one with one value which matches a 'next' or 'previous'
4189 if (gst_value_is_subset_int_range_int_range (src1, src2)) {
4191 gst_value_init_and_copy (dest, src2);
4194 if (gst_value_is_subset_int_range_int_range (src2, src1)) {
4196 gst_value_init_and_copy (dest, src1);
4200 /* 2 - same step and not disjoint */
4201 if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) {
4202 if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 &&
4203 INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) ||
4204 (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 &&
4205 INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) {
4207 gint step = INT_RANGE_STEP (src1);
4208 gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2));
4209 gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2));
4210 g_value_init (dest, GST_TYPE_INT_RANGE);
4211 gst_value_set_int_range_step (dest, min, max, step);
4217 /* 3 - single value matches next or previous */
4218 if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) {
4219 gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1;
4220 gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1;
4221 if (n1 == 1 || n2 == 1) {
4222 const GValue *range_value = NULL;
4226 scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1);
4227 } else if (n2 == 1) {
4229 scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2);
4233 (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) {
4235 guint64 new_min = (guint)
4236 ((INT_RANGE_MIN (range_value) -
4237 1) * INT_RANGE_STEP (range_value));
4238 guint64 new_max = (guint)
4239 (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value));
4241 gst_value_init_and_copy (dest, range_value);
4242 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4245 } else if (scalar ==
4246 (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) {
4248 guint64 new_min = (guint)
4249 (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value));
4250 guint64 new_max = (guint)
4251 ((INT_RANGE_MAX (range_value) +
4252 1) * INT_RANGE_STEP (range_value));
4253 gst_value_init_and_copy (dest, range_value);
4254 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4261 /* If we get there, we did not find a way to make a union that can be
4262 represented with our simplistic model. */
4267 gst_value_union_flagset_flagset (GValue * dest, const GValue * src1,
4268 const GValue * src2)
4270 /* We can union 2 flag sets where they do not disagree on
4271 * required (masked) flag bits */
4275 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4276 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4278 f1 = src1->data[0].v_uint;
4279 f2 = src2->data[0].v_uint;
4281 m1 = src1->data[1].v_uint;
4282 m2 = src2->data[1].v_uint;
4284 /* Can't union if masked bits disagree */
4285 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4289 g_value_init (dest, GST_TYPE_FLAG_SET);
4290 /* Copy masked bits from src2 to src1 */
4294 gst_value_set_flagset (dest, f1, m1);
4300 /* iterating over the result taking the union with the other structure's value */
4302 structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
4304 GstStructure *other = user_data;
4305 const GValue *other_value;
4306 GValue res_value = G_VALUE_INIT;
4308 other_value = gst_structure_id_get_value (other, field_id);
4309 /* no value in the other struct, just keep this value */
4313 if (!gst_value_union (&res_value, val, other_value))
4316 g_value_unset (val);
4317 gst_value_init_and_copy (val, &res_value);
4321 /* iterating over the other source structure adding missing values */
4323 structure_field_union_from (GQuark field_id, const GValue * other_val,
4326 GstStructure *result = user_data;
4327 const GValue *result_value;
4329 result_value = gst_structure_id_get_value (result, field_id);
4331 gst_structure_id_set_value (result, field_id, other_val);
4337 gst_value_union_structure_structure (GValue * dest, const GValue * src1,
4338 const GValue * src2)
4340 const GstStructure *s1, *s2;
4341 GstStructure *result;
4344 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src1), FALSE);
4345 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src2), FALSE);
4347 s1 = gst_value_get_structure (src1);
4348 s2 = gst_value_get_structure (src2);
4350 /* Can't join two structures with different names into a single structure */
4351 if (!gst_structure_has_name (s1, gst_structure_get_name (s2))) {
4352 gst_value_list_concat (dest, src1, src2);
4356 result = gst_structure_copy (s1);
4358 gst_structure_map_in_place (result, structure_field_union_into,
4363 gst_structure_foreach (s2, structure_field_union_from, (gpointer) result);
4366 g_value_init (dest, GST_TYPE_STRUCTURE);
4367 gst_value_set_structure (dest, result);
4371 gst_structure_free (result);
4380 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
4381 const GValue * src2)
4383 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int &&
4384 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int &&
4385 src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) {
4387 gst_value_init_and_copy (dest, src1);
4395 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
4396 const GValue * src2)
4403 INT_RANGE_STEP (src1) /
4404 gst_util_greatest_common_divisor (INT_RANGE_STEP (src1),
4405 INT_RANGE_STEP (src2));
4406 if (G_MAXINT32 / INT_RANGE_STEP (src2) < step)
4408 step *= INT_RANGE_STEP (src2);
4411 MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1),
4412 INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
4413 min = (min + step - 1) / step * step;
4415 MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1),
4416 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
4417 max = max / step * step;
4421 g_value_init (dest, GST_TYPE_INT_RANGE);
4422 gst_value_set_int_range_step (dest, min, max, step);
4428 g_value_init (dest, G_TYPE_INT);
4429 g_value_set_int (dest, min);
4437 #define INT64_RANGE_MIN_VAL(v) (INT64_RANGE_MIN (v) * INT64_RANGE_STEP (v))
4438 #define INT64_RANGE_MAX_VAL(v) (INT64_RANGE_MAX (v) * INT64_RANGE_STEP (v))
4441 gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1,
4442 const GValue * src2)
4444 if (INT64_RANGE_MIN_VAL (src2) <= src1->data[0].v_int64 &&
4445 INT64_RANGE_MAX_VAL (src2) >= src1->data[0].v_int64 &&
4446 src1->data[0].v_int64 % INT64_RANGE_STEP (src2) == 0) {
4448 gst_value_init_and_copy (dest, src1);
4456 gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1,
4457 const GValue * src2)
4464 INT64_RANGE_STEP (src1) /
4465 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1),
4466 INT64_RANGE_STEP (src2));
4467 if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step)
4469 step *= INT64_RANGE_STEP (src2);
4472 MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1),
4473 INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2));
4474 min = (min + step - 1) / step * step;
4476 MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1),
4477 INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2));
4478 max = max / step * step;
4482 g_value_init (dest, GST_TYPE_INT64_RANGE);
4483 gst_value_set_int64_range_step (dest, min, max, step);
4489 g_value_init (dest, G_TYPE_INT64);
4490 g_value_set_int64 (dest, min);
4499 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
4500 const GValue * src2)
4502 if (src2->data[0].v_double <= src1->data[0].v_double &&
4503 src2->data[1].v_double >= src1->data[0].v_double) {
4505 gst_value_init_and_copy (dest, src1);
4513 gst_value_intersect_double_range_double_range (GValue * dest,
4514 const GValue * src1, const GValue * src2)
4519 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
4520 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
4524 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
4525 gst_value_set_double_range (dest, min, max);
4531 g_value_init (dest, G_TYPE_DOUBLE);
4532 g_value_set_int (dest, (int) min);
4541 gst_value_intersect_list (GValue * dest, const GValue * value1,
4542 const GValue * value2)
4545 GValue intersection = { 0, };
4546 gboolean ret = FALSE;
4548 size = VALUE_LIST_SIZE (value1);
4549 for (i = 0; i < size; i++) {
4550 const GValue *cur = VALUE_LIST_GET_VALUE (value1, i);
4552 /* quicker version when we don't need the resulting set */
4554 if (gst_value_intersect (NULL, cur, value2)) {
4561 if (gst_value_intersect (&intersection, cur, value2)) {
4564 gst_value_move (dest, &intersection);
4566 } else if (GST_VALUE_HOLDS_LIST (dest)) {
4567 _gst_value_list_append_and_take_value (dest, &intersection);
4571 gst_value_move (&temp, dest);
4572 gst_value_list_merge (dest, &temp, &intersection);
4573 g_value_unset (&temp);
4574 g_value_unset (&intersection);
4583 gst_value_intersect_array (GValue * dest, const GValue * src1,
4584 const GValue * src2)
4590 /* only works on similar-sized arrays */
4591 size = gst_value_array_get_size (src1);
4592 if (size != gst_value_array_get_size (src2))
4595 /* quicker value when we don't need the resulting set */
4597 for (n = 0; n < size; n++) {
4598 if (!gst_value_intersect (NULL, gst_value_array_get_value (src1, n),
4599 gst_value_array_get_value (src2, n))) {
4606 g_value_init (dest, GST_TYPE_ARRAY);
4608 for (n = 0; n < size; n++) {
4609 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
4610 gst_value_array_get_value (src2, n))) {
4611 g_value_unset (dest);
4614 _gst_value_array_append_and_take_value (dest, &val);
4621 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
4622 const GValue * src2)
4626 GstValueCompareFunc compare;
4628 vals = src2->data[0].v_pointer;
4633 if ((compare = gst_value_get_compare_func (src1))) {
4634 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
4635 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
4637 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
4638 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
4640 gst_value_init_and_copy (dest, src1);
4649 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
4650 const GValue * src1, const GValue * src2)
4655 GValue *vals1, *vals2;
4656 GstValueCompareFunc compare;
4658 vals1 = src1->data[0].v_pointer;
4659 vals2 = src2->data[0].v_pointer;
4660 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
4662 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
4663 /* min = MAX (src1.start, src2.start) */
4664 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
4665 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4666 if (res == GST_VALUE_LESS_THAN)
4667 min = &vals2[0]; /* Take the max of the 2 */
4671 /* max = MIN (src1.end, src2.end) */
4672 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
4673 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4674 if (res == GST_VALUE_GREATER_THAN)
4675 max = &vals2[1]; /* Take the min of the 2 */
4679 res = gst_value_compare_with_func (min, max, compare);
4680 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4681 if (res == GST_VALUE_LESS_THAN) {
4683 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
4684 vals1 = dest->data[0].v_pointer;
4685 g_value_copy (min, &vals1[0]);
4686 g_value_copy (max, &vals1[1]);
4690 if (res == GST_VALUE_EQUAL) {
4692 gst_value_init_and_copy (dest, min);
4700 /* Two flagsets intersect if the masked bits in both
4701 * flagsets are exactly equal */
4703 gst_value_intersect_flagset_flagset (GValue * dest,
4704 const GValue * src1, const GValue * src2)
4708 GType type1, type2, flagset_type;
4710 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4711 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4713 f1 = src1->data[0].v_uint;
4714 f2 = src2->data[0].v_uint;
4716 m1 = src1->data[1].v_uint;
4717 m2 = src2->data[1].v_uint;
4719 /* Don't intersect if masked bits disagree */
4720 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4723 /* Allow intersection with the generic FlagSet type, on one
4724 * side, but not 2 different subtypes - that makes no sense */
4725 type1 = G_VALUE_TYPE (src1);
4726 type2 = G_VALUE_TYPE (src2);
4727 flagset_type = GST_TYPE_FLAG_SET;
4729 if (type1 != type2 && type1 != flagset_type && type2 != flagset_type)
4735 /* Prefer an output type that matches a sub-type,
4736 * rather than the generic type */
4737 if (type1 != flagset_type)
4742 g_value_init (dest, dest_type);
4744 /* The compatible set is all the bits from src1 that it
4745 * cares about and all the bits from src2 that it cares
4747 dest->data[0].v_uint = (f1 & m1) | (f2 & m2);
4748 dest->data[1].v_uint = m1 | m2;
4755 gst_value_intersect_structure_structure (GValue * dest,
4756 const GValue * src1, const GValue * src2)
4758 const GstStructure *s1, *s2;
4761 s1 = gst_value_get_structure (src1);
4762 s2 = gst_value_get_structure (src2);
4764 d1 = gst_structure_intersect (s1, s2);
4769 g_value_init (dest, GST_TYPE_STRUCTURE);
4770 gst_value_set_structure (dest, d1);
4773 gst_structure_free (d1);
4782 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
4783 const GValue * subtrahend)
4785 gint min = gst_value_get_int_range_min (subtrahend);
4786 gint max = gst_value_get_int_range_max (subtrahend);
4787 gint step = gst_value_get_int_range_step (subtrahend);
4788 gint val = g_value_get_int (minuend);
4793 /* subtracting a range from an int only works if the int is not in the
4795 if (val < min || val > max || val % step) {
4796 /* and the result is the int */
4798 gst_value_init_and_copy (dest, minuend);
4804 /* creates a new int range based on input values.
4807 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
4808 gint max2, gint step)
4812 GValue *pv1, *pv2; /* yeah, hungarian! */
4814 g_return_val_if_fail (step > 0, FALSE);
4815 g_return_val_if_fail (min1 % step == 0, FALSE);
4816 g_return_val_if_fail (max1 % step == 0, FALSE);
4817 g_return_val_if_fail (min2 % step == 0, FALSE);
4818 g_return_val_if_fail (max2 % step == 0, FALSE);
4820 if (min1 <= max1 && min2 <= max2) {
4823 } else if (min1 <= max1) {
4826 } else if (min2 <= max2) {
4837 g_value_init (pv1, GST_TYPE_INT_RANGE);
4838 gst_value_set_int_range_step (pv1, min1, max1, step);
4839 } else if (min1 == max1) {
4840 g_value_init (pv1, G_TYPE_INT);
4841 g_value_set_int (pv1, min1);
4844 g_value_init (pv2, GST_TYPE_INT_RANGE);
4845 gst_value_set_int_range_step (pv2, min2, max2, step);
4846 } else if (min2 == max2) {
4847 g_value_init (pv2, G_TYPE_INT);
4848 g_value_set_int (pv2, min2);
4851 if (min1 <= max1 && min2 <= max2) {
4852 gst_value_list_concat_and_take_values (dest, pv1, pv2);
4858 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
4859 const GValue * subtrahend)
4861 gint min = gst_value_get_int_range_min (minuend);
4862 gint max = gst_value_get_int_range_max (minuend);
4863 gint step = gst_value_get_int_range_step (minuend);
4864 gint val = g_value_get_int (subtrahend);
4866 g_return_val_if_fail (min < max, FALSE);
4871 /* value is outside of the range, return range unchanged */
4872 if (val < min || val > max || val % step) {
4874 gst_value_init_and_copy (dest, minuend);
4877 /* max must be MAXINT too as val <= max */
4878 if (val >= G_MAXINT - step + 1) {
4882 /* min must be MININT too as val >= max */
4883 if (val <= G_MININT + step - 1) {
4888 gst_value_create_new_range (dest, min, val - step, val + step, max, step);
4894 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
4895 const GValue * subtrahend)
4897 gint min1 = gst_value_get_int_range_min (minuend);
4898 gint max1 = gst_value_get_int_range_max (minuend);
4899 gint step1 = gst_value_get_int_range_step (minuend);
4900 gint min2 = gst_value_get_int_range_min (subtrahend);
4901 gint max2 = gst_value_get_int_range_max (subtrahend);
4902 gint step2 = gst_value_get_int_range_step (subtrahend);
4905 if (step1 != step2) {
4915 if (max2 >= max1 && min2 <= min1) {
4917 } else if (max2 >= max1) {
4918 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4920 } else if (min2 <= min1) {
4921 return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1,
4924 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4925 MAX (max2 + step, min1), max1, step);
4930 gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
4931 const GValue * subtrahend)
4933 gint64 min = gst_value_get_int64_range_min (subtrahend);
4934 gint64 max = gst_value_get_int64_range_max (subtrahend);
4935 gint64 step = gst_value_get_int64_range_step (subtrahend);
4936 gint64 val = g_value_get_int64 (minuend);
4940 /* subtracting a range from an int64 only works if the int64 is not in the
4942 if (val < min || val > max || val % step) {
4943 /* and the result is the int64 */
4945 gst_value_init_and_copy (dest, minuend);
4951 /* creates a new int64 range based on input values.
4954 gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
4955 gint64 min2, gint64 max2, gint64 step)
4959 GValue *pv1, *pv2; /* yeah, hungarian! */
4961 g_return_val_if_fail (step > 0, FALSE);
4962 g_return_val_if_fail (min1 % step == 0, FALSE);
4963 g_return_val_if_fail (max1 % step == 0, FALSE);
4964 g_return_val_if_fail (min2 % step == 0, FALSE);
4965 g_return_val_if_fail (max2 % step == 0, FALSE);
4967 if (min1 <= max1 && min2 <= max2) {
4970 } else if (min1 <= max1) {
4973 } else if (min2 <= max2) {
4984 g_value_init (pv1, GST_TYPE_INT64_RANGE);
4985 gst_value_set_int64_range_step (pv1, min1, max1, step);
4986 } else if (min1 == max1) {
4987 g_value_init (pv1, G_TYPE_INT64);
4988 g_value_set_int64 (pv1, min1);
4991 g_value_init (pv2, GST_TYPE_INT64_RANGE);
4992 gst_value_set_int64_range_step (pv2, min2, max2, step);
4993 } else if (min2 == max2) {
4994 g_value_init (pv2, G_TYPE_INT64);
4995 g_value_set_int64 (pv2, min2);
4998 if (min1 <= max1 && min2 <= max2) {
4999 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5005 gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
5006 const GValue * subtrahend)
5008 gint64 min = gst_value_get_int64_range_min (minuend);
5009 gint64 max = gst_value_get_int64_range_max (minuend);
5010 gint64 step = gst_value_get_int64_range_step (minuend);
5011 gint64 val = g_value_get_int64 (subtrahend);
5013 g_return_val_if_fail (min < max, FALSE);
5018 /* value is outside of the range, return range unchanged */
5019 if (val < min || val > max || val % step) {
5021 gst_value_init_and_copy (dest, minuend);
5024 /* max must be MAXINT64 too as val <= max */
5025 if (val >= G_MAXINT64 - step + 1) {
5029 /* min must be MININT64 too as val >= max */
5030 if (val <= G_MININT64 + step - 1) {
5035 gst_value_create_new_int64_range (dest, min, val - step, val + step, max,
5042 gst_value_subtract_int64_range_int64_range (GValue * dest,
5043 const GValue * minuend, const GValue * subtrahend)
5045 gint64 min1 = gst_value_get_int64_range_min (minuend);
5046 gint64 max1 = gst_value_get_int64_range_max (minuend);
5047 gint64 step1 = gst_value_get_int64_range_step (minuend);
5048 gint64 min2 = gst_value_get_int64_range_min (subtrahend);
5049 gint64 max2 = gst_value_get_int64_range_max (subtrahend);
5050 gint64 step2 = gst_value_get_int64_range_step (subtrahend);
5053 if (step1 != step2) {
5064 if (max2 >= max1 && min2 <= min1) {
5066 } else if (max2 >= max1) {
5067 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5068 max1), step, 0, step);
5069 } else if (min2 <= min1) {
5070 return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1),
5071 max1, step, 0, step);
5073 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5074 max1), MAX (max2 + step, min1), max1, step);
5079 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
5080 const GValue * subtrahend)
5082 gdouble min = gst_value_get_double_range_min (subtrahend);
5083 gdouble max = gst_value_get_double_range_max (subtrahend);
5084 gdouble val = g_value_get_double (minuend);
5086 if (val < min || val > max) {
5088 gst_value_init_and_copy (dest, minuend);
5095 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
5096 const GValue * subtrahend)
5098 /* since we don't have open ranges, we cannot create a hole in
5099 * a double range. We return the original range */
5101 gst_value_init_and_copy (dest, minuend);
5106 gst_value_subtract_double_range_double_range (GValue * dest,
5107 const GValue * minuend, const GValue * subtrahend)
5109 /* since we don't have open ranges, we have to approximate */
5110 /* done like with ints */
5111 gdouble min1 = gst_value_get_double_range_min (minuend);
5112 gdouble max2 = gst_value_get_double_range_max (minuend);
5113 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
5114 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
5117 GValue *pv1, *pv2; /* yeah, hungarian! */
5119 if (min1 < max1 && min2 < max2) {
5122 } else if (min1 < max1) {
5125 } else if (min2 < max2) {
5136 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
5137 gst_value_set_double_range (pv1, min1, max1);
5140 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
5141 gst_value_set_double_range (pv2, min2, max2);
5144 if (min1 < max1 && min2 < max2) {
5145 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5151 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
5152 const GValue * subtrahend)
5155 GValue subtraction = { 0, };
5156 gboolean ret = FALSE;
5158 size = VALUE_LIST_SIZE (minuend);
5159 for (i = 0; i < size; i++) {
5160 const GValue *cur = VALUE_LIST_GET_VALUE (minuend, i);
5162 /* quicker version when we can discard the result */
5164 if (gst_value_subtract (NULL, cur, subtrahend)) {
5171 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
5173 gst_value_move (dest, &subtraction);
5175 } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST
5176 && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) {
5177 _gst_value_list_append_and_take_value (dest, &subtraction);
5181 gst_value_move (&temp, dest);
5182 gst_value_list_concat_and_take_values (dest, &temp, &subtraction);
5190 gst_value_subtract_list (GValue * dest, const GValue * minuend,
5191 const GValue * subtrahend)
5194 GValue data[2] = { {0,}, {0,} };
5195 GValue *subtraction = &data[0], *result = &data[1];
5197 gst_value_init_and_copy (result, minuend);
5198 size = VALUE_LIST_SIZE (subtrahend);
5199 for (i = 0; i < size; i++) {
5200 const GValue *cur = VALUE_LIST_GET_VALUE (subtrahend, i);
5202 if (gst_value_subtract (subtraction, result, cur)) {
5203 GValue *temp = result;
5205 result = subtraction;
5207 g_value_unset (subtraction);
5209 g_value_unset (result);
5214 gst_value_move (dest, result);
5216 g_value_unset (result);
5222 gst_value_subtract_fraction_fraction_range (GValue * dest,
5223 const GValue * minuend, const GValue * subtrahend)
5225 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
5226 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
5227 GstValueCompareFunc compare;
5229 if ((compare = gst_value_get_compare_func (minuend))) {
5230 /* subtracting a range from an fraction only works if the fraction
5231 * is not in the range */
5232 if (gst_value_compare_with_func (minuend, min, compare) ==
5233 GST_VALUE_LESS_THAN ||
5234 gst_value_compare_with_func (minuend, max, compare) ==
5235 GST_VALUE_GREATER_THAN) {
5236 /* and the result is the value */
5238 gst_value_init_and_copy (dest, minuend);
5246 gst_value_subtract_fraction_range_fraction (GValue * dest,
5247 const GValue * minuend, const GValue * subtrahend)
5249 /* since we don't have open ranges, we cannot create a hole in
5250 * a range. We return the original range */
5252 gst_value_init_and_copy (dest, minuend);
5257 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
5258 const GValue * minuend, const GValue * subtrahend)
5260 /* since we don't have open ranges, we have to approximate */
5261 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
5262 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
5263 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
5264 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
5265 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
5269 GValue *pv1, *pv2; /* yeah, hungarian! */
5270 GstValueCompareFunc compare;
5272 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
5273 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
5275 compare = gst_value_get_compare_func (min1);
5276 g_return_val_if_fail (compare, FALSE);
5278 cmp1 = gst_value_compare_with_func (max2, max1, compare);
5279 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5280 if (cmp1 == GST_VALUE_LESS_THAN)
5282 cmp1 = gst_value_compare_with_func (min1, min2, compare);
5283 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5284 if (cmp1 == GST_VALUE_GREATER_THAN)
5287 cmp1 = gst_value_compare_with_func (min1, max1, compare);
5288 cmp2 = gst_value_compare_with_func (min2, max2, compare);
5290 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5293 } else if (cmp1 == GST_VALUE_LESS_THAN) {
5296 } else if (cmp2 == GST_VALUE_LESS_THAN) {
5306 if (cmp1 == GST_VALUE_LESS_THAN) {
5307 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
5308 gst_value_set_fraction_range (pv1, min1, max1);
5310 if (cmp2 == GST_VALUE_LESS_THAN) {
5311 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
5312 gst_value_set_fraction_range (pv2, min2, max2);
5315 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5316 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5326 * gst_value_get_compare_func:
5327 * @value1: a value to get the compare function for
5329 * Determines the compare function to be used with values of the same type as
5330 * @value1. The function can be given to gst_value_compare_with_func().
5332 * Returns: A #GstValueCompareFunc value
5334 static GstValueCompareFunc
5335 gst_value_get_compare_func (const GValue * value1)
5337 GstValueTable *table, *best = NULL;
5341 type1 = G_VALUE_TYPE (value1);
5343 /* this is a fast check */
5344 best = gst_value_hash_lookup_type (type1);
5347 if (G_UNLIKELY (!best || !best->compare)) {
5348 guint len = gst_value_table->len;
5351 for (i = 0; i < len; i++) {
5352 table = &g_array_index (gst_value_table, GstValueTable, i);
5353 if (table->compare && g_type_is_a (type1, table->type)) {
5354 if (!best || g_type_is_a (table->type, best->type))
5359 if (G_LIKELY (best))
5360 return best->compare;
5365 static inline gboolean
5366 gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2)
5368 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5371 return gst_value_get_compare_func (value1) != NULL;
5375 * gst_value_can_compare:
5376 * @value1: a value to compare
5377 * @value2: another value to compare
5379 * Determines if @value1 and @value2 can be compared.
5381 * Returns: %TRUE if the values can be compared
5384 gst_value_can_compare (const GValue * value1, const GValue * value2)
5386 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5387 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5389 return gst_value_can_compare_unchecked (value1, value2);
5393 gst_value_list_equals_range (const GValue * list, const GValue * value)
5395 const GValue *first;
5398 g_assert (G_IS_VALUE (list));
5399 g_assert (G_IS_VALUE (value));
5400 g_assert (GST_VALUE_HOLDS_LIST (list));
5402 /* TODO: compare against an empty list ? No type though... */
5403 list_size = VALUE_LIST_SIZE (list);
5407 /* compare the basic types - they have to match */
5408 first = VALUE_LIST_GET_VALUE (list, 0);
5409 #define CHECK_TYPES(type,prefix) \
5410 (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value))
5411 if (CHECK_TYPES (INT, G)) {
5412 const gint rmin = gst_value_get_int_range_min (value);
5413 const gint rmax = gst_value_get_int_range_max (value);
5414 const gint rstep = gst_value_get_int_range_step (value);
5417 /* note: this will overflow for min 0 and max INT_MAX, but this
5418 would only be equal to a list of INT_MAX elements, which seems
5420 if (list_size != rmax / rstep - rmin / rstep + 1)
5422 for (n = 0; n < list_size; ++n) {
5423 gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n));
5424 if (v < rmin || v > rmax || v % rstep) {
5429 } else if (CHECK_TYPES (INT64, G)) {
5430 const gint64 rmin = gst_value_get_int64_range_min (value);
5431 const gint64 rmax = gst_value_get_int64_range_max (value);
5432 const gint64 rstep = gst_value_get_int64_range_step (value);
5433 GST_DEBUG ("List/range of int64s");
5436 if (list_size != rmax / rstep - rmin / rstep + 1)
5438 for (n = 0; n < list_size; ++n) {
5439 gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n));
5440 if (v < rmin || v > rmax || v % rstep)
5447 /* other combinations don't make sense for equality */
5451 /* "Pure" variant of gst_value_compare which is guaranteed to
5452 * not have list arguments and therefore does basic comparisions
5455 _gst_value_compare_nolist (const GValue * value1, const GValue * value2)
5457 GstValueCompareFunc compare;
5459 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5460 return GST_VALUE_UNORDERED;
5462 compare = gst_value_get_compare_func (value1);
5464 return compare (value1, value2);
5467 g_critical ("unable to compare values of type %s\n",
5468 g_type_name (G_VALUE_TYPE (value1)));
5469 return GST_VALUE_UNORDERED;
5473 * gst_value_compare:
5474 * @value1: a value to compare
5475 * @value2: another value to compare
5477 * Compares @value1 and @value2. If @value1 and @value2 cannot be
5478 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
5479 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned.
5480 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned.
5481 * If the values are equal, GST_VALUE_EQUAL is returned.
5483 * Returns: comparison result
5486 gst_value_compare (const GValue * value1, const GValue * value2)
5488 gboolean value1_is_list;
5489 gboolean value2_is_list;
5491 g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
5492 g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN);
5494 value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST;
5495 value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST;
5497 /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal),
5498 as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
5499 if (value1_is_list && !value2_is_list) {
5502 if (gst_value_list_equals_range (value1, value2)) {
5503 return GST_VALUE_EQUAL;
5506 n = gst_value_list_get_size (value1);
5508 return GST_VALUE_UNORDERED;
5510 for (i = 0; i < n; i++) {
5513 elt = gst_value_list_get_value (value1, i);
5514 ret = gst_value_compare (elt, value2);
5515 if (ret != GST_VALUE_EQUAL && n == 1)
5517 else if (ret != GST_VALUE_EQUAL)
5518 return GST_VALUE_UNORDERED;
5521 return GST_VALUE_EQUAL;
5522 } else if (value2_is_list && !value1_is_list) {
5525 if (gst_value_list_equals_range (value2, value1)) {
5526 return GST_VALUE_EQUAL;
5529 n = gst_value_list_get_size (value2);
5531 return GST_VALUE_UNORDERED;
5533 for (i = 0; i < n; i++) {
5536 elt = gst_value_list_get_value (value2, i);
5537 ret = gst_value_compare (elt, value1);
5538 if (ret != GST_VALUE_EQUAL && n == 1)
5540 else if (ret != GST_VALUE_EQUAL)
5541 return GST_VALUE_UNORDERED;
5544 return GST_VALUE_EQUAL;
5547 /* And now handle the generic case */
5548 return _gst_value_compare_nolist (value1, value2);
5552 * gst_value_compare_with_func:
5553 * @value1: a value to compare
5554 * @value2: another value to compare
5555 * @compare: compare function
5557 * Compares @value1 and @value2 using the @compare function. Works like
5558 * gst_value_compare() but allows to save time determining the compare function
5561 * Returns: comparison result
5564 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
5565 GstValueCompareFunc compare)
5569 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5570 return GST_VALUE_UNORDERED;
5572 return compare (value1, value2);
5578 * gst_value_can_union:
5579 * @value1: a value to union
5580 * @value2: another value to union
5582 * Determines if @value1 and @value2 can be non-trivially unioned.
5583 * Any two values can be trivially unioned by adding both of them
5584 * to a GstValueList. However, certain types have the possibility
5585 * to be unioned in a simpler way. For example, an integer range
5586 * and an integer can be unioned if the integer is a subset of the
5587 * integer range. If there is the possibility that two values can
5588 * be unioned, this function returns %TRUE.
5590 * Returns: %TRUE if there is a function allowing the two values to
5594 gst_value_can_union (const GValue * value1, const GValue * value2)
5596 GstValueUnionInfo *union_info;
5599 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5600 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5602 len = gst_value_union_funcs->len;
5604 for (i = 0; i < len; i++) {
5605 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5606 if (union_info->type1 == G_VALUE_TYPE (value1) &&
5607 union_info->type2 == G_VALUE_TYPE (value2))
5609 if (union_info->type1 == G_VALUE_TYPE (value2) &&
5610 union_info->type2 == G_VALUE_TYPE (value1))
5619 * @dest: (out caller-allocates): the destination value
5620 * @value1: a value to union
5621 * @value2: another value to union
5623 * Creates a GValue corresponding to the union of @value1 and @value2.
5625 * Returns: %TRUE if the union succeeded.
5628 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
5630 const GstValueUnionInfo *union_info;
5634 g_return_val_if_fail (dest != NULL, FALSE);
5635 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5636 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5637 g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2),
5640 len = gst_value_union_funcs->len;
5641 type1 = G_VALUE_TYPE (value1);
5642 type2 = G_VALUE_TYPE (value2);
5644 for (i = 0; i < len; i++) {
5645 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5646 if (union_info->type1 == type1 && union_info->type2 == type2) {
5647 return union_info->func (dest, value1, value2);
5649 if (union_info->type1 == type2 && union_info->type2 == type1) {
5650 return union_info->func (dest, value2, value1);
5654 gst_value_list_concat (dest, value1, value2);
5658 /* gst_value_register_union_func: (skip)
5659 * @type1: a type to union
5660 * @type2: another type to union
5661 * @func: a function that implements creating a union between the two types
5663 * Registers a union function that can create a union between #GValue items
5664 * of the type @type1 and @type2.
5666 * Union functions should be registered at startup before any pipelines are
5667 * started, as gst_value_register_union_func() is not thread-safe and cannot
5668 * be used at the same time as gst_value_union() or gst_value_can_union().
5671 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
5673 GstValueUnionInfo union_info;
5675 union_info.type1 = type1;
5676 union_info.type2 = type2;
5677 union_info.func = func;
5679 g_array_append_val (gst_value_union_funcs, union_info);
5685 * gst_value_can_intersect:
5686 * @value1: a value to intersect
5687 * @value2: another value to intersect
5689 * Determines if intersecting two values will produce a valid result.
5690 * Two values will produce a valid intersection if they have the same
5693 * Returns: %TRUE if the values can intersect
5696 gst_value_can_intersect (const GValue * value1, const GValue * value2)
5698 GstValueIntersectInfo *intersect_info;
5702 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5703 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5705 type1 = G_VALUE_TYPE (value1);
5706 type2 = G_VALUE_TYPE (value2);
5708 /* practically all GstValue types have a compare function (_can_compare=TRUE)
5709 * GstStructure and GstCaps have not, but are intersectable */
5714 if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST)
5717 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5718 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5719 GType type1, type2, flagset_type;
5721 type1 = G_VALUE_TYPE (value1);
5722 type2 = G_VALUE_TYPE (value2);
5723 flagset_type = GST_TYPE_FLAG_SET;
5725 /* Allow intersection with the generic FlagSet type, on one
5726 * side, but not 2 different subtypes - that makes no sense */
5727 if (type1 == type2 || type1 == flagset_type || type2 == flagset_type)
5731 /* check registered intersect functions */
5732 len = gst_value_intersect_funcs->len;
5733 for (i = 0; i < len; i++) {
5734 intersect_info = &g_array_index (gst_value_intersect_funcs,
5735 GstValueIntersectInfo, i);
5736 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
5737 (intersect_info->type1 == type2 && intersect_info->type2 == type1))
5741 return gst_value_can_compare_unchecked (value1, value2);
5745 * gst_value_intersect:
5746 * @dest: (out caller-allocates) (transfer full) (allow-none):
5747 * a uninitialized #GValue that will hold the calculated
5748 * intersection value. May be %NULL if the resulting set if not
5750 * @value1: a value to intersect
5751 * @value2: another value to intersect
5753 * Calculates the intersection of two values. If the values have
5754 * a non-empty intersection, the value representing the intersection
5755 * is placed in @dest, unless %NULL. If the intersection is non-empty,
5756 * @dest is not modified.
5758 * Returns: %TRUE if the intersection is non-empty
5761 gst_value_intersect (GValue * dest, const GValue * value1,
5762 const GValue * value2)
5764 GstValueIntersectInfo *intersect_info;
5768 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5769 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5771 type1 = G_VALUE_TYPE (value1);
5772 type2 = G_VALUE_TYPE (value2);
5774 /* special cases first */
5775 if (type1 == GST_TYPE_LIST)
5776 return gst_value_intersect_list (dest, value1, value2);
5777 if (type2 == GST_TYPE_LIST)
5778 return gst_value_intersect_list (dest, value2, value1);
5780 if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) {
5782 gst_value_init_and_copy (dest, value1);
5786 len = gst_value_intersect_funcs->len;
5787 for (i = 0; i < len; i++) {
5788 intersect_info = &g_array_index (gst_value_intersect_funcs,
5789 GstValueIntersectInfo, i);
5790 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
5791 return intersect_info->func (dest, value1, value2);
5793 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
5794 return intersect_info->func (dest, value2, value1);
5798 /* Failed to find a direct intersection, check if these are
5799 * GstFlagSet sub-types. */
5800 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5801 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5802 return gst_value_intersect_flagset_flagset (dest, value1, value2);
5810 /* gst_value_register_intersect_func: (skip)
5811 * @type1: the first type to intersect
5812 * @type2: the second type to intersect
5813 * @func: the intersection function
5815 * Registers a function that is called to calculate the intersection
5816 * of the values having the types @type1 and @type2.
5818 * Intersect functions should be registered at startup before any pipelines are
5819 * started, as gst_value_register_intersect_func() is not thread-safe and
5820 * cannot be used at the same time as gst_value_intersect() or
5821 * gst_value_can_intersect().
5824 gst_value_register_intersect_func (GType type1, GType type2,
5825 GstValueIntersectFunc func)
5827 GstValueIntersectInfo intersect_info;
5829 intersect_info.type1 = type1;
5830 intersect_info.type2 = type2;
5831 intersect_info.func = func;
5833 g_array_append_val (gst_value_intersect_funcs, intersect_info);
5840 * gst_value_subtract:
5841 * @dest: (out caller-allocates) (allow-none): the destination value
5842 * for the result if the subtraction is not empty. May be %NULL,
5843 * in which case the resulting set will not be computed, which can
5844 * give a fair speedup.
5845 * @minuend: the value to subtract from
5846 * @subtrahend: the value to subtract
5848 * Subtracts @subtrahend from @minuend and stores the result in @dest.
5849 * Note that this means subtraction as in sets, not as in mathematics.
5851 * Returns: %TRUE if the subtraction is not empty
5854 gst_value_subtract (GValue * dest, const GValue * minuend,
5855 const GValue * subtrahend)
5857 GstValueSubtractInfo *info;
5861 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5862 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5864 mtype = G_VALUE_TYPE (minuend);
5865 stype = G_VALUE_TYPE (subtrahend);
5867 /* special cases first */
5868 if (mtype == GST_TYPE_LIST)
5869 return gst_value_subtract_from_list (dest, minuend, subtrahend);
5870 if (stype == GST_TYPE_LIST)
5871 return gst_value_subtract_list (dest, minuend, subtrahend);
5873 len = gst_value_subtract_funcs->len;
5874 for (i = 0; i < len; i++) {
5875 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5876 if (info->minuend == mtype && info->subtrahend == stype) {
5877 return info->func (dest, minuend, subtrahend);
5881 if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) {
5883 gst_value_init_and_copy (dest, minuend);
5892 gst_value_subtract (GValue * dest, const GValue * minuend,
5893 const GValue * subtrahend)
5895 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
5897 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
5898 gst_value_serialize (subtrahend),
5899 ret ? gst_value_serialize (dest) : "---");
5905 * gst_value_can_subtract:
5906 * @minuend: the value to subtract from
5907 * @subtrahend: the value to subtract
5909 * Checks if it's possible to subtract @subtrahend from @minuend.
5911 * Returns: %TRUE if a subtraction is possible
5914 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
5916 GstValueSubtractInfo *info;
5920 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5921 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5923 mtype = G_VALUE_TYPE (minuend);
5924 stype = G_VALUE_TYPE (subtrahend);
5927 if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST)
5929 if (mtype == GST_TYPE_STRUCTURE || stype == GST_TYPE_STRUCTURE)
5932 len = gst_value_subtract_funcs->len;
5933 for (i = 0; i < len; i++) {
5934 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5935 if (info->minuend == mtype && info->subtrahend == stype)
5939 return gst_value_can_compare_unchecked (minuend, subtrahend);
5942 /* gst_value_register_subtract_func: (skip)
5943 * @minuend_type: type of the minuend
5944 * @subtrahend_type: type of the subtrahend
5945 * @func: function to use
5947 * Registers @func as a function capable of subtracting the values of
5948 * @subtrahend_type from values of @minuend_type.
5950 * Subtract functions should be registered at startup before any pipelines are
5951 * started, as gst_value_register_subtract_func() is not thread-safe and
5952 * cannot be used at the same time as gst_value_subtract().
5955 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
5956 GstValueSubtractFunc func)
5958 GstValueSubtractInfo info;
5960 g_return_if_fail (!gst_type_is_fixed (minuend_type)
5961 || !gst_type_is_fixed (subtrahend_type));
5963 info.minuend = minuend_type;
5964 info.subtrahend = subtrahend_type;
5967 g_array_append_val (gst_value_subtract_funcs, info);
5971 * gst_value_register:
5972 * @table: structure containing functions to register
5974 * Registers functions to perform calculations on #GValue items of a given
5975 * type. Each type can only be added once.
5978 gst_value_register (const GstValueTable * table)
5980 GstValueTable *found;
5982 g_return_if_fail (table != NULL);
5984 g_array_append_val (gst_value_table, *table);
5986 found = gst_value_hash_lookup_type (table->type);
5988 g_warning ("adding type %s multiple times", g_type_name (table->type));
5990 /* FIXME: we're not really doing the const justice, we assume the table is
5992 gst_value_hash_add_type (table->type, table);
5996 * gst_value_init_and_copy:
5997 * @dest: (out caller-allocates): the target value
5998 * @src: the source value
6000 * Initialises the target value to be of the same type as source and then copies
6001 * the contents from source to target.
6004 gst_value_init_and_copy (GValue * dest, const GValue * src)
6006 g_return_if_fail (G_IS_VALUE (src));
6007 g_return_if_fail (dest != NULL);
6009 g_value_init (dest, G_VALUE_TYPE (src));
6010 g_value_copy (src, dest);
6013 /* move src into dest and clear src */
6015 gst_value_move (GValue * dest, GValue * src)
6017 g_assert (G_IS_VALUE (src));
6018 g_assert (dest != NULL);
6021 memset (src, 0, sizeof (GValue));
6025 * gst_value_serialize:
6026 * @value: a #GValue to serialize
6028 * tries to transform the given @value into a string representation that allows
6029 * getting back this string later on using gst_value_deserialize().
6031 * Free-function: g_free
6033 * Returns: (transfer full) (nullable): the serialization for @value
6034 * or %NULL if none exists
6037 gst_value_serialize (const GValue * value)
6040 GValue s_val = { 0 };
6041 GstValueTable *table, *best;
6045 g_return_val_if_fail (G_IS_VALUE (value), NULL);
6047 type = G_VALUE_TYPE (value);
6049 best = gst_value_hash_lookup_type (type);
6051 if (G_UNLIKELY (!best || !best->serialize)) {
6052 len = gst_value_table->len;
6054 for (i = 0; i < len; i++) {
6055 table = &g_array_index (gst_value_table, GstValueTable, i);
6056 if (table->serialize && g_type_is_a (type, table->type)) {
6057 if (!best || g_type_is_a (table->type, best->type))
6062 if (G_LIKELY (best))
6063 return best->serialize (value);
6065 g_value_init (&s_val, G_TYPE_STRING);
6066 if (g_value_transform (value, &s_val)) {
6067 s = gst_string_wrap (g_value_get_string (&s_val));
6071 g_value_unset (&s_val);
6077 * gst_value_deserialize:
6078 * @dest: (out caller-allocates): #GValue to fill with contents of
6080 * @src: string to deserialize
6082 * Tries to deserialize a string into the type specified by the given GValue.
6083 * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
6085 * Returns: %TRUE on success
6088 gst_value_deserialize (GValue * dest, const gchar * src)
6090 GstValueTable *table, *best;
6094 g_return_val_if_fail (src != NULL, FALSE);
6095 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
6097 type = G_VALUE_TYPE (dest);
6099 best = gst_value_hash_lookup_type (type);
6100 if (G_UNLIKELY (!best || !best->deserialize)) {
6101 len = gst_value_table->len;
6103 for (i = 0; i < len; i++) {
6104 table = &g_array_index (gst_value_table, GstValueTable, i);
6105 if (table->deserialize && g_type_is_a (type, table->type)) {
6106 if (!best || g_type_is_a (table->type, best->type))
6111 if (G_LIKELY (best))
6112 return best->deserialize (dest, src);
6118 structure_field_is_fixed (GQuark field_id, const GValue * val,
6121 return gst_value_is_fixed (val);
6125 * gst_value_is_fixed:
6126 * @value: the #GValue to check
6128 * Tests if the given GValue, if available in a GstStructure (or any other
6129 * container) contains a "fixed" (which means: one value) or an "unfixed"
6130 * (which means: multiple possible values, such as data lists or data
6133 * Returns: true if the value is "fixed".
6137 gst_value_is_fixed (const GValue * value)
6141 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
6143 type = G_VALUE_TYPE (value);
6145 /* the most common types are just basic plain glib types */
6146 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
6150 if (type == GST_TYPE_ARRAY) {
6154 /* check recursively */
6155 size = gst_value_array_get_size (value);
6156 for (n = 0; n < size; n++) {
6157 kid = gst_value_array_get_value (value, n);
6158 if (!gst_value_is_fixed (kid))
6162 } else if (GST_VALUE_HOLDS_FLAG_SET (value)) {
6163 /* Flagsets are only fixed if there are no 'don't care' bits */
6164 return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT);
6165 } else if (GST_VALUE_HOLDS_STRUCTURE (value)) {
6166 return gst_structure_foreach (gst_value_get_structure (value),
6167 structure_field_is_fixed, NULL);
6169 return gst_type_is_fixed (type);
6174 * @dest: the #GValue destination
6175 * @src: the #GValue to fixate
6177 * Fixate @src into a new value @dest.
6178 * For ranges, the first element is taken. For lists and arrays, the
6179 * first item is fixated and returned.
6180 * If @src is already fixed, this function returns %FALSE.
6182 * Returns: %TRUE if @dest contains a fixated version of @src.
6185 gst_value_fixate (GValue * dest, const GValue * src)
6187 g_return_val_if_fail (G_IS_VALUE (src), FALSE);
6188 g_return_val_if_fail (dest != NULL, FALSE);
6190 if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
6191 g_value_init (dest, G_TYPE_INT);
6192 g_value_set_int (dest, gst_value_get_int_range_min (src));
6193 } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
6194 g_value_init (dest, G_TYPE_DOUBLE);
6195 g_value_set_double (dest, gst_value_get_double_range_min (src));
6196 } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
6197 gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
6198 } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
6199 GValue temp = { 0 };
6201 /* list could be empty */
6202 if (gst_value_list_get_size (src) <= 0)
6205 gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
6207 if (!gst_value_fixate (dest, &temp)) {
6208 gst_value_move (dest, &temp);
6210 g_value_unset (&temp);
6212 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
6213 gboolean res = FALSE;
6216 len = gst_value_array_get_size (src);
6217 g_value_init (dest, GST_TYPE_ARRAY);
6218 for (n = 0; n < len; n++) {
6220 const GValue *orig_kid = gst_value_array_get_value (src, n);
6222 if (!gst_value_fixate (&kid, orig_kid))
6223 gst_value_init_and_copy (&kid, orig_kid);
6226 _gst_value_array_append_and_take_value (dest, &kid);
6230 g_value_unset (dest);
6233 } else if (GST_VALUE_HOLDS_FLAG_SET (src)) {
6236 if (gst_value_get_flagset_mask (src) == GST_FLAG_SET_MASK_EXACT)
6237 return FALSE; /* Already fixed */
6239 flags = gst_value_get_flagset_flags (src);
6240 g_value_init (dest, G_VALUE_TYPE (src));
6241 gst_value_set_flagset (dest, flags, GST_FLAG_SET_MASK_EXACT);
6243 } else if (GST_VALUE_HOLDS_STRUCTURE (src)) {
6244 const GstStructure *str = (GstStructure *) gst_value_get_structure (src);
6250 kid = gst_structure_copy (str);
6251 gst_structure_fixate (kid);
6252 g_value_init (dest, GST_TYPE_STRUCTURE);
6253 gst_value_set_structure (dest, kid);
6254 gst_structure_free (kid);
6267 /* helper functions */
6269 gst_value_init_fraction (GValue * value)
6271 value->data[0].v_int = 0;
6272 value->data[1].v_int = 1;
6276 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
6278 dest_value->data[0].v_int = src_value->data[0].v_int;
6279 dest_value->data[1].v_int = src_value->data[1].v_int;
6283 gst_value_collect_fraction (GValue * value, guint n_collect_values,
6284 GTypeCValue * collect_values, guint collect_flags)
6286 if (n_collect_values != 2)
6287 return g_strdup_printf ("not enough value locations for `%s' passed",
6288 G_VALUE_TYPE_NAME (value));
6289 if (collect_values[1].v_int == 0)
6290 return g_strdup_printf ("passed '0' as denominator for `%s'",
6291 G_VALUE_TYPE_NAME (value));
6292 if (collect_values[0].v_int < -G_MAXINT)
6295 ("passed value smaller than -G_MAXINT as numerator for `%s'",
6296 G_VALUE_TYPE_NAME (value));
6297 if (collect_values[1].v_int < -G_MAXINT)
6300 ("passed value smaller than -G_MAXINT as denominator for `%s'",
6301 G_VALUE_TYPE_NAME (value));
6303 gst_value_set_fraction (value,
6304 collect_values[0].v_int, collect_values[1].v_int);
6310 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
6311 GTypeCValue * collect_values, guint collect_flags)
6313 gint *numerator = collect_values[0].v_pointer;
6314 gint *denominator = collect_values[1].v_pointer;
6317 return g_strdup_printf ("numerator for `%s' passed as NULL",
6318 G_VALUE_TYPE_NAME (value));
6320 return g_strdup_printf ("denominator for `%s' passed as NULL",
6321 G_VALUE_TYPE_NAME (value));
6323 *numerator = value->data[0].v_int;
6324 *denominator = value->data[1].v_int;
6330 * gst_value_set_fraction:
6331 * @value: a GValue initialized to #GST_TYPE_FRACTION
6332 * @numerator: the numerator of the fraction
6333 * @denominator: the denominator of the fraction
6335 * Sets @value to the fraction specified by @numerator over @denominator.
6336 * The fraction gets reduced to the smallest numerator and denominator,
6337 * and if necessary the sign is moved to the numerator.
6340 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
6344 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
6345 g_return_if_fail (denominator != 0);
6346 g_return_if_fail (denominator >= -G_MAXINT);
6347 g_return_if_fail (numerator >= -G_MAXINT);
6349 /* normalize sign */
6350 if (denominator < 0) {
6351 numerator = -numerator;
6352 denominator = -denominator;
6355 /* check for reduction */
6356 gcd = gst_util_greatest_common_divisor (numerator, denominator);
6362 g_assert (denominator > 0);
6364 value->data[0].v_int = numerator;
6365 value->data[1].v_int = denominator;
6369 * gst_value_get_fraction_numerator:
6370 * @value: a GValue initialized to #GST_TYPE_FRACTION
6372 * Gets the numerator of the fraction specified by @value.
6374 * Returns: the numerator of the fraction.
6377 gst_value_get_fraction_numerator (const GValue * value)
6379 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
6381 return value->data[0].v_int;
6385 * gst_value_get_fraction_denominator:
6386 * @value: a GValue initialized to #GST_TYPE_FRACTION
6388 * Gets the denominator of the fraction specified by @value.
6390 * Returns: the denominator of the fraction.
6393 gst_value_get_fraction_denominator (const GValue * value)
6395 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
6397 return value->data[1].v_int;
6401 * gst_value_fraction_multiply:
6402 * @product: a GValue initialized to #GST_TYPE_FRACTION
6403 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
6404 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
6406 * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets
6407 * @product to the product of the two fractions.
6409 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6412 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
6413 const GValue * factor2)
6415 gint n1, n2, d1, d2;
6418 g_return_val_if_fail (product != NULL, FALSE);
6419 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
6420 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
6422 n1 = factor1->data[0].v_int;
6423 n2 = factor2->data[0].v_int;
6424 d1 = factor1->data[1].v_int;
6425 d2 = factor2->data[1].v_int;
6427 if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
6430 gst_value_set_fraction (product, res_n, res_d);
6436 * gst_value_fraction_subtract:
6437 * @dest: a GValue initialized to #GST_TYPE_FRACTION
6438 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
6439 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
6441 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
6443 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6446 gst_value_fraction_subtract (GValue * dest,
6447 const GValue * minuend, const GValue * subtrahend)
6449 gint n1, n2, d1, d2;
6452 g_return_val_if_fail (dest != NULL, FALSE);
6453 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
6454 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
6456 n1 = minuend->data[0].v_int;
6457 n2 = subtrahend->data[0].v_int;
6458 d1 = minuend->data[1].v_int;
6459 d2 = subtrahend->data[1].v_int;
6461 if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d))
6463 gst_value_set_fraction (dest, res_n, res_d);
6469 gst_value_serialize_fraction (const GValue * value)
6471 gint32 numerator = value->data[0].v_int;
6472 gint32 denominator = value->data[1].v_int;
6473 gboolean positive = TRUE;
6475 /* get the sign and make components absolute */
6476 if (numerator < 0) {
6477 numerator = -numerator;
6478 positive = !positive;
6480 if (denominator < 0) {
6481 denominator = -denominator;
6482 positive = !positive;
6485 return g_strdup_printf ("%s%d/%d",
6486 positive ? "" : "-", numerator, denominator);
6490 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
6495 if (G_UNLIKELY (s == NULL))
6498 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
6501 if (sscanf (s, "%d/%d%n", &num, &den, &num_chars) >= 2) {
6502 if (s[num_chars] != 0)
6507 gst_value_set_fraction (dest, num, den);
6509 } else if (g_ascii_strcasecmp (s, "1/max") == 0) {
6510 gst_value_set_fraction (dest, 1, G_MAXINT);
6512 } else if (sscanf (s, "%d%n", &num, &num_chars) >= 1) {
6513 if (s[num_chars] != 0)
6515 gst_value_set_fraction (dest, num, 1);
6517 } else if (g_ascii_strcasecmp (s, "min") == 0) {
6518 gst_value_set_fraction (dest, -G_MAXINT, 1);
6520 } else if (g_ascii_strcasecmp (s, "max") == 0) {
6521 gst_value_set_fraction (dest, G_MAXINT, 1);
6529 gst_value_transform_fraction_string (const GValue * src_value,
6530 GValue * dest_value)
6532 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
6536 gst_value_transform_string_fraction (const GValue * src_value,
6537 GValue * dest_value)
6539 if (!gst_value_deserialize_fraction (dest_value,
6540 src_value->data[0].v_pointer))
6541 /* If the deserialize fails, ensure we leave the fraction in a
6542 * valid, if incorrect, state */
6543 gst_value_set_fraction (dest_value, 0, 1);
6547 gst_value_transform_double_fraction (const GValue * src_value,
6548 GValue * dest_value)
6550 gdouble src = g_value_get_double (src_value);
6553 gst_util_double_to_fraction (src, &n, &d);
6554 gst_value_set_fraction (dest_value, n, d);
6558 gst_value_transform_float_fraction (const GValue * src_value,
6559 GValue * dest_value)
6561 gfloat src = g_value_get_float (src_value);
6564 gst_util_double_to_fraction (src, &n, &d);
6565 gst_value_set_fraction (dest_value, n, d);
6569 gst_value_transform_fraction_double (const GValue * src_value,
6570 GValue * dest_value)
6572 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
6573 ((double) src_value->data[1].v_int);
6577 gst_value_transform_fraction_float (const GValue * src_value,
6578 GValue * dest_value)
6580 dest_value->data[0].v_float = ((float) src_value->data[0].v_int) /
6581 ((float) src_value->data[1].v_int);
6585 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
6591 n1 = value1->data[0].v_int;
6592 n2 = value2->data[0].v_int;
6593 d1 = value1->data[1].v_int;
6594 d2 = value2->data[1].v_int;
6596 /* fractions are reduced when set, so we can quickly see if they're equal */
6597 if (n1 == n2 && d1 == d2)
6598 return GST_VALUE_EQUAL;
6600 if (d1 == 0 && d2 == 0)
6601 return GST_VALUE_UNORDERED;
6603 return GST_VALUE_GREATER_THAN;
6605 return GST_VALUE_LESS_THAN;
6607 ret = gst_util_fraction_compare (n1, d1, n2, d2);
6609 return GST_VALUE_LESS_THAN;
6611 return GST_VALUE_GREATER_THAN;
6613 /* Equality can't happen here because we check for that
6615 g_return_val_if_reached (GST_VALUE_UNORDERED);
6623 gst_value_compare_date (const GValue * value1, const GValue * value2)
6625 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
6626 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
6630 return GST_VALUE_EQUAL;
6632 if ((date1 == NULL || !g_date_valid (date1))
6633 && (date2 != NULL && g_date_valid (date2))) {
6634 return GST_VALUE_LESS_THAN;
6637 if ((date2 == NULL || !g_date_valid (date2))
6638 && (date1 != NULL && g_date_valid (date1))) {
6639 return GST_VALUE_GREATER_THAN;
6642 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
6643 || !g_date_valid (date2)) {
6644 return GST_VALUE_UNORDERED;
6647 j1 = g_date_get_julian (date1);
6648 j2 = g_date_get_julian (date2);
6651 return GST_VALUE_EQUAL;
6653 return GST_VALUE_LESS_THAN;
6655 return GST_VALUE_GREATER_THAN;
6659 gst_value_serialize_date (const GValue * val)
6661 const GDate *date = (const GDate *) g_value_get_boxed (val);
6663 if (date == NULL || !g_date_valid (date))
6664 return g_strdup ("9999-99-99");
6666 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
6667 g_date_get_month (date), g_date_get_day (date));
6671 gst_value_deserialize_date (GValue * dest, const gchar * s)
6673 guint year, month, day;
6675 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
6678 if (!g_date_valid_dmy (day, month, year))
6681 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
6690 gst_value_compare_date_time (const GValue * value1, const GValue * value2)
6692 const GstDateTime *date1 = (const GstDateTime *) g_value_get_boxed (value1);
6693 const GstDateTime *date2 = (const GstDateTime *) g_value_get_boxed (value2);
6696 return GST_VALUE_EQUAL;
6698 if ((date1 == NULL) && (date2 != NULL)) {
6699 return GST_VALUE_LESS_THAN;
6701 if ((date2 == NULL) && (date1 != NULL)) {
6702 return GST_VALUE_LESS_THAN;
6705 /* returns GST_VALUE_* */
6706 return __gst_date_time_compare (date1, date2);
6710 gst_value_serialize_date_time (const GValue * val)
6712 GstDateTime *date = (GstDateTime *) g_value_get_boxed (val);
6715 return g_strdup ("null");
6717 return __gst_date_time_serialize (date, TRUE);
6721 gst_value_deserialize_date_time (GValue * dest, const gchar * s)
6723 GstDateTime *datetime;
6725 if (!s || strcmp (s, "null") == 0) {
6729 datetime = gst_date_time_new_from_iso8601_string (s);
6730 if (datetime != NULL) {
6731 g_value_take_boxed (dest, datetime);
6734 GST_WARNING ("Failed to deserialize date time string '%s'", s);
6739 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
6741 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
6745 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
6747 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
6755 /* helper functions */
6757 gst_value_init_bitmask (GValue * value)
6759 value->data[0].v_uint64 = 0;
6763 gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
6765 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6769 gst_value_collect_bitmask (GValue * value, guint n_collect_values,
6770 GTypeCValue * collect_values, guint collect_flags)
6772 if (n_collect_values != 1)
6773 return g_strdup_printf ("not enough value locations for `%s' passed",
6774 G_VALUE_TYPE_NAME (value));
6776 gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
6782 gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
6783 GTypeCValue * collect_values, guint collect_flags)
6785 guint64 *bitmask = collect_values[0].v_pointer;
6788 return g_strdup_printf ("value for `%s' passed as NULL",
6789 G_VALUE_TYPE_NAME (value));
6791 *bitmask = value->data[0].v_uint64;
6797 * gst_value_set_bitmask:
6798 * @value: a GValue initialized to #GST_TYPE_BITMASK
6799 * @bitmask: the bitmask
6801 * Sets @value to the bitmask specified by @bitmask.
6804 gst_value_set_bitmask (GValue * value, guint64 bitmask)
6806 g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
6808 value->data[0].v_uint64 = bitmask;
6812 * gst_value_get_bitmask:
6813 * @value: a GValue initialized to #GST_TYPE_BITMASK
6815 * Gets the bitmask specified by @value.
6817 * Returns: the bitmask.
6820 gst_value_get_bitmask (const GValue * value)
6822 g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
6824 return value->data[0].v_uint64;
6828 gst_value_serialize_bitmask (const GValue * value)
6830 guint64 bitmask = value->data[0].v_uint64;
6832 return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
6836 gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
6838 gchar *endptr = NULL;
6841 if (G_UNLIKELY (s == NULL))
6844 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
6848 val = g_ascii_strtoull (s, &endptr, 16);
6849 if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
6851 if (val == 0 && endptr == s)
6854 gst_value_set_bitmask (dest, val);
6860 gst_value_transform_bitmask_string (const GValue * src_value,
6861 GValue * dest_value)
6863 dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
6867 gst_value_transform_string_bitmask (const GValue * src_value,
6868 GValue * dest_value)
6870 if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
6871 gst_value_set_bitmask (dest_value, 0);
6875 gst_value_transform_uint64_bitmask (const GValue * src_value,
6876 GValue * dest_value)
6878 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6882 gst_value_transform_bitmask_uint64 (const GValue * src_value,
6883 GValue * dest_value)
6885 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6889 gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
6893 v1 = value1->data[0].v_uint64;
6894 v2 = value2->data[0].v_uint64;
6897 return GST_VALUE_EQUAL;
6899 return GST_VALUE_UNORDERED;
6906 /* helper functions */
6908 gst_value_init_flagset (GValue * value)
6910 value->data[0].v_uint = 0;
6911 value->data[1].v_uint = 0;
6915 gst_value_copy_flagset (const GValue * src_value, GValue * dest_value)
6917 dest_value->data[0].v_uint = src_value->data[0].v_uint;
6918 dest_value->data[1].v_uint = src_value->data[1].v_uint;
6922 gst_value_collect_flagset (GValue * value, guint n_collect_values,
6923 GTypeCValue * collect_values, guint collect_flags)
6925 if (n_collect_values != 2)
6926 return g_strdup_printf ("not enough value locations for `%s' passed",
6927 G_VALUE_TYPE_NAME (value));
6929 gst_value_set_flagset (value,
6930 (guint) collect_values[0].v_int, (guint) collect_values[1].v_int);
6936 gst_value_lcopy_flagset (const GValue * value, guint n_collect_values,
6937 GTypeCValue * collect_values, guint collect_flags)
6939 guint *flags = collect_values[0].v_pointer;
6940 guint *mask = collect_values[1].v_pointer;
6942 *flags = value->data[0].v_uint;
6943 *mask = value->data[1].v_uint;
6949 * gst_value_set_flagset:
6950 * @value: a GValue initialized to %GST_TYPE_FLAG_SET
6951 * @flags: The value of the flags set or unset
6952 * @mask: The mask indicate which flags bits must match for comparisons
6954 * Sets @value to the flags and mask values provided in @flags and @mask.
6955 * The @flags value indicates the values of flags, the @mask represents
6956 * which bits in the flag value have been set, and which are "don't care"
6961 gst_value_set_flagset (GValue * value, guint flags, guint mask)
6963 g_return_if_fail (GST_VALUE_HOLDS_FLAG_SET (value));
6965 /* Normalise and only keep flags mentioned in the mask */
6966 value->data[0].v_uint = flags & mask;
6967 value->data[1].v_uint = mask;
6971 * gst_value_get_flagset_flags:
6972 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
6974 * Retrieve the flags field of a GstFlagSet @value.
6976 * Returns: the flags field of the flagset instance.
6981 gst_value_get_flagset_flags (const GValue * value)
6983 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 0);
6985 return value->data[0].v_uint;
6989 * gst_value_get_flagset_mask:
6990 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
6992 * Retrieve the mask field of a GstFlagSet @value.
6994 * Returns: the mask field of the flagset instance.
6999 gst_value_get_flagset_mask (const GValue * value)
7001 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 1);
7003 return value->data[1].v_uint;
7007 gst_value_serialize_flagset (const GValue * value)
7009 guint flags = value->data[0].v_uint;
7010 guint mask = value->data[1].v_uint;
7011 GstFlagSetClass *set_klass =
7012 (GstFlagSetClass *) g_type_class_ref (G_VALUE_TYPE (value));
7015 result = g_strdup_printf ("%x:%x", flags, mask);
7017 /* If this flag set class has an associated GFlags GType, and some
7018 * bits in the mask, serialize the bits in human-readable form to
7020 if (mask && set_klass->flags_type) {
7021 GFlagsClass *flags_klass =
7022 (GFlagsClass *) (g_type_class_ref (set_klass->flags_type));
7025 gboolean first = TRUE;
7027 g_return_val_if_fail (flags_klass, NULL);
7029 /* some bits in the mask are set, so serialize one by one, according
7030 * to whether that bit is set or cleared in the flags value */
7032 fl = g_flags_get_first_value (flags_klass, mask);
7034 /* No more bits match in the flags mask - time to stop */
7039 tmp = g_strconcat (result,
7041 (flags & fl->value) ? "+" : "/", fl->value_nick, NULL);
7049 g_type_class_unref (flags_klass);
7052 g_type_class_unref (set_klass);
7058 gst_value_deserialize_flagset (GValue * dest, const gchar * s)
7060 gboolean res = FALSE;
7064 if (G_UNLIKELY (s == NULL))
7067 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FLAG_SET (dest)))
7070 /* Flagset strings look like %x:%x - hex flags : hex bitmask,
7071 * 32-bit each, or like a concatenated list of flag nicks,
7072 * with either '+' or '/' in front. The first form
7073 * may optionally be followed by ':' and a set of text flag descriptions
7074 * for easier debugging */
7076 /* Try and interpret as hex form first, as it's the most efficient */
7077 /* Read the flags first */
7078 flags = strtoul (s, &next, 16);
7079 if (G_UNLIKELY ((flags == 0 && errno == EINVAL) || s == next))
7080 goto try_as_flags_string;
7081 /* Next char should be a colon */
7087 mask = strtoul (cur, &next, 16);
7088 if (G_UNLIKELY ((mask == 0 && errno == EINVAL) || cur == next))
7089 goto try_as_flags_string;
7091 /* Next char should be NULL terminator, or a ':' */
7092 if (G_UNLIKELY (next[0] != 0 && next[0] != ':'))
7093 goto try_as_flags_string;
7097 try_as_flags_string:
7100 const gchar *set_class = g_type_name (G_VALUE_TYPE (dest));
7101 GFlagsClass *flags_klass = NULL;
7104 if (g_str_equal (set_class, "GstFlagSet"))
7105 goto done; /* There's no hope to parse a generic flag set */
7107 /* Flags class is the FlagSet class with 'Set' removed from the end */
7108 end = g_strrstr (set_class, "Set");
7111 gchar *class_name = g_strndup (set_class, end - set_class);
7112 GType flags_type = g_type_from_name (class_name);
7113 if (flags_type == 0) {
7114 GST_TRACE ("Looking for dynamic type %s", class_name);
7115 gst_dynamic_type_factory_load (class_name);
7118 if (flags_type != 0) {
7119 flags_klass = g_type_class_ref (flags_type);
7120 GST_TRACE ("Going to parse %s as %s", s, class_name);
7122 g_free (class_name);
7126 res = gst_value_gflags_str_to_flags (flags_klass, s, &flags, &mask);
7127 g_type_class_unref (flags_klass);
7132 gst_value_set_flagset (dest, flags, mask);
7139 gst_value_transform_flagset_string (const GValue * src_value,
7140 GValue * dest_value)
7142 dest_value->data[0].v_pointer = gst_value_serialize_flagset (src_value);
7146 gst_value_transform_string_flagset (const GValue * src_value,
7147 GValue * dest_value)
7149 if (!gst_value_deserialize_flagset (dest_value, src_value->data[0].v_pointer)) {
7150 /* If the deserialize fails, ensure we leave the flags in a
7151 * valid, if incorrect, state */
7152 gst_value_set_flagset (dest_value, 0, 0);
7157 gst_value_compare_flagset (const GValue * value1, const GValue * value2)
7162 v1 = value1->data[0].v_uint;
7163 v2 = value2->data[0].v_uint;
7165 m1 = value1->data[1].v_uint;
7166 m2 = value2->data[1].v_uint;
7168 if (v1 == v2 && m1 == m2)
7169 return GST_VALUE_EQUAL;
7171 return GST_VALUE_UNORDERED;
7174 /***********************
7175 * GstAllocationParams *
7176 ***********************/
7178 gst_value_compare_allocation_params (const GValue * value1,
7179 const GValue * value2)
7181 GstAllocationParams *v1, *v2;
7183 v1 = value1->data[0].v_pointer;
7184 v2 = value2->data[0].v_pointer;
7186 if (v1 == NULL && v1 == v2)
7187 return GST_VALUE_EQUAL;
7189 if (v1 == NULL || v2 == NULL)
7190 return GST_VALUE_UNORDERED;
7192 if (v1->flags == v2->flags && v1->align == v2->align &&
7193 v1->prefix == v2->prefix && v1->padding == v2->padding)
7194 return GST_VALUE_EQUAL;
7196 return GST_VALUE_UNORDERED;
7205 gst_value_compare_object (const GValue * value1, const GValue * value2)
7209 v1 = value1->data[0].v_pointer;
7210 v2 = value2->data[0].v_pointer;
7213 return GST_VALUE_EQUAL;
7215 return GST_VALUE_UNORDERED;
7219 gst_value_transform_object_string (const GValue * src_value,
7220 GValue * dest_value)
7225 obj = g_value_get_object (src_value);
7228 g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
7229 GST_OBJECT_NAME (obj));
7231 str = g_strdup ("NULL");
7234 dest_value->data[0].v_pointer = str;
7237 static GTypeInfo _info = {
7238 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL,
7241 static GTypeFundamentalInfo _finfo = {
7245 #define FUNC_VALUE_GET_TYPE_CLASSED(type, name, csize, flags) \
7246 GType _gst_ ## type ## _type = 0; \
7248 GType gst_ ## type ## _get_type (void) \
7250 static volatile GType gst_ ## type ## _type = 0; \
7252 if (g_once_init_enter (&gst_ ## type ## _type)) { \
7254 _info.class_size = csize; \
7255 _finfo.type_flags = flags; \
7256 _info.value_table = & _gst_ ## type ## _value_table; \
7257 _type = g_type_register_fundamental ( \
7258 g_type_fundamental_next (), \
7259 name, &_info, &_finfo, 0); \
7260 _gst_ ## type ## _type = _type; \
7261 g_once_init_leave(&gst_ ## type ## _type, _type); \
7264 return gst_ ## type ## _type; \
7267 #define FUNC_VALUE_GET_TYPE(type, name) \
7268 FUNC_VALUE_GET_TYPE_CLASSED(type, name, 0, 0)
7270 static const GTypeValueTable _gst_int_range_value_table = {
7271 gst_value_init_int_range,
7273 gst_value_copy_int_range,
7276 gst_value_collect_int_range, (char *) "pp", gst_value_lcopy_int_range
7279 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
7281 static const GTypeValueTable _gst_int64_range_value_table = {
7282 gst_value_init_int64_range,
7283 gst_value_free_int64_range,
7284 gst_value_copy_int64_range,
7287 gst_value_collect_int64_range,
7288 (char *) "pp", gst_value_lcopy_int64_range
7291 FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range");
7293 static const GTypeValueTable _gst_double_range_value_table = {
7294 gst_value_init_double_range,
7296 gst_value_copy_double_range,
7299 gst_value_collect_double_range,
7300 (char *) "pp", gst_value_lcopy_double_range
7303 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
7305 static const GTypeValueTable _gst_fraction_range_value_table = {
7306 gst_value_init_fraction_range,
7307 gst_value_free_fraction_range,
7308 gst_value_copy_fraction_range,
7311 gst_value_collect_fraction_range,
7312 (char *) "pppp", gst_value_lcopy_fraction_range
7315 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
7317 static const GTypeValueTable _gst_value_list_value_table = {
7318 gst_value_init_list_or_array,
7319 gst_value_free_list_or_array,
7320 gst_value_copy_list_or_array,
7321 gst_value_list_or_array_peek_pointer,
7323 gst_value_collect_list_or_array,
7324 (char *) "p", gst_value_lcopy_list_or_array
7327 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
7329 static const GTypeValueTable _gst_value_array_value_table = {
7330 gst_value_init_list_or_array,
7331 gst_value_free_list_or_array,
7332 gst_value_copy_list_or_array,
7333 gst_value_list_or_array_peek_pointer,
7335 gst_value_collect_list_or_array,
7336 (char *) "p", gst_value_lcopy_list_or_array
7339 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
7341 static const GTypeValueTable _gst_fraction_value_table = {
7342 gst_value_init_fraction,
7344 gst_value_copy_fraction,
7347 gst_value_collect_fraction, (char *) "pp", gst_value_lcopy_fraction
7350 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
7352 static const GTypeValueTable _gst_bitmask_value_table = {
7353 gst_value_init_bitmask,
7355 gst_value_copy_bitmask,
7358 gst_value_collect_bitmask, (char *) "p", gst_value_lcopy_bitmask
7361 FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
7363 static const GTypeValueTable _gst_flagset_value_table = {
7364 gst_value_init_flagset,
7366 gst_value_copy_flagset,
7369 gst_value_collect_flagset, (char *) "pp", gst_value_lcopy_flagset
7372 FUNC_VALUE_GET_TYPE_CLASSED (flagset, "GstFlagSet",
7373 sizeof (GstFlagSetClass), G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE);
7376 gst_g_thread_get_type (void)
7378 return G_TYPE_THREAD;
7381 #define SERIAL_VTABLE(t,c,s,d) { t, c, s, d }
7383 #define REGISTER_SERIALIZATION_CONST(_gtype, _type) \
7385 static const GstValueTable gst_value = \
7386 SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \
7387 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7388 gst_value_register (&gst_value); \
7391 #define REGISTER_SERIALIZATION(_gtype, _type) \
7393 static GstValueTable gst_value = \
7394 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7395 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7396 gst_value.type = _gtype; \
7397 gst_value_register (&gst_value); \
7400 #define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type) \
7402 static GstValueTable gst_value = \
7403 SERIAL_VTABLE (0, NULL, \
7404 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7405 gst_value.type = _gtype; \
7406 gst_value_register (&gst_value); \
7409 #define REGISTER_SERIALIZATION_COMPARE_ONLY(_gtype, _type) \
7411 static GstValueTable gst_value = \
7412 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7414 gst_value.type = _gtype; \
7415 gst_value_register (&gst_value); \
7418 /* These initial sizes are used for the tables
7419 * below, and save a couple of reallocs at startup */
7421 static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 35;
7422 static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 4;
7423 static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 11;
7424 static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 12;
7427 _priv_gst_value_initialize (void)
7430 g_array_sized_new (FALSE, FALSE, sizeof (GstValueTable),
7431 GST_VALUE_TABLE_DEFAULT_SIZE);
7432 gst_value_hash = g_hash_table_new (NULL, NULL);
7433 gst_value_union_funcs = g_array_sized_new (FALSE, FALSE,
7434 sizeof (GstValueUnionInfo), GST_VALUE_UNION_TABLE_DEFAULT_SIZE);
7435 gst_value_intersect_funcs = g_array_sized_new (FALSE, FALSE,
7436 sizeof (GstValueIntersectInfo), GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE);
7437 gst_value_subtract_funcs = g_array_sized_new (FALSE, FALSE,
7438 sizeof (GstValueSubtractInfo), GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE);
7440 REGISTER_SERIALIZATION (gst_int_range_get_type (), int_range);
7441 REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range);
7442 REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range);
7443 REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range);
7444 REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list);
7445 REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array);
7446 REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array);
7447 REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer);
7448 REGISTER_SERIALIZATION (gst_sample_get_type (), sample);
7449 REGISTER_SERIALIZATION (gst_fraction_get_type (), fraction);
7450 REGISTER_SERIALIZATION (gst_caps_get_type (), caps);
7451 REGISTER_SERIALIZATION (gst_tag_list_get_type (), tag_list);
7452 REGISTER_SERIALIZATION (G_TYPE_DATE, date);
7453 REGISTER_SERIALIZATION (gst_date_time_get_type (), date_time);
7454 REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask);
7455 REGISTER_SERIALIZATION (gst_structure_get_type (), structure);
7456 REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset);
7458 REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment);
7459 REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (),
7462 REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (),
7464 REGISTER_SERIALIZATION_COMPARE_ONLY (G_TYPE_OBJECT, object);
7466 REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double);
7467 REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float);
7469 REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string);
7470 REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean);
7471 REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum);
7473 REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags);
7475 REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int);
7477 REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64);
7478 REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long);
7480 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint);
7481 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64);
7482 REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong);
7484 REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar);
7486 REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
7488 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
7489 gst_value_transform_int_range_string);
7490 g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING,
7491 gst_value_transform_int64_range_string);
7492 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
7493 gst_value_transform_double_range_string);
7494 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
7495 gst_value_transform_fraction_range_string);
7496 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
7497 gst_value_transform_list_string);
7498 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
7499 gst_value_transform_array_string);
7500 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, G_TYPE_STRING,
7501 gst_value_transform_g_value_array_string);
7502 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
7503 gst_value_transform_fraction_string);
7504 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
7505 gst_value_transform_string_fraction);
7506 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
7507 gst_value_transform_fraction_double);
7508 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT,
7509 gst_value_transform_fraction_float);
7510 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
7511 gst_value_transform_double_fraction);
7512 g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
7513 gst_value_transform_float_fraction);
7514 g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING,
7515 gst_value_transform_date_string);
7516 g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE,
7517 gst_value_transform_string_date);
7518 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
7519 gst_value_transform_object_string);
7520 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
7521 gst_value_transform_bitmask_uint64);
7522 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
7523 gst_value_transform_bitmask_string);
7524 g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
7525 gst_value_transform_uint64_bitmask);
7526 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
7527 gst_value_transform_string_bitmask);
7529 g_value_register_transform_func (GST_TYPE_FLAG_SET, G_TYPE_STRING,
7530 gst_value_transform_flagset_string);
7531 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
7532 gst_value_transform_string_flagset);
7534 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7535 gst_value_intersect_int_int_range);
7536 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7537 gst_value_intersect_int_range_int_range);
7538 gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7539 gst_value_intersect_int64_int64_range);
7540 gst_value_register_intersect_func (GST_TYPE_INT64_RANGE,
7541 GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range);
7542 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7543 gst_value_intersect_double_double_range);
7544 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
7545 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
7546 gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY,
7547 gst_value_intersect_array);
7548 gst_value_register_intersect_func (GST_TYPE_FRACTION,
7549 GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range);
7550 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
7551 GST_TYPE_FRACTION_RANGE,
7552 gst_value_intersect_fraction_range_fraction_range);
7553 gst_value_register_intersect_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7554 gst_value_intersect_flagset_flagset);
7555 gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7556 gst_value_intersect_structure_structure);
7558 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7559 gst_value_subtract_int_int_range);
7560 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
7561 gst_value_subtract_int_range_int);
7562 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7563 gst_value_subtract_int_range_int_range);
7564 gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7565 gst_value_subtract_int64_int64_range);
7566 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64,
7567 gst_value_subtract_int64_range_int64);
7568 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE,
7569 GST_TYPE_INT64_RANGE, gst_value_subtract_int64_range_int64_range);
7570 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7571 gst_value_subtract_double_double_range);
7572 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
7573 gst_value_subtract_double_range_double);
7574 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
7575 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
7576 gst_value_register_subtract_func (GST_TYPE_FRACTION,
7577 GST_TYPE_FRACTION_RANGE, gst_value_subtract_fraction_fraction_range);
7578 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7579 GST_TYPE_FRACTION, gst_value_subtract_fraction_range_fraction);
7580 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7581 GST_TYPE_FRACTION_RANGE,
7582 gst_value_subtract_fraction_range_fraction_range);
7584 /* see bug #317246, #64994, #65041 */
7586 volatile GType date_type = G_TYPE_DATE;
7588 g_type_name (date_type);
7591 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7592 gst_value_union_int_int_range);
7593 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7594 gst_value_union_int_range_int_range);
7595 gst_value_register_union_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7596 gst_value_union_flagset_flagset);
7597 gst_value_register_union_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7598 gst_value_union_structure_structure);
7600 #if GST_VERSION_NANO == 1
7601 /* If building from git master, check starting array sizes matched actual size
7602 * so we can keep the defines in sync and save a few reallocs on startup */
7603 if (gst_value_table->len != GST_VALUE_TABLE_DEFAULT_SIZE) {
7604 GST_ERROR ("Wrong initial gst_value_table size. "
7605 "Please set GST_VALUE_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7606 gst_value_table->len);
7608 if (gst_value_union_funcs->len != GST_VALUE_UNION_TABLE_DEFAULT_SIZE) {
7609 GST_ERROR ("Wrong initial gst_value_union_funcs table size. "
7610 "Please set GST_VALUE_UNION_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7611 gst_value_union_funcs->len);
7613 if (gst_value_intersect_funcs->len != GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE) {
7614 GST_ERROR ("Wrong initial gst_value_intersect_funcs table size. "
7615 "Please set GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7616 gst_value_intersect_funcs->len);
7618 if (gst_value_subtract_funcs->len != GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE) {
7619 GST_ERROR ("Wrong initial gst_value_subtract_funcs table size. "
7620 "Please set GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7621 gst_value_subtract_funcs->len);
7626 /* Implement these if needed */
7627 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
7628 gst_value_union_fraction_fraction_range);
7629 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
7630 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);
7635 gst_flagset_class_init (gpointer g_class, gpointer class_data)
7637 GstFlagSetClass *f_class = (GstFlagSetClass *) (g_class);
7638 f_class->flags_type = (GType) GPOINTER_TO_SIZE (class_data);
7642 * gst_flagset_register:
7643 * @flags_type: a #GType of a #G_TYPE_FLAGS type.
7645 * Create a new sub-class of #GST_TYPE_FLAG_SET
7646 * which will pretty-print the human-readable flags
7647 * when serializing, for easier debugging.
7652 gst_flagset_register (GType flags_type)
7655 sizeof (GstFlagSetClass),
7657 (GClassInitFunc) gst_flagset_class_init,
7658 NULL, GSIZE_TO_POINTER (flags_type), 0, 0, NULL, NULL
7663 g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0);
7665 class_name = g_strdup_printf ("%sSet", g_type_name (flags_type));
7667 t = g_type_register_static (GST_TYPE_FLAG_SET,
7668 g_intern_string (class_name), &info, 0);
7669 g_free (class_name);