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 (0, "%d\n", entry->data.int_data);
58 case GST_PROPS_FOURCC_ID:
59 GST_DEBUG (0, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
61 case GST_PROPS_BOOL_ID:
62 GST_DEBUG (0, "%d\n", entry->data.bool_data);
64 case GST_PROPS_STRING_ID:
65 GST_DEBUG (0, "%s\n", entry->data.string_data.string);
67 case GST_PROPS_INT_RANGE_ID:
68 GST_DEBUG (0, "%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);
97 gst_props_entry_fill (GstPropsEntry *entry, va_list *var_args)
99 entry->propstype = va_arg (*var_args, GstPropsId);
101 switch (entry->propstype) {
102 case GST_PROPS_INT_ID:
103 entry->data.int_data = va_arg (*var_args, gint);
105 case GST_PROPS_INT_RANGE_ID:
106 entry->data.int_range_data.min = va_arg (*var_args, gint);
107 entry->data.int_range_data.max = va_arg (*var_args, gint);
109 case GST_PROPS_FLOAT_ID:
110 entry->data.float_data = va_arg (*var_args, gdouble);
112 case GST_PROPS_FLOAT_RANGE_ID:
113 entry->data.float_range_data.min = va_arg (*var_args, gdouble);
114 entry->data.float_range_data.max = va_arg (*var_args, gdouble);
116 case GST_PROPS_FOURCC_ID:
117 entry->data.fourcc_data = va_arg (*var_args, gulong);
119 case GST_PROPS_BOOL_ID:
120 entry->data.bool_data = va_arg (*var_args, gboolean);
122 case GST_PROPS_STRING_ID:
123 entry->data.string_data.string = g_strdup (va_arg (*var_args, gchar*));
132 * @firstname: the first property name
133 * @...: the property values
135 * Create a new property from the given key/value pairs
137 * Returns: the new property
140 gst_props_new (const gchar *firstname, ...)
145 va_start (var_args, firstname);
147 props = gst_props_newv (firstname, var_args);
156 * @firstname: the first property name
157 * @var_args: the property values
159 * Create a new property from the list of entries.
161 * Returns: the new property created from the list of entries
164 gst_props_newv (const gchar *firstname, va_list var_args)
167 gboolean inlist = FALSE;
168 const gchar *prop_name;
169 GstPropsEntry *list_entry = NULL;
171 g_mutex_lock (_gst_props_chunk_lock);
172 props = g_mem_chunk_alloc (_gst_props_chunk);
173 g_mutex_unlock (_gst_props_chunk_lock);
175 props->properties = NULL;
178 prop_name = firstname;
182 GstPropsEntry *entry;
184 g_mutex_lock (_gst_props_entries_chunk_lock);
185 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
186 g_mutex_unlock (_gst_props_entries_chunk_lock);
188 entry->propid = g_quark_from_string (prop_name);
189 gst_props_entry_fill (entry, &var_args);
191 switch (entry->propstype) {
192 case GST_PROPS_INT_ID:
193 case GST_PROPS_INT_RANGE_ID:
194 case GST_PROPS_FLOAT_ID:
195 case GST_PROPS_FLOAT_RANGE_ID:
196 case GST_PROPS_FOURCC_ID:
197 case GST_PROPS_BOOL_ID:
198 case GST_PROPS_STRING_ID:
200 case GST_PROPS_LIST_ID:
201 g_return_val_if_fail (inlist == FALSE, NULL);
204 list_entry->data.list_data.entries = NULL;
206 case GST_PROPS_END_ID:
207 g_return_val_if_fail (inlist == TRUE, NULL);
210 prop_name = va_arg (var_args, gchar*);
213 g_mutex_lock (_gst_props_entries_chunk_lock);
214 g_mem_chunk_free (_gst_props_entries_chunk, entry);
215 g_mutex_unlock (_gst_props_entries_chunk_lock);
216 g_assert_not_reached ();
220 if (inlist && (list_entry != entry)) {
221 list_entry->data.list_data.entries = g_list_prepend (list_entry->data.list_data.entries, entry);
224 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
227 prop_name = va_arg (var_args, gchar*);
235 * @props: the props to modify
236 * @name: the name of the entry to modify
237 * @...: More property entries.
239 * Modifies the value of the given entry in the props struct.
241 * Returns: the new modified property structure.
244 gst_props_set (GstProps *props, const gchar *name, ...)
250 quark = g_quark_from_string (name);
252 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
255 GstPropsEntry *entry;
257 entry = (GstPropsEntry *)lentry->data;
259 va_start (var_args, name);
261 gst_props_entry_fill (entry, &var_args);
266 g_print("gstprops: no property '%s' to change\n", name);
274 * @props: the props to unref
276 * Decrease the refcount of the property structure, destroying
277 * the property if the refcount is 0.
280 gst_props_unref (GstProps *props)
282 g_return_if_fail (props != NULL);
286 if (props->refcount == 0)
287 gst_props_destroy (props);
292 * @props: the props to ref
294 * Increase the refcount of the property structure.
297 gst_props_ref (GstProps *props)
299 g_return_if_fail (props != NULL);
306 * @props: the props to destroy
308 * Destroy the property, freeing all the memory that
312 gst_props_destroy (GstProps *props)
316 g_return_if_fail (props != NULL);
318 entries = props->properties;
321 GstPropsEntry *entry = (GstPropsEntry *)entries->data;
323 // FIXME also free the lists
324 g_mutex_lock (_gst_props_entries_chunk_lock);
325 g_mem_chunk_free (_gst_props_entries_chunk, entry);
326 g_mutex_unlock (_gst_props_entries_chunk_lock);
328 entries = g_list_next (entries);
331 g_list_free (props->properties);
336 * @props: the props to copy
338 * Copy the property structure.
340 * Returns: the new property that is a copy of the original
344 gst_props_copy (GstProps *props)
349 g_return_val_if_fail (props != NULL, NULL);
351 g_mutex_lock (_gst_props_chunk_lock);
352 new = g_mem_chunk_alloc (_gst_props_chunk);
353 g_mutex_unlock (_gst_props_chunk_lock);
355 new->properties = NULL;
357 properties = props->properties;
360 GstPropsEntry *entry = (GstPropsEntry *)properties->data;
361 GstPropsEntry *newentry;
363 g_mutex_lock (_gst_props_entries_chunk_lock);
364 newentry = g_mem_chunk_alloc (_gst_props_entries_chunk);
365 g_mutex_unlock (_gst_props_entries_chunk_lock);
367 // FIXME copy lists too
368 memcpy (newentry, entry, sizeof (GstPropsEntry));
370 new->properties = g_list_prepend (new->properties, newentry);
372 properties = g_list_next (properties);
374 new->properties = g_list_reverse (new->properties);
380 * gst_props_copy_on_write:
381 * @props: the props to copy on write
383 * Copy the property structure if the refcount is >1.
385 * Returns: A new props that can be safely written to.
388 gst_props_copy_on_write (GstProps *props)
390 GstProps *new = props;;
392 g_return_val_if_fail (props != NULL, NULL);
394 if (props->refcount > 1) {
395 new = gst_props_copy (props);
396 gst_props_unref (props);
404 * @props: the props to get the int value from
405 * @name: the name of the props entry to get.
407 * Get the named entry as an integer.
409 * Returns: the integer value of the named entry, 0 if not found.
412 gst_props_get_int (GstProps *props, const gchar *name)
417 g_return_val_if_fail (props != NULL, 0);
418 g_return_val_if_fail (name != NULL, 0);
420 quark = g_quark_from_string (name);
422 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
425 GstPropsEntry *thisentry;
427 thisentry = (GstPropsEntry *)lentry->data;
429 return thisentry->data.int_data;
436 * gst_props_get_float:
437 * @props: the props to get the float value from
438 * @name: the name of the props entry to get.
440 * Get the named entry as a float.
442 * Returns: the float value of the named entry, 0.0 if not found.
445 gst_props_get_float (GstProps *props, const gchar *name)
450 quark = g_quark_from_string (name);
452 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
455 GstPropsEntry *thisentry;
457 thisentry = (GstPropsEntry *)lentry->data;
459 return thisentry->data.float_data;
466 * gst_props_get_fourcc_int:
467 * @props: the props to get the fourcc value from
468 * @name: the name of the props entry to get.
470 * Get the named entry as a gulong fourcc.
472 * Returns: the fourcc value of the named entry, 0 if not found.
475 gst_props_get_fourcc_int (GstProps *props, const gchar *name)
480 g_return_val_if_fail (props != NULL, 0);
481 g_return_val_if_fail (name != NULL, 0);
483 quark = g_quark_from_string (name);
485 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
488 GstPropsEntry *thisentry;
490 thisentry = (GstPropsEntry *)lentry->data;
492 return thisentry->data.fourcc_data;
499 * gst_props_get_boolean:
500 * @props: the props to get the fourcc value from
501 * @name: the name of the props entry to get.
503 * Get the named entry as a boolean value.
505 * Returns: the boolean value of the named entry, 0 if not found.
508 gst_props_get_boolean (GstProps *props, const gchar *name)
513 g_return_val_if_fail (props != NULL, FALSE);
514 g_return_val_if_fail (name != NULL, FALSE);
516 quark = g_quark_from_string (name);
518 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
521 GstPropsEntry *thisentry;
523 thisentry = (GstPropsEntry *)lentry->data;
525 return thisentry->data.bool_data;
532 * gst_props_get_string:
533 * @props: the props to get the fourcc value from
534 * @name: the name of the props entry to get.
536 * Get the named entry as a string value.
538 * Returns: the string value of the named entry, NULL if not found.
541 gst_props_get_string (GstProps *props, const gchar *name)
546 g_return_val_if_fail (props != NULL, NULL);
547 g_return_val_if_fail (name != NULL, NULL);
549 quark = g_quark_from_string (name);
551 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
554 GstPropsEntry *thisentry;
556 thisentry = (GstPropsEntry *)lentry->data;
558 return thisentry->data.string_data.string;
566 * @props: the property to merge into
567 * @tomerge: the property to merge
569 * Merge the properties of tomerge into props.
571 * Returns: the new merged property
574 gst_props_merge (GstProps *props, GstProps *tomerge)
578 g_return_val_if_fail (props != NULL, NULL);
579 g_return_val_if_fail (tomerge != NULL, NULL);
581 merge_props = tomerge->properties;
583 // FIXME do proper merging here...
584 while (merge_props) {
585 GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
587 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
589 merge_props = g_list_next (merge_props);
596 /* entry2 is always a list, entry1 never is */
598 gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
600 GList *entrylist = entry2->data.list_data.entries;
601 gboolean found = FALSE;
603 while (entrylist && !found) {
604 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
606 found |= gst_props_entry_check_compatibility (entry1, entry);
608 entrylist = g_list_next (entrylist);
615 gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
617 GST_DEBUG (0,"compare: %s %s\n", g_quark_to_string (entry1->propid),
618 g_quark_to_string (entry2->propid));
619 switch (entry1->propstype) {
620 case GST_PROPS_LIST_ID:
622 GList *entrylist = entry1->data.list_data.entries;
623 gboolean valid = TRUE; // innocent until proven guilty
625 while (entrylist && valid) {
626 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
628 valid &= gst_props_entry_check_compatibility (entry, entry2);
630 entrylist = g_list_next (entrylist);
635 case GST_PROPS_INT_RANGE_ID:
636 switch (entry2->propstype) {
638 case GST_PROPS_INT_RANGE_ID:
639 return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
640 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
641 case GST_PROPS_LIST_ID:
642 return gst_props_entry_check_list_compatibility (entry1, entry2);
647 case GST_PROPS_FLOAT_RANGE_ID:
648 switch (entry2->propstype) {
650 case GST_PROPS_FLOAT_RANGE_ID:
651 return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
652 entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
653 case GST_PROPS_LIST_ID:
654 return gst_props_entry_check_list_compatibility (entry1, entry2);
659 case GST_PROPS_FOURCC_ID:
660 switch (entry2->propstype) {
662 case GST_PROPS_FOURCC_ID:
663 return (entry2->data.fourcc_data == entry1->data.fourcc_data);
665 case GST_PROPS_LIST_ID:
666 return gst_props_entry_check_list_compatibility (entry1, entry2);
671 case GST_PROPS_INT_ID:
672 switch (entry2->propstype) {
674 case GST_PROPS_INT_RANGE_ID:
675 return (entry2->data.int_range_data.min <= entry1->data.int_data &&
676 entry2->data.int_range_data.max >= entry1->data.int_data);
678 case GST_PROPS_INT_ID:
679 return (entry2->data.int_data == entry1->data.int_data);
681 case GST_PROPS_LIST_ID:
682 return gst_props_entry_check_list_compatibility (entry1, entry2);
687 case GST_PROPS_FLOAT_ID:
688 switch (entry2->propstype) {
690 case GST_PROPS_FLOAT_RANGE_ID:
691 return (entry2->data.float_range_data.min <= entry1->data.float_data &&
692 entry2->data.float_range_data.max >= entry1->data.float_data);
694 case GST_PROPS_FLOAT_ID:
695 return (entry2->data.float_data == entry1->data.float_data);
697 case GST_PROPS_LIST_ID:
698 return gst_props_entry_check_list_compatibility (entry1, entry2);
703 case GST_PROPS_BOOL_ID:
704 switch (entry2->propstype) {
706 case GST_PROPS_BOOL_ID:
707 return (entry2->data.bool_data == entry1->data.bool_data);
708 case GST_PROPS_LIST_ID:
709 return gst_props_entry_check_list_compatibility (entry1, entry2);
713 case GST_PROPS_STRING_ID:
714 switch (entry2->propstype) {
716 case GST_PROPS_STRING_ID:
717 return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
718 case GST_PROPS_LIST_ID:
719 return gst_props_entry_check_list_compatibility (entry1, entry2);
731 * gst_props_check_compatibility:
732 * @fromprops: a property
733 * @toprops: a property
735 * Checks whether two capabilities are compatible.
737 * Returns: TRUE if compatible, FALSE otherwise
740 gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
746 gboolean compatible = TRUE;
748 g_return_val_if_fail (fromprops != NULL, FALSE);
749 g_return_val_if_fail (toprops != NULL, FALSE);
751 sourcelist = fromprops->properties;
752 sinklist = toprops->properties;
754 while (sourcelist && sinklist && compatible) {
755 GstPropsEntry *entry1;
756 GstPropsEntry *entry2;
758 entry1 = (GstPropsEntry *)sourcelist->data;
759 entry2 = (GstPropsEntry *)sinklist->data;
761 while (entry1->propid < entry2->propid) {
762 GST_DEBUG (0,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
764 sourcelist = g_list_next (sourcelist);
765 if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
768 while (entry1->propid > entry2->propid) {
769 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
771 sinklist = g_list_next (sinklist);
772 if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
776 if (!gst_props_entry_check_compatibility (entry1, entry2)) {
778 GST_DEBUG (0, "%s are not compatible\n:",
779 g_quark_to_string (entry1->propid));
780 gst_props_debug_entry (entry1);
781 gst_props_debug_entry (entry2);
784 sourcelist = g_list_next (sourcelist);
785 sinklist = g_list_next (sinklist);
787 if (sinklist && compatible) {
788 GstPropsEntry *entry2;
789 entry2 = (GstPropsEntry *)sinklist->data;
791 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
802 gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
807 switch (entry->propstype) {
808 case GST_PROPS_INT_ID:
809 subtree = xmlNewChild (parent, NULL, "int", NULL);
810 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
811 str = g_strdup_printf ("%d", entry->data.int_data);
812 xmlNewProp (subtree, "value", str);
815 case GST_PROPS_INT_RANGE_ID:
816 subtree = xmlNewChild (parent, NULL, "range", NULL);
817 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
818 str = g_strdup_printf ("%d", entry->data.int_range_data.min);
819 xmlNewProp (subtree, "min", str);
821 str = g_strdup_printf ("%d", entry->data.int_range_data.max);
822 xmlNewProp (subtree, "max", str);
825 case GST_PROPS_FLOAT_ID:
826 subtree = xmlNewChild (parent, NULL, "float", NULL);
827 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
828 str = g_strdup_printf ("%f", entry->data.float_data);
829 xmlNewProp (subtree, "value", str);
832 case GST_PROPS_FLOAT_RANGE_ID:
833 subtree = xmlNewChild (parent, NULL, "floatrange", NULL);
834 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
835 str = g_strdup_printf ("%f", entry->data.float_range_data.min);
836 xmlNewProp (subtree, "min", str);
838 str = g_strdup_printf ("%f", entry->data.float_range_data.max);
839 xmlNewProp (subtree, "max", str);
842 case GST_PROPS_FOURCC_ID:
843 str = g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data);
844 xmlAddChild (parent, xmlNewComment (str));
846 subtree = xmlNewChild (parent, NULL, "fourcc", NULL);
847 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
848 str = g_strdup_printf ("%08x", entry->data.fourcc_data);
849 xmlNewProp (subtree, "hexvalue", str);
852 case GST_PROPS_BOOL_ID:
853 subtree = xmlNewChild (parent, NULL, "boolean", NULL);
854 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
855 xmlNewProp (subtree, "value", (entry->data.bool_data ? "true" : "false"));
857 case GST_PROPS_STRING_ID:
858 subtree = xmlNewChild (parent, NULL, "string", NULL);
859 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
860 xmlNewProp (subtree, "value", entry->data.string_data.string);
870 * gst_props_save_thyself:
871 * @props: a property to save
872 * @parent: the parent XML tree
874 * Saves the property into an XML representation.
876 * Returns: the new XML tree
879 gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
884 g_return_val_if_fail (props != NULL, NULL);
886 proplist = props->properties;
889 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
891 switch (entry->propstype) {
892 case GST_PROPS_LIST_ID:
893 subtree = xmlNewChild (parent, NULL, "list", NULL);
894 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
895 g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
897 gst_props_save_thyself_func (entry, parent);
900 proplist = g_list_next (proplist);
906 static GstPropsEntry*
907 gst_props_load_thyself_func (xmlNodePtr field)
909 GstPropsEntry *entry;
912 g_mutex_lock (_gst_props_entries_chunk_lock);
913 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
914 g_mutex_unlock (_gst_props_entries_chunk_lock);
916 if (!strcmp(field->name, "int")) {
917 entry->propstype = GST_PROPS_INT_ID;
918 prop = xmlGetProp(field, "name");
919 entry->propid = g_quark_from_string (prop);
921 prop = xmlGetProp(field, "value");
922 sscanf (prop, "%d", &entry->data.int_data);
925 else if (!strcmp(field->name, "range")) {
926 entry->propstype = GST_PROPS_INT_RANGE_ID;
927 prop = xmlGetProp(field, "name");
928 entry->propid = g_quark_from_string (prop);
930 prop = xmlGetProp (field, "min");
931 sscanf (prop, "%d", &entry->data.int_range_data.min);
933 prop = xmlGetProp (field, "max");
934 sscanf (prop, "%d", &entry->data.int_range_data.max);
937 else if (!strcmp(field->name, "float")) {
938 entry->propstype = GST_PROPS_FLOAT_ID;
939 prop = xmlGetProp(field, "name");
940 entry->propid = g_quark_from_string (prop);
942 prop = xmlGetProp(field, "value");
943 sscanf (prop, "%f", &entry->data.float_data);
946 else if (!strcmp(field->name, "floatrange")) {
947 entry->propstype = GST_PROPS_FLOAT_RANGE_ID;
948 prop = xmlGetProp(field, "name");
949 entry->propid = g_quark_from_string (prop);
951 prop = xmlGetProp (field, "min");
952 sscanf (prop, "%f", &entry->data.float_range_data.min);
954 prop = xmlGetProp (field, "max");
955 sscanf (prop, "%f", &entry->data.float_range_data.max);
958 else if (!strcmp(field->name, "boolean")) {
959 entry->propstype = GST_PROPS_BOOL_ID;
960 prop = xmlGetProp(field, "name");
961 entry->propid = g_quark_from_string (prop);
963 prop = xmlGetProp (field, "value");
964 if (!strcmp (prop, "false")) entry->data.bool_data = 0;
965 else entry->data.bool_data = 1;
968 else if (!strcmp(field->name, "fourcc")) {
969 entry->propstype = GST_PROPS_FOURCC_ID;
970 prop = xmlGetProp(field, "name");
971 entry->propid = g_quark_from_string (prop);
973 prop = xmlGetProp (field, "hexvalue");
974 sscanf (prop, "%08x", &entry->data.fourcc_data);
977 else if (!strcmp(field->name, "string")) {
978 entry->propstype = GST_PROPS_STRING_ID;
979 prop = xmlGetProp(field, "name");
980 entry->propid = g_quark_from_string (prop);
982 entry->data.string_data.string = xmlGetProp (field, "value");
985 g_mutex_lock (_gst_props_entries_chunk_lock);
986 g_mem_chunk_free (_gst_props_entries_chunk, entry);
987 g_mutex_unlock (_gst_props_entries_chunk_lock);
995 * gst_props_load_thyself:
996 * @parent: the XML tree to load from
998 * Creates a new property out of an XML tree.
1000 * Returns: the new property
1003 gst_props_load_thyself (xmlNodePtr parent)
1006 xmlNodePtr field = parent->xmlChildrenNode;
1009 g_mutex_lock (_gst_props_chunk_lock);
1010 props = g_mem_chunk_alloc (_gst_props_chunk);
1011 g_mutex_unlock (_gst_props_chunk_lock);
1013 props->properties = NULL;
1014 props->refcount = 1;
1017 if (!strcmp (field->name, "list")) {
1018 GstPropsEntry *entry;
1019 xmlNodePtr subfield = field->xmlChildrenNode;
1021 g_mutex_lock (_gst_props_entries_chunk_lock);
1022 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1023 g_mutex_unlock (_gst_props_entries_chunk_lock);
1025 entry->propstype = GST_PROPS_LIST_ID;
1026 entry->data.list_data.entries = NULL;
1027 prop = xmlGetProp (field, "name");
1028 entry->propid = g_quark_from_string (prop);
1032 GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
1035 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
1037 subfield = subfield->next;
1039 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
1040 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1043 GstPropsEntry *entry;
1045 entry = gst_props_load_thyself_func (field);
1048 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1050 field = field->next;