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, "%s\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 quark = g_quark_from_string (name);
568 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
571 GstPropsEntry *thisentry;
573 thisentry = (GstPropsEntry *)lentry->data;
575 return thisentry->data.int_data;
582 * gst_props_get_fourcc_int:
583 * @props: the props to get the fourcc value from
584 * @name: the name of the props entry to get.
586 * Get the named entry as a gulong fourcc.
588 * Returns: the fourcc value of the named entry, 0 if not found.
591 gst_props_get_fourcc_int (GstProps *props, const gchar *name)
596 quark = g_quark_from_string (name);
598 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
601 GstPropsEntry *thisentry;
603 thisentry = (GstPropsEntry *)lentry->data;
605 return thisentry->data.fourcc_data;
612 * gst_props_get_boolean:
613 * @props: the props to get the fourcc value from
614 * @name: the name of the props entry to get.
616 * Get the named entry as a boolean value.
618 * Returns: the boolean value of the named entry, 0 if not found.
621 gst_props_get_boolean (GstProps *props, const gchar *name)
626 quark = g_quark_from_string (name);
628 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
631 GstPropsEntry *thisentry;
633 thisentry = (GstPropsEntry *)lentry->data;
635 return thisentry->data.bool_data;
642 * gst_props_get_string:
643 * @props: the props to get the fourcc value from
644 * @name: the name of the props entry to get.
646 * Get the named entry as a string value.
648 * Returns: the string value of the named entry, NULL if not found.
651 gst_props_get_string (GstProps *props, const gchar *name)
656 quark = g_quark_from_string (name);
658 lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
661 GstPropsEntry *thisentry;
663 thisentry = (GstPropsEntry *)lentry->data;
665 return thisentry->data.string_data.string;
673 * @props: the property to merge into
674 * @tomerge: the property to merge
676 * Merge the properties of tomerge into props.
678 * Returns: the new merged property
681 gst_props_merge (GstProps *props, GstProps *tomerge)
685 g_return_val_if_fail (props != NULL, NULL);
686 g_return_val_if_fail (tomerge != NULL, NULL);
688 merge_props = tomerge->properties;
690 // FIXME do proper merging here...
691 while (merge_props) {
692 GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
694 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
696 merge_props = g_list_next (merge_props);
703 /* entry2 is always a list, entry1 never is */
705 gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
707 GList *entrylist = entry2->data.list_data.entries;
708 gboolean found = FALSE;
710 while (entrylist && !found) {
711 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
713 found |= gst_props_entry_check_compatibility (entry1, entry);
715 entrylist = g_list_next (entrylist);
722 gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
724 GST_DEBUG (0,"compare: %s %s\n", g_quark_to_string (entry1->propid),
725 g_quark_to_string (entry2->propid));
726 switch (entry1->propstype) {
727 case GST_PROPS_LIST_ID_NUM:
729 GList *entrylist = entry1->data.list_data.entries;
730 gboolean valid = TRUE; // innocent until proven guilty
732 while (entrylist && valid) {
733 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
735 valid &= gst_props_entry_check_compatibility (entry, entry2);
737 entrylist = g_list_next (entrylist);
742 case GST_PROPS_INT_RANGE_ID_NUM:
743 switch (entry2->propstype) {
745 case GST_PROPS_INT_RANGE_ID_NUM:
746 return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
747 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
748 case GST_PROPS_LIST_ID_NUM:
749 return gst_props_entry_check_list_compatibility (entry1, entry2);
754 case GST_PROPS_FLOAT_RANGE_ID_NUM:
755 switch (entry2->propstype) {
757 case GST_PROPS_FLOAT_RANGE_ID_NUM:
758 return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
759 entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
760 case GST_PROPS_LIST_ID_NUM:
761 return gst_props_entry_check_list_compatibility (entry1, entry2);
766 case GST_PROPS_FOURCC_ID_NUM:
767 switch (entry2->propstype) {
769 case GST_PROPS_FOURCC_ID_NUM:
770 return (entry2->data.fourcc_data == entry1->data.fourcc_data);
772 case GST_PROPS_LIST_ID_NUM:
773 return gst_props_entry_check_list_compatibility (entry1, entry2);
778 case GST_PROPS_INT_ID_NUM:
779 switch (entry2->propstype) {
781 case GST_PROPS_INT_RANGE_ID_NUM:
782 return (entry2->data.int_range_data.min <= entry1->data.int_data &&
783 entry2->data.int_range_data.max >= entry1->data.int_data);
785 case GST_PROPS_INT_ID_NUM:
786 return (entry2->data.int_data == entry1->data.int_data);
788 case GST_PROPS_LIST_ID_NUM:
789 return gst_props_entry_check_list_compatibility (entry1, entry2);
794 case GST_PROPS_FLOAT_ID_NUM:
795 switch (entry2->propstype) {
797 case GST_PROPS_FLOAT_RANGE_ID_NUM:
798 return (entry2->data.float_range_data.min <= entry1->data.float_data &&
799 entry2->data.float_range_data.max >= entry1->data.float_data);
801 case GST_PROPS_FLOAT_ID_NUM:
802 return (entry2->data.float_data == entry1->data.float_data);
804 case GST_PROPS_LIST_ID_NUM:
805 return gst_props_entry_check_list_compatibility (entry1, entry2);
810 case GST_PROPS_BOOL_ID_NUM:
811 switch (entry2->propstype) {
813 case GST_PROPS_BOOL_ID_NUM:
814 return (entry2->data.bool_data == entry1->data.bool_data);
815 case GST_PROPS_LIST_ID_NUM:
816 return gst_props_entry_check_list_compatibility (entry1, entry2);
820 case GST_PROPS_STRING_ID_NUM:
821 switch (entry2->propstype) {
823 case GST_PROPS_STRING_ID_NUM:
824 return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
825 case GST_PROPS_LIST_ID_NUM:
826 return gst_props_entry_check_list_compatibility (entry1, entry2);
838 * gst_props_check_compatibility:
839 * @fromprops: a property
840 * @toprops: a property
842 * Checks whether two capabilities are compatible.
844 * Returns: TRUE if compatible, FALSE otherwise
847 gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
853 gboolean compatible = TRUE;
855 g_return_val_if_fail (fromprops != NULL, FALSE);
856 g_return_val_if_fail (toprops != NULL, FALSE);
858 sourcelist = fromprops->properties;
859 sinklist = toprops->properties;
861 while (sourcelist && sinklist && compatible) {
862 GstPropsEntry *entry1;
863 GstPropsEntry *entry2;
865 entry1 = (GstPropsEntry *)sourcelist->data;
866 entry2 = (GstPropsEntry *)sinklist->data;
868 while (entry1->propid < entry2->propid) {
869 GST_DEBUG (0,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
871 sourcelist = g_list_next (sourcelist);
872 if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
875 while (entry1->propid > entry2->propid) {
876 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
878 sinklist = g_list_next (sinklist);
879 if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
883 if (!gst_props_entry_check_compatibility (entry1, entry2)) {
885 GST_DEBUG (0, "%s are not compatible\n:",
886 g_quark_to_string (entry1->propid));
887 gst_props_debug_entry (entry1);
888 gst_props_debug_entry (entry2);
892 sourcelist = g_list_next (sourcelist);
893 sinklist = g_list_next (sinklist);
895 if (sinklist && compatible) {
896 GstPropsEntry *entry2;
897 entry2 = (GstPropsEntry *)sinklist->data;
899 GST_DEBUG (0,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
910 gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
915 switch (entry->propstype) {
916 case GST_PROPS_INT_ID_NUM:
917 subtree = xmlNewChild (parent, NULL, "int", NULL);
918 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
919 str = g_strdup_printf ("%d", entry->data.int_data);
920 xmlNewProp (subtree, "value", str);
923 case GST_PROPS_INT_RANGE_ID_NUM:
924 subtree = xmlNewChild (parent, NULL, "range", NULL);
925 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
926 str = g_strdup_printf ("%d", entry->data.int_range_data.min);
927 xmlNewProp (subtree, "min", str);
929 str = g_strdup_printf ("%d", entry->data.int_range_data.max);
930 xmlNewProp (subtree, "max", str);
933 case GST_PROPS_FLOAT_ID_NUM:
934 subtree = xmlNewChild (parent, NULL, "float", NULL);
935 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
936 str = g_strdup_printf ("%f", entry->data.float_data);
937 xmlNewProp (subtree, "value", str);
940 case GST_PROPS_FLOAT_RANGE_ID_NUM:
941 subtree = xmlNewChild (parent, NULL, "floatrange", NULL);
942 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
943 str = g_strdup_printf ("%f", entry->data.float_range_data.min);
944 xmlNewProp (subtree, "min", str);
946 str = g_strdup_printf ("%f", entry->data.float_range_data.max);
947 xmlNewProp (subtree, "max", str);
950 case GST_PROPS_FOURCC_ID_NUM:
951 str = g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data);
952 xmlAddChild (parent, xmlNewComment (str));
954 subtree = xmlNewChild (parent, NULL, "fourcc", NULL);
955 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
956 str = g_strdup_printf ("%08x", entry->data.fourcc_data);
957 xmlNewProp (subtree, "hexvalue", str);
960 case GST_PROPS_BOOL_ID_NUM:
961 subtree = xmlNewChild (parent, NULL, "boolean", NULL);
962 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
963 xmlNewProp (subtree, "value", (entry->data.bool_data ? "true" : "false"));
965 case GST_PROPS_STRING_ID_NUM:
966 subtree = xmlNewChild (parent, NULL, "string", NULL);
967 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
968 xmlNewProp (subtree, "value", entry->data.string_data.string);
978 * gst_props_save_thyself:
979 * @props: a property to save
980 * @parent: the parent XML tree
982 * Saves the property into an XML representation.
984 * Returns: the new XML tree
987 gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
992 g_return_val_if_fail (props != NULL, NULL);
994 proplist = props->properties;
997 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
999 switch (entry->propstype) {
1000 case GST_PROPS_LIST_ID_NUM:
1001 subtree = xmlNewChild (parent, NULL, "list", NULL);
1002 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
1003 g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
1005 gst_props_save_thyself_func (entry, parent);
1008 proplist = g_list_next (proplist);
1014 static GstPropsEntry*
1015 gst_props_load_thyself_func (xmlNodePtr field)
1017 GstPropsEntry *entry;
1020 g_mutex_lock (_gst_props_entries_chunk_lock);
1021 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1022 g_mutex_unlock (_gst_props_entries_chunk_lock);
1024 if (!strcmp(field->name, "int")) {
1025 entry->propstype = GST_PROPS_INT_ID_NUM;
1026 prop = xmlGetProp(field, "name");
1027 entry->propid = g_quark_from_string (prop);
1029 prop = xmlGetProp(field, "value");
1030 sscanf (prop, "%d", &entry->data.int_data);
1033 else if (!strcmp(field->name, "range")) {
1034 entry->propstype = GST_PROPS_INT_RANGE_ID_NUM;
1035 prop = xmlGetProp(field, "name");
1036 entry->propid = g_quark_from_string (prop);
1038 prop = xmlGetProp (field, "min");
1039 sscanf (prop, "%d", &entry->data.int_range_data.min);
1041 prop = xmlGetProp (field, "max");
1042 sscanf (prop, "%d", &entry->data.int_range_data.max);
1045 else if (!strcmp(field->name, "float")) {
1046 entry->propstype = GST_PROPS_FLOAT_ID_NUM;
1047 prop = xmlGetProp(field, "name");
1048 entry->propid = g_quark_from_string (prop);
1050 prop = xmlGetProp(field, "value");
1051 sscanf (prop, "%f", &entry->data.float_data);
1054 else if (!strcmp(field->name, "floatrange")) {
1055 entry->propstype = GST_PROPS_FLOAT_RANGE_ID_NUM;
1056 prop = xmlGetProp(field, "name");
1057 entry->propid = g_quark_from_string (prop);
1059 prop = xmlGetProp (field, "min");
1060 sscanf (prop, "%f", &entry->data.float_range_data.min);
1062 prop = xmlGetProp (field, "max");
1063 sscanf (prop, "%f", &entry->data.float_range_data.max);
1066 else if (!strcmp(field->name, "boolean")) {
1067 entry->propstype = GST_PROPS_BOOL_ID_NUM;
1068 prop = xmlGetProp(field, "name");
1069 entry->propid = g_quark_from_string (prop);
1071 prop = xmlGetProp (field, "value");
1072 if (!strcmp (prop, "false")) entry->data.bool_data = 0;
1073 else entry->data.bool_data = 1;
1076 else if (!strcmp(field->name, "fourcc")) {
1077 entry->propstype = GST_PROPS_FOURCC_ID_NUM;
1078 prop = xmlGetProp(field, "name");
1079 entry->propid = g_quark_from_string (prop);
1081 prop = xmlGetProp (field, "hexvalue");
1082 sscanf (prop, "%08x", &entry->data.fourcc_data);
1085 else if (!strcmp(field->name, "string")) {
1086 entry->propstype = GST_PROPS_STRING_ID_NUM;
1087 prop = xmlGetProp(field, "name");
1088 entry->propid = g_quark_from_string (prop);
1090 entry->data.string_data.string = xmlGetProp (field, "value");
1093 g_mutex_lock (_gst_props_entries_chunk_lock);
1094 g_mem_chunk_free (_gst_props_entries_chunk, entry);
1095 g_mutex_unlock (_gst_props_entries_chunk_lock);
1103 * gst_props_load_thyself:
1104 * @parent: the XML tree to load from
1106 * Creates a new property out of an XML tree.
1108 * Returns: the new property
1111 gst_props_load_thyself (xmlNodePtr parent)
1114 xmlNodePtr field = parent->xmlChildrenNode;
1117 g_mutex_lock (_gst_props_chunk_lock);
1118 props = g_mem_chunk_alloc (_gst_props_chunk);
1119 g_mutex_unlock (_gst_props_chunk_lock);
1121 props->properties = NULL;
1122 props->refcount = 1;
1125 if (!strcmp (field->name, "list")) {
1126 GstPropsEntry *entry;
1127 xmlNodePtr subfield = field->xmlChildrenNode;
1129 g_mutex_lock (_gst_props_entries_chunk_lock);
1130 entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
1131 g_mutex_unlock (_gst_props_entries_chunk_lock);
1133 entry->propstype = GST_PROPS_LIST_ID_NUM;
1134 entry->data.list_data.entries = NULL;
1135 prop = xmlGetProp (field, "name");
1136 entry->propid = g_quark_from_string (prop);
1140 GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
1143 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, subentry);
1145 subfield = subfield->next;
1147 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
1148 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1151 GstPropsEntry *entry;
1153 entry = gst_props_load_thyself_func (field);
1156 props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
1158 field = field->next;
1164 gfloat* _gst_props_floatpointer (gfloat f)