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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include "gst_private.h"
29 #include <gobject/gvaluecollector.h>
31 typedef struct _GstValueUnionInfo GstValueUnionInfo;
32 struct _GstValueUnionInfo
36 GstValueUnionFunc func;
39 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
40 struct _GstValueIntersectInfo
44 GstValueIntersectFunc func;
47 typedef struct _GstValueSubtractInfo GstValueSubtractInfo;
48 struct _GstValueSubtractInfo
52 GstValueSubtractFunc func;
55 GType gst_type_fourcc;
56 GType gst_type_int_range;
57 GType gst_type_double_range;
59 GType gst_type_fixed_list;
61 static GArray *gst_value_table;
62 static GArray *gst_value_union_funcs;
63 static GArray *gst_value_intersect_funcs;
64 static GArray *gst_value_subtract_funcs;
70 /* two helper functions to serialize/stringify any type of list
71 * regular lists are done with { }, fixed lists with < >
74 gst_value_serialize_any_list (const GValue * value, const char *begin,
78 GArray *array = value->data[0].v_pointer;
83 s = g_string_new (begin);
84 for (i = 0; i < array->len; i++) {
85 v = &g_array_index (array, GValue, i);
86 s_val = gst_value_serialize (v);
87 g_string_append (s, s_val);
89 if (i < array->len - 1) {
90 g_string_append (s, ", ");
93 g_string_append (s, end);
94 return g_string_free (s, FALSE);
98 gst_value_transform_any_list_string (const GValue * src_value,
99 GValue * dest_value, const char *begin, const char *end)
107 array = src_value->data[0].v_pointer;
109 s = g_string_new (begin);
110 for (i = 0; i < array->len; i++) {
111 list_value = &g_array_index (array, GValue, i);
114 g_string_append (s, ", ");
116 list_s = g_strdup_value_contents (list_value);
117 g_string_append (s, list_s);
120 g_string_append (s, end);
122 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
125 /* GValue functions usable for both regular lists and fixed lists */
127 gst_value_init_list (GValue * value)
129 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
133 gst_value_list_array_copy (const GArray * src)
138 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
139 g_array_set_size (dest, src->len);
140 for (i = 0; i < src->len; i++) {
141 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
142 &g_array_index (src, GValue, i));
149 gst_value_copy_list (const GValue * src_value, GValue * dest_value)
151 dest_value->data[0].v_pointer =
152 gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
156 gst_value_free_list (GValue * value)
159 GArray *src = (GArray *) value->data[0].v_pointer;
161 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
162 for (i = 0; i < src->len; i++) {
163 g_value_unset (&g_array_index (src, GValue, i));
165 g_array_free (src, TRUE);
170 gst_value_list_peek_pointer (const GValue * value)
172 return value->data[0].v_pointer;
176 gst_value_collect_list (GValue * value, guint n_collect_values,
177 GTypeCValue * collect_values, guint collect_flags)
179 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
180 value->data[0].v_pointer = collect_values[0].v_pointer;
181 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
183 value->data[0].v_pointer =
184 gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
190 gst_value_lcopy_list (const GValue * value, guint n_collect_values,
191 GTypeCValue * collect_values, guint collect_flags)
193 GArray **dest = collect_values[0].v_pointer;
196 return g_strdup_printf ("value location for `%s' passed as NULL",
197 G_VALUE_TYPE_NAME (value));
198 if (!value->data[0].v_pointer)
199 return g_strdup_printf ("invalid value given for `%s'",
200 G_VALUE_TYPE_NAME (value));
201 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
202 *dest = (GArray *) value->data[0].v_pointer;
204 *dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
210 * gst_value_list_prepend_value:
211 * @value: a GstValueList to prepend a value to
212 * @prepend_value: the value to prepend
214 * Prepends @prepend_value to the GstValueList in @value.
218 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
222 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)
223 || GST_VALUE_HOLDS_FIXED_LIST (value));
225 gst_value_init_and_copy (&val, prepend_value);
226 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, &val, 1);
230 * gst_value_list_append_value:
231 * @value: a GstValueList to append a value to
232 * @append_value: the value to append
234 * Appends @append_value to the GstValueList in @value.
237 gst_value_list_append_value (GValue * value, const GValue * append_value)
241 g_return_if_fail (GST_VALUE_HOLDS_LIST (value)
242 || GST_VALUE_HOLDS_FIXED_LIST (value));
244 gst_value_init_and_copy (&val, append_value);
245 g_array_append_vals ((GArray *) value->data[0].v_pointer, &val, 1);
249 * gst_value_list_get_size:
250 * @value: a GstValueList
252 * Gets the number of values contained in @value.
254 * Returns: the number of values
257 gst_value_list_get_size (const GValue * value)
259 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value)
260 || GST_VALUE_HOLDS_FIXED_LIST (value), 0);
262 return ((GArray *) value->data[0].v_pointer)->len;
266 * gst_value_list_get_value:
267 * @value: a GstValueList
268 * @index: index of value to get from the list
270 * Gets the value that is a member of the list contained in @value and
271 * has the index @index.
273 * Returns: the value at the given index
276 gst_value_list_get_value (const GValue * value, guint index)
278 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value)
279 || GST_VALUE_HOLDS_FIXED_LIST (value), NULL);
280 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
282 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
287 * gst_value_list_concat:
288 * @dest: an uninitialized #GValue to take the result
289 * @value1: first value to put into the union
290 * @value2: second value to put into the union
292 * Concatenates copies of value1 and value2 into a list. The value
293 * @dest is initialized to the type GST_TYPE_LIST.
296 gst_value_list_concat (GValue * dest, const GValue * value1,
297 const GValue * value2)
299 guint i, value1_length, value2_length;
302 g_return_if_fail (dest != NULL);
303 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
304 g_return_if_fail (G_IS_VALUE (value1));
305 g_return_if_fail (G_IS_VALUE (value2));
308 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
310 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
311 g_value_init (dest, GST_TYPE_LIST);
312 array = (GArray *) dest->data[0].v_pointer;
313 g_array_set_size (array, value1_length + value2_length);
315 if (GST_VALUE_HOLDS_LIST (value1)) {
316 for (i = 0; i < value1_length; i++) {
317 gst_value_init_and_copy (&g_array_index (array, GValue, i),
318 gst_value_list_get_value (value1, i));
321 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
324 if (GST_VALUE_HOLDS_LIST (value2)) {
325 for (i = 0; i < value2_length; i++) {
326 gst_value_init_and_copy (&g_array_index (array, GValue,
327 i + value1_length), gst_value_list_get_value (value2, i));
330 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
336 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
338 gst_value_transform_any_list_string (src_value, dest_value, "{ ", " }");
342 gst_value_transform_fixed_list_string (const GValue * src_value,
345 gst_value_transform_any_list_string (src_value, dest_value, "< ", " >");
349 gst_value_compare_list (const GValue * value1, const GValue * value2)
352 GArray *array1 = value1->data[0].v_pointer;
353 GArray *array2 = value2->data[0].v_pointer;
357 if (array1->len != array2->len)
358 return GST_VALUE_UNORDERED;
360 for (i = 0; i < array1->len; i++) {
361 v1 = &g_array_index (array1, GValue, i);
362 for (j = 0; j < array1->len; j++) {
363 v2 = &g_array_index (array2, GValue, j);
364 if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
367 if (j == array1->len) {
368 return GST_VALUE_UNORDERED;
372 return GST_VALUE_EQUAL;
376 gst_value_serialize_list (const GValue * value)
378 return gst_value_serialize_any_list (value, "{ ", " }");
382 gst_value_deserialize_list (GValue * dest, const char *s)
384 g_warning ("unimplemented");
389 gst_value_serialize_fixed_list (const GValue * value)
391 return gst_value_serialize_any_list (value, "< ", " >");
395 gst_value_deserialize_fixed_list (GValue * dest, const char *s)
397 g_warning ("unimplemented");
406 gst_value_init_fourcc (GValue * value)
408 value->data[0].v_int = 0;
412 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
414 dest_value->data[0].v_int = src_value->data[0].v_int;
418 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
419 GTypeCValue * collect_values, guint collect_flags)
421 value->data[0].v_int = collect_values[0].v_int;
427 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
428 GTypeCValue * collect_values, guint collect_flags)
430 guint32 *fourcc_p = collect_values[0].v_pointer;
433 return g_strdup_printf ("value location for `%s' passed as NULL",
434 G_VALUE_TYPE_NAME (value));
436 *fourcc_p = value->data[0].v_int;
442 * gst_value_set_fourcc:
443 * @value: a GValue initialized to GST_TYPE_FOURCC
444 * @fourcc: the fourcc to set
446 * Sets @value to @fourcc.
449 gst_value_set_fourcc (GValue * value, guint32 fourcc)
451 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
453 value->data[0].v_int = fourcc;
457 * gst_value_get_fourcc:
458 * @value: a GValue initialized to GST_TYPE_FOURCC
460 * Gets the fourcc contained in @value.
462 * Returns: the fourcc contained in @value.
465 gst_value_get_fourcc (const GValue * value)
467 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
469 return value->data[0].v_int;
473 gst_value_transform_fourcc_string (const GValue * src_value,
476 guint32 fourcc = src_value->data[0].v_int;
478 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
479 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
480 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
481 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
482 dest_value->data[0].v_pointer =
483 g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
485 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
490 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
492 if (value2->data[0].v_int == value1->data[0].v_int)
493 return GST_VALUE_EQUAL;
494 return GST_VALUE_UNORDERED;
498 gst_value_serialize_fourcc (const GValue * value)
500 guint32 fourcc = value->data[0].v_int;
502 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
503 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
504 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
505 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
506 return g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
508 return g_strdup_printf ("0x%08x", fourcc);
513 gst_value_deserialize_fourcc (GValue * dest, const char *s)
515 gboolean ret = FALSE;
519 if (strlen (s) == 4) {
520 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
522 } else if (g_ascii_isdigit (*s)) {
523 fourcc = strtoul (s, &end, 0);
528 gst_value_set_fourcc (dest, fourcc);
538 gst_value_init_int_range (GValue * value)
540 value->data[0].v_int = 0;
541 value->data[1].v_int = 0;
545 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
547 dest_value->data[0].v_int = src_value->data[0].v_int;
548 dest_value->data[1].v_int = src_value->data[1].v_int;
552 gst_value_collect_int_range (GValue * value, guint n_collect_values,
553 GTypeCValue * collect_values, guint collect_flags)
556 value->data[0].v_int = collect_values[0].v_int;
557 value->data[1].v_int = collect_values[1].v_int;
563 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
564 GTypeCValue * collect_values, guint collect_flags)
566 guint32 *int_range_start = collect_values[0].v_pointer;
567 guint32 *int_range_end = collect_values[1].v_pointer;
569 if (!int_range_start)
570 return g_strdup_printf ("start value location for `%s' passed as NULL",
571 G_VALUE_TYPE_NAME (value));
573 return g_strdup_printf ("end value location for `%s' passed as NULL",
574 G_VALUE_TYPE_NAME (value));
576 *int_range_start = value->data[0].v_int;
577 *int_range_end = value->data[1].v_int;
583 * gst_value_set_int_range:
584 * @value: a GValue initialized to GST_TYPE_INT_RANGE
585 * @start: the start of the range
586 * @end: the end of the range
588 * Sets @value to the range specified by @start and @end.
591 gst_value_set_int_range (GValue * value, int start, int end)
593 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
594 g_return_if_fail (start < end);
596 value->data[0].v_int = start;
597 value->data[1].v_int = end;
601 * gst_value_get_int_range_min:
602 * @value: a GValue initialized to GST_TYPE_INT_RANGE
604 * Gets the minimum of the range specified by @value.
606 * Returns: the minimum of the range
609 gst_value_get_int_range_min (const GValue * value)
611 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
613 return value->data[0].v_int;
617 * gst_value_get_int_range_max:
618 * @value: a GValue initialized to GST_TYPE_INT_RANGE
620 * Gets the maximum of the range specified by @value.
622 * Returns: the maxumum of the range
625 gst_value_get_int_range_max (const GValue * value)
627 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
629 return value->data[1].v_int;
633 gst_value_transform_int_range_string (const GValue * src_value,
636 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
637 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
641 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
643 if (value2->data[0].v_int == value1->data[0].v_int &&
644 value2->data[1].v_int == value1->data[1].v_int)
645 return GST_VALUE_EQUAL;
646 return GST_VALUE_UNORDERED;
650 gst_value_serialize_int_range (const GValue * value)
652 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
653 value->data[1].v_int);
657 gst_value_deserialize_int_range (GValue * dest, const char *s)
659 g_warning ("unimplemented");
668 gst_value_init_double_range (GValue * value)
670 value->data[0].v_double = 0;
671 value->data[1].v_double = 0;
675 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
677 dest_value->data[0].v_double = src_value->data[0].v_double;
678 dest_value->data[1].v_double = src_value->data[1].v_double;
682 gst_value_collect_double_range (GValue * value, guint n_collect_values,
683 GTypeCValue * collect_values, guint collect_flags)
685 value->data[0].v_double = collect_values[0].v_double;
686 value->data[1].v_double = collect_values[1].v_double;
692 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
693 GTypeCValue * collect_values, guint collect_flags)
695 gdouble *double_range_start = collect_values[0].v_pointer;
696 gdouble *double_range_end = collect_values[1].v_pointer;
698 if (!double_range_start)
699 return g_strdup_printf ("start value location for `%s' passed as NULL",
700 G_VALUE_TYPE_NAME (value));
701 if (!double_range_end)
702 return g_strdup_printf ("end value location for `%s' passed as NULL",
703 G_VALUE_TYPE_NAME (value));
705 *double_range_start = value->data[0].v_double;
706 *double_range_end = value->data[1].v_double;
712 * gst_value_set_double_range:
713 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
714 * @start: the start of the range
715 * @end: the end of the range
717 * Sets @value to the range specified by @start and @end.
720 gst_value_set_double_range (GValue * value, double start, double end)
722 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
724 value->data[0].v_double = start;
725 value->data[1].v_double = end;
729 * gst_value_get_double_range_min:
730 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
732 * Gets the minimum of the range specified by @value.
734 * Returns: the minumum of the range
737 gst_value_get_double_range_min (const GValue * value)
739 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
741 return value->data[0].v_double;
745 * gst_value_get_double_range_max:
746 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
748 * Gets the maximum of the range specified by @value.
750 * Returns: the maxumum of the range
753 gst_value_get_double_range_max (const GValue * value)
755 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
757 return value->data[1].v_double;
761 gst_value_transform_double_range_string (const GValue * src_value,
764 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
766 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
767 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
768 src_value->data[0].v_double),
769 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
770 src_value->data[1].v_double));
774 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
776 if (value2->data[0].v_double == value1->data[0].v_double &&
777 value2->data[0].v_double == value1->data[0].v_double)
778 return GST_VALUE_EQUAL;
779 return GST_VALUE_UNORDERED;
783 gst_value_serialize_double_range (const GValue * value)
785 char d1[G_ASCII_DTOSTR_BUF_SIZE];
786 char d2[G_ASCII_DTOSTR_BUF_SIZE];
788 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
789 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
790 return g_strdup_printf ("[ %s, %s ]", d1, d2);
794 gst_value_deserialize_double_range (GValue * dest, const char *s)
796 g_warning ("unimplemented");
805 * gst_value_set_caps:
806 * @value: a GValue initialized to GST_TYPE_CAPS
807 * @caps: the caps to set the value to
809 * Sets the contents of @value to coorespond to @caps. The actual
810 * #GstCaps structure is copied before it is used.
813 gst_value_set_caps (GValue * value, const GstCaps * caps)
815 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
817 g_value_set_boxed (value, caps);
821 * gst_value_get_caps:
822 * @value: a GValue initialized to GST_TYPE_CAPS
824 * Gets the contents of @value.
826 * Returns: the contents of @value
829 gst_value_get_caps (const GValue * value)
831 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
833 return (GstCaps *) g_value_get_boxed (value);
841 gst_value_compare_buffer (const GValue * value1, const GValue * value2)
843 GstBuffer *buf1 = g_value_get_boxed (value1);
844 GstBuffer *buf2 = g_value_get_boxed (value2);
846 if (GST_BUFFER_SIZE (buf1) != GST_BUFFER_SIZE (buf2))
847 return GST_VALUE_UNORDERED;
848 if (GST_BUFFER_SIZE (buf1) == 0)
849 return GST_VALUE_EQUAL;
850 g_assert (GST_BUFFER_DATA (buf1));
851 g_assert (GST_BUFFER_DATA (buf2));
852 if (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2),
853 GST_BUFFER_SIZE (buf1)) == 0)
854 return GST_VALUE_EQUAL;
856 return GST_VALUE_UNORDERED;
860 gst_value_serialize_buffer (const GValue * value)
866 GstBuffer *buffer = g_value_get_boxed (value);
868 data = GST_BUFFER_DATA (buffer);
869 size = GST_BUFFER_SIZE (buffer);
871 string = malloc (size * 2 + 1);
872 for (i = 0; i < size; i++) {
873 sprintf (string + i * 2, "%02x", data[i]);
875 string[size * 2] = 0;
881 gst_value_deserialize_buffer (GValue * dest, const char *s)
893 buffer = gst_buffer_new_and_alloc (len / 2);
894 data = GST_BUFFER_DATA (buffer);
895 for (i = 0; i < len / 2; i++) {
896 if (!isxdigit ((int) s[i * 2]) || !isxdigit ((int) s[i * 2 + 1])) {
900 ts[0] = s[i * 2 + 0];
901 ts[1] = s[i * 2 + 1];
904 data[i] = strtoul (ts, NULL, 16);
908 g_value_set_boxed (dest, buffer);
911 gst_buffer_unref (buffer);
922 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
924 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
925 return GST_VALUE_EQUAL;
926 return GST_VALUE_UNORDERED;
930 gst_value_serialize_boolean (const GValue * value)
932 if (value->data[0].v_int) {
933 return g_strdup ("true");
935 return g_strdup ("false");
939 gst_value_deserialize_boolean (GValue * dest, const char *s)
941 gboolean ret = FALSE;
943 if (g_ascii_strcasecmp (s, "true") == 0 ||
944 g_ascii_strcasecmp (s, "yes") == 0 ||
945 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
946 g_value_set_boolean (dest, TRUE);
948 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
949 g_ascii_strcasecmp (s, "no") == 0 ||
950 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
951 g_value_set_boolean (dest, FALSE);
963 gst_strtoll (const char *s, char **end, int base)
968 i = -(long long) g_ascii_strtoull (s + 1, end, base);
970 i = g_ascii_strtoull (s, end, base);
976 #define CREATE_SERIALIZATION_START(_type,_macro) \
978 gst_value_compare_ ## _type (const GValue * value1, const GValue * value2) \
980 g ## _type val1 = g_value_get_ ## _type (value1); \
981 g ## _type val2 = g_value_get_ ## _type (value2); \
983 return GST_VALUE_GREATER_THAN; \
985 return GST_VALUE_LESS_THAN; \
986 return GST_VALUE_EQUAL; \
990 gst_value_serialize_ ## _type (const GValue * value) \
992 GValue val = { 0, }; \
993 g_value_init (&val, G_TYPE_STRING); \
994 if (!g_value_transform (value, &val)) \
995 g_assert_not_reached (); \
996 /* NO_COPY_MADNESS!!! */ \
997 return (char *) g_value_get_string (&val); \
1001 gst_value_deserialize_int_helper (long long *to, const char *s, long long min,
1004 gboolean ret = FALSE;
1007 *to = gst_strtoll (s, &end, 0);
1011 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
1012 *to = G_LITTLE_ENDIAN;
1014 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
1017 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
1020 } else if (g_ascii_strcasecmp (s, "min") == 0) {
1023 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1029 if (*to < min || *to > max) {
1036 #define CREATE_SERIALIZATION(_type,_macro) \
1037 CREATE_SERIALIZATION_START(_type,_macro) \
1040 gst_value_deserialize_ ## _type (GValue * dest, const char *s) \
1044 if (gst_value_deserialize_int_helper (&x, s, G_MIN ## _macro, G_MAX ## _macro)) { \
1045 g_value_set_ ## _type (dest, x); \
1052 #define CREATE_USERIALIZATION(_type,_macro) \
1053 CREATE_SERIALIZATION_START(_type,_macro) \
1056 gst_value_deserialize_ ## _type (GValue * dest, const char *s) \
1058 unsigned long long x; \
1060 gboolean ret = FALSE; \
1062 x = g_ascii_strtoull (s, &end, 0); \
1066 if (g_ascii_strcasecmp (s, "little_endian") == 0) { \
1067 x = G_LITTLE_ENDIAN; \
1069 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) { \
1072 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) { \
1075 } else if (g_ascii_strcasecmp (s, "min") == 0) { \
1078 } else if (g_ascii_strcasecmp (s, "max") == 0) { \
1079 x = G_MAX ## _macro; \
1084 if (x > G_MAX ## _macro) {\
1087 g_value_set_ ## _type (dest, x); \
1093 #define REGISTER_SERIALIZATION(_gtype, _type) G_STMT_START{ \
1094 static const GstValueTable gst_value = { \
1096 gst_value_compare_ ## _type, \
1097 gst_value_serialize_ ## _type, \
1098 gst_value_deserialize_ ## _type, \
1101 gst_value_register (&gst_value); \
1104 CREATE_SERIALIZATION (int, INT)
1105 CREATE_SERIALIZATION (int64, INT64)
1106 CREATE_SERIALIZATION (long, LONG)
1107 CREATE_USERIALIZATION (uint, UINT)
1108 CREATE_USERIALIZATION (uint64, UINT64)
1109 CREATE_USERIALIZATION (ulong, ULONG)
1115 gst_value_compare_double (const GValue * value1, const GValue * value2)
1117 if (value1->data[0].v_double > value2->data[0].v_double)
1118 return GST_VALUE_GREATER_THAN;
1119 if (value1->data[0].v_double < value2->data[0].v_double)
1120 return GST_VALUE_LESS_THAN;
1121 if (value1->data[0].v_double == value2->data[0].v_double)
1122 return GST_VALUE_EQUAL;
1123 return GST_VALUE_UNORDERED;
1127 gst_value_serialize_double (const GValue * value)
1129 char d[G_ASCII_DTOSTR_BUF_SIZE];
1131 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
1132 return g_strdup (d);
1136 gst_value_deserialize_double (GValue * dest, const char *s)
1139 gboolean ret = FALSE;
1142 x = g_ascii_strtod (s, &end);
1146 if (g_ascii_strcasecmp (s, "min") == 0) {
1149 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1155 g_value_set_double (dest, x);
1165 gst_value_compare_float (const GValue * value1, const GValue * value2)
1167 if (value1->data[0].v_float > value2->data[0].v_float)
1168 return GST_VALUE_GREATER_THAN;
1169 if (value1->data[0].v_float < value2->data[0].v_float)
1170 return GST_VALUE_LESS_THAN;
1171 if (value1->data[0].v_float == value2->data[0].v_float)
1172 return GST_VALUE_EQUAL;
1173 return GST_VALUE_UNORDERED;
1177 gst_value_serialize_float (const GValue * value)
1179 char d[G_ASCII_DTOSTR_BUF_SIZE];
1181 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_float);
1182 return g_strdup (d);
1186 gst_value_deserialize_float (GValue * dest, const char *s)
1189 gboolean ret = FALSE;
1192 x = g_ascii_strtod (s, &end);
1196 if (g_ascii_strcasecmp (s, "min") == 0) {
1199 } else if (g_ascii_strcasecmp (s, "max") == 0) {
1204 if (x > G_MAXFLOAT || x < -G_MAXFLOAT)
1207 g_value_set_float (dest, x);
1217 gst_value_compare_string (const GValue * value1, const GValue * value2)
1219 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
1222 return GST_VALUE_LESS_THAN;
1224 return GST_VALUE_GREATER_THAN;
1225 return GST_VALUE_EQUAL;
1228 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
1229 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
1233 gst_string_wrap (const char *s)
1238 gboolean wrap = FALSE;
1243 if (GST_ASCII_IS_STRING (*t)) {
1245 } else if (*t < 0x20 || *t >= 0x7f) {
1258 e = d = g_malloc (len + 3);
1263 if (GST_ASCII_IS_STRING (*t)) {
1265 } else if (*t < 0x20 || *t >= 0x7f) {
1267 *e++ = '0' + ((*t) >> 6);
1268 *e++ = '0' + (((*t) >> 3) & 0x7);
1269 *e++ = '0' + ((*t++) & 0x7);
1282 gst_value_serialize_string (const GValue * value)
1284 return gst_string_wrap (value->data[0].v_pointer);
1288 gst_value_deserialize_string (GValue * dest, const char *s)
1290 g_value_set_string (dest, s);
1300 gst_value_compare_enum (const GValue * value1, const GValue * value2)
1302 GEnumValue *en1, *en2;
1303 GEnumClass *klass1 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value1));
1304 GEnumClass *klass2 = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value2));
1306 g_return_val_if_fail (klass1, GST_VALUE_UNORDERED);
1307 g_return_val_if_fail (klass2, GST_VALUE_UNORDERED);
1308 en1 = g_enum_get_value (klass1, g_value_get_enum (value1));
1309 en2 = g_enum_get_value (klass2, g_value_get_enum (value2));
1310 g_type_class_unref (klass1);
1311 g_type_class_unref (klass2);
1312 g_return_val_if_fail (en1, GST_VALUE_UNORDERED);
1313 g_return_val_if_fail (en2, GST_VALUE_UNORDERED);
1314 if (en1->value < en2->value)
1315 return GST_VALUE_LESS_THAN;
1316 if (en1->value > en2->value)
1317 return GST_VALUE_GREATER_THAN;
1319 return GST_VALUE_EQUAL;
1323 gst_value_serialize_enum (const GValue * value)
1326 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (value));
1328 g_return_val_if_fail (klass, NULL);
1329 en = g_enum_get_value (klass, g_value_get_enum (value));
1330 g_type_class_unref (klass);
1331 g_return_val_if_fail (en, NULL);
1332 return g_strdup (en->value_name);
1336 gst_value_deserialize_enum (GValue * dest, const char *s)
1339 gchar *endptr = NULL;
1340 GEnumClass *klass = (GEnumClass *) g_type_class_ref (G_VALUE_TYPE (dest));
1342 g_return_val_if_fail (klass, FALSE);
1343 if (!(en = g_enum_get_value_by_name (klass, s))) {
1344 if (!(en = g_enum_get_value_by_nick (klass, s))) {
1345 gint i = strtol (s, &endptr, 0);
1347 if (endptr && *endptr == '\0') {
1348 en = g_enum_get_value (klass, i);
1352 g_type_class_unref (klass);
1353 g_return_val_if_fail (en, FALSE);
1354 g_value_set_enum (dest, en->value);
1363 gst_value_union_int_int_range (GValue * dest, const GValue * src1,
1364 const GValue * src2)
1366 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
1367 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1369 if (src2->data[0].v_int <= src1->data[0].v_int &&
1370 src2->data[1].v_int >= src1->data[0].v_int) {
1371 gst_value_init_and_copy (dest, src2);
1379 gst_value_union_int_range_int_range (GValue * dest, const GValue * src1,
1380 const GValue * src2)
1385 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
1386 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1388 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1389 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1392 g_value_init (dest, GST_TYPE_INT_RANGE);
1393 gst_value_set_int_range (dest,
1394 MIN (src1->data[0].v_int, src2->data[0].v_int),
1395 MAX (src1->data[1].v_int, src2->data[1].v_int));
1407 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
1408 const GValue * src2)
1410 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
1411 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1413 if (src2->data[0].v_int <= src1->data[0].v_int &&
1414 src2->data[1].v_int >= src1->data[0].v_int) {
1415 gst_value_init_and_copy (dest, src1);
1423 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
1424 const GValue * src2)
1429 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
1430 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1432 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1433 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1436 g_value_init (dest, GST_TYPE_INT_RANGE);
1437 gst_value_set_int_range (dest, min, max);
1441 g_value_init (dest, G_TYPE_INT);
1442 g_value_set_int (dest, min);
1450 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
1451 const GValue * src2)
1453 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_DOUBLE, FALSE);
1454 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1456 if (src2->data[0].v_double <= src1->data[0].v_double &&
1457 src2->data[1].v_double >= src1->data[0].v_double) {
1458 gst_value_init_and_copy (dest, src1);
1466 gst_value_intersect_double_range_double_range (GValue * dest,
1467 const GValue * src1, const GValue * src2)
1472 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_DOUBLE_RANGE, FALSE);
1473 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1475 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
1476 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
1479 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
1480 gst_value_set_double_range (dest, min, max);
1484 g_value_init (dest, G_TYPE_DOUBLE);
1485 g_value_set_int (dest, min);
1493 gst_value_intersect_list (GValue * dest, const GValue * value1,
1494 const GValue * value2)
1497 GValue intersection = { 0, };
1498 gboolean ret = FALSE;
1500 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value1), FALSE);
1502 size = gst_value_list_get_size (value1);
1503 for (i = 0; i < size; i++) {
1504 const GValue *cur = gst_value_list_get_value (value1, i);
1506 if (gst_value_intersect (&intersection, cur, value2)) {
1509 gst_value_init_and_copy (dest, &intersection);
1511 } else if (GST_VALUE_HOLDS_LIST (dest)) {
1512 gst_value_list_append_value (dest, &intersection);
1514 GValue temp = { 0, };
1516 gst_value_init_and_copy (&temp, dest);
1517 g_value_unset (dest);
1518 gst_value_list_concat (dest, &temp, &intersection);
1520 g_value_unset (&intersection);
1532 gst_value_subtract_int_int_range (GValue * dest, const GValue * minuend,
1533 const GValue * subtrahend)
1535 int min = gst_value_get_int_range_min (subtrahend);
1536 int max = gst_value_get_int_range_max (subtrahend);
1537 int val = g_value_get_int (minuend);
1539 if (val < min || val > max) {
1540 gst_value_init_and_copy (dest, minuend);
1547 gst_value_create_new_range (GValue * dest, int min1, int max1, int min2,
1552 GValue *pv1, *pv2; /* yeah, hungarian! */
1554 if (min1 <= max1 && min2 <= max2) {
1557 } else if (min1 <= max1) {
1560 } else if (min2 <= max2) {
1568 g_value_init (pv1, GST_TYPE_INT_RANGE);
1569 gst_value_set_int_range (pv1, min1, max1);
1570 } else if (min1 == max1) {
1571 g_value_init (pv1, G_TYPE_INT);
1572 g_value_set_int (pv1, min1);
1575 g_value_init (pv2, GST_TYPE_INT_RANGE);
1576 gst_value_set_int_range (pv2, min2, max2);
1577 } else if (min2 == max2) {
1578 g_value_init (pv2, G_TYPE_INT);
1579 g_value_set_int (pv2, min2);
1582 if (min1 <= max1 && min2 <= max2) {
1583 gst_value_list_concat (dest, pv1, pv2);
1584 g_value_unset (pv1);
1585 g_value_unset (pv2);
1591 gst_value_subtract_int_range_int (GValue * dest, const GValue * minuend,
1592 const GValue * subtrahend)
1594 int min = gst_value_get_int_range_min (minuend);
1595 int max = gst_value_get_int_range_max (minuend);
1596 int val = g_value_get_int (subtrahend);
1598 g_return_val_if_fail (min < max, FALSE);
1600 if (val < min || val > max) {
1601 gst_value_init_and_copy (dest, minuend);
1604 if (val == G_MAXINT) {
1608 if (val == G_MININT) {
1612 gst_value_create_new_range (dest, min, val - 1, val + 1, max);
1618 gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend,
1619 const GValue * subtrahend)
1621 int min1 = gst_value_get_int_range_min (minuend);
1622 int max1 = gst_value_get_int_range_max (minuend);
1623 int min2 = gst_value_get_int_range_min (subtrahend);
1624 int max2 = gst_value_get_int_range_max (subtrahend);
1626 if (max2 == G_MAXINT && min2 == G_MININT) {
1628 } else if (max2 == G_MAXINT) {
1629 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1), 1, 0);
1630 } else if (min2 == G_MININT) {
1631 return gst_value_create_new_range (dest, MAX (max2 + 1, min1), max1, 1, 0);
1633 return gst_value_create_new_range (dest, min1, MIN (min2 - 1, max1),
1634 MAX (max2 + 1, min1), max1);
1639 gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend,
1640 const GValue * subtrahend)
1642 double min = gst_value_get_double_range_min (subtrahend);
1643 double max = gst_value_get_double_range_max (subtrahend);
1644 double val = g_value_get_double (minuend);
1646 if (val < min || val > max) {
1647 gst_value_init_and_copy (dest, minuend);
1654 gst_value_subtract_double_range_double (GValue * dest, const GValue * minuend,
1655 const GValue * subtrahend)
1658 gst_value_init_and_copy (dest, minuend);
1663 gst_value_subtract_double_range_double_range (GValue * dest,
1664 const GValue * minuend, const GValue * subtrahend)
1667 /* done like with ints */
1668 double min1 = gst_value_get_double_range_min (minuend);
1669 double max2 = gst_value_get_double_range_max (minuend);
1670 double max1 = MIN (gst_value_get_double_range_min (subtrahend), max2);
1671 double min2 = MAX (gst_value_get_double_range_max (subtrahend), min1);
1674 GValue *pv1, *pv2; /* yeah, hungarian! */
1676 if (min1 < max1 && min2 < max2) {
1679 } else if (min1 < max1) {
1682 } else if (min2 < max2) {
1690 g_value_init (pv1, GST_TYPE_DOUBLE_RANGE);
1691 gst_value_set_double_range (pv1, min1, max1);
1694 g_value_init (pv2, GST_TYPE_DOUBLE_RANGE);
1695 gst_value_set_double_range (pv2, min2, max2);
1698 if (min1 < max1 && min2 < max2) {
1699 gst_value_list_concat (dest, pv1, pv2);
1700 g_value_unset (pv1);
1701 g_value_unset (pv2);
1707 gst_value_subtract_from_list (GValue * dest, const GValue * minuend,
1708 const GValue * subtrahend)
1711 GValue subtraction = { 0, };
1712 gboolean ret = FALSE;
1714 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (minuend), FALSE);
1716 size = gst_value_list_get_size (minuend);
1717 for (i = 0; i < size; i++) {
1718 const GValue *cur = gst_value_list_get_value (minuend, i);
1720 if (gst_value_subtract (&subtraction, cur, subtrahend)) {
1722 gst_value_init_and_copy (dest, &subtraction);
1724 } else if (GST_VALUE_HOLDS_LIST (dest)
1725 && GST_VALUE_HOLDS_LIST (&subtraction)) {
1727 GValue unroll = { 0, };
1729 gst_value_init_and_copy (&unroll, dest);
1730 g_value_unset (dest);
1731 gst_value_list_concat (dest, &unroll, &subtraction);
1732 } else if (GST_VALUE_HOLDS_LIST (dest)) {
1733 gst_value_list_append_value (dest, &subtraction);
1735 GValue temp = { 0, };
1737 gst_value_init_and_copy (&temp, dest);
1738 g_value_unset (dest);
1739 gst_value_list_concat (dest, &temp, &subtraction);
1740 g_value_unset (&temp);
1742 g_value_unset (&subtraction);
1749 gst_value_subtract_list (GValue * dest, const GValue * minuend,
1750 const GValue * subtrahend)
1753 GValue data[2] = { {0,}, {0,} };
1754 GValue *subtraction = &data[0], *result = &data[1];
1756 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (subtrahend), FALSE);
1758 gst_value_init_and_copy (result, minuend);
1759 size = gst_value_list_get_size (subtrahend);
1760 for (i = 0; i < size; i++) {
1761 const GValue *cur = gst_value_list_get_value (subtrahend, i);
1763 if (gst_value_subtract (subtraction, result, cur)) {
1764 GValue *temp = result;
1766 result = subtraction;
1768 g_value_unset (subtraction);
1770 g_value_unset (result);
1774 gst_value_init_and_copy (dest, result);
1775 g_value_unset (result);
1785 * gst_value_can_compare:
1786 * @value1: a value to compare
1787 * @value2: another value to compare
1789 * Determines if @value1 and @value2 can be compared.
1791 * Returns: TRUE if the values can be compared
1794 gst_value_can_compare (const GValue * value1, const GValue * value2)
1796 GstValueTable *table;
1799 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1801 for (i = 0; i < gst_value_table->len; i++) {
1802 table = &g_array_index (gst_value_table, GstValueTable, i);
1803 if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare)
1811 * gst_value_compare:
1812 * @value1: a value to compare
1813 * @value2: another value to compare
1815 * Compares @value1 and @value2. If @value1 and @value2 cannot be
1816 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
1817 * if @value1 is greater than @value2, GST_VALUE_GREATER is returned.
1818 * If @value1 is less than @value2, GST_VALUE_LESSER is returned.
1819 * If the values are equal, GST_VALUE_EQUAL is returned.
1821 * Returns: A GstValueCompareType value
1824 gst_value_compare (const GValue * value1, const GValue * value2)
1826 GstValueTable *table, *best = NULL;
1829 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1830 return GST_VALUE_UNORDERED;
1832 for (i = 0; i < gst_value_table->len; i++) {
1833 table = &g_array_index (gst_value_table, GstValueTable, i);
1834 if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) {
1838 if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) {
1839 if (!best || g_type_is_a (table->type, best->type))
1844 return best->compare (value1, value2);
1847 g_critical ("unable to compare values of type %s\n",
1848 g_type_name (G_VALUE_TYPE (value1)));
1849 return GST_VALUE_UNORDERED;
1855 * gst_value_can_union:
1856 * @value1: a value to union
1857 * @value2: another value to union
1859 * Determines if @value1 and @value2 can be non-trivially unioned.
1860 * Any two values can be trivially unioned by adding both of them
1861 * to a GstValueList. However, certain types have the possibility
1862 * to be unioned in a simpler way. For example, an integer range
1863 * and an integer can be unioned if the integer is a subset of the
1864 * integer range. If there is the possibility that two values can
1865 * be unioned, this function returns TRUE.
1867 * Returns: TRUE if there is a function allowing the two values to
1871 gst_value_can_union (const GValue * value1, const GValue * value2)
1873 GstValueUnionInfo *union_info;
1876 for (i = 0; i < gst_value_union_funcs->len; i++) {
1877 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1878 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1879 union_info->type2 == G_VALUE_TYPE (value2))
1881 if (union_info->type1 == G_VALUE_TYPE (value2) &&
1882 union_info->type2 == G_VALUE_TYPE (value1))
1891 * @dest: the destination value
1892 * @value1: a value to union
1893 * @value2: another value to union
1895 * Creates a GValue cooresponding to the union of @value1 and @value2.
1897 * Returns: TRUE if the values could be unioned
1900 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
1902 GstValueUnionInfo *union_info;
1905 for (i = 0; i < gst_value_union_funcs->len; i++) {
1906 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1907 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1908 union_info->type2 == G_VALUE_TYPE (value2)) {
1909 if (union_info->func (dest, value1, value2)) {
1913 if (union_info->type1 == G_VALUE_TYPE (value2) &&
1914 union_info->type2 == G_VALUE_TYPE (value1)) {
1915 if (union_info->func (dest, value2, value1)) {
1921 gst_value_list_concat (dest, value1, value2);
1926 * gst_value_register_union_func:
1927 * @type1: a type to union
1928 * @type2: another type to union
1929 * @func: a function that implments creating a union between the two types
1931 * Registers a union function that can create a union between GValues
1932 * of the type @type1 and @type2.
1936 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
1938 GstValueUnionInfo union_info;
1940 union_info.type1 = type1;
1941 union_info.type2 = type2;
1942 union_info.func = func;
1944 g_array_append_val (gst_value_union_funcs, union_info);
1950 * gst_value_can_intersect:
1957 gst_value_can_intersect (const GValue * value1, const GValue * value2)
1959 GstValueIntersectInfo *intersect_info;
1963 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
1966 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1967 intersect_info = &g_array_index (gst_value_intersect_funcs,
1968 GstValueIntersectInfo, i);
1969 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1970 intersect_info->type2 == G_VALUE_TYPE (value2))
1971 if (intersect_info->type2 == G_VALUE_TYPE (value1) &&
1972 intersect_info->type1 == G_VALUE_TYPE (value2))
1976 return gst_value_can_compare (value1, value2);
1980 * gst_value_intersect:
1981 * @dest: the destination value for intersection
1982 * @value1: a value to intersect
1983 * @value2: another value to intersect
1985 * Calculates the intersection of the two values.
1987 * Returns: TRUE if the intersection is non-empty
1990 gst_value_intersect (GValue * dest, const GValue * value1,
1991 const GValue * value2)
1993 GstValueIntersectInfo *intersect_info;
1997 /* special cases first */
1998 if (GST_VALUE_HOLDS_LIST (value1))
1999 return gst_value_intersect_list (dest, value1, value2);
2000 if (GST_VALUE_HOLDS_LIST (value2))
2001 return gst_value_intersect_list (dest, value2, value1);
2003 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
2004 intersect_info = &g_array_index (gst_value_intersect_funcs,
2005 GstValueIntersectInfo, i);
2006 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
2007 intersect_info->type2 == G_VALUE_TYPE (value2)) {
2008 ret = intersect_info->func (dest, value1, value2);
2011 if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
2012 intersect_info->type2 == G_VALUE_TYPE (value1)) {
2013 ret = intersect_info->func (dest, value2, value1);
2018 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
2019 gst_value_init_and_copy (dest, value1);
2027 * gst_value_register_intersection_func:
2034 gst_value_register_intersect_func (GType type1, GType type2,
2035 GstValueIntersectFunc func)
2037 GstValueIntersectInfo intersect_info;
2039 intersect_info.type1 = type1;
2040 intersect_info.type2 = type2;
2041 intersect_info.func = func;
2043 g_array_append_val (gst_value_intersect_funcs, intersect_info);
2050 * gst_value_subtract:
2051 * @dest: the destination value for the result if the subtraction is not empty
2052 * @minuend: the value to subtract from
2053 * @subtrahend: the value to subtract
2055 * Subtracts @subtrahend from @minuend and stores the result in @dest.
2056 * Note that this means subtraction as in sets, not as in mathematics.
2058 * Returns: TRUE if the subtraction is not empty
2061 gst_value_subtract (GValue * dest, const GValue * minuend,
2062 const GValue * subtrahend)
2064 GstValueSubtractInfo *info;
2067 /* special cases first */
2068 if (GST_VALUE_HOLDS_LIST (minuend))
2069 return gst_value_subtract_from_list (dest, minuend, subtrahend);
2070 if (GST_VALUE_HOLDS_LIST (subtrahend))
2071 return gst_value_subtract_list (dest, minuend, subtrahend);
2073 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
2074 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
2075 if (info->minuend == G_VALUE_TYPE (minuend) &&
2076 info->subtrahend == G_VALUE_TYPE (subtrahend)) {
2077 return info->func (dest, minuend, subtrahend);
2081 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) {
2082 gst_value_init_and_copy (dest, minuend);
2091 gst_value_subtract (GValue * dest, const GValue * minuend,
2092 const GValue * subtrahend)
2094 gboolean ret = gst_value_subtract2 (dest, minuend, subtrahend);
2096 g_printerr ("\"%s\" - \"%s\" = \"%s\"\n", gst_value_serialize (minuend),
2097 gst_value_serialize (subtrahend),
2098 ret ? gst_value_serialize (dest) : "---");
2104 * gst_value_can_subtract:
2105 * @minuend: the value to subtract from
2106 * @subtrahend: the value to subtract
2108 * Checks if it's possible to subtract @subtrahend from @minuend.
2110 * Returns: TRUE if a subtraction is possible
2113 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend)
2115 GstValueSubtractInfo *info;
2119 if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend))
2122 for (i = 0; i < gst_value_subtract_funcs->len; i++) {
2123 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
2124 if (info->minuend == G_VALUE_TYPE (minuend) &&
2125 info->subtrahend == G_VALUE_TYPE (subtrahend))
2129 return gst_value_can_compare (minuend, subtrahend);
2133 * gst_value_register_subtract_func:
2134 * @minuend_type: type of the minuend
2135 * @subtrahend_type: type of the subtrahend
2136 * @func: function to use
2138 * Registers @func as a function capable of subtracting the values of
2139 * @subtrahend_type from values of @minuend_type.
2142 gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
2143 GstValueSubtractFunc func)
2145 GstValueSubtractInfo info;
2147 /* one type must be unfixed, other subtractions can be done as comparisons */
2148 g_return_if_fail (!gst_type_is_fixed (minuend_type)
2149 || !gst_type_is_fixed (subtrahend_type));
2151 info.minuend = minuend_type;
2152 info.subtrahend = subtrahend_type;
2155 g_array_append_val (gst_value_subtract_funcs, info);
2159 * gst_value_register:
2164 gst_value_register (const GstValueTable * table)
2166 g_array_append_val (gst_value_table, *table);
2170 * gst_value_init_and_copy:
2176 gst_value_init_and_copy (GValue * dest, const GValue * src)
2178 g_value_init (dest, G_VALUE_TYPE (src));
2179 g_value_copy (src, dest);
2183 * gst_value_serialize:
2184 * @value: a #GValue to serialize
2186 * tries to transform the given @value into a string representation that allows
2187 * getting back this string later on using gst_value_deserialize().
2189 * Returns: the serialization for @value or NULL if none exists
2192 gst_value_serialize (const GValue * value)
2195 GValue s_val = { 0 };
2196 GstValueTable *table, *best = NULL;
2199 g_return_val_if_fail (G_IS_VALUE (value), NULL);
2201 for (i = 0; i < gst_value_table->len; i++) {
2202 table = &g_array_index (gst_value_table, GstValueTable, i);
2203 if (table->serialize == NULL)
2205 if (table->type == G_VALUE_TYPE (value)) {
2209 if (g_type_is_a (G_VALUE_TYPE (value), table->type)) {
2210 if (!best || g_type_is_a (table->type, best->type))
2215 return best->serialize (value);
2217 g_value_init (&s_val, G_TYPE_STRING);
2218 if (g_value_transform (value, &s_val)) {
2219 s = gst_string_wrap (g_value_get_string (&s_val));
2223 g_value_unset (&s_val);
2229 * gst_value_deserialize:
2230 * @dest: #GValue to fill with contents of deserialization
2231 * @src: string to deserialize
2233 * Tries to deserialize a string into the type specified by the given GValue.
2234 * If the operation succeeds, TRUE is returned, FALSE otherwise.
2236 * Returns: TRUE on success
2239 gst_value_deserialize (GValue * dest, const gchar * src)
2241 GstValueTable *table, *best = NULL;
2244 g_return_val_if_fail (src != NULL, FALSE);
2245 g_return_val_if_fail (G_IS_VALUE (dest), FALSE);
2247 for (i = 0; i < gst_value_table->len; i++) {
2248 table = &g_array_index (gst_value_table, GstValueTable, i);
2249 if (table->serialize == NULL)
2251 if (table->type == G_VALUE_TYPE (dest)) {
2255 if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) {
2256 if (!best || g_type_is_a (table->type, best->type))
2261 return best->deserialize (dest, src);
2267 * gst_type_is_fixed:
2273 gst_type_is_fixed (GType type)
2275 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE ||
2276 type == GST_TYPE_LIST) {
2279 if (G_TYPE_IS_FUNDAMENTAL (type) &&
2280 type < G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) {
2283 if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC
2284 || type == GST_TYPE_FIXED_LIST) {
2292 _gst_value_initialize (void)
2306 GTypeFundamentalInfo finfo = {
2310 //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
2312 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
2313 gst_value_union_funcs = g_array_new (FALSE, FALSE,
2314 sizeof (GstValueUnionInfo));
2315 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
2316 sizeof (GstValueIntersectInfo));
2317 gst_value_subtract_funcs = g_array_new (FALSE, FALSE,
2318 sizeof (GstValueSubtractInfo));
2321 static const GTypeValueTable value_table = {
2322 gst_value_init_fourcc,
2324 gst_value_copy_fourcc,
2327 gst_value_collect_fourcc,
2329 gst_value_lcopy_fourcc
2331 static GstValueTable gst_value = {
2333 gst_value_compare_fourcc,
2334 gst_value_serialize_fourcc,
2335 gst_value_deserialize_fourcc,
2338 info.value_table = &value_table;
2339 gst_type_fourcc = g_type_register_fundamental (g_type_fundamental_next (),
2340 "GstFourcc", &info, &finfo, 0);
2341 gst_value.type = gst_type_fourcc;
2342 gst_value_register (&gst_value);
2346 static const GTypeValueTable value_table = {
2347 gst_value_init_int_range,
2349 gst_value_copy_int_range,
2352 gst_value_collect_int_range,
2354 gst_value_lcopy_int_range
2356 static GstValueTable gst_value = {
2358 gst_value_compare_int_range,
2359 gst_value_serialize_int_range,
2360 gst_value_deserialize_int_range,
2363 info.value_table = &value_table;
2364 gst_type_int_range =
2365 g_type_register_fundamental (g_type_fundamental_next (), "GstIntRange",
2367 gst_value.type = gst_type_int_range;
2368 gst_value_register (&gst_value);
2372 static const GTypeValueTable value_table = {
2373 gst_value_init_double_range,
2375 gst_value_copy_double_range,
2378 gst_value_collect_double_range,
2380 gst_value_lcopy_double_range
2382 static GstValueTable gst_value = {
2384 gst_value_compare_double_range,
2385 gst_value_serialize_double_range,
2386 gst_value_deserialize_double_range,
2389 info.value_table = &value_table;
2390 gst_type_double_range =
2391 g_type_register_fundamental (g_type_fundamental_next (),
2392 "GstDoubleRange", &info, &finfo, 0);
2393 gst_value.type = gst_type_double_range;
2394 gst_value_register (&gst_value);
2398 static const GTypeValueTable value_table = {
2399 gst_value_init_list,
2400 gst_value_free_list,
2401 gst_value_copy_list,
2402 gst_value_list_peek_pointer,
2404 gst_value_collect_list,
2406 gst_value_lcopy_list
2408 static GstValueTable gst_value = {
2410 gst_value_compare_list,
2411 gst_value_serialize_list,
2412 gst_value_deserialize_list,
2415 info.value_table = &value_table;
2416 gst_type_list = g_type_register_fundamental (g_type_fundamental_next (),
2417 "GstValueList", &info, &finfo, 0);
2418 gst_value.type = gst_type_list;
2419 gst_value_register (&gst_value);
2423 static const GTypeValueTable value_table = {
2424 gst_value_init_list,
2425 gst_value_free_list,
2426 gst_value_copy_list,
2427 gst_value_list_peek_pointer,
2429 gst_value_collect_list,
2431 gst_value_lcopy_list
2433 static GstValueTable gst_value = {
2435 gst_value_compare_list,
2436 gst_value_serialize_fixed_list,
2437 gst_value_deserialize_fixed_list,
2440 info.value_table = &value_table;
2441 gst_type_fixed_list =
2442 g_type_register_fundamental (g_type_fundamental_next (),
2443 "GstValueFixedList", &info, &finfo, 0);
2444 gst_value.type = gst_type_fixed_list;
2445 gst_value_register (&gst_value);
2450 static const GTypeValueTable value_table = {
2451 gst_value_init_buffer,
2453 gst_value_copy_buffer,
2456 NULL, /*gst_value_collect_buffer, */
2458 NULL /*gst_value_lcopy_buffer */
2461 static GstValueTable gst_value = {
2463 gst_value_compare_buffer,
2464 gst_value_serialize_buffer,
2465 gst_value_deserialize_buffer,
2469 info.value_table = &value_table;
2471 g_type_register_static (G_TYPE_BOXED, "GstFourcc", &info, 0);
2473 gst_value.type = GST_TYPE_BUFFER;
2474 gst_value_register (&gst_value);
2477 REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
2478 REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
2480 REGISTER_SERIALIZATION (G_TYPE_STRING, string);
2481 REGISTER_SERIALIZATION (G_TYPE_BOOLEAN, boolean);
2482 REGISTER_SERIALIZATION (G_TYPE_ENUM, enum);
2484 REGISTER_SERIALIZATION (G_TYPE_INT, int);
2486 REGISTER_SERIALIZATION (G_TYPE_INT64, int64);
2487 REGISTER_SERIALIZATION (G_TYPE_LONG, long);
2489 REGISTER_SERIALIZATION (G_TYPE_UINT, uint);
2490 REGISTER_SERIALIZATION (G_TYPE_UINT64, uint64);
2491 REGISTER_SERIALIZATION (G_TYPE_ULONG, ulong);
2493 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
2494 gst_value_transform_fourcc_string);
2495 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
2496 gst_value_transform_int_range_string);
2497 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
2498 gst_value_transform_double_range_string);
2499 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
2500 gst_value_transform_list_string);
2501 g_value_register_transform_func (GST_TYPE_FIXED_LIST, G_TYPE_STRING,
2502 gst_value_transform_fixed_list_string);
2504 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
2505 gst_value_intersect_int_int_range);
2506 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
2507 gst_value_intersect_int_range_int_range);
2508 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
2509 gst_value_intersect_double_double_range);
2510 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
2511 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
2513 gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
2514 gst_value_subtract_int_int_range);
2515 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, G_TYPE_INT,
2516 gst_value_subtract_int_range_int);
2517 gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
2518 gst_value_subtract_int_range_int_range);
2519 gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
2520 gst_value_subtract_double_double_range);
2521 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE,
2522 gst_value_subtract_double_range_double);
2523 gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
2524 GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
2526 gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
2527 gst_value_union_int_int_range);
2528 gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
2529 gst_value_union_int_range_int_range);