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 <gobject/gvaluecollector.h>
30 typedef struct _GstValueUnionInfo GstValueUnionInfo;
31 struct _GstValueUnionInfo
35 GstValueUnionFunc func;
38 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
39 struct _GstValueIntersectInfo
43 GstValueIntersectFunc func;
46 GType gst_type_fourcc;
47 GType gst_type_int_range;
48 GType gst_type_double_range;
51 static GArray *gst_value_table;
52 static GArray *gst_value_union_funcs;
53 static GArray *gst_value_intersect_funcs;
55 /*************************************/
59 gst_value_init_list (GValue * value)
61 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
65 gst_value_list_array_copy (const GArray * src)
70 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
71 g_array_set_size (dest, src->len);
72 for (i = 0; i < src->len; i++) {
73 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
74 &g_array_index (src, GValue, i));
81 gst_value_copy_list (const GValue * src_value, GValue * dest_value)
83 dest_value->data[0].v_pointer =
84 gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
88 gst_value_free_list (GValue * value)
91 GArray *src = (GArray *) value->data[0].v_pointer;
93 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
94 for (i = 0; i < src->len; i++) {
95 g_value_unset (&g_array_index (src, GValue, i));
97 g_array_free (src, TRUE);
102 gst_value_list_peek_pointer (const GValue * value)
104 return value->data[0].v_pointer;
108 gst_value_collect_list (GValue * value, guint n_collect_values,
109 GTypeCValue * collect_values, guint collect_flags)
111 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
112 value->data[0].v_pointer = collect_values[0].v_pointer;
113 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
115 value->data[0].v_pointer =
116 gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
122 gst_value_lcopy_list (const GValue * value, guint n_collect_values,
123 GTypeCValue * collect_values, guint collect_flags)
125 GArray **dest = collect_values[0].v_pointer;
128 return g_strdup_printf ("value location for `%s' passed as NULL",
129 G_VALUE_TYPE_NAME (value));
130 if (!value->data[0].v_pointer)
131 return g_strdup_printf ("invalid value given for `%s'",
132 G_VALUE_TYPE_NAME (value));
133 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
134 *dest = (GArray *) value->data[0].v_pointer;
136 *dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
142 * gst_value_list_prepend_value:
146 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
148 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
150 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, prepend_value, 1);
154 * gst_value_list_append_value:
158 gst_value_list_append_value (GValue * value, const GValue * append_value)
160 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
162 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
166 * gst_value_list_get_size:
170 gst_value_list_get_size (const GValue * value)
172 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
174 return ((GArray *) value->data[0].v_pointer)->len;
178 * gst_value_list_get_value:
182 gst_value_list_get_value (const GValue * value, guint index)
184 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
185 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
187 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
192 * gst_value_list_concat:
193 * @dest: an uninitialized #GValue to take the result
194 * @value1: first value to put into the union
195 * @value2: second value to put into the union
197 * Concatenates copies of value1 and value2 into a list. dest will be
198 * initialized to the type GST_TYPE_LIST.
201 gst_value_list_concat (GValue * dest, const GValue * value1,
202 const GValue * value2)
204 guint i, value1_length, value2_length;
207 g_return_if_fail (dest != NULL);
208 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
209 g_return_if_fail (G_IS_VALUE (value1));
210 g_return_if_fail (G_IS_VALUE (value2));
213 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
215 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
216 g_value_init (dest, GST_TYPE_LIST);
217 array = (GArray *) dest->data[0].v_pointer;
218 g_array_set_size (array, value1_length + value2_length);
220 if (GST_VALUE_HOLDS_LIST (value1)) {
221 for (i = 0; i < value1_length; i++) {
222 gst_value_init_and_copy (&g_array_index (array, GValue, i),
223 gst_value_list_get_value (value1, i));
226 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
229 if (GST_VALUE_HOLDS_LIST (value2)) {
230 for (i = 0; i < value2_length; i++) {
231 gst_value_init_and_copy (&g_array_index (array, GValue,
232 i + value1_length), gst_value_list_get_value (value2, i));
235 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
241 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
249 array = src_value->data[0].v_pointer;
251 s = g_string_new ("{ ");
252 for (i = 0; i < array->len; i++) {
253 list_value = &g_array_index (array, GValue, i);
256 g_string_append (s, ", ");
258 list_s = g_strdup_value_contents (list_value);
259 g_string_append (s, list_s);
262 g_string_append (s, " }");
264 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
268 gst_value_compare_list (const GValue * value1, const GValue * value2)
271 GArray *array1 = value1->data[0].v_pointer;
272 GArray *array2 = value2->data[0].v_pointer;
276 if (array1->len != array2->len)
277 return GST_VALUE_UNORDERED;
279 for (i = 0; i < array1->len; i++) {
280 v1 = &g_array_index (array1, GValue, i);
281 for (j = 0; j < array1->len; j++) {
282 v2 = &g_array_index (array2, GValue, j);
283 if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
286 if (j == array1->len) {
287 return GST_VALUE_UNORDERED;
291 return GST_VALUE_EQUAL;
295 gst_value_serialize_list (const GValue * value)
298 GArray *array = value->data[0].v_pointer;
303 s = g_string_new ("{ ");
304 for (i = 0; i < array->len; i++) {
305 v = &g_array_index (array, GValue, i);
306 s_val = gst_value_serialize (v);
307 g_string_append (s, s_val);
309 if (i < array->len - 1) {
310 g_string_append (s, ", ");
313 g_string_append (s, " }");
314 return g_string_free (s, FALSE);
318 gst_value_deserialize_list (GValue * dest, const char *s)
320 g_warning ("unimplemented");
324 /*************************************/
328 gst_value_init_fourcc (GValue * value)
330 value->data[0].v_int = 0;
334 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
336 dest_value->data[0].v_int = src_value->data[0].v_int;
340 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
341 GTypeCValue * collect_values, guint collect_flags)
343 value->data[0].v_int = collect_values[0].v_int;
349 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
350 GTypeCValue * collect_values, guint collect_flags)
352 guint32 *fourcc_p = collect_values[0].v_pointer;
355 return g_strdup_printf ("value location for `%s' passed as NULL",
356 G_VALUE_TYPE_NAME (value));
358 *fourcc_p = value->data[0].v_int;
364 * gst_value_set_fourcc:
368 gst_value_set_fourcc (GValue * value, guint32 fourcc)
370 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
372 value->data[0].v_int = fourcc;
376 * gst_value_get_fourcc:
380 gst_value_get_fourcc (const GValue * value)
382 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
384 return value->data[0].v_int;
388 gst_value_transform_fourcc_string (const GValue * src_value,
391 guint32 fourcc = src_value->data[0].v_int;
393 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
394 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
395 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
396 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
397 dest_value->data[0].v_pointer =
398 g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
400 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
405 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
407 if (value2->data[0].v_int == value1->data[0].v_int)
408 return GST_VALUE_EQUAL;
409 return GST_VALUE_UNORDERED;
413 gst_value_serialize_fourcc (const GValue * value)
415 guint32 fourcc = value->data[0].v_int;
417 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
418 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
419 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
420 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
421 return g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
423 return g_strdup_printf ("0x%08x", fourcc);
428 gst_value_deserialize_fourcc (GValue * dest, const char *s)
430 gboolean ret = FALSE;
434 if (strlen (s) == 4) {
435 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
437 } else if (g_ascii_isdigit (*s)) {
438 fourcc = strtoul (s, &end, 0);
443 gst_value_set_fourcc (dest, fourcc);
448 /*************************************/
452 gst_value_init_int_range (GValue * value)
454 value->data[0].v_int = 0;
455 value->data[1].v_int = 0;
459 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
461 dest_value->data[0].v_int = src_value->data[0].v_int;
462 dest_value->data[1].v_int = src_value->data[1].v_int;
466 gst_value_collect_int_range (GValue * value, guint n_collect_values,
467 GTypeCValue * collect_values, guint collect_flags)
470 value->data[0].v_int = collect_values[0].v_int;
471 value->data[1].v_int = collect_values[1].v_int;
477 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
478 GTypeCValue * collect_values, guint collect_flags)
480 guint32 *int_range_start = collect_values[0].v_pointer;
481 guint32 *int_range_end = collect_values[1].v_pointer;
483 if (!int_range_start)
484 return g_strdup_printf ("start value location for `%s' passed as NULL",
485 G_VALUE_TYPE_NAME (value));
487 return g_strdup_printf ("end value location for `%s' passed as NULL",
488 G_VALUE_TYPE_NAME (value));
490 *int_range_start = value->data[0].v_int;
491 *int_range_end = value->data[1].v_int;
497 * gst_value_set_int_range:
501 gst_value_set_int_range (GValue * value, int start, int end)
503 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
505 value->data[0].v_int = start;
506 value->data[1].v_int = end;
510 * gst_value_get_int_range_min:
514 gst_value_get_int_range_min (const GValue * value)
516 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
518 return value->data[0].v_int;
522 * gst_value_get_int_range_max:
526 gst_value_get_int_range_max (const GValue * value)
528 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
530 return value->data[1].v_int;
534 gst_value_transform_int_range_string (const GValue * src_value,
537 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
538 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
542 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
544 if (value2->data[0].v_int == value1->data[0].v_int &&
545 value2->data[0].v_int == value1->data[0].v_int)
546 return GST_VALUE_EQUAL;
547 return GST_VALUE_UNORDERED;
551 gst_value_serialize_int_range (const GValue * value)
553 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
554 value->data[1].v_int);
558 gst_value_deserialize_int_range (GValue * dest, const char *s)
560 g_warning ("unimplemented");
564 /*************************************/
568 gst_value_init_double_range (GValue * value)
570 value->data[0].v_double = 0;
571 value->data[1].v_double = 0;
575 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
577 dest_value->data[0].v_double = src_value->data[0].v_double;
578 dest_value->data[1].v_double = src_value->data[1].v_double;
582 gst_value_collect_double_range (GValue * value, guint n_collect_values,
583 GTypeCValue * collect_values, guint collect_flags)
585 value->data[0].v_double = collect_values[0].v_double;
586 value->data[1].v_double = collect_values[1].v_double;
592 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
593 GTypeCValue * collect_values, guint collect_flags)
595 gdouble *double_range_start = collect_values[0].v_pointer;
596 gdouble *double_range_end = collect_values[1].v_pointer;
598 if (!double_range_start)
599 return g_strdup_printf ("start value location for `%s' passed as NULL",
600 G_VALUE_TYPE_NAME (value));
601 if (!double_range_end)
602 return g_strdup_printf ("end value location for `%s' passed as NULL",
603 G_VALUE_TYPE_NAME (value));
605 *double_range_start = value->data[0].v_double;
606 *double_range_end = value->data[1].v_double;
612 * gst_value_set_double_range:
616 gst_value_set_double_range (GValue * value, double start, double end)
618 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
620 value->data[0].v_double = start;
621 value->data[1].v_double = end;
625 * gst_value_get_double_range_min:
629 gst_value_get_double_range_min (const GValue * value)
631 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
633 return value->data[0].v_double;
637 * gst_value_get_double_range_max:
641 gst_value_get_double_range_max (const GValue * value)
643 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
645 return value->data[1].v_double;
649 gst_value_transform_double_range_string (const GValue * src_value,
652 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
654 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
655 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
656 src_value->data[0].v_double),
657 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
658 src_value->data[1].v_double));
662 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
664 if (value2->data[0].v_double == value1->data[0].v_double &&
665 value2->data[0].v_double == value1->data[0].v_double)
666 return GST_VALUE_EQUAL;
667 return GST_VALUE_UNORDERED;
671 gst_value_serialize_double_range (const GValue * value)
673 char d1[G_ASCII_DTOSTR_BUF_SIZE];
674 char d2[G_ASCII_DTOSTR_BUF_SIZE];
676 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
677 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
678 return g_strdup_printf ("[ %s, %s ]", d1, d2);
682 gst_value_deserialize_double_range (GValue * dest, const char *s)
684 g_warning ("unimplemented");
688 /*************************************/
692 * gst_value_set_caps:
696 gst_value_set_caps (GValue * value, const GstCaps * caps)
698 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
700 g_value_set_boxed (value, caps);
704 * gst_value_get_caps:
708 gst_value_get_caps (const GValue * value)
710 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
712 return (GstCaps *) g_value_get_boxed (value);
715 /*************************************/
719 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
721 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
722 return GST_VALUE_EQUAL;
723 return GST_VALUE_UNORDERED;
727 gst_value_serialize_boolean (const GValue * value)
729 if (value->data[0].v_int) {
730 return g_strdup ("true");
732 return g_strdup ("false");
736 gst_value_deserialize_boolean (GValue * dest, const char *s)
738 gboolean ret = FALSE;
740 if (g_ascii_strcasecmp (s, "true") == 0 ||
741 g_ascii_strcasecmp (s, "yes") == 0 ||
742 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
743 g_value_set_boolean (dest, TRUE);
745 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
746 g_ascii_strcasecmp (s, "no") == 0 ||
747 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
748 g_value_set_boolean (dest, FALSE);
755 /*************************************/
759 gst_value_compare_int (const GValue * value1, const GValue * value2)
761 if (value1->data[0].v_int > value2->data[0].v_int)
762 return GST_VALUE_GREATER_THAN;
763 if (value1->data[0].v_int < value2->data[0].v_int)
764 return GST_VALUE_LESS_THAN;
765 return GST_VALUE_EQUAL;
769 gst_value_serialize_int (const GValue * value)
771 return g_strdup_printf ("%d", value->data[0].v_int);
775 gst_strtoi (const char *s, char **end, int base)
780 i = -(int) strtoul (s + 1, end, base);
782 i = strtoul (s, end, base);
789 gst_value_deserialize_int (GValue * dest, const char *s)
793 gboolean ret = FALSE;
795 x = gst_strtoi (s, &end, 0);
799 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
802 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
805 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
808 } else if (g_ascii_strcasecmp (s, "min") == 0) {
811 } else if (g_ascii_strcasecmp (s, "max") == 0) {
817 g_value_set_int (dest, x);
822 /*************************************/
826 gst_value_compare_double (const GValue * value1, const GValue * value2)
828 if (value1->data[0].v_double > value2->data[0].v_double)
829 return GST_VALUE_GREATER_THAN;
830 if (value1->data[0].v_double < value2->data[0].v_double)
831 return GST_VALUE_LESS_THAN;
832 if (value1->data[0].v_double == value2->data[0].v_double)
833 return GST_VALUE_EQUAL;
834 return GST_VALUE_UNORDERED;
838 gst_value_serialize_double (const GValue * value)
840 char d[G_ASCII_DTOSTR_BUF_SIZE];
842 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
847 gst_value_deserialize_double (GValue * dest, const char *s)
850 gboolean ret = FALSE;
853 x = g_ascii_strtod (s, &end);
857 if (g_ascii_strcasecmp (s, "min") == 0) {
860 } else if (g_ascii_strcasecmp (s, "max") == 0) {
866 g_value_set_double (dest, x);
871 /*************************************/
875 gst_value_compare_string (const GValue * value1, const GValue * value2)
877 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
880 return GST_VALUE_LESS_THAN;
882 return GST_VALUE_GREATER_THAN;
883 return GST_VALUE_EQUAL;
886 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
887 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
891 gst_string_wrap (const char *s)
896 gboolean wrap = FALSE;
901 if (GST_ASCII_IS_STRING (*t)) {
903 } else if (*t < 0x20 || *t >= 0x7f) {
916 e = d = g_malloc (len + 3);
921 if (GST_ASCII_IS_STRING (*t)) {
923 } else if (*t < 0x20 || *t >= 0x7f) {
925 *e++ = '0' + ((*t) >> 6);
926 *e++ = '0' + (((*t) >> 3) & 0x7);
927 *e++ = '0' + ((*t++) & 0x7);
940 gst_value_serialize_string (const GValue * value)
942 return gst_string_wrap (value->data[0].v_pointer);
946 gst_value_deserialize_string (GValue * dest, const char *s)
948 g_value_set_string (dest, s);
953 /*************************************/
956 /*************************************/
960 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
963 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
964 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
966 if (src2->data[0].v_int <= src1->data[0].v_int &&
967 src2->data[1].v_int >= src1->data[0].v_int) {
968 gst_value_init_and_copy (dest, src1);
976 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
982 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
983 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
985 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
986 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
989 g_value_init (dest, GST_TYPE_INT_RANGE);
990 gst_value_set_int_range (dest, min, max);
994 g_value_init (dest, G_TYPE_INT);
995 g_value_set_int (dest, min);
1003 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
1004 const GValue * src2)
1006 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_DOUBLE, FALSE);
1007 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1009 if (src2->data[0].v_double <= src1->data[0].v_double &&
1010 src2->data[1].v_double >= src1->data[0].v_double) {
1011 gst_value_init_and_copy (dest, src1);
1019 gst_value_intersect_double_range_double_range (GValue * dest,
1020 const GValue * src1, const GValue * src2)
1025 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_DOUBLE_RANGE, FALSE);
1026 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1028 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
1029 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
1032 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
1033 gst_value_set_double_range (dest, min, max);
1037 g_value_init (dest, G_TYPE_DOUBLE);
1038 g_value_set_int (dest, min);
1046 gst_value_intersect_list (GValue * dest, const GValue * value1,
1047 const GValue * value2)
1050 GValue intersection = { 0, };
1051 gboolean ret = FALSE;
1053 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value1), FALSE);
1055 size = gst_value_list_get_size (value1);
1056 for (i = 0; i < size; i++) {
1057 const GValue *cur = gst_value_list_get_value (value1, i);
1059 if (gst_value_intersect (&intersection, cur, value2)) {
1062 gst_value_init_and_copy (dest, &intersection);
1064 } else if (GST_VALUE_HOLDS_LIST (dest)) {
1065 gst_value_list_append_value (dest, &intersection);
1067 GValue temp = { 0, };
1069 gst_value_init_and_copy (&temp, dest);
1070 g_value_unset (dest);
1071 gst_value_list_concat (dest, &temp, &intersection);
1073 g_value_unset (&intersection);
1081 /*************************************/
1084 * gst_value_can_compare:
1088 gst_value_can_compare (const GValue * value1, const GValue * value2)
1090 GstValueTable *table;
1093 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1095 for (i = 0; i < gst_value_table->len; i++) {
1096 table = &g_array_index (gst_value_table, GstValueTable, i);
1097 if (table->type == G_VALUE_TYPE (value1) && table->compare)
1105 * gst_value_compare:
1109 gst_value_compare (const GValue * value1, const GValue * value2)
1111 GstValueTable *table;
1114 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1115 return GST_VALUE_UNORDERED;
1117 for (i = 0; i < gst_value_table->len; i++) {
1118 table = &g_array_index (gst_value_table, GstValueTable, i);
1119 if (table->type != G_VALUE_TYPE (value1) || table->compare == NULL)
1122 return table->compare (value1, value2);
1125 g_critical ("unable to compare values of type %s\n",
1126 g_type_name (G_VALUE_TYPE (value1)));
1127 return GST_VALUE_UNORDERED;
1133 * gst_value_can_union:
1137 gst_value_can_union (const GValue * value1, const GValue * value2)
1139 GstValueUnionInfo *union_info;
1142 for (i = 0; i < gst_value_union_funcs->len; i++) {
1143 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1144 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1145 union_info->type2 == G_VALUE_TYPE (value2))
1157 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
1159 GstValueUnionInfo *union_info;
1162 for (i = 0; i < gst_value_union_funcs->len; i++) {
1163 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1164 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1165 union_info->type2 == G_VALUE_TYPE (value2)) {
1166 return union_info->func (dest, value1, value2);
1170 gst_value_list_concat (dest, value1, value2);
1175 * gst_value_register_union_func:
1179 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
1181 GstValueUnionInfo union_info;
1183 union_info.type1 = type1;
1184 union_info.type2 = type2;
1185 union_info.func = func;
1187 g_array_append_val (gst_value_union_funcs, union_info);
1193 * gst_value_can_intersect:
1197 gst_value_can_intersect (const GValue * value1, const GValue * value2)
1199 GstValueIntersectInfo *intersect_info;
1203 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
1206 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1207 intersect_info = &g_array_index (gst_value_intersect_funcs,
1208 GstValueIntersectInfo, i);
1209 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1210 intersect_info->type2 == G_VALUE_TYPE (value2))
1214 return gst_value_can_compare (value1, value2);
1218 * gst_value_intersect:
1222 gst_value_intersect (GValue * dest, const GValue * value1,
1223 const GValue * value2)
1225 GstValueIntersectInfo *intersect_info;
1229 /* special cases first */
1230 if (GST_VALUE_HOLDS_LIST (value1))
1231 return gst_value_intersect_list (dest, value1, value2);
1232 if (GST_VALUE_HOLDS_LIST (value2))
1233 return gst_value_intersect_list (dest, value2, value1);
1235 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1236 intersect_info = &g_array_index (gst_value_intersect_funcs,
1237 GstValueIntersectInfo, i);
1238 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1239 intersect_info->type2 == G_VALUE_TYPE (value2)) {
1240 ret = intersect_info->func (dest, value1, value2);
1243 if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
1244 intersect_info->type2 == G_VALUE_TYPE (value1)) {
1245 ret = intersect_info->func (dest, value2, value1);
1250 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
1251 gst_value_init_and_copy (dest, value1);
1259 * gst_value_register_intersection_func:
1263 gst_value_register_intersect_func (GType type1, GType type2,
1264 GstValueIntersectFunc func)
1266 GstValueIntersectInfo intersect_info;
1268 intersect_info.type1 = type1;
1269 intersect_info.type2 = type2;
1270 intersect_info.func = func;
1272 g_array_append_val (gst_value_intersect_funcs, intersect_info);
1276 * gst_value_register:
1280 gst_value_register (const GstValueTable * table)
1282 g_array_append_val (gst_value_table, *table);
1286 * gst_value_init_and_copy:
1290 gst_value_init_and_copy (GValue * dest, const GValue * src)
1292 g_value_init (dest, G_VALUE_TYPE (src));
1293 g_value_copy (src, dest);
1297 * gst_value_serialize:
1301 gst_value_serialize (const GValue * value)
1304 GValue s_val = { 0 };
1305 GstValueTable *table;
1308 for (i = 0; i < gst_value_table->len; i++) {
1309 table = &g_array_index (gst_value_table, GstValueTable, i);
1310 if (table->type != G_VALUE_TYPE (value) || table->serialize == NULL)
1313 return table->serialize (value);
1316 g_value_init (&s_val, G_TYPE_STRING);
1317 g_value_transform (value, &s_val);
1318 s = gst_string_wrap (g_value_get_string (&s_val));
1319 g_value_unset (&s_val);
1325 * gst_value_deserialize:
1329 gst_value_deserialize (GValue * dest, const gchar * src)
1331 GstValueTable *table;
1334 for (i = 0; i < gst_value_table->len; i++) {
1335 table = &g_array_index (gst_value_table, GstValueTable, i);
1336 if (table->type != G_VALUE_TYPE (dest) || table->deserialize == NULL)
1339 return table->deserialize (dest, src);
1346 _gst_value_initialize (void)
1361 //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
1363 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
1364 gst_value_union_funcs = g_array_new (FALSE, FALSE,
1365 sizeof (GstValueUnionInfo));
1366 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
1367 sizeof (GstValueIntersectInfo));
1370 static const GTypeValueTable value_table = {
1371 gst_value_init_fourcc,
1373 gst_value_copy_fourcc,
1376 gst_value_collect_fourcc,
1378 gst_value_lcopy_fourcc
1380 static GstValueTable gst_value = {
1382 gst_value_compare_fourcc,
1383 gst_value_serialize_fourcc,
1384 gst_value_deserialize_fourcc,
1387 info.value_table = &value_table;
1389 g_type_register_static (G_TYPE_BOXED, "GstFourcc", &info, 0);
1390 gst_value.type = gst_type_fourcc;
1391 gst_value_register (&gst_value);
1395 static const GTypeValueTable value_table = {
1396 gst_value_init_int_range,
1398 gst_value_copy_int_range,
1401 gst_value_collect_int_range,
1403 gst_value_lcopy_int_range
1405 static GstValueTable gst_value = {
1407 gst_value_compare_int_range,
1408 gst_value_serialize_int_range,
1409 gst_value_deserialize_int_range,
1412 info.value_table = &value_table;
1413 gst_type_int_range =
1414 g_type_register_static (G_TYPE_BOXED, "GstIntRange", &info, 0);
1415 gst_value.type = gst_type_int_range;
1416 gst_value_register (&gst_value);
1420 static const GTypeValueTable value_table = {
1421 gst_value_init_double_range,
1423 gst_value_copy_double_range,
1426 gst_value_collect_double_range,
1428 gst_value_lcopy_double_range
1430 static GstValueTable gst_value = {
1432 gst_value_compare_double_range,
1433 gst_value_serialize_double_range,
1434 gst_value_deserialize_double_range,
1437 info.value_table = &value_table;
1438 gst_type_double_range =
1439 g_type_register_static (G_TYPE_BOXED, "GstDoubleRange", &info, 0);
1440 gst_value.type = gst_type_double_range;
1441 gst_value_register (&gst_value);
1445 static const GTypeValueTable value_table = {
1446 gst_value_init_list,
1447 gst_value_free_list,
1448 gst_value_copy_list,
1449 gst_value_list_peek_pointer,
1451 gst_value_collect_list,
1453 gst_value_lcopy_list
1455 static GstValueTable gst_value = {
1457 gst_value_compare_list,
1458 gst_value_serialize_list,
1459 gst_value_deserialize_list,
1462 info.value_table = &value_table;
1464 g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
1465 gst_value.type = gst_type_list;
1466 gst_value_register (&gst_value);
1470 static const GstValueTable gst_value = {
1472 gst_value_compare_int,
1473 gst_value_serialize_int,
1474 gst_value_deserialize_int,
1477 gst_value_register (&gst_value);
1481 static const GstValueTable gst_value = {
1483 gst_value_compare_double,
1484 gst_value_serialize_double,
1485 gst_value_deserialize_double,
1488 gst_value_register (&gst_value);
1492 static const GstValueTable gst_value = {
1494 gst_value_compare_string,
1495 gst_value_serialize_string,
1496 gst_value_deserialize_string,
1499 gst_value_register (&gst_value);
1503 static const GstValueTable gst_value = {
1505 gst_value_compare_boolean,
1506 gst_value_serialize_boolean,
1507 gst_value_deserialize_boolean,
1510 gst_value_register (&gst_value);
1513 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
1514 gst_value_transform_fourcc_string);
1515 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
1516 gst_value_transform_int_range_string);
1517 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
1518 gst_value_transform_double_range_string);
1519 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
1520 gst_value_transform_list_string);
1522 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
1523 gst_value_intersect_int_int_range);
1524 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
1525 gst_value_intersect_int_range_int_range);
1526 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
1527 gst_value_intersect_double_double_range);
1528 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
1529 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);