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

Revision 21448, 22.8 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.
Line 
1/* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 *                    2000 Wim Taymans <wtay@chello.be>
4 *
5 * gstplugin.c: Plugin subsystem for loading elements, types, and libs
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#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26#include <sys/types.h>
27#include <sys/stat.h>
28#ifdef HAVE_DIRENT_H
29#include <dirent.h>
30#endif
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34#include <signal.h>
35#include <errno.h>
36
37#include "gst_private.h"
38
39#include "gstplugin.h"
40#include "gstversion.h"
41#include "gstregistrypool.h"
42#include "gstinfo.h"
43#include "gstfilter.h"
44
45
46#define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING
47
48static GModule *main_module = NULL;
49static GList *_gst_plugin_static = NULL;
50
51/* static variables for segfault handling of plugin loading */
52static char *_gst_plugin_fault_handler_filename = NULL;
53extern gboolean _gst_disable_segtrap;   /* see gst.c */
54
55#ifndef HAVE_WIN32
56static gboolean _gst_plugin_fault_handler_is_setup = FALSE;
57#endif
58
59/* list of valid licenses.
60 * One of these must be specified or the plugin won't be loaded
61 * Contact gstreamer-devel@lists.sourceforge.net if your license should be
62 * added.
63 *
64 * GPL: http://www.gnu.org/copyleft/gpl.html
65 * LGPL: http://www.gnu.org/copyleft/lesser.html
66 * QPL: http://www.trolltech.com/licenses/qpl.html
67 */
68static gchar *valid_licenses[] = {
69  "LGPL",                       /* GNU Lesser General Public License */
70  "GPL",                        /* GNU General Public License */
71  "QPL",                        /* Trolltech Qt Public License */
72  "GPL/QPL",                    /* Combi-license of GPL + QPL */
73  GST_LICENSE_UNKNOWN,          /* some other license */
74  NULL
75};
76
77static void gst_plugin_desc_copy (GstPluginDesc * dest,
78    const GstPluginDesc * src);
79
80static GstPlugin *gst_plugin_register_func (GstPlugin * plugin,
81    GModule * module, GstPluginDesc * desc);
82
83static GstPlugin *
84gst_plugin_copy (GstPlugin * plugin)
85{
86  return g_memdup (plugin, sizeof (*plugin));
87}
88
89GType
90gst_plugin_get_type (void)
91{
92  static GType plugin_type;
93
94  if (plugin_type == 0) {
95    plugin_type = g_boxed_type_register_static ("GstPlugin",
96        (GBoxedCopyFunc) gst_plugin_copy, g_free);
97  }
98
99  return plugin_type;
100}
101
102GQuark
103gst_plugin_error_quark (void)
104{
105  static GQuark quark = 0;
106
107  if (!quark)
108    quark = g_quark_from_static_string ("gst_plugin_error");
109  return quark;
110}
111
112/* this function can be called in the GCC constructor extension, before
113 * the _gst_plugin_initialize() was called. In that case, we store the
114 * plugin description in a list to initialize it when we open the main
115 * module later on.
116 * When the main module is known, we can register the plugin right away.
117 * */
118void
119_gst_plugin_register_static (GstPluginDesc * desc)
120{
121  if (main_module == NULL) {
122    if (GST_CAT_DEFAULT)
123      GST_LOG ("queueing static plugin \"%s\" for loading later on",
124          desc->name);
125    _gst_plugin_static = g_list_prepend (_gst_plugin_static, desc);
126  } else {
127    GstPlugin *plugin;
128
129    if (GST_CAT_DEFAULT)
130      GST_LOG ("attempting to load static plugin \"%s\" now...", desc->name);
131    plugin = g_new0 (GstPlugin, 1);
132    if (gst_plugin_register_func (plugin, main_module, desc)) {
133      if (GST_CAT_DEFAULT)
134        GST_INFO ("loaded static plugin \"%s\"", desc->name);
135      gst_registry_pool_add_plugin (plugin);
136    }
137  }
138}
139
140void
141_gst_plugin_initialize (void)
142{
143  main_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
144
145  /* now register all static plugins */
146  g_list_foreach (_gst_plugin_static, (GFunc) _gst_plugin_register_static,
147      NULL);
148}
149
150/* this function could be extended to check if the plugin license matches the
151 * applications license (would require the app to register its license somehow).
152 * We'll wait for someone who's interested in it to code it :)
153 */
154static gboolean
155gst_plugin_check_license (const gchar * license)
156{
157  gchar **check_license = valid_licenses;
158
159  g_assert (check_license);
160
161  while (*check_license) {
162    if (strcmp (license, *check_license) == 0)
163      return TRUE;
164    check_license++;
165  }
166  return FALSE;
167}
168
169static gboolean
170gst_plugin_check_version (gint major, gint minor)
171{
172  /* return NULL if the major and minor version numbers are not compatible */
173  /* with ours. */
174  if (major != GST_VERSION_MAJOR || minor != GST_VERSION_MINOR)
175    return FALSE;
176
177  return TRUE;
178}
179
180static GstPlugin *
181gst_plugin_register_func (GstPlugin * plugin, GModule * module,
182    GstPluginDesc * desc)
183{
184  g_assert (plugin->module == NULL);
185
186  if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
187    if (GST_CAT_DEFAULT)
188      GST_INFO ("plugin \"%s\" has incompatible version, not loading",
189          plugin->filename);
190    return NULL;
191  }
192
193  if (!desc->license || !desc->description || !desc->package || !desc->origin) {
194    if (GST_CAT_DEFAULT)
195      GST_INFO ("plugin \"%s\" has incorrect GstPluginDesc, not loading",
196          plugin->filename);
197    return NULL;
198  }
199
200  if (!gst_plugin_check_license (desc->license)) {
201    if (GST_CAT_DEFAULT)
202      GST_INFO ("plugin \"%s\" has invalid license \"%s\", not loading",
203          plugin->filename, desc->license);
204    return NULL;
205  }
206
207  if (GST_CAT_DEFAULT)
208    GST_LOG ("plugin \"%s\" looks good", GST_STR_NULL (plugin->filename));
209
210  gst_plugin_desc_copy (&plugin->desc, desc);
211  plugin->module = module;
212
213  if (!((desc->plugin_init) (plugin))) {
214    if (GST_CAT_DEFAULT)
215      GST_INFO ("plugin \"%s\" failed to initialise", plugin->filename);
216    plugin->module = NULL;
217    return NULL;
218  }
219
220  if (GST_CAT_DEFAULT)
221    GST_LOG ("plugin \"%s\" initialised", GST_STR_NULL (plugin->filename));
222
223  return plugin;
224}
225
226#ifndef HAVE_WIN32
227/*
228 * _gst_plugin_fault_handler_restore:
229 * segfault handler restorer
230 */
231static void
232_gst_plugin_fault_handler_restore (void)
233{
234  struct sigaction action;
235
236  memset (&action, 0, sizeof (action));
237  action.sa_handler = SIG_DFL;
238
239  sigaction (SIGSEGV, &action, NULL);
240}
241
242/*
243 * _gst_plugin_fault_handler_sighandler:
244 * segfault handler implementation
245 */
246static void
247_gst_plugin_fault_handler_sighandler (int signum)
248{
249  /* We need to restore the fault handler or we'll keep getting it */
250  _gst_plugin_fault_handler_restore ();
251
252  switch (signum) {
253    case SIGSEGV:
254      g_print ("\nERROR: ");
255      g_print ("Caught a segmentation fault while loading plugin file:\n");
256      g_print ("%s\n\n", _gst_plugin_fault_handler_filename);
257      g_print ("Please either:\n");
258      g_print ("- remove it and restart.\n");
259      g_print ("- run with --gst-disable-segtrap and debug.\n");
260      exit (-1);
261      break;
262    default:
263      g_print ("Caught unhandled signal on plugin loading\n");
264      break;
265  }
266}
267
268/*
269 * _gst_plugin_fault_handler_setup:
270 * sets up the segfault handler
271 */
272static void
273_gst_plugin_fault_handler_setup (void)
274{
275  struct sigaction action;
276
277  /* if asked to leave segfaults alone, just return */
278  if (_gst_disable_segtrap)
279    return;
280
281  if (_gst_plugin_fault_handler_is_setup)
282    return;
283
284  memset (&action, 0, sizeof (action));
285  action.sa_handler = _gst_plugin_fault_handler_sighandler;
286
287  sigaction (SIGSEGV, &action, NULL);
288}
289#else
290static void
291_gst_plugin_fault_handler_restore (void)
292{
293}
294
295static void
296_gst_plugin_fault_handler_setup (void)
297{
298}
299#endif
300
301static void _gst_plugin_fault_handler_setup ();
302
303/**
304 * gst_plugin_check_file:
305 * @filename: the plugin filename to check for pluginness
306 * @error: pointer to a NULL-valued GError
307 *
308 * Checks if the given path represents a GStreamer plugin.
309 *
310 * Returns: TRUE if the given path is a GStreamer plugin.
311 */
312gboolean
313gst_plugin_check_file (const gchar * filename, GError ** error)
314{
315  GModule *module;
316  struct stat file_status;
317  gpointer ptr;
318
319  g_return_val_if_fail (filename != NULL, FALSE);
320
321  if (g_module_supported () == FALSE) {
322    g_set_error (error,
323        GST_PLUGIN_ERROR,
324        GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported");
325    return FALSE;
326  }
327
328  if (stat (filename, &file_status)) {
329    g_set_error (error,
330        GST_PLUGIN_ERROR,
331        GST_PLUGIN_ERROR_MODULE, "Problem accessing file %s: %s\n", filename,
332        strerror (errno));
333    return FALSE;
334  }
335
336  module = g_module_open (filename, G_MODULE_BIND_LAZY);
337
338  if (module == NULL) {
339    GST_DEBUG ("Error loading plugin %s, reason: %s\n", filename,
340        g_module_error ());
341    g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE,
342        "Error loading plugin %s, reason: %s\n", filename, g_module_error ());
343    return FALSE;
344  }
345
346  if (!g_module_symbol (module, "gst_plugin_desc", &ptr)) {
347    GST_DEBUG ("Could not find plugin entry point in \"%s\"", filename);
348    g_set_error (error,
349        GST_PLUGIN_ERROR,
350        GST_PLUGIN_ERROR_MODULE,
351        "Could not find plugin entry point in \"%s\"", filename);
352    g_module_close (module);
353    return FALSE;
354  }
355  /* it's a plugin */
356  GST_INFO ("looks like a gst plugin \"%s\"", filename);
357  g_module_close (module);
358  return TRUE;
359}
360
361/**
362 * gst_plugin_load_file:
363 * @filename: the plugin filename to load
364 * @error: pointer to a NULL-valued GError
365 *
366 * Loads the given plugin.
367 *
368 * Returns: a new GstPlugin or NULL, if an error occurred.
369 */
370GstPlugin *
371gst_plugin_load_file (const gchar * filename, GError ** error)
372{
373  GstPlugin *plugin;
374  GModule *module;
375  GstPluginDesc *desc;
376  gboolean free_plugin;
377  gpointer ptr;
378
379  g_return_val_if_fail (filename != NULL, NULL);
380
381  GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "attempt to load plugin \"%s\"",
382      filename);
383
384  if (!gst_plugin_check_file (filename, error))
385    return NULL;
386
387  module = g_module_open (filename, G_MODULE_BIND_LAZY);
388
389  if (module == NULL)
390    goto load_error;
391
392  if (!g_module_symbol (module, "gst_plugin_desc", &ptr))
393    goto load_error;
394
395  desc = (GstPluginDesc *) ptr;
396
397  plugin = gst_registry_pool_find_plugin (desc->name);
398  if (!plugin) {
399    free_plugin = TRUE;
400    plugin = g_new0 (GstPlugin, 1);
401    plugin->filename = g_strdup (filename);
402    GST_DEBUG ("created new GstPlugin %p for file \"%s\"", plugin, filename);
403  } else {
404    free_plugin = FALSE;
405    if (gst_plugin_is_loaded (plugin)) {
406      if (plugin->filename && strcmp (plugin->filename, filename) != 0) {
407        GST_WARNING
408            ("plugin %p from file \"%s\" with same name %s is already "
409            "loaded, aborting loading of \"%s\"", plugin, plugin->filename,
410            plugin->desc.name, filename);
411        g_set_error (error, GST_PLUGIN_ERROR,
412            GST_PLUGIN_ERROR_NAME_MISMATCH,
413            "plugin %p from file \"%s\" with same name %s is already "
414            "loaded, aborting loading of \"%s\"", plugin, plugin->filename,
415            plugin->desc.name, filename);
416        if (free_plugin)
417          g_free (plugin);
418        return NULL;
419      }
420      GST_LOG ("Plugin %p for file \"%s\" already loaded, returning it now",
421          plugin, filename);
422      return plugin;
423    }
424  }
425  GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
426      plugin, filename);
427
428  if (g_module_symbol (module, "plugin_init", &ptr)) {
429    GST_WARNING
430        ("plugin %p from file \"%s\" exports a symbol named plugin_init\n",
431        plugin, plugin->filename);
432    g_set_error (error, GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_NAME_MISMATCH,
433        "plugin \"%s\" exports a symbol named plugin_init", desc->name);
434  }
435
436  /* this is where we load the actual .so, so let's trap SIGSEGV */
437  _gst_plugin_fault_handler_setup ();
438  _gst_plugin_fault_handler_filename = plugin->filename;
439
440  GST_LOG ("Plugin %p for file \"%s\" prepared, registering...",
441      plugin, filename);
442
443  if (gst_plugin_register_func (plugin, module, desc)) {
444    /* remove signal handler */
445    _gst_plugin_fault_handler_restore ();
446    _gst_plugin_fault_handler_filename = NULL;
447    GST_INFO ("plugin \"%s\" loaded", plugin->filename);
448    return plugin;
449  } else {
450    /* remove signal handler */
451    _gst_plugin_fault_handler_restore ();
452    GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename);
453    /* plugin == NULL */
454    g_set_error (error,
455        GST_PLUGIN_ERROR,
456        GST_PLUGIN_ERROR_MODULE,
457        "gst_plugin_register_func failed for plugin \"%s\"", filename);
458    if (free_plugin)
459      g_free (plugin);
460    return NULL;
461  }
462load_error:
463  g_set_error (error,
464      GST_PLUGIN_ERROR,
465      GST_PLUGIN_ERROR_MODULE, "generic load error for \"%s\"", filename);
466  return NULL;
467}
468
469static void
470gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src)
471{
472  dest->major_version = src->major_version;
473  dest->minor_version = src->minor_version;
474  g_free (dest->name);
475  dest->name = g_strdup (src->name);
476  g_free (dest->description);
477  dest->description = g_strdup (src->description);
478  dest->plugin_init = src->plugin_init;
479  dest->plugin_exit = src->plugin_exit;
480  g_free (dest->version);
481  dest->version = g_strdup (src->version);
482  g_free (dest->license);
483  dest->license = g_strdup (src->license);
484  g_free (dest->package);
485  dest->package = g_strdup (src->package);
486  g_free (dest->origin);
487  dest->origin = g_strdup (src->origin);
488}
489
490#if 0
491/* unused */
492static void
493gst_plugin_desc_free (GstPluginDesc * desc)
494{
495  g_free (desc->name);
496  g_free (desc->description);
497  g_free (desc->version);
498  g_free (desc->license);
499  g_free (desc->package);
500  g_free (desc->origin);
501
502  memset (desc, 0, sizeof (GstPluginDesc));
503}
504#endif
505/**
506 * gst_plugin_unload_plugin:
507 * @plugin: The plugin to unload
508 *
509 * Unload the given plugin.
510 *
511 * Returns: whether or not the plugin unloaded
512 */
513gboolean
514gst_plugin_unload_plugin (GstPlugin * plugin)
515{
516  g_return_val_if_fail (plugin != NULL, FALSE);
517
518  if (!plugin->module)
519    return TRUE;
520
521  if (g_module_close (plugin->module)) {
522    plugin->module = NULL;
523    GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "plugin \"%s\" unloaded",
524        plugin->filename);
525    return TRUE;
526  } else {
527    GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "failed to unload plugin \"%s\"",
528        plugin->filename);
529    return FALSE;
530  }
531}
532
533/**
534 * gst_plugin_get_name:
535 * @plugin: plugin to get the name of
536 *
537 * Get the short name of the plugin
538 *
539 * Returns: the name of the plugin
540 */
541const gchar *
542gst_plugin_get_name (GstPlugin * plugin)
543{
544  g_return_val_if_fail (plugin != NULL, NULL);
545
546  return plugin->desc.name;
547}
548
549/**
550 * gst_plugin_get_description:
551 * @plugin: plugin to get long name of
552 *
553 * Get the long descriptive name of the plugin
554 *
555 * Returns: the long name of the plugin
556 */
557G_CONST_RETURN gchar *
558gst_plugin_get_description (GstPlugin * plugin)
559{
560  g_return_val_if_fail (plugin != NULL, NULL);
561
562  return plugin->desc.description;
563}
564
565/**
566 * gst_plugin_get_filename:
567 * @plugin: plugin to get the filename of
568 *
569 * get the filename of the plugin
570 *
571 * Returns: the filename of the plugin
572 */
573G_CONST_RETURN gchar *
574gst_plugin_get_filename (GstPlugin * plugin)
575{
576  g_return_val_if_fail (plugin != NULL, NULL);
577
578  return plugin->filename;
579}
580
581/**
582 * gst_plugin_get_version:
583 * @plugin: plugin to get the version of
584 *
585 * get the version of the plugin
586 *
587 * Returns: the version of the plugin
588 */
589G_CONST_RETURN gchar *
590gst_plugin_get_version (GstPlugin * plugin)
591{
592  g_return_val_if_fail (plugin != NULL, NULL);
593
594  return plugin->desc.version;
595}
596
597/**
598 * gst_plugin_get_license:
599 * @plugin: plugin to get the license of
600 *
601 * get the license of the plugin
602 *
603 * Returns: the license of the plugin
604 */
605G_CONST_RETURN gchar *
606gst_plugin_get_license (GstPlugin * plugin)
607{
608  g_return_val_if_fail (plugin != NULL, NULL);
609
610  return plugin->desc.license;
611}
612
613/**
614 * gst_plugin_get_package:
615 * @plugin: plugin to get the package of
616 *
617 * get the package the plugin belongs to.
618 *
619 * Returns: the package of the plugin
620 */
621G_CONST_RETURN gchar *
622gst_plugin_get_package (GstPlugin * plugin)
623{
624  g_return_val_if_fail (plugin != NULL, NULL);
625
626  return plugin->desc.package;
627}
628
629/**
630 * gst_plugin_get_origin:
631 * @plugin: plugin to get the origin of
632 *
633 * get the URL where the plugin comes from
634 *
635 * Returns: the origin of the plugin
636 */
637G_CONST_RETURN gchar *
638gst_plugin_get_origin (GstPlugin * plugin)
639{
640  g_return_val_if_fail (plugin != NULL, NULL);
641
642  return plugin->desc.origin;
643}
644
645/**
646 * gst_plugin_get_module:
647 * @plugin: plugin to query
648 *
649 * Gets the #GModule of the plugin. If the plugin isn't loaded yet, NULL is
650 * returned.
651 *
652 * Returns: module belonging to the plugin or NULL if the plugin isn't
653 *          loaded yet.
654 */
655GModule *
656gst_plugin_get_module (GstPlugin * plugin)
657{
658  g_return_val_if_fail (plugin != NULL, NULL);
659
660  return plugin->module;
661}
662
663/**
664 * gst_plugin_is_loaded:
665 * @plugin: plugin to query
666 *
667 * queries if the plugin is loaded into memory
668 *
669 * Returns: TRUE is loaded, FALSE otherwise
670 */
671gboolean
672gst_plugin_is_loaded (GstPlugin * plugin)
673{
674  g_return_val_if_fail (plugin != NULL, FALSE);
675
676  return (plugin->module != NULL);
677}
678
679/**
680 * gst_plugin_feature_list:
681 * @plugin: plugin to query
682 * @filter: the filter to use
683 * @first: only return first match
684 * @user_data: user data passed to the filter function
685 *
686 * Runs a filter against all plugin features and returns a GList with
687 * the results. If the first flag is set, only the first match is
688 * returned (as a list with a single object).
689 *
690 * Returns: a GList of features, g_list_free after use.
691 */
692GList *
693gst_plugin_feature_filter (GstPlugin * plugin,
694    GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
695{
696  return gst_filter_run (plugin->features, (GstFilterFunc) filter, first,
697      user_data);
698}
699
700typedef struct
701{
702  GstPluginFeatureFilter filter;
703  gboolean first;
704  gpointer user_data;
705  GList *result;
706}
707FeatureFilterData;
708
709static gboolean
710_feature_filter (GstPlugin * plugin, gpointer user_data)
711{
712  GList *result;
713  FeatureFilterData *data = (FeatureFilterData *) user_data;
714
715  result =
716      gst_plugin_feature_filter (plugin, data->filter, data->first,
717      data->user_data);
718  if (result) {
719    data->result = g_list_concat (data->result, result);
720    return TRUE;
721  }
722  return FALSE;
723}
724
725/**
726 * gst_plugin_list_feature_list:
727 * @list: a list of plugins to query
728 * @filter: the filter to use
729 * @first: only return first match
730 * @user_data: user data passed to the filter function
731 *
732 * Runs a filter against all plugin features of the plugins in the given
733 * list and returns a GList with the results.
734 * If the first flag is set, only the first match is
735 * returned (as a list with a single object).
736 *
737 * Returns: a GList of features, g_list_free after use.
738 */
739GList *
740gst_plugin_list_feature_filter (GList * list,
741    GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
742{
743  FeatureFilterData data;
744  GList *result;
745
746  data.filter = filter;
747  data.first = first;
748  data.user_data = user_data;
749  data.result = NULL;
750
751  result = gst_filter_run (list, (GstFilterFunc) _feature_filter, first, &data);
752  g_list_free (result);
753
754  return data.result;
755}
756
757/**
758 * gst_plugin_name_filter:
759 * @plugin: the plugin to check
760 * @name: the name of the plugin
761 *
762 * A standard filter that returns TRUE when the plugin is of the
763 * given name.
764 *
765 * Returns: TRUE if the plugin is of the given name.
766 */
767gboolean
768gst_plugin_name_filter (GstPlugin * plugin, const gchar * name)
769{
770  return (plugin->desc.name && !strcmp (plugin->desc.name, name));
771}
772
773/**
774 * gst_plugin_find_feature:
775 * @plugin: plugin to get the feature from
776 * @name: The name of the feature to find
777 * @type: The type of the feature to find
778 *
779 * Find a feature of the given name and type in the given plugin.
780 *
781 * Returns: a GstPluginFeature or NULL if the feature was not found.
782 */
783GstPluginFeature *
784gst_plugin_find_feature (GstPlugin * plugin, const gchar * name, GType type)
785{
786  GList *walk;
787  GstPluginFeature *result = NULL;
788  GstTypeNameData data;
789
790  g_return_val_if_fail (name != NULL, NULL);
791
792  data.type = type;
793  data.name = name;
794
795  walk = gst_filter_run (plugin->features,
796      (GstFilterFunc) gst_plugin_feature_type_name_filter, TRUE, &data);
797
798  if (walk)
799    result = GST_PLUGIN_FEATURE (walk->data);
800
801  return result;
802}
803
804/**
805 * gst_plugin_add_feature:
806 * @plugin: plugin to add feature to
807 * @feature: feature to add
808 *
809 * Add feature to the list of those provided by the plugin.
810 * There is a separate namespace for each plugin feature type.
811 * See #gst_plugin_get_feature_list
812 */
813void
814gst_plugin_add_feature (GstPlugin * plugin, GstPluginFeature * feature)
815{
816  GstPluginFeature *oldfeature;
817
818  /* FIXME 0.9: get reference counting somewhat right in here,
819   * GstPluginFeatures should probably be GstObjects that are sinked when
820   * adding them to a plugin */
821  g_return_if_fail (plugin != NULL);
822  g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
823  g_return_if_fail (feature != NULL);
824
825  oldfeature = gst_plugin_find_feature (plugin,
826      GST_PLUGIN_FEATURE_NAME (feature), G_OBJECT_TYPE (feature));
827
828  if (oldfeature == feature) {
829    GST_WARNING ("feature %s has already been added",
830        GST_PLUGIN_FEATURE_NAME (feature));
831    /* g_object_unref (feature); */
832  } else if (oldfeature) {
833    GST_WARNING ("feature %s already present in plugin",
834        GST_PLUGIN_FEATURE_NAME (feature));
835    /* g_object_unref (feature); */
836  } else {
837    feature->manager = plugin;
838    plugin->features = g_list_prepend (plugin->features, feature);
839    plugin->numfeatures++;
840  }
841}
842
843/**
844 * gst_plugin_get_feature_list:
845 * @plugin: the plugin to get the features from
846 *
847 * get a list of all the features that this plugin provides
848 *
849 * Returns: a GList of features, use g_list_free to free the list.
850 */
851GList *
852gst_plugin_get_feature_list (GstPlugin * plugin)
853{
854  g_return_val_if_fail (plugin != NULL, NULL);
855
856  return g_list_copy (plugin->features);
857}
858
859/**
860 * gst_plugin_load:
861 * @name: name of plugin to load
862 *
863 * Load the named plugin. 
864 *
865 * Returns: whether the plugin was loaded or not
866 */
867gboolean
868gst_plugin_load (const gchar * name)
869{
870  GstPlugin *plugin;
871  GError *error = NULL;
872
873  plugin = gst_registry_pool_find_plugin (name);
874  if (plugin) {
875    plugin = gst_plugin_load_file (plugin->filename, &error);
876    if (!plugin) {
877      GST_WARNING ("load_plugin error: %s\n", error->message);
878      g_error_free (error);
879      return FALSE;
880    }
881    return TRUE;;
882  }
883
884  GST_DEBUG ("Could not find %s in registry pool", name);
885  return FALSE;
886}
887
888/**
889 * gst_library_load:
890 * @name: name of library to load
891 *
892 * Load the named library.  Name should be given as
893 * &quot;liblibrary.so&quot;. (exception to this rule is 'riff', which .so name is 'gstriff')
894 *
895 * Returns: whether the library was loaded or not (and returns TRUE if it was already loaded)
896 */
897gboolean
898gst_library_load (const gchar * name)
899{
900  gboolean res;
901
902  /* for now this is the same */
903  res = gst_plugin_load (name);
904
905  return res;
906}
Note: See TracBrowser for help on using the repository browser.