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 | |
---|
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 void gst_plugin_desc_copy (GstPluginDesc * dest, |
---|
78 | const GstPluginDesc * src); |
---|
79 | |
---|
80 | static GstPlugin *gst_plugin_register_func (GstPlugin * plugin, |
---|
81 | GModule * module, GstPluginDesc * desc); |
---|
82 | |
---|
83 | static GstPlugin * |
---|
84 | gst_plugin_copy (GstPlugin * plugin) |
---|
85 | { |
---|
86 | return g_memdup (plugin, sizeof (*plugin)); |
---|
87 | } |
---|
88 | |
---|
89 | GType |
---|
90 | gst_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 | |
---|
102 | GQuark |
---|
103 | gst_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 | * */ |
---|
118 | void |
---|
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 | |
---|
140 | void |
---|
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 | */ |
---|
154 | static gboolean |
---|
155 | gst_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 | |
---|
169 | static gboolean |
---|
170 | gst_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 | |
---|
180 | static GstPlugin * |
---|
181 | gst_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 | */ |
---|
231 | static 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 | */ |
---|
246 | static 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 | */ |
---|
272 | static 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 |
---|
290 | static void |
---|
291 | _gst_plugin_fault_handler_restore (void) |
---|
292 | { |
---|
293 | } |
---|
294 | |
---|
295 | static void |
---|
296 | _gst_plugin_fault_handler_setup (void) |
---|
297 | { |
---|
298 | } |
---|
299 | #endif |
---|
300 | |
---|
301 | static 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 | */ |
---|
312 | gboolean |
---|
313 | gst_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 | */ |
---|
370 | GstPlugin * |
---|
371 | gst_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 | } |
---|
462 | load_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 | |
---|
469 | static void |
---|
470 | gst_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 */ |
---|
492 | static void |
---|
493 | gst_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 | */ |
---|
513 | gboolean |
---|
514 | gst_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 | */ |
---|
541 | const gchar * |
---|
542 | gst_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 | */ |
---|
557 | G_CONST_RETURN gchar * |
---|
558 | gst_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 | */ |
---|
573 | G_CONST_RETURN gchar * |
---|
574 | gst_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 | */ |
---|
589 | G_CONST_RETURN gchar * |
---|
590 | gst_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 | */ |
---|
605 | G_CONST_RETURN gchar * |
---|
606 | gst_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 | */ |
---|
621 | G_CONST_RETURN gchar * |
---|
622 | gst_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 | */ |
---|
637 | G_CONST_RETURN gchar * |
---|
638 | gst_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 | */ |
---|
655 | GModule * |
---|
656 | gst_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 | */ |
---|
671 | gboolean |
---|
672 | gst_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 | */ |
---|
692 | GList * |
---|
693 | gst_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 | |
---|
700 | typedef struct |
---|
701 | { |
---|
702 | GstPluginFeatureFilter filter; |
---|
703 | gboolean first; |
---|
704 | gpointer user_data; |
---|
705 | GList *result; |
---|
706 | } |
---|
707 | FeatureFilterData; |
---|
708 | |
---|
709 | static 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 | */ |
---|
739 | GList * |
---|
740 | gst_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 | */ |
---|
767 | gboolean |
---|
768 | gst_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 | */ |
---|
783 | GstPluginFeature * |
---|
784 | gst_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 | */ |
---|
813 | void |
---|
814 | gst_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 | */ |
---|
851 | GList * |
---|
852 | gst_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 | */ |
---|
867 | gboolean |
---|
868 | gst_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 | * "liblibrary.so". (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 | */ |
---|
897 | gboolean |
---|
898 | gst_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 | } |
---|