Updated the manual and the docs.
[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
86  * and the given properties
87  *
88  * Returns: a new capability
89  */
90 GstCaps*
91 gst_caps_new_with_props (const gchar *name, const gchar *mime, GstProps *props)
92 {
93   GstCaps *caps;
94   
95   caps = gst_caps_new (name, mime);
96   caps->properties = props;
97
98   return caps;
99 }
100
101 /**
102  * gst_caps_register:
103  * @factory: the factory to register
104  *
105  * Register the factory. 
106  *
107  * Returns: The registered capability
108  */
109 GstCaps*
110 gst_caps_register (GstCapsFactory *factory)
111 {
112   guint dummy;
113
114   return gst_caps_register_count (factory, &dummy);
115 }
116
117 /**
118  * gst_caps_register_count:
119  * @factory: the factory to register
120  * @counter: count how many entries were consumed
121  *
122  * Register the factory. 
123  *
124  * Returns: The registered capability
125  */
126 GstCaps*
127 gst_caps_register_count (GstCapsFactory *factory, guint *counter)
128 {
129   GstCapsFactoryEntry tag;
130   gint i = 0;
131   guint16 typeid;
132   gchar *name;
133   GstCaps *caps;
134
135   g_return_val_if_fail (factory != NULL, NULL);
136
137   tag = (*factory)[i++];
138   g_return_val_if_fail (tag != NULL, NULL);
139
140   name = tag;
141
142   tag = (*factory)[i++];
143   g_return_val_if_fail (tag != NULL, NULL);
144   
145   typeid = get_type_for_mime ((gchar *)tag);
146
147   caps = g_new0 (GstCaps, 1);
148   g_return_val_if_fail (caps != NULL, NULL);
149
150   caps->name = g_strdup (name);
151   caps->id = typeid;
152   caps->properties = gst_props_register_count (&(*factory)[i], counter);
153
154   *counter += 2;
155
156   return caps;
157 }
158
159 /**
160  * gst_caps_get_name:
161  * @caps: the caps to get the name from
162  *
163  * get the name of a GstCaps structure
164  *
165  * Returns: The name of the caps
166  */
167 const gchar*    
168 gst_caps_get_name (GstCaps *caps)
169 {
170   g_return_val_if_fail (caps != NULL, NULL);
171
172   return (const gchar *)caps->name;
173 }
174
175 /**
176  * gst_caps_set_name:
177  * @caps: the caps to set the name to 
178  * @name: the name to set
179  *
180  * set the name of a caps
181  */
182 void
183 gst_caps_set_name (GstCaps *caps, const gchar *name)
184 {
185   g_return_if_fail (caps != NULL);
186  
187   if (caps->name)
188     g_free (caps->name);
189
190   caps->name = g_strdup (name);
191 }
192
193 /**
194  * gst_caps_get_mime:
195  * @caps: the caps to get the mime type from
196  *
197  * get the mime type of the caps as a string
198  *
199  * Returns: The mime type of the caps
200  */
201 const gchar*    
202 gst_caps_get_mime (GstCaps *caps)
203 {
204   GstType *type;
205
206   g_return_val_if_fail (caps != NULL, NULL);
207
208   type = gst_type_find_by_id (caps->id);
209
210   if (type) 
211     return type->mime;
212   else 
213     return "unknown/unknown";
214 }
215
216 /**
217  * gst_caps_set_mime:
218  * @caps: the caps to set the mime type to
219  * @mime: the mime type to attach to the caps
220  *
221  * set the mime type of the caps as a string
222  */
223 void
224 gst_caps_set_mime (GstCaps *caps, const gchar *mime)
225 {
226   g_return_if_fail (caps != NULL);
227   g_return_if_fail (mime != NULL);
228
229   caps->id = get_type_for_mime (mime);
230 }
231
232 /**
233  * gst_caps_get_type_id:
234  * @caps: the caps to get the type id from
235  *
236  * get the type id of the caps
237  *
238  * Returns: The type id of the caps
239  */
240 guint16         
241 gst_caps_get_type_id (GstCaps *caps)
242 {
243   g_return_val_if_fail (caps != NULL, 0);
244
245   return caps->id;
246 }
247
248 /**
249  * gst_caps_set_type_id:
250  * @caps: the caps to set the type id to
251  * @typeid: the type id to set 
252  *
253  * set the type id of the caps
254  */
255 void
256 gst_caps_set_type_id (GstCaps *caps, guint16 typeid)
257 {
258   g_return_if_fail (caps != NULL);
259
260   caps->id = typeid;
261 }
262
263 /**
264  * gst_caps_set_props:
265  * @caps: the caps to attach the properties to
266  * @props: the properties to attach
267  *
268  * set the properties to the given caps
269  *
270  * Returns: The new caps structure
271  */
272 GstCaps*
273 gst_caps_set_props (GstCaps *caps, GstProps *props)
274 {
275   g_return_val_if_fail (caps != NULL, caps);
276   g_return_val_if_fail (props != NULL, caps);
277   g_return_val_if_fail (caps->properties == NULL, caps);
278
279   caps->properties = props;
280   
281   return caps;
282 }
283
284 /**
285  * gst_caps_get_props:
286  * @caps: the caps to get the properties from
287  *
288  * get the properties of the given caps
289  *
290  * Returns: The properties of the caps
291  */
292 GstProps*
293 gst_caps_get_props (GstCaps *caps)
294 {
295   g_return_val_if_fail (caps != NULL, NULL);
296
297   return caps->properties;
298 }
299
300 /**
301  * gst_caps_check_compatibility:
302  * @fromcaps: a capabilty
303  * @tocaps: a capabilty
304  *
305  * Checks whether two capabilities are compatible
306  *
307  * Returns: true if compatible, false otherwise
308  */
309 gboolean
310 gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
311 {
312   g_return_val_if_fail (fromcaps != NULL, FALSE);
313   g_return_val_if_fail (tocaps != NULL, FALSE);
314         
315   if (fromcaps->id != tocaps->id) {
316     GST_DEBUG (0,"gstcaps: mime types wrong\n");
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->childs;
405
406   while (field) {
407     if (!strcmp (field->name, "name")) {
408       caps->name = g_strdup (xmlNodeGetContent (field));
409     }
410     if (!strcmp (field->name, "type")) {
411       caps->id = get_type_for_mime (xmlNodeGetContent (field));
412     }
413     else if (!strcmp (field->name, "properties")) {
414       caps->properties = gst_props_load_thyself (field);
415     }
416     field = field->next;
417   }
418
419   return caps;
420 }
421
422
423