2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstregistry.c: handle registry
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.
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.
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.
24 #include <sys/types.h>
32 #include "gstregistry.h"
34 #define CLASS(registry) GST_REGISTRY_CLASS (G_OBJECT_GET_CLASS (registry))
36 /* Element signals and args */
43 static GList *_gst_registry_pool = NULL;
44 static GList *_gst_registry_pool_plugins = NULL;
46 static void gst_registry_class_init (GstRegistryClass *klass);
47 static void gst_registry_init (GstRegistry *registry);
49 static GObjectClass *parent_class = NULL;
50 static guint gst_registry_signals[LAST_SIGNAL] = { 0 };
53 gst_registry_get_type (void)
55 static GType registry_type = 0;
58 static const GTypeInfo registry_info = {
59 sizeof (GstRegistryClass),
62 (GClassInitFunc) gst_registry_class_init,
67 (GInstanceInitFunc) gst_registry_init,
70 registry_type = g_type_register_static (G_TYPE_OBJECT, "GstRegistry",
71 ®istry_info, G_TYPE_FLAG_ABSTRACT);
77 gst_registry_class_init (GstRegistryClass *klass)
79 GObjectClass *gobject_class;
81 gobject_class = (GObjectClass*) klass;
83 parent_class = g_type_class_ref (G_TYPE_OBJECT);
85 gst_registry_signals[PLUGIN_ADDED] =
86 g_signal_new ("plugin_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
87 G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL, NULL,
88 gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
91 gobject_class->dispose = NULL;
95 gst_registry_init (GstRegistry *registry)
97 registry->priority = 0;
98 registry->loaded = FALSE;
99 registry->paths = NULL;
104 * @registry: the registry to load
106 * Load the given registry
108 * Returns: TRUE on success.
111 gst_registry_load (GstRegistry *registry)
113 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
115 if (CLASS (registry)->load)
116 return CLASS (registry)->load (registry);
122 * gst_registry_is_loaded:
123 * @registry: the registry to check
125 * Check if the given registry is loaded
127 * Returns: TRUE if loaded.
130 gst_registry_is_loaded (GstRegistry *registry)
132 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
134 return registry->loaded;
139 * @registry: the registry to save
141 * Save the contents of the given registry
143 * Returns: TRUE on success
146 gst_registry_save (GstRegistry *registry)
148 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
150 if (CLASS (registry)->save)
151 return CLASS (registry)->save (registry);
157 * gst_registry_rebuild:
158 * @registry: the registry to rebuild
160 * Rebuild the given registry
162 * Returns: TRUE on success
165 gst_registry_rebuild (GstRegistry *registry)
167 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
169 if (CLASS (registry)->rebuild)
170 return CLASS (registry)->rebuild (registry);
176 * gst_registry_unload:
177 * @registry: the registry to unload
179 * Unload the given registry
181 * Returns: TRUE on success
184 gst_registry_unload (GstRegistry *registry)
186 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
188 if (CLASS (registry)->unload)
189 return CLASS (registry)->unload (registry);
195 * gst_registry_add_path:
196 * @registry: the registry to add the path to
198 * Add the given pathstring to the registry. The syntax of the
199 * pathstring is specific to the registry.
202 gst_registry_add_path (GstRegistry *registry, const gchar *path)
204 g_return_if_fail (GST_IS_REGISTRY (registry));
205 g_return_if_fail (path != NULL);
207 registry->paths = g_list_append (registry->paths, g_strdup (path));
211 * gst_registry_get_path_list:
212 * @registry: the registry to get the pathlist of
214 * Get the list of paths for the given registry.
216 * Returns: A Glist of paths as strings. g_list_free after use.
219 gst_registry_get_path_list (GstRegistry *registry)
221 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
223 return g_list_copy (registry->paths);
228 free_list_strings_func (gpointer data, gpointer user_data)
234 * gst_registry_clear_paths:
235 * @registry: the registry to clear the paths of
237 * Clear the paths of the given registry
240 gst_registry_clear_paths (GstRegistry *registry)
242 g_return_if_fail (GST_IS_REGISTRY (registry));
244 g_list_foreach (registry->paths, free_list_strings_func, NULL);
245 g_list_free (registry->paths);
247 registry->paths = NULL;
251 * gst_registry_add_plugin:
252 * @registry: the registry to add the plugin to
253 * @plugin: the plugin to add
255 * Add the plugin to the registry. The plugin-added signal
258 * Returns: TRUE on success.
261 gst_registry_add_plugin (GstRegistry *registry, GstPlugin *plugin)
263 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
265 plugin->manager = registry;
266 registry->plugins = g_list_prepend (registry->plugins, plugin);
268 g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0, plugin);
274 * gst_registry_remove_plugin:
275 * @registry: the registry to remove the plugin from
276 * @plugin: the plugin to remove
278 * Remove the plugin from the registry.
281 gst_registry_remove_plugin (GstRegistry *registry, GstPlugin *plugin)
283 g_return_if_fail (GST_IS_REGISTRY (registry));
285 registry->plugins = g_list_remove (registry->plugins, plugin);
288 static GstPluginFeature*
289 gst_plugin_list_find_feature (GList *plugins, const gchar *name, GType type)
291 GstPluginFeature *feature = NULL;
294 GstPlugin *plugin = (GstPlugin *) (plugins->data);
296 feature = gst_plugin_find_feature (plugin, name, type);
300 plugins = g_list_next (plugins);
306 gst_plugin_list_find_plugin (GList *plugins, const gchar *name)
309 GstPlugin *plugin = (GstPlugin *) (plugins->data);
311 if (plugin->name && !strcmp (plugin->name, name))
314 plugins = g_list_next (plugins);
320 * gst_registry_find_plugin:
321 * @registry: the registry to search
322 * @name: the plugin name to find
324 * Find the plugin with the given name in the registry.
326 * Returns: The plugin with the given name or NULL if the plugin was not found.
329 gst_registry_find_plugin (GstRegistry *registry, const gchar *name)
331 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
332 g_return_val_if_fail (name != NULL, NULL);
334 return gst_plugin_list_find_plugin (registry->plugins, name);
338 * gst_registry_find_feature:
339 * @registry: the registry to search
340 * @name: the pluginfeature name to find
341 * @type: the pluginfeature type to find
343 * Find the pluginfeature with the given name and type in the registry.
345 * Returns: The pluginfeature with the given name and type or NULL
346 * if the plugin was not found.
349 gst_registry_find_feature (GstRegistry *registry, const gchar *name, GType type)
351 g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
352 g_return_val_if_fail (name != NULL, NULL);
354 return gst_plugin_list_find_feature (registry->plugins, name, type);
359 * gst_registry_load_plugin:
360 * @registry: the registry to load the plugin from
361 * @plugin: the plugin to load
363 * Bring the plugin from the registry into memory.
365 * Returns: a value indicating the result
368 gst_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin)
370 g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
372 if (CLASS (registry)->load_plugin)
373 return CLASS (registry)->load_plugin (registry, plugin);
375 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
379 * gst_registry_unload_plugin:
380 * @registry: the registry to unload the plugin from
381 * @plugin: the plugin to unload
383 * Unload the plugin from the given registry.
385 * Returns: a value indicating the result
388 gst_registry_unload_plugin (GstRegistry *registry, GstPlugin *plugin)
390 g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
392 if (CLASS (registry)->unload_plugin)
393 return CLASS (registry)->unload_plugin (registry, plugin);
395 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
399 * gst_registry_update_plugin:
400 * @registry: the registry to update
401 * @plugin: the plugin to update
403 * Update the plugin in the given registry.
405 * Returns: a value indicating the result
408 gst_registry_update_plugin (GstRegistry *registry, GstPlugin *plugin)
410 g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
412 if (CLASS (registry)->update_plugin)
413 return CLASS (registry)->update_plugin (registry, plugin);
415 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
419 * gst_registry_pool_list:
421 * Get a list of all registries in the pool
423 * Returns: a Glist of GstRegistries, g_list_free after use.
426 gst_registry_pool_list (void)
428 return g_list_copy (_gst_registry_pool);
432 gst_registry_compare_func (gconstpointer a, gconstpointer b)
434 return GST_REGISTRY (a)->priority - GST_REGISTRY (b)->priority;
438 * gst_registry_pool_add:
439 * @registry: the registry to add
440 * @priority: the priority of the registry
442 * Add the registry to the pool with the given priority.
445 gst_registry_pool_add (GstRegistry *registry, guint priority)
447 g_return_if_fail (GST_IS_REGISTRY (registry));
449 registry->priority = priority;
451 _gst_registry_pool = g_list_insert_sorted (_gst_registry_pool, registry, gst_registry_compare_func);
455 * gst_registry_pool_remove:
456 * @registry: the registry to remove
458 * Remove the registry from the pool.
461 gst_registry_pool_remove (GstRegistry *registry)
463 g_return_if_fail (GST_IS_REGISTRY (registry));
465 _gst_registry_pool = g_list_remove (_gst_registry_pool, registry);
469 * gst_registry_pool_add_plugin:
470 * @plugin: the plugin to add
472 * Add the plugin to the global pool of plugins.
475 gst_registry_pool_add_plugin (GstPlugin *plugin)
477 _gst_registry_pool_plugins = g_list_prepend (_gst_registry_pool_plugins, plugin);
482 * gst_registry_pool_load_all:
484 * Load all the registries in the pool. Registries with the
485 * GST_REGISTRY_DELAYED_LOADING will not be loaded.
488 gst_registry_pool_load_all (void)
490 GList *walk = _gst_registry_pool;
493 GstRegistry *registry = GST_REGISTRY (walk->data);
495 if (registry->flags & GST_REGISTRY_READABLE &&
496 !(registry->flags & GST_REGISTRY_DELAYED_LOADING)) {
497 gst_registry_load (registry);
500 walk = g_list_next (walk);
505 * gst_registry_pool_plugin_list:
507 * Get a list of all plugins in the pool.
509 * Returns: a GList of plugins, g_list_free after use.
512 gst_registry_pool_plugin_list (void)
514 GList *result = NULL;
515 GList *walk = _gst_registry_pool;
518 GstRegistry *registry = GST_REGISTRY (walk->data);
520 /* FIXME only include highest priority plugins */
521 result = g_list_concat (result, g_list_copy (registry->plugins));
523 walk = g_list_next (walk);
530 * gst_registry_pool_feature_list:
531 * @type: the type of the features to list.
533 * Get a list of all pluginfeatures of the given type in the pool.
535 * Returns: a GList of pluginfeatures, g_list_free after use.
538 gst_registry_pool_feature_list (GType type)
540 GList *result = NULL;
541 GList *plugins = gst_registry_pool_plugin_list ();
544 GstPlugin *plugin = GST_PLUGIN (plugins->data);
545 GList *features = plugin->features;
548 GstPluginFeature *feature = GST_PLUGIN_FEATURE (features->data);
550 if (type == 0 || G_OBJECT_TYPE (feature) == type) {
551 result = g_list_prepend (result, feature);
553 features = g_list_next (features);
555 plugins = g_list_next (plugins);
557 result = g_list_reverse (result);
563 * gst_registry_pool_find_plugin:
564 * @name: the name of the plugin to find
566 * Get the named plugin from the registry pool
568 * Returns: The plugin with the given name or NULL if the plugin
572 gst_registry_pool_find_plugin (const gchar *name)
574 GstPlugin *result = NULL;
577 result = gst_plugin_list_find_plugin (_gst_registry_pool_plugins, name);
581 walk = _gst_registry_pool;
584 GstRegistry *registry = GST_REGISTRY (walk->data);
586 /* FIXME only include highest priority plugins */
587 result = gst_registry_find_plugin (registry, name);
591 walk = g_list_next (walk);
597 * gst_registry_pool_find_feature:
598 * @name: the name of the pluginfeature to find
599 * @type: the type of the pluginfeature to find
601 * Get the pluginfeature with the given name and type from the pool of
604 * Returns: A pluginfeature with the given name and type or NULL if the feature
608 gst_registry_pool_find_feature (const gchar *name, GType type)
610 GstPluginFeature *result = NULL;
613 result = gst_plugin_list_find_feature (_gst_registry_pool_plugins, name, type);
617 walk = _gst_registry_pool;
620 GstRegistry *registry = GST_REGISTRY (walk->data);
622 /* FIXME only include highest priority plugins */
623 result = gst_registry_find_feature (registry, name, type);
627 walk = g_list_next (walk);
633 * gst_registry_pool_get_prefered:
634 * @flags: The flags for the prefered registry
636 * Get the prefered registry with the given flags
638 * Returns: The registry with the flags.
641 gst_registry_pool_get_prefered (GstRegistryFlags flags)
643 GList *walk = _gst_registry_pool;
646 GstRegistry *registry = GST_REGISTRY (walk->data);
648 if (registry->flags & flags)
651 walk = g_list_next (walk);
658 static gchar *gst_registry_option = NULL;
660 /* save the registry specified as an option */
662 gst_registry_option_set (const gchar *registry)
664 gst_registry_option = g_strdup (registry);
668 /* decide if we're going to use the global registry or not
669 * - if root, use global
671 * - if user can write to global, use global
675 gst_registry_use_global (void)
677 /* struct stat reg_stat; */
680 if (getuid () == 0) return TRUE; /* root always uses global */
682 /* check if we can write to the global registry somehow */
683 reg = fopen (GLOBAL_REGISTRY_FILE, "a");
684 if (reg == NULL) { return FALSE; }
687 /* we can write to it, do so for kicks */
691 /* we can write to it, so now see if we can write in the dir as well */
692 if (access (GLOBAL_REGISTRY_DIR, W_OK) == 0) return TRUE;
697 /* get the data that tells us where we can write the registry
698 * Allocate, fill in the GstRegistryWrite struct according to
699 * current situation, and return it */
701 gst_registry_write_get ()
703 GstRegistryWrite *gst_reg = g_malloc (sizeof (GstRegistryWrite));
705 /* if a registry is specified on command line, use that one */
706 if (gst_registry_option)
708 /* FIXME: maybe parse the dir from file ? */
710 gst_reg->file = gst_registry_option;
711 /* we cannot use the temp dir since the move needs to be on same device */
712 gst_reg->tmp_file = g_strdup_printf ("%s.tmp", gst_registry_option);
714 else if (g_getenv ("GST_REGISTRY"))
717 gst_reg->file = g_strdup (g_getenv ("GST_REGISTRY"));
718 gst_reg->tmp_file = g_strdup_printf ("%s.tmp", g_getenv ("GST_REGISTRY"));
722 if (gst_registry_use_global ())
724 gst_reg->dir = g_strdup (GLOBAL_REGISTRY_DIR);
725 gst_reg->file = g_strdup (GLOBAL_REGISTRY_FILE);
726 gst_reg->tmp_file = g_strdup (GLOBAL_REGISTRY_FILE_TMP);
730 gchar *homedir = (gchar *) g_get_home_dir ();
732 gst_reg->dir = g_strjoin ("/", homedir, LOCAL_REGISTRY_DIR, NULL);
733 gst_reg->file = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
734 gst_reg->tmp_file = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE_TMP, NULL);
740 /* fill in the GstRegistryRead struct according to current situation */
742 gst_registry_read_get ()
744 GstRegistryRead *gst_reg = g_new0 (GstRegistryRead, 1);
746 /* if a registry is specified on command line, use that one */
747 if (gst_registry_option)
749 /* FIXME: maybe parse the dir from file ? */
750 gst_reg->local_reg = NULL;
751 gst_reg->global_reg = gst_registry_option;
753 else if (g_getenv ("GST_REGISTRY"))
755 gst_reg->local_reg = NULL;
756 gst_reg->global_reg = g_strdup (g_getenv ("GST_REGISTRY"));
760 gchar *homedir = (gchar *) g_get_home_dir ();
761 gst_reg->local_reg = g_strjoin ("/", homedir, LOCAL_REGISTRY_FILE, NULL);
762 if (g_file_test (gst_reg->local_reg, G_FILE_TEST_EXISTS) == FALSE)
764 /* it does not exist, so don't read from it */
765 g_free (gst_reg->local_reg);
766 gst_reg->local_reg = NULL;
768 gst_reg->global_reg = g_strdup (GLOBAL_REGISTRY_FILE);