- Removed unused locking from the cothreads
[platform/upstream/gstreamer.git] / gst / gstregistry.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstregistry.c: handle registry
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 #include <glib.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "gstinfo.h"
32 #include "gstregistry.h"
33 #include "gstlog.h"
34 #include "gstmarshal.h"
35
36 #define CLASS(registry)  GST_REGISTRY_CLASS (G_OBJECT_GET_CLASS (registry))
37
38 /* Element signals and args */
39 enum {
40   PLUGIN_ADDED,
41   LAST_SIGNAL
42 };
43
44
45 static GList *_gst_registry_pool = NULL;
46 static GList *_gst_registry_pool_plugins = NULL;
47
48 static void             gst_registry_class_init           (GstRegistryClass *klass);
49 static void             gst_registry_init                 (GstRegistry *registry);
50
51 static GObjectClass *parent_class = NULL;
52 static guint gst_registry_signals[LAST_SIGNAL] = { 0 }; 
53
54 GType
55 gst_registry_get_type (void)
56 {
57   static GType registry_type = 0;
58
59   if (!registry_type) {
60     static const GTypeInfo registry_info = {
61       sizeof (GstRegistryClass),
62       NULL,
63       NULL,
64       (GClassInitFunc) gst_registry_class_init,
65       NULL,
66       NULL,
67       sizeof (GstRegistry),
68       32,
69       (GInstanceInitFunc) gst_registry_init,
70       NULL
71     };
72     registry_type = g_type_register_static (G_TYPE_OBJECT, "GstRegistry",
73                                             &registry_info, G_TYPE_FLAG_ABSTRACT);
74   }
75   return registry_type;
76 }
77
78 static void
79 gst_registry_class_init (GstRegistryClass *klass)
80 {
81   GObjectClass *gobject_class;
82
83   gobject_class = (GObjectClass*) klass;
84
85   parent_class = g_type_class_ref (G_TYPE_OBJECT);
86
87   gst_registry_signals[PLUGIN_ADDED] =
88     g_signal_new ("plugin_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
89                   G_STRUCT_OFFSET (GstRegistryClass, plugin_added), NULL, NULL,
90                   gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
91                   G_TYPE_POINTER);
92
93   gobject_class->dispose = NULL;
94 }
95
96 static void
97 gst_registry_init (GstRegistry *registry)
98 {
99   registry->priority = 0;
100   registry->loaded = FALSE;
101   registry->paths = NULL;
102 }
103
104 /**
105  * gst_registry_load:
106  * @registry: the registry to load
107  *
108  * Load the given registry
109  *
110  * Returns: TRUE on success.
111  */
112 gboolean
113 gst_registry_load (GstRegistry *registry)
114 {
115   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
116
117   if (CLASS (registry)->load)
118     return CLASS (registry)->load (registry);
119
120   return FALSE;
121 }
122
123 /**
124  * gst_registry_is_loaded:
125  * @registry: the registry to check
126  *
127  * Check if the given registry is loaded
128  *
129  * Returns: TRUE if loaded.
130  */
131 gboolean
132 gst_registry_is_loaded (GstRegistry *registry)
133 {
134   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
135
136   return registry->loaded;
137 }
138
139 /**
140  * gst_registry_save:
141  * @registry: the registry to save
142  *
143  * Save the contents of the given registry
144  *
145  * Returns: TRUE on success
146  */
147 gboolean
148 gst_registry_save (GstRegistry *registry)
149 {
150   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
151
152   if (CLASS (registry)->save)
153     return CLASS (registry)->save (registry);
154
155   return FALSE;
156 }
157
158 /**
159  * gst_registry_rebuild:
160  * @registry: the registry to rebuild
161  *
162  * Rebuild the given registry
163  *
164  * Returns: TRUE on success
165  */
166 gboolean
167 gst_registry_rebuild (GstRegistry *registry)
168 {
169   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
170
171   if (CLASS (registry)->rebuild)
172     return CLASS (registry)->rebuild (registry);
173
174   return FALSE;
175 }
176
177 /**
178  * gst_registry_unload:
179  * @registry: the registry to unload
180  *
181  * Unload the given registry
182  *
183  * Returns: TRUE on success
184  */
185 gboolean
186 gst_registry_unload (GstRegistry *registry)
187 {
188   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
189
190   if (CLASS (registry)->unload)
191     return CLASS (registry)->unload (registry);
192
193   return FALSE;
194 }
195
196 /**
197  * gst_registry_add_path:
198  * @registry: the registry to add the path to
199  * @path: the path to add to the registry 
200  *
201  * Add the given path to the registry. The syntax of the
202  * path is specific to the registry. If the path has already been
203  * added, do nothing.
204  */
205 void
206 gst_registry_add_path (GstRegistry *registry, const gchar *path)
207 {
208   GList *l;
209
210   g_return_if_fail (GST_IS_REGISTRY (registry));
211   g_return_if_fail (path != NULL);
212
213   l = registry->paths;
214   while (l) {
215     if (strcmp (l->data, path) == 0)
216       return;
217
218     l = g_list_next (l);
219   }
220   
221   registry->paths = g_list_append (registry->paths, g_strdup (path));
222 }
223
224 /**
225  * gst_registry_get_path_list:
226  * @registry: the registry to get the pathlist of
227  *
228  * Get the list of paths for the given registry.
229  *
230  * Returns: A Glist of paths as strings. g_list_free after use.
231  */
232 GList*
233 gst_registry_get_path_list (GstRegistry *registry)
234 {
235   g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
236
237   return g_list_copy (registry->paths);
238 }
239
240
241 static void
242 free_list_strings_func (gpointer data, gpointer user_data)
243 {
244   g_free (data);
245 }
246
247 /**
248  * gst_registry_clear_paths:
249  * @registry: the registry to clear the paths of
250  *
251  * Clear the paths of the given registry
252  */
253 void
254 gst_registry_clear_paths (GstRegistry *registry)
255 {
256   g_return_if_fail (GST_IS_REGISTRY (registry));
257
258   g_list_foreach (registry->paths, free_list_strings_func, NULL);
259   g_list_free (registry->paths);
260
261   registry->paths = NULL;
262 }
263
264 /**
265  * gst_registry_add_plugin:
266  * @registry: the registry to add the plugin to
267  * @plugin: the plugin to add
268  *
269  * Add the plugin to the registry. The plugin-added signal 
270  * will be emitted.
271  *
272  * Returns: TRUE on success.
273  */
274 gboolean 
275 gst_registry_add_plugin (GstRegistry *registry, GstPlugin *plugin)
276 {
277   g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
278   
279   plugin->manager = registry;
280   registry->plugins = g_list_prepend (registry->plugins, plugin);
281
282   g_signal_emit (G_OBJECT (registry), gst_registry_signals[PLUGIN_ADDED], 0, plugin);
283
284   return TRUE;
285 }
286
287 /**
288  * gst_registry_remove_plugin:
289  * @registry: the registry to remove the plugin from
290  * @plugin: the plugin to remove
291  *
292  * Remove the plugin from the registry.
293  */
294 void
295 gst_registry_remove_plugin (GstRegistry *registry, GstPlugin *plugin)
296 {
297   g_return_if_fail (GST_IS_REGISTRY (registry));
298
299   registry->plugins = g_list_remove (registry->plugins, plugin);
300 }
301
302 static GstPluginFeature*
303 gst_plugin_list_find_feature (GList *plugins, const gchar *name, GType type)
304 {
305   GstPluginFeature *feature = NULL;
306
307   while (plugins) {
308     GstPlugin *plugin = (GstPlugin *) (plugins->data);
309
310     feature = gst_plugin_find_feature (plugin, name, type);
311     if (feature)
312       return feature;
313     
314     plugins = g_list_next (plugins);
315   }
316   return feature;
317 }
318
319 static GstPlugin*
320 gst_plugin_list_find_plugin (GList *plugins, const gchar *name)
321 {
322   while (plugins) {
323     GstPlugin *plugin = (GstPlugin *) (plugins->data);
324
325     if (plugin->name && !strcmp (plugin->name, name))
326       return plugin;
327     
328     plugins = g_list_next (plugins);
329   }
330   return NULL;
331 }
332
333 /**
334  * gst_registry_find_plugin:
335  * @registry: the registry to search
336  * @name: the plugin name to find
337  *
338  * Find the plugin with the given name in the registry.
339  *
340  * Returns: The plugin with the given name or NULL if the plugin was not found.
341  */
342 GstPlugin*
343 gst_registry_find_plugin (GstRegistry *registry, const gchar *name)
344 {
345   g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
346   g_return_val_if_fail (name != NULL, NULL);
347   
348   return gst_plugin_list_find_plugin (registry->plugins, name);
349 }
350
351 /**
352  * gst_registry_find_feature:
353  * @registry: the registry to search
354  * @name: the pluginfeature name to find
355  * @type: the pluginfeature type to find
356  *
357  * Find the pluginfeature with the given name and type in the registry.
358  *
359  * Returns: The pluginfeature with the given name and type or NULL 
360  * if the plugin was not found.
361  */
362 GstPluginFeature*
363 gst_registry_find_feature (GstRegistry *registry, const gchar *name, GType type)
364 {
365   g_return_val_if_fail (GST_IS_REGISTRY (registry), NULL);
366   g_return_val_if_fail (name != NULL, NULL);
367   
368   return gst_plugin_list_find_feature (registry->plugins, name, type);
369 }
370
371
372 /**
373  * gst_registry_load_plugin:
374  * @registry: the registry to load the plugin from
375  * @plugin: the plugin to load
376  *
377  * Bring the plugin from the registry into memory.
378  *
379  * Returns: a value indicating the result 
380  */
381 GstRegistryReturn
382 gst_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin)
383 {
384   g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
385
386   if (CLASS (registry)->load_plugin)
387     return CLASS (registry)->load_plugin (registry, plugin);
388
389   return GST_REGISTRY_PLUGIN_LOAD_ERROR;
390 }
391
392 /**
393  * gst_registry_unload_plugin:
394  * @registry: the registry to unload the plugin from
395  * @plugin: the plugin to unload
396  *
397  * Unload the plugin from the given registry.
398  *
399  * Returns: a value indicating the result 
400  */
401 GstRegistryReturn
402 gst_registry_unload_plugin (GstRegistry *registry, GstPlugin *plugin)
403 {
404   g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
405
406   if (CLASS (registry)->unload_plugin)
407     return CLASS (registry)->unload_plugin (registry, plugin);
408
409   return GST_REGISTRY_PLUGIN_LOAD_ERROR;
410 }
411
412 /**
413  * gst_registry_update_plugin:
414  * @registry: the registry to update
415  * @plugin: the plugin to update
416  *
417  * Update the plugin in the given registry.
418  *
419  * Returns: a value indicating the result 
420  */
421 GstRegistryReturn
422 gst_registry_update_plugin (GstRegistry *registry, GstPlugin *plugin)
423 {
424   g_return_val_if_fail (GST_IS_REGISTRY (registry), GST_REGISTRY_PLUGIN_LOAD_ERROR);
425
426   if (CLASS (registry)->update_plugin)
427     return CLASS (registry)->update_plugin (registry, plugin);
428
429   return GST_REGISTRY_PLUGIN_LOAD_ERROR;
430 }
431
432 /**
433  * gst_registry_pool_list:
434  *
435  * Get a list of all registries in the pool
436  *
437  * Returns: a Glist of GstRegistries, g_list_free after use.
438  */
439 GList*
440 gst_registry_pool_list (void)
441 {
442   return g_list_copy (_gst_registry_pool);
443 }
444
445 static gint
446 gst_registry_compare_func (gconstpointer a, gconstpointer b)
447 {
448   return GST_REGISTRY (a)->priority - GST_REGISTRY (b)->priority;
449 }
450
451 /**
452  * gst_registry_pool_add:
453  * @registry: the registry to add
454  * @priority: the priority of the registry
455  *
456  * Add the registry to the pool with the given priority.
457  */
458 void
459 gst_registry_pool_add (GstRegistry *registry, guint priority)
460 {
461   g_return_if_fail (GST_IS_REGISTRY (registry));
462
463   registry->priority = priority;
464
465   _gst_registry_pool = g_list_insert_sorted (_gst_registry_pool, registry, gst_registry_compare_func);
466 }
467
468 /**
469  * gst_registry_pool_remove:
470  * @registry: the registry to remove
471  *
472  * Remove the registry from the pool.
473  */
474 void
475 gst_registry_pool_remove (GstRegistry *registry)
476 {
477   g_return_if_fail (GST_IS_REGISTRY (registry));
478
479   _gst_registry_pool = g_list_remove (_gst_registry_pool, registry);
480 }
481
482 /**
483  * gst_registry_pool_add_plugin:
484  * @plugin: the plugin to add
485  *
486  * Add the plugin to the global pool of plugins.
487  */
488 void
489 gst_registry_pool_add_plugin (GstPlugin *plugin)
490 {
491   _gst_registry_pool_plugins = g_list_prepend (_gst_registry_pool_plugins, plugin);
492 }
493
494
495 /**
496  * gst_registry_pool_load_all:
497  *
498  * Load all the registries in the pool. Registries with the
499  * GST_REGISTRY_DELAYED_LOADING will not be loaded.
500  */
501 void
502 gst_registry_pool_load_all (void)
503 {
504   GList *walk = _gst_registry_pool;
505
506   while (walk) {
507     GstRegistry *registry = GST_REGISTRY (walk->data);
508
509     if (registry->flags & GST_REGISTRY_READABLE &&
510         !(registry->flags & GST_REGISTRY_DELAYED_LOADING)) {
511       gst_registry_load (registry);
512     }
513     
514     walk = g_list_next (walk);
515   }
516 }
517
518 /**
519  * gst_registry_pool_plugin_list:
520  *
521  * Get a list of all plugins in the pool.
522  * 
523  * Returns: a GList of plugins, g_list_free after use.
524  */
525 GList*
526 gst_registry_pool_plugin_list (void)
527 {
528   GList *result = NULL;
529   GList *walk = _gst_registry_pool;
530
531   while (walk) {
532     GstRegistry *registry = GST_REGISTRY (walk->data);
533
534     /* FIXME only include highest priority plugins */
535     result = g_list_concat (result, g_list_copy (registry->plugins));
536     
537     walk = g_list_next (walk);
538   }
539   
540   return result;
541 }
542
543 /**
544  * gst_registry_pool_feature_list:
545  * @type: the type of the features to list.
546  *
547  * Get a list of all pluginfeatures of the given type in the pool.
548  * 
549  * Returns: a GList of pluginfeatures, g_list_free after use.
550  */
551 GList*
552 gst_registry_pool_feature_list (GType type)
553 {
554   GList *result = NULL;
555   GList *plugins = gst_registry_pool_plugin_list ();
556
557   while (plugins) {
558     GstPlugin *plugin = GST_PLUGIN (plugins->data);
559     GList *features = plugin->features;
560       
561     while (features) {
562       GstPluginFeature *feature = GST_PLUGIN_FEATURE (features->data);
563
564       if (type == 0 || G_OBJECT_TYPE (feature) == type) {
565         result = g_list_prepend (result, feature);
566       }
567       features = g_list_next (features);
568     }
569     plugins = g_list_next (plugins);
570   }
571   result = g_list_reverse (result);
572   
573   return result;
574 }
575
576 /**
577  * gst_registry_pool_find_plugin:
578  * @name: the name of the plugin to find
579  *
580  * Get the named plugin from the registry pool
581  * 
582  * Returns: The plugin with the given name or NULL if the plugin 
583  * was not found.
584  */
585 GstPlugin*
586 gst_registry_pool_find_plugin (const gchar *name)
587 {
588   GstPlugin *result = NULL;
589   GList *walk;
590   
591   result =  gst_plugin_list_find_plugin (_gst_registry_pool_plugins, name);
592   if (result)
593     return result;
594
595   walk = _gst_registry_pool;
596
597   while (walk) {
598     GstRegistry *registry = GST_REGISTRY (walk->data);
599
600     /* FIXME only include highest priority plugins */
601     result = gst_registry_find_plugin (registry, name);
602     if (result)
603       return result;
604     
605     walk = g_list_next (walk);
606   }
607   return NULL;
608 }
609
610 /**
611  * gst_registry_pool_find_feature:
612  * @name: the name of the pluginfeature to find
613  * @type: the type of the pluginfeature to find
614  *
615  * Get the pluginfeature with the given name and type from the pool of
616  * registries.
617  * 
618  * Returns: A pluginfeature with the given name and type or NULL if the feature
619  * was not found.
620  */
621 GstPluginFeature*
622 gst_registry_pool_find_feature (const gchar *name, GType type)
623 {
624   GstPluginFeature *result = NULL;
625   GList *walk;
626   
627   result = gst_plugin_list_find_feature (_gst_registry_pool_plugins, name, type);
628   if (result)
629     return result;
630   
631   walk = _gst_registry_pool;
632
633   while (walk) {
634     GstRegistry *registry = GST_REGISTRY (walk->data);
635
636     /* FIXME only include highest priority plugins */
637     result = gst_registry_find_feature (registry, name, type);
638     if (result)
639       return result;
640     
641     walk = g_list_next (walk);
642   }
643   return NULL;
644 }
645
646 /**
647  * gst_registry_pool_get_prefered:
648  * @flags: The flags for the prefered registry
649  *
650  * Get the prefered registry with the given flags
651  * 
652  * Returns: The registry with the flags.
653  */
654 GstRegistry*
655 gst_registry_pool_get_prefered (GstRegistryFlags flags)
656 {
657   GList *walk = _gst_registry_pool;
658
659   while (walk) {
660     GstRegistry *registry = GST_REGISTRY (walk->data);
661
662     if (registry->flags & flags)
663       return registry;
664     
665     walk = g_list_next (walk);
666   }
667   return NULL;
668 }
669