check/Makefile.am: re-enable tests now that leaks are plugged
[platform/upstream/gstreamer.git] / gst / gstplugin.c
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 "gstinfo.h"
42 #include "gstfilter.h"
43 #include "gstregistry.h"
44
45
46 #define GST_CAT_DEFAULT GST_CAT_PLUGIN_LOADING
47
48 static GModule *main_module = NULL;
49 static GList *_gst_plugin_static = NULL;
50
51 /* static variables for segfault handling of plugin loading */
52 static char *_gst_plugin_fault_handler_filename = NULL;
53 extern gboolean _gst_disable_segtrap;   /* see gst.c */
54
55 #ifndef HAVE_WIN32
56 static 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  */
68 static 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
77 static GstPlugin *gst_plugin_register_func (GstPlugin * plugin,
78     GModule * module, GstPluginDesc * desc);
79 static void
80 gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src);
81 static void gst_plugin_desc_free (GstPluginDesc * desc);
82
83
84 G_DEFINE_TYPE (GstPlugin, gst_plugin, GST_TYPE_OBJECT);
85
86 static GstObjectClass *parent_class = NULL;
87
88 static void
89 gst_plugin_init (GstPlugin * plugin)
90 {
91
92 }
93
94 static void
95 gst_plugin_finalize (GObject * object)
96 {
97   GstPlugin *plugin = GST_PLUGIN (object);
98   GstRegistry *registry = gst_registry_get_default ();
99   GList *g;
100
101   GST_DEBUG ("finalizing plugin %p", plugin);
102   for (g = registry->plugins; g; g = g->next) {
103     if (g->data == (gpointer) plugin) {
104       g_warning ("removing plugin that is still in registry");
105     }
106   }
107   g_free (plugin->filename);
108   gst_plugin_desc_free (&plugin->desc);
109
110   G_OBJECT_CLASS (parent_class)->finalize (object);
111 }
112
113 static void
114 gst_plugin_class_init (GstPluginClass * klass)
115 {
116   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
117
118   G_OBJECT_CLASS (klass)->finalize = GST_DEBUG_FUNCPTR (gst_plugin_finalize);
119 }
120
121 GQuark
122 gst_plugin_error_quark (void)
123 {
124   static GQuark quark = 0;
125
126   if (!quark)
127     quark = g_quark_from_static_string ("gst_plugin_error");
128   return quark;
129 }
130
131 /* this function can be called in the GCC constructor extension, before
132  * the _gst_plugin_initialize() was called. In that case, we store the 
133  * plugin description in a list to initialize it when we open the main
134  * module later on.
135  * When the main module is known, we can register the plugin right away.
136  */
137 void
138 _gst_plugin_register_static (GstPluginDesc * desc)
139 {
140   if (main_module == NULL) {
141     if (GST_CAT_DEFAULT)
142       GST_LOG ("queueing static plugin \"%s\" for loading later on",
143           desc->name);
144     _gst_plugin_static = g_list_prepend (_gst_plugin_static, desc);
145   } else {
146     GstPlugin *plugin;
147
148     if (GST_CAT_DEFAULT)
149       GST_LOG ("attempting to load static plugin \"%s\" now...", desc->name);
150     plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
151     if (gst_plugin_register_func (plugin, main_module, desc)) {
152       if (GST_CAT_DEFAULT)
153         GST_INFO ("loaded static plugin \"%s\"", desc->name);
154       gst_default_registry_add_plugin (plugin);
155     }
156   }
157 }
158
159 void
160 _gst_plugin_initialize (void)
161 {
162   main_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
163
164   /* now register all static plugins */
165   g_list_foreach (_gst_plugin_static, (GFunc) _gst_plugin_register_static,
166       NULL);
167 }
168
169 /* this function could be extended to check if the plugin license matches the 
170  * applications license (would require the app to register its license somehow).
171  * We'll wait for someone who's interested in it to code it :)
172  */
173 static gboolean
174 gst_plugin_check_license (const gchar * license)
175 {
176   gchar **check_license = valid_licenses;
177
178   g_assert (check_license);
179
180   while (*check_license) {
181     if (strcmp (license, *check_license) == 0)
182       return TRUE;
183     check_license++;
184   }
185   return FALSE;
186 }
187
188 static gboolean
189 gst_plugin_check_version (gint major, gint minor)
190 {
191   /* return NULL if the major and minor version numbers are not compatible */
192   /* with ours. */
193   if (major != GST_VERSION_MAJOR || minor != GST_VERSION_MINOR)
194     return FALSE;
195
196   return TRUE;
197 }
198
199 static GstPlugin *
200 gst_plugin_register_func (GstPlugin * plugin, GModule * module,
201     GstPluginDesc * desc)
202 {
203   if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
204     if (GST_CAT_DEFAULT)
205       GST_INFO ("plugin \"%s\" has incompatible version, not loading",
206           plugin->filename);
207     return NULL;
208   }
209
210   if (!desc->license || !desc->description || !desc->source ||
211       !desc->package || !desc->origin) {
212     if (GST_CAT_DEFAULT)
213       GST_INFO ("plugin \"%s\" has incorrect GstPluginDesc, not loading",
214           plugin->filename);
215     return NULL;
216   }
217
218   if (!gst_plugin_check_license (desc->license)) {
219     if (GST_CAT_DEFAULT)
220       GST_INFO ("plugin \"%s\" has invalid license \"%s\", not loading",
221           plugin->filename, desc->license);
222     return NULL;
223   }
224
225   if (GST_CAT_DEFAULT)
226     GST_LOG ("plugin \"%s\" looks good", GST_STR_NULL (plugin->filename));
227
228   gst_plugin_desc_copy (&plugin->desc, desc);
229
230   if (!((desc->plugin_init) (plugin))) {
231     if (GST_CAT_DEFAULT)
232       GST_INFO ("plugin \"%s\" failed to initialise", plugin->filename);
233     plugin->module = NULL;
234     return NULL;
235   }
236
237   if (GST_CAT_DEFAULT)
238     GST_LOG ("plugin \"%s\" initialised", GST_STR_NULL (plugin->filename));
239
240   return plugin;
241 }
242
243 #ifndef HAVE_WIN32
244 /*
245  * _gst_plugin_fault_handler_restore:
246  * segfault handler restorer
247  */
248 static void
249 _gst_plugin_fault_handler_restore (void)
250 {
251   struct sigaction action;
252
253   memset (&action, 0, sizeof (action));
254   action.sa_handler = SIG_DFL;
255
256   sigaction (SIGSEGV, &action, NULL);
257 }
258
259 /*
260  * _gst_plugin_fault_handler_sighandler:
261  * segfault handler implementation
262  */
263 static void
264 _gst_plugin_fault_handler_sighandler (int signum)
265 {
266   /* We need to restore the fault handler or we'll keep getting it */
267   _gst_plugin_fault_handler_restore ();
268
269   switch (signum) {
270     case SIGSEGV:
271       g_print ("\nERROR: ");
272       g_print ("Caught a segmentation fault while loading plugin file:\n");
273       g_print ("%s\n\n", _gst_plugin_fault_handler_filename);
274       g_print ("Please either:\n");
275       g_print ("- remove it and restart.\n");
276       g_print ("- run with --gst-disable-segtrap and debug.\n");
277       exit (-1);
278       break;
279     default:
280       g_print ("Caught unhandled signal on plugin loading\n");
281       break;
282   }
283 }
284
285 /*
286  * _gst_plugin_fault_handler_setup:
287  * sets up the segfault handler
288  */
289 static void
290 _gst_plugin_fault_handler_setup (void)
291 {
292   struct sigaction action;
293
294   /* if asked to leave segfaults alone, just return */
295   if (_gst_disable_segtrap)
296     return;
297
298   if (_gst_plugin_fault_handler_is_setup)
299     return;
300
301   memset (&action, 0, sizeof (action));
302   action.sa_handler = _gst_plugin_fault_handler_sighandler;
303
304   sigaction (SIGSEGV, &action, NULL);
305 }
306 #else
307 static void
308 _gst_plugin_fault_handler_restore (void)
309 {
310 }
311
312 static void
313 _gst_plugin_fault_handler_setup (void)
314 {
315 }
316 #endif
317
318 static void _gst_plugin_fault_handler_setup ();
319
320 GStaticMutex gst_plugin_loading_mutex = G_STATIC_MUTEX_INIT;
321
322 /**
323  * gst_plugin_load_file:
324  * @filename: the plugin filename to load
325  * @error: pointer to a NULL-valued GError
326  *
327  * Loads the given plugin and refs it.  Caller needs to unref after use.
328  *
329  * Returns: a new GstPlugin or NULL, if an error occurred.
330  */
331 GstPlugin *
332 gst_plugin_load_file (const gchar * filename, GError ** error)
333 {
334   GstPlugin *plugin;
335   GModule *module;
336   gboolean ret;
337   gpointer ptr;
338   struct stat file_status;
339   GstRegistry *registry;
340
341   g_return_val_if_fail (filename != NULL, NULL);
342
343   registry = gst_registry_get_default ();
344   g_static_mutex_lock (&gst_plugin_loading_mutex);
345
346   plugin = gst_registry_lookup (registry, filename);
347   if (plugin) {
348     if (plugin->module) {
349       g_static_mutex_unlock (&gst_plugin_loading_mutex);
350       return plugin;
351     } else {
352       gst_object_unref (plugin);
353     }
354   }
355
356   GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "attempt to load plugin \"%s\"",
357       filename);
358
359   if (g_module_supported () == FALSE) {
360     GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "module loading not supported");
361     g_set_error (error,
362         GST_PLUGIN_ERROR,
363         GST_PLUGIN_ERROR_MODULE, "Dynamic loading not supported");
364     goto return_error;
365   }
366
367   if (stat (filename, &file_status)) {
368     GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, "problem accessing file");
369     g_set_error (error,
370         GST_PLUGIN_ERROR,
371         GST_PLUGIN_ERROR_MODULE, "Problem accessing file %s: %s\n", filename,
372         strerror (errno));
373     goto return_error;
374   }
375
376   module = g_module_open (filename, G_MODULE_BIND_LOCAL);
377   if (module == NULL) {
378     GST_CAT_ERROR (GST_CAT_PLUGIN_LOADING, "module_open failed: %s",
379         g_module_error ());
380     g_set_error (error,
381         GST_PLUGIN_ERROR, GST_PLUGIN_ERROR_MODULE, "Opening module failed");
382     goto return_error;
383   }
384
385   plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
386
387   plugin->module = module;
388   plugin->filename = strdup (filename);
389   plugin->file_mtime = file_status.st_mtime;
390   plugin->file_size = file_status.st_size;
391
392   ret = g_module_symbol (module, "gst_plugin_desc", &ptr);
393   if (!ret) {
394     GST_DEBUG ("Could not find plugin entry point in \"%s\"", filename);
395     g_set_error (error,
396         GST_PLUGIN_ERROR,
397         GST_PLUGIN_ERROR_MODULE,
398         "Could not find plugin entry point in \"%s\"", filename);
399     goto return_error;
400   }
401   plugin->orig_desc = (GstPluginDesc *) ptr;
402
403   GST_LOG ("Plugin %p for file \"%s\" prepared, calling entry function...",
404       plugin, filename);
405
406   /* this is where we load the actual .so, so let's trap SIGSEGV */
407   _gst_plugin_fault_handler_setup ();
408   _gst_plugin_fault_handler_filename = plugin->filename;
409
410   GST_LOG ("Plugin %p for file \"%s\" prepared, registering...",
411       plugin, filename);
412
413   if (!gst_plugin_register_func (plugin, module, plugin->orig_desc)) {
414     /* remove signal handler */
415     _gst_plugin_fault_handler_restore ();
416     GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename);
417     /* plugin == NULL */
418     g_set_error (error,
419         GST_PLUGIN_ERROR,
420         GST_PLUGIN_ERROR_MODULE,
421         "gst_plugin_register_func failed for plugin \"%s\"", filename);
422     g_module_close (module);
423     goto return_error;
424   }
425
426   /* remove signal handler */
427   _gst_plugin_fault_handler_restore ();
428   _gst_plugin_fault_handler_filename = NULL;
429   GST_INFO ("plugin \"%s\" loaded", plugin->filename);
430
431   gst_object_ref (plugin);
432   gst_default_registry_add_plugin (plugin);
433
434   g_static_mutex_unlock (&gst_plugin_loading_mutex);
435   return plugin;
436 return_error:
437   if (plugin)
438     gst_object_unref (plugin);
439   g_static_mutex_unlock (&gst_plugin_loading_mutex);
440   return NULL;
441 }
442
443 static void
444 gst_plugin_desc_copy (GstPluginDesc * dest, const GstPluginDesc * src)
445 {
446   dest->major_version = src->major_version;
447   dest->minor_version = src->minor_version;
448   dest->name = g_strdup (src->name);
449   dest->description = g_strdup (src->description);
450   dest->plugin_init = src->plugin_init;
451   dest->version = g_strdup (src->version);
452   dest->license = g_strdup (src->license);
453   dest->source = g_strdup (src->source);
454   dest->package = g_strdup (src->package);
455   dest->origin = g_strdup (src->origin);
456 }
457
458 /* unused */
459 static void
460 gst_plugin_desc_free (GstPluginDesc * desc)
461 {
462   g_free (desc->name);
463   g_free (desc->description);
464   g_free (desc->version);
465   g_free (desc->license);
466   g_free (desc->source);
467   g_free (desc->package);
468   g_free (desc->origin);
469
470   memset (desc, 0, sizeof (GstPluginDesc));
471 }
472
473 /**
474  * gst_plugin_get_name:
475  * @plugin: plugin to get the name of
476  *
477  * Get the short name of the plugin
478  *
479  * Returns: the name of the plugin
480  */
481 const gchar *
482 gst_plugin_get_name (GstPlugin * plugin)
483 {
484   g_return_val_if_fail (plugin != NULL, NULL);
485
486   return plugin->desc.name;
487 }
488
489 /**
490  * gst_plugin_get_description:
491  * @plugin: plugin to get long name of
492  *
493  * Get the long descriptive name of the plugin
494  *
495  * Returns: the long name of the plugin
496  */
497 G_CONST_RETURN gchar *
498 gst_plugin_get_description (GstPlugin * plugin)
499 {
500   g_return_val_if_fail (plugin != NULL, NULL);
501
502   return plugin->desc.description;
503 }
504
505 /**
506  * gst_plugin_get_filename:
507  * @plugin: plugin to get the filename of
508  *
509  * get the filename of the plugin
510  *
511  * Returns: the filename of the plugin
512  */
513 G_CONST_RETURN gchar *
514 gst_plugin_get_filename (GstPlugin * plugin)
515 {
516   g_return_val_if_fail (plugin != NULL, NULL);
517
518   return plugin->filename;
519 }
520
521 /**
522  * gst_plugin_get_version:
523  * @plugin: plugin to get the version of
524  *
525  * get the version of the plugin
526  *
527  * Returns: the version of the plugin
528  */
529 G_CONST_RETURN gchar *
530 gst_plugin_get_version (GstPlugin * plugin)
531 {
532   g_return_val_if_fail (plugin != NULL, NULL);
533
534   return plugin->desc.version;
535 }
536
537 /**
538  * gst_plugin_get_license:
539  * @plugin: plugin to get the license of
540  *
541  * get the license of the plugin
542  *
543  * Returns: the license of the plugin
544  */
545 G_CONST_RETURN gchar *
546 gst_plugin_get_license (GstPlugin * plugin)
547 {
548   g_return_val_if_fail (plugin != NULL, NULL);
549
550   return plugin->desc.license;
551 }
552
553 /**
554  * gst_plugin_get_source:
555  * @plugin: plugin to get the source of
556  *
557  * get the source module the plugin belongs to.
558  *
559  * Returns: the source of the plugin
560  */
561 G_CONST_RETURN gchar *
562 gst_plugin_get_source (GstPlugin * plugin)
563 {
564   g_return_val_if_fail (plugin != NULL, NULL);
565
566   return plugin->desc.source;
567 }
568
569 /**
570  * gst_plugin_get_package:
571  * @plugin: plugin to get the package of
572  *
573  * get the package the plugin belongs to.
574  *
575  * Returns: the package of the plugin
576  */
577 G_CONST_RETURN gchar *
578 gst_plugin_get_package (GstPlugin * plugin)
579 {
580   g_return_val_if_fail (plugin != NULL, NULL);
581
582   return plugin->desc.package;
583 }
584
585 /**
586  * gst_plugin_get_origin:
587  * @plugin: plugin to get the origin of
588  *
589  * get the URL where the plugin comes from
590  *
591  * Returns: the origin of the plugin
592  */
593 G_CONST_RETURN gchar *
594 gst_plugin_get_origin (GstPlugin * plugin)
595 {
596   g_return_val_if_fail (plugin != NULL, NULL);
597
598   return plugin->desc.origin;
599 }
600
601 /**
602  * gst_plugin_get_module:
603  * @plugin: plugin to query
604  *
605  * Gets the #GModule of the plugin. If the plugin isn't loaded yet, NULL is 
606  * returned.
607  *
608  * Returns: module belonging to the plugin or NULL if the plugin isn't 
609  *          loaded yet.
610  */
611 GModule *
612 gst_plugin_get_module (GstPlugin * plugin)
613 {
614   g_return_val_if_fail (plugin != NULL, NULL);
615
616   return plugin->module;
617 }
618
619 /**
620  * gst_plugin_is_loaded:
621  * @plugin: plugin to query
622  *
623  * queries if the plugin is loaded into memory
624  *
625  * Returns: TRUE is loaded, FALSE otherwise
626  */
627 gboolean
628 gst_plugin_is_loaded (GstPlugin * plugin)
629 {
630   g_return_val_if_fail (plugin != NULL, FALSE);
631
632   return (plugin->module != NULL || plugin->filename == NULL);
633 }
634
635 #if 0
636 /**
637  * gst_plugin_feature_list:
638  * @plugin: plugin to query
639  * @filter: the filter to use
640  * @first: only return first match
641  * @user_data: user data passed to the filter function
642  *
643  * Runs a filter against all plugin features and returns a GList with
644  * the results. If the first flag is set, only the first match is
645  * returned (as a list with a single object).
646  *
647  * Returns: a GList of features, g_list_free after use.
648  */
649 GList *
650 gst_plugin_feature_filter (GstPlugin * plugin,
651     GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
652 {
653   GList *list;
654   GList *g;
655
656   list = gst_filter_run (plugin->features, (GstFilterFunc) filter, first,
657       user_data);
658   for (g = list; g; g = g->next) {
659     gst_object_ref (plugin);
660   }
661
662   return list;
663 }
664
665 typedef struct
666 {
667   GstPluginFeatureFilter filter;
668   gboolean first;
669   gpointer user_data;
670   GList *result;
671 }
672 FeatureFilterData;
673
674 static gboolean
675 _feature_filter (GstPlugin * plugin, gpointer user_data)
676 {
677   GList *result;
678   FeatureFilterData *data = (FeatureFilterData *) user_data;
679
680   result = gst_plugin_feature_filter (plugin, data->filter, data->first,
681       data->user_data);
682   if (result) {
683     data->result = g_list_concat (data->result, result);
684     return TRUE;
685   }
686   return FALSE;
687 }
688
689 /**
690  * gst_plugin_list_feature_filter:
691  * @list: a #GList of plugins to query
692  * @filter: the filter function to use
693  * @first: only return first match
694  * @user_data: user data passed to the filter function
695  *
696  * Runs a filter against all plugin features of the plugins in the given
697  * list and returns a GList with the results.
698  * If the first flag is set, only the first match is
699  * returned (as a list with a single object).
700  *
701  * Returns: a GList of features, g_list_free after use.
702  */
703 GList *
704 gst_plugin_list_feature_filter (GList * list,
705     GstPluginFeatureFilter filter, gboolean first, gpointer user_data)
706 {
707   FeatureFilterData data;
708   GList *result;
709
710   data.filter = filter;
711   data.first = first;
712   data.user_data = user_data;
713   data.result = NULL;
714
715   result = gst_filter_run (list, (GstFilterFunc) _feature_filter, first, &data);
716   g_list_free (result);
717
718   return data.result;
719 }
720 #endif
721
722 /**
723  * gst_plugin_name_filter:
724  * @plugin: the plugin to check
725  * @name: the name of the plugin
726  *
727  * A standard filter that returns TRUE when the plugin is of the
728  * given name.
729  *
730  * Returns: TRUE if the plugin is of the given name.
731  */
732 gboolean
733 gst_plugin_name_filter (GstPlugin * plugin, const gchar * name)
734 {
735   return (plugin->desc.name && !strcmp (plugin->desc.name, name));
736 }
737
738 #if 0
739 /**
740  * gst_plugin_find_feature:
741  * @plugin: plugin to get the feature from
742  * @name: The name of the feature to find
743  * @type: The type of the feature to find
744  *
745  * Find a feature of the given name and type in the given plugin.
746  *
747  * Returns: a GstPluginFeature or NULL if the feature was not found.
748  */
749 GstPluginFeature *
750 gst_plugin_find_feature (GstPlugin * plugin, const gchar * name, GType type)
751 {
752   GList *walk;
753   GstPluginFeature *result = NULL;
754   GstTypeNameData data;
755
756   g_return_val_if_fail (name != NULL, NULL);
757
758   data.type = type;
759   data.name = name;
760
761   walk = gst_filter_run (plugin->features,
762       (GstFilterFunc) gst_plugin_feature_type_name_filter, TRUE, &data);
763
764   if (walk) {
765     result = GST_PLUGIN_FEATURE (walk->data);
766
767     gst_object_ref (result);
768     gst_plugin_feature_list_free (walk);
769   }
770
771   return result;
772 }
773 #endif
774
775 #if 0
776 static gboolean
777 gst_plugin_feature_name_filter (GstPluginFeature * feature, const gchar * name)
778 {
779   return !strcmp (name, GST_PLUGIN_FEATURE_NAME (feature));
780 }
781 #endif
782
783 #if 0
784 /**
785  * gst_plugin_find_feature_by_name:
786  * @plugin: plugin to get the feature from
787  * @name: The name of the feature to find
788  *
789  * Find a feature of the given name in the given plugin.
790  *
791  * Returns: a GstPluginFeature or NULL if the feature was not found.
792  */
793 GstPluginFeature *
794 gst_plugin_find_feature_by_name (GstPlugin * plugin, const gchar * name)
795 {
796   GList *walk;
797   GstPluginFeature *result = NULL;
798
799   g_return_val_if_fail (name != NULL, NULL);
800
801   walk = gst_filter_run (plugin->features,
802       (GstFilterFunc) gst_plugin_feature_name_filter, TRUE, (void *) name);
803
804   if (walk) {
805     result = GST_PLUGIN_FEATURE (walk->data);
806
807     gst_object_ref (result);
808     gst_plugin_feature_list_free (walk);
809   }
810
811   return result;
812 }
813 #endif
814
815 /**
816  * gst_plugin_load_by_name:
817  * @name: name of plugin to load
818  *
819  * Load the named plugin. Refs the plugin.
820  *
821  * Returns: whether the plugin was loaded or not
822  */
823 GstPlugin *
824 gst_plugin_load_by_name (const gchar * name)
825 {
826   GstPlugin *plugin, *newplugin;
827   GError *error = NULL;
828
829   GST_DEBUG ("looking up plugin %s in default registry", name);
830   plugin = gst_registry_find_plugin (gst_registry_get_default (), name);
831   if (plugin) {
832     GST_DEBUG ("loading plugin %s from file %s", name, plugin->filename);
833     newplugin = gst_plugin_load_file (plugin->filename, &error);
834     gst_object_unref (plugin);
835
836     if (!newplugin) {
837       GST_WARNING ("load_plugin error: %s\n", error->message);
838       g_error_free (error);
839       return NULL;
840     }
841     /* newplugin was reffed by load_file */
842     return newplugin;
843   }
844
845   GST_DEBUG ("Could not find plugin %s in registry", name);
846   return NULL;
847 }
848
849 GstPlugin *
850 gst_plugin_load (GstPlugin * plugin)
851 {
852   GError *error = NULL;
853   GstPlugin *newplugin;
854
855   if (gst_plugin_is_loaded (plugin)) {
856     return plugin;
857   }
858
859   newplugin = gst_plugin_load_file (plugin->filename, &error);
860   if (newplugin == NULL) {
861     GST_WARNING ("load_plugin error: %s\n", error->message);
862     g_error_free (error);
863     gst_object_unref (plugin);
864     return NULL;
865   }
866
867   gst_object_unref (plugin);
868
869   return newplugin;
870 }
871
872 void
873 gst_plugin_list_free (GList * list)
874 {
875   GList *g;
876
877   for (g = list; g; g = g->next) {
878     gst_object_unref (GST_PLUGIN (g->data));
879   }
880   g_list_free (list);
881 }