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 (gst_structure_is_equal (structure1, structure2))
2758 return GST_VALUE_EQUAL;
2760 return GST_VALUE_UNORDERED;
2763 /*******************
2765 *******************/
2768 * gst_value_set_caps_features:
2769 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2770 * @features: the features to set the value to
2772 * Sets the contents of @value to @features.
2775 gst_value_set_caps_features (GValue * value, const GstCapsFeatures * features)
2777 g_return_if_fail (G_IS_VALUE (value));
2778 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES);
2779 g_return_if_fail (features == NULL || GST_IS_CAPS_FEATURES (features));
2781 g_value_set_boxed (value, features);
2785 * gst_value_get_caps_features:
2786 * @value: a GValue initialized to GST_TYPE_CAPS_FEATURES
2788 * Gets the contents of @value.
2790 * Returns: (transfer none): the contents of @value
2792 const GstCapsFeatures *
2793 gst_value_get_caps_features (const GValue * value)
2795 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2796 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS_FEATURES, NULL);
2798 return (GstCapsFeatures *) g_value_get_boxed (value);
2802 gst_value_serialize_caps_features (const GValue * value)
2804 GstCapsFeatures *features = g_value_get_boxed (value);
2806 return priv_gst_string_take_and_wrap (gst_caps_features_to_string (features));
2810 gst_value_deserialize_caps_features (GValue * dest, const gchar * s)
2812 GstCapsFeatures *features;
2815 features = gst_caps_features_from_string (s);
2817 gchar *str = gst_string_unwrap (s);
2819 if (G_UNLIKELY (!str))
2822 features = gst_caps_features_from_string (str);
2826 if (G_LIKELY (features)) {
2827 g_value_take_boxed (dest, features);
2837 gst_value_compare_tag_list (const GValue * value1, const GValue * value2)
2839 GstTagList *taglist1 = GST_TAG_LIST (g_value_get_boxed (value1));
2840 GstTagList *taglist2 = GST_TAG_LIST (g_value_get_boxed (value2));
2842 if (gst_tag_list_is_equal (taglist1, taglist2))
2843 return GST_VALUE_EQUAL;
2844 return GST_VALUE_UNORDERED;
2848 gst_value_deserialize_tag_list (GValue * dest, const gchar * s)
2850 GstTagList *taglist;
2853 taglist = gst_tag_list_new_from_string (s);
2855 gchar *str = gst_string_unwrap (s);
2857 if (G_UNLIKELY (!str))
2860 taglist = gst_tag_list_new_from_string (str);
2864 if (G_LIKELY (taglist != NULL)) {
2865 g_value_take_boxed (dest, taglist);
2872 gst_value_serialize_tag_list (const GValue * value)
2874 GstTagList *taglist = g_value_get_boxed (value);
2876 return priv_gst_string_take_and_wrap (gst_tag_list_to_string (taglist));
2885 compare_buffer (GstBuffer * buf1, GstBuffer * buf2)
2888 GstMapInfo info1, info2;
2892 return GST_VALUE_EQUAL;
2894 size1 = gst_buffer_get_size (buf1);
2895 size2 = gst_buffer_get_size (buf2);
2898 return GST_VALUE_UNORDERED;
2901 return GST_VALUE_EQUAL;
2903 if (!gst_buffer_map (buf1, &info1, GST_MAP_READ))
2904 return GST_VALUE_UNORDERED;
2906 if (!gst_buffer_map (buf2, &info2, GST_MAP_READ)) {
2907 gst_buffer_unmap (buf1, &info1);
2908 return GST_VALUE_UNORDERED;
2911 mret = memcmp (info1.data, info2.data, info1.size);
2913 result = GST_VALUE_EQUAL;
2915 result = GST_VALUE_LESS_THAN;
2917 result = GST_VALUE_GREATER_THAN;
2919 gst_buffer_unmap (buf1, &info1);
2920 gst_buffer_unmap (buf2, &info2);
2926 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
2928 GstBuffer *buf1 = gst_value_get_buffer (value1);
2929 GstBuffer *buf2 = gst_value_get_buffer (value2);
2931 return compare_buffer (buf1, buf2);
2935 gst_value_serialize_buffer (const GValue * value)
2943 buffer = gst_value_get_buffer (value);
2947 if (!gst_buffer_map (buffer, &info, GST_MAP_READ))
2952 string = g_malloc (info.size * 2 + 1);
2953 for (i = 0; i < info.size; i++) {
2954 sprintf (string + i * 2, "%02x", data[i]);
2956 string[info.size * 2] = 0;
2958 gst_buffer_unmap (buffer, &info);
2964 gst_value_deserialize_buffer (GValue * dest, const gchar * s)
2977 buffer = gst_buffer_new_allocate (NULL, len / 2, NULL);
2978 if (!gst_buffer_map (buffer, &info, GST_MAP_WRITE))
2982 for (i = 0; i < len / 2; i++) {
2983 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1]))
2986 ts[0] = s[i * 2 + 0];
2987 ts[1] = s[i * 2 + 1];
2990 data[i] = (guint8) strtoul (ts, NULL, 16);
2992 gst_buffer_unmap (buffer, &info);
2994 gst_value_take_buffer (dest, buffer);
3009 gst_buffer_unref (buffer);
3010 gst_buffer_unmap (buffer, &info);
3019 /* This function is mostly used for comparing image/buffer tags in taglists */
3021 gst_value_compare_sample (const GValue * value1, const GValue * value2)
3023 GstBuffer *buf1 = gst_sample_get_buffer (gst_value_get_sample (value1));
3024 GstBuffer *buf2 = gst_sample_get_buffer (gst_value_get_sample (value2));
3026 /* FIXME: should we take into account anything else such as caps? */
3027 return compare_buffer (buf1, buf2);
3031 gst_value_serialize_sample (const GValue * value)
3033 const GstStructure *info_structure;
3034 GstSegment *segment;
3038 GValue val = { 0, };
3039 gchar *info_str, *caps_str, *tmp;
3040 gchar *buf_str, *seg_str, *s;
3042 sample = g_value_get_boxed (value);
3044 buffer = gst_sample_get_buffer (sample);
3046 g_value_init (&val, GST_TYPE_BUFFER);
3047 g_value_set_boxed (&val, buffer);
3048 buf_str = gst_value_serialize_buffer (&val);
3049 g_value_unset (&val);
3051 buf_str = g_strdup ("None");
3054 caps = gst_sample_get_caps (sample);
3056 tmp = gst_caps_to_string (caps);
3057 caps_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3058 g_strdelimit (caps_str, "=", '_');
3061 caps_str = g_strdup ("None");
3064 segment = gst_sample_get_segment (sample);
3066 g_value_init (&val, GST_TYPE_SEGMENT);
3067 g_value_set_boxed (&val, segment);
3068 tmp = gst_value_serialize_segment_internal (&val, FALSE);
3069 seg_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3070 g_strdelimit (seg_str, "=", '_');
3072 g_value_unset (&val);
3074 seg_str = g_strdup ("None");
3077 info_structure = gst_sample_get_info (sample);
3078 if (info_structure) {
3079 tmp = gst_structure_to_string (info_structure);
3080 info_str = g_base64_encode ((guchar *) tmp, strlen (tmp) + 1);
3081 g_strdelimit (info_str, "=", '_');
3084 info_str = g_strdup ("None");
3087 s = g_strconcat (buf_str, ":", caps_str, ":", seg_str, ":", info_str, NULL);
3097 gst_value_deserialize_sample (GValue * dest, const gchar * s)
3099 GValue bval = G_VALUE_INIT, sval = G_VALUE_INIT;
3102 GstCaps *caps = NULL;
3103 gboolean ret = FALSE;
3108 GST_TRACE ("deserialize '%s'", s);
3110 fields = g_strsplit (s, ":", -1);
3111 len = g_strv_length (fields);
3115 g_value_init (&bval, GST_TYPE_BUFFER);
3116 g_value_init (&sval, GST_TYPE_SEGMENT);
3118 if (!gst_value_deserialize_buffer (&bval, fields[0]))
3121 if (strcmp (fields[1], "None") != 0) {
3122 g_strdelimit (fields[1], "_", '=');
3123 g_base64_decode_inplace (fields[1], &outlen);
3124 GST_TRACE ("caps : %s", fields[1]);
3125 caps = gst_caps_from_string (fields[1]);
3130 if (strcmp (fields[2], "None") != 0) {
3131 g_strdelimit (fields[2], "_", '=');
3132 g_base64_decode_inplace (fields[2], &outlen);
3133 GST_TRACE ("segment : %s", fields[2]);
3134 if (!gst_value_deserialize_segment (&sval, fields[2]))
3138 if (strcmp (fields[3], "None") != 0) {
3139 g_strdelimit (fields[3], "_", '=');
3140 g_base64_decode_inplace (fields[3], &outlen);
3141 GST_TRACE ("info : %s", fields[3]);
3142 info = gst_structure_from_string (fields[3], NULL);
3149 sample = gst_sample_new (gst_value_get_buffer (&bval), caps,
3150 g_value_get_boxed (&sval), info);
3152 g_value_take_boxed (dest, sample);
3158 gst_caps_unref (caps);
3159 g_value_unset (&bval);
3160 g_value_unset (&sval);
3164 g_strfreev (fields);
3174 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
3176 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
3177 return GST_VALUE_EQUAL;
3178 return GST_VALUE_UNORDERED;
3182 gst_value_serialize_boolean (const GValue * value)
3184 if (value->data[0].v_int) {
3185 return g_strdup ("true");
3187 return g_strdup ("false");
3191 gst_value_deserialize_boolean (GValue * dest, const gchar * s)
3193 gboolean ret = FALSE;
3195 if (g_ascii_strcasecmp (s, "true") == 0 ||
3196 g_ascii_strcasecmp (s, "yes") == 0 ||
3197 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
3198 g_value_set_boolean (dest, TRUE);
3200 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
3201 g_ascii_strcasecmp (s, "no") == 0 ||
3202 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
3203 g_value_set_boolean (dest, FALSE);
3210 #define CREATE_SERIALIZATION_START(_type,_macro) \
3212 gst_value_compare_ ## _type \
3213 (const GValue * value1, const GValue * value2) \
3215 g ## _type val1 = g_value_get_ ## _type (value1); \
3216 g ## _type val2 = g_value_get_ ## _type (value2); \
3218 return GST_VALUE_GREATER_THAN; \
3220 return GST_VALUE_LESS_THAN; \
3221 return GST_VALUE_EQUAL; \
3225 gst_value_serialize_ ## _type (const GValue * value) \
3227 GValue val = { 0, }; \
3228 g_value_init (&val, G_TYPE_STRING); \
3229 if (!g_value_transform (value, &val)) \
3230 g_assert_not_reached (); \
3231 /* NO_COPY_MADNESS!!! */ \
3232 return (char *) g_value_get_string (&val); \
3235 /* deserialize the given s into to as a gint64.
3236 * check if the result is actually storeable in the given size number of
3240 gst_value_deserialize_int_helper (gint64 * to, const gchar * s,
3241 gint64 min, gint64 max, gint size)
3243 gboolean ret = FALSE;
3248 *to = g_ascii_strtoull (s, &end, 0);
3249 /* a range error is a definitive no-no */
3250 if (errno == ERANGE) {
3257 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
3258 *to = G_LITTLE_ENDIAN;
3260 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
3263 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
3266 } else if (g_ascii_strcasecmp (s, "min") == 0) {
3269 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3275 /* by definition, a gint64 fits into a gint64; so ignore those */
3276 if (size != sizeof (mask)) {
3278 /* for positive numbers, we create a mask of 1's outside of the range
3279 * and 0's inside the range. An and will thus keep only 1 bits
3280 * outside of the range */
3281 mask <<= (size * 8);
3282 if ((mask & *to) != 0) {
3286 /* for negative numbers, we do a 2's complement version */
3287 mask <<= ((size * 8) - 1);
3288 if ((mask & *to) != mask) {
3297 #define CREATE_SERIALIZATION(_type,_macro) \
3298 CREATE_SERIALIZATION_START(_type,_macro) \
3301 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3305 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, \
3306 G_MAX ## _macro, sizeof (g ## _type))) { \
3307 g_value_set_ ## _type (dest, /*(g ## _type)*/ x); \
3314 #define CREATE_USERIALIZATION(_type,_macro) \
3315 CREATE_SERIALIZATION_START(_type,_macro) \
3318 gst_value_deserialize_ ## _type (GValue * dest, const gchar *s) \
3322 gboolean ret = FALSE; \
3325 x = g_ascii_strtoull (s, &end, 0); \
3326 /* a range error is a definitive no-no */ \
3327 if (errno == ERANGE) { \
3330 /* the cast ensures the range check later on makes sense */ \
3331 x = (g ## _type) x; \
3335 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
3336 x = G_LITTLE_ENDIAN; \
3338 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
3341 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
3344 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
3347 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
3348 x = G_MAX ## _macro; \
3353 if (x > G_MAX ## _macro) { \
3356 g_value_set_ ## _type (dest, x); \
3362 CREATE_SERIALIZATION (int, INT);
3363 CREATE_SERIALIZATION (int64, INT64);
3364 CREATE_SERIALIZATION (long, LONG);
3366 CREATE_USERIALIZATION (uint, UINT);
3367 CREATE_USERIALIZATION (uint64, UINT64);
3368 CREATE_USERIALIZATION (ulong, ULONG);
3370 /* FIXME 2.0: remove this again, plugins shouldn't have uchar properties */
3372 #define G_MAXUCHAR 255
3374 CREATE_USERIALIZATION (uchar, UCHAR);
3380 gst_value_compare_double (const GValue * value1, const GValue * value2)
3382 if (value1->data[0].v_double > value2->data[0].v_double)
3383 return GST_VALUE_GREATER_THAN;
3384 if (value1->data[0].v_double < value2->data[0].v_double)
3385 return GST_VALUE_LESS_THAN;
3386 if (value1->data[0].v_double == value2->data[0].v_double)
3387 return GST_VALUE_EQUAL;
3388 return GST_VALUE_UNORDERED;
3392 gst_value_serialize_double (const GValue * value)
3394 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3396 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
3397 return g_strdup (d);
3401 gst_value_deserialize_double (GValue * dest, const gchar * s)
3404 gboolean ret = FALSE;
3407 x = g_ascii_strtod (s, &end);
3411 if (g_ascii_strcasecmp (s, "min") == 0) {
3414 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3420 g_value_set_double (dest, x);
3430 gst_value_compare_float (const GValue * value1, const GValue * value2)
3432 if (value1->data[0].v_float > value2->data[0].v_float)
3433 return GST_VALUE_GREATER_THAN;
3434 if (value1->data[0].v_float < value2->data[0].v_float)
3435 return GST_VALUE_LESS_THAN;
3436 if (value1->data[0].v_float == value2->data[0].v_float)
3437 return GST_VALUE_EQUAL;
3438 return GST_VALUE_UNORDERED;
3442 gst_value_serialize_float (const GValue * value)
3444 gchar d[G_ASCII_DTOSTR_BUF_SIZE];
3446 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
3447 return g_strdup (d);
3451 gst_value_deserialize_float (GValue * dest, const gchar * s)
3454 gboolean ret = FALSE;
3457 x = g_ascii_strtod (s, &end);
3461 if (g_ascii_strcasecmp (s, "min") == 0) {
3464 } else if (g_ascii_strcasecmp (s, "max") == 0) {
3469 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
3472 g_value_set_float (dest, (float) x);
3482 gst_value_compare_string (const GValue * value1, const GValue * value2)
3484 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) {
3485 /* if only one is NULL, no match - otherwise both NULL == EQUAL */
3486 if (value1->data[0].v_pointer != value2->data[0].v_pointer)
3487 return GST_VALUE_UNORDERED;
3489 gint x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
3492 return GST_VALUE_LESS_THAN;
3494 return GST_VALUE_GREATER_THAN;
3497 return GST_VALUE_EQUAL;
3501 gst_string_measure_wrapping (const gchar * s)
3504 gboolean wrap = FALSE;
3506 if (G_UNLIKELY (s == NULL))
3509 /* Special case: the actual string NULL needs wrapping */
3510 if (G_UNLIKELY (strcmp (s, "NULL") == 0))
3515 if (GST_ASCII_IS_STRING (*s)) {
3517 } else if (*s < 0x20 || *s >= 0x7f) {
3527 /* Wrap the string if we found something that needs
3528 * wrapping, or the empty string (len == 0) */
3529 return (wrap || len == 0) ? len : -1;
3533 gst_string_wrap_inner (const gchar * s, gint len)
3537 e = d = g_malloc (len + 3);
3541 if (GST_ASCII_IS_STRING (*s)) {
3543 } else if (*s < 0x20 || *s >= 0x7f) {
3545 *e++ = '0' + ((*(guchar *) s) >> 6);
3546 *e++ = '0' + (((*s) >> 3) & 0x7);
3547 *e++ = '0' + ((*s++) & 0x7);
3556 g_assert (e - d <= len + 3);
3560 /* Do string wrapping/escaping */
3562 gst_string_wrap (const gchar * s)
3564 gint len = gst_string_measure_wrapping (s);
3566 if (G_LIKELY (len < 0))
3567 return g_strdup (s);
3569 return gst_string_wrap_inner (s, len);
3572 /* Same as above, but take ownership of the string */
3574 priv_gst_string_take_and_wrap (gchar * s)
3577 gint len = gst_string_measure_wrapping (s);
3579 if (G_LIKELY (len < 0))
3582 out = gst_string_wrap_inner (s, len);
3589 * This function takes a string delimited with double quotes (")
3590 * and unescapes any \xxx octal numbers.
3592 * If sequences of \y are found where y is not in the range of
3593 * 0->3, y is copied unescaped.
3595 * If \xyy is found where x is an octal number but y is not, an
3596 * error is encountered and %NULL is returned.
3598 * the input string must be \0 terminated.
3601 gst_string_unwrap (const gchar * s)
3604 gchar *read, *write;
3606 /* NULL string returns NULL */
3610 /* strings not starting with " are invalid */
3614 /* make copy of original string to hold the result. This
3615 * string will always be smaller than the original */
3620 /* need to move to the next position as we parsed the " */
3624 if (GST_ASCII_IS_STRING (*read)) {
3625 /* normal chars are just copied */
3627 } else if (*read == '"') {
3628 /* quote marks end of string */
3630 } else if (*read == '\\') {
3631 /* got an escape char, move to next position to read a tripplet
3632 * of octal numbers */
3634 /* is the next char a possible first octal number? */
3635 if (*read >= '0' && *read <= '3') {
3636 /* parse other 2 numbers, if one of them is not in the range of
3637 * an octal number, we error. We also catch the case where a zero
3638 * byte is found here. */
3639 if (read[1] < '0' || read[1] > '7' || read[2] < '0' || read[2] > '7')
3642 /* now convert the octal number to a byte again. */
3643 *write++ = ((read[0] - '0') << 6) +
3644 ((read[1] - '0') << 3) + (read[2] - '0');
3648 /* if we run into a \0 here, we definitely won't get a quote later */
3652 /* else copy \X sequence */
3656 /* weird character, error */
3660 /* if the string is not ending in " and zero terminated, we error */
3661 if (*read != '"' || read[1] != '\0')
3664 /* null terminate result string and return */
3674 gst_value_serialize_string (const GValue * value)
3676 return gst_string_wrap (value->data[0].v_pointer);
3680 gst_value_deserialize_string (GValue * dest, const gchar * s)
3682 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) {
3683 g_value_set_string (dest, NULL);
3685 } else if (G_LIKELY (*s != '"' || s[strlen (s) - 1] != '"')) {
3686 if (!g_utf8_validate (s, -1, NULL))
3688 g_value_set_string (dest, s);
3691 /* strings delimited with double quotes should be unwrapped */
3692 gchar *str = gst_string_unwrap (s);
3693 if (G_UNLIKELY (!str))
3695 g_value_take_string (dest, str);
3706 gst_value_compare_enum (const GValue * value1, const GValue * value2)
3708 GEnumValue *en1, *en2;
3709 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3710 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3712 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3713 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3714 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
3715 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
3716 g_type_class_unref (klass1);
3717 g_type_class_unref (klass2);
3718 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
3719 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
3720 if (en1->value < en2->value)
3721 return GST_VALUE_LESS_THAN;
3722 if (en1->value > en2->value)
3723 return GST_VALUE_GREATER_THAN;
3725 return GST_VALUE_EQUAL;
3729 gst_value_serialize_enum (const GValue * value)
3732 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
3734 g_return_val_if_fail (klass, NULL);
3735 en = g_enum_get_value (klass, g_value_get_enum (value));
3736 g_type_class_unref (klass);
3738 /* might be one of the custom formats registered later */
3739 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (value) == GST_TYPE_FORMAT)) {
3740 const GstFormatDefinition *format_def;
3742 format_def = gst_format_get_details ((GstFormat) g_value_get_enum (value));
3743 g_return_val_if_fail (format_def != NULL, NULL);
3744 return g_strdup (format_def->description);
3747 g_return_val_if_fail (en, NULL);
3748 return g_strdup (en->value_name);
3752 gst_value_deserialize_enum_iter_cmp (const GValue * format_def_value,
3755 const GstFormatDefinition *format_def =
3756 g_value_get_pointer (format_def_value);
3758 if (g_ascii_strcasecmp (s, format_def->nick) == 0)
3761 return g_ascii_strcasecmp (s, format_def->description);
3765 gst_value_deserialize_enum (GValue * dest, const gchar * s)
3768 gchar *endptr = NULL;
3769 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3771 g_return_val_if_fail (klass, FALSE);
3772 if (!(en = g_enum_get_value_by_name (klass, s))) {
3773 if (!(en = g_enum_get_value_by_nick (klass, s))) {
3774 gint i = strtol (s, &endptr, 0);
3776 if (endptr && *endptr == '\0') {
3777 en = g_enum_get_value (klass, i);
3781 g_type_class_unref (klass);
3783 /* might be one of the custom formats registered later */
3784 if (G_UNLIKELY (en == NULL && G_VALUE_TYPE (dest) == GST_TYPE_FORMAT)) {
3785 GValue res = { 0, };
3786 const GstFormatDefinition *format_def;
3790 iter = gst_format_iterate_definitions ();
3792 found = gst_iterator_find_custom (iter,
3793 (GCompareFunc) gst_value_deserialize_enum_iter_cmp, &res, (gpointer) s);
3796 format_def = g_value_get_pointer (&res);
3797 g_return_val_if_fail (format_def != NULL, FALSE);
3798 g_value_set_enum (dest, (gint) format_def->value);
3799 g_value_unset (&res);
3801 gst_iterator_free (iter);
3805 /* enum name/nick not found */
3809 g_value_set_enum (dest, en->value);
3817 /* we just compare the value here */
3819 gst_value_compare_gflags (const GValue * value1, const GValue * value2)
3822 GFlagsClass *klass1 =
3823 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value1));
3824 GFlagsClass *klass2 =
3825 (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value2));
3827 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
3828 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
3829 fl1 = g_value_get_flags (value1);
3830 fl2 = g_value_get_flags (value2);
3831 g_type_class_unref (klass1);
3832 g_type_class_unref (klass2);
3834 return GST_VALUE_LESS_THAN;
3836 return GST_VALUE_GREATER_THAN;
3838 return GST_VALUE_EQUAL;
3841 /* the different flags are serialized separated with a + */
3843 gst_value_serialize_gflags (const GValue * value)
3847 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (value));
3848 gchar *result, *tmp;
3849 gboolean first = TRUE;
3851 g_return_val_if_fail (klass, NULL);
3853 flags = g_value_get_flags (value);
3855 /* if no flags are set, try to serialize to the _NONE string */
3857 fl = g_flags_get_first_value (klass, flags);
3859 return g_strdup (fl->value_name);
3861 return g_strdup ("0");
3864 /* some flags are set, so serialize one by one */
3865 result = g_strdup ("");
3867 fl = g_flags_get_first_value (klass, flags);
3869 tmp = g_strconcat (result, (first ? "" : "+"), fl->value_name, NULL);
3875 flags &= ~fl->value;
3878 g_type_class_unref (klass);
3884 gst_value_gflags_str_to_flags (GFlagsClass * klass, const gchar * s,
3885 guint * out_flags, guint * out_mask)
3889 const gchar *pos = NULL;
3891 gchar *cur_str, *endptr;
3896 g_return_val_if_fail (klass, FALSE);
3898 /* split into parts delimited with + or / and
3899 * compose the set of flags and mask. */
3903 goto done; /* Empty string, nothing to do */
3905 /* As a special case if the first char isn't a delimiter, assume
3906 * it's a '+' - for GFlags strings, which don't start with a
3907 * delimiter, while GFlagSet always will */
3908 if (*pos == '/' || *pos == '+') {
3916 /* Find the next delimiter */
3918 while (*next != '\0' && *next != '+' && *next != '/')
3920 cur_str = g_strndup (pos, next - pos);
3922 if ((fl = g_flags_get_value_by_name (klass, cur_str)))
3924 else if ((fl = g_flags_get_value_by_nick (klass, cur_str)))
3927 val = strtoul (cur_str, &endptr, 0);
3928 /* direct numeric value */
3929 if (endptr == NULL || *endptr != '\0') {
3931 return FALSE; /* Invalid numeric or string we can't convert */
3938 if (delimiter == '+')
3942 /* Advance to the next delimiter */
3946 } while (delimiter != '\0');
3959 gst_value_deserialize_gflags (GValue * dest, const gchar * s)
3961 GFlagsClass *klass = (GFlagsClass *) g_type_class_ref (G_VALUE_TYPE (dest));
3962 gboolean res = FALSE;
3965 if (gst_value_gflags_str_to_flags (klass, s, &flags, NULL)) {
3966 g_value_set_flags (dest, flags);
3970 g_type_class_unref (klass);
3980 gst_value_compare_gtype (const GValue * value1, const GValue * value2)
3982 if (value1->data[0].v_pointer == value2->data[0].v_pointer)
3983 return GST_VALUE_EQUAL;
3984 return GST_VALUE_UNORDERED;
3988 gst_value_serialize_gtype (const GValue * value)
3990 return g_strdup (g_type_name (g_value_get_gtype (value)));
3994 gst_value_deserialize_gtype (GValue * dest, const gchar * s)
3996 GType t = g_type_from_name (s);
3997 gboolean ret = TRUE;
3999 if (t == G_TYPE_INVALID)
4002 g_value_set_gtype (dest, t);
4012 gst_value_is_subset_int_range_int_range (const GValue * value1,
4013 const GValue * value2)
4017 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value1), FALSE);
4018 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value2), FALSE);
4020 if (INT_RANGE_MIN (value1) * INT_RANGE_STEP (value1) <
4021 INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2))
4023 if (INT_RANGE_MAX (value1) * INT_RANGE_STEP (value1) >
4024 INT_RANGE_MAX (value2) * INT_RANGE_STEP (value2))
4027 if (INT_RANGE_MIN (value2) == INT_RANGE_MAX (value2)) {
4028 if ((INT_RANGE_MIN (value2) * INT_RANGE_STEP (value2)) %
4029 INT_RANGE_STEP (value1))
4035 gst_util_greatest_common_divisor (INT_RANGE_STEP (value1),
4036 INT_RANGE_STEP (value2));
4037 if (gcd != MIN (INT_RANGE_STEP (value1), INT_RANGE_STEP (value2)))
4044 gst_value_is_subset_int64_range_int64_range (const GValue * value1,
4045 const GValue * value2)
4049 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value1), FALSE);
4050 g_return_val_if_fail (GST_VALUE_HOLDS_INT64_RANGE (value2), FALSE);
4052 if (INT64_RANGE_MIN (value1) < INT64_RANGE_MIN (value2))
4054 if (INT64_RANGE_MAX (value1) > INT64_RANGE_MAX (value2))
4057 if (INT64_RANGE_MIN (value2) == INT64_RANGE_MAX (value2)) {
4058 if ((INT64_RANGE_MIN (value2) * INT64_RANGE_STEP (value2)) %
4059 INT64_RANGE_STEP (value1))
4065 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (value1),
4066 INT64_RANGE_STEP (value2));
4067 if (gcd != MIN (INT64_RANGE_STEP (value1), INT64_RANGE_STEP (value2)))
4073 /* A flag set is a subset of another if the superset allows the
4074 * flags of the subset */
4076 gst_value_is_subset_flagset_flagset (const GValue * value1,
4077 const GValue * value2)
4082 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value1), FALSE);
4083 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value2), FALSE);
4085 f1 = value1->data[0].v_uint;
4086 f2 = value2->data[0].v_uint;
4088 m1 = value1->data[1].v_uint;
4089 m2 = value2->data[1].v_uint;
4091 /* Not a subset if masked bits of superset disagree */
4092 if ((f1 & m1) != (f2 & (m1 & m2)))
4099 gst_value_is_subset_structure_structure (const GValue * value1,
4100 const GValue * value2)
4102 const GstStructure *s1, *s2;
4104 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value1), FALSE);
4105 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (value2), FALSE);
4107 s1 = gst_value_get_structure (value1);
4108 s2 = gst_value_get_structure (value2);
4110 return gst_structure_is_subset (s1, s2);
4114 * gst_value_is_subset:
4115 * @value1: a #GValue
4116 * @value2: a #GValue
4118 * Check that @value1 is a subset of @value2.
4120 * Return: %TRUE is @value1 is a subset of @value2
4123 gst_value_is_subset (const GValue * value1, const GValue * value2)
4125 /* special case for int/int64 ranges, since we cannot compute
4126 the difference for those when they have different steps,
4127 and it's actually a lot simpler to compute whether a range
4128 is a subset of another. */
4129 if (GST_VALUE_HOLDS_INT_RANGE (value1) && GST_VALUE_HOLDS_INT_RANGE (value2)) {
4130 return gst_value_is_subset_int_range_int_range (value1, value2);
4131 } else if (GST_VALUE_HOLDS_INT64_RANGE (value1)
4132 && GST_VALUE_HOLDS_INT64_RANGE (value2)) {
4133 return gst_value_is_subset_int64_range_int64_range (value1, value2);
4134 } else if (GST_VALUE_HOLDS_FLAG_SET (value1) &&
4135 GST_VALUE_HOLDS_FLAG_SET (value2)) {
4136 return gst_value_is_subset_flagset_flagset (value1, value2);
4137 } else if (GST_VALUE_HOLDS_STRUCTURE (value1)
4138 && GST_VALUE_HOLDS_STRUCTURE (value2)) {
4139 return gst_value_is_subset_structure_structure (value1, value2);
4147 * -> 1 - [1,2] = empty
4151 * -> [1,2] - [1,3] = empty
4155 * -> {1,3} - {1,2} = 3
4158 * First caps subtraction needs to return a non-empty set, second
4159 * subtractions needs to give en empty set.
4160 * Both substractions are switched below, as it's faster that way.
4162 if (!gst_value_subtract (NULL, value1, value2)) {
4163 if (gst_value_subtract (NULL, value2, value1)) {
4175 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
4176 const GValue * src2)
4178 gint v = src1->data[0].v_int;
4180 /* check if it's already in the range */
4181 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= v &&
4182 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= v &&
4183 v % INT_RANGE_STEP (src2) == 0) {
4185 gst_value_init_and_copy (dest, src2);
4189 /* check if it extends the range */
4190 if (v == (INT_RANGE_MIN (src2) - 1) * INT_RANGE_STEP (src2)) {
4192 guint64 new_min = INT_RANGE_MIN (src2) - 1;
4193 guint64 new_max = INT_RANGE_MAX (src2);
4195 gst_value_init_and_copy (dest, src2);
4196 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4200 if (v == (INT_RANGE_MAX (src2) + 1) * INT_RANGE_STEP (src2)) {
4202 guint64 new_min = INT_RANGE_MIN (src2);
4203 guint64 new_max = INT_RANGE_MAX (src2) + 1;
4205 gst_value_init_and_copy (dest, src2);
4206 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4215 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
4216 const GValue * src2)
4218 /* We can union in several special cases:
4219 1 - one is a subset of another
4220 2 - same step and not disjoint
4221 3 - different step, at least one with one value which matches a 'next' or 'previous'
4226 if (gst_value_is_subset_int_range_int_range (src1, src2)) {
4228 gst_value_init_and_copy (dest, src2);
4231 if (gst_value_is_subset_int_range_int_range (src2, src1)) {
4233 gst_value_init_and_copy (dest, src1);
4237 /* 2 - same step and not disjoint */
4238 if (INT_RANGE_STEP (src1) == INT_RANGE_STEP (src2)) {
4239 if ((INT_RANGE_MIN (src1) <= INT_RANGE_MAX (src2) + 1 &&
4240 INT_RANGE_MAX (src1) >= INT_RANGE_MIN (src2) - 1) ||
4241 (INT_RANGE_MIN (src2) <= INT_RANGE_MAX (src1) + 1 &&
4242 INT_RANGE_MAX (src2) >= INT_RANGE_MIN (src1) - 1)) {
4244 gint step = INT_RANGE_STEP (src1);
4245 gint min = step * MIN (INT_RANGE_MIN (src1), INT_RANGE_MIN (src2));
4246 gint max = step * MAX (INT_RANGE_MAX (src1), INT_RANGE_MAX (src2));
4247 g_value_init (dest, GST_TYPE_INT_RANGE);
4248 gst_value_set_int_range_step (dest, min, max, step);
4254 /* 3 - single value matches next or previous */
4255 if (INT_RANGE_STEP (src1) != INT_RANGE_STEP (src2)) {
4256 gint n1 = INT_RANGE_MAX (src1) - INT_RANGE_MIN (src1) + 1;
4257 gint n2 = INT_RANGE_MAX (src2) - INT_RANGE_MIN (src2) + 1;
4258 if (n1 == 1 || n2 == 1) {
4259 const GValue *range_value = NULL;
4263 scalar = INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1);
4264 } else if (n2 == 1) {
4266 scalar = INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2);
4270 (INT_RANGE_MIN (range_value) - 1) * INT_RANGE_STEP (range_value)) {
4272 guint64 new_min = (guint)
4273 ((INT_RANGE_MIN (range_value) -
4274 1) * INT_RANGE_STEP (range_value));
4275 guint64 new_max = (guint)
4276 (INT_RANGE_MAX (range_value) * INT_RANGE_STEP (range_value));
4278 gst_value_init_and_copy (dest, range_value);
4279 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4282 } else if (scalar ==
4283 (INT_RANGE_MAX (range_value) + 1) * INT_RANGE_STEP (range_value)) {
4285 guint64 new_min = (guint)
4286 (INT_RANGE_MIN (range_value) * INT_RANGE_STEP (range_value));
4287 guint64 new_max = (guint)
4288 ((INT_RANGE_MAX (range_value) +
4289 1) * INT_RANGE_STEP (range_value));
4290 gst_value_init_and_copy (dest, range_value);
4291 dest->data[0].v_uint64 = (new_min << 32) | (new_max);
4298 /* If we get there, we did not find a way to make a union that can be
4299 represented with our simplistic model. */
4304 gst_value_union_flagset_flagset (GValue * dest, const GValue * src1,
4305 const GValue * src2)
4307 /* We can union 2 flag sets where they do not disagree on
4308 * required (masked) flag bits */
4312 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4313 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4315 f1 = src1->data[0].v_uint;
4316 f2 = src2->data[0].v_uint;
4318 m1 = src1->data[1].v_uint;
4319 m2 = src2->data[1].v_uint;
4321 /* Can't union if masked bits disagree */
4322 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4326 g_value_init (dest, GST_TYPE_FLAG_SET);
4327 /* Copy masked bits from src2 to src1 */
4331 gst_value_set_flagset (dest, f1, m1);
4337 /* iterating over the result taking the union with the other structure's value */
4339 structure_field_union_into (GQuark field_id, GValue * val, gpointer user_data)
4341 GstStructure *other = user_data;
4342 const GValue *other_value;
4343 GValue res_value = G_VALUE_INIT;
4345 other_value = gst_structure_id_get_value (other, field_id);
4346 /* no value in the other struct, just keep this value */
4350 if (!gst_value_union (&res_value, val, other_value))
4353 g_value_unset (val);
4354 gst_value_init_and_copy (val, &res_value);
4358 /* iterating over the other source structure adding missing values */
4360 structure_field_union_from (GQuark field_id, const GValue * other_val,
4363 GstStructure *result = user_data;
4364 const GValue *result_value;
4366 result_value = gst_structure_id_get_value (result, field_id);
4368 gst_structure_id_set_value (result, field_id, other_val);
4374 gst_value_union_structure_structure (GValue * dest, const GValue * src1,
4375 const GValue * src2)
4377 const GstStructure *s1, *s2;
4378 GstStructure *result;
4381 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src1), FALSE);
4382 g_return_val_if_fail (GST_VALUE_HOLDS_STRUCTURE (src2), FALSE);
4384 s1 = gst_value_get_structure (src1);
4385 s2 = gst_value_get_structure (src2);
4387 /* Can't join two structures with different names into a single structure */
4388 if (!gst_structure_has_name (s1, gst_structure_get_name (s2))) {
4389 gst_value_list_concat (dest, src1, src2);
4393 result = gst_structure_copy (s1);
4395 gst_structure_map_in_place (result, structure_field_union_into,
4400 gst_structure_foreach (s2, structure_field_union_from, (gpointer) result);
4403 g_value_init (dest, GST_TYPE_STRUCTURE);
4404 gst_value_set_structure (dest, result);
4408 gst_structure_free (result);
4417 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
4418 const GValue * src2)
4420 if (INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2) <= src1->data[0].v_int &&
4421 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2) >= src1->data[0].v_int &&
4422 src1->data[0].v_int % INT_RANGE_STEP (src2) == 0) {
4424 gst_value_init_and_copy (dest, src1);
4432 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
4433 const GValue * src2)
4440 INT_RANGE_STEP (src1) /
4441 gst_util_greatest_common_divisor (INT_RANGE_STEP (src1),
4442 INT_RANGE_STEP (src2));
4443 if (G_MAXINT32 / INT_RANGE_STEP (src2) < step)
4445 step *= INT_RANGE_STEP (src2);
4448 MAX (INT_RANGE_MIN (src1) * INT_RANGE_STEP (src1),
4449 INT_RANGE_MIN (src2) * INT_RANGE_STEP (src2));
4450 min = (min + step - 1) / step * step;
4452 MIN (INT_RANGE_MAX (src1) * INT_RANGE_STEP (src1),
4453 INT_RANGE_MAX (src2) * INT_RANGE_STEP (src2));
4454 max = max / step * step;
4458 g_value_init (dest, GST_TYPE_INT_RANGE);
4459 gst_value_set_int_range_step (dest, min, max, step);
4465 g_value_init (dest, G_TYPE_INT);
4466 g_value_set_int (dest, min);
4474 #define INT64_RANGE_MIN_VAL(v) (INT64_RANGE_MIN (v) * INT64_RANGE_STEP (v))
4475 #define INT64_RANGE_MAX_VAL(v) (INT64_RANGE_MAX (v) * INT64_RANGE_STEP (v))
4478 gst_value_intersect_int64_int64_range (GValue * dest, const GValue * src1,
4479 const GValue * src2)
4481 if (INT64_RANGE_MIN_VAL (src2) <= src1->data[0].v_int64 &&
4482 INT64_RANGE_MAX_VAL (src2) >= src1->data[0].v_int64 &&
4483 src1->data[0].v_int64 % INT64_RANGE_STEP (src2) == 0) {
4485 gst_value_init_and_copy (dest, src1);
4493 gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1,
4494 const GValue * src2)
4501 INT64_RANGE_STEP (src1) /
4502 gst_util_greatest_common_divisor_int64 (INT64_RANGE_STEP (src1),
4503 INT64_RANGE_STEP (src2));
4504 if (G_MAXINT64 / INT64_RANGE_STEP (src2) < step)
4506 step *= INT64_RANGE_STEP (src2);
4509 MAX (INT64_RANGE_MIN (src1) * INT64_RANGE_STEP (src1),
4510 INT64_RANGE_MIN (src2) * INT64_RANGE_STEP (src2));
4511 min = (min + step - 1) / step * step;
4513 MIN (INT64_RANGE_MAX (src1) * INT64_RANGE_STEP (src1),
4514 INT64_RANGE_MAX (src2) * INT64_RANGE_STEP (src2));
4515 max = max / step * step;
4519 g_value_init (dest, GST_TYPE_INT64_RANGE);
4520 gst_value_set_int64_range_step (dest, min, max, step);
4526 g_value_init (dest, G_TYPE_INT64);
4527 g_value_set_int64 (dest, min);
4536 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
4537 const GValue * src2)
4539 if (src2->data[0].v_double <= src1->data[0].v_double &&
4540 src2->data[1].v_double >= src1->data[0].v_double) {
4542 gst_value_init_and_copy (dest, src1);
4550 gst_value_intersect_double_range_double_range (GValue * dest,
4551 const GValue * src1, const GValue * src2)
4556 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
4557 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
4561 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
4562 gst_value_set_double_range (dest, min, max);
4568 g_value_init (dest, G_TYPE_DOUBLE);
4569 g_value_set_int (dest, (int) min);
4578 gst_value_intersect_list (GValue * dest, const GValue * value1,
4579 const GValue * value2)
4582 GValue intersection = { 0, };
4583 gboolean ret = FALSE;
4585 size = VALUE_LIST_SIZE (value1);
4586 for (i = 0; i < size; i++) {
4587 const GValue *cur = VALUE_LIST_GET_VALUE (value1, i);
4589 /* quicker version when we don't need the resulting set */
4591 if (gst_value_intersect (NULL, cur, value2)) {
4598 if (gst_value_intersect (&intersection, cur, value2)) {
4601 gst_value_move (dest, &intersection);
4603 } else if (GST_VALUE_HOLDS_LIST (dest)) {
4604 _gst_value_list_append_and_take_value (dest, &intersection);
4608 gst_value_move (&temp, dest);
4609 gst_value_list_merge (dest, &temp, &intersection);
4610 g_value_unset (&temp);
4611 g_value_unset (&intersection);
4620 gst_value_intersect_array (GValue * dest, const GValue * src1,
4621 const GValue * src2)
4627 /* only works on similar-sized arrays */
4628 size = gst_value_array_get_size (src1);
4629 if (size != gst_value_array_get_size (src2))
4632 /* quicker value when we don't need the resulting set */
4634 for (n = 0; n < size; n++) {
4635 if (!gst_value_intersect (NULL, gst_value_array_get_value (src1, n),
4636 gst_value_array_get_value (src2, n))) {
4643 g_value_init (dest, GST_TYPE_ARRAY);
4645 for (n = 0; n < size; n++) {
4646 if (!gst_value_intersect (&val, gst_value_array_get_value (src1, n),
4647 gst_value_array_get_value (src2, n))) {
4648 g_value_unset (dest);
4651 _gst_value_array_append_and_take_value (dest, &val);
4658 gst_value_intersect_fraction_fraction_range (GValue * dest, const GValue * src1,
4659 const GValue * src2)
4663 GstValueCompareFunc compare;
4665 vals = src2->data[0].v_pointer;
4670 if ((compare = gst_value_get_compare_func (src1))) {
4671 res1 = gst_value_compare_with_func (&vals[0], src1, compare);
4672 res2 = gst_value_compare_with_func (&vals[1], src1, compare);
4674 if ((res1 == GST_VALUE_EQUAL || res1 == GST_VALUE_LESS_THAN) &&
4675 (res2 == GST_VALUE_EQUAL || res2 == GST_VALUE_GREATER_THAN)) {
4677 gst_value_init_and_copy (dest, src1);
4686 gst_value_intersect_fraction_range_fraction_range (GValue * dest,
4687 const GValue * src1, const GValue * src2)
4692 GValue *vals1, *vals2;
4693 GstValueCompareFunc compare;
4695 vals1 = src1->data[0].v_pointer;
4696 vals2 = src2->data[0].v_pointer;
4697 g_return_val_if_fail (vals1 != NULL && vals2 != NULL, FALSE);
4699 if ((compare = gst_value_get_compare_func (&vals1[0]))) {
4700 /* min = MAX (src1.start, src2.start) */
4701 res = gst_value_compare_with_func (&vals1[0], &vals2[0], compare);
4702 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4703 if (res == GST_VALUE_LESS_THAN)
4704 min = &vals2[0]; /* Take the max of the 2 */
4708 /* max = MIN (src1.end, src2.end) */
4709 res = gst_value_compare_with_func (&vals1[1], &vals2[1], compare);
4710 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4711 if (res == GST_VALUE_GREATER_THAN)
4712 max = &vals2[1]; /* Take the min of the 2 */
4716 res = gst_value_compare_with_func (min, max, compare);
4717 g_return_val_if_fail (res != GST_VALUE_UNORDERED, FALSE);
4718 if (res == GST_VALUE_LESS_THAN) {
4720 g_value_init (dest, GST_TYPE_FRACTION_RANGE);
4721 vals1 = dest->data[0].v_pointer;
4722 g_value_copy (min, &vals1[0]);
4723 g_value_copy (max, &vals1[1]);
4727 if (res == GST_VALUE_EQUAL) {
4729 gst_value_init_and_copy (dest, min);
4737 /* Two flagsets intersect if the masked bits in both
4738 * flagsets are exactly equal */
4740 gst_value_intersect_flagset_flagset (GValue * dest,
4741 const GValue * src1, const GValue * src2)
4745 GType type1, type2, flagset_type;
4747 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src1), FALSE);
4748 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (src2), FALSE);
4750 f1 = src1->data[0].v_uint;
4751 f2 = src2->data[0].v_uint;
4753 m1 = src1->data[1].v_uint;
4754 m2 = src2->data[1].v_uint;
4756 /* Don't intersect if masked bits disagree */
4757 if ((f1 & (m1 & m2)) != (f2 & (m1 & m2)))
4760 /* Allow intersection with the generic FlagSet type, on one
4761 * side, but not 2 different subtypes - that makes no sense */
4762 type1 = G_VALUE_TYPE (src1);
4763 type2 = G_VALUE_TYPE (src2);
4764 flagset_type = GST_TYPE_FLAG_SET;
4766 if (type1 != type2 && type1 != flagset_type && type2 != flagset_type)
4772 /* Prefer an output type that matches a sub-type,
4773 * rather than the generic type */
4774 if (type1 != flagset_type)
4779 g_value_init (dest, dest_type);
4781 /* The compatible set is all the bits from src1 that it
4782 * cares about and all the bits from src2 that it cares
4784 dest->data[0].v_uint = (f1 & m1) | (f2 & m2);
4785 dest->data[1].v_uint = m1 | m2;
4792 gst_value_intersect_structure_structure (GValue * dest,
4793 const GValue * src1, const GValue * src2)
4795 const GstStructure *s1, *s2;
4798 s1 = gst_value_get_structure (src1);
4799 s2 = gst_value_get_structure (src2);
4801 d1 = gst_structure_intersect (s1, s2);
4806 g_value_init (dest, GST_TYPE_STRUCTURE);
4807 gst_value_set_structure (dest, d1);
4810 gst_structure_free (d1);
4819 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
4820 const GValue * subtrahend)
4822 gint min = gst_value_get_int_range_min (subtrahend);
4823 gint max = gst_value_get_int_range_max (subtrahend);
4824 gint step = gst_value_get_int_range_step (subtrahend);
4825 gint val = g_value_get_int (minuend);
4830 /* subtracting a range from an int only works if the int is not in the
4832 if (val < min || val > max || val % step) {
4833 /* and the result is the int */
4835 gst_value_init_and_copy (dest, minuend);
4841 /* creates a new int range based on input values.
4844 gst_value_create_new_range (GValue * dest, gint min1, gint max1, gint min2,
4845 gint max2, gint step)
4849 GValue *pv1, *pv2; /* yeah, hungarian! */
4851 g_return_val_if_fail (step > 0, FALSE);
4852 g_return_val_if_fail (min1 % step == 0, FALSE);
4853 g_return_val_if_fail (max1 % step == 0, FALSE);
4854 g_return_val_if_fail (min2 % step == 0, FALSE);
4855 g_return_val_if_fail (max2 % step == 0, FALSE);
4857 if (min1 <= max1 && min2 <= max2) {
4860 } else if (min1 <= max1) {
4863 } else if (min2 <= max2) {
4874 g_value_init (pv1, GST_TYPE_INT_RANGE);
4875 gst_value_set_int_range_step (pv1, min1, max1, step);
4876 } else if (min1 == max1) {
4877 g_value_init (pv1, G_TYPE_INT);
4878 g_value_set_int (pv1, min1);
4881 g_value_init (pv2, GST_TYPE_INT_RANGE);
4882 gst_value_set_int_range_step (pv2, min2, max2, step);
4883 } else if (min2 == max2) {
4884 g_value_init (pv2, G_TYPE_INT);
4885 g_value_set_int (pv2, min2);
4888 if (min1 <= max1 && min2 <= max2) {
4889 gst_value_list_concat_and_take_values (dest, pv1, pv2);
4895 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
4896 const GValue * subtrahend)
4898 gint min = gst_value_get_int_range_min (minuend);
4899 gint max = gst_value_get_int_range_max (minuend);
4900 gint step = gst_value_get_int_range_step (minuend);
4901 gint val = g_value_get_int (subtrahend);
4903 g_return_val_if_fail (min < max, FALSE);
4908 /* value is outside of the range, return range unchanged */
4909 if (val < min || val > max || val % step) {
4911 gst_value_init_and_copy (dest, minuend);
4914 /* max must be MAXINT too as val <= max */
4915 if (val >= G_MAXINT - step + 1) {
4919 /* min must be MININT too as val >= max */
4920 if (val <= G_MININT + step - 1) {
4925 gst_value_create_new_range (dest, min, val - step, val + step, max, step);
4931 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
4932 const GValue * subtrahend)
4934 gint min1 = gst_value_get_int_range_min (minuend);
4935 gint max1 = gst_value_get_int_range_max (minuend);
4936 gint step1 = gst_value_get_int_range_step (minuend);
4937 gint min2 = gst_value_get_int_range_min (subtrahend);
4938 gint max2 = gst_value_get_int_range_max (subtrahend);
4939 gint step2 = gst_value_get_int_range_step (subtrahend);
4942 if (step1 != step2) {
4952 if (max2 >= max1 && min2 <= min1) {
4954 } else if (max2 >= max1) {
4955 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4957 } else if (min2 <= min1) {
4958 return gst_value_create_new_range (dest, MAX (max2 + step, min1), max1,
4961 return gst_value_create_new_range (dest, min1, MIN (min2 - step, max1),
4962 MAX (max2 + step, min1), max1, step);
4967 gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend,
4968 const GValue * subtrahend)
4970 gint64 min = gst_value_get_int64_range_min (subtrahend);
4971 gint64 max = gst_value_get_int64_range_max (subtrahend);
4972 gint64 step = gst_value_get_int64_range_step (subtrahend);
4973 gint64 val = g_value_get_int64 (minuend);
4977 /* subtracting a range from an int64 only works if the int64 is not in the
4979 if (val < min || val > max || val % step) {
4980 /* and the result is the int64 */
4982 gst_value_init_and_copy (dest, minuend);
4988 /* creates a new int64 range based on input values.
4991 gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1,
4992 gint64 min2, gint64 max2, gint64 step)
4996 GValue *pv1, *pv2; /* yeah, hungarian! */
4998 g_return_val_if_fail (step > 0, FALSE);
4999 g_return_val_if_fail (min1 % step == 0, FALSE);
5000 g_return_val_if_fail (max1 % step == 0, FALSE);
5001 g_return_val_if_fail (min2 % step == 0, FALSE);
5002 g_return_val_if_fail (max2 % step == 0, FALSE);
5004 if (min1 <= max1 && min2 <= max2) {
5007 } else if (min1 <= max1) {
5010 } else if (min2 <= max2) {
5021 g_value_init (pv1, GST_TYPE_INT64_RANGE);
5022 gst_value_set_int64_range_step (pv1, min1, max1, step);
5023 } else if (min1 == max1) {
5024 g_value_init (pv1, G_TYPE_INT64);
5025 g_value_set_int64 (pv1, min1);
5028 g_value_init (pv2, GST_TYPE_INT64_RANGE);
5029 gst_value_set_int64_range_step (pv2, min2, max2, step);
5030 } else if (min2 == max2) {
5031 g_value_init (pv2, G_TYPE_INT64);
5032 g_value_set_int64 (pv2, min2);
5035 if (min1 <= max1 && min2 <= max2) {
5036 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5042 gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend,
5043 const GValue * subtrahend)
5045 gint64 min = gst_value_get_int64_range_min (minuend);
5046 gint64 max = gst_value_get_int64_range_max (minuend);
5047 gint64 step = gst_value_get_int64_range_step (minuend);
5048 gint64 val = g_value_get_int64 (subtrahend);
5050 g_return_val_if_fail (min < max, FALSE);
5055 /* value is outside of the range, return range unchanged */
5056 if (val < min || val > max || val % step) {
5058 gst_value_init_and_copy (dest, minuend);
5061 /* max must be MAXINT64 too as val <= max */
5062 if (val >= G_MAXINT64 - step + 1) {
5066 /* min must be MININT64 too as val >= max */
5067 if (val <= G_MININT64 + step - 1) {
5072 gst_value_create_new_int64_range (dest, min, val - step, val + step, max,
5079 gst_value_subtract_int64_range_int64_range (GValue * dest,
5080 const GValue * minuend, const GValue * subtrahend)
5082 gint64 min1 = gst_value_get_int64_range_min (minuend);
5083 gint64 max1 = gst_value_get_int64_range_max (minuend);
5084 gint64 step1 = gst_value_get_int64_range_step (minuend);
5085 gint64 min2 = gst_value_get_int64_range_min (subtrahend);
5086 gint64 max2 = gst_value_get_int64_range_max (subtrahend);
5087 gint64 step2 = gst_value_get_int64_range_step (subtrahend);
5090 if (step1 != step2) {
5101 if (max2 >= max1 && min2 <= min1) {
5103 } else if (max2 >= max1) {
5104 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5105 max1), step, 0, step);
5106 } else if (min2 <= min1) {
5107 return gst_value_create_new_int64_range (dest, MAX (max2 + step, min1),
5108 max1, step, 0, step);
5110 return gst_value_create_new_int64_range (dest, min1, MIN (min2 - step,
5111 max1), MAX (max2 + step, min1), max1, step);
5116 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
5117 const GValue * subtrahend)
5119 gdouble min = gst_value_get_double_range_min (subtrahend);
5120 gdouble max = gst_value_get_double_range_max (subtrahend);
5121 gdouble val = g_value_get_double (minuend);
5123 if (val < min || val > max) {
5125 gst_value_init_and_copy (dest, minuend);
5132 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
5133 const GValue * subtrahend)
5135 /* since we don't have open ranges, we cannot create a hole in
5136 * a double range. We return the original range */
5138 gst_value_init_and_copy (dest, minuend);
5143 gst_value_subtract_double_range_double_range (GValue * dest,
5144 const GValue * minuend, const GValue * subtrahend)
5146 /* since we don't have open ranges, we have to approximate */
5147 /* done like with ints */
5148 gdouble min1 = gst_value_get_double_range_min (minuend);
5149 gdouble max2 = gst_value_get_double_range_max (minuend);
5150 gdouble max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
5151 gdouble min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
5154 GValue *pv1, *pv2; /* yeah, hungarian! */
5156 if (min1 < max1 && min2 < max2) {
5159 } else if (min1 < max1) {
5162 } else if (min2 < max2) {
5173 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
5174 gst_value_set_double_range (pv1, min1, max1);
5177 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
5178 gst_value_set_double_range (pv2, min2, max2);
5181 if (min1 < max1 && min2 < max2) {
5182 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5188 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
5189 const GValue * subtrahend)
5192 GValue subtraction = { 0, };
5193 gboolean ret = FALSE;
5195 size = VALUE_LIST_SIZE (minuend);
5196 for (i = 0; i < size; i++) {
5197 const GValue *cur = VALUE_LIST_GET_VALUE (minuend, i);
5199 /* quicker version when we can discard the result */
5201 if (gst_value_subtract (NULL, cur, subtrahend)) {
5208 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
5210 gst_value_move (dest, &subtraction);
5212 } else if (G_VALUE_TYPE (dest) == GST_TYPE_LIST
5213 && G_VALUE_TYPE (&subtraction) != GST_TYPE_LIST) {
5214 _gst_value_list_append_and_take_value (dest, &subtraction);
5218 gst_value_move (&temp, dest);
5219 gst_value_list_concat_and_take_values (dest, &temp, &subtraction);
5227 gst_value_subtract_list (GValue * dest, const GValue * minuend,
5228 const GValue * subtrahend)
5231 GValue data[2] = { {0,}, {0,} };
5232 GValue *subtraction = &data[0], *result = &data[1];
5234 gst_value_init_and_copy (result, minuend);
5235 size = VALUE_LIST_SIZE (subtrahend);
5236 for (i = 0; i < size; i++) {
5237 const GValue *cur = VALUE_LIST_GET_VALUE (subtrahend, i);
5239 if (gst_value_subtract (subtraction, result, cur)) {
5240 GValue *temp = result;
5242 result = subtraction;
5244 g_value_unset (subtraction);
5246 g_value_unset (result);
5251 gst_value_move (dest, result);
5253 g_value_unset (result);
5259 gst_value_subtract_fraction_fraction_range (GValue * dest,
5260 const GValue * minuend, const GValue * subtrahend)
5262 const GValue *min = gst_value_get_fraction_range_min (subtrahend);
5263 const GValue *max = gst_value_get_fraction_range_max (subtrahend);
5264 GstValueCompareFunc compare;
5266 if ((compare = gst_value_get_compare_func (minuend))) {
5267 /* subtracting a range from an fraction only works if the fraction
5268 * is not in the range */
5269 if (gst_value_compare_with_func (minuend, min, compare) ==
5270 GST_VALUE_LESS_THAN ||
5271 gst_value_compare_with_func (minuend, max, compare) ==
5272 GST_VALUE_GREATER_THAN) {
5273 /* and the result is the value */
5275 gst_value_init_and_copy (dest, minuend);
5283 gst_value_subtract_fraction_range_fraction (GValue * dest,
5284 const GValue * minuend, const GValue * subtrahend)
5286 /* since we don't have open ranges, we cannot create a hole in
5287 * a range. We return the original range */
5289 gst_value_init_and_copy (dest, minuend);
5294 gst_value_subtract_fraction_range_fraction_range (GValue * dest,
5295 const GValue * minuend, const GValue * subtrahend)
5297 /* since we don't have open ranges, we have to approximate */
5298 /* done like with ints and doubles. Creates a list of 2 fraction ranges */
5299 const GValue *min1 = gst_value_get_fraction_range_min (minuend);
5300 const GValue *max2 = gst_value_get_fraction_range_max (minuend);
5301 const GValue *max1 = gst_value_get_fraction_range_min (subtrahend);
5302 const GValue *min2 = gst_value_get_fraction_range_max (subtrahend);
5306 GValue *pv1, *pv2; /* yeah, hungarian! */
5307 GstValueCompareFunc compare;
5309 g_return_val_if_fail (min1 != NULL && max1 != NULL, FALSE);
5310 g_return_val_if_fail (min2 != NULL && max2 != NULL, FALSE);
5312 compare = gst_value_get_compare_func (min1);
5313 g_return_val_if_fail (compare, FALSE);
5315 cmp1 = gst_value_compare_with_func (max2, max1, compare);
5316 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5317 if (cmp1 == GST_VALUE_LESS_THAN)
5319 cmp1 = gst_value_compare_with_func (min1, min2, compare);
5320 g_return_val_if_fail (cmp1 != GST_VALUE_UNORDERED, FALSE);
5321 if (cmp1 == GST_VALUE_GREATER_THAN)
5324 cmp1 = gst_value_compare_with_func (min1, max1, compare);
5325 cmp2 = gst_value_compare_with_func (min2, max2, compare);
5327 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5330 } else if (cmp1 == GST_VALUE_LESS_THAN) {
5333 } else if (cmp2 == GST_VALUE_LESS_THAN) {
5343 if (cmp1 == GST_VALUE_LESS_THAN) {
5344 g_value_init (pv1, GST_TYPE_FRACTION_RANGE);
5345 gst_value_set_fraction_range (pv1, min1, max1);
5347 if (cmp2 == GST_VALUE_LESS_THAN) {
5348 g_value_init (pv2, GST_TYPE_FRACTION_RANGE);
5349 gst_value_set_fraction_range (pv2, min2, max2);
5352 if (cmp1 == GST_VALUE_LESS_THAN && cmp2 == GST_VALUE_LESS_THAN) {
5353 gst_value_list_concat_and_take_values (dest, pv1, pv2);
5363 * gst_value_get_compare_func:
5364 * @value1: a value to get the compare function for
5366 * Determines the compare function to be used with values of the same type as
5367 * @value1. The function can be given to gst_value_compare_with_func().
5369 * Returns: A #GstValueCompareFunc value
5371 static GstValueCompareFunc
5372 gst_value_get_compare_func (const GValue * value1)
5374 GstValueTable *table, *best = NULL;
5378 type1 = G_VALUE_TYPE (value1);
5380 /* this is a fast check */
5381 best = gst_value_hash_lookup_type (type1);
5384 if (G_UNLIKELY (!best || !best->compare)) {
5385 guint len = gst_value_table->len;
5388 for (i = 0; i < len; i++) {
5389 table = &g_array_index (gst_value_table, GstValueTable, i);
5390 if (table->compare && g_type_is_a (type1, table->type)) {
5391 if (!best || g_type_is_a (table->type, best->type))
5396 if (G_LIKELY (best))
5397 return best->compare;
5402 static inline gboolean
5403 gst_value_can_compare_unchecked (const GValue * value1, const GValue * value2)
5405 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5408 return gst_value_get_compare_func (value1) != NULL;
5412 * gst_value_can_compare:
5413 * @value1: a value to compare
5414 * @value2: another value to compare
5416 * Determines if @value1 and @value2 can be compared.
5418 * Returns: %TRUE if the values can be compared
5421 gst_value_can_compare (const GValue * value1, const GValue * value2)
5423 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5424 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5426 return gst_value_can_compare_unchecked (value1, value2);
5430 gst_value_list_equals_range (const GValue * list, const GValue * value)
5432 const GValue *first;
5435 g_assert (G_IS_VALUE (list));
5436 g_assert (G_IS_VALUE (value));
5437 g_assert (GST_VALUE_HOLDS_LIST (list));
5439 /* TODO: compare against an empty list ? No type though... */
5440 list_size = VALUE_LIST_SIZE (list);
5444 /* compare the basic types - they have to match */
5445 first = VALUE_LIST_GET_VALUE (list, 0);
5446 #define CHECK_TYPES(type,prefix) \
5447 (prefix##_VALUE_HOLDS_##type(first) && GST_VALUE_HOLDS_##type##_RANGE (value))
5448 if (CHECK_TYPES (INT, G)) {
5449 const gint rmin = gst_value_get_int_range_min (value);
5450 const gint rmax = gst_value_get_int_range_max (value);
5451 const gint rstep = gst_value_get_int_range_step (value);
5454 /* note: this will overflow for min 0 and max INT_MAX, but this
5455 would only be equal to a list of INT_MAX elements, which seems
5457 if (list_size != rmax / rstep - rmin / rstep + 1)
5459 for (n = 0; n < list_size; ++n) {
5460 gint v = g_value_get_int (VALUE_LIST_GET_VALUE (list, n));
5461 if (v < rmin || v > rmax || v % rstep) {
5466 } else if (CHECK_TYPES (INT64, G)) {
5467 const gint64 rmin = gst_value_get_int64_range_min (value);
5468 const gint64 rmax = gst_value_get_int64_range_max (value);
5469 const gint64 rstep = gst_value_get_int64_range_step (value);
5470 GST_DEBUG ("List/range of int64s");
5473 if (list_size != rmax / rstep - rmin / rstep + 1)
5475 for (n = 0; n < list_size; ++n) {
5476 gint64 v = g_value_get_int64 (VALUE_LIST_GET_VALUE (list, n));
5477 if (v < rmin || v > rmax || v % rstep)
5484 /* other combinations don't make sense for equality */
5488 /* "Pure" variant of gst_value_compare which is guaranteed to
5489 * not have list arguments and therefore does basic comparisions
5492 _gst_value_compare_nolist (const GValue * value1, const GValue * value2)
5494 GstValueCompareFunc compare;
5496 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5497 return GST_VALUE_UNORDERED;
5499 compare = gst_value_get_compare_func (value1);
5501 return compare (value1, value2);
5504 g_critical ("unable to compare values of type %s\n",
5505 g_type_name (G_VALUE_TYPE (value1)));
5506 return GST_VALUE_UNORDERED;
5510 * gst_value_compare:
5511 * @value1: a value to compare
5512 * @value2: another value to compare
5514 * Compares @value1 and @value2. If @value1 and @value2 cannot be
5515 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
5516 * if @value1 is greater than @value2, GST_VALUE_GREATER_THAN is returned.
5517 * If @value1 is less than @value2, GST_VALUE_LESS_THAN is returned.
5518 * If the values are equal, GST_VALUE_EQUAL is returned.
5520 * Returns: comparison result
5523 gst_value_compare (const GValue * value1, const GValue * value2)
5525 gboolean value1_is_list;
5526 gboolean value2_is_list;
5528 g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
5529 g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN);
5531 value1_is_list = G_VALUE_TYPE (value1) == GST_TYPE_LIST;
5532 value2_is_list = G_VALUE_TYPE (value2) == GST_TYPE_LIST;
5534 /* Special cases: lists and scalar values ("{ 1 }" and "1" are equal),
5535 as well as lists and ranges ("{ 1, 2 }" and "[ 1, 2 ]" are equal) */
5536 if (value1_is_list && !value2_is_list) {
5539 if (gst_value_list_equals_range (value1, value2)) {
5540 return GST_VALUE_EQUAL;
5543 n = gst_value_list_get_size (value1);
5545 return GST_VALUE_UNORDERED;
5547 for (i = 0; i < n; i++) {
5550 elt = gst_value_list_get_value (value1, i);
5551 ret = gst_value_compare (elt, value2);
5552 if (ret != GST_VALUE_EQUAL && n == 1)
5554 else if (ret != GST_VALUE_EQUAL)
5555 return GST_VALUE_UNORDERED;
5558 return GST_VALUE_EQUAL;
5559 } else if (value2_is_list && !value1_is_list) {
5562 if (gst_value_list_equals_range (value2, value1)) {
5563 return GST_VALUE_EQUAL;
5566 n = gst_value_list_get_size (value2);
5568 return GST_VALUE_UNORDERED;
5570 for (i = 0; i < n; i++) {
5573 elt = gst_value_list_get_value (value2, i);
5574 ret = gst_value_compare (elt, value1);
5575 if (ret != GST_VALUE_EQUAL && n == 1)
5577 else if (ret != GST_VALUE_EQUAL)
5578 return GST_VALUE_UNORDERED;
5581 return GST_VALUE_EQUAL;
5584 /* And now handle the generic case */
5585 return _gst_value_compare_nolist (value1, value2);
5589 * gst_value_compare_with_func:
5590 * @value1: a value to compare
5591 * @value2: another value to compare
5592 * @compare: compare function
5594 * Compares @value1 and @value2 using the @compare function. Works like
5595 * gst_value_compare() but allows to save time determining the compare function
5598 * Returns: comparison result
5601 gst_value_compare_with_func (const GValue * value1, const GValue * value2,
5602 GstValueCompareFunc compare)
5606 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
5607 return GST_VALUE_UNORDERED;
5609 return compare (value1, value2);
5615 * gst_value_can_union:
5616 * @value1: a value to union
5617 * @value2: another value to union
5619 * Determines if @value1 and @value2 can be non-trivially unioned.
5620 * Any two values can be trivially unioned by adding both of them
5621 * to a GstValueList. However, certain types have the possibility
5622 * to be unioned in a simpler way. For example, an integer range
5623 * and an integer can be unioned if the integer is a subset of the
5624 * integer range. If there is the possibility that two values can
5625 * be unioned, this function returns %TRUE.
5627 * Returns: %TRUE if there is a function allowing the two values to
5631 gst_value_can_union (const GValue * value1, const GValue * value2)
5633 GstValueUnionInfo *union_info;
5636 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5637 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5639 len = gst_value_union_funcs->len;
5641 for (i = 0; i < len; i++) {
5642 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5643 if (union_info->type1 == G_VALUE_TYPE (value1) &&
5644 union_info->type2 == G_VALUE_TYPE (value2))
5646 if (union_info->type1 == G_VALUE_TYPE (value2) &&
5647 union_info->type2 == G_VALUE_TYPE (value1))
5656 * @dest: (out caller-allocates): the destination value
5657 * @value1: a value to union
5658 * @value2: another value to union
5660 * Creates a GValue corresponding to the union of @value1 and @value2.
5662 * Returns: %TRUE if the union succeeded.
5665 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
5667 const GstValueUnionInfo *union_info;
5671 g_return_val_if_fail (dest != NULL, FALSE);
5672 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5673 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5674 g_return_val_if_fail (gst_value_list_or_array_are_compatible (value1, value2),
5677 len = gst_value_union_funcs->len;
5678 type1 = G_VALUE_TYPE (value1);
5679 type2 = G_VALUE_TYPE (value2);
5681 for (i = 0; i < len; i++) {
5682 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
5683 if (union_info->type1 == type1 && union_info->type2 == type2) {
5684 return union_info->func (dest, value1, value2);
5686 if (union_info->type1 == type2 && union_info->type2 == type1) {
5687 return union_info->func (dest, value2, value1);
5691 gst_value_list_concat (dest, value1, value2);
5695 /* gst_value_register_union_func: (skip)
5696 * @type1: a type to union
5697 * @type2: another type to union
5698 * @func: a function that implements creating a union between the two types
5700 * Registers a union function that can create a union between #GValue items
5701 * of the type @type1 and @type2.
5703 * Union functions should be registered at startup before any pipelines are
5704 * started, as gst_value_register_union_func() is not thread-safe and cannot
5705 * be used at the same time as gst_value_union() or gst_value_can_union().
5708 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
5710 GstValueUnionInfo union_info;
5712 union_info.type1 = type1;
5713 union_info.type2 = type2;
5714 union_info.func = func;
5716 g_array_append_val (gst_value_union_funcs, union_info);
5722 * gst_value_can_intersect:
5723 * @value1: a value to intersect
5724 * @value2: another value to intersect
5726 * Determines if intersecting two values will produce a valid result.
5727 * Two values will produce a valid intersection if they have the same
5730 * Returns: %TRUE if the values can intersect
5733 gst_value_can_intersect (const GValue * value1, const GValue * value2)
5735 GstValueIntersectInfo *intersect_info;
5739 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5740 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5742 type1 = G_VALUE_TYPE (value1);
5743 type2 = G_VALUE_TYPE (value2);
5745 /* practically all GstValue types have a compare function (_can_compare=TRUE)
5746 * GstStructure and GstCaps have not, but are intersectable */
5751 if (type1 == GST_TYPE_LIST || type2 == GST_TYPE_LIST)
5754 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5755 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5756 GType type1, type2, flagset_type;
5758 type1 = G_VALUE_TYPE (value1);
5759 type2 = G_VALUE_TYPE (value2);
5760 flagset_type = GST_TYPE_FLAG_SET;
5762 /* Allow intersection with the generic FlagSet type, on one
5763 * side, but not 2 different subtypes - that makes no sense */
5764 if (type1 == type2 || type1 == flagset_type || type2 == flagset_type)
5768 /* check registered intersect functions */
5769 len = gst_value_intersect_funcs->len;
5770 for (i = 0; i < len; i++) {
5771 intersect_info = &g_array_index (gst_value_intersect_funcs,
5772 GstValueIntersectInfo, i);
5773 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) ||
5774 (intersect_info->type1 == type2 && intersect_info->type2 == type1))
5778 return gst_value_can_compare_unchecked (value1, value2);
5782 * gst_value_intersect:
5783 * @dest: (out caller-allocates) (transfer full) (allow-none):
5784 * a uninitialized #GValue that will hold the calculated
5785 * intersection value. May be %NULL if the resulting set if not
5787 * @value1: a value to intersect
5788 * @value2: another value to intersect
5790 * Calculates the intersection of two values. If the values have
5791 * a non-empty intersection, the value representing the intersection
5792 * is placed in @dest, unless %NULL. If the intersection is non-empty,
5793 * @dest is not modified.
5795 * Returns: %TRUE if the intersection is non-empty
5798 gst_value_intersect (GValue * dest, const GValue * value1,
5799 const GValue * value2)
5801 GstValueIntersectInfo *intersect_info;
5805 g_return_val_if_fail (G_IS_VALUE (value1), FALSE);
5806 g_return_val_if_fail (G_IS_VALUE (value2), FALSE);
5808 type1 = G_VALUE_TYPE (value1);
5809 type2 = G_VALUE_TYPE (value2);
5811 /* special cases first */
5812 if (type1 == GST_TYPE_LIST)
5813 return gst_value_intersect_list (dest, value1, value2);
5814 if (type2 == GST_TYPE_LIST)
5815 return gst_value_intersect_list (dest, value2, value1);
5817 if (_gst_value_compare_nolist (value1, value2) == GST_VALUE_EQUAL) {
5819 gst_value_init_and_copy (dest, value1);
5823 len = gst_value_intersect_funcs->len;
5824 for (i = 0; i < len; i++) {
5825 intersect_info = &g_array_index (gst_value_intersect_funcs,
5826 GstValueIntersectInfo, i);
5827 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) {
5828 return intersect_info->func (dest, value1, value2);
5830 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) {
5831 return intersect_info->func (dest, value2, value1);
5835 /* Failed to find a direct intersection, check if these are
5836 * GstFlagSet sub-types. */
5837 if (G_UNLIKELY (GST_VALUE_HOLDS_FLAG_SET (value1) &&
5838 GST_VALUE_HOLDS_FLAG_SET (value2))) {
5839 return gst_value_intersect_flagset_flagset (dest, value1, value2);
5847 /* gst_value_register_intersect_func: (skip)
5848 * @type1: the first type to intersect
5849 * @type2: the second type to intersect
5850 * @func: the intersection function
5852 * Registers a function that is called to calculate the intersection
5853 * of the values having the types @type1 and @type2.
5855 * Intersect functions should be registered at startup before any pipelines are
5856 * started, as gst_value_register_intersect_func() is not thread-safe and
5857 * cannot be used at the same time as gst_value_intersect() or
5858 * gst_value_can_intersect().
5861 gst_value_register_intersect_func (GType type1, GType type2,
5862 GstValueIntersectFunc func)
5864 GstValueIntersectInfo intersect_info;
5866 intersect_info.type1 = type1;
5867 intersect_info.type2 = type2;
5868 intersect_info.func = func;
5870 g_array_append_val (gst_value_intersect_funcs, intersect_info);
5877 * gst_value_subtract:
5878 * @dest: (out caller-allocates) (allow-none): the destination value
5879 * for the result if the subtraction is not empty. May be %NULL,
5880 * in which case the resulting set will not be computed, which can
5881 * give a fair speedup.
5882 * @minuend: the value to subtract from
5883 * @subtrahend: the value to subtract
5885 * Subtracts @subtrahend from @minuend and stores the result in @dest.
5886 * Note that this means subtraction as in sets, not as in mathematics.
5888 * Returns: %TRUE if the subtraction is not empty
5891 gst_value_subtract (GValue * dest, const GValue * minuend,
5892 const GValue * subtrahend)
5894 GstValueSubtractInfo *info;
5898 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5899 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5901 mtype = G_VALUE_TYPE (minuend);
5902 stype = G_VALUE_TYPE (subtrahend);
5904 /* special cases first */
5905 if (mtype == GST_TYPE_LIST)
5906 return gst_value_subtract_from_list (dest, minuend, subtrahend);
5907 if (stype == GST_TYPE_LIST)
5908 return gst_value_subtract_list (dest, minuend, subtrahend);
5910 len = gst_value_subtract_funcs->len;
5911 for (i = 0; i < len; i++) {
5912 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5913 if (info->minuend == mtype && info->subtrahend == stype) {
5914 return info->func (dest, minuend, subtrahend);
5918 if (_gst_value_compare_nolist (minuend, subtrahend) != GST_VALUE_EQUAL) {
5920 gst_value_init_and_copy (dest, minuend);
5929 gst_value_subtract (GValue * dest, const GValue * minuend,
5930 const GValue * subtrahend)
5932 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
5934 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
5935 gst_value_serialize (subtrahend),
5936 ret ? gst_value_serialize (dest) : "---");
5942 * gst_value_can_subtract:
5943 * @minuend: the value to subtract from
5944 * @subtrahend: the value to subtract
5946 * Checks if it's possible to subtract @subtrahend from @minuend.
5948 * Returns: %TRUE if a subtraction is possible
5951 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
5953 GstValueSubtractInfo *info;
5957 g_return_val_if_fail (G_IS_VALUE (minuend), FALSE);
5958 g_return_val_if_fail (G_IS_VALUE (subtrahend), FALSE);
5960 mtype = G_VALUE_TYPE (minuend);
5961 stype = G_VALUE_TYPE (subtrahend);
5964 if (mtype == GST_TYPE_LIST || stype == GST_TYPE_LIST)
5966 if (mtype == GST_TYPE_STRUCTURE || stype == GST_TYPE_STRUCTURE)
5969 len = gst_value_subtract_funcs->len;
5970 for (i = 0; i < len; i++) {
5971 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
5972 if (info->minuend == mtype && info->subtrahend == stype)
5976 return gst_value_can_compare_unchecked (minuend, subtrahend);
5979 /* gst_value_register_subtract_func: (skip)
5980 * @minuend_type: type of the minuend
5981 * @subtrahend_type: type of the subtrahend
5982 * @func: function to use
5984 * Registers @func as a function capable of subtracting the values of
5985 * @subtrahend_type from values of @minuend_type.
5987 * Subtract functions should be registered at startup before any pipelines are
5988 * started, as gst_value_register_subtract_func() is not thread-safe and
5989 * cannot be used at the same time as gst_value_subtract().
5992 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
5993 GstValueSubtractFunc func)
5995 GstValueSubtractInfo info;
5997 g_return_if_fail (!gst_type_is_fixed (minuend_type)
5998 || !gst_type_is_fixed (subtrahend_type));
6000 info.minuend = minuend_type;
6001 info.subtrahend = subtrahend_type;
6004 g_array_append_val (gst_value_subtract_funcs, info);
6008 * gst_value_register:
6009 * @table: structure containing functions to register
6011 * Registers functions to perform calculations on #GValue items of a given
6012 * type. Each type can only be added once.
6015 gst_value_register (const GstValueTable * table)
6017 GstValueTable *found;
6019 g_return_if_fail (table != NULL);
6021 g_array_append_val (gst_value_table, *table);
6023 found = gst_value_hash_lookup_type (table->type);
6025 g_warning ("adding type %s multiple times", g_type_name (table->type));
6027 /* FIXME: we're not really doing the const justice, we assume the table is
6029 gst_value_hash_add_type (table->type, table);
6033 * gst_value_init_and_copy:
6034 * @dest: (out caller-allocates): the target value
6035 * @src: the source value
6037 * Initialises the target value to be of the same type as source and then copies
6038 * the contents from source to target.
6041 gst_value_init_and_copy (GValue * dest, const GValue * src)
6043 g_return_if_fail (G_IS_VALUE (src));
6044 g_return_if_fail (dest != NULL);
6046 g_value_init (dest, G_VALUE_TYPE (src));
6047 g_value_copy (src, dest);
6050 /* move src into dest and clear src */
6052 gst_value_move (GValue * dest, GValue * src)
6054 g_assert (G_IS_VALUE (src));
6055 g_assert (dest != NULL);
6058 memset (src, 0, sizeof (GValue));
6062 * gst_value_serialize:
6063 * @value: a #GValue to serialize
6065 * tries to transform the given @value into a string representation that allows
6066 * getting back this string later on using gst_value_deserialize().
6068 * Free-function: g_free
6070 * Returns: (transfer full) (nullable): the serialization for @value
6071 * or %NULL if none exists
6074 gst_value_serialize (const GValue * value)
6077 GValue s_val = { 0 };
6078 GstValueTable *table, *best;
6082 g_return_val_if_fail (G_IS_VALUE (value), NULL);
6084 type = G_VALUE_TYPE (value);
6086 best = gst_value_hash_lookup_type (type);
6088 if (G_UNLIKELY (!best || !best->serialize)) {
6089 len = gst_value_table->len;
6091 for (i = 0; i < len; i++) {
6092 table = &g_array_index (gst_value_table, GstValueTable, i);
6093 if (table->serialize && g_type_is_a (type, table->type)) {
6094 if (!best || g_type_is_a (table->type, best->type))
6099 if (G_LIKELY (best))
6100 return best->serialize (value);
6102 g_value_init (&s_val, G_TYPE_STRING);
6103 if (g_value_transform (value, &s_val)) {
6104 s = gst_string_wrap (g_value_get_string (&s_val));
6108 g_value_unset (&s_val);
6114 * gst_value_deserialize:
6115 * @dest: (out caller-allocates): #GValue to fill with contents of
6117 * @src: string to deserialize
6119 * Tries to deserialize a string into the type specified by the given GValue.
6120 * If the operation succeeds, %TRUE is returned, %FALSE otherwise.
6122 * Returns: %TRUE on success
6125 gst_value_deserialize (GValue * dest, const gchar * src)
6127 GstValueTable *table, *best;
6131 g_return_val_if_fail (src != NULL, FALSE);
6132 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
6134 type = G_VALUE_TYPE (dest);
6136 best = gst_value_hash_lookup_type (type);
6137 if (G_UNLIKELY (!best || !best->deserialize)) {
6138 len = gst_value_table->len;
6140 for (i = 0; i < len; i++) {
6141 table = &g_array_index (gst_value_table, GstValueTable, i);
6142 if (table->deserialize && g_type_is_a (type, table->type)) {
6143 if (!best || g_type_is_a (table->type, best->type))
6148 if (G_LIKELY (best))
6149 return best->deserialize (dest, src);
6155 structure_field_is_fixed (GQuark field_id, const GValue * val,
6158 return gst_value_is_fixed (val);
6162 * gst_value_is_fixed:
6163 * @value: the #GValue to check
6165 * Tests if the given GValue, if available in a GstStructure (or any other
6166 * container) contains a "fixed" (which means: one value) or an "unfixed"
6167 * (which means: multiple possible values, such as data lists or data
6170 * Returns: true if the value is "fixed".
6174 gst_value_is_fixed (const GValue * value)
6178 g_return_val_if_fail (G_IS_VALUE (value), FALSE);
6180 type = G_VALUE_TYPE (value);
6182 /* the most common types are just basic plain glib types */
6183 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
6187 if (type == GST_TYPE_ARRAY) {
6191 /* check recursively */
6192 size = gst_value_array_get_size (value);
6193 for (n = 0; n < size; n++) {
6194 kid = gst_value_array_get_value (value, n);
6195 if (!gst_value_is_fixed (kid))
6199 } else if (GST_VALUE_HOLDS_FLAG_SET (value)) {
6200 /* Flagsets are only fixed if there are no 'don't care' bits */
6201 return (gst_value_get_flagset_mask (value) == GST_FLAG_SET_MASK_EXACT);
6202 } else if (GST_VALUE_HOLDS_STRUCTURE (value)) {
6203 return gst_structure_foreach (gst_value_get_structure (value),
6204 structure_field_is_fixed, NULL);
6206 return gst_type_is_fixed (type);
6211 * @dest: the #GValue destination
6212 * @src: the #GValue to fixate
6214 * Fixate @src into a new value @dest.
6215 * For ranges, the first element is taken. For lists and arrays, the
6216 * first item is fixated and returned.
6217 * If @src is already fixed, this function returns %FALSE.
6219 * Returns: %TRUE if @dest contains a fixated version of @src.
6222 gst_value_fixate (GValue * dest, const GValue * src)
6224 g_return_val_if_fail (G_IS_VALUE (src), FALSE);
6225 g_return_val_if_fail (dest != NULL, FALSE);
6227 if (G_VALUE_TYPE (src) == GST_TYPE_INT_RANGE) {
6228 g_value_init (dest, G_TYPE_INT);
6229 g_value_set_int (dest, gst_value_get_int_range_min (src));
6230 } else if (G_VALUE_TYPE (src) == GST_TYPE_DOUBLE_RANGE) {
6231 g_value_init (dest, G_TYPE_DOUBLE);
6232 g_value_set_double (dest, gst_value_get_double_range_min (src));
6233 } else if (G_VALUE_TYPE (src) == GST_TYPE_FRACTION_RANGE) {
6234 gst_value_init_and_copy (dest, gst_value_get_fraction_range_min (src));
6235 } else if (G_VALUE_TYPE (src) == GST_TYPE_LIST) {
6236 GValue temp = { 0 };
6238 /* list could be empty */
6239 if (gst_value_list_get_size (src) <= 0)
6242 gst_value_init_and_copy (&temp, gst_value_list_get_value (src, 0));
6244 if (!gst_value_fixate (dest, &temp)) {
6245 gst_value_move (dest, &temp);
6247 g_value_unset (&temp);
6249 } else if (G_VALUE_TYPE (src) == GST_TYPE_ARRAY) {
6250 gboolean res = FALSE;
6253 len = gst_value_array_get_size (src);
6254 g_value_init (dest, GST_TYPE_ARRAY);
6255 for (n = 0; n < len; n++) {
6257 const GValue *orig_kid = gst_value_array_get_value (src, n);
6259 if (!gst_value_fixate (&kid, orig_kid))
6260 gst_value_init_and_copy (&kid, orig_kid);
6263 _gst_value_array_append_and_take_value (dest, &kid);
6267 g_value_unset (dest);
6270 } else if (GST_VALUE_HOLDS_FLAG_SET (src)) {
6273 if (gst_value_get_flagset_mask (src) == GST_FLAG_SET_MASK_EXACT)
6274 return FALSE; /* Already fixed */
6276 flags = gst_value_get_flagset_flags (src);
6277 g_value_init (dest, G_VALUE_TYPE (src));
6278 gst_value_set_flagset (dest, flags, GST_FLAG_SET_MASK_EXACT);
6280 } else if (GST_VALUE_HOLDS_STRUCTURE (src)) {
6281 const GstStructure *str = (GstStructure *) gst_value_get_structure (src);
6287 kid = gst_structure_copy (str);
6288 gst_structure_fixate (kid);
6289 g_value_init (dest, GST_TYPE_STRUCTURE);
6290 gst_value_set_structure (dest, kid);
6291 gst_structure_free (kid);
6304 /* helper functions */
6306 gst_value_init_fraction (GValue * value)
6308 value->data[0].v_int = 0;
6309 value->data[1].v_int = 1;
6313 gst_value_copy_fraction (const GValue * src_value, GValue * dest_value)
6315 dest_value->data[0].v_int = src_value->data[0].v_int;
6316 dest_value->data[1].v_int = src_value->data[1].v_int;
6320 gst_value_collect_fraction (GValue * value, guint n_collect_values,
6321 GTypeCValue * collect_values, guint collect_flags)
6323 if (n_collect_values != 2)
6324 return g_strdup_printf ("not enough value locations for `%s' passed",
6325 G_VALUE_TYPE_NAME (value));
6326 if (collect_values[1].v_int == 0)
6327 return g_strdup_printf ("passed '0' as denominator for `%s'",
6328 G_VALUE_TYPE_NAME (value));
6329 if (collect_values[0].v_int < -G_MAXINT)
6332 ("passed value smaller than -G_MAXINT as numerator for `%s'",
6333 G_VALUE_TYPE_NAME (value));
6334 if (collect_values[1].v_int < -G_MAXINT)
6337 ("passed value smaller than -G_MAXINT as denominator for `%s'",
6338 G_VALUE_TYPE_NAME (value));
6340 gst_value_set_fraction (value,
6341 collect_values[0].v_int, collect_values[1].v_int);
6347 gst_value_lcopy_fraction (const GValue * value, guint n_collect_values,
6348 GTypeCValue * collect_values, guint collect_flags)
6350 gint *numerator = collect_values[0].v_pointer;
6351 gint *denominator = collect_values[1].v_pointer;
6354 return g_strdup_printf ("numerator for `%s' passed as NULL",
6355 G_VALUE_TYPE_NAME (value));
6357 return g_strdup_printf ("denominator for `%s' passed as NULL",
6358 G_VALUE_TYPE_NAME (value));
6360 *numerator = value->data[0].v_int;
6361 *denominator = value->data[1].v_int;
6367 * gst_value_set_fraction:
6368 * @value: a GValue initialized to #GST_TYPE_FRACTION
6369 * @numerator: the numerator of the fraction
6370 * @denominator: the denominator of the fraction
6372 * Sets @value to the fraction specified by @numerator over @denominator.
6373 * The fraction gets reduced to the smallest numerator and denominator,
6374 * and if necessary the sign is moved to the numerator.
6377 gst_value_set_fraction (GValue * value, gint numerator, gint denominator)
6381 g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value));
6382 g_return_if_fail (denominator != 0);
6383 g_return_if_fail (denominator >= -G_MAXINT);
6384 g_return_if_fail (numerator >= -G_MAXINT);
6386 /* normalize sign */
6387 if (denominator < 0) {
6388 numerator = -numerator;
6389 denominator = -denominator;
6392 /* check for reduction */
6393 gcd = gst_util_greatest_common_divisor (numerator, denominator);
6399 g_assert (denominator > 0);
6401 value->data[0].v_int = numerator;
6402 value->data[1].v_int = denominator;
6406 * gst_value_get_fraction_numerator:
6407 * @value: a GValue initialized to #GST_TYPE_FRACTION
6409 * Gets the numerator of the fraction specified by @value.
6411 * Returns: the numerator of the fraction.
6414 gst_value_get_fraction_numerator (const GValue * value)
6416 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 0);
6418 return value->data[0].v_int;
6422 * gst_value_get_fraction_denominator:
6423 * @value: a GValue initialized to #GST_TYPE_FRACTION
6425 * Gets the denominator of the fraction specified by @value.
6427 * Returns: the denominator of the fraction.
6430 gst_value_get_fraction_denominator (const GValue * value)
6432 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (value), 1);
6434 return value->data[1].v_int;
6438 * gst_value_fraction_multiply:
6439 * @product: a GValue initialized to #GST_TYPE_FRACTION
6440 * @factor1: a GValue initialized to #GST_TYPE_FRACTION
6441 * @factor2: a GValue initialized to #GST_TYPE_FRACTION
6443 * Multiplies the two #GValue items containing a #GST_TYPE_FRACTION and sets
6444 * @product to the product of the two fractions.
6446 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6449 gst_value_fraction_multiply (GValue * product, const GValue * factor1,
6450 const GValue * factor2)
6452 gint n1, n2, d1, d2;
6455 g_return_val_if_fail (product != NULL, FALSE);
6456 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE);
6457 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE);
6459 n1 = factor1->data[0].v_int;
6460 n2 = factor2->data[0].v_int;
6461 d1 = factor1->data[1].v_int;
6462 d2 = factor2->data[1].v_int;
6464 if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
6467 gst_value_set_fraction (product, res_n, res_d);
6473 * gst_value_fraction_subtract:
6474 * @dest: a GValue initialized to #GST_TYPE_FRACTION
6475 * @minuend: a GValue initialized to #GST_TYPE_FRACTION
6476 * @subtrahend: a GValue initialized to #GST_TYPE_FRACTION
6478 * Subtracts the @subtrahend from the @minuend and sets @dest to the result.
6480 * Returns: %FALSE in case of an error (like integer overflow), %TRUE otherwise.
6483 gst_value_fraction_subtract (GValue * dest,
6484 const GValue * minuend, const GValue * subtrahend)
6486 gint n1, n2, d1, d2;
6489 g_return_val_if_fail (dest != NULL, FALSE);
6490 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE);
6491 g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE);
6493 n1 = minuend->data[0].v_int;
6494 n2 = subtrahend->data[0].v_int;
6495 d1 = minuend->data[1].v_int;
6496 d2 = subtrahend->data[1].v_int;
6498 if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d))
6500 gst_value_set_fraction (dest, res_n, res_d);
6506 gst_value_serialize_fraction (const GValue * value)
6508 gint32 numerator = value->data[0].v_int;
6509 gint32 denominator = value->data[1].v_int;
6510 gboolean positive = TRUE;
6512 /* get the sign and make components absolute */
6513 if (numerator < 0) {
6514 numerator = -numerator;
6515 positive = !positive;
6517 if (denominator < 0) {
6518 denominator = -denominator;
6519 positive = !positive;
6522 return g_strdup_printf ("%s%d/%d",
6523 positive ? "" : "-", numerator, denominator);
6527 gst_value_deserialize_fraction (GValue * dest, const gchar * s)
6532 if (G_UNLIKELY (s == NULL))
6535 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FRACTION (dest)))
6538 if (sscanf (s, "%d/%d%n", &num, &den, &num_chars) >= 2) {
6539 if (s[num_chars] != 0)
6544 gst_value_set_fraction (dest, num, den);
6546 } else if (g_ascii_strcasecmp (s, "1/max") == 0) {
6547 gst_value_set_fraction (dest, 1, G_MAXINT);
6549 } else if (sscanf (s, "%d%n", &num, &num_chars) >= 1) {
6550 if (s[num_chars] != 0)
6552 gst_value_set_fraction (dest, num, 1);
6554 } else if (g_ascii_strcasecmp (s, "min") == 0) {
6555 gst_value_set_fraction (dest, -G_MAXINT, 1);
6557 } else if (g_ascii_strcasecmp (s, "max") == 0) {
6558 gst_value_set_fraction (dest, G_MAXINT, 1);
6566 gst_value_transform_fraction_string (const GValue * src_value,
6567 GValue * dest_value)
6569 dest_value->data[0].v_pointer = gst_value_serialize_fraction (src_value);
6573 gst_value_transform_string_fraction (const GValue * src_value,
6574 GValue * dest_value)
6576 if (!gst_value_deserialize_fraction (dest_value,
6577 src_value->data[0].v_pointer))
6578 /* If the deserialize fails, ensure we leave the fraction in a
6579 * valid, if incorrect, state */
6580 gst_value_set_fraction (dest_value, 0, 1);
6584 gst_value_transform_double_fraction (const GValue * src_value,
6585 GValue * dest_value)
6587 gdouble src = g_value_get_double (src_value);
6590 gst_util_double_to_fraction (src, &n, &d);
6591 gst_value_set_fraction (dest_value, n, d);
6595 gst_value_transform_float_fraction (const GValue * src_value,
6596 GValue * dest_value)
6598 gfloat src = g_value_get_float (src_value);
6601 gst_util_double_to_fraction (src, &n, &d);
6602 gst_value_set_fraction (dest_value, n, d);
6606 gst_value_transform_fraction_double (const GValue * src_value,
6607 GValue * dest_value)
6609 dest_value->data[0].v_double = ((double) src_value->data[0].v_int) /
6610 ((double) src_value->data[1].v_int);
6614 gst_value_transform_fraction_float (const GValue * src_value,
6615 GValue * dest_value)
6617 dest_value->data[0].v_float = ((float) src_value->data[0].v_int) /
6618 ((float) src_value->data[1].v_int);
6622 gst_value_compare_fraction (const GValue * value1, const GValue * value2)
6628 n1 = value1->data[0].v_int;
6629 n2 = value2->data[0].v_int;
6630 d1 = value1->data[1].v_int;
6631 d2 = value2->data[1].v_int;
6633 /* fractions are reduced when set, so we can quickly see if they're equal */
6634 if (n1 == n2 && d1 == d2)
6635 return GST_VALUE_EQUAL;
6637 if (d1 == 0 && d2 == 0)
6638 return GST_VALUE_UNORDERED;
6640 return GST_VALUE_GREATER_THAN;
6642 return GST_VALUE_LESS_THAN;
6644 ret = gst_util_fraction_compare (n1, d1, n2, d2);
6646 return GST_VALUE_LESS_THAN;
6648 return GST_VALUE_GREATER_THAN;
6650 /* Equality can't happen here because we check for that
6652 g_return_val_if_reached (GST_VALUE_UNORDERED);
6660 gst_value_compare_date (const GValue * value1, const GValue * value2)
6662 const GDate *date1 = (const GDate *) g_value_get_boxed (value1);
6663 const GDate *date2 = (const GDate *) g_value_get_boxed (value2);
6667 return GST_VALUE_EQUAL;
6669 if ((date1 == NULL || !g_date_valid (date1))
6670 && (date2 != NULL && g_date_valid (date2))) {
6671 return GST_VALUE_LESS_THAN;
6674 if ((date2 == NULL || !g_date_valid (date2))
6675 && (date1 != NULL && g_date_valid (date1))) {
6676 return GST_VALUE_GREATER_THAN;
6679 if (date1 == NULL || date2 == NULL || !g_date_valid (date1)
6680 || !g_date_valid (date2)) {
6681 return GST_VALUE_UNORDERED;
6684 j1 = g_date_get_julian (date1);
6685 j2 = g_date_get_julian (date2);
6688 return GST_VALUE_EQUAL;
6690 return GST_VALUE_LESS_THAN;
6692 return GST_VALUE_GREATER_THAN;
6696 gst_value_serialize_date (const GValue * val)
6698 const GDate *date = (const GDate *) g_value_get_boxed (val);
6700 if (date == NULL || !g_date_valid (date))
6701 return g_strdup ("9999-99-99");
6703 return g_strdup_printf ("%04u-%02u-%02u", g_date_get_year (date),
6704 g_date_get_month (date), g_date_get_day (date));
6708 gst_value_deserialize_date (GValue * dest, const gchar * s)
6710 guint year, month, day;
6712 if (!s || sscanf (s, "%04u-%02u-%02u", &year, &month, &day) != 3)
6715 if (!g_date_valid_dmy (day, month, year))
6718 g_value_take_boxed (dest, g_date_new_dmy (day, month, year));
6727 gst_value_compare_date_time (const GValue * value1, const GValue * value2)
6729 const GstDateTime *date1 = (const GstDateTime *) g_value_get_boxed (value1);
6730 const GstDateTime *date2 = (const GstDateTime *) g_value_get_boxed (value2);
6733 return GST_VALUE_EQUAL;
6735 if ((date1 == NULL) && (date2 != NULL)) {
6736 return GST_VALUE_LESS_THAN;
6738 if ((date2 == NULL) && (date1 != NULL)) {
6739 return GST_VALUE_LESS_THAN;
6742 /* returns GST_VALUE_* */
6743 return __gst_date_time_compare (date1, date2);
6747 gst_value_serialize_date_time (const GValue * val)
6749 GstDateTime *date = (GstDateTime *) g_value_get_boxed (val);
6752 return g_strdup ("null");
6754 return __gst_date_time_serialize (date, TRUE);
6758 gst_value_deserialize_date_time (GValue * dest, const gchar * s)
6760 GstDateTime *datetime;
6762 if (!s || strcmp (s, "null") == 0) {
6766 datetime = gst_date_time_new_from_iso8601_string (s);
6767 if (datetime != NULL) {
6768 g_value_take_boxed (dest, datetime);
6771 GST_WARNING ("Failed to deserialize date time string '%s'", s);
6776 gst_value_transform_date_string (const GValue * src_value, GValue * dest_value)
6778 dest_value->data[0].v_pointer = gst_value_serialize_date (src_value);
6782 gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
6784 gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
6792 /* helper functions */
6794 gst_value_init_bitmask (GValue * value)
6796 value->data[0].v_uint64 = 0;
6800 gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
6802 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6806 gst_value_collect_bitmask (GValue * value, guint n_collect_values,
6807 GTypeCValue * collect_values, guint collect_flags)
6809 if (n_collect_values != 1)
6810 return g_strdup_printf ("not enough value locations for `%s' passed",
6811 G_VALUE_TYPE_NAME (value));
6813 gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
6819 gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
6820 GTypeCValue * collect_values, guint collect_flags)
6822 guint64 *bitmask = collect_values[0].v_pointer;
6825 return g_strdup_printf ("value for `%s' passed as NULL",
6826 G_VALUE_TYPE_NAME (value));
6828 *bitmask = value->data[0].v_uint64;
6834 * gst_value_set_bitmask:
6835 * @value: a GValue initialized to #GST_TYPE_BITMASK
6836 * @bitmask: the bitmask
6838 * Sets @value to the bitmask specified by @bitmask.
6841 gst_value_set_bitmask (GValue * value, guint64 bitmask)
6843 g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
6845 value->data[0].v_uint64 = bitmask;
6849 * gst_value_get_bitmask:
6850 * @value: a GValue initialized to #GST_TYPE_BITMASK
6852 * Gets the bitmask specified by @value.
6854 * Returns: the bitmask.
6857 gst_value_get_bitmask (const GValue * value)
6859 g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
6861 return value->data[0].v_uint64;
6865 gst_value_serialize_bitmask (const GValue * value)
6867 guint64 bitmask = value->data[0].v_uint64;
6869 return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
6873 gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
6875 gchar *endptr = NULL;
6878 if (G_UNLIKELY (s == NULL))
6881 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
6885 val = g_ascii_strtoull (s, &endptr, 16);
6886 if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
6888 if (val == 0 && endptr == s)
6891 gst_value_set_bitmask (dest, val);
6897 gst_value_transform_bitmask_string (const GValue * src_value,
6898 GValue * dest_value)
6900 dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
6904 gst_value_transform_string_bitmask (const GValue * src_value,
6905 GValue * dest_value)
6907 if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
6908 gst_value_set_bitmask (dest_value, 0);
6912 gst_value_transform_uint64_bitmask (const GValue * src_value,
6913 GValue * dest_value)
6915 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6919 gst_value_transform_bitmask_uint64 (const GValue * src_value,
6920 GValue * dest_value)
6922 dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
6926 gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
6930 v1 = value1->data[0].v_uint64;
6931 v2 = value2->data[0].v_uint64;
6934 return GST_VALUE_EQUAL;
6936 return GST_VALUE_UNORDERED;
6943 /* helper functions */
6945 gst_value_init_flagset (GValue * value)
6947 value->data[0].v_uint = 0;
6948 value->data[1].v_uint = 0;
6952 gst_value_copy_flagset (const GValue * src_value, GValue * dest_value)
6954 dest_value->data[0].v_uint = src_value->data[0].v_uint;
6955 dest_value->data[1].v_uint = src_value->data[1].v_uint;
6959 gst_value_collect_flagset (GValue * value, guint n_collect_values,
6960 GTypeCValue * collect_values, guint collect_flags)
6962 if (n_collect_values != 2)
6963 return g_strdup_printf ("not enough value locations for `%s' passed",
6964 G_VALUE_TYPE_NAME (value));
6966 gst_value_set_flagset (value,
6967 (guint) collect_values[0].v_int, (guint) collect_values[1].v_int);
6973 gst_value_lcopy_flagset (const GValue * value, guint n_collect_values,
6974 GTypeCValue * collect_values, guint collect_flags)
6976 guint *flags = collect_values[0].v_pointer;
6977 guint *mask = collect_values[1].v_pointer;
6979 *flags = value->data[0].v_uint;
6980 *mask = value->data[1].v_uint;
6986 * gst_value_set_flagset:
6987 * @value: a GValue initialized to %GST_TYPE_FLAG_SET
6988 * @flags: The value of the flags set or unset
6989 * @mask: The mask indicate which flags bits must match for comparisons
6991 * Sets @value to the flags and mask values provided in @flags and @mask.
6992 * The @flags value indicates the values of flags, the @mask represents
6993 * which bits in the flag value have been set, and which are "don't care"
6998 gst_value_set_flagset (GValue * value, guint flags, guint mask)
7000 g_return_if_fail (GST_VALUE_HOLDS_FLAG_SET (value));
7002 /* Normalise and only keep flags mentioned in the mask */
7003 value->data[0].v_uint = flags & mask;
7004 value->data[1].v_uint = mask;
7008 * gst_value_get_flagset_flags:
7009 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7011 * Retrieve the flags field of a GstFlagSet @value.
7013 * Returns: the flags field of the flagset instance.
7018 gst_value_get_flagset_flags (const GValue * value)
7020 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 0);
7022 return value->data[0].v_uint;
7026 * gst_value_get_flagset_mask:
7027 * @value: a GValue initialized to #GST_TYPE_FLAG_SET
7029 * Retrieve the mask field of a GstFlagSet @value.
7031 * Returns: the mask field of the flagset instance.
7036 gst_value_get_flagset_mask (const GValue * value)
7038 g_return_val_if_fail (GST_VALUE_HOLDS_FLAG_SET (value), 1);
7040 return value->data[1].v_uint;
7044 gst_value_serialize_flagset (const GValue * value)
7046 guint flags = value->data[0].v_uint;
7047 guint mask = value->data[1].v_uint;
7048 GstFlagSetClass *set_klass =
7049 (GstFlagSetClass *) g_type_class_ref (G_VALUE_TYPE (value));
7052 result = g_strdup_printf ("%x:%x", flags, mask);
7054 /* If this flag set class has an associated GFlags GType, and some
7055 * bits in the mask, serialize the bits in human-readable form to
7057 if (mask && set_klass->flags_type) {
7058 GFlagsClass *flags_klass =
7059 (GFlagsClass *) (g_type_class_ref (set_klass->flags_type));
7062 gboolean first = TRUE;
7064 g_return_val_if_fail (flags_klass, NULL);
7066 /* some bits in the mask are set, so serialize one by one, according
7067 * to whether that bit is set or cleared in the flags value */
7069 fl = g_flags_get_first_value (flags_klass, mask);
7071 /* No more bits match in the flags mask - time to stop */
7076 tmp = g_strconcat (result,
7078 (flags & fl->value) ? "+" : "/", fl->value_nick, NULL);
7086 g_type_class_unref (flags_klass);
7089 g_type_class_unref (set_klass);
7095 is_valid_flags_string (const gchar * s)
7097 /* We're looking to match +this/that+other-thing/not-this-thing type strings */
7098 return g_regex_match_simple ("^([\\+\\/][\\w\\d-]+)+$", s, G_REGEX_CASELESS,
7103 gst_value_deserialize_flagset (GValue * dest, const gchar * s)
7105 gboolean res = FALSE;
7109 if (G_UNLIKELY (s == NULL))
7112 if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_FLAG_SET (dest)))
7115 /* Flagset strings look like %x:%x - hex flags : hex bitmask,
7116 * 32-bit each, or like a concatenated list of flag nicks,
7117 * with either '+' or '/' in front. The first form
7118 * may optionally be followed by ':' and a set of text flag descriptions
7119 * for easier debugging */
7121 /* Try and interpret as hex form first, as it's the most efficient */
7122 /* Read the flags first */
7123 flags = strtoul (s, &next, 16);
7124 if (G_UNLIKELY ((flags == 0 && errno == EINVAL) || s == next))
7125 goto try_as_flags_string;
7126 /* Next char should be a colon */
7132 mask = strtoul (cur, &next, 16);
7133 if (G_UNLIKELY ((mask == 0 && errno == EINVAL) || cur == next))
7134 goto try_as_flags_string;
7136 /* Next char should be NULL terminator, or a ':'. If ':', we need the flag string after */
7137 if (G_UNLIKELY (next[0] == 0)) {
7147 if (g_str_equal (g_type_name (G_VALUE_TYPE (dest)), "GstFlagSet")) {
7148 /* If we're parsing a generic flag set, that can mean we're guessing
7149 * at the type in deserialising a GstStructure so at least check that
7150 * we have a valid-looking string, so we don't cause deserialisation of
7151 * other types of strings like 00:01:00:00 - https://bugzilla.gnome.org/show_bug.cgi?id=779755 */
7152 if (is_valid_flags_string (s)) {
7159 /* Otherwise, we already got a hex string for a valid non-generic flagset type */
7163 try_as_flags_string:
7166 const gchar *set_class = g_type_name (G_VALUE_TYPE (dest));
7167 GFlagsClass *flags_klass = NULL;
7170 if (g_str_equal (set_class, "GstFlagSet")) {
7171 /* There's no hope to parse the fields of generic flag set if we didn't already
7172 * catch a hex-string above */
7176 /* Flags class is the FlagSet class with 'Set' removed from the end */
7177 end = g_strrstr (set_class, "Set");
7180 gchar *class_name = g_strndup (set_class, end - set_class);
7181 GType flags_type = g_type_from_name (class_name);
7182 if (flags_type == 0) {
7183 GST_TRACE ("Looking for dynamic type %s", class_name);
7184 gst_dynamic_type_factory_load (class_name);
7187 if (flags_type != 0) {
7188 flags_klass = g_type_class_ref (flags_type);
7189 GST_TRACE ("Going to parse %s as %s", s, class_name);
7191 g_free (class_name);
7195 res = gst_value_gflags_str_to_flags (flags_klass, s, &flags, &mask);
7196 g_type_class_unref (flags_klass);
7202 gst_value_set_flagset (dest, flags, mask);
7208 gst_value_transform_flagset_string (const GValue * src_value,
7209 GValue * dest_value)
7211 dest_value->data[0].v_pointer = gst_value_serialize_flagset (src_value);
7215 gst_value_transform_string_flagset (const GValue * src_value,
7216 GValue * dest_value)
7218 if (!gst_value_deserialize_flagset (dest_value, src_value->data[0].v_pointer)) {
7219 /* If the deserialize fails, ensure we leave the flags in a
7220 * valid, if incorrect, state */
7221 gst_value_set_flagset (dest_value, 0, 0);
7226 gst_value_compare_flagset (const GValue * value1, const GValue * value2)
7231 v1 = value1->data[0].v_uint;
7232 v2 = value2->data[0].v_uint;
7234 m1 = value1->data[1].v_uint;
7235 m2 = value2->data[1].v_uint;
7237 if (v1 == v2 && m1 == m2)
7238 return GST_VALUE_EQUAL;
7240 return GST_VALUE_UNORDERED;
7243 /***********************
7244 * GstAllocationParams *
7245 ***********************/
7247 gst_value_compare_allocation_params (const GValue * value1,
7248 const GValue * value2)
7250 GstAllocationParams *v1, *v2;
7252 v1 = value1->data[0].v_pointer;
7253 v2 = value2->data[0].v_pointer;
7255 if (v1 == NULL && v1 == v2)
7256 return GST_VALUE_EQUAL;
7258 if (v1 == NULL || v2 == NULL)
7259 return GST_VALUE_UNORDERED;
7261 if (v1->flags == v2->flags && v1->align == v2->align &&
7262 v1->prefix == v2->prefix && v1->padding == v2->padding)
7263 return GST_VALUE_EQUAL;
7265 return GST_VALUE_UNORDERED;
7274 gst_value_compare_object (const GValue * value1, const GValue * value2)
7278 v1 = value1->data[0].v_pointer;
7279 v2 = value2->data[0].v_pointer;
7282 return GST_VALUE_EQUAL;
7284 return GST_VALUE_UNORDERED;
7288 gst_value_transform_object_string (const GValue * src_value,
7289 GValue * dest_value)
7294 obj = g_value_get_object (src_value);
7297 g_strdup_printf ("(%s) %s", G_OBJECT_TYPE_NAME (obj),
7298 GST_OBJECT_NAME (obj));
7300 str = g_strdup ("NULL");
7303 dest_value->data[0].v_pointer = str;
7306 static GTypeInfo _info = {
7307 0, NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL,
7310 static GTypeFundamentalInfo _finfo = {
7314 #define FUNC_VALUE_GET_TYPE_CLASSED(type, name, csize, flags) \
7315 GType _gst_ ## type ## _type = 0; \
7317 GType gst_ ## type ## _get_type (void) \
7319 static volatile GType gst_ ## type ## _type = 0; \
7321 if (g_once_init_enter (&gst_ ## type ## _type)) { \
7323 _info.class_size = csize; \
7324 _finfo.type_flags = flags; \
7325 _info.value_table = & _gst_ ## type ## _value_table; \
7326 _type = g_type_register_fundamental ( \
7327 g_type_fundamental_next (), \
7328 name, &_info, &_finfo, 0); \
7329 _gst_ ## type ## _type = _type; \
7330 g_once_init_leave(&gst_ ## type ## _type, _type); \
7333 return gst_ ## type ## _type; \
7336 #define FUNC_VALUE_GET_TYPE(type, name) \
7337 FUNC_VALUE_GET_TYPE_CLASSED(type, name, 0, 0)
7339 static const GTypeValueTable _gst_int_range_value_table = {
7340 gst_value_init_int_range,
7342 gst_value_copy_int_range,
7345 gst_value_collect_int_range, (char *) "pp", gst_value_lcopy_int_range
7348 FUNC_VALUE_GET_TYPE (int_range, "GstIntRange");
7350 static const GTypeValueTable _gst_int64_range_value_table = {
7351 gst_value_init_int64_range,
7352 gst_value_free_int64_range,
7353 gst_value_copy_int64_range,
7356 gst_value_collect_int64_range,
7357 (char *) "pp", gst_value_lcopy_int64_range
7360 FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range");
7362 static const GTypeValueTable _gst_double_range_value_table = {
7363 gst_value_init_double_range,
7365 gst_value_copy_double_range,
7368 gst_value_collect_double_range,
7369 (char *) "pp", gst_value_lcopy_double_range
7372 FUNC_VALUE_GET_TYPE (double_range, "GstDoubleRange");
7374 static const GTypeValueTable _gst_fraction_range_value_table = {
7375 gst_value_init_fraction_range,
7376 gst_value_free_fraction_range,
7377 gst_value_copy_fraction_range,
7380 gst_value_collect_fraction_range,
7381 (char *) "pppp", gst_value_lcopy_fraction_range
7384 FUNC_VALUE_GET_TYPE (fraction_range, "GstFractionRange");
7386 static const GTypeValueTable _gst_value_list_value_table = {
7387 gst_value_init_list_or_array,
7388 gst_value_free_list_or_array,
7389 gst_value_copy_list_or_array,
7390 gst_value_list_or_array_peek_pointer,
7392 gst_value_collect_list_or_array,
7393 (char *) "p", gst_value_lcopy_list_or_array
7396 FUNC_VALUE_GET_TYPE (value_list, "GstValueList");
7398 static const GTypeValueTable _gst_value_array_value_table = {
7399 gst_value_init_list_or_array,
7400 gst_value_free_list_or_array,
7401 gst_value_copy_list_or_array,
7402 gst_value_list_or_array_peek_pointer,
7404 gst_value_collect_list_or_array,
7405 (char *) "p", gst_value_lcopy_list_or_array
7408 FUNC_VALUE_GET_TYPE (value_array, "GstValueArray");
7410 static const GTypeValueTable _gst_fraction_value_table = {
7411 gst_value_init_fraction,
7413 gst_value_copy_fraction,
7416 gst_value_collect_fraction, (char *) "pp", gst_value_lcopy_fraction
7419 FUNC_VALUE_GET_TYPE (fraction, "GstFraction");
7421 static const GTypeValueTable _gst_bitmask_value_table = {
7422 gst_value_init_bitmask,
7424 gst_value_copy_bitmask,
7427 gst_value_collect_bitmask, (char *) "p", gst_value_lcopy_bitmask
7430 FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
7432 static const GTypeValueTable _gst_flagset_value_table = {
7433 gst_value_init_flagset,
7435 gst_value_copy_flagset,
7438 gst_value_collect_flagset, (char *) "pp", gst_value_lcopy_flagset
7441 FUNC_VALUE_GET_TYPE_CLASSED (flagset, "GstFlagSet",
7442 sizeof (GstFlagSetClass), G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE);
7445 gst_g_thread_get_type (void)
7447 return G_TYPE_THREAD;
7450 #define SERIAL_VTABLE(t,c,s,d) { t, c, s, d }
7452 #define REGISTER_SERIALIZATION_CONST(_gtype, _type) \
7454 static const GstValueTable gst_value = \
7455 SERIAL_VTABLE (_gtype, gst_value_compare_ ## _type, \
7456 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7457 gst_value_register (&gst_value); \
7460 #define REGISTER_SERIALIZATION(_gtype, _type) \
7462 static GstValueTable gst_value = \
7463 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7464 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7465 gst_value.type = _gtype; \
7466 gst_value_register (&gst_value); \
7469 #define REGISTER_SERIALIZATION_NO_COMPARE(_gtype, _type) \
7471 static GstValueTable gst_value = \
7472 SERIAL_VTABLE (0, NULL, \
7473 gst_value_serialize_ ## _type, gst_value_deserialize_ ## _type); \
7474 gst_value.type = _gtype; \
7475 gst_value_register (&gst_value); \
7478 #define REGISTER_SERIALIZATION_COMPARE_ONLY(_gtype, _type) \
7480 static GstValueTable gst_value = \
7481 SERIAL_VTABLE (0, gst_value_compare_ ## _type, \
7483 gst_value.type = _gtype; \
7484 gst_value_register (&gst_value); \
7487 /* These initial sizes are used for the tables
7488 * below, and save a couple of reallocs at startup */
7490 static const gint GST_VALUE_TABLE_DEFAULT_SIZE = 35;
7491 static const gint GST_VALUE_UNION_TABLE_DEFAULT_SIZE = 4;
7492 static const gint GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE = 11;
7493 static const gint GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE = 12;
7496 _priv_gst_value_initialize (void)
7499 g_array_sized_new (FALSE, FALSE, sizeof (GstValueTable),
7500 GST_VALUE_TABLE_DEFAULT_SIZE);
7501 gst_value_hash = g_hash_table_new (NULL, NULL);
7502 gst_value_union_funcs = g_array_sized_new (FALSE, FALSE,
7503 sizeof (GstValueUnionInfo), GST_VALUE_UNION_TABLE_DEFAULT_SIZE);
7504 gst_value_intersect_funcs = g_array_sized_new (FALSE, FALSE,
7505 sizeof (GstValueIntersectInfo), GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE);
7506 gst_value_subtract_funcs = g_array_sized_new (FALSE, FALSE,
7507 sizeof (GstValueSubtractInfo), GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE);
7509 REGISTER_SERIALIZATION (gst_int_range_get_type (), int_range);
7510 REGISTER_SERIALIZATION (gst_int64_range_get_type (), int64_range);
7511 REGISTER_SERIALIZATION (gst_double_range_get_type (), double_range);
7512 REGISTER_SERIALIZATION (gst_fraction_range_get_type (), fraction_range);
7513 REGISTER_SERIALIZATION (gst_value_list_get_type (), value_list);
7514 REGISTER_SERIALIZATION (gst_value_array_get_type (), value_array);
7515 REGISTER_SERIALIZATION (g_value_array_get_type (), g_value_array);
7516 REGISTER_SERIALIZATION (gst_buffer_get_type (), buffer);
7517 REGISTER_SERIALIZATION (gst_sample_get_type (), sample);
7518 REGISTER_SERIALIZATION (gst_fraction_get_type (), fraction);
7519 REGISTER_SERIALIZATION (gst_caps_get_type (), caps);
7520 REGISTER_SERIALIZATION (gst_tag_list_get_type (), tag_list);
7521 REGISTER_SERIALIZATION (G_TYPE_DATE, date);
7522 REGISTER_SERIALIZATION (gst_date_time_get_type (), date_time);
7523 REGISTER_SERIALIZATION (gst_bitmask_get_type (), bitmask);
7524 REGISTER_SERIALIZATION (gst_structure_get_type (), structure);
7525 REGISTER_SERIALIZATION (gst_flagset_get_type (), flagset);
7527 REGISTER_SERIALIZATION_NO_COMPARE (gst_segment_get_type (), segment);
7528 REGISTER_SERIALIZATION_NO_COMPARE (gst_caps_features_get_type (),
7531 REGISTER_SERIALIZATION_COMPARE_ONLY (gst_allocation_params_get_type (),
7533 REGISTER_SERIALIZATION_COMPARE_ONLY (G_TYPE_OBJECT, object);
7535 REGISTER_SERIALIZATION_CONST (G_TYPE_DOUBLE, double);
7536 REGISTER_SERIALIZATION_CONST (G_TYPE_FLOAT, float);
7538 REGISTER_SERIALIZATION_CONST (G_TYPE_STRING, string);
7539 REGISTER_SERIALIZATION_CONST (G_TYPE_BOOLEAN, boolean);
7540 REGISTER_SERIALIZATION_CONST (G_TYPE_ENUM, enum);
7542 REGISTER_SERIALIZATION_CONST (G_TYPE_FLAGS, gflags);
7544 REGISTER_SERIALIZATION_CONST (G_TYPE_INT, int);
7546 REGISTER_SERIALIZATION_CONST (G_TYPE_INT64, int64);
7547 REGISTER_SERIALIZATION_CONST (G_TYPE_LONG, long);
7549 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT, uint);
7550 REGISTER_SERIALIZATION_CONST (G_TYPE_UINT64, uint64);
7551 REGISTER_SERIALIZATION_CONST (G_TYPE_ULONG, ulong);
7553 REGISTER_SERIALIZATION_CONST (G_TYPE_UCHAR, uchar);
7555 REGISTER_SERIALIZATION (G_TYPE_GTYPE, gtype);
7557 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
7558 gst_value_transform_int_range_string);
7559 g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING,
7560 gst_value_transform_int64_range_string);
7561 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
7562 gst_value_transform_double_range_string);
7563 g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING,
7564 gst_value_transform_fraction_range_string);
7565 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
7566 gst_value_transform_list_string);
7567 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_VALUE_ARRAY,
7568 gst_value_transform_any_list_g_value_array);
7569 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_STRING,
7570 gst_value_transform_array_string);
7571 g_value_register_transform_func (GST_TYPE_ARRAY, G_TYPE_VALUE_ARRAY,
7572 gst_value_transform_any_list_g_value_array);
7573 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, G_TYPE_STRING,
7574 gst_value_transform_g_value_array_string);
7575 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_ARRAY,
7576 gst_value_transform_g_value_array_any_list);
7577 g_value_register_transform_func (G_TYPE_VALUE_ARRAY, GST_TYPE_LIST,
7578 gst_value_transform_g_value_array_any_list);
7579 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_STRING,
7580 gst_value_transform_fraction_string);
7581 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FRACTION,
7582 gst_value_transform_string_fraction);
7583 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_DOUBLE,
7584 gst_value_transform_fraction_double);
7585 g_value_register_transform_func (GST_TYPE_FRACTION, G_TYPE_FLOAT,
7586 gst_value_transform_fraction_float);
7587 g_value_register_transform_func (G_TYPE_DOUBLE, GST_TYPE_FRACTION,
7588 gst_value_transform_double_fraction);
7589 g_value_register_transform_func (G_TYPE_FLOAT, GST_TYPE_FRACTION,
7590 gst_value_transform_float_fraction);
7591 g_value_register_transform_func (G_TYPE_DATE, G_TYPE_STRING,
7592 gst_value_transform_date_string);
7593 g_value_register_transform_func (G_TYPE_STRING, G_TYPE_DATE,
7594 gst_value_transform_string_date);
7595 g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
7596 gst_value_transform_object_string);
7597 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
7598 gst_value_transform_bitmask_uint64);
7599 g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
7600 gst_value_transform_bitmask_string);
7601 g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
7602 gst_value_transform_uint64_bitmask);
7603 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
7604 gst_value_transform_string_bitmask);
7606 g_value_register_transform_func (GST_TYPE_FLAG_SET, G_TYPE_STRING,
7607 gst_value_transform_flagset_string);
7608 g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_FLAG_SET,
7609 gst_value_transform_string_flagset);
7611 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7612 gst_value_intersect_int_int_range);
7613 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7614 gst_value_intersect_int_range_int_range);
7615 gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7616 gst_value_intersect_int64_int64_range);
7617 gst_value_register_intersect_func (GST_TYPE_INT64_RANGE,
7618 GST_TYPE_INT64_RANGE, gst_value_intersect_int64_range_int64_range);
7619 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7620 gst_value_intersect_double_double_range);
7621 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
7622 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
7623 gst_value_register_intersect_func (GST_TYPE_ARRAY, GST_TYPE_ARRAY,
7624 gst_value_intersect_array);
7625 gst_value_register_intersect_func (GST_TYPE_FRACTION,
7626 GST_TYPE_FRACTION_RANGE, gst_value_intersect_fraction_fraction_range);
7627 gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
7628 GST_TYPE_FRACTION_RANGE,
7629 gst_value_intersect_fraction_range_fraction_range);
7630 gst_value_register_intersect_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7631 gst_value_intersect_flagset_flagset);
7632 gst_value_register_intersect_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7633 gst_value_intersect_structure_structure);
7635 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7636 gst_value_subtract_int_int_range);
7637 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
7638 gst_value_subtract_int_range_int);
7639 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7640 gst_value_subtract_int_range_int_range);
7641 gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE,
7642 gst_value_subtract_int64_int64_range);
7643 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64,
7644 gst_value_subtract_int64_range_int64);
7645 gst_value_register_subtract_func (GST_TYPE_INT64_RANGE,
7646 GST_TYPE_INT64_RANGE, gst_value_subtract_int64_range_int64_range);
7647 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
7648 gst_value_subtract_double_double_range);
7649 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
7650 gst_value_subtract_double_range_double);
7651 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
7652 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
7653 gst_value_register_subtract_func (GST_TYPE_FRACTION,
7654 GST_TYPE_FRACTION_RANGE, gst_value_subtract_fraction_fraction_range);
7655 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7656 GST_TYPE_FRACTION, gst_value_subtract_fraction_range_fraction);
7657 gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
7658 GST_TYPE_FRACTION_RANGE,
7659 gst_value_subtract_fraction_range_fraction_range);
7661 /* see bug #317246, #64994, #65041 */
7663 volatile GType date_type = G_TYPE_DATE;
7665 g_type_name (date_type);
7668 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
7669 gst_value_union_int_int_range);
7670 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
7671 gst_value_union_int_range_int_range);
7672 gst_value_register_union_func (GST_TYPE_FLAG_SET, GST_TYPE_FLAG_SET,
7673 gst_value_union_flagset_flagset);
7674 gst_value_register_union_func (GST_TYPE_STRUCTURE, GST_TYPE_STRUCTURE,
7675 gst_value_union_structure_structure);
7677 #if GST_VERSION_NANO == 1
7678 /* If building from git master, check starting array sizes matched actual size
7679 * so we can keep the defines in sync and save a few reallocs on startup */
7680 if (gst_value_table->len != GST_VALUE_TABLE_DEFAULT_SIZE) {
7681 GST_ERROR ("Wrong initial gst_value_table size. "
7682 "Please set GST_VALUE_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7683 gst_value_table->len);
7685 if (gst_value_union_funcs->len != GST_VALUE_UNION_TABLE_DEFAULT_SIZE) {
7686 GST_ERROR ("Wrong initial gst_value_union_funcs table size. "
7687 "Please set GST_VALUE_UNION_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7688 gst_value_union_funcs->len);
7690 if (gst_value_intersect_funcs->len != GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE) {
7691 GST_ERROR ("Wrong initial gst_value_intersect_funcs table size. "
7692 "Please set GST_VALUE_INTERSECT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7693 gst_value_intersect_funcs->len);
7695 if (gst_value_subtract_funcs->len != GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE) {
7696 GST_ERROR ("Wrong initial gst_value_subtract_funcs table size. "
7697 "Please set GST_VALUE_SUBTRACT_TABLE_DEFAULT_SIZE to %u in gstvalue.c",
7698 gst_value_subtract_funcs->len);
7703 /* Implement these if needed */
7704 gst_value_register_union_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
7705 gst_value_union_fraction_fraction_range);
7706 gst_value_register_union_func (GST_TYPE_FRACTION_RANGE,
7707 GST_TYPE_FRACTION_RANGE, gst_value_union_fraction_range_fraction_range);
7712 gst_flagset_class_init (gpointer g_class, gpointer class_data)
7714 GstFlagSetClass *f_class = (GstFlagSetClass *) (g_class);
7715 f_class->flags_type = (GType) GPOINTER_TO_SIZE (class_data);
7719 * gst_flagset_register:
7720 * @flags_type: a #GType of a #G_TYPE_FLAGS type.
7722 * Create a new sub-class of #GST_TYPE_FLAG_SET
7723 * which will pretty-print the human-readable flags
7724 * when serializing, for easier debugging.
7729 gst_flagset_register (GType flags_type)
7732 sizeof (GstFlagSetClass),
7734 (GClassInitFunc) gst_flagset_class_init,
7735 NULL, GSIZE_TO_POINTER (flags_type), 0, 0, NULL, NULL
7740 g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), 0);
7742 class_name = g_strdup_printf ("%sSet", g_type_name (flags_type));
7744 t = g_type_register_static (GST_TYPE_FLAG_SET,
7745 g_intern_string (class_name), &info, 0);
7746 g_free (class_name);