source: trunk/third/gstreamer/gst/gstelementfactory.c @ 21448

Revision 21448, 17.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21447, which included commits to RCS files with non-trunk default branches.
RevLine 
[18713]1/* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 *                    2000 Wim Taymans <wtay@chello.be>
[21004]4 *                    2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
[18713]5 *
6 * gstelementfactory.c: GstElementFactory object, support routines
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24#include "gst_private.h"
25
26#include "gstelement.h"
[21004]27#include "gstregistrypool.h"
28#include "gstinfo.h"
29#include "gsturi.h"
[21447]30#ifndef GST_DISABLE_REGISTRY
[21004]31#include "registries/gstxmlregistry.h"  /* g_critical in gst_element_factory_create */
[21447]32#endif
[18713]33
[21004]34GST_DEBUG_CATEGORY_STATIC (element_factory_debug);
35#define GST_CAT_DEFAULT element_factory_debug
[18713]36
[21004]37static void gst_element_factory_class_init (GstElementFactoryClass * klass);
38static void gst_element_factory_init (GstElementFactory * factory);
[18713]39
[21004]40static void gst_element_factory_unload_thyself (GstPluginFeature * feature);
41
[18713]42static GstPluginFeatureClass *parent_class = NULL;
[21004]43
[18713]44/* static guint gst_element_factory_signals[LAST_SIGNAL] = { 0 }; */
45
[21004]46GType
47gst_element_factory_get_type (void)
[18713]48{
49  static GType elementfactory_type = 0;
50
51  if (!elementfactory_type) {
52    static const GTypeInfo elementfactory_info = {
53      sizeof (GstElementFactoryClass),
54      NULL,
55      NULL,
56      (GClassInitFunc) gst_element_factory_class_init,
57      NULL,
58      NULL,
[21004]59      sizeof (GstElementFactory),
[18713]60      0,
61      (GInstanceInitFunc) gst_element_factory_init,
62      NULL
63    };
[21004]64
65    elementfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
66        "GstElementFactory", &elementfactory_info, 0);
67    GST_DEBUG_CATEGORY_INIT (element_factory_debug, "GST_ELEMENT_FACTORY",
68        GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED,
69        "element factories keep information about installed elements");
[18713]70  }
71  return elementfactory_type;
72}
73static void
[21004]74gst_element_factory_class_init (GstElementFactoryClass * klass)
[18713]75{
76  GObjectClass *gobject_class;
77  GstObjectClass *gstobject_class;
78  GstPluginFeatureClass *gstpluginfeature_class;
79
[21004]80  gobject_class = (GObjectClass *) klass;
81  gstobject_class = (GstObjectClass *) klass;
82  gstpluginfeature_class = (GstPluginFeatureClass *) klass;
[18713]83
[21004]84  parent_class = g_type_class_peek_parent (klass);
[18713]85
[21004]86  gstpluginfeature_class->unload_thyself =
87      GST_DEBUG_FUNCPTR (gst_element_factory_unload_thyself);
[18713]88}
89static void
[21004]90gst_element_factory_init (GstElementFactory * factory)
[18713]91{
92  factory->padtemplates = NULL;
93  factory->numpadtemplates = 0;
[21004]94
95  factory->uri_type = GST_URI_UNKNOWN;
96  factory->uri_protocols = NULL;
97
98  factory->interfaces = NULL;
[18713]99}
100
101/**
102 * gst_element_factory_find:
103 * @name: name of factory to find
104 *
105 * Search for an element factory of the given name.
106 *
107 * Returns: #GstElementFactory if found, NULL otherwise
108 */
[21004]109GstElementFactory *
110gst_element_factory_find (const gchar * name)
[18713]111{
112  GstPluginFeature *feature;
113
[21004]114  g_return_val_if_fail (name != NULL, NULL);
[18713]115
116  feature = gst_registry_pool_find_feature (name, GST_TYPE_ELEMENT_FACTORY);
117  if (feature)
118    return GST_ELEMENT_FACTORY (feature);
119
[21004]120  /* this isn't an error, for instance when you query if an element factory is
121   * present */
122  GST_LOG ("no such element factory \"%s\"", name);
[18713]123  return NULL;
124}
125
[21004]126void
127__gst_element_details_clear (GstElementDetails * dp)
[18713]128{
129  g_free (dp->longname);
[21004]130  dp->longname = NULL;
[18713]131  g_free (dp->klass);
[21004]132  dp->klass = NULL;
[18713]133  g_free (dp->description);
[21004]134  dp->description = NULL;
[18713]135  g_free (dp->author);
[21004]136  dp->author = NULL;
[18713]137}
138
[21004]139#define VALIDATE_SET(__dest, __src, __entry)                            \
140G_STMT_START {                                                          \
141  if (g_utf8_validate (__src->__entry, -1, NULL)) {                     \
142    __dest->__entry = g_strdup (__src->__entry);                        \
143  } else {                                                              \
144    g_warning ("Invalid UTF-8 in " G_STRINGIFY (__entry) ": %s",        \
145        __src->__entry);                                                \
146    __dest->__entry = g_strdup ("[ERROR: invalid UTF-8]");              \
147  }                                                                     \
148} G_STMT_END
149
150void
151__gst_element_details_set (GstElementDetails * dest,
152    const GstElementDetails * src)
153{
154  VALIDATE_SET (dest, src, longname);
155  VALIDATE_SET (dest, src, klass);
156  VALIDATE_SET (dest, src, description);
157  VALIDATE_SET (dest, src, author);
158}
159
160void
161__gst_element_details_copy (GstElementDetails * dest,
162    const GstElementDetails * src)
163{
164  __gst_element_details_clear (dest);
165  __gst_element_details_set (dest, src);
166}
167
[18713]168static void
[21004]169gst_element_factory_cleanup (GstElementFactory * factory)
[18713]170{
[21004]171  __gst_element_details_clear (&factory->details);
172  if (factory->type) {
173    g_type_class_unref (g_type_class_peek (factory->type));
174    factory->type = 0;
[18713]175  }
176
[21004]177  g_list_foreach (factory->padtemplates, (GFunc) gst_object_unref, NULL);
178  g_list_free (factory->padtemplates);
179  factory->padtemplates = NULL;
180  factory->numpadtemplates = 0;
181  factory->uri_type = GST_URI_UNKNOWN;
182  if (factory->uri_protocols) {
183    g_strfreev (factory->uri_protocols);
184    factory->uri_protocols = NULL;
185  }
186
187  g_list_foreach (factory->interfaces, (GFunc) g_free, NULL);
188  g_list_free (factory->interfaces);
189  factory->interfaces = NULL;
[18713]190}
191
192/**
[21004]193 * gst_element_register:
194 * @plugin: #GstPlugin to register the element with
195 * @name: name of elements of this type
196 * @rank: rank of element (higher rank means more importance when autoplugging)
197 * @type: GType of element to register
[18713]198 *
[21004]199 * Create a new elementfactory capable of instantiating objects of the
[18713]200 * given type.
201 *
[21004]202 * Returns: TRUE, if the registering succeeded, FALSE on error
[18713]203 */
[21004]204gboolean
205gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
206    GType type)
[18713]207{
208  GstElementFactory *factory;
[21004]209  GType *interfaces;
210  guint n_interfaces, i;
211  GstElementClass *klass;
[18713]212
[21004]213  g_return_val_if_fail (name != NULL, FALSE);
214  g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE);
[18713]215
216  factory = gst_element_factory_find (name);
217
[21004]218  if (!factory) {
219    factory =
220        GST_ELEMENT_FACTORY (g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL));
221    gst_plugin_feature_set_name (GST_PLUGIN_FEATURE (factory), name);
222    GST_LOG_OBJECT (factory, "Created new elementfactory for type %s",
223        g_type_name (type));
224    gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
225  } else {
226    g_return_val_if_fail (factory->type == 0, FALSE);
[18713]227    gst_element_factory_cleanup (factory);
[21004]228    GST_LOG_OBJECT (factory, "Reuse existing elementfactory for type %s",
229        g_type_name (type));
[18713]230  }
231
[21004]232  klass = GST_ELEMENT_CLASS (g_type_class_ref (type));
233  factory->type = type;
234  __gst_element_details_copy (&factory->details, &klass->details);
235  factory->padtemplates = g_list_copy (klass->padtemplates);
236  g_list_foreach (factory->padtemplates, (GFunc) gst_object_ref, NULL);
237  factory->numpadtemplates = klass->numpadtemplates;
238  klass->elementfactory = factory;
[18713]239
[21004]240  /* special stuff for URI handling */
241  if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) {
242    GstURIHandlerInterface *iface = (GstURIHandlerInterface *)
243        g_type_interface_peek (klass, GST_TYPE_URI_HANDLER);
[18713]244
[21004]245    if (!iface || !iface->get_type || !iface->get_protocols)
246      goto error;
247    factory->uri_type = iface->get_type ();
248    if (!GST_URI_TYPE_IS_VALID (factory->uri_type))
249      goto error;
250    factory->uri_protocols = g_strdupv (iface->get_protocols ());
251    if (!factory->uri_protocols)
252      goto error;
253  }
[18713]254
[21004]255  interfaces = g_type_interfaces (type, &n_interfaces);
256  for (i = 0; i < n_interfaces; i++) {
257    __gst_element_factory_add_interface (factory, g_type_name (interfaces[i]));
258  }
259  g_free (interfaces);
260
261  gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
262
263  return TRUE;
264
265error:
266  gst_element_factory_cleanup (factory);
267  return FALSE;
[18713]268}
269
270/**
271 * gst_element_factory_create:
272 * @factory: factory to instantiate
273 * @name: name of new element
274 *
275 * Create a new element of the type defined by the given elementfactory.
276 * It will be given the name supplied, since all elements require a name as
277 * their first argument.
278 *
[21004]279 * Returns: new #GstElement or NULL if the element couldn't be created
[18713]280 */
[21004]281GstElement *
282gst_element_factory_create (GstElementFactory * factory, const gchar * name)
[18713]283{
284  GstElement *element;
285  GstElementClass *oclass;
286
287  g_return_val_if_fail (factory != NULL, NULL);
288
[21004]289  if (!gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
290    GST_INFO ("could not load element factory for element \"%s\"", name);
[18713]291    return NULL;
[21004]292  }
[18713]293
[21004]294  if (name)
295    GST_INFO ("creating \"%s\" named \"%s\"", GST_PLUGIN_FEATURE_NAME (factory),
296        GST_STR_NULL (name));
297  else
298    GST_INFO ("creating \"%s\"", GST_PLUGIN_FEATURE_NAME (factory));
[18713]299
300  if (factory->type == 0) {
[21447]301#ifndef GST_DISABLE_REGISTRY
[21004]302    GstPlugin *plugin = GST_PLUGIN_FEATURE (factory)->manager;
303
304    g_critical
305        ("Factory for `%s' has no type. This probably means the plugin wasn't found because the registry is broken. The plugin GStreamer was looking for is named '%s' and is expected in file '%s'. The registry for this plugin is located at '%s'",
306        GST_PLUGIN_FEATURE_NAME (factory),
307        gst_plugin_get_name (plugin), gst_plugin_get_filename (plugin),
308        GST_IS_XML_REGISTRY (plugin->manager) ? GST_XML_REGISTRY (plugin->
309            manager)->location : "Unknown");
[21447]310#else
311    g_critical ("Factory for `%s' has no type",
312        GST_PLUGIN_FEATURE_NAME (factory));
313#endif
[21004]314    return NULL;
[18713]315  }
316
[21004]317  oclass = GST_ELEMENT_CLASS (g_type_class_ref (factory->type));
318  if (oclass->elementfactory == NULL)
319    oclass->elementfactory = factory;
320
[18713]321  /* create an instance of the element */
322  element = GST_ELEMENT (g_object_new (factory->type, NULL));
323  g_assert (element != NULL);
324
[21004]325  g_type_class_unref (oclass);
[18713]326
327  gst_object_set_name (GST_OBJECT (element), name);
328
329  return element;
330}
331
332/**
333 * gst_element_factory_make:
334 * @factoryname: a named factory to instantiate
335 * @name: name of new element
336 *
337 * Create a new element of the type defined by the given element factory.
338 * If name is NULL, then the element will receive a guaranteed unique name,
339 * consisting of the element factory name and a number.
340 * If name is given, it will be given the name supplied.
341 *
[21004]342 * Returns: new #GstElement or NULL if unable to create element
[18713]343 */
[21004]344GstElement *
345gst_element_factory_make (const gchar * factoryname, const gchar * name)
[18713]346{
347  GstElementFactory *factory;
348  GstElement *element;
349
350  g_return_val_if_fail (factoryname != NULL, NULL);
351
[21004]352  GST_LOG ("gstelementfactory: make \"%s\" \"%s\"",
353      factoryname, GST_STR_NULL (name));
[18713]354
355  /* gst_plugin_load_element_factory (factoryname); */
356  factory = gst_element_factory_find (factoryname);
357  if (factory == NULL) {
[21004]358    GST_INFO ("no such element factory \"%s\"!", factoryname);
[18713]359    return NULL;
360  }
361  element = gst_element_factory_create (factory, name);
362  if (element == NULL) {
[21004]363    GST_INFO_OBJECT (factory, "couldn't create instance!");
[18713]364    return NULL;
365  }
366
367  return element;
368}
369
[21004]370void
371__gst_element_factory_add_pad_template (GstElementFactory * factory,
372    GstPadTemplate * templ)
373{
374  g_return_if_fail (factory != NULL);
375  g_return_if_fail (templ != NULL);
376
377  gst_object_ref (GST_OBJECT (templ));
378  gst_object_sink (GST_OBJECT (templ));
379
380  factory->padtemplates = g_list_append (factory->padtemplates, templ);
381  factory->numpadtemplates++;
382}
383
[18713]384/**
[21004]385 * gst_element_factory_get_element_type:
386 * @factory: factory to get managed #GType from
387 *
388 * Get the #GType for elements managed by this factory
[18713]389 *
[21004]390 * Returns: the #GType for elements managed by this factory
391 */
392GType
393gst_element_factory_get_element_type (GstElementFactory * factory)
394{
395  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), 0);
396
397  return factory->type;
398}
399
400/**
401 * gst_element_factory_get_longname:
402 * @factory: a #GstElementFactory
403 *
404 * Gets the longname for this factory
[18713]405 *
[21004]406 * Returns: the longname
[18713]407 */
[21004]408G_CONST_RETURN gchar *
409gst_element_factory_get_longname (GstElementFactory * factory)
[18713]410{
[21004]411  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
[18713]412
[21004]413  return factory->details.longname;
414}
[18713]415
[21004]416/**
417 * gst_element_factory_get_class:
418 * @factory: a #GstElementFactory
419 *
420 * Gets the class for this factory.
421 *
422 * Returns: the class
423 */
424G_CONST_RETURN gchar *
425gst_element_factory_get_klass (GstElementFactory * factory)
426{
427  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
428
429  return factory->details.klass;
[18713]430}
[21004]431
[18713]432/**
[21004]433 * gst_element_factory_get_description:
434 * @factory: a #GstElementFactory
435 *
436 * Gets the description for this factory.
[18713]437 *
[21004]438 * Returns: the description
[18713]439 */
[21004]440G_CONST_RETURN gchar *
441gst_element_factory_get_description (GstElementFactory * factory)
442{
443  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
444
445  return factory->details.description;
446}
447
448/**
449 * gst_element_factory_get_author:
450 * @factory: a #GstElementFactory
451 *
452 * Gets the author for this factory.
453 *
454 * Returns: the author
455 */
456G_CONST_RETURN gchar *
457gst_element_factory_get_author (GstElementFactory * factory)
458{
459  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
460
461  return factory->details.author;
462}
463
464/**
465 * gst_element_factory_get_num_pad_templates:
466 * @factory: a #GstElementFactory
467 *
468 * Gets the number of pad_templates in this factory.
469 *
470 * Returns: the number of pad_templates
471 */
472guint
473gst_element_factory_get_num_pad_templates (GstElementFactory * factory)
474{
475  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), 0);
476
477  return factory->numpadtemplates;
478}
479
480/**
481 * __gst_element_factory_add_interface:
482 * @elementfactory: The elementfactory to add the interface to
483 * @interfacename: Name of the interface
484 *
485 * Adds the given interfacename to the list of implemented interfaces of the
486 * element.
487 */
[18713]488void
[21004]489__gst_element_factory_add_interface (GstElementFactory * elementfactory,
490    const gchar * interfacename)
[18713]491{
[21004]492  g_return_if_fail (GST_IS_ELEMENT_FACTORY (elementfactory));
493  g_return_if_fail (interfacename != NULL);
494  g_return_if_fail (interfacename[0] != '\0');  /* no empty string */
[18713]495
[21004]496  elementfactory->interfaces =
497      g_list_prepend (elementfactory->interfaces, g_strdup (interfacename));
498}
[18713]499
[21004]500/**
501 * gst_element_factory_get_pad_templates:
502 * @factory: a #GstElementFactory
503 *
504 * Gets the #GList of padtemplates for this factory.
505 *
506 * Returns: the padtemplates
507 */
508G_CONST_RETURN GList *
509gst_element_factory_get_pad_templates (GstElementFactory * factory)
510{
511  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
[18713]512
[21004]513  return factory->padtemplates;
[18713]514}
515
516/**
[21004]517 * gst_element_factory_get_uri_type:
518 * @factory: a #GstElementFactory
519 *
520 * Gets the type of URIs the element supports or GST_URI_UNKNOWN if none.
521 *
522 * Returns: type of URIs this element supports
523 */
524guint
525gst_element_factory_get_uri_type (GstElementFactory * factory)
526{
527  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), GST_URI_UNKNOWN);
528
529  return factory->uri_type;
530}
531
532/**
533 * gst_element_factory_get_uri_protocols:
534 * @factory: a #GstElementFactory
535 *
536 * Gets a NULL-terminated array of protocols this element supports or NULL, if
537 * no protocols are supported. You may not change the contents of the returned
538 * array as it is still ownt by the element factory. Use g_strdupv() if you want to.
539 *
540 * Returns: the supported protocols or NULL
541 */
542gchar **
543gst_element_factory_get_uri_protocols (GstElementFactory * factory)
544{
545  g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
546
547  return factory->uri_protocols;
548}
549
550/**
[18713]551 * gst_element_factory_can_src_caps :
552 * @factory: factory to query
553 * @caps: the caps to check
554 *
555 * Checks if the factory can source the given capability.
556 *
557 * Returns: true if it can src the capabilities
558 */
559gboolean
[21004]560gst_element_factory_can_src_caps (GstElementFactory * factory,
561    const GstCaps * caps)
[18713]562{
563  GList *templates;
564
[21004]565  g_return_val_if_fail (factory != NULL, FALSE);
566  g_return_val_if_fail (caps != NULL, FALSE);
[18713]567
568  templates = factory->padtemplates;
569
570  while (templates) {
[21004]571    GstPadTemplate *template = (GstPadTemplate *) templates->data;
[18713]572
573    if (template->direction == GST_PAD_SRC) {
[21004]574      if (gst_caps_is_always_compatible (GST_PAD_TEMPLATE_CAPS (template),
575              caps))
576        return TRUE;
[18713]577    }
578    templates = g_list_next (templates);
579  }
580
581  return FALSE;
582}
583
584/**
585 * gst_element_factory_can_sink_caps :
586 * @factory: factory to query
587 * @caps: the caps to check
588 *
589 * Checks if the factory can sink the given capability.
590 *
591 * Returns: true if it can sink the capabilities
592 */
593gboolean
[21004]594gst_element_factory_can_sink_caps (GstElementFactory * factory,
595    const GstCaps * caps)
[18713]596{
597  GList *templates;
598
[21004]599  g_return_val_if_fail (factory != NULL, FALSE);
600  g_return_val_if_fail (caps != NULL, FALSE);
[18713]601
602  templates = factory->padtemplates;
603
604  while (templates) {
[21004]605    GstPadTemplate *template = (GstPadTemplate *) templates->data;
[18713]606
607    if (template->direction == GST_PAD_SINK) {
[21004]608      if (gst_caps_is_always_compatible (caps,
609              GST_PAD_TEMPLATE_CAPS (template)))
610        return TRUE;
[18713]611    }
612    templates = g_list_next (templates);
613  }
614
615  return FALSE;
616}
617static void
[21004]618gst_element_factory_unload_thyself (GstPluginFeature * feature)
[18713]619{
620  GstElementFactory *factory;
621
622  factory = GST_ELEMENT_FACTORY (feature);
623
[21004]624  if (factory->type) {
625    g_type_class_unref (g_type_class_peek (factory->type));
626    factory->type = 0;
627  }
[18713]628}
Note: See TracBrowser for help on using the repository browser.