49172580c7fb3be0065e818fd629db79dd0c7d28
[platform/upstream/gstreamer.git] / gst / gstvalue.c
1 /* GStreamer
2  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <gst/gst.h>
27 #include <gobject/gvaluecollector.h>
28
29
30 typedef struct _GstValueUnionInfo GstValueUnionInfo;
31 struct _GstValueUnionInfo
32 {
33   GType type1;
34   GType type2;
35   GstValueUnionFunc func;
36 };
37
38 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
39 struct _GstValueIntersectInfo
40 {
41   GType type1;
42   GType type2;
43   GstValueIntersectFunc func;
44 };
45
46 GType gst_type_fourcc;
47 GType gst_type_int_range;
48 GType gst_type_double_range;
49 GType gst_type_list;
50
51 static GArray *gst_value_table;
52 static GArray *gst_value_union_funcs;
53 static GArray *gst_value_intersect_funcs;
54
55 /*************************************/
56 /* list */
57
58 static void
59 gst_value_init_list (GValue * value)
60 {
61   value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
62 }
63
64 static GArray *
65 gst_value_list_array_copy (const GArray * src)
66 {
67   GArray *dest;
68   gint i;
69
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));
75   }
76
77   return dest;
78 }
79
80 static void
81 gst_value_copy_list (const GValue * src_value, GValue * dest_value)
82 {
83   dest_value->data[0].v_pointer =
84       gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
85 }
86
87 static void
88 gst_value_free_list (GValue * value)
89 {
90   gint i;
91   GArray *src = (GArray *) value->data[0].v_pointer;
92
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));
96     }
97     g_array_free (src, TRUE);
98   }
99 }
100
101 static gpointer
102 gst_value_list_peek_pointer (const GValue * value)
103 {
104   return value->data[0].v_pointer;
105 }
106
107 static gchar *
108 gst_value_collect_list (GValue * value, guint n_collect_values,
109     GTypeCValue * collect_values, guint collect_flags)
110 {
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;
114   } else {
115     value->data[0].v_pointer =
116         gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
117   }
118   return NULL;
119 }
120
121 static gchar *
122 gst_value_lcopy_list (const GValue * value, guint n_collect_values,
123     GTypeCValue * collect_values, guint collect_flags)
124 {
125   GArray **dest = collect_values[0].v_pointer;
126
127   if (!dest)
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;
135   } else {
136     *dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
137   }
138   return NULL;
139 }
140
141 /**
142  * gst_value_list_prepend_value:
143  * @value: a GstValueList to prepend a value to
144  * @prepend_value: the value to prepend
145  *
146  * Prepends @prepend_value to the GstValueList in @value.
147  *
148  */
149 void
150 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
151 {
152   g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
153
154   g_array_prepend_vals ((GArray *) value->data[0].v_pointer, prepend_value, 1);
155 }
156
157 /**
158  * gst_value_list_append_value:
159  * @value: a GstValueList to append a value to
160  * @apppend_value: the value to append
161  *
162  * Appends @append_value to the GstValueList in @value.
163  */
164 void
165 gst_value_list_append_value (GValue * value, const GValue * append_value)
166 {
167   g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
168
169   g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
170 }
171
172 /**
173  * gst_value_list_get_size:
174  * @value: a GstValueList
175  *
176  * Gets the number of values contained in @value.
177  *
178  * Returns: the number of values
179  */
180 guint
181 gst_value_list_get_size (const GValue * value)
182 {
183   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
184
185   return ((GArray *) value->data[0].v_pointer)->len;
186 }
187
188 /**
189  * gst_value_list_get_value:
190  * @value: a GstValueList
191  * @index
192  *
193  * Gets the value that is a member of the list contained in @value and
194  * has the index @index.
195  *
196  * Returns: the value at the given index
197  */
198 const GValue *
199 gst_value_list_get_value (const GValue * value, guint index)
200 {
201   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
202   g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
203
204   return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
205       GValue, index);
206 }
207
208 /**
209  * gst_value_list_concat:
210  * @dest: an uninitialized #GValue to take the result
211  * @value1: first value to put into the union
212  * @value2: second value to put into the union
213  *
214  * Concatenates copies of value1 and value2 into a list.  The value
215  * @dest is initialized to the type GST_TYPE_LIST.
216  */
217 void
218 gst_value_list_concat (GValue * dest, const GValue * value1,
219     const GValue * value2)
220 {
221   guint i, value1_length, value2_length;
222   GArray *array;
223
224   g_return_if_fail (dest != NULL);
225   g_return_if_fail (G_VALUE_TYPE (dest) == 0);
226   g_return_if_fail (G_IS_VALUE (value1));
227   g_return_if_fail (G_IS_VALUE (value2));
228
229   value1_length =
230       (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
231   value2_length =
232       (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
233   g_value_init (dest, GST_TYPE_LIST);
234   array = (GArray *) dest->data[0].v_pointer;
235   g_array_set_size (array, value1_length + value2_length);
236
237   if (GST_VALUE_HOLDS_LIST (value1)) {
238     for (i = 0; i < value1_length; i++) {
239       gst_value_init_and_copy (&g_array_index (array, GValue, i),
240           gst_value_list_get_value (value1, i));
241     }
242   } else {
243     gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
244   }
245
246   if (GST_VALUE_HOLDS_LIST (value2)) {
247     for (i = 0; i < value2_length; i++) {
248       gst_value_init_and_copy (&g_array_index (array, GValue,
249               i + value1_length), gst_value_list_get_value (value2, i));
250     }
251   } else {
252     gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
253         value2);
254   }
255 }
256
257 static void
258 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
259 {
260   GValue *list_value;
261   GArray *array;
262   GString *s;
263   int i;
264   char *list_s;
265
266   array = src_value->data[0].v_pointer;
267
268   s = g_string_new ("{ ");
269   for (i = 0; i < array->len; i++) {
270     list_value = &g_array_index (array, GValue, i);
271
272     if (i != 0) {
273       g_string_append (s, ", ");
274     }
275     list_s = g_strdup_value_contents (list_value);
276     g_string_append (s, list_s);
277     g_free (list_s);
278   }
279   g_string_append (s, " }");
280
281   dest_value->data[0].v_pointer = g_string_free (s, FALSE);
282 }
283
284 static int
285 gst_value_compare_list (const GValue * value1, const GValue * value2)
286 {
287   int i, j;
288   GArray *array1 = value1->data[0].v_pointer;
289   GArray *array2 = value2->data[0].v_pointer;
290   GValue *v1;
291   GValue *v2;
292
293   if (array1->len != array2->len)
294     return GST_VALUE_UNORDERED;
295
296   for (i = 0; i < array1->len; i++) {
297     v1 = &g_array_index (array1, GValue, i);
298     for (j = 0; j < array1->len; j++) {
299       v2 = &g_array_index (array2, GValue, j);
300       if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
301         break;
302     }
303     if (j == array1->len) {
304       return GST_VALUE_UNORDERED;
305     }
306   }
307
308   return GST_VALUE_EQUAL;
309 }
310
311 static char *
312 gst_value_serialize_list (const GValue * value)
313 {
314   int i;
315   GArray *array = value->data[0].v_pointer;
316   GString *s;
317   GValue *v;
318   gchar *s_val;
319
320   s = g_string_new ("{ ");
321   for (i = 0; i < array->len; i++) {
322     v = &g_array_index (array, GValue, i);
323     s_val = gst_value_serialize (v);
324     g_string_append (s, s_val);
325     g_free (s_val);
326     if (i < array->len - 1) {
327       g_string_append (s, ", ");
328     }
329   }
330   g_string_append (s, " }");
331   return g_string_free (s, FALSE);
332 }
333
334 static gboolean
335 gst_value_deserialize_list (GValue * dest, const char *s)
336 {
337   g_warning ("unimplemented");
338   return FALSE;
339 }
340
341 /*************************************/
342 /* fourcc */
343
344 static void
345 gst_value_init_fourcc (GValue * value)
346 {
347   value->data[0].v_int = 0;
348 }
349
350 static void
351 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
352 {
353   dest_value->data[0].v_int = src_value->data[0].v_int;
354 }
355
356 static gchar *
357 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
358     GTypeCValue * collect_values, guint collect_flags)
359 {
360   value->data[0].v_int = collect_values[0].v_int;
361
362   return NULL;
363 }
364
365 static gchar *
366 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
367     GTypeCValue * collect_values, guint collect_flags)
368 {
369   guint32 *fourcc_p = collect_values[0].v_pointer;
370
371   if (!fourcc_p)
372     return g_strdup_printf ("value location for `%s' passed as NULL",
373         G_VALUE_TYPE_NAME (value));
374
375   *fourcc_p = value->data[0].v_int;
376
377   return NULL;
378 }
379
380 /**
381  * gst_value_set_fourcc:
382  * @value: a GValue initialized to GST_TYPE_FOURCC
383  * @fourcc: the fourcc to set
384  *
385  * Sets @value to @fourcc.
386  */
387 void
388 gst_value_set_fourcc (GValue * value, guint32 fourcc)
389 {
390   g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
391
392   value->data[0].v_int = fourcc;
393 }
394
395 /**
396  * gst_value_get_fourcc:
397  * @value: a GValue initialized to GST_TYPE_FOURCC
398  *
399  * Gets the fourcc contained in @value.
400  *
401  * Returns: the fourcc contained in @value.
402  */
403 guint32
404 gst_value_get_fourcc (const GValue * value)
405 {
406   g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
407
408   return value->data[0].v_int;
409 }
410
411 static void
412 gst_value_transform_fourcc_string (const GValue * src_value,
413     GValue * dest_value)
414 {
415   guint32 fourcc = src_value->data[0].v_int;
416
417   if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
418       g_ascii_isprint ((fourcc >> 8) & 0xff) &&
419       g_ascii_isprint ((fourcc >> 16) & 0xff) &&
420       g_ascii_isprint ((fourcc >> 24) & 0xff)) {
421     dest_value->data[0].v_pointer =
422         g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
423   } else {
424     dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
425   }
426 }
427
428 static int
429 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
430 {
431   if (value2->data[0].v_int == value1->data[0].v_int)
432     return GST_VALUE_EQUAL;
433   return GST_VALUE_UNORDERED;
434 }
435
436 static char *
437 gst_value_serialize_fourcc (const GValue * value)
438 {
439   guint32 fourcc = value->data[0].v_int;
440
441   if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
442       g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
443       g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
444       g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
445     return g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
446   } else {
447     return g_strdup_printf ("0x%08x", fourcc);
448   }
449 }
450
451 static gboolean
452 gst_value_deserialize_fourcc (GValue * dest, const char *s)
453 {
454   gboolean ret = FALSE;
455   guint32 fourcc = 0;
456   char *end;
457
458   if (strlen (s) == 4) {
459     fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
460     ret = TRUE;
461   } else if (g_ascii_isdigit (*s)) {
462     fourcc = strtoul (s, &end, 0);
463     if (*end == 0) {
464       ret = TRUE;
465     }
466   }
467   gst_value_set_fourcc (dest, fourcc);
468
469   return ret;
470 }
471
472 /*************************************/
473 /* int range */
474
475 static void
476 gst_value_init_int_range (GValue * value)
477 {
478   value->data[0].v_int = 0;
479   value->data[1].v_int = 0;
480 }
481
482 static void
483 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
484 {
485   dest_value->data[0].v_int = src_value->data[0].v_int;
486   dest_value->data[1].v_int = src_value->data[1].v_int;
487 }
488
489 static gchar *
490 gst_value_collect_int_range (GValue * value, guint n_collect_values,
491     GTypeCValue * collect_values, guint collect_flags)
492 {
493   /* FIXME */
494   value->data[0].v_int = collect_values[0].v_int;
495   value->data[1].v_int = collect_values[1].v_int;
496
497   return NULL;
498 }
499
500 static gchar *
501 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
502     GTypeCValue * collect_values, guint collect_flags)
503 {
504   guint32 *int_range_start = collect_values[0].v_pointer;
505   guint32 *int_range_end = collect_values[1].v_pointer;
506
507   if (!int_range_start)
508     return g_strdup_printf ("start value location for `%s' passed as NULL",
509         G_VALUE_TYPE_NAME (value));
510   if (!int_range_end)
511     return g_strdup_printf ("end value location for `%s' passed as NULL",
512         G_VALUE_TYPE_NAME (value));
513
514   *int_range_start = value->data[0].v_int;
515   *int_range_end = value->data[1].v_int;
516
517   return NULL;
518 }
519
520 /**
521  * gst_value_set_int_range:
522  * @value: a GValue initialized to GST_TYPE_INT_RANGE
523  * @start: the start of the range
524  * @end: the end of the range
525  *
526  * Sets @value to the range specified by @start and @end.
527  */
528 void
529 gst_value_set_int_range (GValue * value, int start, int end)
530 {
531   g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
532
533   value->data[0].v_int = start;
534   value->data[1].v_int = end;
535 }
536
537 /**
538  * gst_value_get_int_range_min:
539  * @value: a GValue initialized to GST_TYPE_INT_RANGE
540  *
541  * Gets the minimum of the range specified by @value.
542  *
543  * Returns: the minumum of the range
544  */
545 int
546 gst_value_get_int_range_min (const GValue * value)
547 {
548   g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
549
550   return value->data[0].v_int;
551 }
552
553 /**
554  * gst_value_get_int_range_max:
555  * @value: a GValue initialized to GST_TYPE_INT_RANGE
556  *
557  * Gets the maximum of the range specified by @value.
558  *
559  * Returns: the maxumum of the range
560  */
561 int
562 gst_value_get_int_range_max (const GValue * value)
563 {
564   g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
565
566   return value->data[1].v_int;
567 }
568
569 static void
570 gst_value_transform_int_range_string (const GValue * src_value,
571     GValue * dest_value)
572 {
573   dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
574       (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
575 }
576
577 static int
578 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
579 {
580   if (value2->data[0].v_int == value1->data[0].v_int &&
581       value2->data[0].v_int == value1->data[0].v_int)
582     return GST_VALUE_EQUAL;
583   return GST_VALUE_UNORDERED;
584 }
585
586 static char *
587 gst_value_serialize_int_range (const GValue * value)
588 {
589   return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
590       value->data[1].v_int);
591 }
592
593 static gboolean
594 gst_value_deserialize_int_range (GValue * dest, const char *s)
595 {
596   g_warning ("unimplemented");
597   return FALSE;
598 }
599
600 /*************************************/
601 /* double range */
602
603 static void
604 gst_value_init_double_range (GValue * value)
605 {
606   value->data[0].v_double = 0;
607   value->data[1].v_double = 0;
608 }
609
610 static void
611 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
612 {
613   dest_value->data[0].v_double = src_value->data[0].v_double;
614   dest_value->data[1].v_double = src_value->data[1].v_double;
615 }
616
617 static gchar *
618 gst_value_collect_double_range (GValue * value, guint n_collect_values,
619     GTypeCValue * collect_values, guint collect_flags)
620 {
621   value->data[0].v_double = collect_values[0].v_double;
622   value->data[1].v_double = collect_values[1].v_double;
623
624   return NULL;
625 }
626
627 static gchar *
628 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
629     GTypeCValue * collect_values, guint collect_flags)
630 {
631   gdouble *double_range_start = collect_values[0].v_pointer;
632   gdouble *double_range_end = collect_values[1].v_pointer;
633
634   if (!double_range_start)
635     return g_strdup_printf ("start value location for `%s' passed as NULL",
636         G_VALUE_TYPE_NAME (value));
637   if (!double_range_end)
638     return g_strdup_printf ("end value location for `%s' passed as NULL",
639         G_VALUE_TYPE_NAME (value));
640
641   *double_range_start = value->data[0].v_double;
642   *double_range_end = value->data[1].v_double;
643
644   return NULL;
645 }
646
647 /**
648  * gst_value_set_double_range:
649  * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
650  * @start: the start of the range
651  * @end: the end of the range
652  *
653  * Sets @value to the range specified by @start and @end.
654  */
655 void
656 gst_value_set_double_range (GValue * value, double start, double end)
657 {
658   g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
659
660   value->data[0].v_double = start;
661   value->data[1].v_double = end;
662 }
663
664 /**
665  * gst_value_get_double_range_min:
666  * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
667  *
668  * Gets the minimum of the range specified by @value.
669  *
670  * Returns: the minumum of the range
671  */
672 double
673 gst_value_get_double_range_min (const GValue * value)
674 {
675   g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
676
677   return value->data[0].v_double;
678 }
679
680 /**
681  * gst_value_get_double_range_max:
682  * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
683  *
684  * Gets the maximum of the range specified by @value.
685  *
686  * Returns: the maxumum of the range
687  */
688 double
689 gst_value_get_double_range_max (const GValue * value)
690 {
691   g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
692
693   return value->data[1].v_double;
694 }
695
696 static void
697 gst_value_transform_double_range_string (const GValue * src_value,
698     GValue * dest_value)
699 {
700   char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
701
702   dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
703       g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
704           src_value->data[0].v_double),
705       g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
706           src_value->data[1].v_double));
707 }
708
709 static int
710 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
711 {
712   if (value2->data[0].v_double == value1->data[0].v_double &&
713       value2->data[0].v_double == value1->data[0].v_double)
714     return GST_VALUE_EQUAL;
715   return GST_VALUE_UNORDERED;
716 }
717
718 static char *
719 gst_value_serialize_double_range (const GValue * value)
720 {
721   char d1[G_ASCII_DTOSTR_BUF_SIZE];
722   char d2[G_ASCII_DTOSTR_BUF_SIZE];
723
724   g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
725   g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
726   return g_strdup_printf ("[ %s, %s ]", d1, d2);
727 }
728
729 static gboolean
730 gst_value_deserialize_double_range (GValue * dest, const char *s)
731 {
732   g_warning ("unimplemented");
733   return FALSE;
734 }
735
736 /*************************************/
737 /* GstCaps */
738
739 /**
740  * gst_value_set_caps:
741  * @value: a GValue initialized to GST_TYPE_CAPS
742  * @caps: the caps to set the value to
743  *
744  * Sets the contents of @value to coorespond to @caps.  The actual
745  * #GstCaps structure is copied before it is used.
746  */
747 void
748 gst_value_set_caps (GValue * value, const GstCaps * caps)
749 {
750   g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
751
752   g_value_set_boxed (value, caps);
753 }
754
755 /**
756  * gst_value_get_caps:
757  * @value: a GValue initialized to GST_TYPE_CAPS
758  *
759  * Gets the contents of @value.
760  *
761  * Returns: the contents of @value
762  */
763 const GstCaps *
764 gst_value_get_caps (const GValue * value)
765 {
766   g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
767
768   return (GstCaps *) g_value_get_boxed (value);
769 }
770
771 /*************************************/
772 /* boolean */
773
774 static int
775 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
776 {
777   if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
778     return GST_VALUE_EQUAL;
779   return GST_VALUE_UNORDERED;
780 }
781
782 static char *
783 gst_value_serialize_boolean (const GValue * value)
784 {
785   if (value->data[0].v_int) {
786     return g_strdup ("true");
787   }
788   return g_strdup ("false");
789 }
790
791 static gboolean
792 gst_value_deserialize_boolean (GValue * dest, const char *s)
793 {
794   gboolean ret = FALSE;
795
796   if (g_ascii_strcasecmp (s, "true") == 0 ||
797       g_ascii_strcasecmp (s, "yes") == 0 ||
798       g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
799     g_value_set_boolean (dest, TRUE);
800     ret = TRUE;
801   } else if (g_ascii_strcasecmp (s, "false") == 0 ||
802       g_ascii_strcasecmp (s, "no") == 0 ||
803       g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
804     g_value_set_boolean (dest, FALSE);
805     ret = TRUE;
806   }
807
808   return ret;
809 }
810
811 /*************************************/
812 /* int */
813
814 static int
815 gst_value_compare_int (const GValue * value1, const GValue * value2)
816 {
817   if (value1->data[0].v_int > value2->data[0].v_int)
818     return GST_VALUE_GREATER_THAN;
819   if (value1->data[0].v_int < value2->data[0].v_int)
820     return GST_VALUE_LESS_THAN;
821   return GST_VALUE_EQUAL;
822 }
823
824 static char *
825 gst_value_serialize_int (const GValue * value)
826 {
827   return g_strdup_printf ("%d", value->data[0].v_int);
828 }
829
830 static int
831 gst_strtoi (const char *s, char **end, int base)
832 {
833   int i;
834
835   if (s[0] == '-') {
836     i = -(int) strtoul (s + 1, end, base);
837   } else {
838     i = strtoul (s, end, base);
839   }
840
841   return i;
842 }
843
844 static gboolean
845 gst_value_deserialize_int (GValue * dest, const char *s)
846 {
847   int x;
848   char *end;
849   gboolean ret = FALSE;
850
851   x = gst_strtoi (s, &end, 0);
852   if (*end == 0) {
853     ret = TRUE;
854   } else {
855     if (g_ascii_strcasecmp (s, "little_endian") == 0) {
856       x = G_LITTLE_ENDIAN;
857       ret = TRUE;
858     } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
859       x = G_BIG_ENDIAN;
860       ret = TRUE;
861     } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
862       x = G_BYTE_ORDER;
863       ret = TRUE;
864     } else if (g_ascii_strcasecmp (s, "min") == 0) {
865       x = G_MININT;
866       ret = TRUE;
867     } else if (g_ascii_strcasecmp (s, "max") == 0) {
868       x = G_MAXINT;
869       ret = TRUE;
870     }
871   }
872   if (ret) {
873     g_value_set_int (dest, x);
874   }
875   return ret;
876 }
877
878 /*************************************/
879 /* double */
880
881 static int
882 gst_value_compare_double (const GValue * value1, const GValue * value2)
883 {
884   if (value1->data[0].v_double > value2->data[0].v_double)
885     return GST_VALUE_GREATER_THAN;
886   if (value1->data[0].v_double < value2->data[0].v_double)
887     return GST_VALUE_LESS_THAN;
888   if (value1->data[0].v_double == value2->data[0].v_double)
889     return GST_VALUE_EQUAL;
890   return GST_VALUE_UNORDERED;
891 }
892
893 static char *
894 gst_value_serialize_double (const GValue * value)
895 {
896   char d[G_ASCII_DTOSTR_BUF_SIZE];
897
898   g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
899   return g_strdup (d);
900 }
901
902 static gboolean
903 gst_value_deserialize_double (GValue * dest, const char *s)
904 {
905   double x;
906   gboolean ret = FALSE;
907   char *end;
908
909   x = g_ascii_strtod (s, &end);
910   if (*end == 0) {
911     ret = TRUE;
912   } else {
913     if (g_ascii_strcasecmp (s, "min") == 0) {
914       x = -G_MAXDOUBLE;
915       ret = TRUE;
916     } else if (g_ascii_strcasecmp (s, "max") == 0) {
917       x = G_MAXDOUBLE;
918       ret = TRUE;
919     }
920   }
921   if (ret) {
922     g_value_set_double (dest, x);
923   }
924   return ret;
925 }
926
927 /*************************************/
928 /* string */
929
930 static int
931 gst_value_compare_string (const GValue * value1, const GValue * value2)
932 {
933   int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
934
935   if (x < 0)
936     return GST_VALUE_LESS_THAN;
937   if (x > 0)
938     return GST_VALUE_GREATER_THAN;
939   return GST_VALUE_EQUAL;
940 }
941
942 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
943     ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
944     ((c) == '.'))
945
946 static gchar *
947 gst_string_wrap (const char *s)
948 {
949   const gchar *t;
950   int len;
951   gchar *d, *e;
952   gboolean wrap = FALSE;
953
954   len = 0;
955   t = s;
956   while (*t) {
957     if (GST_ASCII_IS_STRING (*t)) {
958       len++;
959     } else if (*t < 0x20 || *t >= 0x7f) {
960       wrap = TRUE;
961       len += 4;
962     } else {
963       wrap = TRUE;
964       len += 2;
965     }
966     t++;
967   }
968
969   if (!wrap)
970     return strdup (s);
971
972   e = d = g_malloc (len + 3);
973
974   *e++ = '\"';
975   t = s;
976   while (*t) {
977     if (GST_ASCII_IS_STRING (*t)) {
978       *e++ = *t++;
979     } else if (*t < 0x20 || *t >= 0x7f) {
980       *e++ = '\\';
981       *e++ = '0' + ((*t) >> 6);
982       *e++ = '0' + (((*t) >> 3) & 0x7);
983       *e++ = '0' + ((*t++) & 0x7);
984     } else {
985       *e++ = '\\';
986       *e++ = *t++;
987     }
988   }
989   *e++ = '\"';
990   *e = 0;
991
992   return d;
993 }
994
995 static char *
996 gst_value_serialize_string (const GValue * value)
997 {
998   return gst_string_wrap (value->data[0].v_pointer);
999 }
1000
1001 static gboolean
1002 gst_value_deserialize_string (GValue * dest, const char *s)
1003 {
1004   g_value_set_string (dest, s);
1005
1006   return TRUE;
1007 }
1008
1009 /*************************************/
1010 /* unions */
1011
1012 /*************************************/
1013 /* intersection */
1014
1015 static gboolean
1016 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
1017     const GValue * src2)
1018 {
1019   g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
1020   g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1021
1022   if (src2->data[0].v_int <= src1->data[0].v_int &&
1023       src2->data[1].v_int >= src1->data[0].v_int) {
1024     gst_value_init_and_copy (dest, src1);
1025     return TRUE;
1026   }
1027
1028   return FALSE;
1029 }
1030
1031 static gboolean
1032 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
1033     const GValue * src2)
1034 {
1035   int min;
1036   int max;
1037
1038   g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
1039   g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1040
1041   min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1042   max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1043
1044   if (min < max) {
1045     g_value_init (dest, GST_TYPE_INT_RANGE);
1046     gst_value_set_int_range (dest, min, max);
1047     return TRUE;
1048   }
1049   if (min == max) {
1050     g_value_init (dest, G_TYPE_INT);
1051     g_value_set_int (dest, min);
1052     return TRUE;
1053   }
1054
1055   return FALSE;
1056 }
1057
1058 static gboolean
1059 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
1060     const GValue * src2)
1061 {
1062   g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_DOUBLE, FALSE);
1063   g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1064
1065   if (src2->data[0].v_double <= src1->data[0].v_double &&
1066       src2->data[1].v_double >= src1->data[0].v_double) {
1067     gst_value_init_and_copy (dest, src1);
1068     return TRUE;
1069   }
1070
1071   return FALSE;
1072 }
1073
1074 static gboolean
1075 gst_value_intersect_double_range_double_range (GValue * dest,
1076     const GValue * src1, const GValue * src2)
1077 {
1078   double min;
1079   double max;
1080
1081   g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_DOUBLE_RANGE, FALSE);
1082   g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1083
1084   min = MAX (src1->data[0].v_double, src2->data[0].v_double);
1085   max = MIN (src1->data[1].v_double, src2->data[1].v_double);
1086
1087   if (min < max) {
1088     g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
1089     gst_value_set_double_range (dest, min, max);
1090     return TRUE;
1091   }
1092   if (min == max) {
1093     g_value_init (dest, G_TYPE_DOUBLE);
1094     g_value_set_int (dest, min);
1095     return TRUE;
1096   }
1097
1098   return FALSE;
1099 }
1100
1101 static gboolean
1102 gst_value_intersect_list (GValue * dest, const GValue * value1,
1103     const GValue * value2)
1104 {
1105   guint i, size;
1106   GValue intersection = { 0, };
1107   gboolean ret = FALSE;
1108
1109   g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value1), FALSE);
1110
1111   size = gst_value_list_get_size (value1);
1112   for (i = 0; i < size; i++) {
1113     const GValue *cur = gst_value_list_get_value (value1, i);
1114
1115     if (gst_value_intersect (&intersection, cur, value2)) {
1116       /* append value */
1117       if (!ret) {
1118         gst_value_init_and_copy (dest, &intersection);
1119         ret = TRUE;
1120       } else if (GST_VALUE_HOLDS_LIST (dest)) {
1121         gst_value_list_append_value (dest, &intersection);
1122       } else {
1123         GValue temp = { 0, };
1124
1125         gst_value_init_and_copy (&temp, dest);
1126         g_value_unset (dest);
1127         gst_value_list_concat (dest, &temp, &intersection);
1128       }
1129       g_value_unset (&intersection);
1130     }
1131   }
1132
1133   return ret;
1134 }
1135
1136
1137 /*************************************/
1138
1139 /**
1140  * gst_value_can_compare:
1141  * @value1: a value to compare
1142  * @value2: another value to compare
1143  *
1144  * Determines if @value1 and @value2 can be compared.
1145  *
1146  * Returns: TRUE if the values can be compared
1147  */
1148 gboolean
1149 gst_value_can_compare (const GValue * value1, const GValue * value2)
1150 {
1151   GstValueTable *table;
1152   int i;
1153
1154   if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1155     return FALSE;
1156   for (i = 0; i < gst_value_table->len; i++) {
1157     table = &g_array_index (gst_value_table, GstValueTable, i);
1158     if (table->type == G_VALUE_TYPE (value1) && table->compare)
1159       return TRUE;
1160   }
1161
1162   return FALSE;
1163 }
1164
1165 /**
1166  * gst_value_compare:
1167  * @value1: a value to compare
1168  * @value2: another value to compare
1169  *
1170  * Compares @value1 and @value2.  If @value1 and @value2 cannot be
1171  * compared, the function returns GST_VALUE_UNORDERED.  Otherwise,
1172  * if @value1 is greater than @value2, GST_VALUE_GREATER is returned.
1173  * If @value1 is less than @value2, GST_VALUE_LESSER is returned.
1174  * If the values are equal, GST_VALUE_EQUAL is returned.
1175  *
1176  * Returns: A GstValueCompareType value
1177  */
1178 int
1179 gst_value_compare (const GValue * value1, const GValue * value2)
1180 {
1181   GstValueTable *table;
1182   int i;
1183
1184   if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1185     return GST_VALUE_UNORDERED;
1186
1187   for (i = 0; i < gst_value_table->len; i++) {
1188     table = &g_array_index (gst_value_table, GstValueTable, i);
1189     if (table->type != G_VALUE_TYPE (value1) || table->compare == NULL)
1190       continue;
1191
1192     return table->compare (value1, value2);
1193   }
1194
1195   g_critical ("unable to compare values of type %s\n",
1196       g_type_name (G_VALUE_TYPE (value1)));
1197   return GST_VALUE_UNORDERED;
1198 }
1199
1200 /* union */
1201
1202 /**
1203  * gst_value_can_union:
1204  * @value1: a value to union
1205  * @value2: another value to union
1206  *
1207  * Determines if @value1 and @value2 can be non-trivially unioned.
1208  * Any two values can be trivially unioned by adding both of them
1209  * to a GstValueList.  However, certain types have the possibility
1210  * to be unioned in a simpler way.  For example, an integer range
1211  * and an integer can be unioned if the integer is a subset of the
1212  * integer range.  If there is the possibility that two values can
1213  * be unioned, this function returns TRUE.
1214  *
1215  * Returns: TRUE if there is a function allowing the two values to
1216  * be unioned.
1217  */
1218 gboolean
1219 gst_value_can_union (const GValue * value1, const GValue * value2)
1220 {
1221   GstValueUnionInfo *union_info;
1222   int i;
1223
1224   for (i = 0; i < gst_value_union_funcs->len; i++) {
1225     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1226     if (union_info->type1 == G_VALUE_TYPE (value1) &&
1227         union_info->type2 == G_VALUE_TYPE (value2))
1228       return TRUE;
1229   }
1230
1231   return FALSE;
1232 }
1233
1234 /**
1235  * gst_value_union:
1236  * @dest: the destination value
1237  * @value1: a value to union
1238  * @value2: another value to union
1239  *
1240  * Creates a GValue cooresponding to the union of @value1 and @value2.
1241  *
1242  * Returns: TRUE if the values could be unioned
1243  */
1244 gboolean
1245 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
1246 {
1247   GstValueUnionInfo *union_info;
1248   int i;
1249
1250   for (i = 0; i < gst_value_union_funcs->len; i++) {
1251     union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1252     if (union_info->type1 == G_VALUE_TYPE (value1) &&
1253         union_info->type2 == G_VALUE_TYPE (value2)) {
1254       return union_info->func (dest, value1, value2);
1255     }
1256   }
1257
1258   gst_value_list_concat (dest, value1, value2);
1259   return TRUE;
1260 }
1261
1262 /**
1263  * gst_value_register_union_func:
1264  * @type1: a type to union
1265  * @type2: another type to union
1266  * @func: a function that implments creating a union between the two types
1267  *
1268  * Registers a union function that can create a union between GValues
1269  * of the type @type1 and @type2.
1270  *
1271  */
1272 void
1273 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
1274 {
1275   GstValueUnionInfo union_info;
1276
1277   union_info.type1 = type1;
1278   union_info.type2 = type2;
1279   union_info.func = func;
1280
1281   g_array_append_val (gst_value_union_funcs, union_info);
1282 }
1283
1284 /* intersection */
1285
1286 /**
1287  * gst_value_can_intersect:
1288  *
1289  */
1290 gboolean
1291 gst_value_can_intersect (const GValue * value1, const GValue * value2)
1292 {
1293   GstValueIntersectInfo *intersect_info;
1294   int i;
1295
1296   /* special cases */
1297   if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
1298     return TRUE;
1299
1300   for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1301     intersect_info = &g_array_index (gst_value_intersect_funcs,
1302         GstValueIntersectInfo, i);
1303     if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1304         intersect_info->type2 == G_VALUE_TYPE (value2))
1305       return TRUE;
1306   }
1307
1308   return gst_value_can_compare (value1, value2);
1309 }
1310
1311 /**
1312  * gst_value_intersect:
1313  * @dest: the destination value for intersection
1314  * @value1: a value to intersect
1315  * @value2: another value to intersect
1316  *
1317  * Calculates the intersection of the two values.
1318  *
1319  * Returns: TRUE if the intersection is non-empty
1320  */
1321 gboolean
1322 gst_value_intersect (GValue * dest, const GValue * value1,
1323     const GValue * value2)
1324 {
1325   GstValueIntersectInfo *intersect_info;
1326   int i;
1327   int ret = FALSE;
1328
1329   /* special cases first */
1330   if (GST_VALUE_HOLDS_LIST (value1))
1331     return gst_value_intersect_list (dest, value1, value2);
1332   if (GST_VALUE_HOLDS_LIST (value2))
1333     return gst_value_intersect_list (dest, value2, value1);
1334
1335   for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1336     intersect_info = &g_array_index (gst_value_intersect_funcs,
1337         GstValueIntersectInfo, i);
1338     if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1339         intersect_info->type2 == G_VALUE_TYPE (value2)) {
1340       ret = intersect_info->func (dest, value1, value2);
1341       return ret;
1342     }
1343     if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
1344         intersect_info->type2 == G_VALUE_TYPE (value1)) {
1345       ret = intersect_info->func (dest, value2, value1);
1346       return ret;
1347     }
1348   }
1349
1350   if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
1351     gst_value_init_and_copy (dest, value1);
1352     ret = TRUE;
1353   }
1354
1355   return ret;
1356 }
1357
1358 /**
1359  * gst_value_register_intersection_func:
1360  *
1361  */
1362 void
1363 gst_value_register_intersect_func (GType type1, GType type2,
1364     GstValueIntersectFunc func)
1365 {
1366   GstValueIntersectInfo intersect_info;
1367
1368   intersect_info.type1 = type1;
1369   intersect_info.type2 = type2;
1370   intersect_info.func = func;
1371
1372   g_array_append_val (gst_value_intersect_funcs, intersect_info);
1373 }
1374
1375 /**
1376  * gst_value_register:
1377  *
1378  */
1379 void
1380 gst_value_register (const GstValueTable * table)
1381 {
1382   g_array_append_val (gst_value_table, *table);
1383 }
1384
1385 /**
1386  * gst_value_init_and_copy:
1387  *
1388  */
1389 void
1390 gst_value_init_and_copy (GValue * dest, const GValue * src)
1391 {
1392   g_value_init (dest, G_VALUE_TYPE (src));
1393   g_value_copy (src, dest);
1394 }
1395
1396 /**
1397  * gst_value_serialize:
1398  *
1399  */
1400 gchar *
1401 gst_value_serialize (const GValue * value)
1402 {
1403   int i;
1404   GValue s_val = { 0 };
1405   GstValueTable *table;
1406   char *s;
1407
1408   for (i = 0; i < gst_value_table->len; i++) {
1409     table = &g_array_index (gst_value_table, GstValueTable, i);
1410     if (table->type != G_VALUE_TYPE (value) || table->serialize == NULL)
1411       continue;
1412
1413     return table->serialize (value);
1414   }
1415
1416   g_value_init (&s_val, G_TYPE_STRING);
1417   g_value_transform (value, &s_val);
1418   s = gst_string_wrap (g_value_get_string (&s_val));
1419   g_value_unset (&s_val);
1420
1421   return s;
1422 }
1423
1424 /**
1425  * gst_value_deserialize:
1426  *
1427  */
1428 gboolean
1429 gst_value_deserialize (GValue * dest, const gchar * src)
1430 {
1431   GstValueTable *table;
1432   int i;
1433
1434   for (i = 0; i < gst_value_table->len; i++) {
1435     table = &g_array_index (gst_value_table, GstValueTable, i);
1436     if (table->type != G_VALUE_TYPE (dest) || table->deserialize == NULL)
1437       continue;
1438
1439     return table->deserialize (dest, src);
1440   }
1441
1442   return FALSE;
1443 }
1444
1445 void
1446 _gst_value_initialize (void)
1447 {
1448   GTypeInfo info = {
1449     0,
1450     NULL,
1451     NULL,
1452     NULL,
1453     NULL,
1454     NULL,
1455     0,
1456     0,
1457     NULL,
1458     NULL,
1459   };
1460
1461   //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
1462
1463   gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
1464   gst_value_union_funcs = g_array_new (FALSE, FALSE,
1465       sizeof (GstValueUnionInfo));
1466   gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
1467       sizeof (GstValueIntersectInfo));
1468
1469   {
1470     static const GTypeValueTable value_table = {
1471       gst_value_init_fourcc,
1472       NULL,
1473       gst_value_copy_fourcc,
1474       NULL,
1475       "i",
1476       gst_value_collect_fourcc,
1477       "p",
1478       gst_value_lcopy_fourcc
1479     };
1480     static GstValueTable gst_value = {
1481       0,
1482       gst_value_compare_fourcc,
1483       gst_value_serialize_fourcc,
1484       gst_value_deserialize_fourcc,
1485     };
1486
1487     info.value_table = &value_table;
1488     gst_type_fourcc =
1489         g_type_register_static (G_TYPE_BOXED, "GstFourcc", &info, 0);
1490     gst_value.type = gst_type_fourcc;
1491     gst_value_register (&gst_value);
1492   }
1493
1494   {
1495     static const GTypeValueTable value_table = {
1496       gst_value_init_int_range,
1497       NULL,
1498       gst_value_copy_int_range,
1499       NULL,
1500       "ii",
1501       gst_value_collect_int_range,
1502       "pp",
1503       gst_value_lcopy_int_range
1504     };
1505     static GstValueTable gst_value = {
1506       0,
1507       gst_value_compare_int_range,
1508       gst_value_serialize_int_range,
1509       gst_value_deserialize_int_range,
1510     };
1511
1512     info.value_table = &value_table;
1513     gst_type_int_range =
1514         g_type_register_static (G_TYPE_BOXED, "GstIntRange", &info, 0);
1515     gst_value.type = gst_type_int_range;
1516     gst_value_register (&gst_value);
1517   }
1518
1519   {
1520     static const GTypeValueTable value_table = {
1521       gst_value_init_double_range,
1522       NULL,
1523       gst_value_copy_double_range,
1524       NULL,
1525       "dd",
1526       gst_value_collect_double_range,
1527       "pp",
1528       gst_value_lcopy_double_range
1529     };
1530     static GstValueTable gst_value = {
1531       0,
1532       gst_value_compare_double_range,
1533       gst_value_serialize_double_range,
1534       gst_value_deserialize_double_range,
1535     };
1536
1537     info.value_table = &value_table;
1538     gst_type_double_range =
1539         g_type_register_static (G_TYPE_BOXED, "GstDoubleRange", &info, 0);
1540     gst_value.type = gst_type_double_range;
1541     gst_value_register (&gst_value);
1542   }
1543
1544   {
1545     static const GTypeValueTable value_table = {
1546       gst_value_init_list,
1547       gst_value_free_list,
1548       gst_value_copy_list,
1549       gst_value_list_peek_pointer,
1550       "p",
1551       gst_value_collect_list,
1552       "p",
1553       gst_value_lcopy_list
1554     };
1555     static GstValueTable gst_value = {
1556       0,
1557       gst_value_compare_list,
1558       gst_value_serialize_list,
1559       gst_value_deserialize_list,
1560     };
1561
1562     info.value_table = &value_table;
1563     gst_type_list =
1564         g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
1565     gst_value.type = gst_type_list;
1566     gst_value_register (&gst_value);
1567   }
1568
1569   {
1570     static const GstValueTable gst_value = {
1571       G_TYPE_INT,
1572       gst_value_compare_int,
1573       gst_value_serialize_int,
1574       gst_value_deserialize_int,
1575     };
1576
1577     gst_value_register (&gst_value);
1578   }
1579
1580   {
1581     static const GstValueTable gst_value = {
1582       G_TYPE_DOUBLE,
1583       gst_value_compare_double,
1584       gst_value_serialize_double,
1585       gst_value_deserialize_double,
1586     };
1587
1588     gst_value_register (&gst_value);
1589   }
1590
1591   {
1592     static const GstValueTable gst_value = {
1593       G_TYPE_STRING,
1594       gst_value_compare_string,
1595       gst_value_serialize_string,
1596       gst_value_deserialize_string,
1597     };
1598
1599     gst_value_register (&gst_value);
1600   }
1601
1602   {
1603     static const GstValueTable gst_value = {
1604       G_TYPE_BOOLEAN,
1605       gst_value_compare_boolean,
1606       gst_value_serialize_boolean,
1607       gst_value_deserialize_boolean,
1608     };
1609
1610     gst_value_register (&gst_value);
1611   }
1612
1613   g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
1614       gst_value_transform_fourcc_string);
1615   g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
1616       gst_value_transform_int_range_string);
1617   g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
1618       gst_value_transform_double_range_string);
1619   g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
1620       gst_value_transform_list_string);
1621
1622   gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
1623       gst_value_intersect_int_int_range);
1624   gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
1625       gst_value_intersect_int_range_int_range);
1626   gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
1627       gst_value_intersect_double_double_range);
1628   gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
1629       GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);
1630 }