Fixes to work with libxml2.
[platform/upstream/gstreamer.git] / gst / gstcaps.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstcaps.c: Element capabilities subsystem
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 //#define GST_DEBUG_ENABLED
24 #include "gst_private.h"
25
26 #include "gstcaps.h"
27 #include "gsttype.h"
28
29 #include "gstpropsprivate.h"
30
31
32 void 
33 _gst_caps_initialize (void) 
34 {
35 }
36
37 static guint16
38 get_type_for_mime (const gchar *mime)
39 {
40   guint16 typeid;
41
42   typeid = gst_type_find_by_mime (mime);
43   if (typeid == 0) {
44      GstTypeFactory factory; // = g_new0 (GstTypeFactory, 1);
45
46      factory.mime = g_strdup (mime);
47      factory.exts = NULL;
48      factory.typefindfunc = NULL;
49
50      typeid = gst_type_register (&factory);
51   }
52   return typeid;
53 }
54
55 /**
56  * gst_caps_new:
57  * @name: the name of this capability
58  * @mime: the mime type to attach to the capability
59  *
60  * Create a new capability with the given mime type.
61  *
62  * Returns: a new capability
63  */
64 GstCaps*
65 gst_caps_new (const gchar *name, const gchar *mime)
66 {
67   GstCaps *caps;
68
69   g_return_val_if_fail (mime != NULL, NULL);
70   
71   caps = g_new0 (GstCaps, 1);
72   caps->name = g_strdup (name);
73   caps->id = get_type_for_mime (mime);
74   caps->properties = NULL;
75   
76   return caps;
77 }
78
79 /**
80  * gst_caps_new_with_props:
81  * @name: the name of this capability
82  * @mime: the mime type to attach to the capability
83  * @props: the properties for this capability
84  *
85  * Create a new capability with the given mime type and the given properties.
86  *
87  * Returns: a new capability
88  */
89 GstCaps*
90 gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
91 {
92   GstCaps *caps;
93   
94   caps = gst_caps_new (name, mime);
95   caps->properties = props;
96
97   return caps;
98 }
99
100 /**
101  * gst_caps_register:
102  * @factory: the factory to register
103  *
104  * Register the factory. 
105  *
106  * Returns: the registered capability
107  */
108 GstCaps*
109 gst_caps_register (GstCapsFactory *factory)
110 {
111   guint dummy;
112
113   return gst_caps_register_count (factory, &dummy);
114 }
115
116 /**
117  * gst_caps_register_count:
118  * @factory: the factory to register
119  * @counter: count how many entries were consumed
120  *
121  * Register the factory.
122  *
123  * Returns: the registered capability
124  */
125 GstCaps*
126 gst_caps_register_count (GstCapsFactory *factory, guint *counter)
127 {
128   GstCapsFactoryEntry tag;
129   gint i = 0;
130   guint16 typeid;
131   gchar *name;
132   GstCaps *caps;
133
134   g_return_val_if_fail (factory != NULL, NULL);
135
136   tag = (*factory)[i++];
137   g_return_val_if_fail (tag != NULL, NULL);
138
139   name = tag;
140
141   tag = (*factory)[i++];
142   g_return_val_if_fail (tag != NULL, NULL);
143   
144   typeid = get_type_for_mime ((gchar *)tag);
145
146   caps = g_new0 (GstCaps, 1);
147   g_return_val_if_fail (caps != NULL, NULL);
148
149   caps->name = g_strdup (name);
150   caps->id = typeid;
151   caps->properties = gst_props_register_count (&(*factory)[i], counter);
152
153   *counter += 2;
154
155   return caps;
156 }
157
158 /**
159  * gst_caps_get_name:
160  * @caps: the caps to get the name from
161  *
162  * Get the name of a GstCaps structure.
163  *
164  * Returns: the name of the caps
165  */
166 const gchar*    
167 gst_caps_get_name (GstCaps *caps)
168 {
169   g_return_val_if_fail (caps != NULL, NULL);
170
171   return (const gchar *)caps->name;
172 }
173
174 /**
175  * gst_caps_set_name:
176  * @caps: the caps to set the name to 
177  * @name: the name to set
178  *
179  * Set the name of a caps.
180  */
181 void
182 gst_caps_set_name (GstCaps *caps, const gchar *name)
183 {
184   g_return_if_fail (caps != NULL);
185  
186   if (caps->name)
187     g_free (caps->name);
188
189   caps->name = g_strdup (name);
190 }
191
192 /**
193  * gst_caps_get_mime:
194  * @caps: the caps to get the mime type from
195  *
196  * Get the mime type of the caps as a string.
197  *
198  * Returns: the mime type of the caps
199  */
200 const gchar*    
201 gst_caps_get_mime (GstCaps *caps)
202 {
203   GstType *type;
204
205   g_return_val_if_fail (caps != NULL, NULL);
206
207   type = gst_type_find_by_id (caps->id);
208
209   if (type) 
210     return type->mime;
211   else 
212     return "unknown/unknown";
213 }
214
215 /**
216  * gst_caps_set_mime:
217  * @caps: the caps to set the mime type to
218  * @mime: the mime type to attach to the caps
219  *
220  * Set the mime type of the caps as a string.
221  */
222 void
223 gst_caps_set_mime (GstCaps *caps, const gchar *mime)
224 {
225   g_return_if_fail (caps != NULL);
226   g_return_if_fail (mime != NULL);
227
228   caps->id = get_type_for_mime (mime);
229 }
230
231 /**
232  * gst_caps_get_type_id:
233  * @caps: the caps to get the type id from
234  *
235  * Get the type id of the caps.
236  *
237  * Returns: the type id of the caps
238  */
239 guint16         
240 gst_caps_get_type_id (GstCaps *caps)
241 {
242   g_return_val_if_fail (caps != NULL, 0);
243
244   return caps->id;
245 }
246
247 /**
248  * gst_caps_set_type_id:
249  * @caps: the caps to set the type id to
250  * @typeid: the type id to set 
251  *
252  * Set the type id of the caps.
253  */
254 void
255 gst_caps_set_type_id (GstCaps *caps, guint16 typeid)
256 {
257   g_return_if_fail (caps != NULL);
258
259   caps->id = typeid;
260 }
261
262 /**
263  * gst_caps_set_props:
264  * @caps: the caps to attach the properties to
265  * @props: the properties to attach
266  *
267  * Set the properties to the given caps.
268  *
269  * Returns: the new caps structure
270  */
271 GstCaps*
272 gst_caps_set_props (GstCaps *caps, GstProps *props)
273 {
274   g_return_val_if_fail (caps != NULL, caps);
275   g_return_val_if_fail (props != NULL, caps);
276   g_return_val_if_fail (caps->properties == NULL, caps);
277
278   caps->properties = props;
279   
280   return caps;
281 }
282
283 /**
284  * gst_caps_get_props:
285  * @caps: the caps to get the properties from
286  *
287  * Get the properties of the given caps.
288  *
289  * Returns: the properties of the caps
290  */
291 GstProps*
292 gst_caps_get_props (GstCaps *caps)
293 {
294   g_return_val_if_fail (caps != NULL, NULL);
295
296   return caps->properties;
297 }
298
299 /**
300  * gst_caps_check_compatibility:
301  * @fromcaps: a capabilty
302  * @tocaps: a capabilty
303  *
304  * Checks whether two capabilities are compatible.
305  *
306  * Returns: TRUE if compatible, FALSE otherwise
307  */
308 gboolean
309 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
310 {
311   g_return_val_if_fail (fromcaps != NULL, FALSE);
312   g_return_val_if_fail (tocaps != NULL, FALSE);
313         
314   if (fromcaps->id != tocaps->id) {
315     GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n",
316                fromcaps->id, tocaps->id);
317     return FALSE;
318   }
319
320   if (tocaps->properties) {
321     if (fromcaps->properties) {
322       return gst_props_check_compatibility (fromcaps->properties, tocaps->properties);
323     }
324     else {
325       GST_DEBUG (0,"gstcaps: no source caps\n");
326       return FALSE;
327     }
328   }
329   else {
330     // assume it accepts everything
331     GST_DEBUG (0,"gstcaps: no caps\n");
332     return TRUE;
333   }
334 }
335
336 /**
337  * gst_caps_list_check_compatibility:
338  * @fromcaps: a capabilty
339  * @tocaps: a capabilty
340  *
341  * Checks whether two capability lists are compatible.
342  *
343  * Returns: TRUE if compatible, FALSE otherwise
344  */
345 gboolean
346 gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps)
347 {
348   while (fromcaps) {
349     GstCaps *fromcap = (GstCaps *)fromcaps->data;
350     GList *destcaps = tocaps;
351
352     while (destcaps) {
353       GstCaps *destcap = (GstCaps *)destcaps->data;
354
355       if (gst_caps_check_compatibility (fromcap, destcap))
356         return TRUE;
357
358       destcaps = g_list_next (destcaps);
359     }
360     fromcaps = g_list_next (fromcaps);
361   }
362   return FALSE;
363 }
364
365 /**
366  * gst_caps_save_thyself:
367  * @caps: a capabilty to save
368  * @parent: the parent XML node pointer
369  *
370  * Save the capability into an XML representation.
371  *
372  * Returns: a new XML node pointer
373  */
374 xmlNodePtr      
375 gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
376 {
377   xmlNodePtr subtree;
378
379   g_return_val_if_fail (caps != NULL, NULL);
380
381   xmlNewChild (parent, NULL, "name", caps->name);
382   xmlNewChild (parent, NULL, "type", gst_type_find_by_id (caps->id)->mime);
383   if (caps->properties) {
384     subtree = xmlNewChild (parent, NULL, "properties", NULL);
385
386     gst_props_save_thyself (caps->properties, subtree);
387   }
388
389   return parent;
390 }
391
392 /**
393  * gst_caps_load_thyself:
394  * @parent: the parent XML node pointer
395  *
396  * Load a new caps from the XML representation.
397  *
398  * Returns: a new capability
399  */
400 GstCaps*        
401 gst_caps_load_thyself (xmlNodePtr parent)
402 {
403   GstCaps *caps = g_new0 (GstCaps, 1);
404   xmlNodePtr field = parent->xmlChildrenNode;
405   gchar *content;
406
407   while (field) {
408     if (!strcmp (field->name, "name")) {
409       caps->name = xmlNodeGetContent (field);
410     }
411     if (!strcmp (field->name, "type")) {
412       content = xmlNodeGetContent (field);
413       caps->id = get_type_for_mime (content);
414       g_free (content);
415     }
416     else if (!strcmp (field->name, "properties")) {
417       caps->properties = gst_props_load_thyself (field);
418     }
419     field = field->next;
420   }
421
422   return caps;
423 }
424
425
426