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);
37 static guint _arg_len[] = {
38 0, // GST_PROPS_END_ID_NUM = 0,
39 0, // GST_PROPS_LIST_ID_NUM,
40 1, // GST_PROPS_INT_ID_NUM,
41 2, // GST_PROPS_INT_RANGE_ID_NUM,
42 1, // GST_PROPS_FLOAT_ID_NUM,
43 2, // GST_PROPS_FLOAT_RANGE_ID_NUM,
44 1, // GST_PROPS_FOURCC_ID_NUM,
45 1, // GST_PROPS_BOOL_ID_NUM,
46 1, // GST_PROPS_STRING_ID_NUM,
50 _gst_props_initialize (void)
52 _gst_props_entries_chunk = g_mem_chunk_new ("GstPropsEntries",
53 sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 256,
55 _gst_props_entries_chunk_lock = g_mutex_new ();
57 _gst_props_chunk = g_mem_chunk_new ("GstProps",
58 sizeof (GstProps), sizeof (GstProps) * 256,
60 _gst_props_chunk_lock = g_mutex_new ();
64 gst_props_debug_entry (GstPropsEntry *entry)
66 switch (entry->propstype) {
67 case GST_PROPS_INT_ID:
68 GST_DEBUG (0, "%d\n", entry->data.int_data);
70 case GST_PROPS_FOURCC_ID_NUM:
71 GST_DEBUG (0, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
73 case GST_PROPS_BOOL_ID_NUM:
74 GST_DEBUG (0, "%d\n", entry->data.bool_data);
76 case GST_PROPS_STRING_ID_NUM:
77 GST_DEBUG (0, "%s\n", entry->data.string_data.string);
79 case GST_PROPS_INT_RANGE_ID_NUM:
80 GST_DEBUG (0, "%d-%d\n", entry->data.int_range_data.min,
81 entry->data.int_range_data.max);
89 gst_props_create_entry (GstPropsFactory factory, gint *skipped)
91 GstPropsFactoryEntry tag;
95 g_mutex_lock (_gst_props_entries_chunk_lock);
96 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
97 g_mutex_unlock (_gst_props_entries_chunk_lock);
100 switch (GPOINTER_TO_INT (tag)) {
101 case GST_PROPS_INT_ID_NUM:
102 entry->propstype = GST_PROPS_INT_ID_NUM;
103 entry->data.int_data = GPOINTER_TO_INT (factory[i++]);
105 case GST_PROPS_INT_RANGE_ID_NUM:
106 entry->propstype = GST_PROPS_INT_RANGE_ID_NUM;
107 entry->data.int_range_data.min = GPOINTER_TO_INT (factory[i++]);
108 entry->data.int_range_data.max = GPOINTER_TO_INT (factory[i++]);
110 case GST_PROPS_FLOAT_ID_NUM:
111 entry->propstype = GST_PROPS_FLOAT_ID_NUM;
112 entry->data.float_data = *(gfloat*)factory[i++];
114 case GST_PROPS_FLOAT_RANGE_ID_NUM:
115 entry->propstype = GST_PROPS_FLOAT_RANGE_ID_NUM;
116 entry->data.float_range_data.min = *(gfloat*)factory[i++];
117 entry->data.float_range_data.max = *(gfloat*)factory[i++];
119 case GST_PROPS_FOURCC_ID_NUM:
120 entry->propstype = GST_PROPS_FOURCC_ID_NUM;
121 entry->data.fourcc_data = GPOINTER_TO_INT (factory[i++]);
123 case GST_PROPS_LIST_ID_NUM:
124 g_warning ("gstprops: list not allowed in list\n");
126 case GST_PROPS_BOOL_ID_NUM:
127 entry->propstype = GST_PROPS_BOOL_ID_NUM;
128 entry->data.bool_data = GPOINTER_TO_INT (factory[i++]);
130 case GST_PROPS_STRING_ID_NUM:
131 entry->propstype = GST_PROPS_STRING_ID_NUM;
132 entry->data.string_data.string = g_strdup (factory[i++]);
135 g_warning ("gstprops: unknown props id found\n");
136 g_mutex_lock (_gst_props_entries_chunk_lock);
137 g_mem_chunk_free (_gst_props_entries_chunk, entry);
138 g_mutex_unlock (_gst_props_entries_chunk_lock);
150 props_compare_func (gconstpointer a,
153 GstPropsEntry *entry1 = (GstPropsEntry *)a;
154 GstPropsEntry *entry2 = (GstPropsEntry *)b;
156 return (entry1->propid - entry2->propid);
160 props_find_func (gconstpointer a,
163 GstPropsEntry *entry2 = (GstPropsEntry *)a;
164 GQuark entry1 = (GQuark) GPOINTER_TO_INT (b);
166 return (entry1 - entry2->propid);
170 * gst_props_register:
171 * @factory: the factory to register
173 * Register the factory.
175 * Returns: the new property created from the factory
178 gst_props_register (GstPropsFactory factory)
182 return gst_props_register_count (factory, &dummy);
186 * gst_props_register_count:
187 * @factory: the factory to register
188 * @counter: count how many fields were consumed
190 * Register the factory.
192 * Returns: the new property created from the factory
195 gst_props_register_count (GstPropsFactory factory, guint *counter)
197 GstPropsFactoryEntry tag;
199 GstProps *props = NULL;
202 g_return_val_if_fail (factory != NULL, NULL);
208 g_mutex_lock (_gst_props_chunk_lock);
209 props = g_mem_chunk_alloc (_gst_props_chunk);
210 g_mutex_unlock (_gst_props_chunk_lock);
212 g_return_val_if_fail (props != NULL, NULL);
214 props->properties = NULL;
219 GstPropsEntry *entry;
221 if (tag < GST_PROPS_LAST_ID) {
222 g_warning ("properties seem to be wrong\n");
226 quark = g_quark_from_string ((gchar *)tag);
229 switch (GPOINTER_TO_INT (tag)) {
230 case GST_PROPS_LIST_ID_NUM:
232 GstPropsEntry *list_entry;
234 g_mutex_lock (_gst_props_entries_chunk_lock);
235 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
236 g_mutex_unlock (_gst_props_entries_chunk_lock);
238 entry->propid = quark;
239 entry->propstype = GST_PROPS_LIST_ID_NUM;
240 entry->data.list_data.entries = NULL;
242 i++; // skip list tag
245 list_entry = gst_props_create_entry (&factory[i], &skipped);
246 list_entry->propid = quark;
249 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, list_entry);
251 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
252 i++; //skip NULL (list end)
257 entry = gst_props_create_entry (&factory[i], &skipped);
258 entry->propid = quark;
263 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
276 * @entry: the property entries for the property
277 * @...: the property entries for the property
279 * Create a new property from the list of entries.
281 * Returns: the new property created from the list of entries
284 gst_props_new (GstPropsFactoryEntry entry, ...)
287 GstPropsFactoryEntry value;
290 GstPropsFactoryEntry *factory;
291 gboolean inlist = FALSE;
294 #define add_value(value) {\
295 GST_DEBUG (0,"%d %p\n", i, value);\
296 factory[i++] = value; \
299 factory = (GstPropsFactoryEntry *) g_realloc (factory, size*sizeof(GstPropsFactoryEntry));\
304 factory = (GstPropsFactoryEntry *) g_malloc (size*sizeof(GstPropsFactoryEntry));
306 va_start (var_args, entry);
308 value = (GstPropsFactoryEntry) entry;
317 value = va_arg (var_args, GstPropsFactoryEntry);
319 switch (GPOINTER_TO_INT (value)) {
320 case GST_PROPS_END_ID_NUM:
321 g_assert (inlist == TRUE);
326 case GST_PROPS_LIST_ID_NUM:
328 g_assert (inlist == FALSE);
335 skip = _arg_len[GPOINTER_TO_INT (value)];
340 value = va_arg (var_args, GstPropsFactoryEntry);
346 props = gst_props_register (factory);
353 * @props: the props to modify
354 * @name: the name of the entry to modify
355 * @entry: The new value of the property entry
356 * @...: More property entries.
358 * Modifies the value of the given entry in the props struct.
360 * Returns: the new modified property structure.
363 gst_props_set (GstProps *props, const gchar *name, GstPropsFactoryEntry entry, ...)
369 quark = g_quark_from_string (name);
371 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
374 GstPropsEntry *thisentry;
375 GstPropsFactoryEntry value;
377 thisentry = (GstPropsEntry *)lentry->data;
379 va_start (var_args, entry);
381 value = (GstPropsFactoryEntry) entry;
383 switch (GPOINTER_TO_INT (value)) {
384 case GST_PROPS_INT_ID:
385 thisentry->propstype = GST_PROPS_INT_ID_NUM;
386 value = va_arg (var_args, GstPropsFactoryEntry);
387 thisentry->data.int_data = GPOINTER_TO_INT (value);
389 case GST_PROPS_FLOAT_ID:
390 thisentry->propstype = GST_PROPS_FLOAT_ID_NUM;
391 value = va_arg (var_args, GstPropsFactoryEntry);
392 thisentry->data.float_data = *(gfloat*)value;
394 case GST_PROPS_FOURCC_ID_NUM:
395 thisentry->propstype = GST_PROPS_FOURCC_ID_NUM;
396 value = va_arg (var_args, GstPropsFactoryEntry);
397 thisentry->data.fourcc_data = GPOINTER_TO_INT (value);
399 case GST_PROPS_BOOL_ID_NUM:
400 thisentry->propstype = GST_PROPS_BOOL_ID_NUM;
401 value = va_arg (var_args, GstPropsFactoryEntry);
402 thisentry->data.bool_data = GPOINTER_TO_INT (value);
404 case GST_PROPS_STRING_ID_NUM:
405 thisentry->propstype = GST_PROPS_STRING_ID_NUM;
406 value = va_arg (var_args, GstPropsFactoryEntry);
407 thisentry->data.string_data.string = g_strdup (value);
410 g_print("gstprops: type not allowed\n");
415 g_print("gstprops: no property '%s' to change\n", name);
423 * @props: the props to unref
425 * Decrease the refcount of the property structure, destroying
426 * the property if the refcount is 0.
429 gst_props_unref (GstProps *props)
431 g_return_if_fail (props != NULL);
435 if (props->refcount == 0)
436 gst_props_destroy (props);
441 * @props: the props to ref
443 * Increase the refcount of the property structure.
446 gst_props_ref (GstProps *props)
448 g_return_if_fail (props != NULL);
455 * @props: the props to destroy
457 * Destroy the property, freeing all the memory that
461 gst_props_destroy (GstProps *props)
465 g_return_if_fail (props != NULL);
467 entries = props->properties;
470 GstPropsEntry *entry = (GstPropsEntry *)entries->data;
472 // FIXME also free the lists
473 g_mutex_lock (_gst_props_entries_chunk_lock);
474 g_mem_chunk_free (_gst_props_entries_chunk, entry);
475 g_mutex_unlock (_gst_props_entries_chunk_lock);
477 entries = g_list_next (entries);
480 g_list_free (props->properties);
485 * @props: the props to copy
487 * Copy the property structure.
489 * Returns: the new property that is a copy of the original
493 gst_props_copy (GstProps *props)
498 g_return_val_if_fail (props != NULL, NULL);
500 g_mutex_lock (_gst_props_chunk_lock);
501 new = g_mem_chunk_alloc (_gst_props_chunk);
502 g_mutex_unlock (_gst_props_chunk_lock);
504 new->properties = NULL;
506 properties = props->properties;
509 GstPropsEntry *entry = (GstPropsEntry *)properties->data;
510 GstPropsEntry *newentry;
512 g_mutex_lock (_gst_props_entries_chunk_lock);
513 newentry = g_mem_chunk_alloc (_gst_props_entries_chunk);
514 g_mutex_unlock (_gst_props_entries_chunk_lock);
516 // FIXME copy lists too
517 memcpy (newentry, entry, sizeof (GstPropsEntry));
519 new->properties = g_list_prepend (new->properties, newentry);
521 properties = g_list_next (properties);
523 new->properties = g_list_reverse (new->properties);
529 * gst_props_copy_on_write:
530 * @props: the props to copy on write
532 * Copy the property structure if the refcount is >1.
534 * Returns: A new props that can be safely written to.
537 gst_props_copy_on_write (GstProps *props)
539 GstProps *new = props;;
541 g_return_val_if_fail (props != NULL, NULL);
543 if (props->refcount > 1) {
544 new = gst_props_copy (props);
545 gst_props_unref (props);
553 * @props: the props to get the int value from
554 * @name: the name of the props entry to get.
556 * Get the named entry as an integer.
558 * Returns: the integer value of the named entry, 0 if not found.
561 gst_props_get_int (GstProps *props, const gchar *name)
566 g_return_val_if_fail (props != NULL, 0);
567 g_return_val_if_fail (name != NULL, 0);
569 quark = g_quark_from_string (name);
571 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
574 GstPropsEntry *thisentry;
576 thisentry = (GstPropsEntry *)lentry->data;
578 return thisentry->data.int_data;
585 * gst_props_get_fourcc_int:
586 * @props: the props to get the fourcc value from
587 * @name: the name of the props entry to get.
589 * Get the named entry as a gulong fourcc.
591 * Returns: the fourcc value of the named entry, 0 if not found.
594 gst_props_get_fourcc_int (GstProps *props, const gchar *name)
599 g_return_val_if_fail (props != NULL, 0);
600 g_return_val_if_fail (name != NULL, 0);
602 quark = g_quark_from_string (name);
604 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
607 GstPropsEntry *thisentry;
609 thisentry = (GstPropsEntry *)lentry->data;
611 return thisentry->data.fourcc_data;
618 * gst_props_get_boolean:
619 * @props: the props to get the fourcc value from
620 * @name: the name of the props entry to get.
622 * Get the named entry as a boolean value.
624 * Returns: the boolean value of the named entry, 0 if not found.
627 gst_props_get_boolean (GstProps *props, const gchar *name)
632 g_return_val_if_fail (props != NULL, FALSE);
633 g_return_val_if_fail (name != NULL, FALSE);
635 quark = g_quark_from_string (name);
637 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
640 GstPropsEntry *thisentry;
642 thisentry = (GstPropsEntry *)lentry->data;
644 return thisentry->data.bool_data;
651 * gst_props_get_string:
652 * @props: the props to get the fourcc value from
653 * @name: the name of the props entry to get.
655 * Get the named entry as a string value.
657 * Returns: the string value of the named entry, NULL if not found.
660 gst_props_get_string (GstProps *props, const gchar *name)
665 g_return_val_if_fail (props != NULL, NULL);
666 g_return_val_if_fail (name != NULL, NULL);
668 quark = g_quark_from_string (name);
670 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
673 GstPropsEntry *thisentry;
675 thisentry = (GstPropsEntry *)lentry->data;
677 return thisentry->data.string_data.string;
685 * @props: the property to merge into
686 * @tomerge: the property to merge
688 * Merge the properties of tomerge into props.
690 * Returns: the new merged property
693 gst_props_merge (GstProps *props, GstProps *tomerge)
697 g_return_val_if_fail (props != NULL, NULL);
698 g_return_val_if_fail (tomerge != NULL, NULL);
700 merge_props = tomerge->properties;
702 // FIXME do proper merging here...
703 while (merge_props) {
704 GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
706 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
708 merge_props = g_list_next (merge_props);
715 /* entry2 is always a list, entry1 never is */
717 gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
719 GList *entrylist = entry2->data.list_data.entries;
720 gboolean found = FALSE;
722 while (entrylist && !found) {
723 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
725 found |= gst_props_entry_check_compatibility (entry1, entry);
727 entrylist = g_list_next (entrylist);
734 gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
736 GST_DEBUG (0,"compare: %s %s\n", g_quark_to_string (entry1->propid),
737 g_quark_to_string (entry2->propid));
738 switch (entry1->propstype) {
739 case GST_PROPS_LIST_ID_NUM:
741 GList *entrylist = entry1->data.list_data.entries;
742 gboolean valid = TRUE; // innocent until proven guilty
744 while (entrylist && valid) {
745 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
747 valid &= gst_props_entry_check_compatibility (entry, entry2);
749 entrylist = g_list_next (entrylist);
754 case GST_PROPS_INT_RANGE_ID_NUM:
755 switch (entry2->propstype) {
757 case GST_PROPS_INT_RANGE_ID_NUM:
758 return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
759 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
760 case GST_PROPS_LIST_ID_NUM:
761 return gst_props_entry_check_list_compatibility (entry1, entry2);
766 case GST_PROPS_FLOAT_RANGE_ID_NUM:
767 switch (entry2->propstype) {
769 case GST_PROPS_FLOAT_RANGE_ID_NUM:
770 return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
771 entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
772 case GST_PROPS_LIST_ID_NUM:
773 return gst_props_entry_check_list_compatibility (entry1, entry2);
778 case GST_PROPS_FOURCC_ID_NUM:
779 switch (entry2->propstype) {
781 case GST_PROPS_FOURCC_ID_NUM:
782 return (entry2->data.fourcc_data == entry1->data.fourcc_data);
784 case GST_PROPS_LIST_ID_NUM:
785 return gst_props_entry_check_list_compatibility (entry1, entry2);
790 case GST_PROPS_INT_ID_NUM:
791 switch (entry2->propstype) {
793 case GST_PROPS_INT_RANGE_ID_NUM:
794 return (entry2->data.int_range_data.min <= entry1->data.int_data &&
795 entry2->data.int_range_data.max >= entry1->data.int_data);
797 case GST_PROPS_INT_ID_NUM:
798 return (entry2->data.int_data == entry1->data.int_data);
800 case GST_PROPS_LIST_ID_NUM:
801 return gst_props_entry_check_list_compatibility (entry1, entry2);
806 case GST_PROPS_FLOAT_ID_NUM:
807 switch (entry2->propstype) {
809 case GST_PROPS_FLOAT_RANGE_ID_NUM:
810 return (entry2->data.float_range_data.min <= entry1->data.float_data &&
811 entry2->data.float_range_data.max >= entry1->data.float_data);
813 case GST_PROPS_FLOAT_ID_NUM:
814 return (entry2->data.float_data == entry1->data.float_data);
816 case GST_PROPS_LIST_ID_NUM:
817 return gst_props_entry_check_list_compatibility (entry1, entry2);
822 case GST_PROPS_BOOL_ID_NUM:
823 switch (entry2->propstype) {
825 case GST_PROPS_BOOL_ID_NUM:
826 return (entry2->data.bool_data == entry1->data.bool_data);
827 case GST_PROPS_LIST_ID_NUM:
828 return gst_props_entry_check_list_compatibility (entry1, entry2);
832 case GST_PROPS_STRING_ID_NUM:
833 switch (entry2->propstype) {
835 case GST_PROPS_STRING_ID_NUM:
836 return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
837 case GST_PROPS_LIST_ID_NUM:
838 return gst_props_entry_check_list_compatibility (entry1, entry2);
850 * gst_props_check_compatibility:
851 * @fromprops: a property
852 * @toprops: a property
854 * Checks whether two capabilities are compatible.
856 * Returns: TRUE if compatible, FALSE otherwise
859 gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
865 gboolean compatible = TRUE;
867 g_return_val_if_fail (fromprops != NULL, FALSE);
868 g_return_val_if_fail (toprops != NULL, FALSE);
870 sourcelist = fromprops->properties;
871 sinklist = toprops->properties;
873 while (sourcelist && sinklist && compatible) {
874 GstPropsEntry *entry1;
875 GstPropsEntry *entry2;
877 entry1 = (GstPropsEntry *)sourcelist->data;
878 entry2 = (GstPropsEntry *)sinklist->data;
880 while (entry1->propid < entry2->propid) {
881 GST_DEBUG (0,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
883 sourcelist = g_list_next (sourcelist);
884 if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
887 while (entry1->propid > entry2->propid) {
888 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
890 sinklist = g_list_next (sinklist);
891 if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
895 if (!gst_props_entry_check_compatibility (entry1, entry2)) {
897 GST_DEBUG (0, "%s are not compatible\n:",
898 g_quark_to_string (entry1->propid));
899 gst_props_debug_entry (entry1);
900 gst_props_debug_entry (entry2);
903 sourcelist = g_list_next (sourcelist);
904 sinklist = g_list_next (sinklist);
906 if (sinklist && compatible) {
907 GstPropsEntry *entry2;
908 entry2 = (GstPropsEntry *)sinklist->data;
910 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
921 gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
926 switch (entry->propstype) {
927 case GST_PROPS_INT_ID_NUM:
928 subtree = xmlNewChild (parent, NULL, "int", NULL);
929 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
930 str = g_strdup_printf ("%d", entry->data.int_data);
931 xmlNewProp (subtree, "value", str);
934 case GST_PROPS_INT_RANGE_ID_NUM:
935 subtree = xmlNewChild (parent, NULL, "range", NULL);
936 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
937 str = g_strdup_printf ("%d", entry->data.int_range_data.min);
938 xmlNewProp (subtree, "min", str);
940 str = g_strdup_printf ("%d", entry->data.int_range_data.max);
941 xmlNewProp (subtree, "max", str);
944 case GST_PROPS_FLOAT_ID_NUM:
945 subtree = xmlNewChild (parent, NULL, "float", NULL);
946 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
947 str = g_strdup_printf ("%f", entry->data.float_data);
948 xmlNewProp (subtree, "value", str);
951 case GST_PROPS_FLOAT_RANGE_ID_NUM:
952 subtree = xmlNewChild (parent, NULL, "floatrange", NULL);
953 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
954 str = g_strdup_printf ("%f", entry->data.float_range_data.min);
955 xmlNewProp (subtree, "min", str);
957 str = g_strdup_printf ("%f", entry->data.float_range_data.max);
958 xmlNewProp (subtree, "max", str);
961 case GST_PROPS_FOURCC_ID_NUM:
962 str = g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data);
963 xmlAddChild (parent, xmlNewComment (str));
965 subtree = xmlNewChild (parent, NULL, "fourcc", NULL);
966 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
967 str = g_strdup_printf ("%08x", entry->data.fourcc_data);
968 xmlNewProp (subtree, "hexvalue", str);
971 case GST_PROPS_BOOL_ID_NUM:
972 subtree = xmlNewChild (parent, NULL, "boolean", NULL);
973 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
974 xmlNewProp (subtree, "value", (entry->data.bool_data ? "true" : "false"));
976 case GST_PROPS_STRING_ID_NUM:
977 subtree = xmlNewChild (parent, NULL, "string", NULL);
978 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
979 xmlNewProp (subtree, "value", entry->data.string_data.string);
989 * gst_props_save_thyself:
990 * @props: a property to save
991 * @parent: the parent XML tree
993 * Saves the property into an XML representation.
995 * Returns: the new XML tree
998 gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
1003 g_return_val_if_fail (props != NULL, NULL);
1005 proplist = props->properties;
1008 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
1010 switch (entry->propstype) {
1011 case GST_PROPS_LIST_ID_NUM:
1012 subtree = xmlNewChild (parent, NULL, "list", NULL);
1013 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
1014 g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
1016 gst_props_save_thyself_func (entry, parent);
1019 proplist = g_list_next (proplist);
1025 static GstPropsEntry*
1026 gst_props_load_thyself_func (xmlNodePtr field)
1028 GstPropsEntry *entry;
1031 g_mutex_lock (_gst_props_entries_chunk_lock);
1032 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1033 g_mutex_unlock (_gst_props_entries_chunk_lock);
1035 if (!strcmp(field->name, "int")) {
1036 entry->propstype = GST_PROPS_INT_ID_NUM;
1037 prop = xmlGetProp(field, "name");
1038 entry->propid = g_quark_from_string (prop);
1040 prop = xmlGetProp(field, "value");
1041 sscanf (prop, "%d", &entry->data.int_data);
1044 else if (!strcmp(field->name, "range")) {
1045 entry->propstype = GST_PROPS_INT_RANGE_ID_NUM;
1046 prop = xmlGetProp(field, "name");
1047 entry->propid = g_quark_from_string (prop);
1049 prop = xmlGetProp (field, "min");
1050 sscanf (prop, "%d", &entry->data.int_range_data.min);
1052 prop = xmlGetProp (field, "max");
1053 sscanf (prop, "%d", &entry->data.int_range_data.max);
1056 else if (!strcmp(field->name, "float")) {
1057 entry->propstype = GST_PROPS_FLOAT_ID_NUM;
1058 prop = xmlGetProp(field, "name");
1059 entry->propid = g_quark_from_string (prop);
1061 prop = xmlGetProp(field, "value");
1062 sscanf (prop, "%f", &entry->data.float_data);
1065 else if (!strcmp(field->name, "floatrange")) {
1066 entry->propstype = GST_PROPS_FLOAT_RANGE_ID_NUM;
1067 prop = xmlGetProp(field, "name");
1068 entry->propid = g_quark_from_string (prop);
1070 prop = xmlGetProp (field, "min");
1071 sscanf (prop, "%f", &entry->data.float_range_data.min);
1073 prop = xmlGetProp (field, "max");
1074 sscanf (prop, "%f", &entry->data.float_range_data.max);
1077 else if (!strcmp(field->name, "boolean")) {
1078 entry->propstype = GST_PROPS_BOOL_ID_NUM;
1079 prop = xmlGetProp(field, "name");
1080 entry->propid = g_quark_from_string (prop);
1082 prop = xmlGetProp (field, "value");
1083 if (!strcmp (prop, "false")) entry->data.bool_data = 0;
1084 else entry->data.bool_data = 1;
1087 else if (!strcmp(field->name, "fourcc")) {
1088 entry->propstype = GST_PROPS_FOURCC_ID_NUM;
1089 prop = xmlGetProp(field, "name");
1090 entry->propid = g_quark_from_string (prop);
1092 prop = xmlGetProp (field, "hexvalue");
1093 sscanf (prop, "%08x", &entry->data.fourcc_data);
1096 else if (!strcmp(field->name, "string")) {
1097 entry->propstype = GST_PROPS_STRING_ID_NUM;
1098 prop = xmlGetProp(field, "name");
1099 entry->propid = g_quark_from_string (prop);
1101 entry->data.string_data.string = xmlGetProp (field, "value");
1104 g_mutex_lock (_gst_props_entries_chunk_lock);
1105 g_mem_chunk_free (_gst_props_entries_chunk, entry);
1106 g_mutex_unlock (_gst_props_entries_chunk_lock);
1114 * gst_props_load_thyself:
1115 * @parent: the XML tree to load from
1117 * Creates a new property out of an XML tree.
1119 * Returns: the new property
1122 gst_props_load_thyself (xmlNodePtr parent)
1125 xmlNodePtr field = parent->xmlChildrenNode;
1128 g_mutex_lock (_gst_props_chunk_lock);
1129 props = g_mem_chunk_alloc (_gst_props_chunk);
1130 g_mutex_unlock (_gst_props_chunk_lock);
1132 props->properties = NULL;
1133 props->refcount = 1;
1136 if (!strcmp (field->name, "list")) {
1137 GstPropsEntry *entry;
1138 xmlNodePtr subfield = field->xmlChildrenNode;
1140 g_mutex_lock (_gst_props_entries_chunk_lock);
1141 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1142 g_mutex_unlock (_gst_props_entries_chunk_lock);
1144 entry->propstype = GST_PROPS_LIST_ID_NUM;
1145 entry->data.list_data.entries = NULL;
1146 prop = xmlGetProp (field, "name");
1147 entry->propid = g_quark_from_string (prop);
1151 GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
1154 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
1156 subfield = subfield->next;
1158 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
1159 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1162 GstPropsEntry *entry;
1164 entry = gst_props_load_thyself_func (field);
1167 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1169 field = field->next;
1175 gfloat* _gst_props_floatpointer (gfloat f)