2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstprops.c: Properties subsystem for generic usage
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
27 #include "gstpropsprivate.h"
29 static GMemChunk *_gst_props_entries_chunk;
30 static GMutex *_gst_props_entries_chunk_lock;
32 static GMemChunk *_gst_props_chunk;
33 static GMutex *_gst_props_chunk_lock;
35 static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
38 _gst_props_initialize (void)
40 _gst_props_entries_chunk = g_mem_chunk_new ("GstPropsEntries",
41 sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 256,
43 _gst_props_entries_chunk_lock = g_mutex_new ();
45 _gst_props_chunk = g_mem_chunk_new ("GstProps",
46 sizeof (GstProps), sizeof (GstProps) * 256,
48 _gst_props_chunk_lock = g_mutex_new ();
52 gst_props_debug_entry (GstPropsEntry *entry)
54 switch (entry->propstype) {
55 case GST_PROPS_INT_ID:
56 GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.int_data);
58 case GST_PROPS_FOURCC_ID:
59 GST_DEBUG (GST_CAT_PROPERTIES, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
61 case GST_PROPS_BOOL_ID:
62 GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.bool_data);
64 case GST_PROPS_STRING_ID:
65 GST_DEBUG (GST_CAT_PROPERTIES, "%s\n", entry->data.string_data.string);
67 case GST_PROPS_INT_RANGE_ID:
68 GST_DEBUG (GST_CAT_PROPERTIES, "%d-%d\n", entry->data.int_range_data.min,
69 entry->data.int_range_data.max);
77 props_compare_func (gconstpointer a,
80 GstPropsEntry *entry1 = (GstPropsEntry *)a;
81 GstPropsEntry *entry2 = (GstPropsEntry *)b;
83 return (entry1->propid - entry2->propid);
87 props_find_func (gconstpointer a,
90 GstPropsEntry *entry2 = (GstPropsEntry *)a;
91 GQuark entry1 = (GQuark) GPOINTER_TO_INT (b);
93 return (entry1 - entry2->propid);
96 /* This is implemented as a huge macro because we cannot pass
97 * va_list variables by reference on some architectures.
99 #define GST_PROPS_ENTRY_FILL(entry, var_args) \
101 entry->propstype = va_arg (var_args, GstPropsId); \
103 switch (entry->propstype) { \
104 case GST_PROPS_INT_ID: \
105 entry->data.int_data = va_arg (var_args, gint); \
107 case GST_PROPS_INT_RANGE_ID: \
108 entry->data.int_range_data.min = va_arg (var_args, gint); \
109 entry->data.int_range_data.max = va_arg (var_args, gint); \
111 case GST_PROPS_FLOAT_ID: \
112 entry->data.float_data = va_arg (var_args, gdouble); \
114 case GST_PROPS_FLOAT_RANGE_ID: \
115 entry->data.float_range_data.min = va_arg (var_args, gdouble); \
116 entry->data.float_range_data.max = va_arg (var_args, gdouble); \
118 case GST_PROPS_FOURCC_ID: \
119 entry->data.fourcc_data = va_arg (var_args, gulong); \
121 case GST_PROPS_BOOL_ID: \
122 entry->data.bool_data = va_arg (var_args, gboolean); \
124 case GST_PROPS_STRING_ID: \
125 entry->data.string_data.string = g_strdup (va_arg (var_args, gchar*)); \
134 * @firstname: the first property name
135 * @...: the property values
137 * Create a new property from the given key/value pairs
139 * Returns: the new property
142 gst_props_new (const gchar *firstname, ...)
147 va_start (var_args, firstname);
149 props = gst_props_newv (firstname, var_args);
158 * @firstname: the first property name
159 * @var_args: the property values
161 * Create a new property from the list of entries.
163 * Returns: the new property created from the list of entries
166 gst_props_newv (const gchar *firstname, va_list var_args)
169 gboolean inlist = FALSE;
170 const gchar *prop_name;
171 GstPropsEntry *list_entry = NULL;
173 if (firstname == NULL)
176 g_mutex_lock (_gst_props_chunk_lock);
177 props = g_mem_chunk_alloc (_gst_props_chunk);
178 g_mutex_unlock (_gst_props_chunk_lock);
180 props->properties = NULL;
183 prop_name = firstname;
187 GstPropsEntry *entry;
189 g_mutex_lock (_gst_props_entries_chunk_lock);
190 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
191 g_mutex_unlock (_gst_props_entries_chunk_lock);
193 entry->propid = g_quark_from_string (prop_name);
194 GST_PROPS_ENTRY_FILL (entry, var_args);
196 switch (entry->propstype) {
197 case GST_PROPS_INT_ID:
198 case GST_PROPS_INT_RANGE_ID:
199 case GST_PROPS_FLOAT_ID:
200 case GST_PROPS_FLOAT_RANGE_ID:
201 case GST_PROPS_FOURCC_ID:
202 case GST_PROPS_BOOL_ID:
203 case GST_PROPS_STRING_ID:
205 case GST_PROPS_LIST_ID:
206 g_return_val_if_fail (inlist == FALSE, NULL);
209 list_entry->data.list_data.entries = NULL;
211 case GST_PROPS_END_ID:
212 g_return_val_if_fail (inlist == TRUE, NULL);
215 prop_name = va_arg (var_args, gchar*);
218 g_warning ("unknown property type found %d for '%s'\n", entry->propstype, prop_name);
219 g_mutex_lock (_gst_props_entries_chunk_lock);
220 g_mem_chunk_free (_gst_props_entries_chunk, entry);
221 g_mutex_unlock (_gst_props_entries_chunk_lock);
225 if (inlist && (list_entry != entry)) {
226 list_entry->data.list_data.entries = g_list_prepend (list_entry->data.list_data.entries, entry);
229 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
232 prop_name = va_arg (var_args, gchar*);
240 * @props: the props to modify
241 * @name: the name of the entry to modify
242 * @...: More property entries.
244 * Modifies the value of the given entry in the props struct.
246 * Returns: the new modified property structure.
249 gst_props_set (GstProps *props, const gchar *name, ...)
255 quark = g_quark_from_string (name);
257 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
260 GstPropsEntry *entry;
262 entry = (GstPropsEntry *)lentry->data;
264 va_start (var_args, name);
266 GST_PROPS_ENTRY_FILL (entry, var_args);
271 g_print("gstprops: no property '%s' to change\n", name);
279 * @props: the props to unref
281 * Decrease the refcount of the property structure, destroying
282 * the property if the refcount is 0.
285 gst_props_unref (GstProps *props)
287 g_return_if_fail (props != NULL);
291 if (props->refcount == 0)
292 gst_props_destroy (props);
297 * @props: the props to ref
299 * Increase the refcount of the property structure.
302 gst_props_ref (GstProps *props)
304 g_return_if_fail (props != NULL);
311 * @props: the props to destroy
313 * Destroy the property, freeing all the memory that
317 gst_props_destroy (GstProps *props)
321 g_return_if_fail (props != NULL);
323 entries = props->properties;
326 GstPropsEntry *entry = (GstPropsEntry *)entries->data;
328 // FIXME also free the lists
329 g_mutex_lock (_gst_props_entries_chunk_lock);
330 g_mem_chunk_free (_gst_props_entries_chunk, entry);
331 g_mutex_unlock (_gst_props_entries_chunk_lock);
333 entries = g_list_next (entries);
336 g_list_free (props->properties);
341 * @props: the props to copy
343 * Copy the property structure.
345 * Returns: the new property that is a copy of the original
349 gst_props_copy (GstProps *props)
354 g_return_val_if_fail (props != NULL, NULL);
356 g_mutex_lock (_gst_props_chunk_lock);
357 new = g_mem_chunk_alloc (_gst_props_chunk);
358 g_mutex_unlock (_gst_props_chunk_lock);
360 new->properties = NULL;
362 properties = props->properties;
365 GstPropsEntry *entry = (GstPropsEntry *)properties->data;
366 GstPropsEntry *newentry;
368 g_mutex_lock (_gst_props_entries_chunk_lock);
369 newentry = g_mem_chunk_alloc (_gst_props_entries_chunk);
370 g_mutex_unlock (_gst_props_entries_chunk_lock);
372 // FIXME copy lists too
373 memcpy (newentry, entry, sizeof (GstPropsEntry));
375 new->properties = g_list_prepend (new->properties, newentry);
377 properties = g_list_next (properties);
379 new->properties = g_list_reverse (new->properties);
385 * gst_props_copy_on_write:
386 * @props: the props to copy on write
388 * Copy the property structure if the refcount is >1.
390 * Returns: A new props that can be safely written to.
393 gst_props_copy_on_write (GstProps *props)
395 GstProps *new = props;;
397 g_return_val_if_fail (props != NULL, NULL);
399 if (props->refcount > 1) {
400 new = gst_props_copy (props);
401 gst_props_unref (props);
409 * @props: the props to get the int value from
410 * @name: the name of the props entry to get.
412 * Get the named entry as an integer.
414 * Returns: the integer value of the named entry, 0 if not found.
417 gst_props_get_int (GstProps *props, const gchar *name)
422 g_return_val_if_fail (props != NULL, 0);
423 g_return_val_if_fail (name != NULL, 0);
425 quark = g_quark_from_string (name);
427 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
430 GstPropsEntry *thisentry;
432 thisentry = (GstPropsEntry *)lentry->data;
434 return thisentry->data.int_data;
441 * gst_props_get_float:
442 * @props: the props to get the float value from
443 * @name: the name of the props entry to get.
445 * Get the named entry as a float.
447 * Returns: the float value of the named entry, 0.0 if not found.
450 gst_props_get_float (GstProps *props, const gchar *name)
455 quark = g_quark_from_string (name);
457 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
460 GstPropsEntry *thisentry;
462 thisentry = (GstPropsEntry *)lentry->data;
464 return thisentry->data.float_data;
471 * gst_props_get_fourcc_int:
472 * @props: the props to get the fourcc value from
473 * @name: the name of the props entry to get.
475 * Get the named entry as a gulong fourcc.
477 * Returns: the fourcc value of the named entry, 0 if not found.
480 gst_props_get_fourcc_int (GstProps *props, const gchar *name)
485 g_return_val_if_fail (props != NULL, 0);
486 g_return_val_if_fail (name != NULL, 0);
488 quark = g_quark_from_string (name);
490 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
493 GstPropsEntry *thisentry;
495 thisentry = (GstPropsEntry *)lentry->data;
497 return thisentry->data.fourcc_data;
504 * gst_props_get_boolean:
505 * @props: the props to get the fourcc value from
506 * @name: the name of the props entry to get.
508 * Get the named entry as a boolean value.
510 * Returns: the boolean value of the named entry, 0 if not found.
513 gst_props_get_boolean (GstProps *props, const gchar *name)
518 g_return_val_if_fail (props != NULL, FALSE);
519 g_return_val_if_fail (name != NULL, FALSE);
521 quark = g_quark_from_string (name);
523 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
526 GstPropsEntry *thisentry;
528 thisentry = (GstPropsEntry *)lentry->data;
530 return thisentry->data.bool_data;
537 * gst_props_get_string:
538 * @props: the props to get the fourcc value from
539 * @name: the name of the props entry to get.
541 * Get the named entry as a string value.
543 * Returns: the string value of the named entry, NULL if not found.
546 gst_props_get_string (GstProps *props, const gchar *name)
551 g_return_val_if_fail (props != NULL, NULL);
552 g_return_val_if_fail (name != NULL, NULL);
554 quark = g_quark_from_string (name);
556 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
559 GstPropsEntry *thisentry;
561 thisentry = (GstPropsEntry *)lentry->data;
563 return thisentry->data.string_data.string;
571 * @props: the property to merge into
572 * @tomerge: the property to merge
574 * Merge the properties of tomerge into props.
576 * Returns: the new merged property
579 gst_props_merge (GstProps *props, GstProps *tomerge)
583 g_return_val_if_fail (props != NULL, NULL);
584 g_return_val_if_fail (tomerge != NULL, NULL);
586 merge_props = tomerge->properties;
588 // FIXME do proper merging here...
589 while (merge_props) {
590 GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
592 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
594 merge_props = g_list_next (merge_props);
601 /* entry2 is always a list, entry1 never is */
603 gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
605 GList *entrylist = entry2->data.list_data.entries;
606 gboolean found = FALSE;
608 while (entrylist && !found) {
609 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
611 found |= gst_props_entry_check_compatibility (entry1, entry);
613 entrylist = g_list_next (entrylist);
620 gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
622 GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s\n", g_quark_to_string (entry1->propid),
623 g_quark_to_string (entry2->propid));
624 switch (entry1->propstype) {
625 case GST_PROPS_LIST_ID:
627 GList *entrylist = entry1->data.list_data.entries;
628 gboolean valid = TRUE; // innocent until proven guilty
630 while (entrylist && valid) {
631 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
633 valid &= gst_props_entry_check_compatibility (entry, entry2);
635 entrylist = g_list_next (entrylist);
640 case GST_PROPS_INT_RANGE_ID:
641 switch (entry2->propstype) {
643 case GST_PROPS_INT_RANGE_ID:
644 return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
645 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
646 case GST_PROPS_LIST_ID:
647 return gst_props_entry_check_list_compatibility (entry1, entry2);
652 case GST_PROPS_FLOAT_RANGE_ID:
653 switch (entry2->propstype) {
655 case GST_PROPS_FLOAT_RANGE_ID:
656 return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
657 entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
658 case GST_PROPS_LIST_ID:
659 return gst_props_entry_check_list_compatibility (entry1, entry2);
664 case GST_PROPS_FOURCC_ID:
665 switch (entry2->propstype) {
667 case GST_PROPS_FOURCC_ID:
668 return (entry2->data.fourcc_data == entry1->data.fourcc_data);
670 case GST_PROPS_LIST_ID:
671 return gst_props_entry_check_list_compatibility (entry1, entry2);
676 case GST_PROPS_INT_ID:
677 switch (entry2->propstype) {
679 case GST_PROPS_INT_RANGE_ID:
680 GST_DEBUG(GST_CAT_PROPERTIES,"%d <= %d <= %d ?\n",entry2->data.int_range_data.min,
681 entry1->data.int_data,entry2->data.int_range_data.max);
682 return (entry2->data.int_range_data.min <= entry1->data.int_data &&
683 entry2->data.int_range_data.max >= entry1->data.int_data);
685 case GST_PROPS_INT_ID:
686 GST_DEBUG(GST_CAT_PROPERTIES,"%d == %d ?\n",entry1->data.int_data,entry2->data.int_data);
687 return (entry2->data.int_data == entry1->data.int_data);
689 case GST_PROPS_LIST_ID:
690 return gst_props_entry_check_list_compatibility (entry1, entry2);
695 case GST_PROPS_FLOAT_ID:
696 switch (entry2->propstype) {
698 case GST_PROPS_FLOAT_RANGE_ID:
699 return (entry2->data.float_range_data.min <= entry1->data.float_data &&
700 entry2->data.float_range_data.max >= entry1->data.float_data);
702 case GST_PROPS_FLOAT_ID:
703 return (entry2->data.float_data == entry1->data.float_data);
705 case GST_PROPS_LIST_ID:
706 return gst_props_entry_check_list_compatibility (entry1, entry2);
711 case GST_PROPS_BOOL_ID:
712 switch (entry2->propstype) {
714 case GST_PROPS_BOOL_ID:
715 return (entry2->data.bool_data == entry1->data.bool_data);
716 case GST_PROPS_LIST_ID:
717 return gst_props_entry_check_list_compatibility (entry1, entry2);
721 case GST_PROPS_STRING_ID:
722 switch (entry2->propstype) {
724 case GST_PROPS_STRING_ID:
725 return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
726 case GST_PROPS_LIST_ID:
727 return gst_props_entry_check_list_compatibility (entry1, entry2);
739 * gst_props_check_compatibility:
740 * @fromprops: a property
741 * @toprops: a property
743 * Checks whether two capabilities are compatible.
745 * Returns: TRUE if compatible, FALSE otherwise
748 gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
754 gboolean compatible = TRUE;
756 g_return_val_if_fail (fromprops != NULL, FALSE);
757 g_return_val_if_fail (toprops != NULL, FALSE);
759 sourcelist = fromprops->properties;
760 sinklist = toprops->properties;
762 while (sourcelist && sinklist && compatible) {
763 GstPropsEntry *entry1;
764 GstPropsEntry *entry2;
766 entry1 = (GstPropsEntry *)sourcelist->data;
767 entry2 = (GstPropsEntry *)sinklist->data;
769 while (entry1->propid < entry2->propid) {
770 GST_DEBUG (GST_CAT_PROPERTIES,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
772 sourcelist = g_list_next (sourcelist);
773 if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
776 while (entry1->propid > entry2->propid) {
777 GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
779 sinklist = g_list_next (sinklist);
780 if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
784 if (!gst_props_entry_check_compatibility (entry1, entry2)) {
786 GST_DEBUG (GST_CAT_PROPERTIES, "%s are not compatible: \n",
787 g_quark_to_string (entry1->propid));
788 gst_props_debug_entry (entry1);
789 gst_props_debug_entry (entry2);
792 sourcelist = g_list_next (sourcelist);
793 sinklist = g_list_next (sinklist);
795 if (sinklist && compatible) {
796 GstPropsEntry *entry2;
797 entry2 = (GstPropsEntry *)sinklist->data;
799 GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
810 gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
815 switch (entry->propstype) {
816 case GST_PROPS_INT_ID:
817 subtree = xmlNewChild (parent, NULL, "int", NULL);
818 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
819 str = g_strdup_printf ("%d", entry->data.int_data);
820 xmlNewProp (subtree, "value", str);
823 case GST_PROPS_INT_RANGE_ID:
824 subtree = xmlNewChild (parent, NULL, "range", NULL);
825 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
826 str = g_strdup_printf ("%d", entry->data.int_range_data.min);
827 xmlNewProp (subtree, "min", str);
829 str = g_strdup_printf ("%d", entry->data.int_range_data.max);
830 xmlNewProp (subtree, "max", str);
833 case GST_PROPS_FLOAT_ID:
834 subtree = xmlNewChild (parent, NULL, "float", NULL);
835 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
836 str = g_strdup_printf ("%f", entry->data.float_data);
837 xmlNewProp (subtree, "value", str);
840 case GST_PROPS_FLOAT_RANGE_ID:
841 subtree = xmlNewChild (parent, NULL, "floatrange", NULL);
842 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
843 str = g_strdup_printf ("%f", entry->data.float_range_data.min);
844 xmlNewProp (subtree, "min", str);
846 str = g_strdup_printf ("%f", entry->data.float_range_data.max);
847 xmlNewProp (subtree, "max", str);
850 case GST_PROPS_FOURCC_ID:
851 str = g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data);
852 xmlAddChild (parent, xmlNewComment (str));
854 subtree = xmlNewChild (parent, NULL, "fourcc", NULL);
855 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
856 str = g_strdup_printf ("%08x", entry->data.fourcc_data);
857 xmlNewProp (subtree, "hexvalue", str);
860 case GST_PROPS_BOOL_ID:
861 subtree = xmlNewChild (parent, NULL, "boolean", NULL);
862 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
863 xmlNewProp (subtree, "value", (entry->data.bool_data ? "true" : "false"));
865 case GST_PROPS_STRING_ID:
866 subtree = xmlNewChild (parent, NULL, "string", NULL);
867 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
868 xmlNewProp (subtree, "value", entry->data.string_data.string);
878 * gst_props_save_thyself:
879 * @props: a property to save
880 * @parent: the parent XML tree
882 * Saves the property into an XML representation.
884 * Returns: the new XML tree
887 gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
892 g_return_val_if_fail (props != NULL, NULL);
894 proplist = props->properties;
897 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
899 switch (entry->propstype) {
900 case GST_PROPS_LIST_ID:
901 subtree = xmlNewChild (parent, NULL, "list", NULL);
902 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
903 g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
905 gst_props_save_thyself_func (entry, parent);
908 proplist = g_list_next (proplist);
914 static GstPropsEntry*
915 gst_props_load_thyself_func (xmlNodePtr field)
917 GstPropsEntry *entry;
920 g_mutex_lock (_gst_props_entries_chunk_lock);
921 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
922 g_mutex_unlock (_gst_props_entries_chunk_lock);
924 if (!strcmp(field->name, "int")) {
925 entry->propstype = GST_PROPS_INT_ID;
926 prop = xmlGetProp(field, "name");
927 entry->propid = g_quark_from_string (prop);
929 prop = xmlGetProp(field, "value");
930 sscanf (prop, "%d", &entry->data.int_data);
933 else if (!strcmp(field->name, "range")) {
934 entry->propstype = GST_PROPS_INT_RANGE_ID;
935 prop = xmlGetProp(field, "name");
936 entry->propid = g_quark_from_string (prop);
938 prop = xmlGetProp (field, "min");
939 sscanf (prop, "%d", &entry->data.int_range_data.min);
941 prop = xmlGetProp (field, "max");
942 sscanf (prop, "%d", &entry->data.int_range_data.max);
945 else if (!strcmp(field->name, "float")) {
946 entry->propstype = GST_PROPS_FLOAT_ID;
947 prop = xmlGetProp(field, "name");
948 entry->propid = g_quark_from_string (prop);
950 prop = xmlGetProp(field, "value");
951 sscanf (prop, "%f", &entry->data.float_data);
954 else if (!strcmp(field->name, "floatrange")) {
955 entry->propstype = GST_PROPS_FLOAT_RANGE_ID;
956 prop = xmlGetProp(field, "name");
957 entry->propid = g_quark_from_string (prop);
959 prop = xmlGetProp (field, "min");
960 sscanf (prop, "%f", &entry->data.float_range_data.min);
962 prop = xmlGetProp (field, "max");
963 sscanf (prop, "%f", &entry->data.float_range_data.max);
966 else if (!strcmp(field->name, "boolean")) {
967 entry->propstype = GST_PROPS_BOOL_ID;
968 prop = xmlGetProp(field, "name");
969 entry->propid = g_quark_from_string (prop);
971 prop = xmlGetProp (field, "value");
972 if (!strcmp (prop, "false")) entry->data.bool_data = 0;
973 else entry->data.bool_data = 1;
976 else if (!strcmp(field->name, "fourcc")) {
977 entry->propstype = GST_PROPS_FOURCC_ID;
978 prop = xmlGetProp(field, "name");
979 entry->propid = g_quark_from_string (prop);
981 prop = xmlGetProp (field, "hexvalue");
982 sscanf (prop, "%08x", &entry->data.fourcc_data);
985 else if (!strcmp(field->name, "string")) {
986 entry->propstype = GST_PROPS_STRING_ID;
987 prop = xmlGetProp(field, "name");
988 entry->propid = g_quark_from_string (prop);
990 entry->data.string_data.string = xmlGetProp (field, "value");
993 g_mutex_lock (_gst_props_entries_chunk_lock);
994 g_mem_chunk_free (_gst_props_entries_chunk, entry);
995 g_mutex_unlock (_gst_props_entries_chunk_lock);
1003 * gst_props_load_thyself:
1004 * @parent: the XML tree to load from
1006 * Creates a new property out of an XML tree.
1008 * Returns: the new property
1011 gst_props_load_thyself (xmlNodePtr parent)
1014 xmlNodePtr field = parent->xmlChildrenNode;
1017 g_mutex_lock (_gst_props_chunk_lock);
1018 props = g_mem_chunk_alloc (_gst_props_chunk);
1019 g_mutex_unlock (_gst_props_chunk_lock);
1021 props->properties = NULL;
1022 props->refcount = 1;
1025 if (!strcmp (field->name, "list")) {
1026 GstPropsEntry *entry;
1027 xmlNodePtr subfield = field->xmlChildrenNode;
1029 g_mutex_lock (_gst_props_entries_chunk_lock);
1030 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1031 g_mutex_unlock (_gst_props_entries_chunk_lock);
1033 entry->propstype = GST_PROPS_LIST_ID;
1034 entry->data.list_data.entries = NULL;
1035 prop = xmlGetProp (field, "name");
1036 entry->propid = g_quark_from_string (prop);
1040 GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
1043 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
1045 subfield = subfield->next;
1047 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
1048 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1051 GstPropsEntry *entry;
1053 entry = gst_props_load_thyself_func (field);
1056 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1058 field = field->next;