fix doc build fix autogen
[platform/upstream/gstreamer.git] / gst / gststructure.c
1 /* GStreamer
2  * Copyright (C) 2003 David A. Schleef <ds@schleef.org>
3  *
4  * gststructure.c: lists of { GQuark, GValue } tuples
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include <gst/gst.h>
29 #include <gobject/gvaluecollector.h>
30
31 static GType _gst_structure_type;
32
33 typedef struct _GstStructureField GstStructureField;
34 struct _GstStructureField {
35   GQuark name;
36   GValue value;
37 };
38
39 #define GST_STRUCTURE_FIELD(structure, index) \
40     &g_array_index((structure)->fields, GstStructureField, (index))
41
42 static void gst_structure_set_field (GstStructure *structure,
43     GstStructureField *field);
44 static GstStructureField *gst_structure_get_field(const GstStructure *structure,
45         const gchar *fieldname);
46 static GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
47         GQuark fieldname);
48
49 static void _gst_structure_transform_to_string(const GValue *src_value,
50     GValue *dest_value);
51
52 static void _gst_structure_value_init (GValue *value);
53 static void _gst_structure_value_free (GValue *value);
54 static void _gst_structure_value_copy (const GValue *src, GValue *dest);
55 static gpointer _gst_structure_value_peek_pointer (const GValue *value);
56
57
58 GType gst_structure_get_type(void)
59 {
60   return _gst_structure_type;
61 }
62
63 void _gst_structure_initialize(void)
64 {
65   static const GTypeValueTable type_value_table = {
66     _gst_structure_value_init,
67     _gst_structure_value_free,
68     _gst_structure_value_copy,
69     _gst_structure_value_peek_pointer,
70     NULL,
71     NULL,
72     NULL,
73     NULL,
74   };
75   static const GTypeInfo structure_info = {
76     0,
77     NULL,
78     NULL,
79     NULL,
80     NULL,
81     NULL,
82     0, /* sizeof(GstStructure), */
83     0,
84     NULL, /* _gst_structure_init, */
85     &type_value_table,
86   };
87
88   _gst_structure_type = g_type_register_static(G_TYPE_BOXED, "GstStructure",
89       &structure_info, 0);
90 #if 0
91   _gst_structure_type = g_boxed_type_register_static("GstStructure",
92       (GBoxedCopyFunc) gst_structure_copy,
93       (GBoxedFreeFunc) gst_structure_free);
94 #endif
95
96   g_value_register_transform_func(_gst_structure_type, G_TYPE_STRING,
97       _gst_structure_transform_to_string);
98 }
99
100 /**
101  * gst_structure_id_empty_new:
102  * @name: name of new structure
103  *
104  * Creates a new, empty #GstStructure with the given name.
105  *
106  * Returns: a new, empty #GstStructure
107  */
108 GstStructure *gst_structure_id_empty_new(GQuark quark)
109 {
110   GstStructure *structure;
111
112   g_return_val_if_fail(quark != 0, NULL);
113
114   structure = g_new0(GstStructure, 1);
115   structure->name = quark;
116   structure->fields = g_array_new(FALSE,TRUE,sizeof(GstStructureField));
117
118   return structure;
119 }
120
121 /**
122  * gst_structure_empty_new:
123  * @name: name of new structure
124  *
125  * Creates a new, empty #GstStructure with the given name.
126  *
127  * Returns: a new, empty #GstStructure
128  */
129 GstStructure *gst_structure_empty_new(const gchar *name)
130 {
131   GstStructure *structure;
132
133   g_return_val_if_fail(name != NULL, NULL);
134
135   structure = g_new0(GstStructure, 1);
136   structure->name = g_quark_from_string(name);
137   structure->fields = g_array_new(FALSE,TRUE,sizeof(GstStructureField));
138
139   return structure;
140 }
141
142 /**
143  * gst_structure_new:
144  * @name: name of new structure
145  * @firstfield: name of first field to set
146  * @...: additional arguments
147  *
148  * Creates a new #GstStructure with the given name.  Parses the
149  * list of variable arguments and sets fields to the values listed.
150  * Variable arguments should be passed as field name, field type,
151  * and value.  Last variable argument should be NULL.
152  *
153  * Returns: a new #GstStructure
154  */
155 GstStructure *gst_structure_new(const gchar *name,
156     const gchar *firstfield, ...)
157 {
158   GstStructure *structure;
159   va_list varargs;
160
161   g_return_val_if_fail(name != NULL, NULL);
162
163   va_start(varargs, firstfield);
164
165   structure = gst_structure_new_valist(name,firstfield,varargs);
166
167   va_end(varargs);
168
169   return structure;
170 }
171
172 /**
173  * gst_structure_new_valist:
174  * @name: name of new structure
175  * @firstfield: name of first field to set
176  * @varags: variable argument list
177  *
178  * Creates a new #GstStructure with the given name.  Structure fields
179  * are set according to the varargs in a manner similar to
180  * @gst_structure_new.
181  *
182  * Returns: a new #GstStructure
183  */
184 GstStructure *gst_structure_new_valist(const gchar *name,
185     const gchar *firstfield, va_list varargs)
186 {
187   GstStructure *structure;
188
189   g_return_val_if_fail(name != NULL, NULL);
190
191   structure = gst_structure_empty_new(name);
192   gst_structure_set_valist(structure, firstfield, varargs);
193
194   return structure;
195 }
196
197 /**
198  * gst_structure_copy:
199  * @structure: a #GstStructure to duplicate
200  *
201  * Duplicates a #GstStructure and all its fields and values.
202  *
203  * Returns: a new #GstStructure.
204  */
205 GstStructure *gst_structure_copy(GstStructure *structure)
206 {
207   GstStructure *new_structure;
208   GstStructureField *field;
209   int i;
210
211   g_return_val_if_fail(structure != NULL, NULL);
212
213   new_structure = gst_structure_empty_new(g_quark_to_string(structure->name));
214   new_structure->name = structure->name;
215
216   for(i=0;i<structure->fields->len;i++){
217     GstStructureField new_field = { 0 };
218
219     field = GST_STRUCTURE_FIELD(structure, i);
220
221     new_field.name = field->name;
222     gst_value_init_and_copy (&new_field.value, &field->value);
223     g_array_append_val(new_structure->fields, new_field);
224   }
225
226   return new_structure;
227 }
228
229 /**
230  * gst_structure_free: 
231  * @structure: the #GstStructure to free
232  *
233  * Frees a #GstStructure and all its fields and values.
234  */
235 void gst_structure_free(GstStructure *structure)
236 {
237   GstStructureField *field;
238   int i;
239
240   return;
241
242   g_return_if_fail(structure != NULL);
243
244   for(i=0;i<structure->fields->len;i++){
245     field = GST_STRUCTURE_FIELD(structure, i);
246
247     if(G_IS_VALUE(&field->value)){
248       g_value_unset(&field->value);
249     }
250   }
251 #ifdef USE_POISONING
252   memset (structure, 0xff, sizeof(GstStructure));
253 #endif
254   g_free(structure);
255 }
256
257 /**
258  * gst_structure_get_name:
259  * @structure: a #GstStructure
260  *
261  * Accessor fuction.
262  *
263  * Returns: the name of the structure.
264  */
265 const gchar *gst_structure_get_name(const GstStructure *structure)
266 {
267   g_return_val_if_fail(structure != NULL, NULL);
268
269   return g_quark_to_string(structure->name);
270 }
271
272 /**
273  * gst_structure_set_name:
274  * @structure: a #GstStructure
275  * @name: the new name of the structure
276  *
277  * Sets the name of the structure to the given name.  The string
278  * provided is copied before being used.
279  */
280 void gst_structure_set_name(GstStructure *structure, const gchar *name)
281 {
282   g_return_if_fail(structure != NULL);
283   g_return_if_fail(name != NULL);
284
285   structure->name = g_quark_from_string(name);
286 }
287
288 /**
289  * gst_structure_id_set_value:
290  * @structure: a #GstStructure
291  * @field_id: a #GQuark representing a field
292  * @value: the new value of the field
293  *
294  * Sets the field with the given ID to the provided value.  If the field
295  * does not exist, it is created.  If the field exists, the previous
296  * value is freed.
297  */
298 void gst_structure_id_set_value(GstStructure *structure, GQuark fieldname,
299     const GValue *value)
300 {
301   GstStructureField field = { 0, { 0, } };
302
303   g_return_if_fail(structure != NULL);
304   g_return_if_fail(G_IS_VALUE(value));
305
306   field.name = fieldname;
307   gst_value_init_and_copy (&field.value, value);
308
309   gst_structure_set_field(structure, &field);
310 }
311
312 /**
313  * gst_structure_set_value:
314  * @structure: a #GstStructure
315  * @field: the name of the field to set
316  * @value: the new value of the field
317  *
318  * Sets the field with the given name to the provided value.  If the field
319  * does not exist, it is created.  If the field exists, the previous
320  * value is freed.
321  */
322 void gst_structure_set_value(GstStructure *structure, const gchar *field,
323     const GValue *value)
324 {
325   g_return_if_fail(structure != NULL);
326   g_return_if_fail(field != NULL);
327   g_return_if_fail(G_IS_VALUE(value));
328
329   gst_structure_id_set_value(structure, g_quark_from_string(field), value);
330 }
331
332 /**
333  * gst_structure_set:
334  * @structure: a #GstStructure
335  * @field: the name of the field to set
336  * @...: variable arguments
337  *
338  * Parses the variable arguments and sets fields accordingly.
339  * Variable arguments should be in the form field name, field type
340  * (as a GType), value.  The last variable argument should be NULL.
341  */
342 void gst_structure_set(GstStructure *structure, const gchar *field, ...)
343 {
344   va_list varargs;
345
346   g_return_if_fail(structure != NULL);
347
348   va_start(varargs, field);
349
350   gst_structure_set_valist(structure,field,varargs);
351
352   va_end(varargs);
353 }
354
355 /**
356  * gst_structure_set_valist:
357  * @structure: a #GstStructure
358  * @field: the name of the field to set
359  * @varargs: variable arguments
360  *
361  * va_list form of #gst_structure_set.
362  */
363 void gst_structure_set_valist(GstStructure *structure, const gchar *fieldname,
364     va_list varargs)
365 {
366   GType type;
367   int i;
368   double d;
369   char *s;
370
371   g_return_if_fail(structure != NULL);
372
373   while(fieldname){
374     GstStructureField field = { 0 };
375
376     field.name = g_quark_from_string(fieldname);
377
378     type = va_arg (varargs, GType); 
379
380     switch(type){
381       case G_TYPE_INT:
382         i = va_arg(varargs, int);
383         g_value_init(&field.value, G_TYPE_INT);
384         g_value_set_int(&field.value, i);
385         break;
386       case G_TYPE_DOUBLE:
387         d = va_arg(varargs, double);
388         g_value_init(&field.value, G_TYPE_DOUBLE);
389         g_value_set_double(&field.value, d);
390         break;
391       case G_TYPE_BOOLEAN:
392         i = va_arg(varargs, int);
393         g_value_init(&field.value, G_TYPE_BOOLEAN);
394         g_value_set_boolean(&field.value, i);
395         break;
396       case G_TYPE_STRING:
397         s = va_arg(varargs, char *);
398         g_value_init(&field.value, G_TYPE_STRING);
399         g_value_set_string(&field.value, s);
400         break;
401       default:
402         if(type == GST_TYPE_FOURCC){
403           i = va_arg(varargs, int);
404           g_value_init(&field.value, GST_TYPE_FOURCC);
405           gst_value_set_fourcc(&field.value, i);
406         } else if (type == GST_TYPE_INT_RANGE){
407           int min, max;
408           min = va_arg(varargs, int);
409           max = va_arg(varargs, int);
410           g_value_init(&field.value, GST_TYPE_INT_RANGE);
411           gst_value_set_int_range(&field.value, min, max);
412         } else if (type == GST_TYPE_DOUBLE_RANGE){
413           double min, max;
414           min = va_arg(varargs, double);
415           max = va_arg(varargs, double);
416           g_value_init(&field.value, GST_TYPE_DOUBLE_RANGE);
417           gst_value_set_double_range(&field.value, min, max);
418         } else {
419           g_critical("unimplemented vararg field type %d\n", (int)type);
420           return;
421         }
422         break;
423     }
424
425     gst_structure_set_field(structure, &field);
426
427     fieldname = va_arg (varargs, gchar *);
428   }
429 }
430
431 /**
432  * gst_structure_set_field:
433  * @structure: a #GstStructure
434  * @field: the #GstStructureField to set
435  *
436  * Sets a field in the structure.  If the structure currently contains
437  * a field with the same name, it is replaced with the provided field.
438  * Otherwise, the field is added to the structure.  The field's value
439  * is not deeply copied.
440  *
441  * This function is intended mainly for internal use.  The function
442  * #gst_structure_set() is recommended instead of this one.
443  */
444 static void gst_structure_set_field(GstStructure *structure, GstStructureField *field)
445 {
446   GstStructureField *f;
447   int i;
448
449   for(i=0;i<structure->fields->len;i++){
450     f = GST_STRUCTURE_FIELD(structure, i);
451
452     if(f->name == field->name){
453       g_value_unset(&f->value);
454       memcpy(f,field,sizeof(GstStructureField));
455       return;
456     }
457   }
458
459   g_array_append_val(structure->fields, *field);
460 }
461
462 /**
463  * gst_structure_id_get_field:
464  * @structure: a #GstStructure
465  * @field_id: the GQuark of the field to get
466  *
467  * Gets the specified field from the structure.  If there is no
468  * field with the given ID, NULL is returned.
469  *
470  * Returns: the #GstStructureField with the given ID
471  */
472 static GstStructureField *gst_structure_id_get_field(const GstStructure *structure,
473     GQuark field_id)
474 {
475   GstStructureField *field;
476   int i;
477
478   g_return_val_if_fail(structure != NULL, NULL);
479
480   for(i=0;i<structure->fields->len;i++){
481     field = GST_STRUCTURE_FIELD(structure, i);
482
483     if(field->name == field_id) return field;
484   }
485
486   return NULL;
487 }
488
489 /**
490  * gst_structure_get_field:
491  * @structure: a #GstStructure
492  * @fieldname: the name of the field to get
493  *
494  * Gets the specified field from the structure.  If there is no
495  * field with the given ID, NULL is returned.
496  *
497  * Returns: the #GstStructureField with the given name
498  */
499 static GstStructureField *
500 gst_structure_get_field(const GstStructure *structure, const gchar *fieldname)
501 {
502   g_return_val_if_fail(structure != NULL, NULL);
503   g_return_val_if_fail(fieldname != NULL, NULL);
504
505   return gst_structure_id_get_field(structure,
506       g_quark_from_string(fieldname));
507 }
508
509 /**
510  * gst_structure_get_value:
511  * @structure: a #GstStructure
512  * @fieldname: the name of the field to get
513  *
514  * Accessor function.
515  *
516  * Returns: the #GValue corresponding to the field with the given name.
517  */
518 const GValue *
519 gst_structure_get_value(const GstStructure *structure, const gchar *fieldname)
520 {
521   GstStructureField *field;
522
523   g_return_val_if_fail(structure != NULL, NULL);
524   g_return_val_if_fail(fieldname != NULL, NULL);
525
526   field = gst_structure_get_field(structure, fieldname);
527   if(field == NULL) return NULL;
528
529   return &field->value;
530 }
531
532 /**
533  * gst_structure_id_get_value:
534  * @structure: a #GstStructure
535  * @id: the #GQuark of the field to get
536  *
537  * Accessor function.
538  *
539  * Returns: the #GValue corresponding to the field with the given name 
540  *          identifier.
541  */
542 const GValue *
543 gst_structure_id_get_value(const GstStructure *structure, GQuark id)
544 {
545   GstStructureField *field;
546
547   g_return_val_if_fail(structure != NULL, NULL);
548
549   field = gst_structure_id_get_field(structure, id);
550   if(field == NULL) return NULL;
551
552   return &field->value;
553 }
554
555 #if 0
556 void gst_structure_get(GstStructure *structure, const gchar *fieldname, ...)
557 {
558
559 }
560 #endif
561
562 /**
563  * gst_structure_remove_field:
564  * @structure: a #GstStructure
565  * @fieldname: the name of the field to remove
566  *
567  * Removes the field with the given name.  If the field with the given
568  * name does not exist, the structure is unchanged.
569  */
570 void
571 gst_structure_remove_field(GstStructure *structure, const gchar *fieldname)
572 {
573   GstStructureField *field;
574   GQuark id;
575   int i;
576
577   g_return_if_fail(structure != NULL);
578   g_return_if_fail(fieldname != NULL);
579
580   id = g_quark_from_string(fieldname);
581
582   for(i=0;i<structure->fields->len;i++){
583     field = GST_STRUCTURE_FIELD(structure, i);
584
585     if(field->name == id){
586       if(G_IS_VALUE(&field->value)){
587         g_value_unset(&field->value);
588       }
589       structure->fields = g_array_remove_index(structure->fields, i);
590       return;
591     }
592   }
593 }
594
595 /**
596  * gst_structure_remove_all_fields:
597  * @structure: a #GstStructure
598  *
599  * Removes all fields in a GstStructure. 
600  */
601 void
602 gst_structure_remove_all_fields(GstStructure *structure)
603 {
604   GstStructureField *field;
605   int i;
606
607   g_return_if_fail(structure != NULL);
608
609   for (i = structure->fields->len - 1; i >= 0; i-- ) {
610     field = GST_STRUCTURE_FIELD(structure, i);
611
612     if (G_IS_VALUE (&field->value)) {
613       g_value_unset(&field->value);
614     }
615     structure->fields = g_array_remove_index (structure->fields, i);
616   }
617 }
618
619 /**
620  * gst_structure_get_field_type:
621  * @structure: a #GstStructure
622  * @fieldname: the name of the field
623  *
624  * Finds the field with the given name, and returns the type of the
625  * value it contains.  If the field is not found, G_TYPE_INVALID is
626  * returned.
627  *
628  * Returns: the #GValue of the field
629  */
630 GType
631 gst_structure_get_field_type(const GstStructure *structure, const gchar *fieldname)
632 {
633   GstStructureField *field;
634
635   g_return_val_if_fail(structure != NULL, G_TYPE_INVALID);
636   g_return_val_if_fail(fieldname != NULL, G_TYPE_INVALID);
637
638   field = gst_structure_get_field(structure, fieldname);
639   if(field == NULL) return G_TYPE_INVALID;
640
641   return G_VALUE_TYPE(&field->value);
642 }
643
644 /**
645  * gst_structure_n_fields:
646  * @structure: a #GstStructure
647  *
648  * Accessor function.
649  *
650  * Returns: the number of fields in the structure
651  */
652 gint
653 gst_structure_n_fields(const GstStructure *structure)
654 {
655   g_return_val_if_fail(structure != NULL, 0);
656
657   return structure->fields->len;
658 }
659
660 /**
661  * gst_structure_foreach:
662  * @structure: a #GstStructure
663  * @func: a function to call for each field
664  * @user_data: private data
665  *
666  * Calls the provided function once for each field in the #GstStructure.
667  */
668 gboolean
669 gst_structure_foreach (GstStructure *structure,
670     GstStructureForeachFunc func, gpointer user_data)
671 {
672   int i;
673   GstStructureField *field;
674   gboolean ret;
675
676   for(i=0;i<structure->fields->len;i++){
677     field = GST_STRUCTURE_FIELD(structure, i);
678
679     ret = func (field->name, &field->value, user_data);
680     if (!ret) return FALSE;
681   }
682
683   return TRUE;
684 }
685
686 /**
687  * gst_structure_has_field:
688  * @structure: a #GstStructure
689  * @fieldname: the name of a field
690  *
691  * Accessor function.
692  *
693  * Returns: TRUE if the structure contains a field with the given name
694  */
695 gboolean
696 gst_structure_has_field(const GstStructure *structure, const gchar *fieldname)
697 {
698   GstStructureField *field;
699
700   g_return_val_if_fail(structure != NULL, 0);
701   g_return_val_if_fail(fieldname != NULL, 0);
702
703   field = gst_structure_get_field(structure, fieldname);
704
705   return (field != NULL);
706 }
707
708 /**
709  * gst_structure_has_field:
710  * @structure: a #GstStructure
711  * @fieldname: the name of a field
712  * @type: the type of a value
713  *
714  * Accessor function.
715  *
716  * Returns: TRUE if the structure contains a field with the given name and type
717  */
718 gboolean
719 gst_structure_has_field_typed(const GstStructure *structure, const gchar *fieldname,
720     GType type)
721 {
722   GstStructureField *field;
723
724   g_return_val_if_fail(structure != NULL, 0);
725   g_return_val_if_fail(fieldname != NULL, 0);
726
727   field = gst_structure_get_field(structure, fieldname);
728   if(field == NULL) return FALSE;
729
730   return (G_VALUE_TYPE(&field->value) == type);
731 }
732
733
734 /* utility functions */
735
736 /**
737  * gst_structure_get_boolean:
738  * @structure: a #GstStructure
739  * @fieldname: the name of a field
740  * @ptr: a pointer to a #gboolean to set
741  *
742  * Sets the boolean pointed to by @ptr corresponding to the value of the
743  * given field.  Caller is responsible for making sure the field exists
744  * and has the correct type.
745  *
746  * Returns: TRUE if the value could be set correctly
747  */
748 gboolean
749 gst_structure_get_boolean(const GstStructure *structure, const gchar *fieldname,
750     gboolean *value)
751 {
752   GstStructureField *field;
753
754   g_return_val_if_fail(structure != NULL, FALSE);
755   g_return_val_if_fail(fieldname != NULL, FALSE);
756
757   field = gst_structure_get_field(structure, fieldname);
758
759   if(field == NULL) return FALSE;
760   if(!G_VALUE_HOLDS_BOOLEAN(&field->value))return FALSE;
761
762   *value = g_value_get_boolean(&field->value);
763
764   return TRUE;
765 }
766
767 /**
768  * gst_structure_get_int:
769  * @structure: a #GstStructure
770  * @fieldname: the name of a field
771  * @ptr: a pointer to an int to set
772  *
773  * Sets the int pointed to by @ptr corresponding to the value of the
774  * given field.  Caller is responsible for making sure the field exists
775  * and has the correct type.
776  *
777  * Returns: TRUE if the value could be set correctly
778  */
779 gboolean
780 gst_structure_get_int(const GstStructure *structure, const gchar *fieldname,
781     gint *value)
782 {
783   GstStructureField *field;
784
785   g_return_val_if_fail(structure != NULL, FALSE);
786   g_return_val_if_fail(fieldname != NULL, FALSE);
787   g_return_val_if_fail(value != NULL, FALSE);
788
789   field = gst_structure_get_field(structure, fieldname);
790
791   if(field == NULL) return FALSE;
792   if(!G_VALUE_HOLDS_INT(&field->value))return FALSE;
793
794   *value = g_value_get_int(&field->value);
795
796   return TRUE;
797 }
798
799 /**
800  * gst_structure_get_fourcc:
801  * @structure: a #GstStructure
802  * @fieldname: the name of a field
803  * @ptr: a pointer to a #GstFourcc to set
804  *
805  * Sets the #GstFourcc pointed to by @ptr corresponding to the value of the
806  * given field.  Caller is responsible for making sure the field exists
807  * and has the correct type.
808  *
809  * Returns: TRUE if the value could be set correctly
810  */
811 gboolean
812 gst_structure_get_fourcc(const GstStructure *structure, const gchar *fieldname,
813     guint32 *value)
814 {
815   GstStructureField *field;
816
817   g_return_val_if_fail(structure != NULL, FALSE);
818   g_return_val_if_fail(fieldname != NULL, FALSE);
819   g_return_val_if_fail(value != NULL, FALSE);
820
821   field = gst_structure_get_field(structure, fieldname);
822
823   if(field == NULL) return FALSE;
824   if(!GST_VALUE_HOLDS_FOURCC(&field->value))return FALSE;
825
826   *value = gst_value_get_fourcc (&field->value);
827
828   return TRUE;
829 }
830
831 /**
832  * gst_structure_get_double:
833  * @structure: a #GstStructure
834  * @fieldname: the name of a field
835  * @ptr: a pointer to a #GstFourcc to set
836  *
837  * Sets the double pointed to by @ptr corresponding to the value of the
838  * given field.  Caller is responsible for making sure the field exists
839  * and has the correct type.
840  *
841  * Returns: TRUE if the value could be set correctly
842  */
843 gboolean gst_structure_get_double(const GstStructure *structure,
844     const gchar *fieldname, gdouble *value)
845 {
846   GstStructureField *field;
847
848   g_return_val_if_fail(structure != NULL, FALSE);
849   g_return_val_if_fail(fieldname != NULL, FALSE);
850   g_return_val_if_fail(value != NULL, FALSE);
851
852   field = gst_structure_get_field(structure, fieldname);
853
854   if(field == NULL) return FALSE;
855   if(!G_VALUE_HOLDS_DOUBLE(&field->value))return FALSE;
856
857   *value = g_value_get_double(&field->value);
858
859   return TRUE;
860 }
861
862 /**
863  * gst_structure_get_string:
864  * @structure: a #GstStructure
865  * @fieldname: the name of a field
866  * @ptr: a pointer to a #GstFourcc to set
867  *
868  * Finds the field corresponding to @fieldname, and returns the string
869  * contained in the field's value.  Caller is responsible for making
870  * sure the field exists and has the correct type.
871  *
872  * The string should not be modified, and remains valid until the next
873  * call to a gst_structure_*() function with the given structure.
874  *
875  * Returns: a pointer to the string
876  */
877 const gchar *
878 gst_structure_get_string(const GstStructure *structure, const gchar *fieldname)
879 {
880   GstStructureField *field;
881
882   g_return_val_if_fail(structure != NULL, NULL);
883   g_return_val_if_fail(fieldname != NULL, NULL);
884
885   field = gst_structure_get_field(structure, fieldname);
886
887   if(field == NULL) return FALSE;
888   if(!G_VALUE_HOLDS_STRING(&field->value))return FALSE;
889
890   return g_value_get_string(&field->value);
891 }
892
893 typedef struct _GstStructureAbbreviation {
894   char *type_name;
895   GType type;
896 } GstStructureAbbreviation;
897
898 static GstStructureAbbreviation _gst_structure_abbrs[] = {
899   { "int",      G_TYPE_INT },
900   { "i",        G_TYPE_INT },
901   { "float",    G_TYPE_FLOAT },
902   { "f",        G_TYPE_FLOAT },
903   { "double",   G_TYPE_DOUBLE },
904   { "d",        G_TYPE_DOUBLE },
905 //{ "fourcc",   GST_TYPE_FOURCC },
906   { "boolean",  G_TYPE_BOOLEAN },
907   { "bool",     G_TYPE_BOOLEAN },
908   { "b",        G_TYPE_BOOLEAN },
909   { "string",   G_TYPE_STRING },
910   { "str",      G_TYPE_STRING },
911   { "s",        G_TYPE_STRING }
912 };
913
914 static GType _gst_structure_from_abbr(const char *type_name)
915 {
916   int i;
917
918   g_return_val_if_fail(type_name != NULL, G_TYPE_INVALID);
919
920   for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
921     if(strcmp(type_name,_gst_structure_abbrs[i].type_name)==0){
922       return _gst_structure_abbrs[i].type;
923     }
924   }
925
926   /* FIXME shouldn't be a special case */
927   if (strcmp (type_name,"fourcc") == 0 || strcmp (type_name, "4") == 0) {
928     return GST_TYPE_FOURCC;
929   }
930
931   return g_type_from_name (type_name);
932 }
933
934 static const char *_gst_structure_to_abbr(GType type)
935 {
936   int i;
937
938   g_return_val_if_fail(type != G_TYPE_INVALID, NULL);
939
940   for(i=0;i<G_N_ELEMENTS(_gst_structure_abbrs);i++){
941     if(type == _gst_structure_abbrs[i].type){
942       return _gst_structure_abbrs[i].type_name;
943     }
944   }
945
946   /* FIXME shouldn't be a special case */
947   if (type == GST_TYPE_FOURCC) {
948     return "fourcc";
949   }
950
951   return g_type_name(type);
952 }
953
954 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
955       ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
956       ((c) == '.'))
957
958 /**
959  * gst_structure_to_string:
960  * @structure: a #GstStructure
961  *
962  * Converts @structure to a human-readable representation.
963  * 
964  * Returns: a pointer to string allocated by g_malloc()
965  */
966 gchar *
967 gst_structure_to_string(const GstStructure *structure)
968 {
969   GstStructureField *field;
970   GString *s;
971   int i;
972
973   g_return_val_if_fail(structure != NULL, NULL);
974
975   s = g_string_new("");
976   /* FIXME this string may need to be escaped */
977   g_string_append_printf(s, "%s", g_quark_to_string(structure->name));
978   for(i=0;i<structure->fields->len;i++) {
979     char *t;
980     GType type;
981
982     field = GST_STRUCTURE_FIELD(structure, i);
983
984     t = gst_value_serialize (&field->value);
985     type = G_VALUE_TYPE (&field->value);
986
987     if (type == GST_TYPE_LIST) {
988       GArray *array = g_value_peek_pointer (&field->value);
989       if (array->len > 0){
990         GValue *value = &g_array_index (array, GValue, 0);
991
992         type = G_VALUE_TYPE (value);
993       } else {
994         type = G_TYPE_INT;
995       }
996     } else if (G_VALUE_TYPE(&field->value) == GST_TYPE_INT_RANGE) {
997       type = G_TYPE_INT;
998     } else if (G_VALUE_TYPE(&field->value) == GST_TYPE_DOUBLE_RANGE) {
999       type = G_TYPE_DOUBLE;
1000     }
1001     g_string_append_printf(s, ", %s=(%s)%s", g_quark_to_string(field->name),
1002         _gst_structure_to_abbr(type), t);
1003     g_free(t);
1004   }
1005   return g_string_free(s, FALSE);
1006 }
1007
1008 /*
1009  * r will still point to the string. if end == next, the string will not be 
1010  * null-terminated. In all other cases it will be.
1011  * end = pointer to char behind end of string, next = pointer to start of
1012  * unread data.
1013  * THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING 
1014  */
1015 static gboolean _gst_structure_parse_simple_string (gchar *s, gchar **end);
1016 static gboolean
1017 _gst_structure_parse_string (gchar *s, gchar **end, gchar **next)
1018 {
1019   gchar *w;
1020
1021   if (*s == 0) return FALSE;
1022
1023   if (*s != '"') {
1024     int ret;
1025
1026     ret = _gst_structure_parse_simple_string (s, end);
1027     *next = *end;
1028
1029     return ret;
1030   }
1031
1032   w = s;
1033   s++;
1034   while (*s != '"') {
1035     if (*s == 0) return FALSE;
1036
1037     if (*s == '\\') {
1038       s++;
1039     }
1040
1041     *w = *s;
1042     w++;
1043     s++;
1044   }
1045   s++;
1046
1047   *end = w;
1048   *next = s;
1049
1050   return TRUE;
1051 }
1052
1053 static int
1054 gst_strtoi (const char *s, char **end, int base)
1055 {
1056   int i;
1057
1058   if (s[0] == '-') {
1059     i = - (int) strtoul (s + 1, end, base);
1060   } else {
1061     i = strtoul (s, end, base);
1062   }
1063
1064   return i;
1065 }
1066
1067 static gboolean
1068 gst_value_from_string (GValue *value, const char *s)
1069 {
1070   gboolean ret = FALSE;
1071   gchar *end;
1072   GType type = G_VALUE_TYPE (value);
1073
1074   if (type == G_TYPE_INVALID) return FALSE;
1075
1076   switch (type) {
1077     case G_TYPE_INT:
1078       {
1079         int x;
1080         x = gst_strtoi (s, &end, 0);
1081         if (*end == 0) {
1082           ret = TRUE;
1083         } else {
1084           if (g_ascii_strcasecmp (s, "little_endian") == 0) {
1085             x = G_LITTLE_ENDIAN;
1086             ret = TRUE;
1087           } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
1088             x = G_BIG_ENDIAN;
1089             ret = TRUE;
1090           } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
1091             x = G_BYTE_ORDER;
1092             ret = TRUE;
1093           } else if (g_ascii_strcasecmp (s, "min") == 0) {
1094             x = G_MININT;
1095             ret = TRUE;
1096           } else if (g_ascii_strcasecmp (s, "max") == 0) {
1097             x = G_MAXINT;
1098             ret = TRUE;
1099           }
1100         }
1101         if (ret) {
1102           g_value_set_int (value, x);
1103         }
1104       }
1105       break;
1106     case G_TYPE_FLOAT:
1107       {
1108         double x;
1109         x = g_ascii_strtod (s, &end);
1110         if (*end == 0) {
1111           g_value_set_float (value, x);
1112           ret = TRUE;
1113         }
1114       }
1115       break;
1116     case G_TYPE_DOUBLE:
1117       {
1118         double x;
1119         x = g_ascii_strtod (s, &end);
1120         if (*end == 0) {
1121           ret = TRUE;
1122         } else {
1123           if (g_ascii_strcasecmp (s, "min") == 0) {
1124             x = -G_MAXDOUBLE;
1125             ret = TRUE;
1126           } else if (g_ascii_strcasecmp (s, "max") == 0) {
1127             x = G_MAXDOUBLE;
1128             ret = TRUE;
1129           }
1130         }
1131         if (ret) {
1132           g_value_set_double (value, x);
1133         }
1134       }
1135       break;
1136     case G_TYPE_BOOLEAN:
1137       {
1138         if (g_ascii_strcasecmp (s, "true") == 0 ||
1139             g_ascii_strcasecmp (s, "yes") == 0 ||
1140             g_ascii_strcasecmp (s, "t") == 0 ||
1141             strcmp (s, "1") == 0) {
1142           g_value_set_boolean (value, TRUE);
1143           ret = TRUE;
1144         } else if (g_ascii_strcasecmp (s, "false") == 0 ||
1145             g_ascii_strcasecmp (s, "no") == 0 ||
1146             g_ascii_strcasecmp (s, "f") == 0 ||
1147             strcmp (s, "0") == 0) {
1148           g_value_set_boolean (value, FALSE);
1149           ret = TRUE;
1150         }
1151       }
1152       break;
1153     case G_TYPE_STRING:
1154       {
1155         g_value_set_string (value, s);
1156         ret = TRUE;
1157       }
1158       break;
1159     default:
1160       /* FIXME: make more general */
1161       if (type == GST_TYPE_FOURCC) {
1162         guint32 fourcc = 0;
1163         if (strlen(s) == 4) {
1164           fourcc = GST_MAKE_FOURCC(s[0], s[1], s[2], s[3]);
1165           ret = TRUE;
1166         } else if (g_ascii_isdigit (*s)) {
1167           fourcc = strtoul (s, &end, 0);
1168           if (*end == 0) {
1169             ret = TRUE;
1170           }
1171         }
1172         gst_value_set_fourcc (value, fourcc);
1173       } else {
1174         g_critical("type %s not handled", g_type_name(type));
1175       }
1176       break;
1177   }
1178
1179   return ret;
1180 }
1181
1182 static gboolean _gst_structure_parse_value (gchar *str, gchar **after,
1183     GValue *value, GType default_type);
1184
1185 static gboolean
1186 _gst_structure_parse_range (gchar *s, gchar **after, GValue *value, GType type)
1187 {
1188   GValue value1 = { 0 };
1189   GValue value2 = { 0 };
1190   GType range_type;
1191   gboolean ret;
1192
1193
1194   if (*s != '[') return FALSE;
1195   s++;
1196
1197   ret = _gst_structure_parse_value(s, &s, &value1, type);
1198   if (ret == FALSE) return FALSE;
1199
1200   while (g_ascii_isspace (*s)) s++;
1201     
1202   if (*s != ',') return FALSE;
1203   s++;
1204
1205   while (g_ascii_isspace (*s)) s++;
1206
1207   ret = _gst_structure_parse_value(s, &s, &value2, type);
1208   if (ret == FALSE) return FALSE;
1209
1210   while (g_ascii_isspace (*s)) s++;
1211
1212   if (*s != ']') return FALSE;
1213   s++;
1214
1215   if (G_VALUE_TYPE (&value1) != G_VALUE_TYPE (&value2)) return FALSE;
1216   
1217   if (G_VALUE_TYPE (&value1) == G_TYPE_DOUBLE) {
1218     range_type = GST_TYPE_DOUBLE_RANGE;
1219   } else if (G_VALUE_TYPE (&value1) == G_TYPE_INT) {
1220     range_type = GST_TYPE_INT_RANGE;
1221   } else {
1222     return FALSE;
1223   }
1224
1225   g_value_init(value, range_type);
1226   if (range_type == GST_TYPE_DOUBLE_RANGE) {
1227     gst_value_set_double_range(value, g_value_get_double(&value1),
1228         g_value_get_double(&value2));
1229   } else {
1230     gst_value_set_int_range(value, g_value_get_int(&value1),
1231         g_value_get_int(&value2));
1232   }
1233
1234   *after = s;
1235   return TRUE;
1236 }
1237
1238 static gboolean
1239 _gst_structure_parse_list (gchar *s, gchar **after, GValue *value, GType type)
1240 {
1241   GValue list_value = { 0 };
1242   gboolean ret;
1243   GArray *array;
1244
1245   g_value_init(value, GST_TYPE_LIST);
1246   array = g_value_peek_pointer (value);
1247
1248   if (*s != '{') return FALSE;
1249   s++;
1250
1251   while (g_ascii_isspace (*s)) s++;
1252   if (*s == '}') {
1253     s++;
1254     *after = s;
1255     return TRUE;
1256   }
1257
1258   ret = _gst_structure_parse_value(s, &s, &list_value, type);
1259   if (ret == FALSE) return FALSE;
1260   
1261   g_array_append_val (array, list_value);
1262
1263   while (g_ascii_isspace (*s)) s++;
1264     
1265   while (*s != '}') {
1266     if (*s != ',') return FALSE;
1267     s++;
1268
1269     while (g_ascii_isspace (*s)) s++;
1270
1271     memset (&list_value, 0, sizeof (list_value));
1272     ret = _gst_structure_parse_value(s, &s, &list_value, type);
1273     if (ret == FALSE) return FALSE;
1274
1275     g_array_append_val (array, list_value);
1276     while (g_ascii_isspace (*s)) s++;
1277   }
1278
1279   s++;
1280
1281   *after = s;
1282   return TRUE;
1283 }
1284
1285 static gboolean
1286 _gst_structure_parse_simple_string (gchar *str, gchar **end)
1287 {
1288   char *s = str;
1289
1290   while(GST_ASCII_IS_STRING(*s)){
1291     s++;
1292   }
1293
1294   *end = s;
1295
1296   return (s != str);
1297 }
1298
1299 static gboolean
1300 _gst_structure_parse_field (gchar *str, gchar **after, GstStructureField *field)
1301 {
1302   gchar *name;
1303   gchar *name_end;
1304   gchar *s;
1305   gchar c;
1306
1307   s = str;
1308
1309   while(g_ascii_isspace (*s)) s++;
1310   name = s;
1311   if (!_gst_structure_parse_simple_string (s, &name_end)) return FALSE;
1312
1313   s = name_end;
1314   while(g_ascii_isspace (*s)) s++;
1315
1316   if (*s != '=') return FALSE;
1317   s++;
1318
1319   c = *name_end;
1320   *name_end = 0;
1321   field->name = g_quark_from_string (name);
1322   *name_end = c;
1323
1324   if (!_gst_structure_parse_value (s, &s, &field->value, G_TYPE_INVALID))
1325     return FALSE;
1326
1327   *after = s;
1328   return TRUE;
1329 }
1330
1331 static gboolean
1332 _gst_structure_parse_value (gchar *str, gchar **after, GValue *value,
1333     GType default_type)
1334 {
1335   gchar *type_name;
1336   gchar *type_end;
1337   gchar *value_s;
1338   gchar *value_end;
1339   gchar *s;
1340   gchar c;
1341   int ret = 0;
1342   GType type = default_type;
1343
1344
1345   s = str;
1346   while(g_ascii_isspace (*s)) s++;
1347
1348   type_name = NULL;
1349   if (*s == '(') {
1350     type = G_TYPE_INVALID;
1351
1352     s++;
1353     while(g_ascii_isspace (*s)) s++;
1354     type_name = s;
1355     if (!_gst_structure_parse_simple_string (s, &type_end)) return FALSE;
1356     s = type_end;
1357     while(g_ascii_isspace (*s)) s++;
1358     if (*s != ')') return FALSE;
1359     s++;
1360     while(g_ascii_isspace (*s)) s++;
1361
1362     c = *type_end;
1363     *type_end = 0;
1364     type = _gst_structure_from_abbr(type_name);
1365     *type_end = c;
1366
1367     if (type == G_TYPE_INVALID) return FALSE;
1368   }
1369
1370   while(g_ascii_isspace (*s)) s++;
1371   if (*s == '[') {
1372     ret = _gst_structure_parse_range (s, &s, value, type);
1373   } else if (*s == '{') {
1374     ret = _gst_structure_parse_list (s, &s, value, type);
1375   } else {
1376     value_s = s;
1377     if (!_gst_structure_parse_string (s, &value_end, &s)) return FALSE;
1378
1379     c = *value_end;
1380     *value_end = 0;
1381     if (type == G_TYPE_INVALID) {
1382       GType try_types[] = { G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_STRING };
1383       int i;
1384
1385       for(i=0;i<3;i++) {
1386         g_value_init(value, try_types[i]);
1387         ret = gst_value_from_string (value, value_s);
1388         if (ret) break;
1389         g_value_unset(value);
1390       }
1391     } else {
1392       g_value_init(value, type);
1393
1394       ret = gst_value_from_string (value, value_s);
1395     }
1396     *value_end = c;
1397   }
1398   
1399   *after = s;
1400
1401   return ret;
1402 }
1403
1404 /**
1405  * gst_structure_from_string:
1406  * @structure: a #GstStructure
1407  *
1408  * Creates a #GstStructure from a string representation.
1409  * 
1410  * Returns: a new #GstStructure
1411  */
1412 GstStructure *
1413 gst_structure_from_string (const gchar *string, gchar **end)
1414 {
1415   char *name;
1416   char *copy;
1417   char *w;
1418   char *r;
1419   char save;
1420   GstStructure *structure;
1421   GstStructureField field = { 0 };
1422   gboolean res;
1423
1424   g_return_val_if_fail(string != NULL, NULL);
1425
1426   copy = g_strdup(string);
1427   r = copy;
1428
1429   name = r;
1430   res = _gst_structure_parse_string (r, &w, &r);
1431   if (!res) return NULL;
1432   
1433   while (g_ascii_isspace(*r)) r++;
1434   if(*r != 0 && *r != ';' && *r != ',') return NULL;
1435
1436   save = *w;
1437   *w = 0;
1438   structure = gst_structure_empty_new(name);
1439   *w = save;
1440
1441   while (*r && (*r != ';')){
1442     if(*r != ',') {
1443       return NULL;
1444     }
1445     r++;
1446     while (*r && g_ascii_isspace(*r)) r++;
1447
1448     memset(&field,0,sizeof(field));
1449     res = _gst_structure_parse_field (r, &r, &field);
1450     if (!res) {
1451       gst_structure_free (structure);
1452       return NULL;
1453     }
1454     gst_structure_set_field(structure, &field);
1455     while (*r && g_ascii_isspace(*r)) r++;
1456   }
1457
1458   if (end) *end = (char *)string + (r - copy);
1459   return structure;
1460 }
1461
1462 static void
1463 _gst_structure_transform_to_string(const GValue *src_value, GValue *dest_value)
1464 {
1465   g_return_if_fail(src_value != NULL);
1466   g_return_if_fail(dest_value != NULL);
1467
1468   dest_value->data[0].v_pointer =
1469     gst_structure_to_string (src_value->data[0].v_pointer);
1470 }
1471
1472
1473 static void _gst_structure_value_init (GValue *value)
1474 {
1475   value->data[0].v_pointer = gst_structure_empty_new("");
1476 }
1477
1478 static void _gst_structure_value_free (GValue *value)
1479 {
1480   gst_structure_free(value->data[0].v_pointer);
1481
1482 }
1483
1484 static void _gst_structure_value_copy (const GValue *src, GValue *dest)
1485 {
1486   dest->data[0].v_pointer = gst_structure_copy(src->data[0].v_pointer);
1487 }
1488
1489 static gpointer _gst_structure_value_peek_pointer (const GValue *value)
1490 {
1491   return value->data[0].v_pointer;
1492 }
1493