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;
282 alen = array->n_values;
284 /* estimate minimum string length to minimise re-allocs in GString */
285 s = g_string_sized_new (2 + (6 * alen) + 2);
286 g_string_append (s, begin);
287 for (i = 0; i < alen; i++) {
288 v = g_value_array_get_nth (array, i);
289 s_val = gst_value_serialize (v);
291 g_string_append (s, s_val);
294 g_string_append_len (s, ", ", 2);
297 GST_WARNING ("Could not serialize list/array value of type '%s'",
298 G_VALUE_TYPE_NAME (v));
301 g_string_append (s, end);
302 return g_string_free (s, FALSE);
306 _gst_value_transform_g_value_array_string (const GValue * src_value,
307 GValue * dest_value, const gchar * begin, const gchar * end)
316 array = src_value->data[0].v_pointer;
317 alen = array->n_values;
319 /* estimate minimum string length to minimise re-allocs in GString */
320 s = g_string_sized_new (2 + (10 * alen) + 2);
321 g_string_append (s, begin);
322 for (i = 0; i < alen; i++) {
323 list_value = g_value_array_get_nth (array, i);
326 g_string_append_len (s, ", ", 2);
328 list_s = g_strdup_value_contents (list_value);
329 g_string_append (s, list_s);
332 g_string_append (s, end);
334 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
338 * helper function to see if a type is fixed. Is used internally here and
339 * there. Do not export, since it doesn't work for types where the content
340 * decides the fixedness (e.g. GST_TYPE_ARRAY).
343 gst_type_is_fixed (GType type)
345 /* the basic int, string, double types */
346 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
349 /* our fundamental types that are certainly not fixed */
350 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
351 type == GST_TYPE_INT64_RANGE ||
352 type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE ||
353 type == GST_TYPE_STRUCTURE) {
356 /* other (boxed) types that are fixed */
357 if (type == GST_TYPE_BUFFER) {
361 if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
362 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
369 /* GValue functions usable for both regular lists and arrays */
371 gst_value_init_list_or_array (GValue * value)
373 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
377 copy_garray_of_gstvalue (const GArray * src)
383 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
384 g_array_set_size (dest, len);
385 for (i = 0; i < len; i++) {
386 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
387 &g_array_index (src, GValue, i));
394 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
396 dest_value->data[0].v_pointer =
397 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
401 gst_value_free_list_or_array (GValue * value)
404 GArray *src = (GArray *) value->data[0].v_pointer;
407 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
408 for (i = 0; i < len; i++) {
409 g_value_unset (&g_array_index (src, GValue, i));
411 g_array_free (src, TRUE);
416 gst_value_list_or_array_peek_pointer (const GValue * value)
418 return value->data[0].v_pointer;
422 gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
423 GTypeCValue * collect_values, guint collect_flags)
425 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
426 value->data[0].v_pointer = collect_values[0].v_pointer;
427 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
429 value->data[0].v_pointer =
430 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
436 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
437 GTypeCValue * collect_values, guint collect_flags)
439 GArray **dest = collect_values[0].v_pointer;
442 return g_strdup_printf ("value location for `%s' passed as NULL",
443 G_VALUE_TYPE_NAME (value));
444 if (!value->data[0].v_pointer)
445 return g_strdup_printf ("invalid value given for `%s'",
446 G_VALUE_TYPE_NAME (value));
447 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
448 *dest = (GArray *) value->data[0].v_pointer;
450 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
456 gst_value_list_or_array_get_basic_type (const GValue * value, GType * type)
458 if (G_UNLIKELY (value == NULL))
461 if (GST_VALUE_HOLDS_LIST (value)) {
462 if (VALUE_LIST_SIZE (value) == 0)
464 return gst_value_list_or_array_get_basic_type (VALUE_LIST_GET_VALUE (value,
467 if (GST_VALUE_HOLDS_ARRAY (value)) {
468 const GArray *array = (const GArray *) value->data[0].v_pointer;
471 return gst_value_list_or_array_get_basic_type (&g_array_index (array,
475 *type = G_VALUE_TYPE (value);
480 #define IS_RANGE_COMPAT(type1,type2,t1,t2) \
481 (((t1) == (type1) && (t2) == (type2)) || ((t2) == (type1) && (t1) == (type2)))
484 gst_value_list_or_array_are_compatible (const GValue * value1,
485 const GValue * value2)
487 GType basic_type1, basic_type2;
489 /* empty or same type is OK */
490 if (!gst_value_list_or_array_get_basic_type (value1, &basic_type1) ||
491 !gst_value_list_or_array_get_basic_type (value2, &basic_type2) ||
492 basic_type1 == basic_type2)
495 /* ranges are distinct types for each bound type... */
496 if (IS_RANGE_COMPAT (G_TYPE_INT, GST_TYPE_INT_RANGE, basic_type1,
499 if (IS_RANGE_COMPAT (G_TYPE_INT64, GST_TYPE_INT64_RANGE, basic_type1,
502 if (IS_RANGE_COMPAT (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, basic_type1,
505 if (IS_RANGE_COMPAT (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, basic_type1,
513 _gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
515 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
516 memset (append_value, 0, sizeof (GValue));
520 * gst_value_list_append_and_take_value:
521 * @value: a #GValue of type #GST_TYPE_LIST
522 * @append_value: (transfer full): the value to append
524 * Appends @append_value to the GstValueList in @value.
529 gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
531 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
532 g_return_if_fail (G_IS_VALUE (append_value));
533 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
536 _gst_value_list_append_and_take_value (value, append_value);
540 * gst_value_list_append_value:
541 * @value: a #GValue of type #GST_TYPE_LIST
542 * @append_value: (transfer none): the value to append
544 * Appends @append_value to the GstValueList in @value.
547 gst_value_list_append_value (GValue * value, const GValue * append_value)
551 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
552 g_return_if_fail (G_IS_VALUE (append_value));
553 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
556 gst_value_init_and_copy (&val, append_value);
557 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
561 * gst_value_list_prepend_value:
562 * @value: a #GValue of type #GST_TYPE_LIST
563 * @prepend_value: the value to prepend
565 * Prepends @prepend_value to the GstValueList in @value.
568 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
572 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
573 g_return_if_fail (G_IS_VALUE (prepend_value));
574 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
577 gst_value_init_and_copy (&val, prepend_value);
578 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
582 * gst_value_list_concat:
583 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
587 * Concatenates copies of @value1 and @value2 into a list. Values that are not
588 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
589 * @dest will be initialized to the type #GST_TYPE_LIST.
592 gst_value_list_concat (GValue * dest, const GValue * value1,
593 const GValue * value2)
595 guint i, value1_length, value2_length;
598 g_return_if_fail (dest != NULL);
599 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
600 g_return_if_fail (G_IS_VALUE (value1));
601 g_return_if_fail (G_IS_VALUE (value2));
602 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
605 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
607 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
608 g_value_init (dest, GST_TYPE_LIST);
609 array = (GArray *) dest->data[0].v_pointer;
610 g_array_set_size (array, value1_length + value2_length);
612 if (GST_VALUE_HOLDS_LIST (value1)) {
613 for (i = 0; i < value1_length; i++) {
614 gst_value_init_and_copy (&g_array_index (array, GValue, i),
615 VALUE_LIST_GET_VALUE (value1, i));
618 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
621 if (GST_VALUE_HOLDS_LIST (value2)) {
622 for (i = 0; i < value2_length; i++) {
623 gst_value_init_and_copy (&g_array_index (array, GValue,
624 i + value1_length), VALUE_LIST_GET_VALUE (value2, i));
627 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
632 /* same as gst_value_list_concat() but takes ownership of GValues */
634 gst_value_list_concat_and_take_values (GValue * dest, GValue * val1,
637 guint i, val1_length, val2_length;
638 gboolean val1_is_list;
639 gboolean val2_is_list;
642 g_assert (dest != NULL);
643 g_assert (G_VALUE_TYPE (dest) == 0);
644 g_assert (G_IS_VALUE (val1));
645 g_assert (G_IS_VALUE (val2));
646 g_assert (gst_value_list_or_array_are_compatible (val1, val2));
648 val1_is_list = GST_VALUE_HOLDS_LIST (val1);
649 val1_length = (val1_is_list ? VALUE_LIST_SIZE (val1) : 1);
651 val2_is_list = GST_VALUE_HOLDS_LIST (val2);
652 val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1);
654 g_value_init (dest, GST_TYPE_LIST);
655 array = (GArray *) dest->data[0].v_pointer;
656 g_array_set_size (array, val1_length + val2_length);
659 for (i = 0; i < val1_length; i++) {
660 g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i);
662 g_array_set_size (VALUE_LIST_ARRAY (val1), 0);
663 g_value_unset (val1);
665 g_array_index (array, GValue, 0) = *val1;
666 G_VALUE_TYPE (val1) = G_TYPE_INVALID;
670 for (i = 0; i < val2_length; i++) {
671 const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i);
672 g_array_index (array, GValue, i + val1_length) = *v2;
674 g_array_set_size (VALUE_LIST_ARRAY (val2), 0);
675 g_value_unset (val2);
677 g_array_index (array, GValue, val1_length) = *val2;
678 G_VALUE_TYPE (val2) = G_TYPE_INVALID;
683 * gst_value_list_merge:
684 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
688 * Merges copies of @value1 and @value2. Values that are not
689 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
691 * The result will be put into @dest and will either be a list that will not
692 * contain any duplicates, or a non-list type (if @value1 and @value2
696 gst_value_list_merge (GValue * dest, const GValue * value1,
697 const GValue * value2)
699 guint i, j, k, value1_length, value2_length, skipped;
704 g_return_if_fail (dest != NULL);
705 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
706 g_return_if_fail (G_IS_VALUE (value1));
707 g_return_if_fail (G_IS_VALUE (value2));
708 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
711 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
713 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
714 g_value_init (dest, GST_TYPE_LIST);
715 array = (GArray *) dest->data[0].v_pointer;
716 g_array_set_size (array, value1_length + value2_length);
718 if (GST_VALUE_HOLDS_LIST (value1)) {
719 for (i = 0; i < value1_length; i++) {
720 gst_value_init_and_copy (&g_array_index (array, GValue, i),
721 VALUE_LIST_GET_VALUE (value1, i));
724 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
729 if (GST_VALUE_HOLDS_LIST (value2)) {
730 for (i = 0; i < value2_length; i++) {
732 src = VALUE_LIST_GET_VALUE (value2, i);
733 for (k = 0; k < value1_length; k++) {
734 if (gst_value_compare (&g_array_index (array, GValue, k),
735 src) == GST_VALUE_EQUAL) {
742 gst_value_init_and_copy (&g_array_index (array, GValue, j), src);
748 for (k = 0; k < value1_length; k++) {
749 if (gst_value_compare (&g_array_index (array, GValue, k),
750 value2) == GST_VALUE_EQUAL) {
757 gst_value_init_and_copy (&g_array_index (array, GValue, j), value2);
761 guint new_size = value1_length + (value2_length - skipped);
765 g_array_set_size (array, new_size);
769 /* size is 1, take single value in list and make it new dest */
770 single_dest = g_array_index (array, GValue, 0);
772 /* clean up old value allocations: must set array size to 0, because
773 * allocated values are not inited meaning g_value_unset() will not
775 g_array_set_size (array, 0);
776 g_value_unset (dest);
778 /* the single value is our new result */
785 * gst_value_list_get_size:
786 * @value: a #GValue of type #GST_TYPE_LIST
788 * Gets the number of values contained in @value.
790 * Returns: the number of values
793 gst_value_list_get_size (const GValue * value)
795 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
797 return ((GArray *) value->data[0].v_pointer)->len;
801 * gst_value_list_get_value:
802 * @value: a #GValue of type #GST_TYPE_LIST
803 * @index: index of value to get from the list
805 * Gets the value that is a member of the list contained in @value and
806 * has the index @index.
808 * Returns: (transfer none): the value at the given index
811 gst_value_list_get_value (const GValue * value, guint index)
813 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
814 g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL);
816 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
821 * gst_value_array_append_value:
822 * @value: a #GValue of type #GST_TYPE_ARRAY
823 * @append_value: the value to append
825 * Appends @append_value to the GstValueArray in @value.
828 gst_value_array_append_value (GValue * value, const GValue * append_value)
832 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
833 g_return_if_fail (G_IS_VALUE (append_value));
834 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
837 gst_value_init_and_copy (&val, append_value);
838 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
842 _gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
844 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
845 memset (append_value, 0, sizeof (GValue));
849 * gst_value_array_append_and_take_value:
850 * @value: a #GValue of type #GST_TYPE_ARRAY
851 * @append_value: (transfer full): the value to append
853 * Appends @append_value to the GstValueArray in @value.
858 gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
860 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
861 g_return_if_fail (G_IS_VALUE (append_value));
862 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
865 _gst_value_array_append_and_take_value (value, append_value);
869 * gst_value_array_prepend_value:
870 * @value: a #GValue of type #GST_TYPE_ARRAY
871 * @prepend_value: the value to prepend
873 * Prepends @prepend_value to the GstValueArray in @value.
876 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
880 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
881 g_return_if_fail (G_IS_VALUE (prepend_value));
882 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
885 gst_value_init_and_copy (&val, prepend_value);
886 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
890 * gst_value_array_get_size:
891 * @value: a #GValue of type #GST_TYPE_ARRAY
893 * Gets the number of values contained in @value.
895 * Returns: the number of values
898 gst_value_array_get_size (const GValue * value)
900 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
902 return ((GArray *) value->data[0].v_pointer)->len;
906 * gst_value_array_get_value:
907 * @value: a #GValue of type #GST_TYPE_ARRAY
908 * @index: index of value to get from the array
910 * Gets the value that is a member of the array contained in @value and
911 * has the index @index.
913 * Returns: (transfer none): the value at the given index
916 gst_value_array_get_value (const GValue * value, guint index)
918 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
919 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
921 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
926 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
928 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
932 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
934 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
938 gst_value_transform_g_value_array_string (const GValue * src_value,
941 _gst_value_transform_g_value_array_string (src_value, dest_value, "< ", " >");
945 gst_value_transform_g_value_array_any_list (const GValue * src_value,
948 const GValueArray *varray;
952 /* GLib will unset the value, memset to 0 the data instead of doing a proper
953 * reset. That's why we need to allocate the array here */
954 gst_value_init_list_or_array (dest_value);
956 varray = g_value_get_boxed (src_value);
957 array = dest_value->data[0].v_pointer;
959 for (i = 0; i < varray->n_values; i++) {
960 GValue val = G_VALUE_INIT;
961 gst_value_init_and_copy (&val, &varray->values[i]);
962 g_array_append_vals (array, &val, 1);
967 gst_value_transform_any_list_g_value_array (const GValue * src_value,
974 array = src_value->data[0].v_pointer;
975 varray = g_value_array_new (array->len);
977 for (i = 0; i < array->len; i++)
978 g_value_array_append (varray, &g_array_index (array, GValue, i));
980 g_value_take_boxed (dest_value, varray);
983 /* Do an unordered compare of the contents of a list */
985 gst_value_compare_value_list (const GValue * value1, const GValue * value2)
988 GArray *array1 = value1->data[0].v_pointer;
989 GArray *array2 = value2->data[0].v_pointer;
994 GstValueCompareFunc compare;
996 /* get length and do initial length check. */
998 if (len != array2->len)
999 return GST_VALUE_UNORDERED;
1001 /* place to mark removed value indices of array2 */
1002 removed = g_newa (guint8, len);
1003 memset (removed, 0, len);
1006 /* loop over array1, all items should be in array2. When we find an
1007 * item in array2, remove it from array2 by marking it as removed */
1008 for (i = 0; i < len; i++) {
1009 v1 = &g_array_index (array1, GValue, i);
1010 if ((compare = gst_value_get_compare_func (v1))) {
1011 for (j = 0; j < len; j++) {
1012 /* item is removed, we can skip it */
1015 v2 = &g_array_index (array2, GValue, j);
1016 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
1017 /* mark item as removed now that we found it in array2 and
1018 * decrement the number of remaining items in array2. */
1024 /* item in array1 and not in array2, UNORDERED */
1026 return GST_VALUE_UNORDERED;
1028 return GST_VALUE_UNORDERED;
1030 /* if not all items were removed, array2 contained something not in array1 */
1032 return GST_VALUE_UNORDERED;
1034 /* arrays are equal */
1035 return GST_VALUE_EQUAL;
1038 /* Perform an ordered comparison of the contents of an array */
1040 gst_value_compare_value_array (const GValue * value1, const GValue * value2)
1043 GArray *array1 = value1->data[0].v_pointer;
1044 GArray *array2 = value2->data[0].v_pointer;
1045 guint len = array1->len;
1049 if (len != array2->len)
1050 return GST_VALUE_UNORDERED;
1052 for (i = 0; i < len; i++) {
1053 v1 = &g_array_index (array1, GValue, i);
1054 v2 = &g_array_index (array2, GValue, i);
1055 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1056 return GST_VALUE_UNORDERED;
1059 return GST_VALUE_EQUAL;
1063 gst_value_compare_g_value_array (const GValue * value1, const GValue * value2)
1066 GValueArray *array1 = value1->data[0].v_pointer;
1067 GValueArray *array2 = value2->data[0].v_pointer;
1068 guint len = array1->n_values;
1072 if (len != array2->n_values)
1073 return GST_VALUE_UNORDERED;
1075 for (i = 0; i < len; i++) {
1076 v1 = g_value_array_get_nth (array1, i);
1077 v2 = g_value_array_get_nth (array2, i);
1078 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1079 return GST_VALUE_UNORDERED;
1082 return GST_VALUE_EQUAL;
1086 gst_value_serialize_value_list (const GValue * value)
1088 return _priv_gst_value_serialize_any_list (value, "{ ", " }", TRUE);
1092 gst_value_deserialize_value_list (GValue * dest, const gchar * s)
1094 gchar *s2 = (gchar *) s;
1095 return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID);
1099 gst_value_serialize_value_array (const GValue * value)
1101 return _priv_gst_value_serialize_any_list (value, "< ", " >", TRUE);
1105 gst_value_deserialize_value_array (GValue * dest, const gchar * s)
1107 gchar *s2 = (gchar *) s;
1108 return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID);
1112 gst_value_serialize_g_value_array (const GValue * value)
1114 return _gst_value_serialize_g_value_array (value, "< ", " >");
1118 gst_value_deserialize_g_value_array (GValue * dest, const gchar * s)
1120 g_warning ("gst_value_deserialize_g_value_array: unimplemented");
1127 * Values in the range are defined as any value greater or equal
1128 * to min*step, AND lesser or equal to max*step.
1129 * For step == 1, this falls back to the traditional range semantics.
1131 * data[0] = (min << 32) | (max)
1136 #define INT_RANGE_MIN(v) ((gint) (((v)->data[0].v_uint64) >> 32))
1137 #define INT_RANGE_MAX(v) ((gint) (((v)->data[0].v_uint64) & 0xffffffff))
1138 #define INT_RANGE_STEP(v) ((v)->data[1].v_int)
1141 gst_value_init_int_range (GValue * value)
1143 G_STATIC_ASSERT (sizeof (gint) <= 2 * sizeof (guint64));
1145 value->data[0].v_uint64 = 0;
1146 value->data[1].v_int = 1;
1150 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
1152 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
1153 dest_value->data[1].v_int = src_value->data[1].v_int;
1157 gst_value_collect_int_range (GValue * value, guint n_collect_values,
1158 GTypeCValue * collect_values, guint collect_flags)
1160 if (n_collect_values != 2)
1161 return g_strdup_printf ("not enough value locations for `%s' passed",
1162 G_VALUE_TYPE_NAME (value));
1163 if (collect_values[0].v_int >= collect_values[1].v_int)
1164 return g_strdup_printf ("range start is not smaller than end for `%s'",
1165 G_VALUE_TYPE_NAME (value));
1167 gst_value_set_int_range_step (value, collect_values[0].v_int,
1168 collect_values[1].v_int, 1);
1174 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
1175 GTypeCValue * collect_values, guint collect_flags)
1177 guint32 *int_range_start = collect_values[0].v_pointer;
1178 guint32 *int_range_end = collect_values[1].v_pointer;
1180 if (!int_range_start)
1181 return g_strdup_printf ("start value location for `%s' passed as NULL",
1182 G_VALUE_TYPE_NAME (value));
1184 return g_strdup_printf ("end value location for `%s' passed as NULL",
1185 G_VALUE_TYPE_NAME (value));
1187 *int_range_start = INT_RANGE_MIN (value);
1188 *int_range_end = INT_RANGE_MAX (value);
1194 * gst_value_set_int_range_step:
1195 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1196 * @start: the start of the range
1197 * @end: the end of the range
1198 * @step: the step of the range
1200 * Sets @value to the range specified by @start, @end and @step.
1203 gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step)
1205 guint64 sstart, sstop;
1207 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
1208 g_return_if_fail (start < end);
1209 g_return_if_fail (step > 0);
1210 g_return_if_fail (start % step == 0);
1211 g_return_if_fail (end % step == 0);
1213 sstart = (guint) (start / step);
1214 sstop = (guint) (end / step);
1215 value->data[0].v_uint64 = (sstart << 32) | sstop;
1216 value->data[1].v_int = step;
1220 * gst_value_set_int_range:
1221 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1222 * @start: the start of the range
1223 * @end: the end of the range
1225 * Sets @value to the range specified by @start and @end.
1228 gst_value_set_int_range (GValue * value, gint start, gint end)
1230 gst_value_set_int_range_step (value, start, end, 1);
1234 * gst_value_get_int_range_min:
1235 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1237 * Gets the minimum of the range specified by @value.
1239 * Returns: the minimum of the range
1242 gst_value_get_int_range_min (const GValue * value)
1244 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1246 return INT_RANGE_MIN (value) * INT_RANGE_STEP (value);
1250 * gst_value_get_int_range_max:
1251 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1253 * Gets the maximum of the range specified by @value.
1255 * Returns: the maximum of the range
1258 gst_value_get_int_range_max (const GValue * value)
1260 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1262 return INT_RANGE_MAX (value) * INT_RANGE_STEP (value);
1266 * gst_value_get_int_range_step:
1267 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1269 * Gets the step of the range specified by @value.
1271 * Returns: the step of the range
1274 gst_value_get_int_range_step (const GValue * value)
1276 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1278 return INT_RANGE_STEP (value);
1282 gst_value_transform_int_range_string (const GValue * src_value,
1283 GValue * dest_value)
1285 if (INT_RANGE_STEP (src_value) == 1)
1286 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
1287 INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value));
1289 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]",
1290 INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value),
1291 INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value),
1292 INT_RANGE_STEP (src_value));
1296 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
1298 /* calculate the number of values in each range */
1299 gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1;
1300 gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1;
1302 /* they must be equal */
1304 return GST_VALUE_UNORDERED;
1306 /* if empty, equal */
1308 return GST_VALUE_EQUAL;
1310 /* if more than one value, then it is only equal if the step is equal
1311 and bounds lie on the same value */
1313 if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
1314 INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) &&
1315 INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) {
1316 return GST_VALUE_EQUAL;
1318 return GST_VALUE_UNORDERED;
1320 /* if just one, only if the value is equal */
1321 if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2))
1322 return GST_VALUE_EQUAL;
1323 return GST_VALUE_UNORDERED;
1328 gst_value_serialize_int_range (const GValue * value)
1330 if (INT_RANGE_STEP (value) == 1)
1331 return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value),
1332 INT_RANGE_MAX (value));
1334 return g_strdup_printf ("[ %d, %d, %d ]",
1335 INT_RANGE_MIN (value) * INT_RANGE_STEP (value),
1336 INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value));
1340 gst_value_deserialize_int_range (GValue * dest, const gchar * s)
1342 g_warning ("unimplemented");
1349 * Values in the range are defined as any value greater or equal
1350 * to min*step, AND lesser or equal to max*step.
1351 * For step == 1, this falls back to the traditional range semantics.
1354 #define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0])
1355 #define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1])
1356 #define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2])
1359 gst_value_init_int64_range (GValue * value)
1361 gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64));
1362 value->data[0].v_pointer = vals;
1363 INT64_RANGE_MIN (value) = 0;
1364 INT64_RANGE_MAX (value) = 0;
1365 INT64_RANGE_STEP (value) = 1;
1369 gst_value_free_int64_range (GValue * value)
1371 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1372 g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer);
1373 value->data[0].v_pointer = NULL;
1377 gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value)
1379 gint64 *vals = (gint64 *) dest_value->data[0].v_pointer;
1380 gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer;
1383 gst_value_init_int64_range (dest_value);
1386 if (src_vals != NULL) {
1387 INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value);
1388 INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value);
1389 INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value);
1394 gst_value_collect_int64_range (GValue * value, guint n_collect_values,
1395 GTypeCValue * collect_values, guint collect_flags)
1397 gint64 *vals = value->data[0].v_pointer;
1399 if (n_collect_values != 2)
1400 return g_strdup_printf ("not enough value locations for `%s' passed",
1401 G_VALUE_TYPE_NAME (value));
1402 if (collect_values[0].v_int64 >= collect_values[1].v_int64)
1403 return g_strdup_printf ("range start is not smaller than end for `%s'",
1404 G_VALUE_TYPE_NAME (value));
1407 gst_value_init_int64_range (value);
1410 gst_value_set_int64_range_step (value, collect_values[0].v_int64,
1411 collect_values[1].v_int64, 1);
1417 gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
1418 GTypeCValue * collect_values, guint collect_flags)
1420 guint64 *int_range_start = collect_values[0].v_pointer;
1421 guint64 *int_range_end = collect_values[1].v_pointer;
1422 guint64 *int_range_step = collect_values[2].v_pointer;
1423 gint64 *vals = (gint64 *) value->data[0].v_pointer;
1425 if (!int_range_start)
1426 return g_strdup_printf ("start value location for `%s' passed as NULL",
1427 G_VALUE_TYPE_NAME (value));
1429 return g_strdup_printf ("end value location for `%s' passed as NULL",
1430 G_VALUE_TYPE_NAME (value));
1431 if (!int_range_step)
1432 return g_strdup_printf ("step value location for `%s' passed as NULL",
1433 G_VALUE_TYPE_NAME (value));
1435 if (G_UNLIKELY (vals == NULL)) {
1436 return g_strdup_printf ("Uninitialised `%s' passed",
1437 G_VALUE_TYPE_NAME (value));
1440 *int_range_start = INT64_RANGE_MIN (value);
1441 *int_range_end = INT64_RANGE_MAX (value);
1442 *int_range_step = INT64_RANGE_STEP (value);
1448 * gst_value_set_int64_range_step:
1449 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1450 * @start: the start of the range
1451 * @end: the end of the range
1452 * @step: the step of the range
1454 * Sets @value to the range specified by @start, @end and @step.
1457 gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end,
1460 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1461 g_return_if_fail (start < end);
1462 g_return_if_fail (step > 0);
1463 g_return_if_fail (start % step == 0);
1464 g_return_if_fail (end % step == 0);
1466 INT64_RANGE_MIN (value) = start / step;
1467 INT64_RANGE_MAX (value) = end / step;
1468 INT64_RANGE_STEP (value) = step;
1472 * gst_value_set_int64_range:
1473 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1474 * @start: the start of the range
1475 * @end: the end of the range
1477 * Sets @value to the range specified by @start and @end.
1480 gst_value_set_int64_range (GValue * value, gint64 start, gint64 end)
1482 gst_value_set_int64_range_step (value, start, end, 1);
1486 * gst_value_get_int64_range_min:
1487 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1489 * Gets the minimum of the range specified by @value.
1491 * Returns: the minimum of the range
1494 gst_value_get_int64_range_min (const GValue * value)
1496 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1498 return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value);
1502 * gst_value_get_int64_range_max:
1503 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1505 * Gets the maximum of the range specified by @value.
1507 * Returns: the maximum of the range
1510 gst_value_get_int64_range_max (const GValue * value)
1512 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1514 return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value);
1518 * gst_value_get_int64_range_step:
1519 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1521 * Gets the step of the range specified by @value.
1523 * Returns: the step of the range
1526 gst_value_get_int64_range_step (const GValue * value)
1528 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1530 return INT64_RANGE_STEP (value);
1534 gst_value_transform_int64_range_string (const GValue * src_value,
1535 GValue * dest_value)
1537 if (INT64_RANGE_STEP (src_value) == 1)
1538 dest_value->data[0].v_pointer =
1539 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]",
1540 INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value));
1542 dest_value->data[0].v_pointer =
1543 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT
1544 ",%" G_GINT64_FORMAT "]",
1545 INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value),
1546 INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value),
1547 INT64_RANGE_STEP (src_value));
1551 gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
1553 /* calculate the number of values in each range */
1554 gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1;
1555 gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1;
1557 /* they must be equal */
1559 return GST_VALUE_UNORDERED;
1561 /* if empty, equal */
1563 return GST_VALUE_EQUAL;
1565 /* if more than one value, then it is only equal if the step is equal
1566 and bounds lie on the same value */
1568 if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
1569 INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) &&
1570 INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) {
1571 return GST_VALUE_EQUAL;
1573 return GST_VALUE_UNORDERED;
1575 /* if just one, only if the value is equal */
1576 if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2))
1577 return GST_VALUE_EQUAL;
1578 return GST_VALUE_UNORDERED;
1583 gst_value_serialize_int64_range (const GValue * value)
1585 if (INT64_RANGE_STEP (value) == 1)
1586 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]",
1587 INT64_RANGE_MIN (value), INT64_RANGE_MAX (value));
1589 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %"
1590 G_GINT64_FORMAT " ]",
1591 INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value),
1592 INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value),
1593 INT64_RANGE_STEP (value));
1597 gst_value_deserialize_int64_range (GValue * dest, const gchar * s)
1599 g_warning ("unimplemented");
1608 gst_value_init_double_range (GValue * value)
1610 value->data[0].v_double = 0;
1611 value->data[1].v_double = 0;
1615 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
1617 dest_value->data[0].v_double = src_value->data[0].v_double;
1618 dest_value->data[1].v_double = src_value->data[1].v_double;
1622 gst_value_collect_double_range (GValue * value, guint n_collect_values,
1623 GTypeCValue * collect_values, guint collect_flags)
1625 if (n_collect_values != 2)
1626 return g_strdup_printf ("not enough value locations for `%s' passed",
1627 G_VALUE_TYPE_NAME (value));
1628 if (collect_values[0].v_double >= collect_values[1].v_double)
1629 return g_strdup_printf ("range start is not smaller than end for `%s'",
1630 G_VALUE_TYPE_NAME (value));
1632 value->data[0].v_double = collect_values[0].v_double;
1633 value->data[1].v_double = collect_values[1].v_double;
1639 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
1640 GTypeCValue * collect_values, guint collect_flags)
1642 gdouble *double_range_start = collect_values[0].v_pointer;
1643 gdouble *double_range_end = collect_values[1].v_pointer;
1645 if (!double_range_start)
1646 return g_strdup_printf ("start value location for `%s' passed as NULL",
1647 G_VALUE_TYPE_NAME (value));
1648 if (!double_range_end)
1649 return g_strdup_printf ("end value location for `%s' passed as NULL",
1650 G_VALUE_TYPE_NAME (value));
1652 *double_range_start = value->data[0].v_double;
1653 *double_range_end = value->data[1].v_double;
1659 * gst_value_set_double_range:
1660 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1661 * @start: the start of the range
1662 * @end: the end of the range
1664 * Sets @value to the range specified by @start and @end.
1667 gst_value_set_double_range (GValue * value, gdouble start, gdouble end)
1669 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
1670 g_return_if_fail (start < end);
1672 value->data[0].v_double = start;
1673 value->data[1].v_double = end;
1677 * gst_value_get_double_range_min:
1678 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1680 * Gets the minimum of the range specified by @value.
1682 * Returns: the minimum of the range
1685 gst_value_get_double_range_min (const GValue * value)
1687 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1689 return value->data[0].v_double;
1693 * gst_value_get_double_range_max:
1694 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1696 * Gets the maximum of the range specified by @value.
1698 * Returns: the maximum of the range
1701 gst_value_get_double_range_max (const GValue * value)
1703 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1705 return value->data[1].v_double;
1709 gst_value_transform_double_range_string (const GValue * src_value,
1710 GValue * dest_value)
1712 gchar s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
1714 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
1715 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
1716 src_value->data[0].v_double),
1717 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
1718 src_value->data[1].v_double));
1722 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
1724 if (value2->data[0].v_double == value1->data[0].v_double &&
1725 value2->data[1].v_double == value1->data[1].v_double)
1726 return GST_VALUE_EQUAL;
1727 return GST_VALUE_UNORDERED;
1731 gst_value_serialize_double_range (const GValue * value)
1733 gchar d1[G_ASCII_DTOSTR_BUF_SIZE];
1734 gchar d2[G_ASCII_DTOSTR_BUF_SIZE];
1736 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1737 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
1738 return g_strdup_printf ("[ %s, %s ]", d1, d2);
1742 gst_value_deserialize_double_range (GValue * dest, const gchar * s)
1744 g_warning ("unimplemented");
1753 gst_value_init_fraction_range (GValue * value)
1758 ftype = GST_TYPE_FRACTION;
1760 value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
1761 g_value_init (&vals[0], ftype);
1762 g_value_init (&vals[1], ftype);
1766 gst_value_free_fraction_range (GValue * value)
1768 GValue *vals = (GValue *) value->data[0].v_pointer;
1771 /* we know the two values contain fractions without internal allocs */
1772 /* g_value_unset (&vals[0]); */
1773 /* g_value_unset (&vals[1]); */
1774 g_slice_free1 (2 * sizeof (GValue), vals);
1775 value->data[0].v_pointer = NULL;
1780 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value)
1782 GValue *vals = (GValue *) dest_value->data[0].v_pointer;
1783 GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
1786 gst_value_init_fraction_range (dest_value);
1787 vals = dest_value->data[0].v_pointer;
1789 if (src_vals != NULL) {
1790 g_value_copy (&src_vals[0], &vals[0]);
1791 g_value_copy (&src_vals[1], &vals[1]);
1796 gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
1797 GTypeCValue * collect_values, guint collect_flags)
1799 GValue *vals = (GValue *) value->data[0].v_pointer;
1801 if (n_collect_values != 4)
1802 return g_strdup_printf ("not enough value locations for `%s' passed",
1803 G_VALUE_TYPE_NAME (value));
1804 if (collect_values[1].v_int == 0)
1805 return g_strdup_printf ("passed '0' as first denominator for `%s'",
1806 G_VALUE_TYPE_NAME (value));
1807 if (collect_values[3].v_int == 0)
1808 return g_strdup_printf ("passed '0' as second denominator for `%s'",
1809 G_VALUE_TYPE_NAME (value));
1810 if (gst_util_fraction_compare (collect_values[0].v_int,
1811 collect_values[1].v_int, collect_values[2].v_int,
1812 collect_values[3].v_int) >= 0)
1813 return g_strdup_printf ("range start is not smaller than end for `%s'",
1814 G_VALUE_TYPE_NAME (value));
1817 gst_value_init_fraction_range (value);
1818 vals = value->data[0].v_pointer;
1821 gst_value_set_fraction (&vals[0], collect_values[0].v_int,
1822 collect_values[1].v_int);
1823 gst_value_set_fraction (&vals[1], collect_values[2].v_int,
1824 collect_values[3].v_int);
1830 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
1831 GTypeCValue * collect_values, guint collect_flags)
1834 gint *dest_values[4];
1835 GValue *vals = (GValue *) value->data[0].v_pointer;
1837 if (G_UNLIKELY (n_collect_values != 4))
1838 return g_strdup_printf ("not enough value locations for `%s' passed",
1839 G_VALUE_TYPE_NAME (value));
1841 for (i = 0; i < 4; i++) {
1842 if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
1843 return g_strdup_printf ("value location for `%s' passed as NULL",
1844 G_VALUE_TYPE_NAME (value));
1846 dest_values[i] = collect_values[i].v_pointer;
1849 if (G_UNLIKELY (vals == NULL)) {
1850 return g_strdup_printf ("Uninitialised `%s' passed",
1851 G_VALUE_TYPE_NAME (value));
1854 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
1855 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
1856 dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
1857 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
1862 * gst_value_set_fraction_range:
1863 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1864 * @start: the start of the range (a GST_TYPE_FRACTION GValue)
1865 * @end: the end of the range (a GST_TYPE_FRACTION GValue)
1867 * Sets @value to the range specified by @start and @end.
1870 gst_value_set_fraction_range (GValue * value, const GValue * start,
1875 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
1876 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start));
1877 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end));
1878 g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int,
1879 start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0);
1881 vals = (GValue *) value->data[0].v_pointer;
1883 gst_value_init_fraction_range (value);
1884 vals = value->data[0].v_pointer;
1886 g_value_copy (start, &vals[0]);
1887 g_value_copy (end, &vals[1]);
1891 * gst_value_set_fraction_range_full:
1892 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1893 * @numerator_start: the numerator start of the range
1894 * @denominator_start: the denominator start of the range
1895 * @numerator_end: the numerator end of the range
1896 * @denominator_end: the denominator end of the range
1898 * Sets @value to the range specified by @numerator_start/@denominator_start
1899 * and @numerator_end/@denominator_end.
1902 gst_value_set_fraction_range_full (GValue * value,
1903 gint numerator_start, gint denominator_start,
1904 gint numerator_end, gint denominator_end)
1906 GValue start = { 0 };
1909 g_return_if_fail (value != NULL);
1910 g_return_if_fail (denominator_start != 0);
1911 g_return_if_fail (denominator_end != 0);
1912 g_return_if_fail (gst_util_fraction_compare (numerator_start,
1913 denominator_start, numerator_end, denominator_end) < 0);
1915 g_value_init (&start, GST_TYPE_FRACTION);
1916 g_value_init (&end, GST_TYPE_FRACTION);
1918 gst_value_set_fraction (&start, numerator_start, denominator_start);
1919 gst_value_set_fraction (&end, numerator_end, denominator_end);
1920 gst_value_set_fraction_range (value, &start, &end);
1922 /* we know the two values contain fractions without internal allocs */
1923 /* g_value_unset (&start); */
1924 /* g_value_unset (&end); */
1927 /* FIXME 2.0: Don't leak the internal representation of fraction
1928 * ranges but instead return the numerator and denominator
1930 * This would allow to store fraction ranges as
1931 * data[0] = (min_n << 32) | (min_d)
1932 * data[1] = (max_n << 32) | (max_d)
1933 * without requiring an additional allocation for each value.
1937 * gst_value_get_fraction_range_min:
1938 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1940 * Gets the minimum of the range specified by @value.
1942 * Returns: the minimum of the range
1945 gst_value_get_fraction_range_min (const GValue * value)
1949 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1951 vals = (GValue *) value->data[0].v_pointer;
1960 * gst_value_get_fraction_range_max:
1961 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1963 * Gets the maximum of the range specified by @value.
1965 * Returns: the maximum of the range
1968 gst_value_get_fraction_range_max (const GValue * value)
1972 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1974 vals = (GValue *) value->data[0].v_pointer;
1983 gst_value_serialize_fraction_range (const GValue * value)
1985 GValue *vals = (GValue *) value->data[0].v_pointer;
1989 retval = g_strdup ("[ 0/1, 0/1 ]");
1993 start = gst_value_serialize_fraction (&vals[0]);
1994 end = gst_value_serialize_fraction (&vals[1]);
1996 retval = g_strdup_printf ("[ %s, %s ]", start, end);
2005 gst_value_transform_fraction_range_string (const GValue * src_value,
2006 GValue * dest_value)
2008 dest_value->data[0].v_pointer =
2009 gst_value_serialize_fraction_range (src_value);
2013 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
2015 GValue *vals1, *vals2;
2016 GstValueCompareFunc compare;
2018 if (value2->data[0].v_pointer == value1->data[0].v_pointer)
2019 return GST_VALUE_EQUAL; /* Only possible if both are NULL */
2021 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL)
2022 return GST_VALUE_UNORDERED;
2024 vals1 = (GValue *) value1->data[0].v_pointer;
2025 vals2 = (GValue *) value2->data[0].v_pointer;
2026 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
2027 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
2029 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
2031 return GST_VALUE_EQUAL;
2033 return GST_VALUE_UNORDERED;
2037 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s)
2039 g_warning ("unimplemented");
2048 * gst_value_set_caps:
2049 * @value: a GValue initialized to GST_TYPE_CAPS
2050 * @caps: (transfer none): the caps to set the value to
2052 * Sets the contents of @value to @caps. A reference to the
2053 * provided @caps will be taken by the @value.
2056 gst_value_set_caps (GValue * value, const GstCaps * caps)
2058 g_return_if_fail (G_IS_VALUE (value));
2059 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
2060 g_return_if_fail (caps == NULL || GST_IS_CAPS (caps));
2062 g_value_set_boxed (value, caps);
2066 * gst_value_get_caps:
2067 * @value: a GValue initialized to GST_TYPE_CAPS
2069 * Gets the contents of @value. The reference count of the returned
2070 * #GstCaps will not be modified, therefore the caller must take one
2071 * before getting rid of the @value.
2073 * Returns: (transfer none): the contents of @value
2076 gst_value_get_caps (const GValue * value)
2078 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2079 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
2081 return (GstCaps *) g_value_get_boxed (value);
2085 gst_value_compare_caps (const GValue * value1, const GValue * value2)
2087 GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1));
2088 GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2));
2090 if (gst_caps_is_equal (caps1, caps2))
2091 return GST_VALUE_EQUAL;
2092 return GST_VALUE_UNORDERED;
2096 gst_value_serialize_caps (const GValue * value)
2098 GstCaps *caps = g_value_get_boxed (value);
2099 return priv_gst_string_take_and_wrap (gst_caps_to_string (caps));
2103 gst_value_deserialize_caps (GValue * dest, const gchar * s)
2108 caps = gst_caps_from_string (s);
2110 gchar *str = gst_string_unwrap (s);
2112 if (G_UNLIKELY (!str))
2115 caps = gst_caps_from_string (str);
2120 g_value_take_boxed (dest, caps);
2126 /********************************************
2127 * Serialization/deserialization of GValues *
2128 ********************************************/
2130 static GstValueAbbreviation *
2131 _priv_gst_value_get_abbrs (gint * n_abbrs)
2133 static GstValueAbbreviation *abbrs = NULL;
2134 static volatile gsize num = 0;
2136 if (g_once_init_enter (&num)) {
2137 /* dynamically generate the array */
2139 GstValueAbbreviation dyn_abbrs[] = {
2144 {"uint", G_TYPE_UINT}
2148 {"float", G_TYPE_FLOAT}
2152 {"double", G_TYPE_DOUBLE}
2154 {"d", G_TYPE_DOUBLE}
2156 {"buffer", GST_TYPE_BUFFER}
2158 {"fraction", GST_TYPE_FRACTION}
2160 {"boolean", G_TYPE_BOOLEAN}
2162 {"bool", G_TYPE_BOOLEAN}
2164 {"b", G_TYPE_BOOLEAN}
2166 {"string", G_TYPE_STRING}
2168 {"str", G_TYPE_STRING}
2170 {"s", G_TYPE_STRING}
2172 {"structure", GST_TYPE_STRUCTURE}
2174 {"date", G_TYPE_DATE}
2176 {"datetime", GST_TYPE_DATE_TIME}
2178 {"bitmask", GST_TYPE_BITMASK}
2180 {"flagset", GST_TYPE_FLAG_SET}
2182 {"sample", GST_TYPE_SAMPLE}
2184 {"taglist", GST_TYPE_TAG_LIST}
2186 {"type", G_TYPE_GTYPE}
2188 {"array", GST_TYPE_ARRAY}
2190 {"list", GST_TYPE_LIST}
2192 _num = G_N_ELEMENTS (dyn_abbrs);
2193 /* permanently allocate and copy the array now */
2194 abbrs = g_new0 (GstValueAbbreviation, _num);
2195 memcpy (abbrs, dyn_abbrs, sizeof (GstValueAbbreviation) * _num);
2196 g_once_init_leave (&num, _num);
2203 /* given a type_name that could be a type abbreviation or a registered GType,
2204 * return a matching GType */
2206 _priv_gst_value_gtype_from_abbr (const char *type_name)
2209 GstValueAbbreviation *abbrs;
2213 g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2215 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2217 for (i = 0; i < n_abbrs; i++) {
2218 if (strcmp (type_name, abbrs[i].type_name) == 0) {
2219 return abbrs[i].type;
2223 /* this is the fallback */
2224 ret = g_type_from_name (type_name);
2225 /* If not found, try it as a dynamic type */
2226 if (G_UNLIKELY (ret == 0))
2227 ret = gst_dynamic_type_factory_load (type_name);
2233 _priv_gst_value_gtype_to_abbr (GType type)
2236 GstValueAbbreviation *abbrs;
2239 g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
2241 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2243 for (i = 0; i < n_abbrs; i++) {
2244 if (type == abbrs[i].type) {
2245 return abbrs[i].type_name;
2249 return g_type_name (type);
2253 * _priv_gst_value_parse_string:
2254 * @s: string to parse
2255 * @end: out-pointer to char behind end of string
2256 * @next: out-pointer to start of unread data
2257 * @unescape: @TRUE if the substring is escaped.
2259 * Find the end of a sub-string. If end == next, the string will not be
2260 * null-terminated. In all other cases it will be.
2262 * Note: This function modifies the string in @s (if unescape == @TRUE).
2264 * Returns: @TRUE if a sub-string was found and @FALSE if the string is not
2268 _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next,
2277 int ret = _priv_gst_value_parse_simple_string (s, end);
2283 /* Find the closing quotes */
2288 if (G_UNLIKELY (*s == 0))
2290 if (G_UNLIKELY (*s == '\\')) {
2292 if (G_UNLIKELY (*s == 0))
2303 if (G_UNLIKELY (*s == 0))
2305 if (G_UNLIKELY (*s == '\\')) {
2307 if (G_UNLIKELY (*s == 0))
2323 _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
2326 GValue value1 = { 0 };
2327 GValue value2 = { 0 };
2328 GValue value3 = { 0 };
2330 gboolean ret, have_step = FALSE;
2336 ret = _priv_gst_value_parse_value (s, &s, &value1, type);
2340 while (g_ascii_isspace (*s))
2347 while (g_ascii_isspace (*s))
2350 ret = _priv_gst_value_parse_value (s, &s, &value2, type);
2354 while (g_ascii_isspace (*s))
2357 /* optional step for int and int64 */
2358 if (G_VALUE_TYPE (&value1) == G_TYPE_INT
2359 || G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2363 while (g_ascii_isspace (*s))
2366 ret = _priv_gst_value_parse_value (s, &s, &value3, type);
2370 while (g_ascii_isspace (*s))
2381 if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
2383 if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
2386 if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
2387 range_type = GST_TYPE_DOUBLE_RANGE;
2388 g_value_init (value, range_type);
2389 gst_value_set_double_range (value,
2390 gst_g_value_get_double_unchecked (&value1),
2391 gst_g_value_get_double_unchecked (&value2));
2392 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
2393 range_type = GST_TYPE_INT_RANGE;
2394 g_value_init (value, range_type);
2396 gst_value_set_int_range_step (value,
2397 gst_g_value_get_int_unchecked (&value1),
2398 gst_g_value_get_int_unchecked (&value2),
2399 gst_g_value_get_int_unchecked (&value3));
2401 gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
2402 gst_g_value_get_int_unchecked (&value2));
2403 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2404 range_type = GST_TYPE_INT64_RANGE;
2405 g_value_init (value, range_type);
2407 gst_value_set_int64_range_step (value,
2408 gst_g_value_get_int64_unchecked (&value1),
2409 gst_g_value_get_int64_unchecked (&value2),
2410 gst_g_value_get_int64_unchecked (&value3));
2412 gst_value_set_int64_range (value,
2413 gst_g_value_get_int64_unchecked (&value1),
2414 gst_g_value_get_int64_unchecked (&value2));
2415 } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
2416 range_type = GST_TYPE_FRACTION_RANGE;
2417 g_value_init (value, range_type);
2418 gst_value_set_fraction_range (value, &value1, &value2);
2428 _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
2429 GType type, char begin, char end)
2431 GValue list_value = { 0 };
2435 array = g_value_peek_pointer (value);
2441 while (g_ascii_isspace (*s))
2449 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2453 g_array_append_val (array, list_value);
2455 while (g_ascii_isspace (*s))
2463 while (g_ascii_isspace (*s))
2466 memset (&list_value, 0, sizeof (list_value));
2467 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2471 g_array_append_val (array, list_value);
2472 while (g_ascii_isspace (*s))
2483 _priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value,
2486 return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}');
2490 _priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value,
2493 return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>');
2497 _priv_gst_value_parse_simple_string (gchar * str, gchar ** end)
2501 while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
2511 _priv_gst_value_parse_value (gchar * str,
2512 gchar ** after, GValue * value, GType default_type)
2521 GType type = default_type;
2524 while (g_ascii_isspace (*s))
2527 /* check if there's a (type_name) 'cast' */
2531 while (g_ascii_isspace (*s))
2534 if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &type_end)))
2537 while (g_ascii_isspace (*s))
2539 if (G_UNLIKELY (*s != ')'))
2542 while (g_ascii_isspace (*s))
2547 type = _priv_gst_value_gtype_from_abbr (type_name);
2548 GST_DEBUG ("trying type name '%s'", type_name);
2551 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2552 GST_WARNING ("invalid type");
2557 while (g_ascii_isspace (*s))
2560 ret = _priv_gst_value_parse_range (s, &s, value, type);
2561 } else if (*s == '{') {
2562 g_value_init (value, GST_TYPE_LIST);
2563 ret = _priv_gst_value_parse_list (s, &s, value, type);
2564 } else if (*s == '<') {
2565 g_value_init (value, GST_TYPE_ARRAY);
2566 ret = _priv_gst_value_parse_array (s, &s, value, type);
2570 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2572 { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
2573 G_TYPE_BOOLEAN, G_TYPE_STRING
2577 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE)))
2579 /* Set NULL terminator for deserialization */
2583 for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
2584 g_value_init (value, try_types[i]);
2585 ret = gst_value_deserialize (value, value_s);
2588 g_value_unset (value);
2591 g_value_init (value, type);
2593 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s,
2594 (type != G_TYPE_STRING))))
2596 /* Set NULL terminator for deserialization */
2600 ret = gst_value_deserialize (value, value_s);
2601 if (G_UNLIKELY (!ret))
2602 g_value_unset (value);
2617 gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
2619 GstSegment *seg = g_value_get_boxed (value);
2623 s = gst_structure_new ("GstSegment",
2624 "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
2625 "rate", G_TYPE_DOUBLE, seg->rate,
2626 "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
2627 "format", GST_TYPE_FORMAT, seg->format,
2628 "base", G_TYPE_UINT64, seg->base,
2629 "offset", G_TYPE_UINT64, seg->offset,
2630 "start", G_TYPE_UINT64, seg->start,
2631 "stop", G_TYPE_UINT64, seg->stop,
2632 "time", G_TYPE_UINT64, seg->time,
2633 "position", G_TYPE_UINT64, seg->position,
2634 "duration", G_TYPE_UINT64, seg->duration, NULL);
2635 t = gst_structure_to_string (s);
2637 res = g_strdup_printf ("\"%s\"", t);
2642 gst_structure_free (s);
2648 gst_value_serialize_segment (const GValue * value)
2650 return gst_value_serialize_segment_internal (value, TRUE);
2654 gst_value_deserialize_segment (GValue * dest, const gchar * s)
2660 str = gst_structure_from_string (s, NULL);
2664 res = gst_structure_get (str,
2665 "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags,
2666 "rate", G_TYPE_DOUBLE, &seg.rate,
2667 "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
2668 "format", GST_TYPE_FORMAT, &seg.format,
2669 "base", G_TYPE_UINT64, &seg.base,
2670 "offset", G_TYPE_UINT64, &seg.offset,
2671 "start", G_TYPE_UINT64, &seg.start,
2672 "stop", G_TYPE_UINT64, &seg.stop,
2673 "time", G_TYPE_UINT64, &seg.time,
2674 "position", G_TYPE_UINT64, &seg.position,
2675 "duration", G_TYPE_UINT64, &seg.duration, NULL);
2676 gst_structure_free (str);
2679 g_value_set_boxed (dest, &seg);
2689 * gst_value_set_structure:
2690 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2691 * @structure: the structure to set the value to
2693 * Sets the contents of @value to @structure.
2696 gst_value_set_structure (GValue * value, const GstStructure * structure)
2698 g_return_if_fail (G_IS_VALUE (value));
2699 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE);
2700 g_return_if_fail (structure == NULL || GST_IS_STRUCTURE (structure));
2702 g_value_set_boxed (value, structure);
2706 * gst_value_get_structure:
2707 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2709 * Gets the contents of @value.
2711 * Returns: (transfer none): the contents of @value
2713 const GstStructure *
2714 gst_value_get_structure (const GValue * value)
2716 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2717 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL);
2719 return (GstStructure *) g_value_get_boxed (value);
2723 gst_value_serialize_structure (const GValue * value)
2725 GstStructure *structure = g_value_get_boxed (value);
2727 return priv_gst_string_take_and_wrap (gst_structure_to_string (structure));
2731 gst_value_deserialize_structure (GValue * dest, const gchar * s)
2733 GstStructure *structure;
2736 structure = gst_structure_from_string (s, NULL);
2738 gchar *str = gst_string_unwrap (s);
2740 if (G_UNLIKELY (!str))
2743 structure = gst_structure_from_string (str, NULL);
2747 if (G_LIKELY (structure)) {
2748 g_value_take_boxed (dest, structure);
2755 gst_value_compare_structure (const GValue * value1, const GValue * value2)
2757 GstStructure *structure1 = GST_STRUCTURE (g_value_get_boxed (value1));
2758 GstStructure *structure2 = GST_STRUCTURE (g_value_get_boxed (value2));
2760 if (structure1 == structure2)
2761 return GST_VALUE_EQUAL;
2763 if (!structure1 || !structure2)
2764 return GST_VALUE_UNORDERED;
2766 if (gst_structure_is_equal (structure1, structure2))
2767 return GST_VALUE_EQUAL;
2769 return GST_VALUE_UNORDERED;
2772 /*******************
2774 *******************/
2777 * gst_value_set_caps_features:
2778 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2779 * @features: the features to set the value to
2781 * Sets the contents of @value to @features.
2784 gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features)
2786 g_return_if_fail (G_IS_VALUE (value));
2787 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES);
2788 g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features));
2790 g_value_set_boxed (value, features);
2794 * gst_value_get_caps_features:
2795 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2797 * Gets the contents of @value.
2799 * Returns: (transfer none): the contents of @value
2801 const GstCapsFeatures *
2802 gst_value_get_caps_features (const GValue * value)
2804 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2805 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL);
2807 return (GstCapsFeatures *) g_value_get_boxed (value);
2811 gst_value_serialize_caps_features (const GValue * value)
2813 GstCapsFeatures *features = g_value_get_boxed (value);
2815 return priv_gst_string_take_and_wrap (gst_caps_features_to_string (features));
2819 gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
2821 GstCapsFeatures *features;
2824 features = gst_caps_features_from_string (s);
2826 gchar *str = gst_string_unwrap (s);
2828 if (G_UNLIKELY (!str))
2831 features = gst_caps_features_from_string (str);
2835 if (G_LIKELY (features)) {
2836 g_value_take_boxed (dest, features);
2846 gst_value_compare_tag_list (const GValue * value1, const GValue * value2)
2848 GstTagList *taglist1 = GST_TAG_LIST (g_value_get_boxed (value1));
2849 GstTagList *taglist2 = GST_TAG_LIST (g_value_get_boxed (value2));
2851 if (gst_tag_list_is_equal (taglist1, taglist2))
2852 return GST_VALUE_EQUAL;
2853 return GST_VALUE_UNORDERED;
2857 gst_value_deserialize_tag_list (GValue * dest, const gchar * s)
2859 GstTagList *taglist;
2862 taglist = gst_tag_list_new_from_string (s);
2864 gchar *str = gst_string_unwrap (s);
2866 if (G_UNLIKELY (!str))
2869 taglist = gst_tag_list_new_from_string (str);
2873 if (G_LIKELY (taglist != NULL)) {
2874 g_value_take_boxed (dest, taglist);
2881 gst_value_serialize_tag_list (const GValue * value)
2883 GstTagList *taglist = g_value_get_boxed (value);
2885 return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist));
2894 compare_buffer (GstBuffer * buf1, GstBuffer * buf2)
2897 GstMapInfo info1, info2;
2901 return GST_VALUE_EQUAL;
2903 size1 = gst_buffer_get_size (buf1);
2904 size2 = gst_buffer_get_size (buf2);
2907 return GST_VALUE_UNORDERED;
2910 return GST_VALUE_EQUAL;
2912 if (!gst_buffer_map (buf1, &info1, GST_MAP_READ))
2913 return GST_VALUE_UNORDERED;
2915 if (!gst_buffer_map (buf2, &info2, GST_MAP_READ)) {
2916 gst_buffer_unmap (buf1, &info1);
2917 return GST_VALUE_UNORDERED;
2920 mret = memcmp (info1.data, info2.data, info1.size);
2922 result = GST_VALUE_EQUAL;
2924 result = GST_VALUE_LESS_THAN;
2926 result = GST_VALUE_GREATER_THAN;
2928 gst_buffer_unmap (buf1, &info1);
2929 gst_buffer_unmap (buf2, &info2);
2935 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
2937 GstBuffer *buf1 = gst_value_get_buffer (value1);
2938 GstBuffer *buf2 = gst_value_get_buffer (value2);
2940 return compare_buffer (buf1, buf2);
2944 gst_value_serialize_buffer (const GValue * value)
2952 buffer = gst_value_get_buffer (value);
2956 if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
2961 string = g_malloc (info.size * 2 + 1);
2962 for (i = 0; i < info.size; i++) {
2963 sprintf (string + i * 2, "%02x", data[i]);
2965 string[info.size * 2] = 0;
2967 gst_buffer_unmap (buffer, &info);
2973 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
2986 buffer = gst_buffer_new_allocate (NULL, len / 2, NULL);
2987 if (!gst_buffer_map (buffer, &info, GST_MAP_WRITE))
2991 for (i = 0; i < len / 2; i++) {
2992 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
2995 ts[0] = s[i * 2 + 0];
2996 ts[1] = s[i * 2 + 1];
2999 data[i] = (guint8) strtoul (ts, NULL, 16);
3001 gst_buffer_unmap (buffer, &info);
3003 gst_value_take_buffer (dest, buffer);
3018 gst_buffer_unref (buffer);
3019 gst_buffer_unmap (buffer, &info);
3028 /* This function is mostly used for comparing image/buffer tags in taglists */
3030 gst_value_compare_sample (const GValue * value1, const GValue * value2)
3032 GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1));
3033 GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2));
3035 /* FIXME: should we take into account anything else such as caps? */
3036 return compare_buffer (buf1, buf2);
3040 gst_value_serialize_sample (const GValue * value)
3042 const GstStructure *info_structure;
3043 GstSegment *segment;
3047 GValue val = { 0, };
3048 gchar *info_str, *caps_str, *tmp;
3049 gchar *buf_str, *seg_str, *s;
3051 sample = g_value_get_boxed (value);
3053 buffer = gst_sample_get_buffer (sample);
3055 g_value_init (&val, GST_TYPE_BUFFER);
3056 g_value_set_boxed (&val, buffer);
3057 buf_str = gst_value_serialize_buffer (&val);
3058 g_value_unset (&val);
3060 buf_str = g_strdup ("None");
3063 caps = gst_sample_get_caps (sample);
3065 tmp = gst_caps_to_string (caps);
3066 caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3067 g_strdelimit (caps_str, "=", '_');
3070 caps_str = g_strdup ("None");
3073 segment = gst_sample_get_segment (sample);
3075 g_value_init (&val, GST_TYPE_SEGMENT);
3076 g_value_set_boxed (&val, segment);
3077 tmp = gst_value_serialize_segment_internal (&val, FALSE);
3078 seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3079 g_strdelimit (seg_str, "=", '_');
3081 g_value_unset (&val);
3083 seg_str = g_strdup ("None");
3086 info_structure = gst_sample_get_info (sample);
3087 if (info_structure) {
3088 tmp = gst_structure_to_string (info_structure);
3089 info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3090 g_strdelimit (info_str, "=", '_');
3093 info_str = g_strdup ("None");
3096 s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL);
3106 gst_value_deserialize_sample (GValue * dest, const gchar * s)
3108 GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT;
3111 GstCaps *caps = NULL;
3112 gboolean ret = FALSE;
3117 GST_TRACE ("deserialize '%s'", s);
3119 fields = g_strsplit (s, ":", -1);
3120 len = g_strv_length (fields);
3124 g_value_init (&bval, GST_TYPE_BUFFER);
3125 g_value_init (&sval, GST_TYPE_SEGMENT);
3127 if (!gst_value_deserialize_buffer (&bval, fields[0]))
3130 if (strcmp (fields[1], "None") != 0) {
3131 g_strdelimit (fields[1], "_", '=');
3132 g_base64_decode_inplace (fields[1], &outlen);
3133 GST_TRACE ("caps : %s", fields[1]);
3134 caps = gst_caps_from_string (fields[1]);
3139 if (strcmp (fields[2], "None") != 0) {
3140 g_strdelimit (fields[2], "_", '=');
3141 g_base64_decode_inplace (fields[2], &outlen);
3142 GST_TRACE ("segment : %s", fields[2]);
3143 if (!gst_value_deserialize_segment (&sval, fields[2]))
3147 if (strcmp (fields[3], "None") != 0) {
3148 g_strdelimit (fields[3], "_", '=');
3149 g_base64_decode_inplace (fields[3], &outlen);
3150 GST_TRACE ("info : %s", fields[3]);
3151 info = gst_structure_from_string (fields[3], NULL);
3158 sample = gst_sample_new (gst_value_get_buffer (&bval), caps,
3159 g_value_get_boxed (&sval), info);
3161 g_value_take_boxed (dest, sample);
3167 gst_caps_unref (caps);
3168 g_value_unset (&bval);
3169 g_value_unset (&sval);
3173 g_strfreev (fields);
3183 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
3185 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
3186 return GST_VALUE_EQUAL;
3187 return GST_VALUE_UNORDERED;
3191 gst_value_serialize_boolean (const GValue * value)
3193 if (value->data[0].v_int) {
3194 return g_strdup ("true");
3196 return g_strdup ("false");
3200 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
3202 gboolean ret = FALSE;
3204 if (g_ascii_strcasecmp (s, "true") == 0 ||
3205 g_ascii_strcasecmp (s, "yes") == 0 ||
3206 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
3207 g_value_set_boolean (dest, TRUE);
3209 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
3210 g_ascii_strcasecmp (s, "no") == 0 ||
3211 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
3212 g_value_set_boolean (dest, FALSE);
3219 #define CREATE_SERIALIZATION_START(_type,_macro) \
3221 gst_value_compare_ ## _type \
3222 (const GValue * value1, const GValue * value2) \
3224 g ## _type val1 = g_value_get_ ## _type (value1); \
3225 g ## _type val2 = g_value_get_ ## _type (value2); \
3227 return GST_VALUE_GREATER_THAN; \
3229 return GST_VALUE_LESS_THAN; \
3230 return GST_VALUE_EQUAL; \
3234 gst_value_serialize_ ## _type (const GValue * value) \
3236 GValue val = { 0, }; \
3237 g_value_init (&val, G_TYPE_STRING); \
3238 if (!g_value_transform (value, &val)) \
3239 g_assert_not_reached (); \
3240 /* NO_COPY_MADNESS!!! */ \
3241 return (char *) g_value_get_string (&val); \
3244 /* deserialize the given s into to as a gint64.
3245 * check if the result is actually storeable in the given size number of
3249 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
3250 gint64 min, gint64 max, gint size)
3252 gboolean ret = FALSE;
3257 *to = g_ascii_strtoull (s, &end, 0);
3258 /* a range error is a definitive no-no */
3259 if (errno == ERANGE) {
3266 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
3267 *to = G_LITTLE_ENDIAN;
3269 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
3272 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
3275 } else if (g_ascii_strcasecmp (s, "min") == 0) {
3278 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3284 /* by definition, a gint64 fits into a gint64; so ignore those */
3285 if (size != sizeof (mask)) {
3287 /* for positive numbers, we create a mask of 1's outside of the range
3288 * and 0's inside the range. An and will thus keep only 1 bits
3289 * outside of the range */
3290 mask <<= (size * 8);
3291 if ((mask & *to) != 0) {
3295 /* for negative numbers, we do a 2's complement version */
3296 mask <<= ((size * 8) - 1);
3297 if ((mask & *to) != mask) {
3306 #define CREATE_SERIALIZATION(_type,_macro) \
3307 CREATE_SERIALIZATION_START(_type,_macro) \
3310 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3314 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
3315 G_MAX ## _macro, sizeof (g ## _type))) { \
3316 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
3323 #define CREATE_USERIALIZATION(_type,_macro) \
3324 CREATE_SERIALIZATION_START(_type,_macro) \
3327 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3331 gboolean ret = FALSE; \
3334 x = g_ascii_strtoull (s, &end, 0); \
3335 /* a range error is a definitive no-no */ \
3336 if (errno == ERANGE) { \
3339 /* the cast ensures the range check later on makes sense */ \
3340 x = (g ## _type) x; \
3344 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
3345 x = G_LITTLE_ENDIAN; \
3347 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
3350 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
3353 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
3356 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
3357 x = G_MAX ## _macro; \
3362 if (x > G_MAX ## _macro) { \
3365 g_value_set_ ## _type (dest, x); \
3371 CREATE_SERIALIZATION (int, INT);
3372 CREATE_SERIALIZATION (int64, INT64);
3373 CREATE_SERIALIZATION (long, LONG);
3375 CREATE_USERIALIZATION (uint, UINT);
3376 CREATE_USERIALIZATION (uint64, UINT64);
3377 CREATE_USERIALIZATION (ulong, ULONG);
3379 /* FIXME 2.0: remove this again, plugins shouldn't have uchar properties */
3381 #define G_MAXUCHAR 255
3383 CREATE_USERIALIZATION (uchar, UCHAR);
3389 gst_value_compare_double (const GValue * value1, const GValue * value2)
3391 if (value1->data[0].v_double > value2->data[0].v_double)
3392 return GST_VALUE_GREATER_THAN;
3393 if (value1->data[0].v_double < value2->data[0].v_double)
3394 return GST_VALUE_LESS_THAN;
3395 if (value1->data[0].v_double == value2->data[0].v_double)
3396 return GST_VALUE_EQUAL;
3397 return GST_VALUE_UNORDERED;
3401 gst_value_serialize_double (const GValue * value)
3403 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3405 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
3406 return g_strdup (d);
3410 gst_value_deserialize_double (GValue * dest, const gchar * s)
3413 gboolean ret = FALSE;
3416 x = g_ascii_strtod (s, &end);
3420 if (g_ascii_strcasecmp (s, "min") == 0) {
3423 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3429 g_value_set_double (dest, x);
3439 gst_value_compare_float (const GValue * value1, const GValue * value2)
3441 if (value1->data[0].v_float > value2->data[0].v_float)
3442 return GST_VALUE_GREATER_THAN;
3443 if (value1->data[0].v_float < value2->data[0].v_float)
3444 return GST_VALUE_LESS_THAN;
3445 if (value1->data[0].v_float == value2->data[0].v_float)
3446 return GST_VALUE_EQUAL;
3447 return GST_VALUE_UNORDERED;
3451 gst_value_serialize_float (const GValue * value)
3453 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3455 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
3456 return g_strdup (d);
3460 gst_value_deserialize_float (GValue * dest, const gchar * s)
3463 gboolean ret = FALSE;
3466 x = g_ascii_strtod (s, &end);
3470 if (g_ascii_strcasecmp (s, "min") == 0) {
3473 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3478 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
3481 g_value_set_float (dest, (float) x);
3491 gst_value_compare_string (const GValue * value1, const GValue * value2)
3493 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
3494 /* if only one is NULL, no match - otherwise both NULL == EQUAL */
3495 if (value1->data[0].v_pointer != value2->data[0].v_pointer)
3496 return GST_VALUE_UNORDERED;
3498 gint x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
3501 return GST_VALUE_LESS_THAN;
3503 return GST_VALUE_GREATER_THAN;
3506 return GST_VALUE_EQUAL;
3510 gst_string_measure_wrapping (const gchar * s)
3513 gboolean wrap = FALSE;
3515 if (G_UNLIKELY (s == NULL))
3518 /* Special case: the actual string NULL needs wrapping */
3519 if (G_UNLIKELY (strcmp (s, "NULL") == 0))
3524 if (GST_ASCII_IS_STRING (*s)) {
3526 } else if (*s < 0x20 || *s >= 0x7f) {
3536 /* Wrap the string if we found something that needs
3537 * wrapping, or the empty string (len == 0) */
3538 return (wrap || len == 0) ? len : -1;
3542 gst_string_wrap_inner (const gchar * s, gint len)
3546 e = d = g_malloc (len + 3);
3550 if (GST_ASCII_IS_STRING (*s)) {
3552 } else if (*s < 0x20 || *s >= 0x7f) {
3554 *e++ = '0' + ((*(guchar *) s) >> 6);
3555 *e++ = '0' + (((*s) >> 3) & 0x7);
3556 *e++ = '0' + ((*s++) & 0x7);
3565 g_assert (e - d <= len + 3);
3569 /* Do string wrapping/escaping */
3571 gst_string_wrap (const gchar * s)
3573 gint len = gst_string_measure_wrapping (s);
3575 if (G_LIKELY (len < 0))
3576 return g_strdup (s);
3578 return gst_string_wrap_inner (s, len);
3581 /* Same as above, but take ownership of the string */
3583 priv_gst_string_take_and_wrap (gchar * s)
3586 gint len = gst_string_measure_wrapping (s);
3588 if (G_LIKELY (len < 0))
3591 out = gst_string_wrap_inner (s, len);
3598 * This function takes a string delimited with double quotes (")
3599 * and unescapes any \xxx octal numbers.
3601 * If sequences of \y are found where y is not in the range of
3602 * 0->3, y is copied unescaped.
3604 * If \xyy is found where x is an octal number but y is not, an
3605 * error is encountered and %NULL is returned.
3607 * the input string must be \0 terminated.
3610 gst_string_unwrap (const gchar * s)
3613 gchar *read, *write;
3615 /* NULL string returns NULL */
3619 /* strings not starting with " are invalid */
3623 /* make copy of original string to hold the result. This
3624 * string will always be smaller than the original */
3629 /* need to move to the next position as we parsed the " */
3633 if (GST_ASCII_IS_STRING (*read)) {
3634 /* normal chars are just copied */
3636 } else if (*read == '"') {
3637 /* quote marks end of string */
3639 } else if (*read == '\\') {
3640 /* got an escape char, move to next position to read a tripplet
3641 * of octal numbers */
3643 /* is the next char a possible first octal number? */
3644 if (*read >= '0' && *read <= '3') {
3645 /* parse other 2 numbers, if one of them is not in the range of
3646 * an octal number, we error. We also catch the case where a zero
3647 * byte is found here. */
3648 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
3651 /* now convert the octal number to a byte again. */
3652 *write++ = ((read[0] - '0') << 6) +
3653 ((read[1] - '0') << 3) + (read[2] - '0');
3657 /* if we run into a \0 here, we definitely won't get a quote later */
3661 /* else copy \X sequence */
3665 /* weird character, error */
3669 /* if the string is not ending in " and zero terminated, we error */
3670 if (*read != '"' || read[1] != '\0')
3673 /* null terminate result string and return */
3683 gst_value_serialize_string (const GValue * value)
3685 return gst_string_wrap (value->data[0].v_pointer);
3689 gst_value_deserialize_string (GValue * dest, const gchar * s)
3691 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
3692 g_value_set_string (dest, NULL);
3694 } else if (G_LIKELY (*s != '"' || s[strlen (s) - 1] != '"')) {
3695 if (!g_utf8_validate (s, -1, NULL))
3697 g_value_set_string (dest, s);
3700 /* strings delimited with double quotes should be unwrapped */
3701 gchar *str = gst_string_unwrap (s);
3702 if (G_UNLIKELY (!str))
3704 g_value_take_string (dest, str);
3715 gst_value_compare_enum (const GValue * value1, const GValue * value2)
3717 GEnumValue *en1, *en2;
3718 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3719 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3721 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3722 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3723 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
3724 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
3725 g_type_class_unref (klass1);
3726 g_type_class_unref (klass2);
3727 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
3728 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
3729 if (en1->value < en2->value)
3730 return GST_VALUE_LESS_THAN;
3731 if (en1->value > en2->value)
3732 return GST_VALUE_GREATER_THAN;
3734 return GST_VALUE_EQUAL;
3738 gst_value_serialize_enum (const GValue * value)
3741 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
3743 g_return_val_if_fail (klass, NULL);
3744 en = g_enum_get_value (klass, g_value_get_enum (value));
3745 g_type_class_unref (klass);
3747 /* might be one of the custom formats registered later */
3748 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) {
3749 const GstFormatDefinition *format_def;
3751 format_def = gst_format_get_details ((GstFormat) g_value_get_enum (value));
3752 g_return_val_if_fail (format_def != NULL, NULL);
3753 return g_strdup (format_def->description);
3756 g_return_val_if_fail (en, NULL);
3757 return g_strdup (en->value_name);
3761 gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value,
3764 const GstFormatDefinition *format_def =
3765 g_value_get_pointer (format_def_value);
3767 if (g_ascii_strcasecmp (s, format_def->nick) == 0)
3770 return g_ascii_strcasecmp (s, format_def->description);
3774 gst_value_deserialize_enum (GValue * dest, const gchar * s)
3777 gchar *endptr = NULL;
3778 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3780 g_return_val_if_fail (klass, FALSE);
3781 if (!(en = g_enum_get_value_by_name (klass, s))) {
3782 if (!(en = g_enum_get_value_by_nick (klass, s))) {
3783 gint i = strtol (s, &endptr, 0);
3785 if (endptr && *endptr == '\0') {
3786 en = g_enum_get_value (klass, i);
3790 g_type_class_unref (klass);
3792 /* might be one of the custom formats registered later */
3793 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
3794 GValue res = { 0, };
3795 const GstFormatDefinition *format_def;
3799 iter = gst_format_iterate_definitions ();
3801 found = gst_iterator_find_custom (iter,
3802 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
3805 format_def = g_value_get_pointer (&res);
3806 g_return_val_if_fail (format_def != NULL, FALSE);
3807 g_value_set_enum (dest, (gint) format_def->value);
3808 g_value_unset (&res);
3810 gst_iterator_free (iter);
3814 /* enum name/nick not found */
3818 g_value_set_enum (dest, en->value);
3826 /* we just compare the value here */
3828 gst_value_compare_gflags (const GValue * value1, const GValue * value2)
3831 GFlagsClass *klass1 =
3832 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3833 GFlagsClass *klass2 =
3834 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3836 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3837 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3838 fl1 = g_value_get_flags (value1);
3839 fl2 = g_value_get_flags (value2);
3840 g_type_class_unref (klass1);
3841 g_type_class_unref (klass2);
3843 return GST_VALUE_LESS_THAN;
3845 return GST_VALUE_GREATER_THAN;
3847 return GST_VALUE_EQUAL;
3850 /* the different flags are serialized separated with a + */
3852 gst_value_serialize_gflags (const GValue * value)
3856 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
3857 gchar *result, *tmp;
3858 gboolean first = TRUE;
3860 g_return_val_if_fail (klass, NULL);
3862 flags = g_value_get_flags (value);
3864 /* if no flags are set, try to serialize to the _NONE string */
3866 fl = g_flags_get_first_value (klass, flags);
3868 return g_strdup (fl->value_name);
3870 return g_strdup ("0");
3873 /* some flags are set, so serialize one by one */
3874 result = g_strdup ("");
3876 fl = g_flags_get_first_value (klass, flags);
3878 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
3884 flags &= ~fl->value;
3887 g_type_class_unref (klass);
3893 gst_value_gflags_str_to_flags (GFlagsClass * klass, const gchar * s,
3894 guint * out_flags, guint * out_mask)
3898 const gchar *pos = NULL;
3900 gchar *cur_str, *endptr;
3905 g_return_val_if_fail (klass, FALSE);
3907 /* split into parts delimited with + or / and
3908 * compose the set of flags and mask. */
3912 goto done; /* Empty string, nothing to do */
3914 /* As a special case if the first char isn't a delimiter, assume
3915 * it's a '+' - for GFlags strings, which don't start with a
3916 * delimiter, while GFlagSet always will */
3917 if (*pos == '/' || *pos == '+') {
3925 /* Find the next delimiter */
3927 while (*next != '\0' && *next != '+' && *next != '/')
3929 cur_str = g_strndup (pos, next - pos);
3931 if ((fl = g_flags_get_value_by_name (klass, cur_str)))
3933 else if ((fl = g_flags_get_value_by_nick (klass, cur_str)))
3936 val = strtoul (cur_str, &endptr, 0);
3937 /* direct numeric value */
3938 if (endptr == NULL || *endptr != '\0') {
3940 return FALSE; /* Invalid numeric or string we can't convert */
3947 if (delimiter == '+')
3951 /* Advance to the next delimiter */
3955 } while (delimiter != '\0');
3968 gst_value_deserialize_gflags (GValue * dest, const gchar * s)
3970 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3971 gboolean res = FALSE;
3974 if (gst_value_gflags_str_to_flags (klass, s, &flags, NULL)) {
3975 g_value_set_flags (dest, flags);
3979 g_type_class_unref (klass);
3989 gst_value_compare_gtype (const GValue * value1, const GValue * value2)
3991 if (value1->data[0].v_pointer == value2->data[0].v_pointer)
3992 return GST_VALUE_EQUAL;
3993 return GST_VALUE_UNORDERED;
3997 gst_value_serialize_gtype (const GValue * value)
3999 return g_strdup (g_type_name (g_value_get_gtype (value)));
4003 gst_value_deserialize_gtype (GValue * dest, const gchar * s)
4005 GType t = g_type_from_name (s);
4006 gboolean ret = TRUE;
4008 if (t == G_TYPE_INVALID)
4011 g_value_set_gtype (dest, t);
4021 gst_value_is_subset_int_range_int_range (const GValue * value1,
4022 const GValue * value2)
4026 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE);
4027 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE);
4029 if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) <
4030 INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2))
4032 if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) >
4033 INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2))
4036 if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) {
4037 if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) %
4038 INT_RANGE_STEP (value1))
4044 gst_util_greatest_common_divisor (INT_RANGE_STEP (value1),
4045 INT_RANGE_STEP (value2));
4046 if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2)))
4053 gst_value_is_subset_int64_range_int64_range (const GValue * value1,
4054 const GValue * value2)
4058 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE);
4059 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE);
4061 if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2))
4063 if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2))
4066 if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) {
4067 if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) %
4068 INT64_RANGE_STEP (value1))
4074 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1),
4075 INT64_RANGE_STEP (value2));
4076 if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2)))
4082 /* A flag set is a subset of another if the superset allows the
4083 * flags of the subset */
4085 gst_value_is_subset_flagset_flagset (const GValue * value1,
4086 const GValue * value2)
4091 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value1), FALSE);
4092 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value2), FALSE);
4094 f1 = value1->data[0].v_uint;
4095 f2 = value2->data[0].v_uint;
4097 m1 = value1->data[1].v_uint;
4098 m2 = value2->data[1].v_uint;
4100 /* Not a subset if masked bits of superset disagree */
4101 if ((f1 & m1) != (f2 & (m1 & m2)))
4108 gst_value_is_subset_structure_structure (const GValue * value1,
4109 const GValue * value2)
4111 const GstStructure *s1, *s2;
4113 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value1), FALSE);
4114 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value2), FALSE);
4116 s1 = gst_value_get_structure (value1);
4117 s2 = gst_value_get_structure (value2);
4119 return gst_structure_is_subset (s1, s2);
4123 * gst_value_is_subset:
4124 * @value1: a #GValue
4125 * @value2: a #GValue
4127 * Check that @value1 is a subset of @value2.
4129 * Return: %TRUE is @value1 is a subset of @value2
4132 gst_value_is_subset (const GValue * value1, const GValue * value2)
4134 /* special case for int/int64 ranges, since we cannot compute
4135 the difference for those when they have different steps,
4136 and it's actually a lot simpler to compute whether a range
4137 is a subset of another. */
4138 if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) {
4139 return gst_value_is_subset_int_range_int_range (value1, value2);
4140 } else if (GST_VALUE_HOLDS_INT64_RANGE (value1)
4141 && GST_VALUE_HOLDS_INT64_RANGE (value2)) {
4142 return gst_value_is_subset_int64_range_int64_range (value1, value2);
4143 } else if (GST_VALUE_HOLDS_FLAG_SET (value1) &&
4144 GST_VALUE_HOLDS_FLAG_SET (value2)) {
4145 return gst_value_is_subset_flagset_flagset (value1, value2);
4146 } else if (GST_VALUE_HOLDS_STRUCTURE (value1)
4147 && GST_VALUE_HOLDS_STRUCTURE (value2)) {
4148 return gst_value_is_subset_structure_structure (value1, value2);
4156 * -> 1 - [1,2] = empty
4160 * -> [1,2] - [1,3] = empty
4164 * -> {1,3} - {1,2} = 3
4167 * First caps subtraction needs to return a non-empty set, second
4168 * subtractions needs to give en empty set.
4169 * Both substractions are switched below, as it's faster that way.
4171 if (!gst_value_subtract (NULL, value1, value2)) {
4172 if (gst_value_subtract (NULL, value2, value1)) {
4184 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
4185 const GValue * src2)
4187 gint v = src1->data[0].v_int;
4189 /* check if it's already in the range */
4190 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v &&
4191 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v &&
4192 v % INT_RANGE_STEP (src2) == 0) {
4194 gst_value_init_and_copy (dest, src2);
4198 /* check if it extends the range */
4199 if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) {
4201 guint64 new_min = INT_RANGE_MIN (src2) - 1;
4202 guint64 new_max = INT_RANGE_MAX (src2);
4204 gst_value_init_and_copy (dest, src2);
4205 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4209 if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) {
4211 guint64 new_min = INT_RANGE_MIN (src2);
4212 guint64 new_max = INT_RANGE_MAX (src2) + 1;
4214 gst_value_init_and_copy (dest, src2);
4215 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4224 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
4225 const GValue * src2)
4227 /* We can union in several special cases:
4228 1 - one is a subset of another
4229 2 - same step and not disjoint
4230 3 - different step, at least one with one value which matches a 'next' or 'previous'
4235 if (gst_value_is_subset_int_range_int_range (src1, src2)) {
4237 gst_value_init_and_copy (dest, src2);
4240 if (gst_value_is_subset_int_range_int_range (src2, src1)) {
4242 gst_value_init_and_copy (dest, src1);
4246 /* 2 - same step and not disjoint */
4247 if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) {
4248 if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 &&
4249 INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) ||
4250 (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 &&
4251 INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) {
4253 gint step = INT_RANGE_STEP (src1);
4254 gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2));
4255 gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2));
4256 g_value_init (dest, GST_TYPE_INT_RANGE);
4257 gst_value_set_int_range_step (dest, min, max, step);
4263 /* 3 - single value matches next or previous */
4264 if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) {
4265 gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1;
4266 gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1;
4267 if (n1 == 1 || n2 == 1) {
4268 const GValue *range_value = NULL;
4272 scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1);
4273 } else if (n2 == 1) {
4275 scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2);
4279 (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) {
4281 guint64 new_min = (guint)
4282 ((INT_RANGE_MIN (range_value) -
4283 1) * INT_RANGE_STEP (range_value));
4284 guint64 new_max = (guint)
4285 (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value));
4287 gst_value_init_and_copy (dest, range_value);
4288 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4291 } else if (scalar ==
4292 (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) {
4294 guint64 new_min = (guint)
4295 (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value));
4296 guint64 new_max = (guint)
4297 ((INT_RANGE_MAX (range_value) +
4298 1) * INT_RANGE_STEP (range_value));
4299 gst_value_init_and_copy (dest, range_value);
4300 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4307 /* If we get there, we did not find a way to make a union that can be
4308 represented with our simplistic model. */
4313 gst_value_union_flagset_flagset (GValue * dest, const GValue * src1,
4314 const GValue * src2)
4316 /* We can union 2 flag sets where they do not disagree on
4317 * required (masked) flag bits */
4321 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4322 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4324 f1 = src1->data[0].v_uint;
4325 f2 = src2->data[0].v_uint;
4327 m1 = src1->data[1].v_uint;
4328 m2 = src2->data[1].v_uint;
4330 /* Can't union if masked bits disagree */
4331 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4335 g_value_init (dest, GST_TYPE_FLAG_SET);
4336 /* Copy masked bits from src2 to src1 */
4340 gst_value_set_flagset (dest, f1, m1);
4346 /* iterating over the result taking the union with the other structure's value */
4348 structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
4350 GstStructure *other = user_data;
4351 const GValue *other_value;
4352 GValue res_value = G_VALUE_INIT;
4354 other_value = gst_structure_id_get_value (other, field_id);
4355 /* no value in the other struct, just keep this value */
4359 if (!gst_value_union (&res_value, val, other_value))
4362 g_value_unset (val);
4363 gst_value_move (val, &res_value);
4367 /* iterating over the other source structure adding missing values */
4369 structure_field_union_from (GQuark field_id, const GValue * other_val,
4372 GstStructure *result = user_data;
4373 const GValue *result_value;
4375 result_value = gst_structure_id_get_value (result, field_id);
4377 gst_structure_id_set_value (result, field_id, other_val);
4383 gst_value_union_structure_structure (GValue * dest, const GValue * src1,
4384 const GValue * src2)
4386 const GstStructure *s1, *s2;
4387 GstStructure *result;
4390 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src1), FALSE);
4391 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src2), FALSE);
4393 s1 = gst_value_get_structure (src1);
4394 s2 = gst_value_get_structure (src2);
4396 /* Can't join two structures with different names into a single structure */
4397 if (!gst_structure_has_name (s1, gst_structure_get_name (s2))) {
4398 gst_value_list_concat (dest, src1, src2);
4402 result = gst_structure_copy (s1);
4404 gst_structure_map_in_place (result, structure_field_union_into,
4409 gst_structure_foreach (s2, structure_field_union_from, (gpointer) result);
4412 g_value_init (dest, GST_TYPE_STRUCTURE);
4413 gst_value_set_structure (dest, result);
4417 gst_structure_free (result);
4426 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
4427 const GValue * src2)
4429 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int &&
4430 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int &&
4431 src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) {
4433 gst_value_init_and_copy (dest, src1);
4441 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
4442 const GValue * src2)
4449 INT_RANGE_STEP (src1) /
4450 gst_util_greatest_common_divisor (INT_RANGE_STEP (src1),
4451 INT_RANGE_STEP (src2));
4452 if (G_MAXINT32 / INT_RANGE_STEP (src2) < step)
4454 step *= INT_RANGE_STEP (src2);
4457 MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1),
4458 INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
4459 min = (min + step - 1) / step * step;
4461 MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1),
4462 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
4463 max = max / step * step;
4467 g_value_init (dest, GST_TYPE_INT_RANGE);
4468 gst_value_set_int_range_step (dest, min, max, step);
4474 g_value_init (dest, G_TYPE_INT);
4475 g_value_set_int (dest, min);
4483 #define INT64_RANGE_MIN_VAL(v) (INT64_RANGE_MIN (v) * INT64_RANGE_STEP (v))
4484 #define INT64_RANGE_MAX_VAL(v) (INT64_RANGE_MAX (v) * INT64_RANGE_STEP (v))
4487 gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1,
4488 const GValue * src2)
4490 if (INT64_RANGE_MIN_VAL (src2) <= src1->data[0].v_int64 &&
4491 INT64_RANGE_MAX_VAL (src2) >= src1->data[0].v_int64 &&
4492 src1->data[0].v_int64 % INT64_RANGE_STEP (src2) == 0) {
4494 gst_value_init_and_copy (dest, src1);
4502 gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1,
4503 const GValue * src2)
4510 INT64_RANGE_STEP (src1) /
4511 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1),
4512 INT64_RANGE_STEP (src2));
4513 if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step)
4515 step *= INT64_RANGE_STEP (src2);
4518 MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1),
4519 INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2));
4520 min = (min + step - 1) / step * step;
4522 MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1),
4523 INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2));
4524 max = max / step * step;
4528 g_value_init (dest, GST_TYPE_INT64_RANGE);
4529 gst_value_set_int64_range_step (dest, min, max, step);
4535 g_value_init (dest, G_TYPE_INT64);
4536 g_value_set_int64 (dest, min);
4545 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
4546 const GValue * src2)
4548 if (src2->data[0].v_double <= src1->data[0].v_double &&
4549 src2->data[1].v_double >= src1->data[0].v_double) {
4551 gst_value_init_and_copy (dest, src1);
4559 gst_value_intersect_double_range_double_range (GValue * dest,
4560 const GValue * src1, const GValue * src2)
4565 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
4566 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
4570 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
4571 gst_value_set_double_range (dest, min, max);
4577 g_value_init (dest, G_TYPE_DOUBLE);
4578 g_value_set_int (dest, (int) min);
4587 gst_value_intersect_list (GValue * dest, const GValue * value1,
4588 const GValue * value2)
4591 GValue intersection = { 0, };
4592 gboolean ret = FALSE;
4594 size = VALUE_LIST_SIZE (value1);
4595 for (i = 0; i < size; i++) {
4596 const GValue *cur = VALUE_LIST_GET_VALUE (value1, i);
4598 /* quicker version when we don't need the resulting set */
4600 if (gst_value_intersect (NULL, cur, value2)) {
4607 if (gst_value_intersect (&intersection, cur, value2)) {
4610 gst_value_move (dest, &intersection);
4612 } else if (GST_VALUE_HOLDS_LIST (dest)) {
4613 _gst_value_list_append_and_take_value (dest, &intersection);
4617 gst_value_move (&temp, dest);
4618 gst_value_list_merge (dest, &temp, &intersection);
4619 g_value_unset (&temp);
4620 g_value_unset (&intersection);
4629 gst_value_intersect_array (GValue * dest, const GValue * src1,
4630 const GValue * src2)
4636 /* only works on similar-sized arrays */
4637 size = gst_value_array_get_size (src1);
4638 if (size != gst_value_array_get_size (src2))
4641 /* quicker value when we don't need the resulting set */
4643 for (n = 0; n < size; n++) {
4644 if (!gst_value_intersect (NULL, gst_value_array_get_value (src1, n),
4645 gst_value_array_get_value (src2, n))) {
4652 g_value_init (dest, GST_TYPE_ARRAY);
4654 for (n = 0; n < size; n++) {
4655 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
4656 gst_value_array_get_value (src2, n))) {
4657 g_value_unset (dest);
4660 _gst_value_array_append_and_take_value (dest, &val);
4667 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
4668 const GValue * src2)
4672 GstValueCompareFunc compare;
4674 vals = src2->data[0].v_pointer;
4679 if ((compare = gst_value_get_compare_func (src1))) {
4680 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
4681 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
4683 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
4684 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
4686 gst_value_init_and_copy (dest, src1);
4695 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
4696 const GValue * src1, const GValue * src2)
4701 GValue *vals1, *vals2;
4702 GstValueCompareFunc compare;
4704 vals1 = src1->data[0].v_pointer;
4705 vals2 = src2->data[0].v_pointer;
4706 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
4708 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
4709 /* min = MAX (src1.start, src2.start) */
4710 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
4711 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4712 if (res == GST_VALUE_LESS_THAN)
4713 min = &vals2[0]; /* Take the max of the 2 */
4717 /* max = MIN (src1.end, src2.end) */
4718 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
4719 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4720 if (res == GST_VALUE_GREATER_THAN)
4721 max = &vals2[1]; /* Take the min of the 2 */
4725 res = gst_value_compare_with_func (min, max, compare);
4726 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4727 if (res == GST_VALUE_LESS_THAN) {
4729 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
4730 vals1 = dest->data[0].v_pointer;
4731 g_value_copy (min, &vals1[0]);
4732 g_value_copy (max, &vals1[1]);
4736 if (res == GST_VALUE_EQUAL) {
4738 gst_value_init_and_copy (dest, min);
4746 /* Two flagsets intersect if the masked bits in both
4747 * flagsets are exactly equal */
4749 gst_value_intersect_flagset_flagset (GValue * dest,
4750 const GValue * src1, const GValue * src2)
4754 GType type1, type2, flagset_type;
4756 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4757 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4759 f1 = src1->data[0].v_uint;
4760 f2 = src2->data[0].v_uint;
4762 m1 = src1->data[1].v_uint;
4763 m2 = src2->data[1].v_uint;
4765 /* Don't intersect if masked bits disagree */
4766 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4769 /* Allow intersection with the generic FlagSet type, on one
4770 * side, but not 2 different subtypes - that makes no sense */
4771 type1 = G_VALUE_TYPE (src1);
4772 type2 = G_VALUE_TYPE (src2);
4773 flagset_type = GST_TYPE_FLAG_SET;
4775 if (type1 != type2 && type1 != flagset_type && type2 != flagset_type)
4781 /* Prefer an output type that matches a sub-type,
4782 * rather than the generic type */
4783 if (type1 != flagset_type)
4788 g_value_init (dest, dest_type);
4790 /* The compatible set is all the bits from src1 that it
4791 * cares about and all the bits from src2 that it cares
4793 dest->data[0].v_uint = (f1 & m1) | (f2 & m2);
4794 dest->data[1].v_uint = m1 | m2;
4801 gst_value_intersect_structure_structure (GValue * dest,
4802 const GValue * src1, const GValue * src2)
4804 const GstStructure *s1, *s2;
4807 s1 = gst_value_get_structure (src1);
4808 s2 = gst_value_get_structure (src2);
4810 d1 = gst_structure_intersect (s1, s2);
4815 g_value_init (dest, GST_TYPE_STRUCTURE);
4816 gst_value_set_structure (dest, d1);
4819 gst_structure_free (d1);
4828 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
4829 const GValue * subtrahend)
4831 gint min = gst_value_get_int_range_min (subtrahend);
4832 gint max = gst_value_get_int_range_max (subtrahend);
4833 gint step = gst_value_get_int_range_step (subtrahend);
4834 gint val = g_value_get_int (minuend);
4839 /* subtracting a range from an int only works if the int is not in the
4841 if (val < min || val > max || val % step) {
4842 /* and the result is the int */
4844 gst_value_init_and_copy (dest, minuend);
4850 /* creates a new int range based on input values.
4853 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
4854 gint max2, gint step)
4858 GValue *pv1, *pv2; /* yeah, hungarian! */
4860 g_return_val_if_fail (step > 0, FALSE);
4861 g_return_val_if_fail (min1 % step == 0, FALSE);
4862 g_return_val_if_fail (max1 % step == 0, FALSE);
4863 g_return_val_if_fail (min2 % step == 0, FALSE);
4864 g_return_val_if_fail (max2 % step == 0, FALSE);
4866 if (min1 <= max1 && min2 <= max2) {
4869 } else if (min1 <= max1) {
4872 } else if (min2 <= max2) {
4883 g_value_init (pv1, GST_TYPE_INT_RANGE);
4884 gst_value_set_int_range_step (pv1, min1, max1, step);
4885 } else if (min1 == max1) {
4886 g_value_init (pv1, G_TYPE_INT);
4887 g_value_set_int (pv1, min1);
4890 g_value_init (pv2, GST_TYPE_INT_RANGE);
4891 gst_value_set_int_range_step (pv2, min2, max2, step);
4892 } else if (min2 == max2) {
4893 g_value_init (pv2, G_TYPE_INT);
4894 g_value_set_int (pv2, min2);
4897 if (min1 <= max1 && min2 <= max2) {
4898 gst_value_list_concat_and_take_values (dest, pv1, pv2);
4904 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
4905 const GValue * subtrahend)
4907 gint min = gst_value_get_int_range_min (minuend);
4908 gint max = gst_value_get_int_range_max (minuend);
4909 gint step = gst_value_get_int_range_step (minuend);
4910 gint val = g_value_get_int (subtrahend);
4912 g_return_val_if_fail (min < max, FALSE);
4917 /* value is outside of the range, return range unchanged */
4918 if (val < min || val > max || val % step) {
4920 gst_value_init_and_copy (dest, minuend);
4923 /* max must be MAXINT too as val <= max */
4924 if (val >= G_MAXINT - step + 1) {
4928 /* min must be MININT too as val >= max */
4929 if (val <= G_MININT + step - 1) {
4934 gst_value_create_new_range (dest, min, val - step, val + step, max, step);
4940 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
4941 const GValue * subtrahend)
4943 gint min1 = gst_value_get_int_range_min (minuend);
4944 gint max1 = gst_value_get_int_range_max (minuend);
4945 gint step1 = gst_value_get_int_range_step (minuend);
4946 gint min2 = gst_value_get_int_range_min (subtrahend);
4947 gint max2 = gst_value_get_int_range_max (subtrahend);
4948 gint step2 = gst_value_get_int_range_step (subtrahend);
4951 if (step1 != step2) {
4961 if (max2 >= max1 && min2 <= min1) {
4963 } else if (max2 >= max1) {
4964 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4966 } else if (min2 <= min1) {
4967 return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1,
4970 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4971 MAX (max2 + step, min1), max1, step);
4976 gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
4977 const GValue * subtrahend)
4979 gint64 min = gst_value_get_int64_range_min (subtrahend);
4980 gint64 max = gst_value_get_int64_range_max (subtrahend);
4981 gint64 step = gst_value_get_int64_range_step (subtrahend);
4982 gint64 val = g_value_get_int64 (minuend);
4986 /* subtracting a range from an int64 only works if the int64 is not in the
4988 if (val < min || val > max || val % step) {
4989 /* and the result is the int64 */
4991 gst_value_init_and_copy (dest, minuend);
4997 /* creates a new int64 range based on input values.
5000 gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
5001 gint64 min2, gint64 max2, gint64 step)
5005 GValue *pv1, *pv2; /* yeah, hungarian! */
5007 g_return_val_if_fail (step > 0, FALSE);
5008 g_return_val_if_fail (min1 % step == 0, FALSE);
5009 g_return_val_if_fail (max1 % step == 0, FALSE);
5010 g_return_val_if_fail (min2 % step == 0, FALSE);
5011 g_return_val_if_fail (max2 % step == 0, FALSE);
5013 if (min1 <= max1 && min2 <= max2) {
5016 } else if (min1 <= max1) {
5019 } else if (min2 <= max2) {
5030 g_value_init (pv1, GST_TYPE_INT64_RANGE);
5031 gst_value_set_int64_range_step (pv1, min1, max1, step);
5032 } else if (min1 == max1) {
5033 g_value_init (pv1, G_TYPE_INT64);
5034 g_value_set_int64 (pv1, min1);
5037 g_value_init (pv2, GST_TYPE_INT64_RANGE);
5038 gst_value_set_int64_range_step (pv2, min2, max2, step);
5039 } else if (min2 == max2) {
5040 g_value_init (pv2, G_TYPE_INT64);
5041 g_value_set_int64 (pv2, min2);
5044 if (min1 <= max1 && min2 <= max2) {
5045 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5051 gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
5052 const GValue * subtrahend)
5054 gint64 min = gst_value_get_int64_range_min (minuend);
5055 gint64 max = gst_value_get_int64_range_max (minuend);
5056 gint64 step = gst_value_get_int64_range_step (minuend);
5057 gint64 val = g_value_get_int64 (subtrahend);
5059 g_return_val_if_fail (min < max, FALSE);
5064 /* value is outside of the range, return range unchanged */
5065 if (val < min || val > max || val % step) {
5067 gst_value_init_and_copy (dest, minuend);
5070 /* max must be MAXINT64 too as val <= max */
5071 if (val >= G_MAXINT64 - step + 1) {
5075 /* min must be MININT64 too as val >= max */
5076 if (val <= G_MININT64 + step - 1) {
5081 gst_value_create_new_int64_range (dest, min, val - step, val + step, max,
5088 gst_value_subtract_int64_range_int64_range (GValue * dest,
5089 const GValue * minuend, const GValue * subtrahend)
5091 gint64 min1 = gst_value_get_int64_range_min (minuend);
5092 gint64 max1 = gst_value_get_int64_range_max (minuend);
5093 gint64 step1 = gst_value_get_int64_range_step (minuend);
5094 gint64 min2 = gst_value_get_int64_range_min (subtrahend);
5095 gint64 max2 = gst_value_get_int64_range_max (subtrahend);
5096 gint64 step2 = gst_value_get_int64_range_step (subtrahend);
5099 if (step1 != step2) {
5110 if (max2 >= max1 && min2 <= min1) {
5112 } else if (max2 >= max1) {
5113 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5114 max1), step, 0, step);
5115 } else if (min2 <= min1) {
5116 return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1),
5117 max1, step, 0, step);
5119 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5120 max1), MAX (max2 + step, min1), max1, step);
5125 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
5126 const GValue * subtrahend)
5128 gdouble min = gst_value_get_double_range_min (subtrahend);
5129 gdouble max = gst_value_get_double_range_max (subtrahend);
5130 gdouble val = g_value_get_double (minuend);
5132 if (val < min || val > max) {
5134 gst_value_init_and_copy (dest, minuend);
5141 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
5142 const GValue * subtrahend)
5144 /* since we don't have open ranges, we cannot create a hole in
5145 * a double range. We return the original range */
5147 gst_value_init_and_copy (dest, minuend);
5152 gst_value_subtract_double_range_double_range (GValue * dest,
5153 const GValue * minuend, const GValue * subtrahend)
5155 /* since we don't have open ranges, we have to approximate */
5156 /* done like with ints */
5157 gdouble min1 = gst_value_get_double_range_min (minuend);
5158 gdouble max2 = gst_value_get_double_range_max (minuend);
5159 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
5160 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
5163 GValue *pv1, *pv2; /* yeah, hungarian! */
5165 if (min1 < max1 && min2 < max2) {
5168 } else if (min1 < max1) {
5171 } else if (min2 < max2) {
5182 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
5183 gst_value_set_double_range (pv1, min1, max1);
5186 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
5187 gst_value_set_double_range (pv2, min2, max2);
5190 if (min1 < max1 && min2 < max2) {
5191 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5197 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
5198 const GValue * subtrahend)
5201 GValue subtraction = { 0, };
5202 gboolean ret = FALSE;
5204 size = VALUE_LIST_SIZE (minuend);
5205 for (i = 0; i < size; i++) {
5206 const GValue *cur = VALUE_LIST_GET_VALUE (minuend, i);
5208 /* quicker version when we can discard the result */
5210 if (gst_value_subtract (NULL, cur, subtrahend)) {
5217 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
5219 gst_value_move (dest, &subtraction);
5221 } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST
5222 && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) {
5223 _gst_value_list_append_and_take_value (dest, &subtraction);
5227 gst_value_move (&temp, dest);
5228 gst_value_list_concat_and_take_values (dest, &temp, &subtraction);
5236 gst_value_subtract_list (GValue * dest, const GValue * minuend,
5237 const GValue * subtrahend)
5240 GValue data[2] = { {0,}, {0,} };
5241 GValue *subtraction = &data[0], *result = &data[1];
5243 gst_value_init_and_copy (result, minuend);
5244 size = VALUE_LIST_SIZE (subtrahend);
5245 for (i = 0; i < size; i++) {
5246 const GValue *cur = VALUE_LIST_GET_VALUE (subtrahend, i);
5248 if (gst_value_subtract (subtraction, result, cur)) {
5249 GValue *temp = result;
5251 result = subtraction;
5253 g_value_unset (subtraction);
5255 g_value_unset (result);
5260 gst_value_move (dest, result);
5262 g_value_unset (result);
5268 gst_value_subtract_fraction_fraction_range (GValue * dest,
5269 const GValue * minuend, const GValue * subtrahend)
5271 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
5272 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
5273 GstValueCompareFunc compare;
5275 if ((compare = gst_value_get_compare_func (minuend))) {
5276 /* subtracting a range from an fraction only works if the fraction
5277 * is not in the range */
5278 if (gst_value_compare_with_func (minuend, min, compare) ==
5279 GST_VALUE_LESS_THAN ||
5280 gst_value_compare_with_func (minuend, max, compare) ==
5281 GST_VALUE_GREATER_THAN) {
5282 /* and the result is the value */
5284 gst_value_init_and_copy (dest, minuend);
5292 gst_value_subtract_fraction_range_fraction (GValue * dest,
5293 const GValue * minuend, const GValue * subtrahend)
5295 /* since we don't have open ranges, we cannot create a hole in
5296 * a range. We return the original range */
5298 gst_value_init_and_copy (dest, minuend);
5303 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
5304 const GValue * minuend, const GValue * subtrahend)
5306 /* since we don't have open ranges, we have to approximate */
5307 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
5308 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
5309 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
5310 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
5311 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
5315 GValue *pv1, *pv2; /* yeah, hungarian! */
5316 GstValueCompareFunc compare;
5318 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
5319 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
5321 compare = gst_value_get_compare_func (min1);
5322 g_return_val_if_fail (compare, FALSE);
5324 cmp1 = gst_value_compare_with_func (max2, max1, compare);
5325 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5326 if (cmp1 == GST_VALUE_LESS_THAN)
5328 cmp1 = gst_value_compare_with_func (min1, min2, compare);
5329 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5330 if (cmp1 == GST_VALUE_GREATER_THAN)
5333 cmp1 = gst_value_compare_with_func (min1, max1, compare);
5334 cmp2 = gst_value_compare_with_func (min2, max2, compare);
5336 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5339 } else if (cmp1 == GST_VALUE_LESS_THAN) {
5342 } else if (cmp2 == GST_VALUE_LESS_THAN) {
5352 if (cmp1 == GST_VALUE_LESS_THAN) {
5353 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
5354 gst_value_set_fraction_range (pv1, min1, max1);
5356 if (cmp2 == GST_VALUE_LESS_THAN) {
5357 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
5358 gst_value_set_fraction_range (pv2, min2, max2);
5361 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5362 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5372 * gst_value_get_compare_func:
5373 * @value1: a value to get the compare function for
5375 * Determines the compare function to be used with values of the same type as
5376 * @value1. The function can be given to gst_value_compare_with_func().
5378 * Returns: A #GstValueCompareFunc value
5380 static GstValueCompareFunc
5381 gst_value_get_compare_func (const GValue * value1)
5383 GstValueTable *table, *best = NULL;
5387 type1 = G_VALUE_TYPE (value1);
5389 /* this is a fast check */
5390 best = gst_value_hash_lookup_type (type1);
5393 if (G_UNLIKELY (!best || !best->compare)) {
5394 guint len = gst_value_table->len;
5397 for (i = 0; i < len; i++) {
5398 table = &g_array_index (gst_value_table, GstValueTable, i);
5399 if (table->compare && g_type_is_a (type1, table->type)) {
5400 if (!best || g_type_is_a (table->type, best->type))
5405 if (G_LIKELY (best))
5406 return best->compare;
5411 static inline gboolean
5412 gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2)
5414 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5417 return gst_value_get_compare_func (value1) != NULL;
5421 * gst_value_can_compare:
5422 * @value1: a value to compare
5423 * @value2: another value to compare
5425 * Determines if @value1 and @value2 can be compared.
5427 * Returns: %TRUE if the values can be compared
5430 gst_value_can_compare (const GValue * value1, const GValue * value2)
5432 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5433 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5435 return gst_value_can_compare_unchecked (value1, value2);
5439 gst_value_list_equals_range (const GValue * list, const GValue * value)
5441 const GValue *first;
5444 g_assert (G_IS_VALUE (list));
5445 g_assert (G_IS_VALUE (value));
5446 g_assert (GST_VALUE_HOLDS_LIST (list));
5448 /* TODO: compare against an empty list ? No type though... */
5449 list_size = VALUE_LIST_SIZE (list);
5453 /* compare the basic types - they have to match */
5454 first = VALUE_LIST_GET_VALUE (list, 0);
5455 #define CHECK_TYPES(type,prefix) \
5456 (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value))
5457 if (CHECK_TYPES (INT, G)) {
5458 const gint rmin = gst_value_get_int_range_min (value);
5459 const gint rmax = gst_value_get_int_range_max (value);
5460 const gint rstep = gst_value_get_int_range_step (value);
5463 /* note: this will overflow for min 0 and max INT_MAX, but this
5464 would only be equal to a list of INT_MAX elements, which seems
5466 if (list_size != rmax / rstep - rmin / rstep + 1)
5468 for (n = 0; n < list_size; ++n) {
5469 gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n));
5470 if (v < rmin || v > rmax || v % rstep) {
5475 } else if (CHECK_TYPES (INT64, G)) {
5476 const gint64 rmin = gst_value_get_int64_range_min (value);
5477 const gint64 rmax = gst_value_get_int64_range_max (value);
5478 const gint64 rstep = gst_value_get_int64_range_step (value);
5479 GST_DEBUG ("List/range of int64s");
5482 if (list_size != rmax / rstep - rmin / rstep + 1)
5484 for (n = 0; n < list_size; ++n) {
5485 gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n));
5486 if (v < rmin || v > rmax || v % rstep)
5493 /* other combinations don't make sense for equality */
5497 /* "Pure" variant of gst_value_compare which is guaranteed to
5498 * not have list arguments and therefore does basic comparisions
5501 _gst_value_compare_nolist (const GValue * value1, const GValue * value2)
5503 GstValueCompareFunc compare;
5505 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5506 return GST_VALUE_UNORDERED;
5508 compare = gst_value_get_compare_func (value1);
5510 return compare (value1, value2);
5513 g_critical ("unable to compare values of type %s\n",
5514 g_type_name (G_VALUE_TYPE (value1)));
5515 return GST_VALUE_UNORDERED;
5519 * gst_value_compare:
5520 * @value1: a value to compare
5521 * @value2: another value to compare
5523 * Compares @value1 and @value2. If @value1 and @value2 cannot be
5524 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
5525 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned.
5526 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned.
5527 * If the values are equal, GST_VALUE_EQUAL is returned.
5529 * Returns: comparison result
5532 gst_value_compare (const GValue * value1, const GValue * value2)
5534 gboolean value1_is_list;
5535 gboolean value2_is_list;
5537 g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
5538 g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN);
5540 value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST;
5541 value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST;
5543 /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal),
5544 as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
5545 if (value1_is_list && !value2_is_list) {
5548 if (gst_value_list_equals_range (value1, value2)) {
5549 return GST_VALUE_EQUAL;
5552 n = gst_value_list_get_size (value1);
5554 return GST_VALUE_UNORDERED;
5556 for (i = 0; i < n; i++) {
5559 elt = gst_value_list_get_value (value1, i);
5560 ret = gst_value_compare (elt, value2);
5561 if (ret != GST_VALUE_EQUAL && n == 1)
5563 else if (ret != GST_VALUE_EQUAL)
5564 return GST_VALUE_UNORDERED;
5567 return GST_VALUE_EQUAL;
5568 } else if (value2_is_list && !value1_is_list) {
5571 if (gst_value_list_equals_range (value2, value1)) {
5572 return GST_VALUE_EQUAL;
5575 n = gst_value_list_get_size (value2);
5577 return GST_VALUE_UNORDERED;
5579 for (i = 0; i < n; i++) {
5582 elt = gst_value_list_get_value (value2, i);
5583 ret = gst_value_compare (elt, value1);
5584 if (ret != GST_VALUE_EQUAL && n == 1)
5586 else if (ret != GST_VALUE_EQUAL)
5587 return GST_VALUE_UNORDERED;
5590 return GST_VALUE_EQUAL;
5593 /* And now handle the generic case */
5594 return _gst_value_compare_nolist (value1, value2);
5598 * gst_value_compare_with_func:
5599 * @value1: a value to compare
5600 * @value2: another value to compare
5601 * @compare: compare function
5603 * Compares @value1 and @value2 using the @compare function. Works like
5604 * gst_value_compare() but allows to save time determining the compare function
5607 * Returns: comparison result
5610 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
5611 GstValueCompareFunc compare)
5615 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5616 return GST_VALUE_UNORDERED;
5618 return compare (value1, value2);
5624 * gst_value_can_union:
5625 * @value1: a value to union
5626 * @value2: another value to union
5628 * Determines if @value1 and @value2 can be non-trivially unioned.
5629 * Any two values can be trivially unioned by adding both of them
5630 * to a GstValueList. However, certain types have the possibility
5631 * to be unioned in a simpler way. For example, an integer range
5632 * and an integer can be unioned if the integer is a subset of the
5633 * integer range. If there is the possibility that two values can
5634 * be unioned, this function returns %TRUE.
5636 * Returns: %TRUE if there is a function allowing the two values to
5640 gst_value_can_union (const GValue * value1, const GValue * value2)
5642 GstValueUnionInfo *union_info;
5645 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5646 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5648 len = gst_value_union_funcs->len;
5650 for (i = 0; i < len; i++) {
5651 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5652 if (union_info->type1 == G_VALUE_TYPE (value1) &&
5653 union_info->type2 == G_VALUE_TYPE (value2))
5655 if (union_info->type1 == G_VALUE_TYPE (value2) &&
5656 union_info->type2 == G_VALUE_TYPE (value1))
5665 * @dest: (out caller-allocates): the destination value
5666 * @value1: a value to union
5667 * @value2: another value to union
5669 * Creates a GValue corresponding to the union of @value1 and @value2.
5671 * Returns: %TRUE if the union succeeded.
5674 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
5676 const GstValueUnionInfo *union_info;
5680 g_return_val_if_fail (dest != NULL, FALSE);
5681 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5682 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5683 g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2),
5686 len = gst_value_union_funcs->len;
5687 type1 = G_VALUE_TYPE (value1);
5688 type2 = G_VALUE_TYPE (value2);
5690 for (i = 0; i < len; i++) {
5691 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5692 if (union_info->type1 == type1 && union_info->type2 == type2) {
5693 return union_info->func (dest, value1, value2);
5695 if (union_info->type1 == type2 && union_info->type2 == type1) {
5696 return union_info->func (dest, value2, value1);
5700 gst_value_list_concat (dest, value1, value2);
5704 /* gst_value_register_union_func: (skip)
5705 * @type1: a type to union
5706 * @type2: another type to union
5707 * @func: a function that implements creating a union between the two types
5709 * Registers a union function that can create a union between #GValue items
5710 * of the type @type1 and @type2.
5712 * Union functions should be registered at startup before any pipelines are
5713 * started, as gst_value_register_union_func() is not thread-safe and cannot
5714 * be used at the same time as gst_value_union() or gst_value_can_union().
5717 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
5719 GstValueUnionInfo union_info;
5721 union_info.type1 = type1;
5722 union_info.type2 = type2;
5723 union_info.func = func;
5725 g_array_append_val (gst_value_union_funcs, union_info);
5731 * gst_value_can_intersect:
5732 * @value1: a value to intersect
5733 * @value2: another value to intersect
5735 * Determines if intersecting two values will produce a valid result.
5736 * Two values will produce a valid intersection if they have the same
5739 * Returns: %TRUE if the values can intersect
5742 gst_value_can_intersect (const GValue * value1, const GValue * value2)
5744 GstValueIntersectInfo *intersect_info;
5748 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5749 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5751 type1 = G_VALUE_TYPE (value1);
5752 type2 = G_VALUE_TYPE (value2);
5754 /* practically all GstValue types have a compare function (_can_compare=TRUE)
5755 * GstStructure and GstCaps have not, but are intersectable */
5760 if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST)
5763 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5764 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5765 GType type1, type2, flagset_type;
5767 type1 = G_VALUE_TYPE (value1);
5768 type2 = G_VALUE_TYPE (value2);
5769 flagset_type = GST_TYPE_FLAG_SET;
5771 /* Allow intersection with the generic FlagSet type, on one
5772 * side, but not 2 different subtypes - that makes no sense */
5773 if (type1 == type2 || type1 == flagset_type || type2 == flagset_type)
5777 /* check registered intersect functions */
5778 len = gst_value_intersect_funcs->len;
5779 for (i = 0; i < len; i++) {
5780 intersect_info = &g_array_index (gst_value_intersect_funcs,
5781 GstValueIntersectInfo, i);
5782 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
5783 (intersect_info->type1 == type2 && intersect_info->type2 == type1))
5787 return gst_value_can_compare_unchecked (value1, value2);
5791 * gst_value_intersect:
5792 * @dest: (out caller-allocates) (transfer full) (allow-none):
5793 * a uninitialized #GValue that will hold the calculated
5794 * intersection value. May be %NULL if the resulting set if not
5796 * @value1: a value to intersect
5797 * @value2: another value to intersect
5799 * Calculates the intersection of two values. If the values have
5800 * a non-empty intersection, the value representing the intersection
5801 * is placed in @dest, unless %NULL. If the intersection is non-empty,
5802 * @dest is not modified.
5804 * Returns: %TRUE if the intersection is non-empty
5807 gst_value_intersect (GValue * dest, const GValue * value1,
5808 const GValue * value2)
5810 GstValueIntersectInfo *intersect_info;
5814 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5815 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5817 type1 = G_VALUE_TYPE (value1);
5818 type2 = G_VALUE_TYPE (value2);
5820 /* special cases first */
5821 if (type1 == GST_TYPE_LIST)
5822 return gst_value_intersect_list (dest, value1, value2);
5823 if (type2 == GST_TYPE_LIST)
5824 return gst_value_intersect_list (dest, value2, value1);
5826 if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) {
5828 gst_value_init_and_copy (dest, value1);
5832 len = gst_value_intersect_funcs->len;
5833 for (i = 0; i < len; i++) {
5834 intersect_info = &g_array_index (gst_value_intersect_funcs,
5835 GstValueIntersectInfo, i);
5836 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
5837 return intersect_info->func (dest, value1, value2);
5839 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
5840 return intersect_info->func (dest, value2, value1);
5844 /* Failed to find a direct intersection, check if these are
5845 * GstFlagSet sub-types. */
5846 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5847 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5848 return gst_value_intersect_flagset_flagset (dest, value1, value2);
5856 /* gst_value_register_intersect_func: (skip)
5857 * @type1: the first type to intersect
5858 * @type2: the second type to intersect
5859 * @func: the intersection function
5861 * Registers a function that is called to calculate the intersection
5862 * of the values having the types @type1 and @type2.
5864 * Intersect functions should be registered at startup before any pipelines are
5865 * started, as gst_value_register_intersect_func() is not thread-safe and
5866 * cannot be used at the same time as gst_value_intersect() or
5867 * gst_value_can_intersect().
5870 gst_value_register_intersect_func (GType type1, GType type2,
5871 GstValueIntersectFunc func)
5873 GstValueIntersectInfo intersect_info;
5875 intersect_info.type1 = type1;
5876 intersect_info.type2 = type2;
5877 intersect_info.func = func;
5879 g_array_append_val (gst_value_intersect_funcs, intersect_info);
5886 * gst_value_subtract:
5887 * @dest: (out caller-allocates) (allow-none): the destination value
5888 * for the result if the subtraction is not empty. May be %NULL,
5889 * in which case the resulting set will not be computed, which can
5890 * give a fair speedup.
5891 * @minuend: the value to subtract from
5892 * @subtrahend: the value to subtract
5894 * Subtracts @subtrahend from @minuend and stores the result in @dest.
5895 * Note that this means subtraction as in sets, not as in mathematics.
5897 * Returns: %TRUE if the subtraction is not empty
5900 gst_value_subtract (GValue * dest, const GValue * minuend,
5901 const GValue * subtrahend)
5903 GstValueSubtractInfo *info;
5907 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5908 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5910 mtype = G_VALUE_TYPE (minuend);
5911 stype = G_VALUE_TYPE (subtrahend);
5913 /* special cases first */
5914 if (mtype == GST_TYPE_LIST)
5915 return gst_value_subtract_from_list (dest, minuend, subtrahend);
5916 if (stype == GST_TYPE_LIST)
5917 return gst_value_subtract_list (dest, minuend, subtrahend);
5919 len = gst_value_subtract_funcs->len;
5920 for (i = 0; i < len; i++) {
5921 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5922 if (info->minuend == mtype && info->subtrahend == stype) {
5923 return info->func (dest, minuend, subtrahend);
5927 if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) {
5929 gst_value_init_and_copy (dest, minuend);
5938 gst_value_subtract (GValue * dest, const GValue * minuend,
5939 const GValue * subtrahend)
5941 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
5943 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
5944 gst_value_serialize (subtrahend),
5945 ret ? gst_value_serialize (dest) : "---");
5951 * gst_value_can_subtract:
5952 * @minuend: the value to subtract from
5953 * @subtrahend: the value to subtract
5955 * Checks if it's possible to subtract @subtrahend from @minuend.
5957 * Returns: %TRUE if a subtraction is possible
5960 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
5962 GstValueSubtractInfo *info;
5966 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5967 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5969 mtype = G_VALUE_TYPE (minuend);
5970 stype = G_VALUE_TYPE (subtrahend);
5973 if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST)
5975 if (mtype == GST_TYPE_STRUCTURE || stype == GST_TYPE_STRUCTURE)
5978 len = gst_value_subtract_funcs->len;
5979 for (i = 0; i < len; i++) {
5980 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5981 if (info->minuend == mtype && info->subtrahend == stype)
5985 return gst_value_can_compare_unchecked (minuend, subtrahend);
5988 /* gst_value_register_subtract_func: (skip)
5989 * @minuend_type: type of the minuend
5990 * @subtrahend_type: type of the subtrahend
5991 * @func: function to use
5993 * Registers @func as a function capable of subtracting the values of
5994 * @subtrahend_type from values of @minuend_type.
5996 * Subtract functions should be registered at startup before any pipelines are
5997 * started, as gst_value_register_subtract_func() is not thread-safe and
5998 * cannot be used at the same time as gst_value_subtract().
6001 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
6002 GstValueSubtractFunc func)
6004 GstValueSubtractInfo info;
6006 g_return_if_fail (!gst_type_is_fixed (minuend_type)
6007 || !gst_type_is_fixed (subtrahend_type));
6009 info.minuend = minuend_type;
6010 info.subtrahend = subtrahend_type;
6013 g_array_append_val (gst_value_subtract_funcs, info);
6017 * gst_value_register:
6018 * @table: structure containing functions to register
6020 * Registers functions to perform calculations on #GValue items of a given
6021 * type. Each type can only be added once.
6024 gst_value_register (const GstValueTable * table)
6026 GstValueTable *found;
6028 g_return_if_fail (table != NULL);
6030 g_array_append_val (gst_value_table, *table);
6032 found = gst_value_hash_lookup_type (table->type);
6034 g_warning ("adding type %s multiple times", g_type_name (table->type));
6036 /* FIXME: we're not really doing the const justice, we assume the table is
6038 gst_value_hash_add_type (table->type, table);
6042 * gst_value_init_and_copy:
6043 * @dest: (out caller-allocates): the target value
6044 * @src: the source value
6046 * Initialises the target value to be of the same type as source and then copies
6047 * the contents from source to target.
6050 gst_value_init_and_copy (GValue * dest, const GValue * src)
6052 g_return_if_fail (G_IS_VALUE (src));
6053 g_return_if_fail (dest != NULL);
6055 g_value_init (dest, G_VALUE_TYPE (src));
6056 g_value_copy (src, dest);
6059 /* move src into dest and clear src */
6061 gst_value_move (GValue * dest, GValue * src)
6063 g_assert (G_IS_VALUE (src));
6064 g_assert (dest != NULL);
6067 memset (src, 0, sizeof (GValue));
6071 * gst_value_serialize:
6072 * @value: a #GValue to serialize
6074 * tries to transform the given @value into a string representation that allows
6075 * getting back this string later on using gst_value_deserialize().
6077 * Free-function: g_free
6079 * Returns: (transfer full) (nullable): the serialization for @value
6080 * or %NULL if none exists
6083 gst_value_serialize (const GValue * value)
6086 GValue s_val = { 0 };
6087 GstValueTable *table, *best;
6091 g_return_val_if_fail (G_IS_VALUE (value), NULL);
6093 type = G_VALUE_TYPE (value);
6095 best = gst_value_hash_lookup_type (type);
6097 if (G_UNLIKELY (!best || !best->serialize)) {
6098 len = gst_value_table->len;
6100 for (i = 0; i < len; i++) {
6101 table = &g_array_index (gst_value_table, GstValueTable, i);
6102 if (table->serialize && g_type_is_a (type, table->type)) {
6103 if (!best || g_type_is_a (table->type, best->type))
6108 if (G_LIKELY (best))
6109 return best->serialize (value);
6111 g_value_init (&s_val, G_TYPE_STRING);
6112 if (g_value_transform (value, &s_val)) {
6113 s = gst_string_wrap (g_value_get_string (&s_val));
6117 g_value_unset (&s_val);
6123 * gst_value_deserialize:
6124 * @dest: (out caller-allocates): #GValue to fill with contents of
6126 * @src: string to deserialize
6128 * Tries to deserialize a string into the type specified by the given GValue.
6129 * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
6131 * Returns: %TRUE on success
6134 gst_value_deserialize (GValue * dest, const gchar * src)
6136 GstValueTable *table, *best;
6140 g_return_val_if_fail (src != NULL, FALSE);
6141 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
6143 type = G_VALUE_TYPE (dest);
6145 best = gst_value_hash_lookup_type (type);
6146 if (G_UNLIKELY (!best || !best->deserialize)) {
6147 len = gst_value_table->len;
6149 for (i = 0; i < len; i++) {
6150 table = &g_array_index (gst_value_table, GstValueTable, i);
6151 if (table->deserialize && g_type_is_a (type, table->type)) {
6152 if (!best || g_type_is_a (table->type, best->type))
6157 if (G_LIKELY (best))
6158 return best->deserialize (dest, src);
6164 structure_field_is_fixed (GQuark field_id, const GValue * val,
6167 return gst_value_is_fixed (val);
6171 * gst_value_is_fixed:
6172 * @value: the #GValue to check
6174 * Tests if the given GValue, if available in a GstStructure (or any other
6175 * container) contains a "fixed" (which means: one value) or an "unfixed"
6176 * (which means: multiple possible values, such as data lists or data
6179 * Returns: true if the value is "fixed".
6183 gst_value_is_fixed (const GValue * value)
6187 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
6189 type = G_VALUE_TYPE (value);
6191 /* the most common types are just basic plain glib types */
6192 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
6196 if (type == GST_TYPE_ARRAY) {
6200 /* check recursively */
6201 size = gst_value_array_get_size (value);
6202 for (n = 0; n < size; n++) {
6203 kid = gst_value_array_get_value (value, n);
6204 if (!gst_value_is_fixed (kid))
6208 } else if (GST_VALUE_HOLDS_FLAG_SET (value)) {
6209 /* Flagsets are only fixed if there are no 'don't care' bits */
6210 return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT);
6211 } else if (GST_VALUE_HOLDS_STRUCTURE (value)) {
6212 return gst_structure_foreach (gst_value_get_structure (value),
6213 structure_field_is_fixed, NULL);
6215 return gst_type_is_fixed (type);
6220 * @dest: the #GValue destination
6221 * @src: the #GValue to fixate
6223 * Fixate @src into a new value @dest.
6224 * For ranges, the first element is taken. For lists and arrays, the
6225 * first item is fixated and returned.
6226 * If @src is already fixed, this function returns %FALSE.
6228 * Returns: %TRUE if @dest contains a fixated version of @src.
6231 gst_value_fixate (GValue * dest, const GValue * src)
6233 g_return_val_if_fail (G_IS_VALUE (src), FALSE);
6234 g_return_val_if_fail (dest != NULL, FALSE);
6236 if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
6237 g_value_init (dest, G_TYPE_INT);
6238 g_value_set_int (dest, gst_value_get_int_range_min (src));
6239 } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
6240 g_value_init (dest, G_TYPE_DOUBLE);
6241 g_value_set_double (dest, gst_value_get_double_range_min (src));
6242 } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
6243 gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
6244 } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
6245 GValue temp = { 0 };
6247 /* list could be empty */
6248 if (gst_value_list_get_size (src) <= 0)
6251 gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
6253 if (!gst_value_fixate (dest, &temp)) {
6254 gst_value_move (dest, &temp);
6256 g_value_unset (&temp);
6258 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
6259 gboolean res = FALSE;
6262 len = gst_value_array_get_size (src);
6263 g_value_init (dest, GST_TYPE_ARRAY);
6264 for (n = 0; n < len; n++) {
6266 const GValue *orig_kid = gst_value_array_get_value (src, n);
6268 if (!gst_value_fixate (&kid, orig_kid))
6269 gst_value_init_and_copy (&kid, orig_kid);
6272 _gst_value_array_append_and_take_value (dest, &kid);
6276 g_value_unset (dest);
6279 } else if (GST_VALUE_HOLDS_FLAG_SET (src)) {
6282 if (gst_value_get_flagset_mask (src) == GST_FLAG_SET_MASK_EXACT)
6283 return FALSE; /* Already fixed */
6285 flags = gst_value_get_flagset_flags (src);
6286 g_value_init (dest, G_VALUE_TYPE (src));
6287 gst_value_set_flagset (dest, flags, GST_FLAG_SET_MASK_EXACT);
6289 } else if (GST_VALUE_HOLDS_STRUCTURE (src)) {
6290 const GstStructure *str = (GstStructure *) gst_value_get_structure (src);
6296 kid = gst_structure_copy (str);
6297 gst_structure_fixate (kid);
6298 g_value_init (dest, GST_TYPE_STRUCTURE);
6299 gst_value_set_structure (dest, kid);
6300 gst_structure_free (kid);
6313 /* helper functions */
6315 gst_value_init_fraction (GValue * value)
6317 value->data[0].v_int = 0;
6318 value->data[1].v_int = 1;
6322 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
6324 dest_value->data[0].v_int = src_value->data[0].v_int;
6325 dest_value->data[1].v_int = src_value->data[1].v_int;
6329 gst_value_collect_fraction (GValue * value, guint n_collect_values,
6330 GTypeCValue * collect_values, guint collect_flags)
6332 if (n_collect_values != 2)
6333 return g_strdup_printf ("not enough value locations for `%s' passed",
6334 G_VALUE_TYPE_NAME (value));
6335 if (collect_values[1].v_int == 0)
6336 return g_strdup_printf ("passed '0' as denominator for `%s'",
6337 G_VALUE_TYPE_NAME (value));
6338 if (collect_values[0].v_int < -G_MAXINT)
6341 ("passed value smaller than -G_MAXINT as numerator for `%s'",
6342 G_VALUE_TYPE_NAME (value));
6343 if (collect_values[1].v_int < -G_MAXINT)
6346 ("passed value smaller than -G_MAXINT as denominator for `%s'",
6347 G_VALUE_TYPE_NAME (value));
6349 gst_value_set_fraction (value,
6350 collect_values[0].v_int, collect_values[1].v_int);
6356 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
6357 GTypeCValue * collect_values, guint collect_flags)
6359 gint *numerator = collect_values[0].v_pointer;
6360 gint *denominator = collect_values[1].v_pointer;
6363 return g_strdup_printf ("numerator for `%s' passed as NULL",
6364 G_VALUE_TYPE_NAME (value));
6366 return g_strdup_printf ("denominator for `%s' passed as NULL",
6367 G_VALUE_TYPE_NAME (value));
6369 *numerator = value->data[0].v_int;
6370 *denominator = value->data[1].v_int;
6376 * gst_value_set_fraction:
6377 * @value: a GValue initialized to #GST_TYPE_FRACTION
6378 * @numerator: the numerator of the fraction
6379 * @denominator: the denominator of the fraction
6381 * Sets @value to the fraction specified by @numerator over @denominator.
6382 * The fraction gets reduced to the smallest numerator and denominator,
6383 * and if necessary the sign is moved to the numerator.
6386 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
6390 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
6391 g_return_if_fail (denominator != 0);
6392 g_return_if_fail (denominator >= -G_MAXINT);
6393 g_return_if_fail (numerator >= -G_MAXINT);
6395 /* normalize sign */
6396 if (denominator < 0) {
6397 numerator = -numerator;
6398 denominator = -denominator;
6401 /* check for reduction */
6402 gcd = gst_util_greatest_common_divisor (numerator, denominator);
6408 g_assert (denominator > 0);
6410 value->data[0].v_int = numerator;
6411 value->data[1].v_int = denominator;
6415 * gst_value_get_fraction_numerator:
6416 * @value: a GValue initialized to #GST_TYPE_FRACTION
6418 * Gets the numerator of the fraction specified by @value.
6420 * Returns: the numerator of the fraction.
6423 gst_value_get_fraction_numerator (const GValue * value)
6425 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
6427 return value->data[0].v_int;
6431 * gst_value_get_fraction_denominator:
6432 * @value: a GValue initialized to #GST_TYPE_FRACTION
6434 * Gets the denominator of the fraction specified by @value.
6436 * Returns: the denominator of the fraction.
6439 gst_value_get_fraction_denominator (const GValue * value)
6441 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
6443 return value->data[1].v_int;
6447 * gst_value_fraction_multiply:
6448 * @product: a GValue initialized to #GST_TYPE_FRACTION
6449 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
6450 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
6452 * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets
6453 * @product to the product of the two fractions.
6455 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6458 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
6459 const GValue * factor2)
6461 gint n1, n2, d1, d2;
6464 g_return_val_if_fail (product != NULL, FALSE);
6465 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
6466 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
6468 n1 = factor1->data[0].v_int;
6469 n2 = factor2->data[0].v_int;
6470 d1 = factor1->data[1].v_int;
6471 d2 = factor2->data[1].v_int;
6473 if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
6476 gst_value_set_fraction (product, res_n, res_d);
6482 * gst_value_fraction_subtract:
6483 * @dest: a GValue initialized to #GST_TYPE_FRACTION
6484 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
6485 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
6487 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
6489 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6492 gst_value_fraction_subtract (GValue * dest,
6493 const GValue * minuend, const GValue * subtrahend)
6495 gint n1, n2, d1, d2;
6498 g_return_val_if_fail (dest != NULL, FALSE);
6499 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
6500 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
6502 n1 = minuend->data[0].v_int;
6503 n2 = subtrahend->data[0].v_int;
6504 d1 = minuend->data[1].v_int;
6505 d2 = subtrahend->data[1].v_int;
6507 if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d))
6509 gst_value_set_fraction (dest, res_n, res_d);
6515 gst_value_serialize_fraction (const GValue * value)
6517 gint32 numerator = value->data[0].v_int;
6518 gint32 denominator = value->data[1].v_int;
6519 gboolean positive = TRUE;
6521 /* get the sign and make components absolute */
6522 if (numerator < 0) {
6523 numerator = -numerator;
6524 positive = !positive;
6526 if (denominator < 0) {
6527 denominator = -denominator;
6528 positive = !positive;
6531 return g_strdup_printf ("%s%d/%d",
6532 positive ? "" : "-", numerator, denominator);
6536 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
6541 if (G_UNLIKELY (s == NULL))
6544 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
6547 if (sscanf (s, "%d/%d%n", &num, &den, &num_chars) >= 2) {
6548 if (s[num_chars] != 0)
6553 gst_value_set_fraction (dest, num, den);
6555 } else if (g_ascii_strcasecmp (s, "1/max") == 0) {
6556 gst_value_set_fraction (dest, 1, G_MAXINT);
6558 } else if (sscanf (s, "%d%n", &num, &num_chars) >= 1) {
6559 if (s[num_chars] != 0)
6561 gst_value_set_fraction (dest, num, 1);
6563 } else if (g_ascii_strcasecmp (s, "min") == 0) {
6564 gst_value_set_fraction (dest, -G_MAXINT, 1);
6566 } else if (g_ascii_strcasecmp (s, "max") == 0) {
6567 gst_value_set_fraction (dest, G_MAXINT, 1);
6575 gst_value_transform_fraction_string (const GValue * src_value,
6576 GValue * dest_value)
6578 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
6582 gst_value_transform_string_fraction (const GValue * src_value,
6583 GValue * dest_value)
6585 if (!gst_value_deserialize_fraction (dest_value,
6586 src_value->data[0].v_pointer))
6587 /* If the deserialize fails, ensure we leave the fraction in a
6588 * valid, if incorrect, state */
6589 gst_value_set_fraction (dest_value, 0, 1);
6593 gst_value_transform_double_fraction (const GValue * src_value,
6594 GValue * dest_value)
6596 gdouble src = g_value_get_double (src_value);
6599 gst_util_double_to_fraction (src, &n, &d);
6600 gst_value_set_fraction (dest_value, n, d);
6604 gst_value_transform_float_fraction (const GValue * src_value,
6605 GValue * dest_value)
6607 gfloat src = g_value_get_float (src_value);
6610 gst_util_double_to_fraction (src, &n, &d);
6611 gst_value_set_fraction (dest_value, n, d);
6615 gst_value_transform_fraction_double (const GValue * src_value,
6616 GValue * dest_value)
6618 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
6619 ((double) src_value->data[1].v_int);
6623 gst_value_transform_fraction_float (const GValue * src_value,
6624 GValue * dest_value)
6626 dest_value->data[0].v_float = ((float) src_value->data[0].v_int) /
6627 ((float) src_value->data[1].v_int);
6631 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
6637 n1 = value1->data[0].v_int;
6638 n2 = value2->data[0].v_int;
6639 d1 = value1->data[1].v_int;
6640 d2 = value2->data[1].v_int;
6642 /* fractions are reduced when set, so we can quickly see if they're equal */
6643 if (n1 == n2 && d1 == d2)
6644 return GST_VALUE_EQUAL;
6646 if (d1 == 0 && d2 == 0)
6647 return GST_VALUE_UNORDERED;
6649 return GST_VALUE_GREATER_THAN;
6651 return GST_VALUE_LESS_THAN;
6653 ret = gst_util_fraction_compare (n1, d1, n2, d2);
6655 return GST_VALUE_LESS_THAN;
6657 return GST_VALUE_GREATER_THAN;
6659 /* Equality can't happen here because we check for that
6661 g_return_val_if_reached (GST_VALUE_UNORDERED);
6669 gst_value_compare_date (const GValue * value1, const GValue * value2)
6671 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
6672 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
6676 return GST_VALUE_EQUAL;
6678 if ((date1 == NULL || !g_date_valid (date1))
6679 && (date2 != NULL && g_date_valid (date2))) {
6680 return GST_VALUE_LESS_THAN;
6683 if ((date2 == NULL || !g_date_valid (date2))
6684 && (date1 != NULL && g_date_valid (date1))) {
6685 return GST_VALUE_GREATER_THAN;
6688 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
6689 || !g_date_valid (date2)) {
6690 return GST_VALUE_UNORDERED;
6693 j1 = g_date_get_julian (date1);
6694 j2 = g_date_get_julian (date2);
6697 return GST_VALUE_EQUAL;
6699 return GST_VALUE_LESS_THAN;
6701 return GST_VALUE_GREATER_THAN;
6705 gst_value_serialize_date (const GValue * val)
6707 const GDate *date = (const GDate *) g_value_get_boxed (val);
6709 if (date == NULL || !g_date_valid (date))
6710 return g_strdup ("9999-99-99");
6712 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
6713 g_date_get_month (date), g_date_get_day (date));
6717 gst_value_deserialize_date (GValue * dest, const gchar * s)
6719 guint year, month, day;
6721 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
6724 if (!g_date_valid_dmy (day, month, year))
6727 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
6736 gst_value_compare_date_time (const GValue * value1, const GValue * value2)
6738 const GstDateTime *date1 = (const GstDateTime *) g_value_get_boxed (value1);
6739 const GstDateTime *date2 = (const GstDateTime *) g_value_get_boxed (value2);
6742 return GST_VALUE_EQUAL;
6744 if ((date1 == NULL) && (date2 != NULL)) {
6745 return GST_VALUE_LESS_THAN;
6747 if ((date2 == NULL) && (date1 != NULL)) {
6748 return GST_VALUE_LESS_THAN;
6751 /* returns GST_VALUE_* */
6752 return __gst_date_time_compare (date1, date2);
6756 gst_value_serialize_date_time (const GValue * val)
6758 GstDateTime *date = (GstDateTime *) g_value_get_boxed (val);
6761 return g_strdup ("null");
6763 return __gst_date_time_serialize (date, TRUE);
6767 gst_value_deserialize_date_time (GValue * dest, const gchar * s)
6769 GstDateTime *datetime;
6771 if (!s || strcmp (s, "null") == 0) {
6775 datetime = gst_date_time_new_from_iso8601_string (s);
6776 if (datetime != NULL) {
6777 g_value_take_boxed (dest, datetime);
6780 GST_WARNING ("Failed to deserialize date time string '%s'", s);
6785 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
6787 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
6791 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
6793 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
6801 /* helper functions */
6803 gst_value_init_bitmask (GValue * value)
6805 value->data[0].v_uint64 = 0;
6809 gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
6811 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6815 gst_value_collect_bitmask (GValue * value, guint n_collect_values,
6816 GTypeCValue * collect_values, guint collect_flags)
6818 if (n_collect_values != 1)
6819 return g_strdup_printf ("not enough value locations for `%s' passed",
6820 G_VALUE_TYPE_NAME (value));
6822 gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
6828 gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
6829 GTypeCValue * collect_values, guint collect_flags)
6831 guint64 *bitmask = collect_values[0].v_pointer;
6834 return g_strdup_printf ("value for `%s' passed as NULL",
6835 G_VALUE_TYPE_NAME (value));
6837 *bitmask = value->data[0].v_uint64;
6843 * gst_value_set_bitmask:
6844 * @value: a GValue initialized to #GST_TYPE_BITMASK
6845 * @bitmask: the bitmask
6847 * Sets @value to the bitmask specified by @bitmask.
6850 gst_value_set_bitmask (GValue * value, guint64 bitmask)
6852 g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
6854 value->data[0].v_uint64 = bitmask;
6858 * gst_value_get_bitmask:
6859 * @value: a GValue initialized to #GST_TYPE_BITMASK
6861 * Gets the bitmask specified by @value.
6863 * Returns: the bitmask.
6866 gst_value_get_bitmask (const GValue * value)
6868 g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
6870 return value->data[0].v_uint64;
6874 gst_value_serialize_bitmask (const GValue * value)
6876 guint64 bitmask = value->data[0].v_uint64;
6878 return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
6882 gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
6884 gchar *endptr = NULL;
6887 if (G_UNLIKELY (s == NULL))
6890 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
6894 val = g_ascii_strtoull (s, &endptr, 16);
6895 if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
6897 if (val == 0 && endptr == s)
6900 gst_value_set_bitmask (dest, val);
6906 gst_value_transform_bitmask_string (const GValue * src_value,
6907 GValue * dest_value)
6909 dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
6913 gst_value_transform_string_bitmask (const GValue * src_value,
6914 GValue * dest_value)
6916 if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
6917 gst_value_set_bitmask (dest_value, 0);
6921 gst_value_transform_uint64_bitmask (const GValue * src_value,
6922 GValue * dest_value)
6924 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6928 gst_value_transform_bitmask_uint64 (const GValue * src_value,
6929 GValue * dest_value)
6931 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6935 gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
6939 v1 = value1->data[0].v_uint64;
6940 v2 = value2->data[0].v_uint64;
6943 return GST_VALUE_EQUAL;
6945 return GST_VALUE_UNORDERED;
6952 /* helper functions */
6954 gst_value_init_flagset (GValue * value)
6956 value->data[0].v_uint = 0;
6957 value->data[1].v_uint = 0;
6961 gst_value_copy_flagset (const GValue * src_value, GValue * dest_value)
6963 dest_value->data[0].v_uint = src_value->data[0].v_uint;
6964 dest_value->data[1].v_uint = src_value->data[1].v_uint;
6968 gst_value_collect_flagset (GValue * value, guint n_collect_values,
6969 GTypeCValue * collect_values, guint collect_flags)
6971 if (n_collect_values != 2)
6972 return g_strdup_printf ("not enough value locations for `%s' passed",
6973 G_VALUE_TYPE_NAME (value));
6975 gst_value_set_flagset (value,
6976 (guint) collect_values[0].v_int, (guint) collect_values[1].v_int);
6982 gst_value_lcopy_flagset (const GValue * value, guint n_collect_values,
6983 GTypeCValue * collect_values, guint collect_flags)
6985 guint *flags = collect_values[0].v_pointer;
6986 guint *mask = collect_values[1].v_pointer;
6988 *flags = value->data[0].v_uint;
6989 *mask = value->data[1].v_uint;
6995 * gst_value_set_flagset:
6996 * @value: a GValue initialized to %GST_TYPE_FLAG_SET
6997 * @flags: The value of the flags set or unset
6998 * @mask: The mask indicate which flags bits must match for comparisons
7000 * Sets @value to the flags and mask values provided in @flags and @mask.
7001 * The @flags value indicates the values of flags, the @mask represents
7002 * which bits in the flag value have been set, and which are "don't care"
7007 gst_value_set_flagset (GValue * value, guint flags, guint mask)
7009 g_return_if_fail (GST_VALUE_HOLDS_FLAG_SET (value));
7011 /* Normalise and only keep flags mentioned in the mask */
7012 value->data[0].v_uint = flags & mask;
7013 value->data[1].v_uint = mask;
7017 * gst_value_get_flagset_flags:
7018 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7020 * Retrieve the flags field of a GstFlagSet @value.
7022 * Returns: the flags field of the flagset instance.
7027 gst_value_get_flagset_flags (const GValue * value)
7029 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 0);
7031 return value->data[0].v_uint;
7035 * gst_value_get_flagset_mask:
7036 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7038 * Retrieve the mask field of a GstFlagSet @value.
7040 * Returns: the mask field of the flagset instance.
7045 gst_value_get_flagset_mask (const GValue * value)
7047 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 1);
7049 return value->data[1].v_uint;
7053 gst_value_serialize_flagset (const GValue * value)
7055 guint flags = value->data[0].v_uint;
7056 guint mask = value->data[1].v_uint;
7057 GstFlagSetClass *set_klass =
7058 (GstFlagSetClass *) g_type_class_ref (G_VALUE_TYPE (value));
7061 result = g_strdup_printf ("%x:%x", flags, mask);
7063 /* If this flag set class has an associated GFlags GType, and some
7064 * bits in the mask, serialize the bits in human-readable form to
7066 if (mask && set_klass->flags_type) {
7067 GFlagsClass *flags_klass =
7068 (GFlagsClass *) (g_type_class_ref (set_klass->flags_type));
7071 gboolean first = TRUE;
7073 g_return_val_if_fail (flags_klass, NULL);
7075 /* some bits in the mask are set, so serialize one by one, according
7076 * to whether that bit is set or cleared in the flags value */
7078 fl = g_flags_get_first_value (flags_klass, mask);
7080 /* No more bits match in the flags mask - time to stop */
7085 tmp = g_strconcat (result,
7087 (flags & fl->value) ? "+" : "/", fl->value_nick, NULL);
7095 g_type_class_unref (flags_klass);
7098 g_type_class_unref (set_klass);
7104 is_valid_flags_string (const gchar * s)
7106 /* We're looking to match +this/that+other-thing/not-this-thing type strings */
7107 return g_regex_match_simple ("^([\\+\\/][\\w\\d-]+)+$", s, G_REGEX_CASELESS,
7112 gst_value_deserialize_flagset (GValue * dest, const gchar * s)
7114 gboolean res = FALSE;
7118 if (G_UNLIKELY (s == NULL))
7121 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FLAG_SET (dest)))
7124 /* Flagset strings look like %x:%x - hex flags : hex bitmask,
7125 * 32-bit each, or like a concatenated list of flag nicks,
7126 * with either '+' or '/' in front. The first form
7127 * may optionally be followed by ':' and a set of text flag descriptions
7128 * for easier debugging */
7130 /* Try and interpret as hex form first, as it's the most efficient */
7131 /* Read the flags first */
7132 flags = strtoul (s, &next, 16);
7133 if (G_UNLIKELY ((flags == 0 && errno == EINVAL) || s == next))
7134 goto try_as_flags_string;
7135 /* Next char should be a colon */
7141 mask = strtoul (cur, &next, 16);
7142 if (G_UNLIKELY ((mask == 0 && errno == EINVAL) || cur == next))
7143 goto try_as_flags_string;
7145 /* Next char should be NULL terminator, or a ':'. If ':', we need the flag string after */
7146 if (G_UNLIKELY (next[0] == 0)) {
7156 if (g_str_equal (g_type_name (G_VALUE_TYPE (dest)), "GstFlagSet")) {
7157 /* If we're parsing a generic flag set, that can mean we're guessing
7158 * at the type in deserialising a GstStructure so at least check that
7159 * we have a valid-looking string, so we don't cause deserialisation of
7160 * other types of strings like 00:01:00:00 - https://bugzilla.gnome.org/show_bug.cgi?id=779755 */
7161 if (is_valid_flags_string (s)) {
7168 /* Otherwise, we already got a hex string for a valid non-generic flagset type */
7172 try_as_flags_string:
7175 const gchar *set_class = g_type_name (G_VALUE_TYPE (dest));
7176 GFlagsClass *flags_klass = NULL;
7179 if (g_str_equal (set_class, "GstFlagSet")) {
7180 /* There's no hope to parse the fields of generic flag set if we didn't already
7181 * catch a hex-string above */
7185 /* Flags class is the FlagSet class with 'Set' removed from the end */
7186 end = g_strrstr (set_class, "Set");
7189 gchar *class_name = g_strndup (set_class, end - set_class);
7190 GType flags_type = g_type_from_name (class_name);
7191 if (flags_type == 0) {
7192 GST_TRACE ("Looking for dynamic type %s", class_name);
7193 gst_dynamic_type_factory_load (class_name);
7196 if (flags_type != 0) {
7197 flags_klass = g_type_class_ref (flags_type);
7198 GST_TRACE ("Going to parse %s as %s", s, class_name);
7200 g_free (class_name);
7204 res = gst_value_gflags_str_to_flags (flags_klass, s, &flags, &mask);
7205 g_type_class_unref (flags_klass);
7211 gst_value_set_flagset (dest, flags, mask);
7217 gst_value_transform_flagset_string (const GValue * src_value,
7218 GValue * dest_value)
7220 dest_value->data[0].v_pointer = gst_value_serialize_flagset (src_value);
7224 gst_value_transform_string_flagset (const GValue * src_value,
7225 GValue * dest_value)
7227 if (!gst_value_deserialize_flagset (dest_value, src_value->data[0].v_pointer)) {
7228 /* If the deserialize fails, ensure we leave the flags in a
7229 * valid, if incorrect, state */
7230 gst_value_set_flagset (dest_value, 0, 0);
7235 gst_value_compare_flagset (const GValue * value1, const GValue * value2)
7240 v1 = value1->data[0].v_uint;
7241 v2 = value2->data[0].v_uint;
7243 m1 = value1->data[1].v_uint;
7244 m2 = value2->data[1].v_uint;
7246 if (v1 == v2 && m1 == m2)
7247 return GST_VALUE_EQUAL;
7249 return GST_VALUE_UNORDERED;
7252 /***********************
7253 * GstAllocationParams *
7254 ***********************/
7256 gst_value_compare_allocation_params (const GValue * value1,
7257 const GValue * value2)
7259 GstAllocationParams *v1, *v2;
7261 v1 = value1->data[0].v_pointer;
7262 v2 = value2->data[0].v_pointer;
7264 if (v1 == NULL && v1 == v2)
7265 return GST_VALUE_EQUAL;
7267 if (v1 == NULL || v2 == NULL)
7268 return GST_VALUE_UNORDERED;
7270 if (v1->flags == v2->flags && v1->align == v2->align &&
7271 v1->prefix == v2->prefix && v1->padding == v2->padding)
7272 return GST_VALUE_EQUAL;
7274 return GST_VALUE_UNORDERED;
7283 gst_value_compare_object (const GValue * value1, const GValue * value2)
7287 v1 = value1->data[0].v_pointer;
7288 v2 = value2->data[0].v_pointer;
7291 return GST_VALUE_EQUAL;
7293 return GST_VALUE_UNORDERED;
7297 gst_value_transform_object_string (const GValue * src_value,
7298 GValue * dest_value)
7303 obj = g_value_get_object (src_value);
7306 g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
7307 GST_OBJECT_NAME (obj));
7309 str = g_strdup ("NULL");
7312 dest_value->data[0].v_pointer = str;
7315 static GTypeInfo _info = {
7316 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL,
7319 static GTypeFundamentalInfo _finfo = {
7323 #define FUNC_VALUE_GET_TYPE_CLASSED(type, name, csize, flags) \
7324 GType _gst_ ## type ## _type = 0; \
7326 GType gst_ ## type ## _get_type (void) \
7328 static volatile GType gst_ ## type ## _type = 0; \
7330 if (g_once_init_enter (&gst_ ## type ## _type)) { \
7332 _info.class_size = csize; \
7333 _finfo.type_flags = flags; \
7334 _info.value_table = & _gst_ ## type ## _value_table; \
7335 _type = g_type_register_fundamental ( \
7336 g_type_fundamental_next (), \
7337 name, &_info, &_finfo, 0); \
7338 _gst_ ## type ## _type = _type; \
7339 g_once_init_leave(&gst_ ## type ## _type, _type); \
7342 return gst_ ## type ## _type; \
7345 #define FUNC_VALUE_GET_TYPE(type, name) \
7346 FUNC_VALUE_GET_TYPE_CLASSED(type, name, 0, 0)
7348 static const GTypeValueTable _gst_int_range_value_table = {
7349 gst_value_init_int_range,
7351 gst_value_copy_int_range,
7354 gst_value_collect_int_range, (char *) "pp", gst_value_lcopy_int_range
7357 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
7359 static const GTypeValueTable _gst_int64_range_value_table = {
7360 gst_value_init_int64_range,
7361 gst_value_free_int64_range,
7362 gst_value_copy_int64_range,
7365 gst_value_collect_int64_range,
7366 (char *) "pp", gst_value_lcopy_int64_range
7369 FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range");
7371 static const GTypeValueTable _gst_double_range_value_table = {
7372 gst_value_init_double_range,
7374 gst_value_copy_double_range,
7377 gst_value_collect_double_range,
7378 (char *) "pp", gst_value_lcopy_double_range
7381 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
7383 static const GTypeValueTable _gst_fraction_range_value_table = {
7384 gst_value_init_fraction_range,
7385 gst_value_free_fraction_range,
7386 gst_value_copy_fraction_range,
7389 gst_value_collect_fraction_range,
7390 (char *) "pppp", gst_value_lcopy_fraction_range
7393 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
7395 static const GTypeValueTable _gst_value_list_value_table = {
7396 gst_value_init_list_or_array,
7397 gst_value_free_list_or_array,
7398 gst_value_copy_list_or_array,
7399 gst_value_list_or_array_peek_pointer,
7401 gst_value_collect_list_or_array,
7402 (char *) "p", gst_value_lcopy_list_or_array
7405 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
7407 static const GTypeValueTable _gst_value_array_value_table = {
7408 gst_value_init_list_or_array,
7409 gst_value_free_list_or_array,
7410 gst_value_copy_list_or_array,
7411 gst_value_list_or_array_peek_pointer,
7413 gst_value_collect_list_or_array,
7414 (char *) "p", gst_value_lcopy_list_or_array
7417 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
7419 static const GTypeValueTable _gst_fraction_value_table = {
7420 gst_value_init_fraction,
7422 gst_value_copy_fraction,
7425 gst_value_collect_fraction, (char *) "pp", gst_value_lcopy_fraction
7428 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
7430 static const GTypeValueTable _gst_bitmask_value_table = {
7431 gst_value_init_bitmask,
7433 gst_value_copy_bitmask,
7436 gst_value_collect_bitmask, (char *) "p", gst_value_lcopy_bitmask
7439 FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
7441 static const GTypeValueTable _gst_flagset_value_table = {
7442 gst_value_init_flagset,
7444 gst_value_copy_flagset,
7447 gst_value_collect_flagset, (char *) "pp", gst_value_lcopy_flagset
7450 FUNC_VALUE_GET_TYPE_CLASSED (flagset, "GstFlagSet",
7451 sizeof (GstFlagSetClass), G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE);
7454 gst_g_thread_get_type (void)
7456 return G_TYPE_THREAD;
7459 #define SERIAL_VTABLE(t,c,s,d) { t, c, s, d }
7461 #define REGISTER_SERIALIZATION_CONST(_gtype, _type) \
7463 static const GstValueTable gst_value = \
7464 SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \
7465 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7466 gst_value_register (&gst_value); \
7469 #define REGISTER_SERIALIZATION(_gtype, _type) \
7471 static GstValueTable gst_value = \
7472 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7473 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7474 gst_value.type = _gtype; \
7475 gst_value_register (&gst_value); \
7478 #define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type) \
7480 static GstValueTable gst_value = \
7481 SERIAL_VTABLE (0, NULL, \
7482 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7483 gst_value.type = _gtype; \
7484 gst_value_register (&gst_value); \
7487 #define REGISTER_SERIALIZATION_COMPARE_ONLY(_gtype, _type) \
7489 static GstValueTable gst_value = \
7490 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7492 gst_value.type = _gtype; \
7493 gst_value_register (&gst_value); \
7496 /* These initial sizes are used for the tables
7497 * below, and save a couple of reallocs at startup */
7499 static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 40;
7500 static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 8;
7501 static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 16;
7502 static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 16;
7505 _priv_gst_value_initialize (void)
7508 g_array_sized_new (FALSE, FALSE, sizeof (GstValueTable),
7509 GST_VALUE_TABLE_DEFAULT_SIZE);
7510 gst_value_hash = g_hash_table_new (NULL, NULL);
7511 gst_value_union_funcs = g_array_sized_new (FALSE, FALSE,
7512 sizeof (GstValueUnionInfo), GST_VALUE_UNION_TABLE_DEFAULT_SIZE);
7513 gst_value_intersect_funcs = g_array_sized_new (FALSE, FALSE,
7514 sizeof (GstValueIntersectInfo), GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE);
7515 gst_value_subtract_funcs = g_array_sized_new (FALSE, FALSE,
7516 sizeof (GstValueSubtractInfo), GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE);
7518 REGISTER_SERIALIZATION (gst_int_range_get_type (), int_range);
7519 REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range);
7520 REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range);
7521 REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range);
7522 REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list);
7523 REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array);
7524 REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array);
7525 REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer);
7526 REGISTER_SERIALIZATION (gst_sample_get_type (), sample);
7527 REGISTER_SERIALIZATION (gst_fraction_get_type (), fraction);
7528 REGISTER_SERIALIZATION (gst_caps_get_type (), caps);
7529 REGISTER_SERIALIZATION (gst_tag_list_get_type (), tag_list);
7530 REGISTER_SERIALIZATION (G_TYPE_DATE, date);
7531 REGISTER_SERIALIZATION (gst_date_time_get_type (), date_time);
7532 REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask);
7533 REGISTER_SERIALIZATION (gst_structure_get_type (), structure);
7534 REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset);
7536 REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment);
7537 REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (),
7540 REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (),
7542 REGISTER_SERIALIZATION_COMPARE_ONLY (G_TYPE_OBJECT, object);
7544 REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double);
7545 REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float);
7547 REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string);
7548 REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean);
7549 REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum);
7551 REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags);
7553 REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int);
7555 REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64);
7556 REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long);
7558 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint);
7559 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64);
7560 REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong);
7562 REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar);
7564 REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
7566 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
7567 gst_value_transform_int_range_string);
7568 g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING,
7569 gst_value_transform_int64_range_string);
7570 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
7571 gst_value_transform_double_range_string);
7572 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
7573 gst_value_transform_fraction_range_string);
7574 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
7575 gst_value_transform_list_string);
7576 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_VALUE_ARRAY,
7577 gst_value_transform_any_list_g_value_array);
7578 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
7579 gst_value_transform_array_string);
7580 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_VALUE_ARRAY,
7581 gst_value_transform_any_list_g_value_array);
7582 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, G_TYPE_STRING,
7583 gst_value_transform_g_value_array_string);
7584 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_ARRAY,
7585 gst_value_transform_g_value_array_any_list);
7586 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_LIST,
7587 gst_value_transform_g_value_array_any_list);
7588 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
7589 gst_value_transform_fraction_string);
7590 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
7591 gst_value_transform_string_fraction);
7592 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
7593 gst_value_transform_fraction_double);
7594 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT,
7595 gst_value_transform_fraction_float);
7596 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
7597 gst_value_transform_double_fraction);
7598 g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
7599 gst_value_transform_float_fraction);
7600 g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING,
7601 gst_value_transform_date_string);
7602 g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE,
7603 gst_value_transform_string_date);
7604 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
7605 gst_value_transform_object_string);
7606 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
7607 gst_value_transform_bitmask_uint64);
7608 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
7609 gst_value_transform_bitmask_string);
7610 g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
7611 gst_value_transform_uint64_bitmask);
7612 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
7613 gst_value_transform_string_bitmask);
7615 g_value_register_transform_func (GST_TYPE_FLAG_SET, G_TYPE_STRING,
7616 gst_value_transform_flagset_string);
7617 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
7618 gst_value_transform_string_flagset);
7620 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7621 gst_value_intersect_int_int_range);
7622 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7623 gst_value_intersect_int_range_int_range);
7624 gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7625 gst_value_intersect_int64_int64_range);
7626 gst_value_register_intersect_func (GST_TYPE_INT64_RANGE,
7627 GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range);
7628 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7629 gst_value_intersect_double_double_range);
7630 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
7631 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
7632 gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY,
7633 gst_value_intersect_array);
7634 gst_value_register_intersect_func (GST_TYPE_FRACTION,
7635 GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range);
7636 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
7637 GST_TYPE_FRACTION_RANGE,
7638 gst_value_intersect_fraction_range_fraction_range);
7639 gst_value_register_intersect_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7640 gst_value_intersect_flagset_flagset);
7641 gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7642 gst_value_intersect_structure_structure);
7644 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7645 gst_value_subtract_int_int_range);
7646 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
7647 gst_value_subtract_int_range_int);
7648 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7649 gst_value_subtract_int_range_int_range);
7650 gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7651 gst_value_subtract_int64_int64_range);
7652 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64,
7653 gst_value_subtract_int64_range_int64);
7654 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE,
7655 GST_TYPE_INT64_RANGE, gst_value_subtract_int64_range_int64_range);
7656 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7657 gst_value_subtract_double_double_range);
7658 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
7659 gst_value_subtract_double_range_double);
7660 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
7661 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
7662 gst_value_register_subtract_func (GST_TYPE_FRACTION,
7663 GST_TYPE_FRACTION_RANGE, gst_value_subtract_fraction_fraction_range);
7664 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7665 GST_TYPE_FRACTION, gst_value_subtract_fraction_range_fraction);
7666 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7667 GST_TYPE_FRACTION_RANGE,
7668 gst_value_subtract_fraction_range_fraction_range);
7670 /* see bug #317246, #64994, #65041 */
7672 volatile GType date_type = G_TYPE_DATE;
7674 g_type_name (date_type);
7677 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7678 gst_value_union_int_int_range);
7679 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7680 gst_value_union_int_range_int_range);
7681 gst_value_register_union_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7682 gst_value_union_flagset_flagset);
7683 gst_value_register_union_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7684 gst_value_union_structure_structure);
7686 #if GST_VERSION_NANO == 1
7687 /* If building from git master, check starting array sizes matched actual size
7688 * so we can keep the defines in sync and save a few reallocs on startup */
7689 if (gst_value_table->len > GST_VALUE_TABLE_DEFAULT_SIZE) {
7690 GST_ERROR ("Wrong initial gst_value_table size. "
7691 "Please set GST_VALUE_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7692 gst_value_table->len);
7694 if (gst_value_union_funcs->len > GST_VALUE_UNION_TABLE_DEFAULT_SIZE) {
7695 GST_ERROR ("Wrong initial gst_value_union_funcs table size. "
7696 "Please set GST_VALUE_UNION_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7697 gst_value_union_funcs->len);
7699 if (gst_value_intersect_funcs->len > GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE) {
7700 GST_ERROR ("Wrong initial gst_value_intersect_funcs table size. "
7701 "Please set GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7702 gst_value_intersect_funcs->len);
7704 if (gst_value_subtract_funcs->len > GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE) {
7705 GST_ERROR ("Wrong initial gst_value_subtract_funcs table size. "
7706 "Please set GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7707 gst_value_subtract_funcs->len);
7712 /* Implement these if needed */
7713 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
7714 gst_value_union_fraction_fraction_range);
7715 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
7716 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);
7721 gst_flagset_class_init (gpointer g_class, gpointer class_data)
7723 GstFlagSetClass *f_class = (GstFlagSetClass *) (g_class);
7724 f_class->flags_type = (GType) GPOINTER_TO_SIZE (class_data);
7728 * gst_flagset_register:
7729 * @flags_type: a #GType of a #G_TYPE_FLAGS type.
7731 * Create a new sub-class of #GST_TYPE_FLAG_SET
7732 * which will pretty-print the human-readable flags
7733 * when serializing, for easier debugging.
7738 gst_flagset_register (GType flags_type)
7741 sizeof (GstFlagSetClass),
7743 (GClassInitFunc) gst_flagset_class_init,
7744 NULL, GSIZE_TO_POINTER (flags_type), 0, 0, NULL, NULL
7749 g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0);
7751 class_name = g_strdup_printf ("%sSet", g_type_name (flags_type));
7753 t = g_type_register_static (GST_TYPE_FLAG_SET,
7754 g_intern_string (class_name), &info, 0);
7755 g_free (class_name);