2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 * @short_description: GValue implementations specific
26 * GValue implementations specific to GStreamer.
28 * Note that operations on the same #GValue from multiple threads may lead to
29 * undefined behaviour.
32 /* Suppress warnings for GValueAraray */
33 #define GLIB_DISABLE_DEPRECATION_WARNINGS
44 #include "gst_private.h"
45 #include "glib-compat-private.h"
47 #include <gobject/gvaluecollector.h>
51 * @dest: a #GValue for the result
52 * @value1: a #GValue operand
53 * @value2: a #GValue operand
55 * Used by gst_value_union() to perform unification for a specific #GValue
56 * type. Register a new implementation with gst_value_register_union_func().
58 * Returns: %TRUE if a union was successful
60 typedef gboolean (*GstValueUnionFunc) (GValue * dest,
61 const GValue * value1, const GValue * value2);
63 /* GstValueIntersectFunc:
64 * @dest: (out caller-allocates): a #GValue for the result
65 * @value1: a #GValue operand
66 * @value2: a #GValue operand
68 * Used by gst_value_intersect() to perform intersection for a specific #GValue
69 * type. If the intersection is non-empty, the result is
70 * placed in @dest and %TRUE is returned. If the intersection is
71 * empty, @dest is unmodified and %FALSE is returned.
72 * Register a new implementation with gst_value_register_intersect_func().
74 * Returns: %TRUE if the values can intersect
76 typedef gboolean (*GstValueIntersectFunc) (GValue * dest,
77 const GValue * value1, const GValue * value2);
79 /* GstValueSubtractFunc:
80 * @dest: (out caller-allocates): a #GValue for the result
81 * @minuend: a #GValue operand
82 * @subtrahend: a #GValue operand
84 * Used by gst_value_subtract() to perform subtraction for a specific #GValue
85 * type. Register a new implementation with gst_value_register_subtract_func().
87 * Returns: %TRUE if the subtraction is not empty
89 typedef gboolean (*GstValueSubtractFunc) (GValue * dest,
90 const GValue * minuend, const GValue * subtrahend);
92 static void gst_value_register_union_func (GType type1,
93 GType type2, GstValueUnionFunc func);
94 static void gst_value_register_intersect_func (GType type1,
95 GType type2, GstValueIntersectFunc func);
96 static void gst_value_register_subtract_func (GType minuend_type,
97 GType subtrahend_type, GstValueSubtractFunc func);
99 static gboolean _priv_gst_value_parse_list (gchar * s, gchar ** after,
100 GValue * value, GType type);
101 static gboolean _priv_gst_value_parse_array (gchar * s, gchar ** after,
102 GValue * value, GType type);
104 typedef struct _GstValueUnionInfo GstValueUnionInfo;
105 struct _GstValueUnionInfo
109 GstValueUnionFunc func;
112 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
113 struct _GstValueIntersectInfo
117 GstValueIntersectFunc func;
120 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
121 struct _GstValueSubtractInfo
125 GstValueSubtractFunc func;
128 struct _GstFlagSetClass
131 GType flags_type; /* Type of the GFlags this flagset carries (can be 0) */
134 typedef struct _GstFlagSetClass GstFlagSetClass;
136 typedef struct _GstValueAbbreviation GstValueAbbreviation;
138 struct _GstValueAbbreviation
140 const gchar *type_name;
144 #define FUNDAMENTAL_TYPE_ID_MAX \
145 (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT)
146 #define FUNDAMENTAL_TYPE_ID(type) \
147 ((type) >> G_TYPE_FUNDAMENTAL_SHIFT)
149 #define VALUE_LIST_ARRAY(v) ((GArray *) (v)->data[0].v_pointer)
150 #define VALUE_LIST_SIZE(v) (VALUE_LIST_ARRAY(v)->len)
151 #define VALUE_LIST_GET_VALUE(v, index) ((const GValue *) &g_array_index (VALUE_LIST_ARRAY(v), GValue, (index)))
153 static GArray *gst_value_table;
154 static GHashTable *gst_value_hash;
155 static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1];
156 static GArray *gst_value_union_funcs;
157 static GArray *gst_value_intersect_funcs;
158 static GArray *gst_value_subtract_funcs;
160 /* Forward declarations */
161 static gchar *gst_value_serialize_fraction (const GValue * value);
163 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1);
164 static gint gst_value_compare_with_func (const GValue * value1,
165 const GValue * value2, GstValueCompareFunc compare);
167 static gchar *gst_string_wrap (const gchar * s);
168 static gchar *gst_string_unwrap (const gchar * s);
170 static void gst_value_move (GValue * dest, GValue * src);
171 static void _gst_value_list_append_and_take_value (GValue * value,
172 GValue * append_value);
173 static void _gst_value_array_append_and_take_value (GValue * value,
174 GValue * append_value);
176 static inline GstValueTable *
177 gst_value_hash_lookup_type (GType type)
179 if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type)))
180 return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)];
182 return g_hash_table_lookup (gst_value_hash, (gpointer) type);
186 gst_value_hash_add_type (GType type, const GstValueTable * table)
188 if (G_TYPE_IS_FUNDAMENTAL (type))
189 gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table;
191 g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table);
198 /* two helper functions to serialize/stringify any type of list
199 * regular lists are done with { }, arrays with < >
202 _priv_gst_value_serialize_any_list (const GValue * value, const gchar * begin,
203 const gchar * end, gboolean print_type)
206 GArray *array = value->data[0].v_pointer;
210 guint alen = array->len;
212 /* estimate minimum string length to minimise re-allocs in GString */
213 s = g_string_sized_new (2 + (6 * alen) + 2);
214 g_string_append (s, begin);
215 for (i = 0; i < alen; i++) {
216 v = &g_array_index (array, GValue, i);
217 s_val = gst_value_serialize (v);
220 g_string_append_c (s, '(');
221 g_string_append (s, _priv_gst_value_gtype_to_abbr (G_VALUE_TYPE (v)));
222 g_string_append_c (s, ')');
224 g_string_append (s, s_val);
227 g_string_append_len (s, ", ", 2);
230 GST_WARNING ("Could not serialize list/array value of type '%s'",
231 G_VALUE_TYPE_NAME (v));
234 g_string_append (s, end);
235 return g_string_free (s, FALSE);
239 gst_value_transform_any_list_string (const GValue * src_value,
240 GValue * dest_value, const gchar * begin, const gchar * end)
249 array = src_value->data[0].v_pointer;
252 /* estimate minimum string length to minimise re-allocs in GString */
253 s = g_string_sized_new (2 + (10 * alen) + 2);
254 g_string_append (s, begin);
255 for (i = 0; i < alen; i++) {
256 list_value = &g_array_index (array, GValue, i);
259 g_string_append_len (s, ", ", 2);
261 list_s = g_strdup_value_contents (list_value);
262 g_string_append (s, list_s);
265 g_string_append (s, end);
267 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
271 _gst_value_serialize_g_value_array (const GValue * value, const gchar * begin,
275 GValueArray *array = value->data[0].v_pointer;
279 guint alen = array->n_values;
281 /* estimate minimum string length to minimise re-allocs in GString */
282 s = g_string_sized_new (2 + (6 * alen) + 2);
283 g_string_append (s, begin);
284 for (i = 0; i < alen; i++) {
285 v = g_value_array_get_nth (array, i);
286 s_val = gst_value_serialize (v);
288 g_string_append (s, s_val);
291 g_string_append_len (s, ", ", 2);
294 GST_WARNING ("Could not serialize list/array value of type '%s'",
295 G_VALUE_TYPE_NAME (v));
298 g_string_append (s, end);
299 return g_string_free (s, FALSE);
303 _gst_value_transform_g_value_array_string (const GValue * src_value,
304 GValue * dest_value, const gchar * begin, const gchar * end)
313 array = src_value->data[0].v_pointer;
314 alen = array->n_values;
316 /* estimate minimum string length to minimise re-allocs in GString */
317 s = g_string_sized_new (2 + (10 * alen) + 2);
318 g_string_append (s, begin);
319 for (i = 0; i < alen; i++) {
320 list_value = g_value_array_get_nth (array, i);
323 g_string_append_len (s, ", ", 2);
325 list_s = g_strdup_value_contents (list_value);
326 g_string_append (s, list_s);
329 g_string_append (s, end);
331 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
335 * helper function to see if a type is fixed. Is used internally here and
336 * there. Do not export, since it doesn't work for types where the content
337 * decides the fixedness (e.g. GST_TYPE_ARRAY).
340 gst_type_is_fixed (GType type)
342 /* the basic int, string, double types */
343 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
346 /* our fundamental types that are certainly not fixed */
347 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
348 type == GST_TYPE_INT64_RANGE ||
349 type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE ||
350 type == GST_TYPE_STRUCTURE) {
353 /* other (boxed) types that are fixed */
354 if (type == GST_TYPE_BUFFER) {
358 if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <=
359 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
366 /* GValue functions usable for both regular lists and arrays */
368 gst_value_init_list_or_array (GValue * value)
370 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
374 copy_garray_of_gstvalue (const GArray * src)
380 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len);
381 g_array_set_size (dest, len);
382 for (i = 0; i < len; i++) {
383 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
384 &g_array_index (src, GValue, i));
391 gst_value_copy_list_or_array (const GValue * src_value, GValue * dest_value)
393 dest_value->data[0].v_pointer =
394 copy_garray_of_gstvalue ((GArray *) src_value->data[0].v_pointer);
398 gst_value_free_list_or_array (GValue * value)
401 GArray *src = (GArray *) value->data[0].v_pointer;
404 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
405 for (i = 0; i < len; i++) {
406 g_value_unset (&g_array_index (src, GValue, i));
408 g_array_free (src, TRUE);
413 gst_value_list_or_array_peek_pointer (const GValue * value)
415 return value->data[0].v_pointer;
419 gst_value_collect_list_or_array (GValue * value, guint n_collect_values,
420 GTypeCValue * collect_values, guint collect_flags)
422 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
423 value->data[0].v_pointer = collect_values[0].v_pointer;
424 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
426 value->data[0].v_pointer =
427 copy_garray_of_gstvalue ((GArray *) collect_values[0].v_pointer);
433 gst_value_lcopy_list_or_array (const GValue * value, guint n_collect_values,
434 GTypeCValue * collect_values, guint collect_flags)
436 GArray **dest = collect_values[0].v_pointer;
439 return g_strdup_printf ("value location for `%s' passed as NULL",
440 G_VALUE_TYPE_NAME (value));
441 if (!value->data[0].v_pointer)
442 return g_strdup_printf ("invalid value given for `%s'",
443 G_VALUE_TYPE_NAME (value));
444 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
445 *dest = (GArray *) value->data[0].v_pointer;
447 *dest = copy_garray_of_gstvalue ((GArray *) value->data[0].v_pointer);
453 gst_value_list_or_array_get_basic_type (const GValue * value, GType * type)
455 if (G_UNLIKELY (value == NULL))
458 if (GST_VALUE_HOLDS_LIST (value)) {
459 if (VALUE_LIST_SIZE (value) == 0)
461 return gst_value_list_or_array_get_basic_type (VALUE_LIST_GET_VALUE (value,
464 if (GST_VALUE_HOLDS_ARRAY (value)) {
465 const GArray *array = (const GArray *) value->data[0].v_pointer;
468 return gst_value_list_or_array_get_basic_type (&g_array_index (array,
472 *type = G_VALUE_TYPE (value);
477 #define IS_RANGE_COMPAT(type1,type2,t1,t2) \
478 (((t1) == (type1) && (t2) == (type2)) || ((t2) == (type1) && (t1) == (type2)))
481 gst_value_list_or_array_are_compatible (const GValue * value1,
482 const GValue * value2)
484 GType basic_type1, basic_type2;
486 /* empty or same type is OK */
487 if (!gst_value_list_or_array_get_basic_type (value1, &basic_type1) ||
488 !gst_value_list_or_array_get_basic_type (value2, &basic_type2) ||
489 basic_type1 == basic_type2)
492 /* ranges are distinct types for each bound type... */
493 if (IS_RANGE_COMPAT (G_TYPE_INT, GST_TYPE_INT_RANGE, basic_type1,
496 if (IS_RANGE_COMPAT (G_TYPE_INT64, GST_TYPE_INT64_RANGE, basic_type1,
499 if (IS_RANGE_COMPAT (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, basic_type1,
502 if (IS_RANGE_COMPAT (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE, basic_type1,
510 _gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
512 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
513 memset (append_value, 0, sizeof (GValue));
517 * gst_value_list_append_and_take_value:
518 * @value: a #GValue of type #GST_TYPE_LIST
519 * @append_value: (transfer full): the value to append
521 * Appends @append_value to the GstValueList in @value.
526 gst_value_list_append_and_take_value (GValue * value, GValue * append_value)
528 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
529 g_return_if_fail (G_IS_VALUE (append_value));
530 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
533 _gst_value_list_append_and_take_value (value, append_value);
537 * gst_value_list_append_value:
538 * @value: a #GValue of type #GST_TYPE_LIST
539 * @append_value: (transfer none): the value to append
541 * Appends @append_value to the GstValueList in @value.
544 gst_value_list_append_value (GValue * value, const GValue * append_value)
548 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
549 g_return_if_fail (G_IS_VALUE (append_value));
550 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
553 gst_value_init_and_copy (&val, append_value);
554 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
558 * gst_value_list_prepend_value:
559 * @value: a #GValue of type #GST_TYPE_LIST
560 * @prepend_value: the value to prepend
562 * Prepends @prepend_value to the GstValueList in @value.
565 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
569 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
570 g_return_if_fail (G_IS_VALUE (prepend_value));
571 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
574 gst_value_init_and_copy (&val, prepend_value);
575 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
579 * gst_value_list_concat:
580 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
584 * Concatenates copies of @value1 and @value2 into a list. Values that are not
585 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
586 * @dest will be initialized to the type #GST_TYPE_LIST.
589 gst_value_list_concat (GValue * dest, const GValue * value1,
590 const GValue * value2)
592 guint i, value1_length, value2_length;
595 g_return_if_fail (dest != NULL);
596 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
597 g_return_if_fail (G_IS_VALUE (value1));
598 g_return_if_fail (G_IS_VALUE (value2));
599 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
602 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
604 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
605 g_value_init (dest, GST_TYPE_LIST);
606 array = (GArray *) dest->data[0].v_pointer;
607 g_array_set_size (array, value1_length + value2_length);
609 if (GST_VALUE_HOLDS_LIST (value1)) {
610 for (i = 0; i < value1_length; i++) {
611 gst_value_init_and_copy (&g_array_index (array, GValue, i),
612 VALUE_LIST_GET_VALUE (value1, i));
615 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
618 if (GST_VALUE_HOLDS_LIST (value2)) {
619 for (i = 0; i < value2_length; i++) {
620 gst_value_init_and_copy (&g_array_index (array, GValue,
621 i + value1_length), VALUE_LIST_GET_VALUE (value2, i));
624 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
629 /* same as gst_value_list_concat() but takes ownership of GValues */
631 gst_value_list_concat_and_take_values (GValue * dest, GValue * val1,
634 guint i, val1_length, val2_length;
635 gboolean val1_is_list;
636 gboolean val2_is_list;
639 g_assert (dest != NULL);
640 g_assert (G_VALUE_TYPE (dest) == 0);
641 g_assert (G_IS_VALUE (val1));
642 g_assert (G_IS_VALUE (val2));
643 g_assert (gst_value_list_or_array_are_compatible (val1, val2));
645 val1_is_list = GST_VALUE_HOLDS_LIST (val1);
646 val1_length = (val1_is_list ? VALUE_LIST_SIZE (val1) : 1);
648 val2_is_list = GST_VALUE_HOLDS_LIST (val2);
649 val2_length = (val2_is_list ? VALUE_LIST_SIZE (val2) : 1);
651 g_value_init (dest, GST_TYPE_LIST);
652 array = (GArray *) dest->data[0].v_pointer;
653 g_array_set_size (array, val1_length + val2_length);
656 for (i = 0; i < val1_length; i++) {
657 g_array_index (array, GValue, i) = *VALUE_LIST_GET_VALUE (val1, i);
659 g_array_set_size (VALUE_LIST_ARRAY (val1), 0);
660 g_value_unset (val1);
662 g_array_index (array, GValue, 0) = *val1;
663 G_VALUE_TYPE (val1) = G_TYPE_INVALID;
667 for (i = 0; i < val2_length; i++) {
668 const GValue *v2 = VALUE_LIST_GET_VALUE (val2, i);
669 g_array_index (array, GValue, i + val1_length) = *v2;
671 g_array_set_size (VALUE_LIST_ARRAY (val2), 0);
672 g_value_unset (val2);
674 g_array_index (array, GValue, val1_length) = *val2;
675 G_VALUE_TYPE (val2) = G_TYPE_INVALID;
680 * gst_value_list_merge:
681 * @dest: (out caller-allocates): an uninitialized #GValue to take the result
685 * Merges copies of @value1 and @value2. Values that are not
686 * of type #GST_TYPE_LIST are treated as if they were lists of length 1.
688 * The result will be put into @dest and will either be a list that will not
689 * contain any duplicates, or a non-list type (if @value1 and @value2
693 gst_value_list_merge (GValue * dest, const GValue * value1,
694 const GValue * value2)
696 guint i, j, k, value1_length, value2_length, skipped;
701 g_return_if_fail (dest != NULL);
702 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
703 g_return_if_fail (G_IS_VALUE (value1));
704 g_return_if_fail (G_IS_VALUE (value2));
705 g_return_if_fail (gst_value_list_or_array_are_compatible (value1, value2));
708 (GST_VALUE_HOLDS_LIST (value1) ? VALUE_LIST_SIZE (value1) : 1);
710 (GST_VALUE_HOLDS_LIST (value2) ? VALUE_LIST_SIZE (value2) : 1);
711 g_value_init (dest, GST_TYPE_LIST);
712 array = (GArray *) dest->data[0].v_pointer;
713 g_array_set_size (array, value1_length + value2_length);
715 if (GST_VALUE_HOLDS_LIST (value1)) {
716 for (i = 0; i < value1_length; i++) {
717 gst_value_init_and_copy (&g_array_index (array, GValue, i),
718 VALUE_LIST_GET_VALUE (value1, i));
721 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
726 if (GST_VALUE_HOLDS_LIST (value2)) {
727 for (i = 0; i < value2_length; i++) {
729 src = VALUE_LIST_GET_VALUE (value2, i);
730 for (k = 0; k < value1_length; k++) {
731 if (gst_value_compare (&g_array_index (array, GValue, k),
732 src) == GST_VALUE_EQUAL) {
739 gst_value_init_and_copy (&g_array_index (array, GValue, j), src);
745 for (k = 0; k < value1_length; k++) {
746 if (gst_value_compare (&g_array_index (array, GValue, k),
747 value2) == GST_VALUE_EQUAL) {
754 gst_value_init_and_copy (&g_array_index (array, GValue, j), value2);
758 guint new_size = value1_length + (value2_length - skipped);
762 g_array_set_size (array, new_size);
766 /* size is 1, take single value in list and make it new dest */
767 single_dest = g_array_index (array, GValue, 0);
769 /* clean up old value allocations: must set array size to 0, because
770 * allocated values are not inited meaning g_value_unset() will not
772 g_array_set_size (array, 0);
773 g_value_unset (dest);
775 /* the single value is our new result */
782 * gst_value_list_get_size:
783 * @value: a #GValue of type #GST_TYPE_LIST
785 * Gets the number of values contained in @value.
787 * Returns: the number of values
790 gst_value_list_get_size (const GValue * value)
792 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
794 return ((GArray *) value->data[0].v_pointer)->len;
798 * gst_value_list_get_value:
799 * @value: a #GValue of type #GST_TYPE_LIST
800 * @index: index of value to get from the list
802 * Gets the value that is a member of the list contained in @value and
803 * has the index @index.
805 * Returns: (transfer none): the value at the given index
808 gst_value_list_get_value (const GValue * value, guint index)
810 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
811 g_return_val_if_fail (index < VALUE_LIST_SIZE (value), NULL);
813 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
818 * gst_value_array_append_value:
819 * @value: a #GValue of type #GST_TYPE_ARRAY
820 * @append_value: the value to append
822 * Appends @append_value to the GstValueArray in @value.
825 gst_value_array_append_value (GValue * value, const GValue * append_value)
829 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
830 g_return_if_fail (G_IS_VALUE (append_value));
831 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
834 gst_value_init_and_copy (&val, append_value);
835 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
839 _gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
841 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
842 memset (append_value, 0, sizeof (GValue));
846 * gst_value_array_append_and_take_value:
847 * @value: a #GValue of type #GST_TYPE_ARRAY
848 * @append_value: (transfer full): the value to append
850 * Appends @append_value to the GstValueArray in @value.
855 gst_value_array_append_and_take_value (GValue * value, GValue * append_value)
857 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
858 g_return_if_fail (G_IS_VALUE (append_value));
859 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
862 _gst_value_array_append_and_take_value (value, append_value);
866 * gst_value_array_prepend_value:
867 * @value: a #GValue of type #GST_TYPE_ARRAY
868 * @prepend_value: the value to prepend
870 * Prepends @prepend_value to the GstValueArray in @value.
873 gst_value_array_prepend_value (GValue * value, const GValue * prepend_value)
877 g_return_if_fail (GST_VALUE_HOLDS_ARRAY (value));
878 g_return_if_fail (G_IS_VALUE (prepend_value));
879 g_return_if_fail (gst_value_list_or_array_are_compatible (value,
882 gst_value_init_and_copy (&val, prepend_value);
883 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
887 * gst_value_array_get_size:
888 * @value: a #GValue of type #GST_TYPE_ARRAY
890 * Gets the number of values contained in @value.
892 * Returns: the number of values
895 gst_value_array_get_size (const GValue * value)
897 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), 0);
899 return ((GArray *) value->data[0].v_pointer)->len;
903 * gst_value_array_get_value:
904 * @value: a #GValue of type #GST_TYPE_ARRAY
905 * @index: index of value to get from the array
907 * Gets the value that is a member of the array contained in @value and
908 * has the index @index.
910 * Returns: (transfer none): the value at the given index
913 gst_value_array_get_value (const GValue * value, guint index)
915 g_return_val_if_fail (GST_VALUE_HOLDS_ARRAY (value), NULL);
916 g_return_val_if_fail (index < gst_value_array_get_size (value), NULL);
918 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
923 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
925 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
929 gst_value_transform_array_string (const GValue * src_value, GValue * dest_value)
931 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
935 gst_value_transform_g_value_array_string (const GValue * src_value,
938 _gst_value_transform_g_value_array_string (src_value, dest_value, "< ", " >");
942 gst_value_transform_g_value_array_any_list (const GValue * src_value,
945 const GValueArray *varray;
949 /* GLib will unset the value, memset to 0 the data instead of doing a proper
950 * reset. That's why we need to allocate the array here */
951 gst_value_init_list_or_array (dest_value);
953 varray = g_value_get_boxed (src_value);
954 array = dest_value->data[0].v_pointer;
956 for (i = 0; i < varray->n_values; i++) {
957 GValue val = G_VALUE_INIT;
958 gst_value_init_and_copy (&val, &varray->values[i]);
959 g_array_append_vals (array, &val, 1);
964 gst_value_transform_any_list_g_value_array (const GValue * src_value,
971 array = src_value->data[0].v_pointer;
972 varray = g_value_array_new (array->len);
974 for (i = 0; i < array->len; i++)
975 g_value_array_append (varray, &g_array_index (array, GValue, i));
977 g_value_take_boxed (dest_value, varray);
980 /* Do an unordered compare of the contents of a list */
982 gst_value_compare_value_list (const GValue * value1, const GValue * value2)
985 GArray *array1 = value1->data[0].v_pointer;
986 GArray *array2 = value2->data[0].v_pointer;
991 GstValueCompareFunc compare;
993 /* get length and do initial length check. */
995 if (len != array2->len)
996 return GST_VALUE_UNORDERED;
998 /* place to mark removed value indices of array2 */
999 removed = g_newa (guint8, len);
1000 memset (removed, 0, len);
1003 /* loop over array1, all items should be in array2. When we find an
1004 * item in array2, remove it from array2 by marking it as removed */
1005 for (i = 0; i < len; i++) {
1006 v1 = &g_array_index (array1, GValue, i);
1007 if ((compare = gst_value_get_compare_func (v1))) {
1008 for (j = 0; j < len; j++) {
1009 /* item is removed, we can skip it */
1012 v2 = &g_array_index (array2, GValue, j);
1013 if (gst_value_compare_with_func (v1, v2, compare) == GST_VALUE_EQUAL) {
1014 /* mark item as removed now that we found it in array2 and
1015 * decrement the number of remaining items in array2. */
1021 /* item in array1 and not in array2, UNORDERED */
1023 return GST_VALUE_UNORDERED;
1025 return GST_VALUE_UNORDERED;
1027 /* if not all items were removed, array2 contained something not in array1 */
1029 return GST_VALUE_UNORDERED;
1031 /* arrays are equal */
1032 return GST_VALUE_EQUAL;
1035 /* Perform an ordered comparison of the contents of an array */
1037 gst_value_compare_value_array (const GValue * value1, const GValue * value2)
1040 GArray *array1 = value1->data[0].v_pointer;
1041 GArray *array2 = value2->data[0].v_pointer;
1042 guint len = array1->len;
1046 if (len != array2->len)
1047 return GST_VALUE_UNORDERED;
1049 for (i = 0; i < len; i++) {
1050 v1 = &g_array_index (array1, GValue, i);
1051 v2 = &g_array_index (array2, GValue, i);
1052 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1053 return GST_VALUE_UNORDERED;
1056 return GST_VALUE_EQUAL;
1060 gst_value_compare_g_value_array (const GValue * value1, const GValue * value2)
1063 GValueArray *array1 = value1->data[0].v_pointer;
1064 GValueArray *array2 = value2->data[0].v_pointer;
1065 guint len = array1->n_values;
1069 if (len != array2->n_values)
1070 return GST_VALUE_UNORDERED;
1072 for (i = 0; i < len; i++) {
1073 v1 = g_value_array_get_nth (array1, i);
1074 v2 = g_value_array_get_nth (array2, i);
1075 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL)
1076 return GST_VALUE_UNORDERED;
1079 return GST_VALUE_EQUAL;
1083 gst_value_serialize_value_list (const GValue * value)
1085 return _priv_gst_value_serialize_any_list (value, "{ ", " }", TRUE);
1089 gst_value_deserialize_value_list (GValue * dest, const gchar * s)
1091 gchar *s2 = (gchar *) s;
1092 return _priv_gst_value_parse_list (s2, &s2, dest, G_TYPE_INVALID);
1096 gst_value_serialize_value_array (const GValue * value)
1098 return _priv_gst_value_serialize_any_list (value, "< ", " >", TRUE);
1102 gst_value_deserialize_value_array (GValue * dest, const gchar * s)
1104 gchar *s2 = (gchar *) s;
1105 return _priv_gst_value_parse_array (s2, &s2, dest, G_TYPE_INVALID);
1109 gst_value_serialize_g_value_array (const GValue * value)
1111 return _gst_value_serialize_g_value_array (value, "< ", " >");
1115 gst_value_deserialize_g_value_array (GValue * dest, const gchar * s)
1117 g_warning ("gst_value_deserialize_g_value_array: unimplemented");
1124 * Values in the range are defined as any value greater or equal
1125 * to min*step, AND lesser or equal to max*step.
1126 * For step == 1, this falls back to the traditional range semantics.
1128 * data[0] = (min << 32) | (max)
1133 #define INT_RANGE_MIN(v) ((gint) (((v)->data[0].v_uint64) >> 32))
1134 #define INT_RANGE_MAX(v) ((gint) (((v)->data[0].v_uint64) & 0xffffffff))
1135 #define INT_RANGE_STEP(v) ((v)->data[1].v_int)
1138 gst_value_init_int_range (GValue * value)
1140 G_STATIC_ASSERT (sizeof (gint) <= 2 * sizeof (guint64));
1142 value->data[0].v_uint64 = 0;
1143 value->data[1].v_int = 1;
1147 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
1149 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
1150 dest_value->data[1].v_int = src_value->data[1].v_int;
1154 gst_value_collect_int_range (GValue * value, guint n_collect_values,
1155 GTypeCValue * collect_values, guint collect_flags)
1157 if (n_collect_values != 2)
1158 return g_strdup_printf ("not enough value locations for `%s' passed",
1159 G_VALUE_TYPE_NAME (value));
1160 if (collect_values[0].v_int >= collect_values[1].v_int)
1161 return g_strdup_printf ("range start is not smaller than end for `%s'",
1162 G_VALUE_TYPE_NAME (value));
1164 gst_value_set_int_range_step (value, collect_values[0].v_int,
1165 collect_values[1].v_int, 1);
1171 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
1172 GTypeCValue * collect_values, guint collect_flags)
1174 guint32 *int_range_start = collect_values[0].v_pointer;
1175 guint32 *int_range_end = collect_values[1].v_pointer;
1177 if (!int_range_start)
1178 return g_strdup_printf ("start value location for `%s' passed as NULL",
1179 G_VALUE_TYPE_NAME (value));
1181 return g_strdup_printf ("end value location for `%s' passed as NULL",
1182 G_VALUE_TYPE_NAME (value));
1184 *int_range_start = INT_RANGE_MIN (value);
1185 *int_range_end = INT_RANGE_MAX (value);
1191 * gst_value_set_int_range_step:
1192 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1193 * @start: the start of the range
1194 * @end: the end of the range
1195 * @step: the step of the range
1197 * Sets @value to the range specified by @start, @end and @step.
1200 gst_value_set_int_range_step (GValue * value, gint start, gint end, gint step)
1202 guint64 sstart, sstop;
1204 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
1205 g_return_if_fail (start < end);
1206 g_return_if_fail (step > 0);
1207 g_return_if_fail (start % step == 0);
1208 g_return_if_fail (end % step == 0);
1210 sstart = (guint) (start / step);
1211 sstop = (guint) (end / step);
1212 value->data[0].v_uint64 = (sstart << 32) | sstop;
1213 value->data[1].v_int = step;
1217 * gst_value_set_int_range:
1218 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1219 * @start: the start of the range
1220 * @end: the end of the range
1222 * Sets @value to the range specified by @start and @end.
1225 gst_value_set_int_range (GValue * value, gint start, gint end)
1227 gst_value_set_int_range_step (value, start, end, 1);
1231 * gst_value_get_int_range_min:
1232 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1234 * Gets the minimum of the range specified by @value.
1236 * Returns: the minimum of the range
1239 gst_value_get_int_range_min (const GValue * value)
1241 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1243 return INT_RANGE_MIN (value) * INT_RANGE_STEP (value);
1247 * gst_value_get_int_range_max:
1248 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1250 * Gets the maximum of the range specified by @value.
1252 * Returns: the maximum of the range
1255 gst_value_get_int_range_max (const GValue * value)
1257 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1259 return INT_RANGE_MAX (value) * INT_RANGE_STEP (value);
1263 * gst_value_get_int_range_step:
1264 * @value: a GValue initialized to GST_TYPE_INT_RANGE
1266 * Gets the step of the range specified by @value.
1268 * Returns: the step of the range
1271 gst_value_get_int_range_step (const GValue * value)
1273 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
1275 return INT_RANGE_STEP (value);
1279 gst_value_transform_int_range_string (const GValue * src_value,
1280 GValue * dest_value)
1282 if (INT_RANGE_STEP (src_value) == 1)
1283 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
1284 INT_RANGE_MIN (src_value), INT_RANGE_MAX (src_value));
1286 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d,%d]",
1287 INT_RANGE_MIN (src_value) * INT_RANGE_STEP (src_value),
1288 INT_RANGE_MAX (src_value) * INT_RANGE_STEP (src_value),
1289 INT_RANGE_STEP (src_value));
1293 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
1295 /* calculate the number of values in each range */
1296 gint n1 = INT_RANGE_MAX (value1) - INT_RANGE_MIN (value1) + 1;
1297 gint n2 = INT_RANGE_MAX (value2) - INT_RANGE_MIN (value2) + 1;
1299 /* they must be equal */
1301 return GST_VALUE_UNORDERED;
1303 /* if empty, equal */
1305 return GST_VALUE_EQUAL;
1307 /* if more than one value, then it is only equal if the step is equal
1308 and bounds lie on the same value */
1310 if (INT_RANGE_STEP (value1) == INT_RANGE_STEP (value2) &&
1311 INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2) &&
1312 INT_RANGE_MAX (value1) == INT_RANGE_MAX (value2)) {
1313 return GST_VALUE_EQUAL;
1315 return GST_VALUE_UNORDERED;
1317 /* if just one, only if the value is equal */
1318 if (INT_RANGE_MIN (value1) == INT_RANGE_MIN (value2))
1319 return GST_VALUE_EQUAL;
1320 return GST_VALUE_UNORDERED;
1325 gst_value_serialize_int_range (const GValue * value)
1327 if (INT_RANGE_STEP (value) == 1)
1328 return g_strdup_printf ("[ %d, %d ]", INT_RANGE_MIN (value),
1329 INT_RANGE_MAX (value));
1331 return g_strdup_printf ("[ %d, %d, %d ]",
1332 INT_RANGE_MIN (value) * INT_RANGE_STEP (value),
1333 INT_RANGE_MAX (value) * INT_RANGE_STEP (value), INT_RANGE_STEP (value));
1337 gst_value_deserialize_int_range (GValue * dest, const gchar * s)
1339 g_warning ("unimplemented");
1346 * Values in the range are defined as any value greater or equal
1347 * to min*step, AND lesser or equal to max*step.
1348 * For step == 1, this falls back to the traditional range semantics.
1351 #define INT64_RANGE_MIN(v) (((gint64 *)((v)->data[0].v_pointer))[0])
1352 #define INT64_RANGE_MAX(v) (((gint64 *)((v)->data[0].v_pointer))[1])
1353 #define INT64_RANGE_STEP(v) (((gint64 *)((v)->data[0].v_pointer))[2])
1356 gst_value_init_int64_range (GValue * value)
1358 gint64 *vals = g_slice_alloc0 (3 * sizeof (gint64));
1359 value->data[0].v_pointer = vals;
1360 INT64_RANGE_MIN (value) = 0;
1361 INT64_RANGE_MAX (value) = 0;
1362 INT64_RANGE_STEP (value) = 1;
1366 gst_value_free_int64_range (GValue * value)
1368 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1369 g_slice_free1 (3 * sizeof (gint64), value->data[0].v_pointer);
1370 value->data[0].v_pointer = NULL;
1374 gst_value_copy_int64_range (const GValue * src_value, GValue * dest_value)
1376 gint64 *vals = (gint64 *) dest_value->data[0].v_pointer;
1377 gint64 *src_vals = (gint64 *) src_value->data[0].v_pointer;
1380 gst_value_init_int64_range (dest_value);
1383 if (src_vals != NULL) {
1384 INT64_RANGE_MIN (dest_value) = INT64_RANGE_MIN (src_value);
1385 INT64_RANGE_MAX (dest_value) = INT64_RANGE_MAX (src_value);
1386 INT64_RANGE_STEP (dest_value) = INT64_RANGE_STEP (src_value);
1391 gst_value_collect_int64_range (GValue * value, guint n_collect_values,
1392 GTypeCValue * collect_values, guint collect_flags)
1394 gint64 *vals = value->data[0].v_pointer;
1396 if (n_collect_values != 2)
1397 return g_strdup_printf ("not enough value locations for `%s' passed",
1398 G_VALUE_TYPE_NAME (value));
1399 if (collect_values[0].v_int64 >= collect_values[1].v_int64)
1400 return g_strdup_printf ("range start is not smaller than end for `%s'",
1401 G_VALUE_TYPE_NAME (value));
1404 gst_value_init_int64_range (value);
1407 gst_value_set_int64_range_step (value, collect_values[0].v_int64,
1408 collect_values[1].v_int64, 1);
1414 gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values,
1415 GTypeCValue * collect_values, guint collect_flags)
1417 guint64 *int_range_start = collect_values[0].v_pointer;
1418 guint64 *int_range_end = collect_values[1].v_pointer;
1419 guint64 *int_range_step = collect_values[2].v_pointer;
1420 gint64 *vals = (gint64 *) value->data[0].v_pointer;
1422 if (!int_range_start)
1423 return g_strdup_printf ("start value location for `%s' passed as NULL",
1424 G_VALUE_TYPE_NAME (value));
1426 return g_strdup_printf ("end value location for `%s' passed as NULL",
1427 G_VALUE_TYPE_NAME (value));
1428 if (!int_range_step)
1429 return g_strdup_printf ("step value location for `%s' passed as NULL",
1430 G_VALUE_TYPE_NAME (value));
1432 if (G_UNLIKELY (vals == NULL)) {
1433 return g_strdup_printf ("Uninitialised `%s' passed",
1434 G_VALUE_TYPE_NAME (value));
1437 *int_range_start = INT64_RANGE_MIN (value);
1438 *int_range_end = INT64_RANGE_MAX (value);
1439 *int_range_step = INT64_RANGE_STEP (value);
1445 * gst_value_set_int64_range_step:
1446 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1447 * @start: the start of the range
1448 * @end: the end of the range
1449 * @step: the step of the range
1451 * Sets @value to the range specified by @start, @end and @step.
1454 gst_value_set_int64_range_step (GValue * value, gint64 start, gint64 end,
1457 g_return_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value));
1458 g_return_if_fail (start < end);
1459 g_return_if_fail (step > 0);
1460 g_return_if_fail (start % step == 0);
1461 g_return_if_fail (end % step == 0);
1463 INT64_RANGE_MIN (value) = start / step;
1464 INT64_RANGE_MAX (value) = end / step;
1465 INT64_RANGE_STEP (value) = step;
1469 * gst_value_set_int64_range:
1470 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1471 * @start: the start of the range
1472 * @end: the end of the range
1474 * Sets @value to the range specified by @start and @end.
1477 gst_value_set_int64_range (GValue * value, gint64 start, gint64 end)
1479 gst_value_set_int64_range_step (value, start, end, 1);
1483 * gst_value_get_int64_range_min:
1484 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1486 * Gets the minimum of the range specified by @value.
1488 * Returns: the minimum of the range
1491 gst_value_get_int64_range_min (const GValue * value)
1493 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1495 return INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value);
1499 * gst_value_get_int64_range_max:
1500 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1502 * Gets the maximum of the range specified by @value.
1504 * Returns: the maximum of the range
1507 gst_value_get_int64_range_max (const GValue * value)
1509 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1511 return INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value);
1515 * gst_value_get_int64_range_step:
1516 * @value: a GValue initialized to GST_TYPE_INT64_RANGE
1518 * Gets the step of the range specified by @value.
1520 * Returns: the step of the range
1523 gst_value_get_int64_range_step (const GValue * value)
1525 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value), 0);
1527 return INT64_RANGE_STEP (value);
1531 gst_value_transform_int64_range_string (const GValue * src_value,
1532 GValue * dest_value)
1534 if (INT64_RANGE_STEP (src_value) == 1)
1535 dest_value->data[0].v_pointer =
1536 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT "]",
1537 INT64_RANGE_MIN (src_value), INT64_RANGE_MAX (src_value));
1539 dest_value->data[0].v_pointer =
1540 g_strdup_printf ("(gint64)[%" G_GINT64_FORMAT ",%" G_GINT64_FORMAT
1541 ",%" G_GINT64_FORMAT "]",
1542 INT64_RANGE_MIN (src_value) * INT64_RANGE_STEP (src_value),
1543 INT64_RANGE_MAX (src_value) * INT64_RANGE_STEP (src_value),
1544 INT64_RANGE_STEP (src_value));
1548 gst_value_compare_int64_range (const GValue * value1, const GValue * value2)
1550 /* calculate the number of values in each range */
1551 gint64 n1 = INT64_RANGE_MAX (value1) - INT64_RANGE_MIN (value1) + 1;
1552 gint64 n2 = INT64_RANGE_MAX (value2) - INT64_RANGE_MIN (value2) + 1;
1554 /* they must be equal */
1556 return GST_VALUE_UNORDERED;
1558 /* if empty, equal */
1560 return GST_VALUE_EQUAL;
1562 /* if more than one value, then it is only equal if the step is equal
1563 and bounds lie on the same value */
1565 if (INT64_RANGE_STEP (value1) == INT64_RANGE_STEP (value2) &&
1566 INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2) &&
1567 INT64_RANGE_MAX (value1) == INT64_RANGE_MAX (value2)) {
1568 return GST_VALUE_EQUAL;
1570 return GST_VALUE_UNORDERED;
1572 /* if just one, only if the value is equal */
1573 if (INT64_RANGE_MIN (value1) == INT64_RANGE_MIN (value2))
1574 return GST_VALUE_EQUAL;
1575 return GST_VALUE_UNORDERED;
1580 gst_value_serialize_int64_range (const GValue * value)
1582 if (INT64_RANGE_STEP (value) == 1)
1583 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT " ]",
1584 INT64_RANGE_MIN (value), INT64_RANGE_MAX (value));
1586 return g_strdup_printf ("[ %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT ", %"
1587 G_GINT64_FORMAT " ]",
1588 INT64_RANGE_MIN (value) * INT64_RANGE_STEP (value),
1589 INT64_RANGE_MAX (value) * INT64_RANGE_STEP (value),
1590 INT64_RANGE_STEP (value));
1594 gst_value_deserialize_int64_range (GValue * dest, const gchar * s)
1596 g_warning ("unimplemented");
1605 gst_value_init_double_range (GValue * value)
1607 value->data[0].v_double = 0;
1608 value->data[1].v_double = 0;
1612 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
1614 dest_value->data[0].v_double = src_value->data[0].v_double;
1615 dest_value->data[1].v_double = src_value->data[1].v_double;
1619 gst_value_collect_double_range (GValue * value, guint n_collect_values,
1620 GTypeCValue * collect_values, guint collect_flags)
1622 if (n_collect_values != 2)
1623 return g_strdup_printf ("not enough value locations for `%s' passed",
1624 G_VALUE_TYPE_NAME (value));
1625 if (collect_values[0].v_double >= collect_values[1].v_double)
1626 return g_strdup_printf ("range start is not smaller than end for `%s'",
1627 G_VALUE_TYPE_NAME (value));
1629 value->data[0].v_double = collect_values[0].v_double;
1630 value->data[1].v_double = collect_values[1].v_double;
1636 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
1637 GTypeCValue * collect_values, guint collect_flags)
1639 gdouble *double_range_start = collect_values[0].v_pointer;
1640 gdouble *double_range_end = collect_values[1].v_pointer;
1642 if (!double_range_start)
1643 return g_strdup_printf ("start value location for `%s' passed as NULL",
1644 G_VALUE_TYPE_NAME (value));
1645 if (!double_range_end)
1646 return g_strdup_printf ("end value location for `%s' passed as NULL",
1647 G_VALUE_TYPE_NAME (value));
1649 *double_range_start = value->data[0].v_double;
1650 *double_range_end = value->data[1].v_double;
1656 * gst_value_set_double_range:
1657 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1658 * @start: the start of the range
1659 * @end: the end of the range
1661 * Sets @value to the range specified by @start and @end.
1664 gst_value_set_double_range (GValue * value, gdouble start, gdouble end)
1666 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
1667 g_return_if_fail (start < end);
1669 value->data[0].v_double = start;
1670 value->data[1].v_double = end;
1674 * gst_value_get_double_range_min:
1675 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1677 * Gets the minimum of the range specified by @value.
1679 * Returns: the minimum of the range
1682 gst_value_get_double_range_min (const GValue * value)
1684 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1686 return value->data[0].v_double;
1690 * gst_value_get_double_range_max:
1691 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
1693 * Gets the maximum of the range specified by @value.
1695 * Returns: the maximum of the range
1698 gst_value_get_double_range_max (const GValue * value)
1700 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
1702 return value->data[1].v_double;
1706 gst_value_transform_double_range_string (const GValue * src_value,
1707 GValue * dest_value)
1709 gchar s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
1711 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
1712 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
1713 src_value->data[0].v_double),
1714 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
1715 src_value->data[1].v_double));
1719 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
1721 if (value2->data[0].v_double == value1->data[0].v_double &&
1722 value2->data[1].v_double == value1->data[1].v_double)
1723 return GST_VALUE_EQUAL;
1724 return GST_VALUE_UNORDERED;
1728 gst_value_serialize_double_range (const GValue * value)
1730 gchar d1[G_ASCII_DTOSTR_BUF_SIZE];
1731 gchar d2[G_ASCII_DTOSTR_BUF_SIZE];
1733 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1734 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
1735 return g_strdup_printf ("[ %s, %s ]", d1, d2);
1739 gst_value_deserialize_double_range (GValue * dest, const gchar * s)
1741 g_warning ("unimplemented");
1750 gst_value_init_fraction_range (GValue * value)
1755 ftype = GST_TYPE_FRACTION;
1757 value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue));
1758 g_value_init (&vals[0], ftype);
1759 g_value_init (&vals[1], ftype);
1763 gst_value_free_fraction_range (GValue * value)
1765 GValue *vals = (GValue *) value->data[0].v_pointer;
1768 /* we know the two values contain fractions without internal allocs */
1769 /* g_value_unset (&vals[0]); */
1770 /* g_value_unset (&vals[1]); */
1771 g_slice_free1 (2 * sizeof (GValue), vals);
1772 value->data[0].v_pointer = NULL;
1777 gst_value_copy_fraction_range (const GValue * src_value, GValue * dest_value)
1779 GValue *vals = (GValue *) dest_value->data[0].v_pointer;
1780 GValue *src_vals = (GValue *) src_value->data[0].v_pointer;
1783 gst_value_init_fraction_range (dest_value);
1784 vals = dest_value->data[0].v_pointer;
1786 if (src_vals != NULL) {
1787 g_value_copy (&src_vals[0], &vals[0]);
1788 g_value_copy (&src_vals[1], &vals[1]);
1793 gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
1794 GTypeCValue * collect_values, guint collect_flags)
1796 GValue *vals = (GValue *) value->data[0].v_pointer;
1798 if (n_collect_values != 4)
1799 return g_strdup_printf ("not enough value locations for `%s' passed",
1800 G_VALUE_TYPE_NAME (value));
1801 if (collect_values[1].v_int == 0)
1802 return g_strdup_printf ("passed '0' as first denominator for `%s'",
1803 G_VALUE_TYPE_NAME (value));
1804 if (collect_values[3].v_int == 0)
1805 return g_strdup_printf ("passed '0' as second denominator for `%s'",
1806 G_VALUE_TYPE_NAME (value));
1807 if (gst_util_fraction_compare (collect_values[0].v_int,
1808 collect_values[1].v_int, collect_values[2].v_int,
1809 collect_values[3].v_int) >= 0)
1810 return g_strdup_printf ("range start is not smaller than end for `%s'",
1811 G_VALUE_TYPE_NAME (value));
1814 gst_value_init_fraction_range (value);
1815 vals = value->data[0].v_pointer;
1818 gst_value_set_fraction (&vals[0], collect_values[0].v_int,
1819 collect_values[1].v_int);
1820 gst_value_set_fraction (&vals[1], collect_values[2].v_int,
1821 collect_values[3].v_int);
1827 gst_value_lcopy_fraction_range (const GValue * value, guint n_collect_values,
1828 GTypeCValue * collect_values, guint collect_flags)
1831 gint *dest_values[4];
1832 GValue *vals = (GValue *) value->data[0].v_pointer;
1834 if (G_UNLIKELY (n_collect_values != 4))
1835 return g_strdup_printf ("not enough value locations for `%s' passed",
1836 G_VALUE_TYPE_NAME (value));
1838 for (i = 0; i < 4; i++) {
1839 if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) {
1840 return g_strdup_printf ("value location for `%s' passed as NULL",
1841 G_VALUE_TYPE_NAME (value));
1843 dest_values[i] = collect_values[i].v_pointer;
1846 if (G_UNLIKELY (vals == NULL)) {
1847 return g_strdup_printf ("Uninitialised `%s' passed",
1848 G_VALUE_TYPE_NAME (value));
1851 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]);
1852 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]);
1853 dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]);
1854 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]);
1859 * gst_value_set_fraction_range:
1860 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1861 * @start: the start of the range (a GST_TYPE_FRACTION GValue)
1862 * @end: the end of the range (a GST_TYPE_FRACTION GValue)
1864 * Sets @value to the range specified by @start and @end.
1867 gst_value_set_fraction_range (GValue * value, const GValue * start,
1872 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
1873 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start));
1874 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end));
1875 g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int,
1876 start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0);
1878 vals = (GValue *) value->data[0].v_pointer;
1880 gst_value_init_fraction_range (value);
1881 vals = value->data[0].v_pointer;
1883 g_value_copy (start, &vals[0]);
1884 g_value_copy (end, &vals[1]);
1888 * gst_value_set_fraction_range_full:
1889 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1890 * @numerator_start: the numerator start of the range
1891 * @denominator_start: the denominator start of the range
1892 * @numerator_end: the numerator end of the range
1893 * @denominator_end: the denominator end of the range
1895 * Sets @value to the range specified by @numerator_start/@denominator_start
1896 * and @numerator_end/@denominator_end.
1899 gst_value_set_fraction_range_full (GValue * value,
1900 gint numerator_start, gint denominator_start,
1901 gint numerator_end, gint denominator_end)
1903 GValue start = { 0 };
1906 g_return_if_fail (value != NULL);
1907 g_return_if_fail (denominator_start != 0);
1908 g_return_if_fail (denominator_end != 0);
1909 g_return_if_fail (gst_util_fraction_compare (numerator_start,
1910 denominator_start, numerator_end, denominator_end) < 0);
1912 g_value_init (&start, GST_TYPE_FRACTION);
1913 g_value_init (&end, GST_TYPE_FRACTION);
1915 gst_value_set_fraction (&start, numerator_start, denominator_start);
1916 gst_value_set_fraction (&end, numerator_end, denominator_end);
1917 gst_value_set_fraction_range (value, &start, &end);
1919 /* we know the two values contain fractions without internal allocs */
1920 /* g_value_unset (&start); */
1921 /* g_value_unset (&end); */
1924 /* FIXME 2.0: Don't leak the internal representation of fraction
1925 * ranges but instead return the numerator and denominator
1927 * This would allow to store fraction ranges as
1928 * data[0] = (min_n << 32) | (min_d)
1929 * data[1] = (max_n << 32) | (max_d)
1930 * without requiring an additional allocation for each value.
1934 * gst_value_get_fraction_range_min:
1935 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1937 * Gets the minimum of the range specified by @value.
1939 * Returns: the minimum of the range
1942 gst_value_get_fraction_range_min (const GValue * value)
1946 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1948 vals = (GValue *) value->data[0].v_pointer;
1957 * gst_value_get_fraction_range_max:
1958 * @value: a GValue initialized to GST_TYPE_FRACTION_RANGE
1960 * Gets the maximum of the range specified by @value.
1962 * Returns: the maximum of the range
1965 gst_value_get_fraction_range_max (const GValue * value)
1969 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value), NULL);
1971 vals = (GValue *) value->data[0].v_pointer;
1980 gst_value_serialize_fraction_range (const GValue * value)
1982 GValue *vals = (GValue *) value->data[0].v_pointer;
1986 retval = g_strdup ("[ 0/1, 0/1 ]");
1990 start = gst_value_serialize_fraction (&vals[0]);
1991 end = gst_value_serialize_fraction (&vals[1]);
1993 retval = g_strdup_printf ("[ %s, %s ]", start, end);
2002 gst_value_transform_fraction_range_string (const GValue * src_value,
2003 GValue * dest_value)
2005 dest_value->data[0].v_pointer =
2006 gst_value_serialize_fraction_range (src_value);
2010 gst_value_compare_fraction_range (const GValue * value1, const GValue * value2)
2012 GValue *vals1, *vals2;
2013 GstValueCompareFunc compare;
2015 if (value2->data[0].v_pointer == value1->data[0].v_pointer)
2016 return GST_VALUE_EQUAL; /* Only possible if both are NULL */
2018 if (value2->data[0].v_pointer == NULL || value1->data[0].v_pointer == NULL)
2019 return GST_VALUE_UNORDERED;
2021 vals1 = (GValue *) value1->data[0].v_pointer;
2022 vals2 = (GValue *) value2->data[0].v_pointer;
2023 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
2024 if (gst_value_compare_with_func (&vals1[0], &vals2[0], compare) ==
2026 gst_value_compare_with_func (&vals1[1], &vals2[1], compare) ==
2028 return GST_VALUE_EQUAL;
2030 return GST_VALUE_UNORDERED;
2034 gst_value_deserialize_fraction_range (GValue * dest, const gchar * s)
2036 g_warning ("unimplemented");
2045 * gst_value_set_caps:
2046 * @value: a GValue initialized to GST_TYPE_CAPS
2047 * @caps: (transfer none): the caps to set the value to
2049 * Sets the contents of @value to @caps. A reference to the
2050 * provided @caps will be taken by the @value.
2053 gst_value_set_caps (GValue * value, const GstCaps * caps)
2055 g_return_if_fail (G_IS_VALUE (value));
2056 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
2057 g_return_if_fail (caps == NULL || GST_IS_CAPS (caps));
2059 g_value_set_boxed (value, caps);
2063 * gst_value_get_caps:
2064 * @value: a GValue initialized to GST_TYPE_CAPS
2066 * Gets the contents of @value. The reference count of the returned
2067 * #GstCaps will not be modified, therefore the caller must take one
2068 * before getting rid of the @value.
2070 * Returns: (transfer none): the contents of @value
2073 gst_value_get_caps (const GValue * value)
2075 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2076 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
2078 return (GstCaps *) g_value_get_boxed (value);
2082 gst_value_compare_caps (const GValue * value1, const GValue * value2)
2084 GstCaps *caps1 = GST_CAPS (gst_value_get_caps (value1));
2085 GstCaps *caps2 = GST_CAPS (gst_value_get_caps (value2));
2087 if (gst_caps_is_equal (caps1, caps2))
2088 return GST_VALUE_EQUAL;
2089 return GST_VALUE_UNORDERED;
2093 gst_value_serialize_caps (const GValue * value)
2095 GstCaps *caps = g_value_get_boxed (value);
2096 return priv_gst_string_take_and_wrap (gst_caps_to_string (caps));
2100 gst_value_deserialize_caps (GValue * dest, const gchar * s)
2105 caps = gst_caps_from_string (s);
2107 gchar *str = gst_string_unwrap (s);
2109 if (G_UNLIKELY (!str))
2112 caps = gst_caps_from_string (str);
2117 g_value_take_boxed (dest, caps);
2123 /********************************************
2124 * Serialization/deserialization of GValues *
2125 ********************************************/
2127 static GstValueAbbreviation *
2128 _priv_gst_value_get_abbrs (gint * n_abbrs)
2130 static GstValueAbbreviation *abbrs = NULL;
2131 static volatile gsize num = 0;
2133 if (g_once_init_enter (&num)) {
2134 /* dynamically generate the array */
2136 GstValueAbbreviation dyn_abbrs[] = {
2141 {"uint", G_TYPE_UINT}
2145 {"float", G_TYPE_FLOAT}
2149 {"double", G_TYPE_DOUBLE}
2151 {"d", G_TYPE_DOUBLE}
2153 {"buffer", GST_TYPE_BUFFER}
2155 {"fraction", GST_TYPE_FRACTION}
2157 {"boolean", G_TYPE_BOOLEAN}
2159 {"bool", G_TYPE_BOOLEAN}
2161 {"b", G_TYPE_BOOLEAN}
2163 {"string", G_TYPE_STRING}
2165 {"str", G_TYPE_STRING}
2167 {"s", G_TYPE_STRING}
2169 {"structure", GST_TYPE_STRUCTURE}
2171 {"date", G_TYPE_DATE}
2173 {"datetime", GST_TYPE_DATE_TIME}
2175 {"bitmask", GST_TYPE_BITMASK}
2177 {"flagset", GST_TYPE_FLAG_SET}
2179 {"sample", GST_TYPE_SAMPLE}
2181 {"taglist", GST_TYPE_TAG_LIST}
2183 {"type", G_TYPE_GTYPE}
2185 {"array", GST_TYPE_ARRAY}
2187 {"list", GST_TYPE_LIST}
2189 _num = G_N_ELEMENTS (dyn_abbrs);
2190 /* permanently allocate and copy the array now */
2191 abbrs = g_new0 (GstValueAbbreviation, _num);
2192 memcpy (abbrs, dyn_abbrs, sizeof (GstValueAbbreviation) * _num);
2193 g_once_init_leave (&num, _num);
2200 /* given a type_name that could be a type abbreviation or a registered GType,
2201 * return a matching GType */
2203 _priv_gst_value_gtype_from_abbr (const char *type_name)
2206 GstValueAbbreviation *abbrs;
2210 g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
2212 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2214 for (i = 0; i < n_abbrs; i++) {
2215 if (strcmp (type_name, abbrs[i].type_name) == 0) {
2216 return abbrs[i].type;
2220 /* this is the fallback */
2221 ret = g_type_from_name (type_name);
2222 /* If not found, try it as a dynamic type */
2223 if (G_UNLIKELY (ret == 0))
2224 ret = gst_dynamic_type_factory_load (type_name);
2230 _priv_gst_value_gtype_to_abbr (GType type)
2233 GstValueAbbreviation *abbrs;
2236 g_return_val_if_fail (type != G_TYPE_INVALID, NULL);
2238 abbrs = _priv_gst_value_get_abbrs (&n_abbrs);
2240 for (i = 0; i < n_abbrs; i++) {
2241 if (type == abbrs[i].type) {
2242 return abbrs[i].type_name;
2246 return g_type_name (type);
2250 * _priv_gst_value_parse_string:
2251 * @s: string to parse
2252 * @end: out-pointer to char behind end of string
2253 * @next: out-pointer to start of unread data
2254 * @unescape: @TRUE if the substring is escaped.
2256 * Find the end of a sub-string. If end == next, the string will not be
2257 * null-terminated. In all other cases it will be.
2259 * Note: This function modifies the string in @s (if unescape == @TRUE).
2261 * Returns: @TRUE if a sub-string was found and @FALSE if the string is not
2265 _priv_gst_value_parse_string (gchar * s, gchar ** end, gchar ** next,
2274 int ret = _priv_gst_value_parse_simple_string (s, end);
2280 /* Find the closing quotes */
2285 if (G_UNLIKELY (*s == 0))
2287 if (G_UNLIKELY (*s == '\\')) {
2289 if (G_UNLIKELY (*s == 0))
2300 if (G_UNLIKELY (*s == 0))
2302 if (G_UNLIKELY (*s == '\\')) {
2304 if (G_UNLIKELY (*s == 0))
2320 _priv_gst_value_parse_range (gchar * s, gchar ** after, GValue * value,
2323 GValue value1 = { 0 };
2324 GValue value2 = { 0 };
2325 GValue value3 = { 0 };
2327 gboolean ret, have_step = FALSE;
2333 ret = _priv_gst_value_parse_value (s, &s, &value1, type);
2337 while (g_ascii_isspace (*s))
2344 while (g_ascii_isspace (*s))
2347 ret = _priv_gst_value_parse_value (s, &s, &value2, type);
2351 while (g_ascii_isspace (*s))
2354 /* optional step for int and int64 */
2355 if (G_VALUE_TYPE (&value1) == G_TYPE_INT
2356 || G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2360 while (g_ascii_isspace (*s))
2363 ret = _priv_gst_value_parse_value (s, &s, &value3, type);
2367 while (g_ascii_isspace (*s))
2378 if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2))
2380 if (have_step && G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value3))
2383 if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
2384 range_type = GST_TYPE_DOUBLE_RANGE;
2385 g_value_init (value, range_type);
2386 gst_value_set_double_range (value,
2387 gst_g_value_get_double_unchecked (&value1),
2388 gst_g_value_get_double_unchecked (&value2));
2389 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
2390 range_type = GST_TYPE_INT_RANGE;
2391 g_value_init (value, range_type);
2393 gst_value_set_int_range_step (value,
2394 gst_g_value_get_int_unchecked (&value1),
2395 gst_g_value_get_int_unchecked (&value2),
2396 gst_g_value_get_int_unchecked (&value3));
2398 gst_value_set_int_range (value, gst_g_value_get_int_unchecked (&value1),
2399 gst_g_value_get_int_unchecked (&value2));
2400 } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT64) {
2401 range_type = GST_TYPE_INT64_RANGE;
2402 g_value_init (value, range_type);
2404 gst_value_set_int64_range_step (value,
2405 gst_g_value_get_int64_unchecked (&value1),
2406 gst_g_value_get_int64_unchecked (&value2),
2407 gst_g_value_get_int64_unchecked (&value3));
2409 gst_value_set_int64_range (value,
2410 gst_g_value_get_int64_unchecked (&value1),
2411 gst_g_value_get_int64_unchecked (&value2));
2412 } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) {
2413 range_type = GST_TYPE_FRACTION_RANGE;
2414 g_value_init (value, range_type);
2415 gst_value_set_fraction_range (value, &value1, &value2);
2425 _priv_gst_value_parse_any_list (gchar * s, gchar ** after, GValue * value,
2426 GType type, char begin, char end)
2428 GValue list_value = { 0 };
2432 array = g_value_peek_pointer (value);
2438 while (g_ascii_isspace (*s))
2446 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2450 g_array_append_val (array, list_value);
2452 while (g_ascii_isspace (*s))
2460 while (g_ascii_isspace (*s))
2463 memset (&list_value, 0, sizeof (list_value));
2464 ret = _priv_gst_value_parse_value (s, &s, &list_value, type);
2468 g_array_append_val (array, list_value);
2469 while (g_ascii_isspace (*s))
2480 _priv_gst_value_parse_list (gchar * s, gchar ** after, GValue * value,
2483 return _priv_gst_value_parse_any_list (s, after, value, type, '{', '}');
2487 _priv_gst_value_parse_array (gchar * s, gchar ** after, GValue * value,
2490 return _priv_gst_value_parse_any_list (s, after, value, type, '<', '>');
2494 _priv_gst_value_parse_simple_string (gchar * str, gchar ** end)
2498 while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
2508 _priv_gst_value_parse_value (gchar * str,
2509 gchar ** after, GValue * value, GType default_type)
2518 GType type = default_type;
2521 while (g_ascii_isspace (*s))
2524 /* check if there's a (type_name) 'cast' */
2528 while (g_ascii_isspace (*s))
2531 if (G_UNLIKELY (!_priv_gst_value_parse_simple_string (s, &type_end)))
2534 while (g_ascii_isspace (*s))
2536 if (G_UNLIKELY (*s != ')'))
2539 while (g_ascii_isspace (*s))
2544 type = _priv_gst_value_gtype_from_abbr (type_name);
2545 GST_DEBUG ("trying type name '%s'", type_name);
2548 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2549 GST_WARNING ("invalid type");
2554 while (g_ascii_isspace (*s))
2557 ret = _priv_gst_value_parse_range (s, &s, value, type);
2558 } else if (*s == '{') {
2559 g_value_init (value, GST_TYPE_LIST);
2560 ret = _priv_gst_value_parse_list (s, &s, value, type);
2561 } else if (*s == '<') {
2562 g_value_init (value, GST_TYPE_ARRAY);
2563 ret = _priv_gst_value_parse_array (s, &s, value, type);
2567 if (G_UNLIKELY (type == G_TYPE_INVALID)) {
2569 { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
2570 G_TYPE_BOOLEAN, G_TYPE_STRING
2574 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s, TRUE)))
2576 /* Set NULL terminator for deserialization */
2580 for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
2581 g_value_init (value, try_types[i]);
2582 ret = gst_value_deserialize (value, value_s);
2585 g_value_unset (value);
2588 g_value_init (value, type);
2590 if (G_UNLIKELY (!_priv_gst_value_parse_string (s, &value_end, &s,
2591 (type != G_TYPE_STRING))))
2593 /* Set NULL terminator for deserialization */
2597 ret = gst_value_deserialize (value, value_s);
2598 if (G_UNLIKELY (!ret))
2599 g_value_unset (value);
2614 gst_value_serialize_segment_internal (const GValue * value, gboolean escape)
2616 GstSegment *seg = g_value_get_boxed (value);
2620 s = gst_structure_new ("GstSegment",
2621 "flags", GST_TYPE_SEGMENT_FLAGS, seg->flags,
2622 "rate", G_TYPE_DOUBLE, seg->rate,
2623 "applied-rate", G_TYPE_DOUBLE, seg->applied_rate,
2624 "format", GST_TYPE_FORMAT, seg->format,
2625 "base", G_TYPE_UINT64, seg->base,
2626 "offset", G_TYPE_UINT64, seg->offset,
2627 "start", G_TYPE_UINT64, seg->start,
2628 "stop", G_TYPE_UINT64, seg->stop,
2629 "time", G_TYPE_UINT64, seg->time,
2630 "position", G_TYPE_UINT64, seg->position,
2631 "duration", G_TYPE_UINT64, seg->duration, NULL);
2632 t = gst_structure_to_string (s);
2634 res = g_strdup_printf ("\"%s\"", t);
2639 gst_structure_free (s);
2645 gst_value_serialize_segment (const GValue * value)
2647 return gst_value_serialize_segment_internal (value, TRUE);
2651 gst_value_deserialize_segment (GValue * dest, const gchar * s)
2657 str = gst_structure_from_string (s, NULL);
2661 res = gst_structure_get (str,
2662 "flags", GST_TYPE_SEGMENT_FLAGS, &seg.flags,
2663 "rate", G_TYPE_DOUBLE, &seg.rate,
2664 "applied-rate", G_TYPE_DOUBLE, &seg.applied_rate,
2665 "format", GST_TYPE_FORMAT, &seg.format,
2666 "base", G_TYPE_UINT64, &seg.base,
2667 "offset", G_TYPE_UINT64, &seg.offset,
2668 "start", G_TYPE_UINT64, &seg.start,
2669 "stop", G_TYPE_UINT64, &seg.stop,
2670 "time", G_TYPE_UINT64, &seg.time,
2671 "position", G_TYPE_UINT64, &seg.position,
2672 "duration", G_TYPE_UINT64, &seg.duration, NULL);
2673 gst_structure_free (str);
2676 g_value_set_boxed (dest, &seg);
2686 * gst_value_set_structure:
2687 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2688 * @structure: the structure to set the value to
2690 * Sets the contents of @value to @structure.
2693 gst_value_set_structure (GValue * value, const GstStructure * structure)
2695 g_return_if_fail (G_IS_VALUE (value));
2696 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE);
2697 g_return_if_fail (structure == NULL || GST_IS_STRUCTURE (structure));
2699 g_value_set_boxed (value, structure);
2703 * gst_value_get_structure:
2704 * @value: a GValue initialized to GST_TYPE_STRUCTURE
2706 * Gets the contents of @value.
2708 * Returns: (transfer none): the contents of @value
2710 const GstStructure *
2711 gst_value_get_structure (const GValue * value)
2713 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2714 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_STRUCTURE, NULL);
2716 return (GstStructure *) g_value_get_boxed (value);
2720 gst_value_serialize_structure (const GValue * value)
2722 GstStructure *structure = g_value_get_boxed (value);
2724 return priv_gst_string_take_and_wrap (gst_structure_to_string (structure));
2728 gst_value_deserialize_structure (GValue * dest, const gchar * s)
2730 GstStructure *structure;
2733 structure = gst_structure_from_string (s, NULL);
2735 gchar *str = gst_string_unwrap (s);
2737 if (G_UNLIKELY (!str))
2740 structure = gst_structure_from_string (str, NULL);
2744 if (G_LIKELY (structure)) {
2745 g_value_take_boxed (dest, structure);
2752 gst_value_compare_structure (const GValue * value1, const GValue * value2)
2754 GstStructure *structure1 = GST_STRUCTURE (g_value_get_boxed (value1));
2755 GstStructure *structure2 = GST_STRUCTURE (g_value_get_boxed (value2));
2757 if (structure1 == structure2)
2758 return GST_VALUE_EQUAL;
2760 if (!structure1 || !structure2)
2761 return GST_VALUE_UNORDERED;
2763 if (gst_structure_is_equal (structure1, structure2))
2764 return GST_VALUE_EQUAL;
2766 return GST_VALUE_UNORDERED;
2769 /*******************
2771 *******************/
2774 * gst_value_set_caps_features:
2775 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2776 * @features: the features to set the value to
2778 * Sets the contents of @value to @features.
2781 gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features)
2783 g_return_if_fail (G_IS_VALUE (value));
2784 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES);
2785 g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features));
2787 g_value_set_boxed (value, features);
2791 * gst_value_get_caps_features:
2792 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2794 * Gets the contents of @value.
2796 * Returns: (transfer none): the contents of @value
2798 const GstCapsFeatures *
2799 gst_value_get_caps_features (const GValue * value)
2801 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2802 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL);
2804 return (GstCapsFeatures *) g_value_get_boxed (value);
2808 gst_value_serialize_caps_features (const GValue * value)
2810 GstCapsFeatures *features = g_value_get_boxed (value);
2812 return priv_gst_string_take_and_wrap (gst_caps_features_to_string (features));
2816 gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
2818 GstCapsFeatures *features;
2821 features = gst_caps_features_from_string (s);
2823 gchar *str = gst_string_unwrap (s);
2825 if (G_UNLIKELY (!str))
2828 features = gst_caps_features_from_string (str);
2832 if (G_LIKELY (features)) {
2833 g_value_take_boxed (dest, features);
2843 gst_value_compare_tag_list (const GValue * value1, const GValue * value2)
2845 GstTagList *taglist1 = GST_TAG_LIST (g_value_get_boxed (value1));
2846 GstTagList *taglist2 = GST_TAG_LIST (g_value_get_boxed (value2));
2848 if (gst_tag_list_is_equal (taglist1, taglist2))
2849 return GST_VALUE_EQUAL;
2850 return GST_VALUE_UNORDERED;
2854 gst_value_deserialize_tag_list (GValue * dest, const gchar * s)
2856 GstTagList *taglist;
2859 taglist = gst_tag_list_new_from_string (s);
2861 gchar *str = gst_string_unwrap (s);
2863 if (G_UNLIKELY (!str))
2866 taglist = gst_tag_list_new_from_string (str);
2870 if (G_LIKELY (taglist != NULL)) {
2871 g_value_take_boxed (dest, taglist);
2878 gst_value_serialize_tag_list (const GValue * value)
2880 GstTagList *taglist = g_value_get_boxed (value);
2882 return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist));
2891 compare_buffer (GstBuffer * buf1, GstBuffer * buf2)
2894 GstMapInfo info1, info2;
2898 return GST_VALUE_EQUAL;
2900 size1 = gst_buffer_get_size (buf1);
2901 size2 = gst_buffer_get_size (buf2);
2904 return GST_VALUE_UNORDERED;
2907 return GST_VALUE_EQUAL;
2909 if (!gst_buffer_map (buf1, &info1, GST_MAP_READ))
2910 return GST_VALUE_UNORDERED;
2912 if (!gst_buffer_map (buf2, &info2, GST_MAP_READ)) {
2913 gst_buffer_unmap (buf1, &info1);
2914 return GST_VALUE_UNORDERED;
2917 mret = memcmp (info1.data, info2.data, info1.size);
2919 result = GST_VALUE_EQUAL;
2921 result = GST_VALUE_LESS_THAN;
2923 result = GST_VALUE_GREATER_THAN;
2925 gst_buffer_unmap (buf1, &info1);
2926 gst_buffer_unmap (buf2, &info2);
2932 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
2934 GstBuffer *buf1 = gst_value_get_buffer (value1);
2935 GstBuffer *buf2 = gst_value_get_buffer (value2);
2937 return compare_buffer (buf1, buf2);
2941 gst_value_serialize_buffer (const GValue * value)
2949 buffer = gst_value_get_buffer (value);
2953 if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
2958 string = g_malloc (info.size * 2 + 1);
2959 for (i = 0; i < info.size; i++) {
2960 sprintf (string + i * 2, "%02x", data[i]);
2962 string[info.size * 2] = 0;
2964 gst_buffer_unmap (buffer, &info);
2970 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
2983 buffer = gst_buffer_new_allocate (NULL, len / 2, NULL);
2984 if (!gst_buffer_map (buffer, &info, GST_MAP_WRITE))
2988 for (i = 0; i < len / 2; i++) {
2989 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
2992 ts[0] = s[i * 2 + 0];
2993 ts[1] = s[i * 2 + 1];
2996 data[i] = (guint8) strtoul (ts, NULL, 16);
2998 gst_buffer_unmap (buffer, &info);
3000 gst_value_take_buffer (dest, buffer);
3015 gst_buffer_unref (buffer);
3016 gst_buffer_unmap (buffer, &info);
3025 /* This function is mostly used for comparing image/buffer tags in taglists */
3027 gst_value_compare_sample (const GValue * value1, const GValue * value2)
3029 GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1));
3030 GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2));
3032 /* FIXME: should we take into account anything else such as caps? */
3033 return compare_buffer (buf1, buf2);
3037 gst_value_serialize_sample (const GValue * value)
3039 const GstStructure *info_structure;
3040 GstSegment *segment;
3044 GValue val = { 0, };
3045 gchar *info_str, *caps_str, *tmp;
3046 gchar *buf_str, *seg_str, *s;
3048 sample = g_value_get_boxed (value);
3050 buffer = gst_sample_get_buffer (sample);
3052 g_value_init (&val, GST_TYPE_BUFFER);
3053 g_value_set_boxed (&val, buffer);
3054 buf_str = gst_value_serialize_buffer (&val);
3055 g_value_unset (&val);
3057 buf_str = g_strdup ("None");
3060 caps = gst_sample_get_caps (sample);
3062 tmp = gst_caps_to_string (caps);
3063 caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3064 g_strdelimit (caps_str, "=", '_');
3067 caps_str = g_strdup ("None");
3070 segment = gst_sample_get_segment (sample);
3072 g_value_init (&val, GST_TYPE_SEGMENT);
3073 g_value_set_boxed (&val, segment);
3074 tmp = gst_value_serialize_segment_internal (&val, FALSE);
3075 seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3076 g_strdelimit (seg_str, "=", '_');
3078 g_value_unset (&val);
3080 seg_str = g_strdup ("None");
3083 info_structure = gst_sample_get_info (sample);
3084 if (info_structure) {
3085 tmp = gst_structure_to_string (info_structure);
3086 info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3087 g_strdelimit (info_str, "=", '_');
3090 info_str = g_strdup ("None");
3093 s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL);
3103 gst_value_deserialize_sample (GValue * dest, const gchar * s)
3105 GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT;
3108 GstCaps *caps = NULL;
3109 gboolean ret = FALSE;
3114 GST_TRACE ("deserialize '%s'", s);
3116 fields = g_strsplit (s, ":", -1);
3117 len = g_strv_length (fields);
3121 g_value_init (&bval, GST_TYPE_BUFFER);
3122 g_value_init (&sval, GST_TYPE_SEGMENT);
3124 if (!gst_value_deserialize_buffer (&bval, fields[0]))
3127 if (strcmp (fields[1], "None") != 0) {
3128 g_strdelimit (fields[1], "_", '=');
3129 g_base64_decode_inplace (fields[1], &outlen);
3130 GST_TRACE ("caps : %s", fields[1]);
3131 caps = gst_caps_from_string (fields[1]);
3136 if (strcmp (fields[2], "None") != 0) {
3137 g_strdelimit (fields[2], "_", '=');
3138 g_base64_decode_inplace (fields[2], &outlen);
3139 GST_TRACE ("segment : %s", fields[2]);
3140 if (!gst_value_deserialize_segment (&sval, fields[2]))
3144 if (strcmp (fields[3], "None") != 0) {
3145 g_strdelimit (fields[3], "_", '=');
3146 g_base64_decode_inplace (fields[3], &outlen);
3147 GST_TRACE ("info : %s", fields[3]);
3148 info = gst_structure_from_string (fields[3], NULL);
3155 sample = gst_sample_new (gst_value_get_buffer (&bval), caps,
3156 g_value_get_boxed (&sval), info);
3158 g_value_take_boxed (dest, sample);
3164 gst_caps_unref (caps);
3165 g_value_unset (&bval);
3166 g_value_unset (&sval);
3170 g_strfreev (fields);
3180 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
3182 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
3183 return GST_VALUE_EQUAL;
3184 return GST_VALUE_UNORDERED;
3188 gst_value_serialize_boolean (const GValue * value)
3190 if (value->data[0].v_int) {
3191 return g_strdup ("true");
3193 return g_strdup ("false");
3197 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
3199 gboolean ret = FALSE;
3201 if (g_ascii_strcasecmp (s, "true") == 0 ||
3202 g_ascii_strcasecmp (s, "yes") == 0 ||
3203 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
3204 g_value_set_boolean (dest, TRUE);
3206 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
3207 g_ascii_strcasecmp (s, "no") == 0 ||
3208 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
3209 g_value_set_boolean (dest, FALSE);
3216 #define CREATE_SERIALIZATION_START(_type,_macro) \
3218 gst_value_compare_ ## _type \
3219 (const GValue * value1, const GValue * value2) \
3221 g ## _type val1 = g_value_get_ ## _type (value1); \
3222 g ## _type val2 = g_value_get_ ## _type (value2); \
3224 return GST_VALUE_GREATER_THAN; \
3226 return GST_VALUE_LESS_THAN; \
3227 return GST_VALUE_EQUAL; \
3231 gst_value_serialize_ ## _type (const GValue * value) \
3233 GValue val = { 0, }; \
3234 g_value_init (&val, G_TYPE_STRING); \
3235 if (!g_value_transform (value, &val)) \
3236 g_assert_not_reached (); \
3237 /* NO_COPY_MADNESS!!! */ \
3238 return (char *) g_value_get_string (&val); \
3241 /* deserialize the given s into to as a gint64.
3242 * check if the result is actually storeable in the given size number of
3246 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
3247 gint64 min, gint64 max, gint size)
3249 gboolean ret = FALSE;
3254 *to = g_ascii_strtoull (s, &end, 0);
3255 /* a range error is a definitive no-no */
3256 if (errno == ERANGE) {
3263 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
3264 *to = G_LITTLE_ENDIAN;
3266 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
3269 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
3272 } else if (g_ascii_strcasecmp (s, "min") == 0) {
3275 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3281 /* by definition, a gint64 fits into a gint64; so ignore those */
3282 if (size != sizeof (mask)) {
3284 /* for positive numbers, we create a mask of 1's outside of the range
3285 * and 0's inside the range. An and will thus keep only 1 bits
3286 * outside of the range */
3287 mask <<= (size * 8);
3288 if ((mask & *to) != 0) {
3292 /* for negative numbers, we do a 2's complement version */
3293 mask <<= ((size * 8) - 1);
3294 if ((mask & *to) != mask) {
3303 #define CREATE_SERIALIZATION(_type,_macro) \
3304 CREATE_SERIALIZATION_START(_type,_macro) \
3307 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3311 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
3312 G_MAX ## _macro, sizeof (g ## _type))) { \
3313 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
3320 #define CREATE_USERIALIZATION(_type,_macro) \
3321 CREATE_SERIALIZATION_START(_type,_macro) \
3324 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3328 gboolean ret = FALSE; \
3331 x = g_ascii_strtoull (s, &end, 0); \
3332 /* a range error is a definitive no-no */ \
3333 if (errno == ERANGE) { \
3336 /* the cast ensures the range check later on makes sense */ \
3337 x = (g ## _type) x; \
3341 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
3342 x = G_LITTLE_ENDIAN; \
3344 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
3347 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
3350 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
3353 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
3354 x = G_MAX ## _macro; \
3359 if (x > G_MAX ## _macro) { \
3362 g_value_set_ ## _type (dest, x); \
3368 CREATE_SERIALIZATION (int, INT);
3369 CREATE_SERIALIZATION (int64, INT64);
3370 CREATE_SERIALIZATION (long, LONG);
3372 CREATE_USERIALIZATION (uint, UINT);
3373 CREATE_USERIALIZATION (uint64, UINT64);
3374 CREATE_USERIALIZATION (ulong, ULONG);
3376 /* FIXME 2.0: remove this again, plugins shouldn't have uchar properties */
3378 #define G_MAXUCHAR 255
3380 CREATE_USERIALIZATION (uchar, UCHAR);
3386 gst_value_compare_double (const GValue * value1, const GValue * value2)
3388 if (value1->data[0].v_double > value2->data[0].v_double)
3389 return GST_VALUE_GREATER_THAN;
3390 if (value1->data[0].v_double < value2->data[0].v_double)
3391 return GST_VALUE_LESS_THAN;
3392 if (value1->data[0].v_double == value2->data[0].v_double)
3393 return GST_VALUE_EQUAL;
3394 return GST_VALUE_UNORDERED;
3398 gst_value_serialize_double (const GValue * value)
3400 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3402 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
3403 return g_strdup (d);
3407 gst_value_deserialize_double (GValue * dest, const gchar * s)
3410 gboolean ret = FALSE;
3413 x = g_ascii_strtod (s, &end);
3417 if (g_ascii_strcasecmp (s, "min") == 0) {
3420 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3426 g_value_set_double (dest, x);
3436 gst_value_compare_float (const GValue * value1, const GValue * value2)
3438 if (value1->data[0].v_float > value2->data[0].v_float)
3439 return GST_VALUE_GREATER_THAN;
3440 if (value1->data[0].v_float < value2->data[0].v_float)
3441 return GST_VALUE_LESS_THAN;
3442 if (value1->data[0].v_float == value2->data[0].v_float)
3443 return GST_VALUE_EQUAL;
3444 return GST_VALUE_UNORDERED;
3448 gst_value_serialize_float (const GValue * value)
3450 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3452 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
3453 return g_strdup (d);
3457 gst_value_deserialize_float (GValue * dest, const gchar * s)
3460 gboolean ret = FALSE;
3463 x = g_ascii_strtod (s, &end);
3467 if (g_ascii_strcasecmp (s, "min") == 0) {
3470 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3475 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
3478 g_value_set_float (dest, (float) x);
3488 gst_value_compare_string (const GValue * value1, const GValue * value2)
3490 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
3491 /* if only one is NULL, no match - otherwise both NULL == EQUAL */
3492 if (value1->data[0].v_pointer != value2->data[0].v_pointer)
3493 return GST_VALUE_UNORDERED;
3495 gint x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
3498 return GST_VALUE_LESS_THAN;
3500 return GST_VALUE_GREATER_THAN;
3503 return GST_VALUE_EQUAL;
3507 gst_string_measure_wrapping (const gchar * s)
3510 gboolean wrap = FALSE;
3512 if (G_UNLIKELY (s == NULL))
3515 /* Special case: the actual string NULL needs wrapping */
3516 if (G_UNLIKELY (strcmp (s, "NULL") == 0))
3521 if (GST_ASCII_IS_STRING (*s)) {
3523 } else if (*s < 0x20 || *s >= 0x7f) {
3533 /* Wrap the string if we found something that needs
3534 * wrapping, or the empty string (len == 0) */
3535 return (wrap || len == 0) ? len : -1;
3539 gst_string_wrap_inner (const gchar * s, gint len)
3543 e = d = g_malloc (len + 3);
3547 if (GST_ASCII_IS_STRING (*s)) {
3549 } else if (*s < 0x20 || *s >= 0x7f) {
3551 *e++ = '0' + ((*(guchar *) s) >> 6);
3552 *e++ = '0' + (((*s) >> 3) & 0x7);
3553 *e++ = '0' + ((*s++) & 0x7);
3562 g_assert (e - d <= len + 3);
3566 /* Do string wrapping/escaping */
3568 gst_string_wrap (const gchar * s)
3570 gint len = gst_string_measure_wrapping (s);
3572 if (G_LIKELY (len < 0))
3573 return g_strdup (s);
3575 return gst_string_wrap_inner (s, len);
3578 /* Same as above, but take ownership of the string */
3580 priv_gst_string_take_and_wrap (gchar * s)
3583 gint len = gst_string_measure_wrapping (s);
3585 if (G_LIKELY (len < 0))
3588 out = gst_string_wrap_inner (s, len);
3595 * This function takes a string delimited with double quotes (")
3596 * and unescapes any \xxx octal numbers.
3598 * If sequences of \y are found where y is not in the range of
3599 * 0->3, y is copied unescaped.
3601 * If \xyy is found where x is an octal number but y is not, an
3602 * error is encountered and %NULL is returned.
3604 * the input string must be \0 terminated.
3607 gst_string_unwrap (const gchar * s)
3610 gchar *read, *write;
3612 /* NULL string returns NULL */
3616 /* strings not starting with " are invalid */
3620 /* make copy of original string to hold the result. This
3621 * string will always be smaller than the original */
3626 /* need to move to the next position as we parsed the " */
3630 if (GST_ASCII_IS_STRING (*read)) {
3631 /* normal chars are just copied */
3633 } else if (*read == '"') {
3634 /* quote marks end of string */
3636 } else if (*read == '\\') {
3637 /* got an escape char, move to next position to read a tripplet
3638 * of octal numbers */
3640 /* is the next char a possible first octal number? */
3641 if (*read >= '0' && *read <= '3') {
3642 /* parse other 2 numbers, if one of them is not in the range of
3643 * an octal number, we error. We also catch the case where a zero
3644 * byte is found here. */
3645 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
3648 /* now convert the octal number to a byte again. */
3649 *write++ = ((read[0] - '0') << 6) +
3650 ((read[1] - '0') << 3) + (read[2] - '0');
3654 /* if we run into a \0 here, we definitely won't get a quote later */
3658 /* else copy \X sequence */
3662 /* weird character, error */
3666 /* if the string is not ending in " and zero terminated, we error */
3667 if (*read != '"' || read[1] != '\0')
3670 /* null terminate result string and return */
3680 gst_value_serialize_string (const GValue * value)
3682 return gst_string_wrap (value->data[0].v_pointer);
3686 gst_value_deserialize_string (GValue * dest, const gchar * s)
3688 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
3689 g_value_set_string (dest, NULL);
3691 } else if (G_LIKELY (*s != '"' || s[strlen (s) - 1] != '"')) {
3692 if (!g_utf8_validate (s, -1, NULL))
3694 g_value_set_string (dest, s);
3697 /* strings delimited with double quotes should be unwrapped */
3698 gchar *str = gst_string_unwrap (s);
3699 if (G_UNLIKELY (!str))
3701 g_value_take_string (dest, str);
3712 gst_value_compare_enum (const GValue * value1, const GValue * value2)
3714 GEnumValue *en1, *en2;
3715 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3716 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3718 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3719 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3720 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
3721 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
3722 g_type_class_unref (klass1);
3723 g_type_class_unref (klass2);
3724 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
3725 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
3726 if (en1->value < en2->value)
3727 return GST_VALUE_LESS_THAN;
3728 if (en1->value > en2->value)
3729 return GST_VALUE_GREATER_THAN;
3731 return GST_VALUE_EQUAL;
3735 gst_value_serialize_enum (const GValue * value)
3738 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
3740 g_return_val_if_fail (klass, NULL);
3741 en = g_enum_get_value (klass, g_value_get_enum (value));
3742 g_type_class_unref (klass);
3744 /* might be one of the custom formats registered later */
3745 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) {
3746 const GstFormatDefinition *format_def;
3748 format_def = gst_format_get_details ((GstFormat) g_value_get_enum (value));
3749 g_return_val_if_fail (format_def != NULL, NULL);
3750 return g_strdup (format_def->description);
3753 g_return_val_if_fail (en, NULL);
3754 return g_strdup (en->value_name);
3758 gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value,
3761 const GstFormatDefinition *format_def =
3762 g_value_get_pointer (format_def_value);
3764 if (g_ascii_strcasecmp (s, format_def->nick) == 0)
3767 return g_ascii_strcasecmp (s, format_def->description);
3771 gst_value_deserialize_enum (GValue * dest, const gchar * s)
3774 gchar *endptr = NULL;
3775 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3777 g_return_val_if_fail (klass, FALSE);
3778 if (!(en = g_enum_get_value_by_name (klass, s))) {
3779 if (!(en = g_enum_get_value_by_nick (klass, s))) {
3780 gint i = strtol (s, &endptr, 0);
3782 if (endptr && *endptr == '\0') {
3783 en = g_enum_get_value (klass, i);
3787 g_type_class_unref (klass);
3789 /* might be one of the custom formats registered later */
3790 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
3791 GValue res = { 0, };
3792 const GstFormatDefinition *format_def;
3796 iter = gst_format_iterate_definitions ();
3798 found = gst_iterator_find_custom (iter,
3799 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
3802 format_def = g_value_get_pointer (&res);
3803 g_return_val_if_fail (format_def != NULL, FALSE);
3804 g_value_set_enum (dest, (gint) format_def->value);
3805 g_value_unset (&res);
3807 gst_iterator_free (iter);
3811 /* enum name/nick not found */
3815 g_value_set_enum (dest, en->value);
3823 /* we just compare the value here */
3825 gst_value_compare_gflags (const GValue * value1, const GValue * value2)
3828 GFlagsClass *klass1 =
3829 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3830 GFlagsClass *klass2 =
3831 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3833 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3834 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3835 fl1 = g_value_get_flags (value1);
3836 fl2 = g_value_get_flags (value2);
3837 g_type_class_unref (klass1);
3838 g_type_class_unref (klass2);
3840 return GST_VALUE_LESS_THAN;
3842 return GST_VALUE_GREATER_THAN;
3844 return GST_VALUE_EQUAL;
3847 /* the different flags are serialized separated with a + */
3849 gst_value_serialize_gflags (const GValue * value)
3853 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
3854 gchar *result, *tmp;
3855 gboolean first = TRUE;
3857 g_return_val_if_fail (klass, NULL);
3859 flags = g_value_get_flags (value);
3861 /* if no flags are set, try to serialize to the _NONE string */
3863 fl = g_flags_get_first_value (klass, flags);
3865 return g_strdup (fl->value_name);
3867 return g_strdup ("0");
3870 /* some flags are set, so serialize one by one */
3871 result = g_strdup ("");
3873 fl = g_flags_get_first_value (klass, flags);
3875 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
3881 flags &= ~fl->value;
3884 g_type_class_unref (klass);
3890 gst_value_gflags_str_to_flags (GFlagsClass * klass, const gchar * s,
3891 guint * out_flags, guint * out_mask)
3895 const gchar *pos = NULL;
3897 gchar *cur_str, *endptr;
3902 g_return_val_if_fail (klass, FALSE);
3904 /* split into parts delimited with + or / and
3905 * compose the set of flags and mask. */
3909 goto done; /* Empty string, nothing to do */
3911 /* As a special case if the first char isn't a delimiter, assume
3912 * it's a '+' - for GFlags strings, which don't start with a
3913 * delimiter, while GFlagSet always will */
3914 if (*pos == '/' || *pos == '+') {
3922 /* Find the next delimiter */
3924 while (*next != '\0' && *next != '+' && *next != '/')
3926 cur_str = g_strndup (pos, next - pos);
3928 if ((fl = g_flags_get_value_by_name (klass, cur_str)))
3930 else if ((fl = g_flags_get_value_by_nick (klass, cur_str)))
3933 val = strtoul (cur_str, &endptr, 0);
3934 /* direct numeric value */
3935 if (endptr == NULL || *endptr != '\0') {
3937 return FALSE; /* Invalid numeric or string we can't convert */
3944 if (delimiter == '+')
3948 /* Advance to the next delimiter */
3952 } while (delimiter != '\0');
3965 gst_value_deserialize_gflags (GValue * dest, const gchar * s)
3967 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3968 gboolean res = FALSE;
3971 if (gst_value_gflags_str_to_flags (klass, s, &flags, NULL)) {
3972 g_value_set_flags (dest, flags);
3976 g_type_class_unref (klass);
3986 gst_value_compare_gtype (const GValue * value1, const GValue * value2)
3988 if (value1->data[0].v_pointer == value2->data[0].v_pointer)
3989 return GST_VALUE_EQUAL;
3990 return GST_VALUE_UNORDERED;
3994 gst_value_serialize_gtype (const GValue * value)
3996 return g_strdup (g_type_name (g_value_get_gtype (value)));
4000 gst_value_deserialize_gtype (GValue * dest, const gchar * s)
4002 GType t = g_type_from_name (s);
4003 gboolean ret = TRUE;
4005 if (t == G_TYPE_INVALID)
4008 g_value_set_gtype (dest, t);
4018 gst_value_is_subset_int_range_int_range (const GValue * value1,
4019 const GValue * value2)
4023 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE);
4024 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE);
4026 if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) <
4027 INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2))
4029 if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) >
4030 INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2))
4033 if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) {
4034 if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) %
4035 INT_RANGE_STEP (value1))
4041 gst_util_greatest_common_divisor (INT_RANGE_STEP (value1),
4042 INT_RANGE_STEP (value2));
4043 if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2)))
4050 gst_value_is_subset_int64_range_int64_range (const GValue * value1,
4051 const GValue * value2)
4055 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE);
4056 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE);
4058 if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2))
4060 if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2))
4063 if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) {
4064 if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) %
4065 INT64_RANGE_STEP (value1))
4071 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1),
4072 INT64_RANGE_STEP (value2));
4073 if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2)))
4079 /* A flag set is a subset of another if the superset allows the
4080 * flags of the subset */
4082 gst_value_is_subset_flagset_flagset (const GValue * value1,
4083 const GValue * value2)
4088 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value1), FALSE);
4089 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value2), FALSE);
4091 f1 = value1->data[0].v_uint;
4092 f2 = value2->data[0].v_uint;
4094 m1 = value1->data[1].v_uint;
4095 m2 = value2->data[1].v_uint;
4097 /* Not a subset if masked bits of superset disagree */
4098 if ((f1 & m1) != (f2 & (m1 & m2)))
4105 gst_value_is_subset_structure_structure (const GValue * value1,
4106 const GValue * value2)
4108 const GstStructure *s1, *s2;
4110 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value1), FALSE);
4111 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value2), FALSE);
4113 s1 = gst_value_get_structure (value1);
4114 s2 = gst_value_get_structure (value2);
4116 return gst_structure_is_subset (s1, s2);
4120 * gst_value_is_subset:
4121 * @value1: a #GValue
4122 * @value2: a #GValue
4124 * Check that @value1 is a subset of @value2.
4126 * Return: %TRUE is @value1 is a subset of @value2
4129 gst_value_is_subset (const GValue * value1, const GValue * value2)
4131 /* special case for int/int64 ranges, since we cannot compute
4132 the difference for those when they have different steps,
4133 and it's actually a lot simpler to compute whether a range
4134 is a subset of another. */
4135 if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) {
4136 return gst_value_is_subset_int_range_int_range (value1, value2);
4137 } else if (GST_VALUE_HOLDS_INT64_RANGE (value1)
4138 && GST_VALUE_HOLDS_INT64_RANGE (value2)) {
4139 return gst_value_is_subset_int64_range_int64_range (value1, value2);
4140 } else if (GST_VALUE_HOLDS_FLAG_SET (value1) &&
4141 GST_VALUE_HOLDS_FLAG_SET (value2)) {
4142 return gst_value_is_subset_flagset_flagset (value1, value2);
4143 } else if (GST_VALUE_HOLDS_STRUCTURE (value1)
4144 && GST_VALUE_HOLDS_STRUCTURE (value2)) {
4145 return gst_value_is_subset_structure_structure (value1, value2);
4153 * -> 1 - [1,2] = empty
4157 * -> [1,2] - [1,3] = empty
4161 * -> {1,3} - {1,2} = 3
4164 * First caps subtraction needs to return a non-empty set, second
4165 * subtractions needs to give en empty set.
4166 * Both substractions are switched below, as it's faster that way.
4168 if (!gst_value_subtract (NULL, value1, value2)) {
4169 if (gst_value_subtract (NULL, value2, value1)) {
4181 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
4182 const GValue * src2)
4184 gint v = src1->data[0].v_int;
4186 /* check if it's already in the range */
4187 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v &&
4188 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v &&
4189 v % INT_RANGE_STEP (src2) == 0) {
4191 gst_value_init_and_copy (dest, src2);
4195 /* check if it extends the range */
4196 if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) {
4198 guint64 new_min = INT_RANGE_MIN (src2) - 1;
4199 guint64 new_max = INT_RANGE_MAX (src2);
4201 gst_value_init_and_copy (dest, src2);
4202 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4206 if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) {
4208 guint64 new_min = INT_RANGE_MIN (src2);
4209 guint64 new_max = INT_RANGE_MAX (src2) + 1;
4211 gst_value_init_and_copy (dest, src2);
4212 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4221 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
4222 const GValue * src2)
4224 /* We can union in several special cases:
4225 1 - one is a subset of another
4226 2 - same step and not disjoint
4227 3 - different step, at least one with one value which matches a 'next' or 'previous'
4232 if (gst_value_is_subset_int_range_int_range (src1, src2)) {
4234 gst_value_init_and_copy (dest, src2);
4237 if (gst_value_is_subset_int_range_int_range (src2, src1)) {
4239 gst_value_init_and_copy (dest, src1);
4243 /* 2 - same step and not disjoint */
4244 if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) {
4245 if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 &&
4246 INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) ||
4247 (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 &&
4248 INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) {
4250 gint step = INT_RANGE_STEP (src1);
4251 gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2));
4252 gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2));
4253 g_value_init (dest, GST_TYPE_INT_RANGE);
4254 gst_value_set_int_range_step (dest, min, max, step);
4260 /* 3 - single value matches next or previous */
4261 if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) {
4262 gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1;
4263 gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1;
4264 if (n1 == 1 || n2 == 1) {
4265 const GValue *range_value = NULL;
4269 scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1);
4270 } else if (n2 == 1) {
4272 scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2);
4276 (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) {
4278 guint64 new_min = (guint)
4279 ((INT_RANGE_MIN (range_value) -
4280 1) * INT_RANGE_STEP (range_value));
4281 guint64 new_max = (guint)
4282 (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value));
4284 gst_value_init_and_copy (dest, range_value);
4285 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4288 } else if (scalar ==
4289 (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) {
4291 guint64 new_min = (guint)
4292 (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value));
4293 guint64 new_max = (guint)
4294 ((INT_RANGE_MAX (range_value) +
4295 1) * INT_RANGE_STEP (range_value));
4296 gst_value_init_and_copy (dest, range_value);
4297 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4304 /* If we get there, we did not find a way to make a union that can be
4305 represented with our simplistic model. */
4310 gst_value_union_flagset_flagset (GValue * dest, const GValue * src1,
4311 const GValue * src2)
4313 /* We can union 2 flag sets where they do not disagree on
4314 * required (masked) flag bits */
4318 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4319 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4321 f1 = src1->data[0].v_uint;
4322 f2 = src2->data[0].v_uint;
4324 m1 = src1->data[1].v_uint;
4325 m2 = src2->data[1].v_uint;
4327 /* Can't union if masked bits disagree */
4328 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4332 g_value_init (dest, GST_TYPE_FLAG_SET);
4333 /* Copy masked bits from src2 to src1 */
4337 gst_value_set_flagset (dest, f1, m1);
4343 /* iterating over the result taking the union with the other structure's value */
4345 structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
4347 GstStructure *other = user_data;
4348 const GValue *other_value;
4349 GValue res_value = G_VALUE_INIT;
4351 other_value = gst_structure_id_get_value (other, field_id);
4352 /* no value in the other struct, just keep this value */
4356 if (!gst_value_union (&res_value, val, other_value))
4359 g_value_unset (val);
4360 gst_value_move (val, &res_value);
4364 /* iterating over the other source structure adding missing values */
4366 structure_field_union_from (GQuark field_id, const GValue * other_val,
4369 GstStructure *result = user_data;
4370 const GValue *result_value;
4372 result_value = gst_structure_id_get_value (result, field_id);
4374 gst_structure_id_set_value (result, field_id, other_val);
4380 gst_value_union_structure_structure (GValue * dest, const GValue * src1,
4381 const GValue * src2)
4383 const GstStructure *s1, *s2;
4384 GstStructure *result;
4387 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src1), FALSE);
4388 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src2), FALSE);
4390 s1 = gst_value_get_structure (src1);
4391 s2 = gst_value_get_structure (src2);
4393 /* Can't join two structures with different names into a single structure */
4394 if (!gst_structure_has_name (s1, gst_structure_get_name (s2))) {
4395 gst_value_list_concat (dest, src1, src2);
4399 result = gst_structure_copy (s1);
4401 gst_structure_map_in_place (result, structure_field_union_into,
4406 gst_structure_foreach (s2, structure_field_union_from, (gpointer) result);
4409 g_value_init (dest, GST_TYPE_STRUCTURE);
4410 gst_value_set_structure (dest, result);
4414 gst_structure_free (result);
4423 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
4424 const GValue * src2)
4426 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int &&
4427 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int &&
4428 src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) {
4430 gst_value_init_and_copy (dest, src1);
4438 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
4439 const GValue * src2)
4446 INT_RANGE_STEP (src1) /
4447 gst_util_greatest_common_divisor (INT_RANGE_STEP (src1),
4448 INT_RANGE_STEP (src2));
4449 if (G_MAXINT32 / INT_RANGE_STEP (src2) < step)
4451 step *= INT_RANGE_STEP (src2);
4454 MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1),
4455 INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
4456 min = (min + step - 1) / step * step;
4458 MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1),
4459 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
4460 max = max / step * step;
4464 g_value_init (dest, GST_TYPE_INT_RANGE);
4465 gst_value_set_int_range_step (dest, min, max, step);
4471 g_value_init (dest, G_TYPE_INT);
4472 g_value_set_int (dest, min);
4480 #define INT64_RANGE_MIN_VAL(v) (INT64_RANGE_MIN (v) * INT64_RANGE_STEP (v))
4481 #define INT64_RANGE_MAX_VAL(v) (INT64_RANGE_MAX (v) * INT64_RANGE_STEP (v))
4484 gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1,
4485 const GValue * src2)
4487 if (INT64_RANGE_MIN_VAL (src2) <= src1->data[0].v_int64 &&
4488 INT64_RANGE_MAX_VAL (src2) >= src1->data[0].v_int64 &&
4489 src1->data[0].v_int64 % INT64_RANGE_STEP (src2) == 0) {
4491 gst_value_init_and_copy (dest, src1);
4499 gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1,
4500 const GValue * src2)
4507 INT64_RANGE_STEP (src1) /
4508 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1),
4509 INT64_RANGE_STEP (src2));
4510 if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step)
4512 step *= INT64_RANGE_STEP (src2);
4515 MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1),
4516 INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2));
4517 min = (min + step - 1) / step * step;
4519 MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1),
4520 INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2));
4521 max = max / step * step;
4525 g_value_init (dest, GST_TYPE_INT64_RANGE);
4526 gst_value_set_int64_range_step (dest, min, max, step);
4532 g_value_init (dest, G_TYPE_INT64);
4533 g_value_set_int64 (dest, min);
4542 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
4543 const GValue * src2)
4545 if (src2->data[0].v_double <= src1->data[0].v_double &&
4546 src2->data[1].v_double >= src1->data[0].v_double) {
4548 gst_value_init_and_copy (dest, src1);
4556 gst_value_intersect_double_range_double_range (GValue * dest,
4557 const GValue * src1, const GValue * src2)
4562 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
4563 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
4567 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
4568 gst_value_set_double_range (dest, min, max);
4574 g_value_init (dest, G_TYPE_DOUBLE);
4575 g_value_set_int (dest, (int) min);
4584 gst_value_intersect_list (GValue * dest, const GValue * value1,
4585 const GValue * value2)
4588 GValue intersection = { 0, };
4589 gboolean ret = FALSE;
4591 size = VALUE_LIST_SIZE (value1);
4592 for (i = 0; i < size; i++) {
4593 const GValue *cur = VALUE_LIST_GET_VALUE (value1, i);
4595 /* quicker version when we don't need the resulting set */
4597 if (gst_value_intersect (NULL, cur, value2)) {
4604 if (gst_value_intersect (&intersection, cur, value2)) {
4607 gst_value_move (dest, &intersection);
4609 } else if (GST_VALUE_HOLDS_LIST (dest)) {
4610 _gst_value_list_append_and_take_value (dest, &intersection);
4614 gst_value_move (&temp, dest);
4615 gst_value_list_merge (dest, &temp, &intersection);
4616 g_value_unset (&temp);
4617 g_value_unset (&intersection);
4626 gst_value_intersect_array (GValue * dest, const GValue * src1,
4627 const GValue * src2)
4633 /* only works on similar-sized arrays */
4634 size = gst_value_array_get_size (src1);
4635 if (size != gst_value_array_get_size (src2))
4638 /* quicker value when we don't need the resulting set */
4640 for (n = 0; n < size; n++) {
4641 if (!gst_value_intersect (NULL, gst_value_array_get_value (src1, n),
4642 gst_value_array_get_value (src2, n))) {
4649 g_value_init (dest, GST_TYPE_ARRAY);
4651 for (n = 0; n < size; n++) {
4652 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
4653 gst_value_array_get_value (src2, n))) {
4654 g_value_unset (dest);
4657 _gst_value_array_append_and_take_value (dest, &val);
4664 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
4665 const GValue * src2)
4669 GstValueCompareFunc compare;
4671 vals = src2->data[0].v_pointer;
4676 if ((compare = gst_value_get_compare_func (src1))) {
4677 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
4678 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
4680 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
4681 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
4683 gst_value_init_and_copy (dest, src1);
4692 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
4693 const GValue * src1, const GValue * src2)
4698 GValue *vals1, *vals2;
4699 GstValueCompareFunc compare;
4701 vals1 = src1->data[0].v_pointer;
4702 vals2 = src2->data[0].v_pointer;
4703 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
4705 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
4706 /* min = MAX (src1.start, src2.start) */
4707 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
4708 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4709 if (res == GST_VALUE_LESS_THAN)
4710 min = &vals2[0]; /* Take the max of the 2 */
4714 /* max = MIN (src1.end, src2.end) */
4715 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
4716 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4717 if (res == GST_VALUE_GREATER_THAN)
4718 max = &vals2[1]; /* Take the min of the 2 */
4722 res = gst_value_compare_with_func (min, max, compare);
4723 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4724 if (res == GST_VALUE_LESS_THAN) {
4726 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
4727 vals1 = dest->data[0].v_pointer;
4728 g_value_copy (min, &vals1[0]);
4729 g_value_copy (max, &vals1[1]);
4733 if (res == GST_VALUE_EQUAL) {
4735 gst_value_init_and_copy (dest, min);
4743 /* Two flagsets intersect if the masked bits in both
4744 * flagsets are exactly equal */
4746 gst_value_intersect_flagset_flagset (GValue * dest,
4747 const GValue * src1, const GValue * src2)
4751 GType type1, type2, flagset_type;
4753 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4754 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4756 f1 = src1->data[0].v_uint;
4757 f2 = src2->data[0].v_uint;
4759 m1 = src1->data[1].v_uint;
4760 m2 = src2->data[1].v_uint;
4762 /* Don't intersect if masked bits disagree */
4763 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4766 /* Allow intersection with the generic FlagSet type, on one
4767 * side, but not 2 different subtypes - that makes no sense */
4768 type1 = G_VALUE_TYPE (src1);
4769 type2 = G_VALUE_TYPE (src2);
4770 flagset_type = GST_TYPE_FLAG_SET;
4772 if (type1 != type2 && type1 != flagset_type && type2 != flagset_type)
4778 /* Prefer an output type that matches a sub-type,
4779 * rather than the generic type */
4780 if (type1 != flagset_type)
4785 g_value_init (dest, dest_type);
4787 /* The compatible set is all the bits from src1 that it
4788 * cares about and all the bits from src2 that it cares
4790 dest->data[0].v_uint = (f1 & m1) | (f2 & m2);
4791 dest->data[1].v_uint = m1 | m2;
4798 gst_value_intersect_structure_structure (GValue * dest,
4799 const GValue * src1, const GValue * src2)
4801 const GstStructure *s1, *s2;
4804 s1 = gst_value_get_structure (src1);
4805 s2 = gst_value_get_structure (src2);
4807 d1 = gst_structure_intersect (s1, s2);
4812 g_value_init (dest, GST_TYPE_STRUCTURE);
4813 gst_value_set_structure (dest, d1);
4816 gst_structure_free (d1);
4825 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
4826 const GValue * subtrahend)
4828 gint min = gst_value_get_int_range_min (subtrahend);
4829 gint max = gst_value_get_int_range_max (subtrahend);
4830 gint step = gst_value_get_int_range_step (subtrahend);
4831 gint val = g_value_get_int (minuend);
4836 /* subtracting a range from an int only works if the int is not in the
4838 if (val < min || val > max || val % step) {
4839 /* and the result is the int */
4841 gst_value_init_and_copy (dest, minuend);
4847 /* creates a new int range based on input values.
4850 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
4851 gint max2, gint step)
4855 GValue *pv1, *pv2; /* yeah, hungarian! */
4857 g_return_val_if_fail (step > 0, FALSE);
4858 g_return_val_if_fail (min1 % step == 0, FALSE);
4859 g_return_val_if_fail (max1 % step == 0, FALSE);
4860 g_return_val_if_fail (min2 % step == 0, FALSE);
4861 g_return_val_if_fail (max2 % step == 0, FALSE);
4863 if (min1 <= max1 && min2 <= max2) {
4866 } else if (min1 <= max1) {
4869 } else if (min2 <= max2) {
4880 g_value_init (pv1, GST_TYPE_INT_RANGE);
4881 gst_value_set_int_range_step (pv1, min1, max1, step);
4882 } else if (min1 == max1) {
4883 g_value_init (pv1, G_TYPE_INT);
4884 g_value_set_int (pv1, min1);
4887 g_value_init (pv2, GST_TYPE_INT_RANGE);
4888 gst_value_set_int_range_step (pv2, min2, max2, step);
4889 } else if (min2 == max2) {
4890 g_value_init (pv2, G_TYPE_INT);
4891 g_value_set_int (pv2, min2);
4894 if (min1 <= max1 && min2 <= max2) {
4895 gst_value_list_concat_and_take_values (dest, pv1, pv2);
4901 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
4902 const GValue * subtrahend)
4904 gint min = gst_value_get_int_range_min (minuend);
4905 gint max = gst_value_get_int_range_max (minuend);
4906 gint step = gst_value_get_int_range_step (minuend);
4907 gint val = g_value_get_int (subtrahend);
4909 g_return_val_if_fail (min < max, FALSE);
4914 /* value is outside of the range, return range unchanged */
4915 if (val < min || val > max || val % step) {
4917 gst_value_init_and_copy (dest, minuend);
4920 /* max must be MAXINT too as val <= max */
4921 if (val >= G_MAXINT - step + 1) {
4925 /* min must be MININT too as val >= max */
4926 if (val <= G_MININT + step - 1) {
4931 gst_value_create_new_range (dest, min, val - step, val + step, max, step);
4937 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
4938 const GValue * subtrahend)
4940 gint min1 = gst_value_get_int_range_min (minuend);
4941 gint max1 = gst_value_get_int_range_max (minuend);
4942 gint step1 = gst_value_get_int_range_step (minuend);
4943 gint min2 = gst_value_get_int_range_min (subtrahend);
4944 gint max2 = gst_value_get_int_range_max (subtrahend);
4945 gint step2 = gst_value_get_int_range_step (subtrahend);
4948 if (step1 != step2) {
4958 if (max2 >= max1 && min2 <= min1) {
4960 } else if (max2 >= max1) {
4961 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4963 } else if (min2 <= min1) {
4964 return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1,
4967 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4968 MAX (max2 + step, min1), max1, step);
4973 gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
4974 const GValue * subtrahend)
4976 gint64 min = gst_value_get_int64_range_min (subtrahend);
4977 gint64 max = gst_value_get_int64_range_max (subtrahend);
4978 gint64 step = gst_value_get_int64_range_step (subtrahend);
4979 gint64 val = g_value_get_int64 (minuend);
4983 /* subtracting a range from an int64 only works if the int64 is not in the
4985 if (val < min || val > max || val % step) {
4986 /* and the result is the int64 */
4988 gst_value_init_and_copy (dest, minuend);
4994 /* creates a new int64 range based on input values.
4997 gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
4998 gint64 min2, gint64 max2, gint64 step)
5002 GValue *pv1, *pv2; /* yeah, hungarian! */
5004 g_return_val_if_fail (step > 0, FALSE);
5005 g_return_val_if_fail (min1 % step == 0, FALSE);
5006 g_return_val_if_fail (max1 % step == 0, FALSE);
5007 g_return_val_if_fail (min2 % step == 0, FALSE);
5008 g_return_val_if_fail (max2 % step == 0, FALSE);
5010 if (min1 <= max1 && min2 <= max2) {
5013 } else if (min1 <= max1) {
5016 } else if (min2 <= max2) {
5027 g_value_init (pv1, GST_TYPE_INT64_RANGE);
5028 gst_value_set_int64_range_step (pv1, min1, max1, step);
5029 } else if (min1 == max1) {
5030 g_value_init (pv1, G_TYPE_INT64);
5031 g_value_set_int64 (pv1, min1);
5034 g_value_init (pv2, GST_TYPE_INT64_RANGE);
5035 gst_value_set_int64_range_step (pv2, min2, max2, step);
5036 } else if (min2 == max2) {
5037 g_value_init (pv2, G_TYPE_INT64);
5038 g_value_set_int64 (pv2, min2);
5041 if (min1 <= max1 && min2 <= max2) {
5042 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5048 gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
5049 const GValue * subtrahend)
5051 gint64 min = gst_value_get_int64_range_min (minuend);
5052 gint64 max = gst_value_get_int64_range_max (minuend);
5053 gint64 step = gst_value_get_int64_range_step (minuend);
5054 gint64 val = g_value_get_int64 (subtrahend);
5056 g_return_val_if_fail (min < max, FALSE);
5061 /* value is outside of the range, return range unchanged */
5062 if (val < min || val > max || val % step) {
5064 gst_value_init_and_copy (dest, minuend);
5067 /* max must be MAXINT64 too as val <= max */
5068 if (val >= G_MAXINT64 - step + 1) {
5072 /* min must be MININT64 too as val >= max */
5073 if (val <= G_MININT64 + step - 1) {
5078 gst_value_create_new_int64_range (dest, min, val - step, val + step, max,
5085 gst_value_subtract_int64_range_int64_range (GValue * dest,
5086 const GValue * minuend, const GValue * subtrahend)
5088 gint64 min1 = gst_value_get_int64_range_min (minuend);
5089 gint64 max1 = gst_value_get_int64_range_max (minuend);
5090 gint64 step1 = gst_value_get_int64_range_step (minuend);
5091 gint64 min2 = gst_value_get_int64_range_min (subtrahend);
5092 gint64 max2 = gst_value_get_int64_range_max (subtrahend);
5093 gint64 step2 = gst_value_get_int64_range_step (subtrahend);
5096 if (step1 != step2) {
5107 if (max2 >= max1 && min2 <= min1) {
5109 } else if (max2 >= max1) {
5110 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5111 max1), step, 0, step);
5112 } else if (min2 <= min1) {
5113 return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1),
5114 max1, step, 0, step);
5116 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5117 max1), MAX (max2 + step, min1), max1, step);
5122 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
5123 const GValue * subtrahend)
5125 gdouble min = gst_value_get_double_range_min (subtrahend);
5126 gdouble max = gst_value_get_double_range_max (subtrahend);
5127 gdouble val = g_value_get_double (minuend);
5129 if (val < min || val > max) {
5131 gst_value_init_and_copy (dest, minuend);
5138 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
5139 const GValue * subtrahend)
5141 /* since we don't have open ranges, we cannot create a hole in
5142 * a double range. We return the original range */
5144 gst_value_init_and_copy (dest, minuend);
5149 gst_value_subtract_double_range_double_range (GValue * dest,
5150 const GValue * minuend, const GValue * subtrahend)
5152 /* since we don't have open ranges, we have to approximate */
5153 /* done like with ints */
5154 gdouble min1 = gst_value_get_double_range_min (minuend);
5155 gdouble max2 = gst_value_get_double_range_max (minuend);
5156 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
5157 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
5160 GValue *pv1, *pv2; /* yeah, hungarian! */
5162 if (min1 < max1 && min2 < max2) {
5165 } else if (min1 < max1) {
5168 } else if (min2 < max2) {
5179 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
5180 gst_value_set_double_range (pv1, min1, max1);
5183 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
5184 gst_value_set_double_range (pv2, min2, max2);
5187 if (min1 < max1 && min2 < max2) {
5188 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5194 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
5195 const GValue * subtrahend)
5198 GValue subtraction = { 0, };
5199 gboolean ret = FALSE;
5201 size = VALUE_LIST_SIZE (minuend);
5202 for (i = 0; i < size; i++) {
5203 const GValue *cur = VALUE_LIST_GET_VALUE (minuend, i);
5205 /* quicker version when we can discard the result */
5207 if (gst_value_subtract (NULL, cur, subtrahend)) {
5214 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
5216 gst_value_move (dest, &subtraction);
5218 } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST
5219 && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) {
5220 _gst_value_list_append_and_take_value (dest, &subtraction);
5224 gst_value_move (&temp, dest);
5225 gst_value_list_concat_and_take_values (dest, &temp, &subtraction);
5233 gst_value_subtract_list (GValue * dest, const GValue * minuend,
5234 const GValue * subtrahend)
5237 GValue data[2] = { {0,}, {0,} };
5238 GValue *subtraction = &data[0], *result = &data[1];
5240 gst_value_init_and_copy (result, minuend);
5241 size = VALUE_LIST_SIZE (subtrahend);
5242 for (i = 0; i < size; i++) {
5243 const GValue *cur = VALUE_LIST_GET_VALUE (subtrahend, i);
5245 if (gst_value_subtract (subtraction, result, cur)) {
5246 GValue *temp = result;
5248 result = subtraction;
5250 g_value_unset (subtraction);
5252 g_value_unset (result);
5257 gst_value_move (dest, result);
5259 g_value_unset (result);
5265 gst_value_subtract_fraction_fraction_range (GValue * dest,
5266 const GValue * minuend, const GValue * subtrahend)
5268 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
5269 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
5270 GstValueCompareFunc compare;
5272 if ((compare = gst_value_get_compare_func (minuend))) {
5273 /* subtracting a range from an fraction only works if the fraction
5274 * is not in the range */
5275 if (gst_value_compare_with_func (minuend, min, compare) ==
5276 GST_VALUE_LESS_THAN ||
5277 gst_value_compare_with_func (minuend, max, compare) ==
5278 GST_VALUE_GREATER_THAN) {
5279 /* and the result is the value */
5281 gst_value_init_and_copy (dest, minuend);
5289 gst_value_subtract_fraction_range_fraction (GValue * dest,
5290 const GValue * minuend, const GValue * subtrahend)
5292 /* since we don't have open ranges, we cannot create a hole in
5293 * a range. We return the original range */
5295 gst_value_init_and_copy (dest, minuend);
5300 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
5301 const GValue * minuend, const GValue * subtrahend)
5303 /* since we don't have open ranges, we have to approximate */
5304 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
5305 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
5306 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
5307 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
5308 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
5312 GValue *pv1, *pv2; /* yeah, hungarian! */
5313 GstValueCompareFunc compare;
5315 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
5316 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
5318 compare = gst_value_get_compare_func (min1);
5319 g_return_val_if_fail (compare, FALSE);
5321 cmp1 = gst_value_compare_with_func (max2, max1, compare);
5322 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5323 if (cmp1 == GST_VALUE_LESS_THAN)
5325 cmp1 = gst_value_compare_with_func (min1, min2, compare);
5326 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5327 if (cmp1 == GST_VALUE_GREATER_THAN)
5330 cmp1 = gst_value_compare_with_func (min1, max1, compare);
5331 cmp2 = gst_value_compare_with_func (min2, max2, compare);
5333 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5336 } else if (cmp1 == GST_VALUE_LESS_THAN) {
5339 } else if (cmp2 == GST_VALUE_LESS_THAN) {
5349 if (cmp1 == GST_VALUE_LESS_THAN) {
5350 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
5351 gst_value_set_fraction_range (pv1, min1, max1);
5353 if (cmp2 == GST_VALUE_LESS_THAN) {
5354 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
5355 gst_value_set_fraction_range (pv2, min2, max2);
5358 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5359 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5369 * gst_value_get_compare_func:
5370 * @value1: a value to get the compare function for
5372 * Determines the compare function to be used with values of the same type as
5373 * @value1. The function can be given to gst_value_compare_with_func().
5375 * Returns: A #GstValueCompareFunc value
5377 static GstValueCompareFunc
5378 gst_value_get_compare_func (const GValue * value1)
5380 GstValueTable *table, *best = NULL;
5384 type1 = G_VALUE_TYPE (value1);
5386 /* this is a fast check */
5387 best = gst_value_hash_lookup_type (type1);
5390 if (G_UNLIKELY (!best || !best->compare)) {
5391 guint len = gst_value_table->len;
5394 for (i = 0; i < len; i++) {
5395 table = &g_array_index (gst_value_table, GstValueTable, i);
5396 if (table->compare && g_type_is_a (type1, table->type)) {
5397 if (!best || g_type_is_a (table->type, best->type))
5402 if (G_LIKELY (best))
5403 return best->compare;
5408 static inline gboolean
5409 gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2)
5411 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5414 return gst_value_get_compare_func (value1) != NULL;
5418 * gst_value_can_compare:
5419 * @value1: a value to compare
5420 * @value2: another value to compare
5422 * Determines if @value1 and @value2 can be compared.
5424 * Returns: %TRUE if the values can be compared
5427 gst_value_can_compare (const GValue * value1, const GValue * value2)
5429 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5430 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5432 return gst_value_can_compare_unchecked (value1, value2);
5436 gst_value_list_equals_range (const GValue * list, const GValue * value)
5438 const GValue *first;
5441 g_assert (G_IS_VALUE (list));
5442 g_assert (G_IS_VALUE (value));
5443 g_assert (GST_VALUE_HOLDS_LIST (list));
5445 /* TODO: compare against an empty list ? No type though... */
5446 list_size = VALUE_LIST_SIZE (list);
5450 /* compare the basic types - they have to match */
5451 first = VALUE_LIST_GET_VALUE (list, 0);
5452 #define CHECK_TYPES(type,prefix) \
5453 (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value))
5454 if (CHECK_TYPES (INT, G)) {
5455 const gint rmin = gst_value_get_int_range_min (value);
5456 const gint rmax = gst_value_get_int_range_max (value);
5457 const gint rstep = gst_value_get_int_range_step (value);
5460 /* note: this will overflow for min 0 and max INT_MAX, but this
5461 would only be equal to a list of INT_MAX elements, which seems
5463 if (list_size != rmax / rstep - rmin / rstep + 1)
5465 for (n = 0; n < list_size; ++n) {
5466 gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n));
5467 if (v < rmin || v > rmax || v % rstep) {
5472 } else if (CHECK_TYPES (INT64, G)) {
5473 const gint64 rmin = gst_value_get_int64_range_min (value);
5474 const gint64 rmax = gst_value_get_int64_range_max (value);
5475 const gint64 rstep = gst_value_get_int64_range_step (value);
5476 GST_DEBUG ("List/range of int64s");
5479 if (list_size != rmax / rstep - rmin / rstep + 1)
5481 for (n = 0; n < list_size; ++n) {
5482 gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n));
5483 if (v < rmin || v > rmax || v % rstep)
5490 /* other combinations don't make sense for equality */
5494 /* "Pure" variant of gst_value_compare which is guaranteed to
5495 * not have list arguments and therefore does basic comparisions
5498 _gst_value_compare_nolist (const GValue * value1, const GValue * value2)
5500 GstValueCompareFunc compare;
5502 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5503 return GST_VALUE_UNORDERED;
5505 compare = gst_value_get_compare_func (value1);
5507 return compare (value1, value2);
5510 g_critical ("unable to compare values of type %s\n",
5511 g_type_name (G_VALUE_TYPE (value1)));
5512 return GST_VALUE_UNORDERED;
5516 * gst_value_compare:
5517 * @value1: a value to compare
5518 * @value2: another value to compare
5520 * Compares @value1 and @value2. If @value1 and @value2 cannot be
5521 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
5522 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned.
5523 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned.
5524 * If the values are equal, GST_VALUE_EQUAL is returned.
5526 * Returns: comparison result
5529 gst_value_compare (const GValue * value1, const GValue * value2)
5531 gboolean value1_is_list;
5532 gboolean value2_is_list;
5534 g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
5535 g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN);
5537 value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST;
5538 value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST;
5540 /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal),
5541 as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
5542 if (value1_is_list && !value2_is_list) {
5545 if (gst_value_list_equals_range (value1, value2)) {
5546 return GST_VALUE_EQUAL;
5549 n = gst_value_list_get_size (value1);
5551 return GST_VALUE_UNORDERED;
5553 for (i = 0; i < n; i++) {
5556 elt = gst_value_list_get_value (value1, i);
5557 ret = gst_value_compare (elt, value2);
5558 if (ret != GST_VALUE_EQUAL && n == 1)
5560 else if (ret != GST_VALUE_EQUAL)
5561 return GST_VALUE_UNORDERED;
5564 return GST_VALUE_EQUAL;
5565 } else if (value2_is_list && !value1_is_list) {
5568 if (gst_value_list_equals_range (value2, value1)) {
5569 return GST_VALUE_EQUAL;
5572 n = gst_value_list_get_size (value2);
5574 return GST_VALUE_UNORDERED;
5576 for (i = 0; i < n; i++) {
5579 elt = gst_value_list_get_value (value2, i);
5580 ret = gst_value_compare (elt, value1);
5581 if (ret != GST_VALUE_EQUAL && n == 1)
5583 else if (ret != GST_VALUE_EQUAL)
5584 return GST_VALUE_UNORDERED;
5587 return GST_VALUE_EQUAL;
5590 /* And now handle the generic case */
5591 return _gst_value_compare_nolist (value1, value2);
5595 * gst_value_compare_with_func:
5596 * @value1: a value to compare
5597 * @value2: another value to compare
5598 * @compare: compare function
5600 * Compares @value1 and @value2 using the @compare function. Works like
5601 * gst_value_compare() but allows to save time determining the compare function
5604 * Returns: comparison result
5607 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
5608 GstValueCompareFunc compare)
5612 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5613 return GST_VALUE_UNORDERED;
5615 return compare (value1, value2);
5621 * gst_value_can_union:
5622 * @value1: a value to union
5623 * @value2: another value to union
5625 * Determines if @value1 and @value2 can be non-trivially unioned.
5626 * Any two values can be trivially unioned by adding both of them
5627 * to a GstValueList. However, certain types have the possibility
5628 * to be unioned in a simpler way. For example, an integer range
5629 * and an integer can be unioned if the integer is a subset of the
5630 * integer range. If there is the possibility that two values can
5631 * be unioned, this function returns %TRUE.
5633 * Returns: %TRUE if there is a function allowing the two values to
5637 gst_value_can_union (const GValue * value1, const GValue * value2)
5639 GstValueUnionInfo *union_info;
5642 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5643 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5645 len = gst_value_union_funcs->len;
5647 for (i = 0; i < len; i++) {
5648 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5649 if (union_info->type1 == G_VALUE_TYPE (value1) &&
5650 union_info->type2 == G_VALUE_TYPE (value2))
5652 if (union_info->type1 == G_VALUE_TYPE (value2) &&
5653 union_info->type2 == G_VALUE_TYPE (value1))
5662 * @dest: (out caller-allocates): the destination value
5663 * @value1: a value to union
5664 * @value2: another value to union
5666 * Creates a GValue corresponding to the union of @value1 and @value2.
5668 * Returns: %TRUE if the union succeeded.
5671 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
5673 const GstValueUnionInfo *union_info;
5677 g_return_val_if_fail (dest != NULL, FALSE);
5678 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5679 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5680 g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2),
5683 len = gst_value_union_funcs->len;
5684 type1 = G_VALUE_TYPE (value1);
5685 type2 = G_VALUE_TYPE (value2);
5687 for (i = 0; i < len; i++) {
5688 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5689 if (union_info->type1 == type1 && union_info->type2 == type2) {
5690 return union_info->func (dest, value1, value2);
5692 if (union_info->type1 == type2 && union_info->type2 == type1) {
5693 return union_info->func (dest, value2, value1);
5697 gst_value_list_concat (dest, value1, value2);
5701 /* gst_value_register_union_func: (skip)
5702 * @type1: a type to union
5703 * @type2: another type to union
5704 * @func: a function that implements creating a union between the two types
5706 * Registers a union function that can create a union between #GValue items
5707 * of the type @type1 and @type2.
5709 * Union functions should be registered at startup before any pipelines are
5710 * started, as gst_value_register_union_func() is not thread-safe and cannot
5711 * be used at the same time as gst_value_union() or gst_value_can_union().
5714 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
5716 GstValueUnionInfo union_info;
5718 union_info.type1 = type1;
5719 union_info.type2 = type2;
5720 union_info.func = func;
5722 g_array_append_val (gst_value_union_funcs, union_info);
5728 * gst_value_can_intersect:
5729 * @value1: a value to intersect
5730 * @value2: another value to intersect
5732 * Determines if intersecting two values will produce a valid result.
5733 * Two values will produce a valid intersection if they have the same
5736 * Returns: %TRUE if the values can intersect
5739 gst_value_can_intersect (const GValue * value1, const GValue * value2)
5741 GstValueIntersectInfo *intersect_info;
5745 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5746 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5748 type1 = G_VALUE_TYPE (value1);
5749 type2 = G_VALUE_TYPE (value2);
5751 /* practically all GstValue types have a compare function (_can_compare=TRUE)
5752 * GstStructure and GstCaps have not, but are intersectable */
5757 if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST)
5760 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5761 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5762 GType type1, type2, flagset_type;
5764 type1 = G_VALUE_TYPE (value1);
5765 type2 = G_VALUE_TYPE (value2);
5766 flagset_type = GST_TYPE_FLAG_SET;
5768 /* Allow intersection with the generic FlagSet type, on one
5769 * side, but not 2 different subtypes - that makes no sense */
5770 if (type1 == type2 || type1 == flagset_type || type2 == flagset_type)
5774 /* check registered intersect functions */
5775 len = gst_value_intersect_funcs->len;
5776 for (i = 0; i < len; i++) {
5777 intersect_info = &g_array_index (gst_value_intersect_funcs,
5778 GstValueIntersectInfo, i);
5779 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
5780 (intersect_info->type1 == type2 && intersect_info->type2 == type1))
5784 return gst_value_can_compare_unchecked (value1, value2);
5788 * gst_value_intersect:
5789 * @dest: (out caller-allocates) (transfer full) (allow-none):
5790 * a uninitialized #GValue that will hold the calculated
5791 * intersection value. May be %NULL if the resulting set if not
5793 * @value1: a value to intersect
5794 * @value2: another value to intersect
5796 * Calculates the intersection of two values. If the values have
5797 * a non-empty intersection, the value representing the intersection
5798 * is placed in @dest, unless %NULL. If the intersection is non-empty,
5799 * @dest is not modified.
5801 * Returns: %TRUE if the intersection is non-empty
5804 gst_value_intersect (GValue * dest, const GValue * value1,
5805 const GValue * value2)
5807 GstValueIntersectInfo *intersect_info;
5811 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5812 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5814 type1 = G_VALUE_TYPE (value1);
5815 type2 = G_VALUE_TYPE (value2);
5817 /* special cases first */
5818 if (type1 == GST_TYPE_LIST)
5819 return gst_value_intersect_list (dest, value1, value2);
5820 if (type2 == GST_TYPE_LIST)
5821 return gst_value_intersect_list (dest, value2, value1);
5823 if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) {
5825 gst_value_init_and_copy (dest, value1);
5829 len = gst_value_intersect_funcs->len;
5830 for (i = 0; i < len; i++) {
5831 intersect_info = &g_array_index (gst_value_intersect_funcs,
5832 GstValueIntersectInfo, i);
5833 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
5834 return intersect_info->func (dest, value1, value2);
5836 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
5837 return intersect_info->func (dest, value2, value1);
5841 /* Failed to find a direct intersection, check if these are
5842 * GstFlagSet sub-types. */
5843 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5844 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5845 return gst_value_intersect_flagset_flagset (dest, value1, value2);
5853 /* gst_value_register_intersect_func: (skip)
5854 * @type1: the first type to intersect
5855 * @type2: the second type to intersect
5856 * @func: the intersection function
5858 * Registers a function that is called to calculate the intersection
5859 * of the values having the types @type1 and @type2.
5861 * Intersect functions should be registered at startup before any pipelines are
5862 * started, as gst_value_register_intersect_func() is not thread-safe and
5863 * cannot be used at the same time as gst_value_intersect() or
5864 * gst_value_can_intersect().
5867 gst_value_register_intersect_func (GType type1, GType type2,
5868 GstValueIntersectFunc func)
5870 GstValueIntersectInfo intersect_info;
5872 intersect_info.type1 = type1;
5873 intersect_info.type2 = type2;
5874 intersect_info.func = func;
5876 g_array_append_val (gst_value_intersect_funcs, intersect_info);
5883 * gst_value_subtract:
5884 * @dest: (out caller-allocates) (allow-none): the destination value
5885 * for the result if the subtraction is not empty. May be %NULL,
5886 * in which case the resulting set will not be computed, which can
5887 * give a fair speedup.
5888 * @minuend: the value to subtract from
5889 * @subtrahend: the value to subtract
5891 * Subtracts @subtrahend from @minuend and stores the result in @dest.
5892 * Note that this means subtraction as in sets, not as in mathematics.
5894 * Returns: %TRUE if the subtraction is not empty
5897 gst_value_subtract (GValue * dest, const GValue * minuend,
5898 const GValue * subtrahend)
5900 GstValueSubtractInfo *info;
5904 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5905 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5907 mtype = G_VALUE_TYPE (minuend);
5908 stype = G_VALUE_TYPE (subtrahend);
5910 /* special cases first */
5911 if (mtype == GST_TYPE_LIST)
5912 return gst_value_subtract_from_list (dest, minuend, subtrahend);
5913 if (stype == GST_TYPE_LIST)
5914 return gst_value_subtract_list (dest, minuend, subtrahend);
5916 len = gst_value_subtract_funcs->len;
5917 for (i = 0; i < len; i++) {
5918 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5919 if (info->minuend == mtype && info->subtrahend == stype) {
5920 return info->func (dest, minuend, subtrahend);
5924 if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) {
5926 gst_value_init_and_copy (dest, minuend);
5935 gst_value_subtract (GValue * dest, const GValue * minuend,
5936 const GValue * subtrahend)
5938 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
5940 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
5941 gst_value_serialize (subtrahend),
5942 ret ? gst_value_serialize (dest) : "---");
5948 * gst_value_can_subtract:
5949 * @minuend: the value to subtract from
5950 * @subtrahend: the value to subtract
5952 * Checks if it's possible to subtract @subtrahend from @minuend.
5954 * Returns: %TRUE if a subtraction is possible
5957 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
5959 GstValueSubtractInfo *info;
5963 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5964 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5966 mtype = G_VALUE_TYPE (minuend);
5967 stype = G_VALUE_TYPE (subtrahend);
5970 if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST)
5972 if (mtype == GST_TYPE_STRUCTURE || stype == GST_TYPE_STRUCTURE)
5975 len = gst_value_subtract_funcs->len;
5976 for (i = 0; i < len; i++) {
5977 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5978 if (info->minuend == mtype && info->subtrahend == stype)
5982 return gst_value_can_compare_unchecked (minuend, subtrahend);
5985 /* gst_value_register_subtract_func: (skip)
5986 * @minuend_type: type of the minuend
5987 * @subtrahend_type: type of the subtrahend
5988 * @func: function to use
5990 * Registers @func as a function capable of subtracting the values of
5991 * @subtrahend_type from values of @minuend_type.
5993 * Subtract functions should be registered at startup before any pipelines are
5994 * started, as gst_value_register_subtract_func() is not thread-safe and
5995 * cannot be used at the same time as gst_value_subtract().
5998 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
5999 GstValueSubtractFunc func)
6001 GstValueSubtractInfo info;
6003 g_return_if_fail (!gst_type_is_fixed (minuend_type)
6004 || !gst_type_is_fixed (subtrahend_type));
6006 info.minuend = minuend_type;
6007 info.subtrahend = subtrahend_type;
6010 g_array_append_val (gst_value_subtract_funcs, info);
6014 * gst_value_register:
6015 * @table: structure containing functions to register
6017 * Registers functions to perform calculations on #GValue items of a given
6018 * type. Each type can only be added once.
6021 gst_value_register (const GstValueTable * table)
6023 GstValueTable *found;
6025 g_return_if_fail (table != NULL);
6027 g_array_append_val (gst_value_table, *table);
6029 found = gst_value_hash_lookup_type (table->type);
6031 g_warning ("adding type %s multiple times", g_type_name (table->type));
6033 /* FIXME: we're not really doing the const justice, we assume the table is
6035 gst_value_hash_add_type (table->type, table);
6039 * gst_value_init_and_copy:
6040 * @dest: (out caller-allocates): the target value
6041 * @src: the source value
6043 * Initialises the target value to be of the same type as source and then copies
6044 * the contents from source to target.
6047 gst_value_init_and_copy (GValue * dest, const GValue * src)
6049 g_return_if_fail (G_IS_VALUE (src));
6050 g_return_if_fail (dest != NULL);
6052 g_value_init (dest, G_VALUE_TYPE (src));
6053 g_value_copy (src, dest);
6056 /* move src into dest and clear src */
6058 gst_value_move (GValue * dest, GValue * src)
6060 g_assert (G_IS_VALUE (src));
6061 g_assert (dest != NULL);
6064 memset (src, 0, sizeof (GValue));
6068 * gst_value_serialize:
6069 * @value: a #GValue to serialize
6071 * tries to transform the given @value into a string representation that allows
6072 * getting back this string later on using gst_value_deserialize().
6074 * Free-function: g_free
6076 * Returns: (transfer full) (nullable): the serialization for @value
6077 * or %NULL if none exists
6080 gst_value_serialize (const GValue * value)
6083 GValue s_val = { 0 };
6084 GstValueTable *table, *best;
6088 g_return_val_if_fail (G_IS_VALUE (value), NULL);
6090 type = G_VALUE_TYPE (value);
6092 best = gst_value_hash_lookup_type (type);
6094 if (G_UNLIKELY (!best || !best->serialize)) {
6095 len = gst_value_table->len;
6097 for (i = 0; i < len; i++) {
6098 table = &g_array_index (gst_value_table, GstValueTable, i);
6099 if (table->serialize && g_type_is_a (type, table->type)) {
6100 if (!best || g_type_is_a (table->type, best->type))
6105 if (G_LIKELY (best))
6106 return best->serialize (value);
6108 g_value_init (&s_val, G_TYPE_STRING);
6109 if (g_value_transform (value, &s_val)) {
6110 s = gst_string_wrap (g_value_get_string (&s_val));
6114 g_value_unset (&s_val);
6120 * gst_value_deserialize:
6121 * @dest: (out caller-allocates): #GValue to fill with contents of
6123 * @src: string to deserialize
6125 * Tries to deserialize a string into the type specified by the given GValue.
6126 * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
6128 * Returns: %TRUE on success
6131 gst_value_deserialize (GValue * dest, const gchar * src)
6133 GstValueTable *table, *best;
6137 g_return_val_if_fail (src != NULL, FALSE);
6138 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
6140 type = G_VALUE_TYPE (dest);
6142 best = gst_value_hash_lookup_type (type);
6143 if (G_UNLIKELY (!best || !best->deserialize)) {
6144 len = gst_value_table->len;
6146 for (i = 0; i < len; i++) {
6147 table = &g_array_index (gst_value_table, GstValueTable, i);
6148 if (table->deserialize && g_type_is_a (type, table->type)) {
6149 if (!best || g_type_is_a (table->type, best->type))
6154 if (G_LIKELY (best))
6155 return best->deserialize (dest, src);
6161 structure_field_is_fixed (GQuark field_id, const GValue * val,
6164 return gst_value_is_fixed (val);
6168 * gst_value_is_fixed:
6169 * @value: the #GValue to check
6171 * Tests if the given GValue, if available in a GstStructure (or any other
6172 * container) contains a "fixed" (which means: one value) or an "unfixed"
6173 * (which means: multiple possible values, such as data lists or data
6176 * Returns: true if the value is "fixed".
6180 gst_value_is_fixed (const GValue * value)
6184 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
6186 type = G_VALUE_TYPE (value);
6188 /* the most common types are just basic plain glib types */
6189 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
6193 if (type == GST_TYPE_ARRAY) {
6197 /* check recursively */
6198 size = gst_value_array_get_size (value);
6199 for (n = 0; n < size; n++) {
6200 kid = gst_value_array_get_value (value, n);
6201 if (!gst_value_is_fixed (kid))
6205 } else if (GST_VALUE_HOLDS_FLAG_SET (value)) {
6206 /* Flagsets are only fixed if there are no 'don't care' bits */
6207 return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT);
6208 } else if (GST_VALUE_HOLDS_STRUCTURE (value)) {
6209 return gst_structure_foreach (gst_value_get_structure (value),
6210 structure_field_is_fixed, NULL);
6212 return gst_type_is_fixed (type);
6217 * @dest: the #GValue destination
6218 * @src: the #GValue to fixate
6220 * Fixate @src into a new value @dest.
6221 * For ranges, the first element is taken. For lists and arrays, the
6222 * first item is fixated and returned.
6223 * If @src is already fixed, this function returns %FALSE.
6225 * Returns: %TRUE if @dest contains a fixated version of @src.
6228 gst_value_fixate (GValue * dest, const GValue * src)
6230 g_return_val_if_fail (G_IS_VALUE (src), FALSE);
6231 g_return_val_if_fail (dest != NULL, FALSE);
6233 if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
6234 g_value_init (dest, G_TYPE_INT);
6235 g_value_set_int (dest, gst_value_get_int_range_min (src));
6236 } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
6237 g_value_init (dest, G_TYPE_DOUBLE);
6238 g_value_set_double (dest, gst_value_get_double_range_min (src));
6239 } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
6240 gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
6241 } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
6242 GValue temp = { 0 };
6244 /* list could be empty */
6245 if (gst_value_list_get_size (src) <= 0)
6248 gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
6250 if (!gst_value_fixate (dest, &temp)) {
6251 gst_value_move (dest, &temp);
6253 g_value_unset (&temp);
6255 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
6256 gboolean res = FALSE;
6259 len = gst_value_array_get_size (src);
6260 g_value_init (dest, GST_TYPE_ARRAY);
6261 for (n = 0; n < len; n++) {
6263 const GValue *orig_kid = gst_value_array_get_value (src, n);
6265 if (!gst_value_fixate (&kid, orig_kid))
6266 gst_value_init_and_copy (&kid, orig_kid);
6269 _gst_value_array_append_and_take_value (dest, &kid);
6273 g_value_unset (dest);
6276 } else if (GST_VALUE_HOLDS_FLAG_SET (src)) {
6279 if (gst_value_get_flagset_mask (src) == GST_FLAG_SET_MASK_EXACT)
6280 return FALSE; /* Already fixed */
6282 flags = gst_value_get_flagset_flags (src);
6283 g_value_init (dest, G_VALUE_TYPE (src));
6284 gst_value_set_flagset (dest, flags, GST_FLAG_SET_MASK_EXACT);
6286 } else if (GST_VALUE_HOLDS_STRUCTURE (src)) {
6287 const GstStructure *str = (GstStructure *) gst_value_get_structure (src);
6293 kid = gst_structure_copy (str);
6294 gst_structure_fixate (kid);
6295 g_value_init (dest, GST_TYPE_STRUCTURE);
6296 gst_value_set_structure (dest, kid);
6297 gst_structure_free (kid);
6310 /* helper functions */
6312 gst_value_init_fraction (GValue * value)
6314 value->data[0].v_int = 0;
6315 value->data[1].v_int = 1;
6319 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
6321 dest_value->data[0].v_int = src_value->data[0].v_int;
6322 dest_value->data[1].v_int = src_value->data[1].v_int;
6326 gst_value_collect_fraction (GValue * value, guint n_collect_values,
6327 GTypeCValue * collect_values, guint collect_flags)
6329 if (n_collect_values != 2)
6330 return g_strdup_printf ("not enough value locations for `%s' passed",
6331 G_VALUE_TYPE_NAME (value));
6332 if (collect_values[1].v_int == 0)
6333 return g_strdup_printf ("passed '0' as denominator for `%s'",
6334 G_VALUE_TYPE_NAME (value));
6335 if (collect_values[0].v_int < -G_MAXINT)
6338 ("passed value smaller than -G_MAXINT as numerator for `%s'",
6339 G_VALUE_TYPE_NAME (value));
6340 if (collect_values[1].v_int < -G_MAXINT)
6343 ("passed value smaller than -G_MAXINT as denominator for `%s'",
6344 G_VALUE_TYPE_NAME (value));
6346 gst_value_set_fraction (value,
6347 collect_values[0].v_int, collect_values[1].v_int);
6353 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
6354 GTypeCValue * collect_values, guint collect_flags)
6356 gint *numerator = collect_values[0].v_pointer;
6357 gint *denominator = collect_values[1].v_pointer;
6360 return g_strdup_printf ("numerator for `%s' passed as NULL",
6361 G_VALUE_TYPE_NAME (value));
6363 return g_strdup_printf ("denominator for `%s' passed as NULL",
6364 G_VALUE_TYPE_NAME (value));
6366 *numerator = value->data[0].v_int;
6367 *denominator = value->data[1].v_int;
6373 * gst_value_set_fraction:
6374 * @value: a GValue initialized to #GST_TYPE_FRACTION
6375 * @numerator: the numerator of the fraction
6376 * @denominator: the denominator of the fraction
6378 * Sets @value to the fraction specified by @numerator over @denominator.
6379 * The fraction gets reduced to the smallest numerator and denominator,
6380 * and if necessary the sign is moved to the numerator.
6383 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
6387 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
6388 g_return_if_fail (denominator != 0);
6389 g_return_if_fail (denominator >= -G_MAXINT);
6390 g_return_if_fail (numerator >= -G_MAXINT);
6392 /* normalize sign */
6393 if (denominator < 0) {
6394 numerator = -numerator;
6395 denominator = -denominator;
6398 /* check for reduction */
6399 gcd = gst_util_greatest_common_divisor (numerator, denominator);
6405 g_assert (denominator > 0);
6407 value->data[0].v_int = numerator;
6408 value->data[1].v_int = denominator;
6412 * gst_value_get_fraction_numerator:
6413 * @value: a GValue initialized to #GST_TYPE_FRACTION
6415 * Gets the numerator of the fraction specified by @value.
6417 * Returns: the numerator of the fraction.
6420 gst_value_get_fraction_numerator (const GValue * value)
6422 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
6424 return value->data[0].v_int;
6428 * gst_value_get_fraction_denominator:
6429 * @value: a GValue initialized to #GST_TYPE_FRACTION
6431 * Gets the denominator of the fraction specified by @value.
6433 * Returns: the denominator of the fraction.
6436 gst_value_get_fraction_denominator (const GValue * value)
6438 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
6440 return value->data[1].v_int;
6444 * gst_value_fraction_multiply:
6445 * @product: a GValue initialized to #GST_TYPE_FRACTION
6446 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
6447 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
6449 * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets
6450 * @product to the product of the two fractions.
6452 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6455 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
6456 const GValue * factor2)
6458 gint n1, n2, d1, d2;
6461 g_return_val_if_fail (product != NULL, FALSE);
6462 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
6463 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
6465 n1 = factor1->data[0].v_int;
6466 n2 = factor2->data[0].v_int;
6467 d1 = factor1->data[1].v_int;
6468 d2 = factor2->data[1].v_int;
6470 if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
6473 gst_value_set_fraction (product, res_n, res_d);
6479 * gst_value_fraction_subtract:
6480 * @dest: a GValue initialized to #GST_TYPE_FRACTION
6481 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
6482 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
6484 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
6486 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6489 gst_value_fraction_subtract (GValue * dest,
6490 const GValue * minuend, const GValue * subtrahend)
6492 gint n1, n2, d1, d2;
6495 g_return_val_if_fail (dest != NULL, FALSE);
6496 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
6497 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
6499 n1 = minuend->data[0].v_int;
6500 n2 = subtrahend->data[0].v_int;
6501 d1 = minuend->data[1].v_int;
6502 d2 = subtrahend->data[1].v_int;
6504 if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d))
6506 gst_value_set_fraction (dest, res_n, res_d);
6512 gst_value_serialize_fraction (const GValue * value)
6514 gint32 numerator = value->data[0].v_int;
6515 gint32 denominator = value->data[1].v_int;
6516 gboolean positive = TRUE;
6518 /* get the sign and make components absolute */
6519 if (numerator < 0) {
6520 numerator = -numerator;
6521 positive = !positive;
6523 if (denominator < 0) {
6524 denominator = -denominator;
6525 positive = !positive;
6528 return g_strdup_printf ("%s%d/%d",
6529 positive ? "" : "-", numerator, denominator);
6533 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
6538 if (G_UNLIKELY (s == NULL))
6541 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
6544 if (sscanf (s, "%d/%d%n", &num, &den, &num_chars) >= 2) {
6545 if (s[num_chars] != 0)
6550 gst_value_set_fraction (dest, num, den);
6552 } else if (g_ascii_strcasecmp (s, "1/max") == 0) {
6553 gst_value_set_fraction (dest, 1, G_MAXINT);
6555 } else if (sscanf (s, "%d%n", &num, &num_chars) >= 1) {
6556 if (s[num_chars] != 0)
6558 gst_value_set_fraction (dest, num, 1);
6560 } else if (g_ascii_strcasecmp (s, "min") == 0) {
6561 gst_value_set_fraction (dest, -G_MAXINT, 1);
6563 } else if (g_ascii_strcasecmp (s, "max") == 0) {
6564 gst_value_set_fraction (dest, G_MAXINT, 1);
6572 gst_value_transform_fraction_string (const GValue * src_value,
6573 GValue * dest_value)
6575 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
6579 gst_value_transform_string_fraction (const GValue * src_value,
6580 GValue * dest_value)
6582 if (!gst_value_deserialize_fraction (dest_value,
6583 src_value->data[0].v_pointer))
6584 /* If the deserialize fails, ensure we leave the fraction in a
6585 * valid, if incorrect, state */
6586 gst_value_set_fraction (dest_value, 0, 1);
6590 gst_value_transform_double_fraction (const GValue * src_value,
6591 GValue * dest_value)
6593 gdouble src = g_value_get_double (src_value);
6596 gst_util_double_to_fraction (src, &n, &d);
6597 gst_value_set_fraction (dest_value, n, d);
6601 gst_value_transform_float_fraction (const GValue * src_value,
6602 GValue * dest_value)
6604 gfloat src = g_value_get_float (src_value);
6607 gst_util_double_to_fraction (src, &n, &d);
6608 gst_value_set_fraction (dest_value, n, d);
6612 gst_value_transform_fraction_double (const GValue * src_value,
6613 GValue * dest_value)
6615 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
6616 ((double) src_value->data[1].v_int);
6620 gst_value_transform_fraction_float (const GValue * src_value,
6621 GValue * dest_value)
6623 dest_value->data[0].v_float = ((float) src_value->data[0].v_int) /
6624 ((float) src_value->data[1].v_int);
6628 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
6634 n1 = value1->data[0].v_int;
6635 n2 = value2->data[0].v_int;
6636 d1 = value1->data[1].v_int;
6637 d2 = value2->data[1].v_int;
6639 /* fractions are reduced when set, so we can quickly see if they're equal */
6640 if (n1 == n2 && d1 == d2)
6641 return GST_VALUE_EQUAL;
6643 if (d1 == 0 && d2 == 0)
6644 return GST_VALUE_UNORDERED;
6646 return GST_VALUE_GREATER_THAN;
6648 return GST_VALUE_LESS_THAN;
6650 ret = gst_util_fraction_compare (n1, d1, n2, d2);
6652 return GST_VALUE_LESS_THAN;
6654 return GST_VALUE_GREATER_THAN;
6656 /* Equality can't happen here because we check for that
6658 g_return_val_if_reached (GST_VALUE_UNORDERED);
6666 gst_value_compare_date (const GValue * value1, const GValue * value2)
6668 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
6669 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
6673 return GST_VALUE_EQUAL;
6675 if ((date1 == NULL || !g_date_valid (date1))
6676 && (date2 != NULL && g_date_valid (date2))) {
6677 return GST_VALUE_LESS_THAN;
6680 if ((date2 == NULL || !g_date_valid (date2))
6681 && (date1 != NULL && g_date_valid (date1))) {
6682 return GST_VALUE_GREATER_THAN;
6685 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
6686 || !g_date_valid (date2)) {
6687 return GST_VALUE_UNORDERED;
6690 j1 = g_date_get_julian (date1);
6691 j2 = g_date_get_julian (date2);
6694 return GST_VALUE_EQUAL;
6696 return GST_VALUE_LESS_THAN;
6698 return GST_VALUE_GREATER_THAN;
6702 gst_value_serialize_date (const GValue * val)
6704 const GDate *date = (const GDate *) g_value_get_boxed (val);
6706 if (date == NULL || !g_date_valid (date))
6707 return g_strdup ("9999-99-99");
6709 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
6710 g_date_get_month (date), g_date_get_day (date));
6714 gst_value_deserialize_date (GValue * dest, const gchar * s)
6716 guint year, month, day;
6718 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
6721 if (!g_date_valid_dmy (day, month, year))
6724 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
6733 gst_value_compare_date_time (const GValue * value1, const GValue * value2)
6735 const GstDateTime *date1 = (const GstDateTime *) g_value_get_boxed (value1);
6736 const GstDateTime *date2 = (const GstDateTime *) g_value_get_boxed (value2);
6739 return GST_VALUE_EQUAL;
6741 if ((date1 == NULL) && (date2 != NULL)) {
6742 return GST_VALUE_LESS_THAN;
6744 if ((date2 == NULL) && (date1 != NULL)) {
6745 return GST_VALUE_LESS_THAN;
6748 /* returns GST_VALUE_* */
6749 return __gst_date_time_compare (date1, date2);
6753 gst_value_serialize_date_time (const GValue * val)
6755 GstDateTime *date = (GstDateTime *) g_value_get_boxed (val);
6758 return g_strdup ("null");
6760 return __gst_date_time_serialize (date, TRUE);
6764 gst_value_deserialize_date_time (GValue * dest, const gchar * s)
6766 GstDateTime *datetime;
6768 if (!s || strcmp (s, "null") == 0) {
6772 datetime = gst_date_time_new_from_iso8601_string (s);
6773 if (datetime != NULL) {
6774 g_value_take_boxed (dest, datetime);
6777 GST_WARNING ("Failed to deserialize date time string '%s'", s);
6782 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
6784 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
6788 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
6790 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
6798 /* helper functions */
6800 gst_value_init_bitmask (GValue * value)
6802 value->data[0].v_uint64 = 0;
6806 gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
6808 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6812 gst_value_collect_bitmask (GValue * value, guint n_collect_values,
6813 GTypeCValue * collect_values, guint collect_flags)
6815 if (n_collect_values != 1)
6816 return g_strdup_printf ("not enough value locations for `%s' passed",
6817 G_VALUE_TYPE_NAME (value));
6819 gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
6825 gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
6826 GTypeCValue * collect_values, guint collect_flags)
6828 guint64 *bitmask = collect_values[0].v_pointer;
6831 return g_strdup_printf ("value for `%s' passed as NULL",
6832 G_VALUE_TYPE_NAME (value));
6834 *bitmask = value->data[0].v_uint64;
6840 * gst_value_set_bitmask:
6841 * @value: a GValue initialized to #GST_TYPE_BITMASK
6842 * @bitmask: the bitmask
6844 * Sets @value to the bitmask specified by @bitmask.
6847 gst_value_set_bitmask (GValue * value, guint64 bitmask)
6849 g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
6851 value->data[0].v_uint64 = bitmask;
6855 * gst_value_get_bitmask:
6856 * @value: a GValue initialized to #GST_TYPE_BITMASK
6858 * Gets the bitmask specified by @value.
6860 * Returns: the bitmask.
6863 gst_value_get_bitmask (const GValue * value)
6865 g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
6867 return value->data[0].v_uint64;
6871 gst_value_serialize_bitmask (const GValue * value)
6873 guint64 bitmask = value->data[0].v_uint64;
6875 return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
6879 gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
6881 gchar *endptr = NULL;
6884 if (G_UNLIKELY (s == NULL))
6887 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
6891 val = g_ascii_strtoull (s, &endptr, 16);
6892 if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
6894 if (val == 0 && endptr == s)
6897 gst_value_set_bitmask (dest, val);
6903 gst_value_transform_bitmask_string (const GValue * src_value,
6904 GValue * dest_value)
6906 dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
6910 gst_value_transform_string_bitmask (const GValue * src_value,
6911 GValue * dest_value)
6913 if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
6914 gst_value_set_bitmask (dest_value, 0);
6918 gst_value_transform_uint64_bitmask (const GValue * src_value,
6919 GValue * dest_value)
6921 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6925 gst_value_transform_bitmask_uint64 (const GValue * src_value,
6926 GValue * dest_value)
6928 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6932 gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
6936 v1 = value1->data[0].v_uint64;
6937 v2 = value2->data[0].v_uint64;
6940 return GST_VALUE_EQUAL;
6942 return GST_VALUE_UNORDERED;
6949 /* helper functions */
6951 gst_value_init_flagset (GValue * value)
6953 value->data[0].v_uint = 0;
6954 value->data[1].v_uint = 0;
6958 gst_value_copy_flagset (const GValue * src_value, GValue * dest_value)
6960 dest_value->data[0].v_uint = src_value->data[0].v_uint;
6961 dest_value->data[1].v_uint = src_value->data[1].v_uint;
6965 gst_value_collect_flagset (GValue * value, guint n_collect_values,
6966 GTypeCValue * collect_values, guint collect_flags)
6968 if (n_collect_values != 2)
6969 return g_strdup_printf ("not enough value locations for `%s' passed",
6970 G_VALUE_TYPE_NAME (value));
6972 gst_value_set_flagset (value,
6973 (guint) collect_values[0].v_int, (guint) collect_values[1].v_int);
6979 gst_value_lcopy_flagset (const GValue * value, guint n_collect_values,
6980 GTypeCValue * collect_values, guint collect_flags)
6982 guint *flags = collect_values[0].v_pointer;
6983 guint *mask = collect_values[1].v_pointer;
6985 *flags = value->data[0].v_uint;
6986 *mask = value->data[1].v_uint;
6992 * gst_value_set_flagset:
6993 * @value: a GValue initialized to %GST_TYPE_FLAG_SET
6994 * @flags: The value of the flags set or unset
6995 * @mask: The mask indicate which flags bits must match for comparisons
6997 * Sets @value to the flags and mask values provided in @flags and @mask.
6998 * The @flags value indicates the values of flags, the @mask represents
6999 * which bits in the flag value have been set, and which are "don't care"
7004 gst_value_set_flagset (GValue * value, guint flags, guint mask)
7006 g_return_if_fail (GST_VALUE_HOLDS_FLAG_SET (value));
7008 /* Normalise and only keep flags mentioned in the mask */
7009 value->data[0].v_uint = flags & mask;
7010 value->data[1].v_uint = mask;
7014 * gst_value_get_flagset_flags:
7015 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7017 * Retrieve the flags field of a GstFlagSet @value.
7019 * Returns: the flags field of the flagset instance.
7024 gst_value_get_flagset_flags (const GValue * value)
7026 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 0);
7028 return value->data[0].v_uint;
7032 * gst_value_get_flagset_mask:
7033 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7035 * Retrieve the mask field of a GstFlagSet @value.
7037 * Returns: the mask field of the flagset instance.
7042 gst_value_get_flagset_mask (const GValue * value)
7044 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 1);
7046 return value->data[1].v_uint;
7050 gst_value_serialize_flagset (const GValue * value)
7052 guint flags = value->data[0].v_uint;
7053 guint mask = value->data[1].v_uint;
7054 GstFlagSetClass *set_klass =
7055 (GstFlagSetClass *) g_type_class_ref (G_VALUE_TYPE (value));
7058 result = g_strdup_printf ("%x:%x", flags, mask);
7060 /* If this flag set class has an associated GFlags GType, and some
7061 * bits in the mask, serialize the bits in human-readable form to
7063 if (mask && set_klass->flags_type) {
7064 GFlagsClass *flags_klass =
7065 (GFlagsClass *) (g_type_class_ref (set_klass->flags_type));
7068 gboolean first = TRUE;
7070 g_return_val_if_fail (flags_klass, NULL);
7072 /* some bits in the mask are set, so serialize one by one, according
7073 * to whether that bit is set or cleared in the flags value */
7075 fl = g_flags_get_first_value (flags_klass, mask);
7077 /* No more bits match in the flags mask - time to stop */
7082 tmp = g_strconcat (result,
7084 (flags & fl->value) ? "+" : "/", fl->value_nick, NULL);
7092 g_type_class_unref (flags_klass);
7095 g_type_class_unref (set_klass);
7101 is_valid_flags_string (const gchar * s)
7103 /* We're looking to match +this/that+other-thing/not-this-thing type strings */
7104 return g_regex_match_simple ("^([\\+\\/][\\w\\d-]+)+$", s, G_REGEX_CASELESS,
7109 gst_value_deserialize_flagset (GValue * dest, const gchar * s)
7111 gboolean res = FALSE;
7115 if (G_UNLIKELY (s == NULL))
7118 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FLAG_SET (dest)))
7121 /* Flagset strings look like %x:%x - hex flags : hex bitmask,
7122 * 32-bit each, or like a concatenated list of flag nicks,
7123 * with either '+' or '/' in front. The first form
7124 * may optionally be followed by ':' and a set of text flag descriptions
7125 * for easier debugging */
7127 /* Try and interpret as hex form first, as it's the most efficient */
7128 /* Read the flags first */
7129 flags = strtoul (s, &next, 16);
7130 if (G_UNLIKELY ((flags == 0 && errno == EINVAL) || s == next))
7131 goto try_as_flags_string;
7132 /* Next char should be a colon */
7138 mask = strtoul (cur, &next, 16);
7139 if (G_UNLIKELY ((mask == 0 && errno == EINVAL) || cur == next))
7140 goto try_as_flags_string;
7142 /* Next char should be NULL terminator, or a ':'. If ':', we need the flag string after */
7143 if (G_UNLIKELY (next[0] == 0)) {
7153 if (g_str_equal (g_type_name (G_VALUE_TYPE (dest)), "GstFlagSet")) {
7154 /* If we're parsing a generic flag set, that can mean we're guessing
7155 * at the type in deserialising a GstStructure so at least check that
7156 * we have a valid-looking string, so we don't cause deserialisation of
7157 * other types of strings like 00:01:00:00 - https://bugzilla.gnome.org/show_bug.cgi?id=779755 */
7158 if (is_valid_flags_string (s)) {
7165 /* Otherwise, we already got a hex string for a valid non-generic flagset type */
7169 try_as_flags_string:
7172 const gchar *set_class = g_type_name (G_VALUE_TYPE (dest));
7173 GFlagsClass *flags_klass = NULL;
7176 if (g_str_equal (set_class, "GstFlagSet")) {
7177 /* There's no hope to parse the fields of generic flag set if we didn't already
7178 * catch a hex-string above */
7182 /* Flags class is the FlagSet class with 'Set' removed from the end */
7183 end = g_strrstr (set_class, "Set");
7186 gchar *class_name = g_strndup (set_class, end - set_class);
7187 GType flags_type = g_type_from_name (class_name);
7188 if (flags_type == 0) {
7189 GST_TRACE ("Looking for dynamic type %s", class_name);
7190 gst_dynamic_type_factory_load (class_name);
7193 if (flags_type != 0) {
7194 flags_klass = g_type_class_ref (flags_type);
7195 GST_TRACE ("Going to parse %s as %s", s, class_name);
7197 g_free (class_name);
7201 res = gst_value_gflags_str_to_flags (flags_klass, s, &flags, &mask);
7202 g_type_class_unref (flags_klass);
7208 gst_value_set_flagset (dest, flags, mask);
7214 gst_value_transform_flagset_string (const GValue * src_value,
7215 GValue * dest_value)
7217 dest_value->data[0].v_pointer = gst_value_serialize_flagset (src_value);
7221 gst_value_transform_string_flagset (const GValue * src_value,
7222 GValue * dest_value)
7224 if (!gst_value_deserialize_flagset (dest_value, src_value->data[0].v_pointer)) {
7225 /* If the deserialize fails, ensure we leave the flags in a
7226 * valid, if incorrect, state */
7227 gst_value_set_flagset (dest_value, 0, 0);
7232 gst_value_compare_flagset (const GValue * value1, const GValue * value2)
7237 v1 = value1->data[0].v_uint;
7238 v2 = value2->data[0].v_uint;
7240 m1 = value1->data[1].v_uint;
7241 m2 = value2->data[1].v_uint;
7243 if (v1 == v2 && m1 == m2)
7244 return GST_VALUE_EQUAL;
7246 return GST_VALUE_UNORDERED;
7249 /***********************
7250 * GstAllocationParams *
7251 ***********************/
7253 gst_value_compare_allocation_params (const GValue * value1,
7254 const GValue * value2)
7256 GstAllocationParams *v1, *v2;
7258 v1 = value1->data[0].v_pointer;
7259 v2 = value2->data[0].v_pointer;
7261 if (v1 == NULL && v1 == v2)
7262 return GST_VALUE_EQUAL;
7264 if (v1 == NULL || v2 == NULL)
7265 return GST_VALUE_UNORDERED;
7267 if (v1->flags == v2->flags && v1->align == v2->align &&
7268 v1->prefix == v2->prefix && v1->padding == v2->padding)
7269 return GST_VALUE_EQUAL;
7271 return GST_VALUE_UNORDERED;
7280 gst_value_compare_object (const GValue * value1, const GValue * value2)
7284 v1 = value1->data[0].v_pointer;
7285 v2 = value2->data[0].v_pointer;
7288 return GST_VALUE_EQUAL;
7290 return GST_VALUE_UNORDERED;
7294 gst_value_transform_object_string (const GValue * src_value,
7295 GValue * dest_value)
7300 obj = g_value_get_object (src_value);
7303 g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
7304 GST_OBJECT_NAME (obj));
7306 str = g_strdup ("NULL");
7309 dest_value->data[0].v_pointer = str;
7312 static GTypeInfo _info = {
7313 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL,
7316 static GTypeFundamentalInfo _finfo = {
7320 #define FUNC_VALUE_GET_TYPE_CLASSED(type, name, csize, flags) \
7321 GType _gst_ ## type ## _type = 0; \
7323 GType gst_ ## type ## _get_type (void) \
7325 static volatile GType gst_ ## type ## _type = 0; \
7327 if (g_once_init_enter (&gst_ ## type ## _type)) { \
7329 _info.class_size = csize; \
7330 _finfo.type_flags = flags; \
7331 _info.value_table = & _gst_ ## type ## _value_table; \
7332 _type = g_type_register_fundamental ( \
7333 g_type_fundamental_next (), \
7334 name, &_info, &_finfo, 0); \
7335 _gst_ ## type ## _type = _type; \
7336 g_once_init_leave(&gst_ ## type ## _type, _type); \
7339 return gst_ ## type ## _type; \
7342 #define FUNC_VALUE_GET_TYPE(type, name) \
7343 FUNC_VALUE_GET_TYPE_CLASSED(type, name, 0, 0)
7345 static const GTypeValueTable _gst_int_range_value_table = {
7346 gst_value_init_int_range,
7348 gst_value_copy_int_range,
7351 gst_value_collect_int_range, (char *) "pp", gst_value_lcopy_int_range
7354 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
7356 static const GTypeValueTable _gst_int64_range_value_table = {
7357 gst_value_init_int64_range,
7358 gst_value_free_int64_range,
7359 gst_value_copy_int64_range,
7362 gst_value_collect_int64_range,
7363 (char *) "pp", gst_value_lcopy_int64_range
7366 FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range");
7368 static const GTypeValueTable _gst_double_range_value_table = {
7369 gst_value_init_double_range,
7371 gst_value_copy_double_range,
7374 gst_value_collect_double_range,
7375 (char *) "pp", gst_value_lcopy_double_range
7378 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
7380 static const GTypeValueTable _gst_fraction_range_value_table = {
7381 gst_value_init_fraction_range,
7382 gst_value_free_fraction_range,
7383 gst_value_copy_fraction_range,
7386 gst_value_collect_fraction_range,
7387 (char *) "pppp", gst_value_lcopy_fraction_range
7390 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
7392 static const GTypeValueTable _gst_value_list_value_table = {
7393 gst_value_init_list_or_array,
7394 gst_value_free_list_or_array,
7395 gst_value_copy_list_or_array,
7396 gst_value_list_or_array_peek_pointer,
7398 gst_value_collect_list_or_array,
7399 (char *) "p", gst_value_lcopy_list_or_array
7402 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
7404 static const GTypeValueTable _gst_value_array_value_table = {
7405 gst_value_init_list_or_array,
7406 gst_value_free_list_or_array,
7407 gst_value_copy_list_or_array,
7408 gst_value_list_or_array_peek_pointer,
7410 gst_value_collect_list_or_array,
7411 (char *) "p", gst_value_lcopy_list_or_array
7414 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
7416 static const GTypeValueTable _gst_fraction_value_table = {
7417 gst_value_init_fraction,
7419 gst_value_copy_fraction,
7422 gst_value_collect_fraction, (char *) "pp", gst_value_lcopy_fraction
7425 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
7427 static const GTypeValueTable _gst_bitmask_value_table = {
7428 gst_value_init_bitmask,
7430 gst_value_copy_bitmask,
7433 gst_value_collect_bitmask, (char *) "p", gst_value_lcopy_bitmask
7436 FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
7438 static const GTypeValueTable _gst_flagset_value_table = {
7439 gst_value_init_flagset,
7441 gst_value_copy_flagset,
7444 gst_value_collect_flagset, (char *) "pp", gst_value_lcopy_flagset
7447 FUNC_VALUE_GET_TYPE_CLASSED (flagset, "GstFlagSet",
7448 sizeof (GstFlagSetClass), G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE);
7451 gst_g_thread_get_type (void)
7453 return G_TYPE_THREAD;
7456 #define SERIAL_VTABLE(t,c,s,d) { t, c, s, d }
7458 #define REGISTER_SERIALIZATION_CONST(_gtype, _type) \
7460 static const GstValueTable gst_value = \
7461 SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \
7462 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7463 gst_value_register (&gst_value); \
7466 #define REGISTER_SERIALIZATION(_gtype, _type) \
7468 static GstValueTable gst_value = \
7469 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7470 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7471 gst_value.type = _gtype; \
7472 gst_value_register (&gst_value); \
7475 #define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type) \
7477 static GstValueTable gst_value = \
7478 SERIAL_VTABLE (0, NULL, \
7479 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7480 gst_value.type = _gtype; \
7481 gst_value_register (&gst_value); \
7484 #define REGISTER_SERIALIZATION_COMPARE_ONLY(_gtype, _type) \
7486 static GstValueTable gst_value = \
7487 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7489 gst_value.type = _gtype; \
7490 gst_value_register (&gst_value); \
7493 /* These initial sizes are used for the tables
7494 * below, and save a couple of reallocs at startup */
7496 static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 35;
7497 static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 4;
7498 static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 11;
7499 static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 12;
7502 _priv_gst_value_initialize (void)
7505 g_array_sized_new (FALSE, FALSE, sizeof (GstValueTable),
7506 GST_VALUE_TABLE_DEFAULT_SIZE);
7507 gst_value_hash = g_hash_table_new (NULL, NULL);
7508 gst_value_union_funcs = g_array_sized_new (FALSE, FALSE,
7509 sizeof (GstValueUnionInfo), GST_VALUE_UNION_TABLE_DEFAULT_SIZE);
7510 gst_value_intersect_funcs = g_array_sized_new (FALSE, FALSE,
7511 sizeof (GstValueIntersectInfo), GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE);
7512 gst_value_subtract_funcs = g_array_sized_new (FALSE, FALSE,
7513 sizeof (GstValueSubtractInfo), GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE);
7515 REGISTER_SERIALIZATION (gst_int_range_get_type (), int_range);
7516 REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range);
7517 REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range);
7518 REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range);
7519 REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list);
7520 REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array);
7521 REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array);
7522 REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer);
7523 REGISTER_SERIALIZATION (gst_sample_get_type (), sample);
7524 REGISTER_SERIALIZATION (gst_fraction_get_type (), fraction);
7525 REGISTER_SERIALIZATION (gst_caps_get_type (), caps);
7526 REGISTER_SERIALIZATION (gst_tag_list_get_type (), tag_list);
7527 REGISTER_SERIALIZATION (G_TYPE_DATE, date);
7528 REGISTER_SERIALIZATION (gst_date_time_get_type (), date_time);
7529 REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask);
7530 REGISTER_SERIALIZATION (gst_structure_get_type (), structure);
7531 REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset);
7533 REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment);
7534 REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (),
7537 REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (),
7539 REGISTER_SERIALIZATION_COMPARE_ONLY (G_TYPE_OBJECT, object);
7541 REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double);
7542 REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float);
7544 REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string);
7545 REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean);
7546 REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum);
7548 REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags);
7550 REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int);
7552 REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64);
7553 REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long);
7555 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint);
7556 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64);
7557 REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong);
7559 REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar);
7561 REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
7563 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
7564 gst_value_transform_int_range_string);
7565 g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING,
7566 gst_value_transform_int64_range_string);
7567 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
7568 gst_value_transform_double_range_string);
7569 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
7570 gst_value_transform_fraction_range_string);
7571 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
7572 gst_value_transform_list_string);
7573 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_VALUE_ARRAY,
7574 gst_value_transform_any_list_g_value_array);
7575 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
7576 gst_value_transform_array_string);
7577 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_VALUE_ARRAY,
7578 gst_value_transform_any_list_g_value_array);
7579 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, G_TYPE_STRING,
7580 gst_value_transform_g_value_array_string);
7581 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_ARRAY,
7582 gst_value_transform_g_value_array_any_list);
7583 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_LIST,
7584 gst_value_transform_g_value_array_any_list);
7585 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
7586 gst_value_transform_fraction_string);
7587 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
7588 gst_value_transform_string_fraction);
7589 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
7590 gst_value_transform_fraction_double);
7591 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT,
7592 gst_value_transform_fraction_float);
7593 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
7594 gst_value_transform_double_fraction);
7595 g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
7596 gst_value_transform_float_fraction);
7597 g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING,
7598 gst_value_transform_date_string);
7599 g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE,
7600 gst_value_transform_string_date);
7601 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
7602 gst_value_transform_object_string);
7603 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
7604 gst_value_transform_bitmask_uint64);
7605 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
7606 gst_value_transform_bitmask_string);
7607 g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
7608 gst_value_transform_uint64_bitmask);
7609 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
7610 gst_value_transform_string_bitmask);
7612 g_value_register_transform_func (GST_TYPE_FLAG_SET, G_TYPE_STRING,
7613 gst_value_transform_flagset_string);
7614 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
7615 gst_value_transform_string_flagset);
7617 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7618 gst_value_intersect_int_int_range);
7619 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7620 gst_value_intersect_int_range_int_range);
7621 gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7622 gst_value_intersect_int64_int64_range);
7623 gst_value_register_intersect_func (GST_TYPE_INT64_RANGE,
7624 GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range);
7625 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7626 gst_value_intersect_double_double_range);
7627 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
7628 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
7629 gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY,
7630 gst_value_intersect_array);
7631 gst_value_register_intersect_func (GST_TYPE_FRACTION,
7632 GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range);
7633 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
7634 GST_TYPE_FRACTION_RANGE,
7635 gst_value_intersect_fraction_range_fraction_range);
7636 gst_value_register_intersect_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7637 gst_value_intersect_flagset_flagset);
7638 gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7639 gst_value_intersect_structure_structure);
7641 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7642 gst_value_subtract_int_int_range);
7643 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
7644 gst_value_subtract_int_range_int);
7645 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7646 gst_value_subtract_int_range_int_range);
7647 gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7648 gst_value_subtract_int64_int64_range);
7649 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64,
7650 gst_value_subtract_int64_range_int64);
7651 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE,
7652 GST_TYPE_INT64_RANGE, gst_value_subtract_int64_range_int64_range);
7653 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7654 gst_value_subtract_double_double_range);
7655 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
7656 gst_value_subtract_double_range_double);
7657 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
7658 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
7659 gst_value_register_subtract_func (GST_TYPE_FRACTION,
7660 GST_TYPE_FRACTION_RANGE, gst_value_subtract_fraction_fraction_range);
7661 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7662 GST_TYPE_FRACTION, gst_value_subtract_fraction_range_fraction);
7663 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7664 GST_TYPE_FRACTION_RANGE,
7665 gst_value_subtract_fraction_range_fraction_range);
7667 /* see bug #317246, #64994, #65041 */
7669 volatile GType date_type = G_TYPE_DATE;
7671 g_type_name (date_type);
7674 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7675 gst_value_union_int_int_range);
7676 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7677 gst_value_union_int_range_int_range);
7678 gst_value_register_union_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7679 gst_value_union_flagset_flagset);
7680 gst_value_register_union_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7681 gst_value_union_structure_structure);
7683 #if GST_VERSION_NANO == 1
7684 /* If building from git master, check starting array sizes matched actual size
7685 * so we can keep the defines in sync and save a few reallocs on startup */
7686 if (gst_value_table->len != GST_VALUE_TABLE_DEFAULT_SIZE) {
7687 GST_ERROR ("Wrong initial gst_value_table size. "
7688 "Please set GST_VALUE_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7689 gst_value_table->len);
7691 if (gst_value_union_funcs->len != GST_VALUE_UNION_TABLE_DEFAULT_SIZE) {
7692 GST_ERROR ("Wrong initial gst_value_union_funcs table size. "
7693 "Please set GST_VALUE_UNION_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7694 gst_value_union_funcs->len);
7696 if (gst_value_intersect_funcs->len != GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE) {
7697 GST_ERROR ("Wrong initial gst_value_intersect_funcs table size. "
7698 "Please set GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7699 gst_value_intersect_funcs->len);
7701 if (gst_value_subtract_funcs->len != GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE) {
7702 GST_ERROR ("Wrong initial gst_value_subtract_funcs table size. "
7703 "Please set GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7704 gst_value_subtract_funcs->len);
7709 /* Implement these if needed */
7710 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
7711 gst_value_union_fraction_fraction_range);
7712 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
7713 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);
7718 gst_flagset_class_init (gpointer g_class, gpointer class_data)
7720 GstFlagSetClass *f_class = (GstFlagSetClass *) (g_class);
7721 f_class->flags_type = (GType) GPOINTER_TO_SIZE (class_data);
7725 * gst_flagset_register:
7726 * @flags_type: a #GType of a #G_TYPE_FLAGS type.
7728 * Create a new sub-class of #GST_TYPE_FLAG_SET
7729 * which will pretty-print the human-readable flags
7730 * when serializing, for easier debugging.
7735 gst_flagset_register (GType flags_type)
7738 sizeof (GstFlagSetClass),
7740 (GClassInitFunc) gst_flagset_class_init,
7741 NULL, GSIZE_TO_POINTER (flags_type), 0, 0, NULL, NULL
7746 g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0);
7748 class_name = g_strdup_printf ("%sSet", g_type_name (flags_type));
7750 t = g_type_register_static (GST_TYPE_FLAG_SET,
7751 g_intern_string (class_name), &info, 0);
7752 g_free (class_name);