2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstxml_registry.c: GstXMLRegistry object, support routines
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.
29 #include <sys/types.h>
35 #include <gst/gst_private.h>
36 #include <gst/gstelement.h>
37 #include <gst/gsttypefind.h>
38 #include <gst/gstscheduler.h>
39 #include <gst/gsturi.h>
40 #include <gst/gstinfo.h>
42 #include "gstxmlregistry.h"
44 #define BLOCK_SIZE 1024*10
46 #define CLASS(registry) GST_XML_REGISTRY_CLASS (G_OBJECT_GET_CLASS (registry))
56 static void gst_xml_registry_class_init (GstXMLRegistryClass *klass);
57 static void gst_xml_registry_init (GstXMLRegistry *registry);
59 static void gst_xml_registry_set_property (GObject * object, guint prop_id,
60 const GValue * value, GParamSpec * pspec);
61 static void gst_xml_registry_get_property (GObject * object, guint prop_id,
62 GValue * value, GParamSpec * pspec);
64 static gboolean gst_xml_registry_load (GstRegistry *registry);
65 static gboolean gst_xml_registry_save (GstRegistry *registry);
66 static gboolean gst_xml_registry_rebuild (GstRegistry *registry);
68 static void gst_xml_registry_get_perms_func (GstXMLRegistry *registry);
69 static void gst_xml_registry_add_path_list_func (GstXMLRegistry *registry);
70 static gboolean gst_xml_registry_open_func (GstXMLRegistry *registry, GstXMLRegistryMode mode);
71 static gboolean gst_xml_registry_load_func (GstXMLRegistry *registry, gchar *data, gssize *size);
72 static gboolean gst_xml_registry_save_func (GstXMLRegistry *registry, gchar *format, ...);
73 static gboolean gst_xml_registry_close_func (GstXMLRegistry *registry);
75 static GstRegistryReturn gst_xml_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin);
77 static void gst_xml_registry_start_element (GMarkupParseContext *context,
78 const gchar *element_name,
79 const gchar **attribute_names,
80 const gchar **attribute_values,
83 static void gst_xml_registry_end_element (GMarkupParseContext *context,
84 const gchar *element_name,
87 static void gst_xml_registry_text (GMarkupParseContext *context,
92 static void gst_xml_registry_passthrough (GMarkupParseContext *context,
93 const gchar *passthrough_text,
97 static void gst_xml_registry_error (GMarkupParseContext *context,
102 static void gst_xml_registry_paths_start_element (GMarkupParseContext *context,
103 const gchar *element_name,
104 const gchar **attribute_names,
105 const gchar **attribute_values,
108 static void gst_xml_registry_paths_end_element (GMarkupParseContext *context,
109 const gchar *element_name,
112 static void gst_xml_registry_paths_text (GMarkupParseContext *context,
118 static GstRegistryClass *parent_class = NULL;
119 /* static guint gst_xml_registry_signals[LAST_SIGNAL] = { 0 }; */
121 static const GMarkupParser
122 gst_xml_registry_parser =
124 gst_xml_registry_start_element,
125 gst_xml_registry_end_element,
126 gst_xml_registry_text,
127 gst_xml_registry_passthrough,
128 gst_xml_registry_error,
131 static const GMarkupParser
132 gst_xml_registry_paths_parser =
134 gst_xml_registry_paths_start_element,
135 gst_xml_registry_paths_end_element,
136 gst_xml_registry_paths_text,
143 gst_xml_registry_get_type (void)
145 static GType xml_registry_type = 0;
147 if (!xml_registry_type) {
148 static const GTypeInfo xml_registry_info = {
149 sizeof (GstXMLRegistryClass),
152 (GClassInitFunc) gst_xml_registry_class_init,
155 sizeof(GstXMLRegistry),
157 (GInstanceInitFunc) gst_xml_registry_init,
160 xml_registry_type = g_type_register_static (GST_TYPE_REGISTRY,
161 "GstXMLRegistry", &xml_registry_info, 0);
163 return xml_registry_type;
167 gst_xml_registry_class_init (GstXMLRegistryClass *klass)
169 GObjectClass *gobject_class;
170 GstRegistryClass *gstregistry_class;
171 GstXMLRegistryClass *gstxmlregistry_class;
173 gobject_class = (GObjectClass*)klass;
174 gstregistry_class = (GstRegistryClass*)klass;
175 gstxmlregistry_class = (GstXMLRegistryClass*)klass;
177 parent_class = g_type_class_ref (GST_TYPE_REGISTRY);
179 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_xml_registry_get_property);
180 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_xml_registry_set_property);
182 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LOCATION,
183 g_param_spec_string ("location", "Location", "Location of the registry file",
184 NULL, G_PARAM_READWRITE));
186 gstregistry_class->load = GST_DEBUG_FUNCPTR (gst_xml_registry_load);
187 gstregistry_class->save = GST_DEBUG_FUNCPTR (gst_xml_registry_save);
188 gstregistry_class->rebuild = GST_DEBUG_FUNCPTR (gst_xml_registry_rebuild);
190 gstregistry_class->load_plugin = GST_DEBUG_FUNCPTR (gst_xml_registry_load_plugin);
192 gstxmlregistry_class->get_perms_func = GST_DEBUG_FUNCPTR (gst_xml_registry_get_perms_func);
193 gstxmlregistry_class->add_path_list_func = GST_DEBUG_FUNCPTR (gst_xml_registry_add_path_list_func);
194 gstxmlregistry_class->open_func = GST_DEBUG_FUNCPTR (gst_xml_registry_open_func);
195 gstxmlregistry_class->load_func = GST_DEBUG_FUNCPTR (gst_xml_registry_load_func);
196 gstxmlregistry_class->save_func = GST_DEBUG_FUNCPTR (gst_xml_registry_save_func);
197 gstxmlregistry_class->close_func = GST_DEBUG_FUNCPTR (gst_xml_registry_close_func);
201 gst_xml_registry_init (GstXMLRegistry *registry)
203 registry->location = NULL;
204 registry->context = NULL;
205 registry->state = GST_XML_REGISTRY_NONE;
206 registry->current_plugin = NULL;
207 registry->current_feature = NULL;
208 registry->open_tags = NULL;
212 * gst_xml_registry_new:
213 * @name: the name of the registry
214 * @location: the location of the registry file
216 * Create a new xml registry with the given name and location.
218 * Returns: a new GstXMLRegistry with the given name an location.
221 gst_xml_registry_new (const gchar *name, const gchar *location)
223 GstXMLRegistry *xmlregistry;
225 xmlregistry = GST_XML_REGISTRY (g_object_new (GST_TYPE_XML_REGISTRY, NULL));
227 g_object_set (G_OBJECT (xmlregistry), "location", location, NULL);
229 GST_REGISTRY (xmlregistry)->name = g_strdup (name);
231 return GST_REGISTRY (xmlregistry);
235 gst_xml_registry_set_property (GObject* object, guint prop_id,
236 const GValue* value, GParamSpec* pspec)
238 GstXMLRegistry *registry;
240 registry = GST_XML_REGISTRY (object);
244 if (registry->open) {
245 CLASS (object)->close_func (registry);
246 g_return_if_fail (registry->open == FALSE);
249 if (registry->location)
250 g_free (registry->location);
252 registry->location = g_strdup (g_value_get_string (value));
253 GST_REGISTRY (registry)->flags = 0x0;
255 if (CLASS (object)->get_perms_func)
256 CLASS (object)->get_perms_func (registry);
258 if (CLASS (object)->add_path_list_func)
259 CLASS (object)->add_path_list_func (registry);
262 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
268 gst_xml_registry_get_property (GObject* object, guint prop_id,
269 GValue* value, GParamSpec* pspec)
271 GstXMLRegistry *registry;
273 registry = GST_XML_REGISTRY (object);
277 g_value_set_string (value, g_strdup (registry->location));
280 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285 /* this function returns the biggest of the path's mtime and ctime
286 * mtime is updated through an actual write (data)
287 * ctime is updated through changing inode information
288 * so this function returns the last time *anything* changed to this path
291 get_time(const char * path)
294 if (stat(path, &statbuf)) return 0;
295 if (statbuf.st_mtime > statbuf.st_ctime) return statbuf.st_mtime;
296 return statbuf.st_ctime;
301 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
304 make_dir (gchar *filename)
309 if (strrchr (filename, '/') == NULL)
312 dirname = g_strndup(filename, strrchr(filename, '/') - filename);
314 if (stat (dirname, &dirstat) == -1 && errno == ENOENT) {
315 if (mkdir (dirname, dirmode) != 0) {
316 if (make_dir (dirname) != TRUE) {
320 if (mkdir (dirname, dirmode) != 0)
331 gst_xml_registry_get_perms_func (GstXMLRegistry *registry)
336 /* if the dir does not exist, make it. if that can't be done, flags = 0x0.
337 if the file can be appended to, it's writable. if it can then be read,
339 After that check if it exists. */
341 if (make_dir (registry->location) != TRUE) {
342 /* we can't do anything with it, leave flags as 0x0 */
346 mod_time = get_time (registry->location);
348 if ((temp = fopen (registry->location, "a"))) {
349 GST_REGISTRY (registry)->flags |= GST_REGISTRY_WRITABLE;
353 if ((temp = fopen (registry->location, "r"))) {
354 GST_REGISTRY (registry)->flags |= GST_REGISTRY_READABLE;
358 if (g_file_test (registry->location, G_FILE_TEST_EXISTS)) {
359 GST_REGISTRY (registry)->flags |= GST_REGISTRY_EXISTS;
363 struct utimbuf utime_buf;
365 /* set the modification time back to its previous value */
366 utime_buf.actime = mod_time;
367 utime_buf.modtime = mod_time;
368 utime (registry->location, &utime_buf);
369 } else if (GST_REGISTRY (registry)->flags & GST_REGISTRY_WRITABLE) {
370 /* it did not exist before, so delete it */
371 unlink (registry->location);
376 gst_xml_registry_add_path_list_func (GstXMLRegistry *registry)
379 GMarkupParseContext *context;
382 GError *error = NULL;
384 context = g_markup_parse_context_new (&gst_xml_registry_paths_parser, 0,
387 if (! (reg = fopen (registry->location, "r"))) {
391 /* slightly allocate more as gmarkup reads too much */
392 text = g_malloc0 (BLOCK_SIZE + 32);
394 size = fread (text, 1, BLOCK_SIZE, reg);
397 g_markup_parse_context_parse (context, text, size, &error);
400 GST_ERROR ("parsing registry %s: %s\n",
401 registry->location, error->message);
407 if (registry->state == GST_XML_REGISTRY_PATHS_DONE)
410 size = fread (text, 1, BLOCK_SIZE, reg);
419 plugin_times_older_than_recurse(gchar *path, time_t regtime)
422 struct dirent *dirent;
425 time_t pathtime = get_time(path);
427 if (pathtime > regtime) {
428 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING,
429 "time for %s was %ld; more recent than registry time of %ld\n",
430 path, (long)pathtime, (long)regtime);
436 while ((dirent = readdir(dir))) {
437 /* don't want to recurse in place or backwards */
438 if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
439 pluginname = g_strjoin("/",path,dirent->d_name,NULL);
440 if (!plugin_times_older_than_recurse(pluginname , regtime)) {
454 plugin_times_older_than(GList *paths, time_t regtime)
456 /* return true iff regtime is more recent than the times of all the files
457 * in the plugin dirs.
461 GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING,
462 "comparing plugin times from %s with %ld\n",
463 (gchar *)paths->data, (long) regtime);
464 if(!plugin_times_older_than_recurse(paths->data, regtime))
466 paths = g_list_next(paths);
472 gst_xml_registry_open_func (GstXMLRegistry *registry, GstXMLRegistryMode mode)
474 GstRegistry *gst_registry;
477 gst_registry = GST_REGISTRY (registry);
478 paths = gst_registry->paths;
480 g_return_val_if_fail (registry->open == FALSE, FALSE);
482 /* if it doesn't exist, first try to build it, and check if it worked
483 * if it's not readable, return false
484 * if it's out of date, rebuild it */
485 if (mode == GST_XML_REGISTRY_READ) {
486 if (!(gst_registry->flags & GST_REGISTRY_EXISTS))
488 /* if it's not writable, then don't bother */
489 if (!(gst_registry->flags & GST_REGISTRY_WRITABLE))
491 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry isn't writable");
494 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry doesn't exist, trying to build...");
495 gst_registry_rebuild (gst_registry);
496 gst_registry_save (gst_registry);
497 /* FIXME: verify that the flags actually get updated ! */
498 if (!(gst_registry->flags & GST_REGISTRY_EXISTS))
503 /* at this point we know it exists */
504 g_return_val_if_fail (gst_registry->flags & GST_REGISTRY_READABLE, FALSE);
506 if (!plugin_times_older_than (paths, get_time (registry->location))) {
507 if (gst_registry->flags & GST_REGISTRY_WRITABLE) {
508 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry out of date, rebuilding...");
510 gst_registry_rebuild (gst_registry);
512 gst_registry_save (gst_registry);
514 if (!plugin_times_older_than (paths, get_time (registry->location))) {
515 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry still out of date, something is wrong...");
519 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "Can't write to this registry and it's out of date, ignoring it");
524 registry->regfile = fopen (registry->location, "r");
526 else if (mode == GST_XML_REGISTRY_WRITE)
528 g_return_val_if_fail (gst_registry->flags & GST_REGISTRY_WRITABLE, FALSE);
530 registry->regfile = fopen (registry->location, "w");
533 if (!registry->regfile)
536 registry->open = TRUE;
542 gst_xml_registry_load_func (GstXMLRegistry *registry, gchar *data, gssize *size)
544 *size = fread (data, 1, *size, registry->regfile);
550 gst_xml_registry_save_func (GstXMLRegistry *registry, gchar *format, ...)
554 va_start (var_args, format);
556 vfprintf (registry->regfile, format, var_args);
564 gst_xml_registry_close_func (GstXMLRegistry *registry)
566 fclose (registry->regfile);
568 registry->open = FALSE;
574 gst_xml_registry_load (GstRegistry *registry)
576 GstXMLRegistry *xmlregistry;
579 GError *error = NULL;
583 xmlregistry = GST_XML_REGISTRY (registry);
585 timer = g_timer_new();
587 xmlregistry->context = g_markup_parse_context_new (&gst_xml_registry_parser, 0, registry, NULL);
589 if (!CLASS (xmlregistry)->open_func (xmlregistry, GST_XML_REGISTRY_READ)) {
593 text = g_malloc0 (BLOCK_SIZE + 32);
596 CLASS (xmlregistry)->load_func (xmlregistry, text, &size);
599 g_markup_parse_context_parse (xmlregistry->context, text, size, &error);
602 GST_ERROR ("parsing registry: %s\n", error->message);
604 CLASS (xmlregistry)->close_func (xmlregistry);
609 CLASS (xmlregistry)->load_func (xmlregistry, text, &size);
614 g_timer_stop (timer);
616 seconds = g_timer_elapsed (timer, NULL);
617 g_timer_destroy (timer);
619 GST_INFO ( "registry: loaded %s in %f seconds\n (%s)",
620 registry->name, seconds, xmlregistry->location);
622 CLASS (xmlregistry)->close_func (xmlregistry);
628 static GstRegistryReturn
629 gst_xml_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin)
631 GError *error = NULL;
632 GstPlugin *loaded_plugin;
634 /* FIXME: add gerror support */
635 loaded_plugin = gst_plugin_load_file (plugin->filename, &error);
638 g_warning ("could not load plugin %s: %s", plugin->desc.name, error->message);
640 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
641 } else if (loaded_plugin != plugin) {
642 g_critical ("how to remove plugins?");
645 return GST_REGISTRY_OK;
649 gst_xml_registry_parse_plugin (GMarkupParseContext *context, const gchar *tag, const gchar *text,
650 gsize text_len, GstXMLRegistry *registry, GError **error)
652 GstPlugin *plugin = registry->current_plugin;
654 if (!strcmp (tag, "name")) {
655 plugin->desc.name = g_strndup (text, text_len);
657 else if (!strcmp (tag, "description")) {
658 plugin->desc.description = g_strndup (text, text_len);
660 else if (!strcmp (tag, "filename")) {
661 plugin->filename = g_strndup (text, text_len);
663 else if (!strcmp (tag, "version")) {
664 plugin->desc.version = g_strndup (text, text_len);
666 else if (!strcmp (tag, "copyright")) {
667 plugin->desc.copyright = g_strndup (text, text_len);
669 else if (!strcmp (tag, "license")) {
670 plugin->desc.license = g_strndup (text, text_len);
672 else if (!strcmp (tag, "package")) {
673 plugin->desc.package = g_strndup (text, text_len);
675 else if (!strcmp (tag, "origin")) {
676 plugin->desc.origin = g_strndup (text, text_len);
683 add_to_char_array (gchar ***array, gchar *value)
686 gchar **old = *array;
689 /* expensive, but cycles are cheap... */
692 new = g_new0 (gchar *, i + 2);
703 gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
704 gsize text_len, GstXMLRegistry *registry, GError **error)
706 GstElementFactory *factory = GST_ELEMENT_FACTORY (registry->current_feature);
708 if (!strcmp (tag, "name")) {
709 gchar *name = g_strndup (text, text_len);
710 gst_plugin_feature_set_name (registry->current_feature, name);
713 else if (!strcmp (tag, "longname")) {
714 g_free (factory->details.longname);
715 factory->details.longname = g_strndup (text, text_len);
717 else if (!strcmp(tag, "class")) {
718 g_free (factory->details.klass);
719 factory->details.klass = g_strndup (text, text_len);
721 else if (!strcmp(tag, "description")) {
722 g_free (factory->details.description);
723 factory->details.description = g_strndup (text, text_len);
725 else if (!strcmp(tag, "author")) {
726 g_free (factory->details.author);
727 factory->details.author = g_strndup (text, text_len);
729 else if (!strcmp(tag, "rank")) {
733 rank = strtol (text, &ret, 0);
734 if (ret == text + text_len) {
735 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
737 } else if (!strcmp (tag, "uri_type")) {
738 if (strncasecmp (text, "sink", 4) == 0) {
739 factory->uri_type = GST_URI_SINK;
740 } else if (strncasecmp (text, "source", 5) == 0) {
741 factory->uri_type = GST_URI_SRC;
743 } else if (!strcmp (tag, "uri_protocol")) {
744 add_to_char_array (&factory->uri_protocols, g_strndup (text, text_len));
746 else if (!strcmp(tag, "interface")) {
747 gchar *tmp = g_strndup (text, text_len);
748 __gst_element_factory_add_interface (factory, tmp);
756 gst_xml_registry_parse_type_find_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
757 gsize text_len, GstXMLRegistry *registry, GError **error)
759 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (registry->current_feature);
761 if (!strcmp (tag, "name")) {
762 registry->current_feature->name = g_strndup (text, text_len);
764 else if (!strcmp(tag, "rank")) {
767 rank = strtol (text, &ret, 0);
768 if (ret == text + text_len) {
769 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
773 else if (!strcmp (tag, "caps")) {
774 factory->caps = g_strndup (text, text_len);
776 else if (!strcmp(tag, "extension")) {
777 add_to_char_array (&factory->extensions, g_strndup (text, text_len));
784 gst_xml_registry_parse_scheduler_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
785 gsize text_len, GstXMLRegistry *registry, GError **error)
787 GstSchedulerFactory *factory = GST_SCHEDULER_FACTORY (registry->current_feature);
789 if (!strcmp (tag, "name")) {
790 registry->current_feature->name = g_strndup (text, text_len);
792 else if (!strcmp (tag, "longdesc")) {
793 factory->longdesc = g_strndup (text, text_len);
799 gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
800 gsize text_len, GstXMLRegistry *registry, GError **error)
802 GstIndexFactory *factory = GST_INDEX_FACTORY (registry->current_feature);
804 if (!strcmp (tag, "name")) {
805 registry->current_feature->name = g_strndup (text, text_len);
807 else if (!strcmp (tag, "longdesc")) {
808 factory->longdesc = g_strndup (text, text_len);
814 gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
815 gsize text_len, GstXMLRegistry *registry, GError **error)
817 if (!strcmp (tag, "nametemplate")) {
818 registry->name_template = g_strndup (text, text_len);
820 else if (!strcmp (tag, "direction")) {
821 if (!strncmp(text, "sink", text_len)) {
822 registry->direction = GST_PAD_SINK;
824 else if (!strncmp(text, "src", text_len)) {
825 registry->direction = GST_PAD_SRC;
828 else if (!strcmp (tag, "presence")) {
829 if (!strncmp(text, "always", text_len)) {
830 registry->presence = GST_PAD_ALWAYS;
832 else if (!strncmp(text, "sometimes", text_len)) {
833 registry->presence = GST_PAD_SOMETIMES;
835 else if (!strncmp(text, "request", text_len)) {
836 registry->presence = GST_PAD_REQUEST;
843 gst_xml_registry_parse_capscomp (GMarkupParseContext *context, const gchar *tag, const gchar *text,
844 gsize text_len, GstXMLRegistry *registry, GError **error)
846 if (!strcmp (tag, "name")) {
847 registry->caps_name = g_strndup (text, text_len);
849 else if (!strcmp (tag, "type")) {
850 registry->caps_mime = g_strndup (text, text_len);
856 find_index_for (const gchar *name, const gchar **attribute_names)
860 while (attribute_names[i]) {
861 if (!strcmp (attribute_names[i], name))
869 gst_xml_registry_start_element (GMarkupParseContext *context,
870 const gchar *element_name,
871 const gchar **attribute_names,
872 const gchar **attribute_values,
873 gpointer user_data, GError **error)
875 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
877 xmlregistry->open_tags = g_list_prepend (xmlregistry->open_tags,
878 g_strdup (element_name));
880 switch (xmlregistry->state) {
881 case GST_XML_REGISTRY_NONE:
882 if (!strcmp (element_name, "GST-PluginRegistry")) {
883 xmlregistry->state = GST_XML_REGISTRY_TOP;
886 case GST_XML_REGISTRY_TOP:
887 if (!strncmp (element_name, "plugin", 6)) {
888 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
889 xmlregistry->parser = gst_xml_registry_parse_plugin;
890 xmlregistry->current_plugin = (GstPlugin *) g_new0 (GstPlugin, 1);
893 case GST_XML_REGISTRY_PLUGIN:
894 if (!strncmp (element_name, "feature", 7)) {
896 GstPluginFeature *feature = NULL;
898 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
900 while (attribute_names[i]) {
901 if (!strncmp (attribute_names[i], "typename", 8)) {
902 feature = GST_PLUGIN_FEATURE (g_object_new (g_type_from_name (attribute_values[i]), NULL));
908 xmlregistry->current_feature = feature;
910 if (GST_IS_ELEMENT_FACTORY (feature)) {
911 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
913 factory->padtemplates = NULL;
914 xmlregistry->parser = gst_xml_registry_parse_element_factory;
917 else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
918 xmlregistry->parser = gst_xml_registry_parse_type_find_factory;
920 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
921 xmlregistry->parser = gst_xml_registry_parse_scheduler_factory;
922 GST_SCHEDULER_FACTORY (feature)->type = 0;
924 else if (GST_IS_INDEX_FACTORY (feature)) {
925 xmlregistry->parser = gst_xml_registry_parse_index_factory;
928 g_warning ("unkown feature type");
933 case GST_XML_REGISTRY_FEATURE:
934 if (!strncmp (element_name, "padtemplate", 11)) {
935 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
936 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
937 xmlregistry->name_template = NULL;
938 xmlregistry->direction = 0;
939 xmlregistry->presence = 0;
940 xmlregistry->caps = NULL;
943 case GST_XML_REGISTRY_PADTEMPLATE:
944 if (!strncmp (element_name, "caps", 4)) {
945 xmlregistry->state = GST_XML_REGISTRY_CAPS;
946 xmlregistry->parser = NULL;
949 case GST_XML_REGISTRY_CAPS:
950 if (!strncmp (element_name, "capscomp", 8)) {
951 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
952 xmlregistry->parser = gst_xml_registry_parse_capscomp;
955 case GST_XML_REGISTRY_CAPSCOMP:
956 if (!strncmp (element_name, "properties", 10)) {
957 xmlregistry->state = GST_XML_REGISTRY_PROPERTIES;
958 xmlregistry->parser = NULL;
959 xmlregistry->props = gst_props_empty_new ();
962 case GST_XML_REGISTRY_PROPERTIES:
965 GstPropsEntry *entry = NULL;
967 name_index = find_index_for ("name", attribute_names);
971 if (!strncmp (element_name, "list", 4)) {
972 xmlregistry->in_list = TRUE;
973 xmlregistry->list_name = g_strdup (attribute_values[name_index]);
976 if (!strncmp (element_name, "int", 3)) {
980 if ((index = find_index_for ("value", attribute_names)) < 0)
982 sscanf (attribute_values[index], "%d", &value);
984 entry = gst_props_entry_new (attribute_values[name_index],
985 GST_PROPS_INT (value));
987 else if (!strncmp (element_name, "range", 5)) {
989 gint min_idx, max_idx;
991 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
993 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
995 sscanf (attribute_values[min_idx], "%d", &min);
996 sscanf (attribute_values[max_idx], "%d", &max);
998 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_INT_RANGE (min, max));
1000 else if (!strncmp (element_name, "float", 5)) {
1004 if ((index = find_index_for ("value", attribute_names)) < 0)
1006 sscanf (attribute_values[index], "%f", &value);
1008 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT (value));
1010 else if (!strncmp (element_name, "floatrange", 10)) {
1012 gint min_idx, max_idx;
1014 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
1016 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
1018 sscanf (attribute_values[min_idx], "%f", &min);
1019 sscanf (attribute_values[max_idx], "%f", &max);
1021 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT_RANGE (min, max));
1023 else if (!strncmp (element_name, "boolean", 7)) {
1024 gboolean value = TRUE;
1027 if ((index = find_index_for ("value", attribute_names)) < 0)
1029 if (!strcmp (attribute_values[index], "false"))
1032 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_BOOLEAN (value));
1034 else if (!strncmp (element_name, "fourcc", 6)) {
1038 if ((index = find_index_for ("hexvalue", attribute_names)) < 0)
1040 sscanf (attribute_values[index], "%08x", &value);
1042 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FOURCC (value));
1044 else if (!strncmp (element_name, "string", 6)) {
1047 if ((index = find_index_for ("value", attribute_names)) < 0)
1050 entry = gst_props_entry_new (attribute_values[name_index],
1051 GST_PROPS_STRING (attribute_values[index]));
1053 /* add property to list or parent */
1055 if (xmlregistry->in_list)
1056 xmlregistry->entry_list = g_list_prepend (xmlregistry->entry_list, entry);
1058 gst_props_add_entry (xmlregistry->props, entry);
1068 gst_xml_registry_end_element (GMarkupParseContext *context,
1069 const gchar *element_name,
1070 gpointer user_data, GError **error)
1072 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1073 gchar *open_tag = (gchar *)xmlregistry->open_tags->data;
1075 xmlregistry->open_tags = g_list_remove (xmlregistry->open_tags, open_tag);
1078 switch (xmlregistry->state) {
1079 case GST_XML_REGISTRY_TOP:
1080 if (!strcmp (element_name, "GST-PluginRegistry")) {
1081 xmlregistry->state = GST_XML_REGISTRY_NONE;
1084 case GST_XML_REGISTRY_PLUGIN:
1085 if (!strcmp (element_name, "plugin")) {
1086 xmlregistry->state = GST_XML_REGISTRY_TOP;
1087 xmlregistry->parser = NULL;
1088 gst_registry_add_plugin (GST_REGISTRY (xmlregistry), xmlregistry->current_plugin);
1091 case GST_XML_REGISTRY_FEATURE:
1092 if (!strcmp (element_name, "feature")) {
1093 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
1094 xmlregistry->parser = gst_xml_registry_parse_plugin;
1095 gst_plugin_add_feature (xmlregistry->current_plugin, xmlregistry->current_feature);
1096 xmlregistry->current_feature = NULL;
1099 case GST_XML_REGISTRY_PADTEMPLATE:
1100 if (!strcmp (element_name, "padtemplate")) {
1101 GstPadTemplate *template;
1103 template = gst_pad_template_new (xmlregistry->name_template,
1104 xmlregistry->direction,
1105 xmlregistry->presence,
1106 xmlregistry->caps, NULL);
1108 g_free (xmlregistry->name_template);
1109 xmlregistry->name_template = NULL;
1110 xmlregistry->caps = NULL;
1112 __gst_element_factory_add_pad_template (GST_ELEMENT_FACTORY (xmlregistry->current_feature),
1114 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
1115 xmlregistry->parser = gst_xml_registry_parse_element_factory;
1118 case GST_XML_REGISTRY_CAPS:
1119 if (!strcmp (element_name, "caps")) {
1120 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
1121 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1124 case GST_XML_REGISTRY_CAPSCOMP:
1125 if (!strcmp (element_name, "capscomp")) {
1128 xmlregistry->state = GST_XML_REGISTRY_CAPS;
1129 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1131 caps = gst_caps_new (xmlregistry->caps_name, xmlregistry->caps_mime, xmlregistry->props);
1132 g_free (xmlregistry->caps_mime);
1133 g_free (xmlregistry->caps_name);
1135 xmlregistry->caps = gst_caps_append (xmlregistry->caps, caps);
1136 xmlregistry->props = NULL;
1139 case GST_XML_REGISTRY_PROPERTIES:
1140 if (!strncmp (element_name, "list", 4)) {
1141 GstPropsEntry *entry;
1143 xmlregistry->entry_list = g_list_reverse (xmlregistry->entry_list);
1145 entry = gst_props_entry_new (xmlregistry->list_name,
1146 GST_PROPS_GLIST (xmlregistry->entry_list));
1148 gst_props_add_entry (xmlregistry->props, entry);
1149 g_list_free (xmlregistry->entry_list);
1150 g_free (xmlregistry->list_name);
1152 xmlregistry->entry_list = NULL;
1153 xmlregistry->list_name = NULL;
1154 xmlregistry->in_list = FALSE;
1156 else if (!strcmp (element_name, "properties")) {
1157 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
1158 xmlregistry->parser = NULL;
1167 gst_xml_registry_text (GMarkupParseContext *context, const gchar *text,
1168 gsize text_len, gpointer user_data, GError **error)
1170 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1173 if (xmlregistry->open_tags) {
1174 open_tag = (gchar *)xmlregistry->open_tags->data;
1176 if (!strcmp (open_tag, "plugin-path")) {
1177 //gst_plugin_add_path (g_strndup (text, text_len));
1179 else if (xmlregistry->parser) {
1180 xmlregistry->parser (context, open_tag, text, text_len, xmlregistry, error);
1186 gst_xml_registry_passthrough (GMarkupParseContext *context, const gchar *passthrough_text,
1187 gsize text_len, gpointer user_data, GError **error)
1192 gst_xml_registry_error (GMarkupParseContext *context, GError *error,
1195 GST_ERROR ("%s\n", error->message);
1199 gst_xml_registry_paths_start_element (GMarkupParseContext *context,
1200 const gchar *element_name,
1201 const gchar **attribute_names,
1202 const gchar **attribute_values,
1203 gpointer user_data, GError **error)
1205 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1207 switch (xmlregistry->state) {
1208 case GST_XML_REGISTRY_NONE:
1209 if (!strcmp (element_name, "GST-PluginRegistry")) {
1210 xmlregistry->state = GST_XML_REGISTRY_TOP;
1213 case GST_XML_REGISTRY_TOP:
1214 if (!strcmp (element_name, "gst-registry-paths")) {
1215 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1218 case GST_XML_REGISTRY_PATHS:
1219 if (!strcmp (element_name, "path")) {
1220 xmlregistry->state = GST_XML_REGISTRY_PATH;
1229 gst_xml_registry_paths_end_element (GMarkupParseContext *context,
1230 const gchar *element_name,
1231 gpointer user_data, GError **error)
1233 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1235 switch (xmlregistry->state) {
1236 case GST_XML_REGISTRY_PATH:
1237 if (!strcmp (element_name, "path")) {
1238 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1241 case GST_XML_REGISTRY_PATHS:
1242 if (!strcmp (element_name, "gst-plugin-paths")) {
1243 xmlregistry->state = GST_XML_REGISTRY_PATHS_DONE;
1252 gst_xml_registry_paths_text (GMarkupParseContext *context, const gchar *text,
1253 gsize text_len, gpointer user_data, GError **error)
1255 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1257 if (xmlregistry->state == GST_XML_REGISTRY_PATH)
1258 gst_registry_add_path (GST_REGISTRY (xmlregistry), g_strndup (text, text_len));
1264 #define PUT_ESCAPED(tag,value) \
1266 const gchar *toconv = value; \
1268 gchar *v = g_markup_escape_text (toconv, strlen (toconv)); \
1269 CLASS (xmlregistry)->save_func (xmlregistry, "<%s>%s</%s>\n", tag, v, tag); \
1273 #define PUT_ESCAPED_INT(tag,value) \
1275 gchar *save = g_strdup_printf ("%ld", (glong) value); \
1276 CLASS (xmlregistry)->save_func (xmlregistry, "<%s>%s</%s>\n", tag, save, tag); \
1282 gst_xml_registry_save_props_func (GstPropsEntry *entry,
1283 GstXMLRegistry *xmlregistry)
1287 name = gst_props_entry_get_name (entry);
1289 switch (gst_props_entry_get_props_type (entry)) {
1290 case GST_PROPS_INT_TYPE:
1293 gst_props_entry_get_int (entry, &value);
1294 CLASS (xmlregistry)->save_func (xmlregistry, "<int name=\"%s\" value=\"%d\"/>\n", name, value);
1297 case GST_PROPS_INT_RANGE_TYPE:
1300 gst_props_entry_get_int_range (entry, &min, &max);
1301 CLASS (xmlregistry)->save_func (xmlregistry, "<range name=\"%s\" min=\"%d\" max=\"%d\"/>\n", name, min, max);
1304 case GST_PROPS_FLOAT_TYPE:
1307 gst_props_entry_get_float (entry, &value);
1308 CLASS (xmlregistry)->save_func (xmlregistry, "<float name=\"%s\" value=\"%f\"/>\n", name, value);
1311 case GST_PROPS_FLOAT_RANGE_TYPE:
1314 gst_props_entry_get_float_range (entry, &min, &max);
1315 CLASS (xmlregistry)->save_func (xmlregistry, "<floatrange name=\"%s\" min=\"%f\" max=\"%f\"/>\n", name, min, max);
1318 case GST_PROPS_FOURCC_TYPE:
1321 gst_props_entry_get_fourcc_int (entry, &fourcc);
1322 CLASS (xmlregistry)->save_func (xmlregistry, "<!-- "GST_FOURCC_FORMAT" -->\n",
1323 GST_FOURCC_ARGS (fourcc));
1324 CLASS (xmlregistry)->save_func (xmlregistry, "<fourcc name=\"%s\" hexvalue=\"%08x\"/>\n", name, fourcc);
1327 case GST_PROPS_BOOLEAN_TYPE:
1330 gst_props_entry_get_boolean (entry, &value);
1331 CLASS (xmlregistry)->save_func (xmlregistry, "<boolean name=\"%s\" value=\"%s\"/>\n", name, (value ? "true" : "false"));
1334 case GST_PROPS_STRING_TYPE:
1337 gst_props_entry_get_string (entry, &value);
1338 CLASS (xmlregistry)->save_func (xmlregistry, "<string name=\"%s\" value=\"%s\"/>\n", name, value);
1342 g_warning ("trying to save unknown property type %d", gst_props_entry_get_props_type (entry));
1349 gst_xml_registry_save_props (GstXMLRegistry *xmlregistry, GstProps *props)
1353 proplist = props->properties;
1356 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
1358 switch (gst_props_entry_get_props_type (entry)) {
1359 case GST_PROPS_LIST_TYPE:
1363 gst_props_entry_get_list (entry, &list);
1365 CLASS (xmlregistry)->save_func (xmlregistry, "<list name=\"%s\">\n", gst_props_entry_get_name (entry));
1366 g_list_foreach ((GList *)list, (GFunc) gst_xml_registry_save_props_func, xmlregistry);
1367 CLASS (xmlregistry)->save_func (xmlregistry, "</list>\n");
1371 gst_xml_registry_save_props_func (entry, xmlregistry);
1374 proplist = g_list_next (proplist);
1380 gst_xml_registry_save_caps (GstXMLRegistry *xmlregistry, GstCaps *caps)
1383 CLASS (xmlregistry)->save_func (xmlregistry, "<capscomp>\n");
1384 PUT_ESCAPED ("name", caps->name);
1385 PUT_ESCAPED ("type", gst_caps_get_mime (caps));
1387 if (caps->properties) {
1388 CLASS (xmlregistry)->save_func (xmlregistry, "<properties>\n");
1389 gst_xml_registry_save_props (xmlregistry, caps->properties);
1390 CLASS (xmlregistry)->save_func (xmlregistry, "</properties>\n");
1392 CLASS (xmlregistry)->save_func (xmlregistry, "</capscomp>\n");
1399 gst_xml_registry_save_pad_template (GstXMLRegistry *xmlregistry, GstPadTemplate *template)
1403 PUT_ESCAPED ("nametemplate", template->name_template);
1404 CLASS (xmlregistry)->save_func (xmlregistry, "<direction>%s</direction>\n", (template->direction == GST_PAD_SINK? "sink":"src"));
1406 switch (template->presence) {
1407 case GST_PAD_ALWAYS:
1408 presence = "always";
1410 case GST_PAD_SOMETIMES:
1411 presence = "sometimes";
1413 case GST_PAD_REQUEST:
1414 presence = "request";
1417 presence = "unknown";
1420 CLASS (xmlregistry)->save_func (xmlregistry, "<presence>%s</presence>\n", presence);
1422 if (GST_PAD_TEMPLATE_CAPS (template)) {
1423 CLASS (xmlregistry)->save_func (xmlregistry, "<caps>\n");
1424 gst_xml_registry_save_caps (xmlregistry, GST_PAD_TEMPLATE_CAPS (template));
1425 CLASS (xmlregistry)->save_func (xmlregistry, "</caps>\n");
1431 gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *feature)
1433 PUT_ESCAPED ("name", feature->name);
1435 if (feature->rank > 0) {
1436 gint rank = feature->rank;
1437 CLASS (xmlregistry)->save_func (xmlregistry, "<rank>%d</rank>\n", rank);
1440 if (GST_IS_ELEMENT_FACTORY (feature)) {
1441 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
1444 PUT_ESCAPED ("longname", factory->details.longname);
1445 PUT_ESCAPED ("class", factory->details.klass);
1446 PUT_ESCAPED ("description", factory->details.description);
1447 PUT_ESCAPED ("author", factory->details.author);
1449 walk = factory->padtemplates;
1452 GstPadTemplate *template = GST_PAD_TEMPLATE (walk->data);
1454 CLASS (xmlregistry)->save_func (xmlregistry, "<padtemplate>\n");
1455 gst_xml_registry_save_pad_template (xmlregistry, template);
1456 CLASS (xmlregistry)->save_func (xmlregistry, "</padtemplate>\n");
1458 walk = g_list_next (walk);
1461 walk = factory->interfaces;
1463 PUT_ESCAPED ("interface", (gchar *) walk->data);
1464 walk = g_list_next (walk);
1467 if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
1470 PUT_ESCAPED ("uri_type", factory->uri_type == GST_URI_SINK ? "sink" : "source");
1471 g_assert (factory->uri_protocols);
1472 protocol = factory->uri_protocols;
1474 PUT_ESCAPED ("uri_protocol", *protocol);
1479 else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
1480 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
1483 if (factory->caps) {
1484 CLASS (xmlregistry)->save_func (xmlregistry, "<caps>\n");
1485 gst_xml_registry_save_caps (xmlregistry, factory->caps);
1486 CLASS (xmlregistry)->save_func (xmlregistry, "</caps>\n");
1488 if (factory->extensions) {
1489 while (factory->extensions[i]) {
1490 PUT_ESCAPED ("extension", factory->extensions[i]);
1495 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
1496 PUT_ESCAPED ("longdesc", GST_SCHEDULER_FACTORY (feature)->longdesc);
1498 else if (GST_IS_INDEX_FACTORY (feature)) {
1499 PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
1505 gst_xml_registry_save_plugin (GstXMLRegistry *xmlregistry, GstPlugin *plugin)
1509 PUT_ESCAPED ("name", plugin->desc.name);
1510 PUT_ESCAPED ("description", plugin->desc.description);
1511 PUT_ESCAPED ("filename", plugin->filename);
1512 PUT_ESCAPED ("version", plugin->desc.version);
1513 PUT_ESCAPED ("license", plugin->desc.license);
1514 PUT_ESCAPED ("copyright", plugin->desc.copyright);
1515 PUT_ESCAPED ("package", plugin->desc.package);
1516 PUT_ESCAPED ("origin", plugin->desc.origin);
1518 walk = plugin->features;
1521 GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
1523 CLASS (xmlregistry)->save_func (xmlregistry, "<feature typename=\"%s\">\n", g_type_name (G_OBJECT_TYPE (feature)));
1524 gst_xml_registry_save_feature (xmlregistry, feature);
1525 CLASS (xmlregistry)->save_func (xmlregistry, "</feature>\n");
1527 walk = g_list_next (walk);
1534 gst_xml_registry_save (GstRegistry *registry)
1537 GstXMLRegistry *xmlregistry;
1539 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
1540 g_return_val_if_fail (registry->flags & GST_REGISTRY_WRITABLE, FALSE);
1542 xmlregistry = GST_XML_REGISTRY (registry);
1544 if (!CLASS (xmlregistry)->open_func (xmlregistry, GST_XML_REGISTRY_WRITE)) {
1548 CLASS (xmlregistry)->save_func (xmlregistry, "<?xml version=\"1.0\"?>\n");
1549 CLASS (xmlregistry)->save_func (xmlregistry, "<GST-PluginRegistry>\n");
1551 walk = g_list_last (gst_registry_get_path_list (GST_REGISTRY (registry)));
1553 CLASS (xmlregistry)->save_func (xmlregistry, "<gst-plugin-paths>\n");
1555 CLASS (xmlregistry)->save_func (xmlregistry, "<path>");
1556 CLASS (xmlregistry)->save_func (xmlregistry, (gchar*)walk->data);
1557 CLASS (xmlregistry)->save_func (xmlregistry, "</path>\n");
1558 walk = g_list_previous (walk);
1560 CLASS (xmlregistry)->save_func (xmlregistry, "</gst-plugin-paths>\n");
1562 walk = g_list_last (registry->plugins);
1565 GstPlugin *plugin = GST_PLUGIN (walk->data);
1567 CLASS (xmlregistry)->save_func (xmlregistry, "<plugin>\n");
1568 gst_xml_registry_save_plugin (xmlregistry, plugin);
1569 CLASS (xmlregistry)->save_func (xmlregistry, "</plugin>\n");
1571 walk = g_list_previous (walk);
1573 CLASS (xmlregistry)->save_func (xmlregistry, "</GST-PluginRegistry>\n");
1575 CLASS (xmlregistry)->close_func (xmlregistry);
1581 gst_xml_registry_rebuild_recurse (GstXMLRegistry *registry,
1582 const gchar *directory)
1588 dir = g_dir_open (directory, 0, NULL);
1591 const gchar *dirent;
1593 while ((dirent = g_dir_read_name (dir))) {
1596 if (*dirent == '=') {
1597 /* =build, =inst, etc. -- automake distcheck directories */
1601 dirname = g_strjoin ("/", directory, dirent, NULL);
1602 ret = g_list_concat (ret, gst_xml_registry_rebuild_recurse (registry, dirname));
1607 if ((temp = strstr (directory, G_MODULE_SUFFIX)) &&
1608 (!strcmp (temp, G_MODULE_SUFFIX))) {
1609 ret = g_list_prepend (ret, g_strdup (directory));
1617 gst_xml_registry_rebuild (GstRegistry *registry)
1619 GList *walk = NULL, *plugins = NULL, *prune = NULL;
1620 GError *error = NULL;
1623 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (registry);
1625 walk = registry->paths;
1628 gchar *path = (gchar *) walk->data;
1630 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING,
1631 "Rebuilding registry %p in directory %s...", registry, path);
1633 plugins = g_list_concat (plugins,
1634 gst_xml_registry_rebuild_recurse (xmlregistry,
1637 walk = g_list_next (walk);
1640 plugins = g_list_reverse (plugins);
1643 length = g_list_length (plugins);
1647 g_assert (walk->data);
1648 plugin = gst_plugin_load_file ((gchar *) walk->data, NULL);
1650 prune = g_list_prepend (prune, walk->data);
1651 gst_registry_add_plugin (registry, plugin);
1654 walk = g_list_next (walk);
1659 plugins = g_list_remove (plugins, walk->data);
1660 g_free (walk->data);
1661 walk = g_list_next (walk);
1663 g_list_free (prune);
1665 } while (g_list_length (plugins) != length);
1669 if ((plugin = gst_plugin_load_file ((gchar *) walk->data, &error))) {
1670 g_warning ("Bizarre behavior: plugin %s actually loaded",
1671 (gchar *) walk->data);
1672 gst_registry_add_plugin (registry, plugin);
1674 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "Plugin %s failed to load: %s",
1675 (gchar *) walk->data, error->message);
1677 g_free (walk->data);
1678 g_error_free (error);
1682 walk = g_list_next (walk);