2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 //#define DEBUG_ENABLED
24 #include "gstpropsprivate.h"
26 static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
30 _gst_props_initialize (void)
34 static GstPropsEntry *
35 gst_props_create_entry (GstPropsFactory factory, gint *skipped)
37 GstPropsFactoryEntry tag;
41 entry = g_new0 (GstPropsEntry, 1);
44 switch (GPOINTER_TO_INT (tag)) {
45 case GST_PROPS_INT_ID:
46 entry->propstype = GST_PROPS_INT_ID_NUM;
47 entry->data.int_data = GPOINTER_TO_INT (factory[i++]);
49 case GST_PROPS_INT_RANGE_ID:
50 entry->propstype = GST_PROPS_INT_RANGE_ID_NUM;
51 entry->data.int_range_data.min = GPOINTER_TO_INT (factory[i++]);
52 entry->data.int_range_data.max = GPOINTER_TO_INT (factory[i++]);
54 case GST_PROPS_FOURCC_ID:
55 entry->propstype = GST_PROPS_FOURCC_ID_NUM;
56 entry->data.fourcc_data = GPOINTER_TO_INT (factory[i++]);
58 case GST_PROPS_LIST_ID:
59 g_print("gstprops: list not allowed in list\n");
61 case GST_PROPS_BOOL_ID:
62 entry->propstype = GST_PROPS_BOOL_ID_NUM;
63 entry->data.bool_data = GPOINTER_TO_INT (factory[i++]);
66 g_print("gstprops: unknown props id found\n");
79 props_compare_func (gconstpointer a,
82 GstPropsEntry *entry1 = (GstPropsEntry *)a;
83 GstPropsEntry *entry2 = (GstPropsEntry *)b;
85 return (entry1->propid - entry2->propid);
90 * @factory: the factory to register
92 * Register the factory.
94 * Returns: The registered capability
97 gst_props_register (GstPropsFactory factory)
99 GstPropsFactoryEntry tag;
104 g_return_val_if_fail (factory != NULL, NULL);
106 props = g_new0 (GstProps, 1);
107 g_return_val_if_fail (props != NULL, NULL);
109 props->properties = NULL;
115 GstPropsEntry *entry;
117 quark = g_quark_from_string ((gchar *)tag);
120 switch (GPOINTER_TO_INT (tag)) {
121 case GST_PROPS_LIST_ID:
123 GstPropsEntry *list_entry;
125 entry = g_new0 (GstPropsEntry, 1);
126 entry->propid = quark;
127 entry->propstype = GST_PROPS_LIST_ID_NUM;
128 entry->data.list_data.entries = NULL;
130 i++; // skip list tag
133 list_entry = gst_props_create_entry (&factory[i], &skipped);
134 list_entry->propid = quark;
137 entry->data.list_data.entries = g_list_prepend (entry->data.list_data.entries, list_entry);
139 entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
140 i++; //skip NULL (list end)
145 entry = gst_props_create_entry (&factory[i], &skipped);
146 entry->propid = quark;
151 props->properties = g_slist_insert_sorted (props->properties, entry, props_compare_func);
159 /* entry2 is always a list, entry1 never is */
161 gst_props_entry_check_list_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
163 GList *entrylist = entry2->data.list_data.entries;
164 gboolean found = FALSE;
166 while (entrylist && !found) {
167 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
169 found |= gst_props_entry_check_compatibility (entry1, entry);
171 entrylist = g_list_next (entrylist);
178 gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2)
180 DEBUG ("compare: %s %s\n", g_quark_to_string (entry1->propid),
181 g_quark_to_string (entry2->propid));
182 switch (entry1->propstype) {
183 case GST_PROPS_LIST_ID_NUM:
185 GList *entrylist = entry1->data.list_data.entries;
186 gboolean valid = TRUE; // innocent until proven guilty
188 while (entrylist && valid) {
189 GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
191 valid &= gst_props_entry_check_compatibility (entry, entry2);
193 entrylist = g_list_next (entrylist);
198 case GST_PROPS_INT_RANGE_ID_NUM:
199 switch (entry2->propstype) {
201 case GST_PROPS_INT_RANGE_ID_NUM:
202 return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
203 entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
204 case GST_PROPS_LIST_ID_NUM:
205 return gst_props_entry_check_list_compatibility (entry1, entry2);
210 case GST_PROPS_FOURCC_ID_NUM:
211 switch (entry2->propstype) {
213 case GST_PROPS_FOURCC_ID_NUM:
214 return (entry2->data.fourcc_data == entry1->data.fourcc_data);
216 case GST_PROPS_LIST_ID_NUM:
217 return gst_props_entry_check_list_compatibility (entry1, entry2);
222 case GST_PROPS_INT_ID_NUM:
223 switch (entry2->propstype) {
225 case GST_PROPS_INT_RANGE_ID_NUM:
226 return (entry2->data.int_range_data.min <= entry1->data.int_data &&
227 entry2->data.int_range_data.max >= entry1->data.int_data);
229 case GST_PROPS_INT_ID_NUM:
230 return (entry2->data.int_data == entry1->data.int_data);
232 case GST_PROPS_LIST_ID_NUM:
233 return gst_props_entry_check_list_compatibility (entry1, entry2);
238 case GST_PROPS_BOOL_ID_NUM:
239 switch (entry2->propstype) {
241 case GST_PROPS_BOOL_ID_NUM:
242 return (entry2->data.bool_data == entry1->data.bool_data);
243 case GST_PROPS_LIST_ID_NUM:
244 return gst_props_entry_check_list_compatibility (entry1, entry2);
256 * gst_props_check_compatibility:
257 * @fromprops: a capabilty
258 * @toprops: a capabilty
260 * Checks whether two capabilities are compatible
262 * Returns: true if compatible, false otherwise
265 gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
271 gboolean compatible = TRUE;
273 g_return_val_if_fail (fromprops != NULL, FALSE);
274 g_return_val_if_fail (toprops != NULL, FALSE);
276 sourcelist = fromprops->properties;
277 sinklist = toprops->properties;
279 while (sourcelist && sinklist && compatible) {
280 GstPropsEntry *entry1;
281 GstPropsEntry *entry2;
283 entry1 = (GstPropsEntry *)sourcelist->data;
284 entry2 = (GstPropsEntry *)sinklist->data;
286 while (entry1->propid < entry2->propid) {
287 DEBUG ("source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
289 sourcelist = g_slist_next (sourcelist);
290 if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
293 while (entry1->propid > entry2->propid) {
294 DEBUG ("source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
296 sinklist = g_slist_next (sinklist);
297 if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
301 compatible &= gst_props_entry_check_compatibility (entry1, entry2);
303 sourcelist = g_slist_next (sourcelist);
304 sinklist = g_slist_next (sinklist);
315 gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
319 switch (entry->propstype) {
320 case GST_PROPS_INT_ID_NUM:
321 subtree = xmlNewChild (parent, NULL, "int", NULL);
322 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
323 xmlNewProp (subtree, "value", g_strdup_printf ("%d", entry->data.int_data));
325 case GST_PROPS_INT_RANGE_ID_NUM:
326 subtree = xmlNewChild (parent, NULL, "range", NULL);
327 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
328 xmlNewProp (subtree, "min", g_strdup_printf ("%d", entry->data.int_range_data.min));
329 xmlNewProp (subtree, "max", g_strdup_printf ("%d", entry->data.int_range_data.max));
331 case GST_PROPS_FOURCC_ID_NUM:
332 xmlAddChild (parent, xmlNewComment (g_strdup_printf ("%4.4s", (gchar *)&entry->data.fourcc_data)));
333 subtree = xmlNewChild (parent, NULL, "fourcc", NULL);
334 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
335 xmlNewProp (subtree, "hexvalue", g_strdup_printf ("%08x", entry->data.fourcc_data));
337 case GST_PROPS_BOOL_ID_NUM:
338 subtree = xmlNewChild (parent, NULL, "boolean", NULL);
339 xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
340 xmlNewProp (subtree, "value", (entry->data.bool_data ? "true" : "false"));
350 gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
355 g_return_val_if_fail (props != NULL, NULL);
357 proplist = props->properties;
360 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
362 switch (entry->propstype) {
363 case GST_PROPS_LIST_ID_NUM:
364 subtree = xmlNewChild (parent, NULL, "list", NULL);
365 g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
367 gst_props_save_thyself_func (entry, parent);
370 proplist = g_slist_next (proplist);
377 gst_props_load_thyself (xmlNodePtr parent)