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/gstautoplug.h>
40 #include <gst/gsturi.h>
41 #include <gst/gstinfo.h>
43 #include "gstxmlregistry.h"
45 #define BLOCK_SIZE 1024*10
47 #define CLASS(registry) GST_XML_REGISTRY_CLASS (G_OBJECT_GET_CLASS (registry))
57 static void gst_xml_registry_class_init (GstXMLRegistryClass *klass);
58 static void gst_xml_registry_init (GstXMLRegistry *registry);
60 static void gst_xml_registry_set_property (GObject * object, guint prop_id,
61 const GValue * value, GParamSpec * pspec);
62 static void gst_xml_registry_get_property (GObject * object, guint prop_id,
63 GValue * value, GParamSpec * pspec);
65 static gboolean gst_xml_registry_load (GstRegistry *registry);
66 static gboolean gst_xml_registry_save (GstRegistry *registry);
67 static gboolean gst_xml_registry_rebuild (GstRegistry *registry);
69 static void gst_xml_registry_get_perms_func (GstXMLRegistry *registry);
70 static void gst_xml_registry_add_path_list_func (GstXMLRegistry *registry);
71 static gboolean gst_xml_registry_open_func (GstXMLRegistry *registry, GstXMLRegistryMode mode);
72 static gboolean gst_xml_registry_load_func (GstXMLRegistry *registry, gchar *data, gssize *size);
73 static gboolean gst_xml_registry_save_func (GstXMLRegistry *registry, gchar *format, ...);
74 static gboolean gst_xml_registry_close_func (GstXMLRegistry *registry);
76 static GstRegistryReturn gst_xml_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin);
78 static void gst_xml_registry_start_element (GMarkupParseContext *context,
79 const gchar *element_name,
80 const gchar **attribute_names,
81 const gchar **attribute_values,
84 static void gst_xml_registry_end_element (GMarkupParseContext *context,
85 const gchar *element_name,
88 static void gst_xml_registry_text (GMarkupParseContext *context,
93 static void gst_xml_registry_passthrough (GMarkupParseContext *context,
94 const gchar *passthrough_text,
98 static void gst_xml_registry_error (GMarkupParseContext *context,
103 static void gst_xml_registry_paths_start_element (GMarkupParseContext *context,
104 const gchar *element_name,
105 const gchar **attribute_names,
106 const gchar **attribute_values,
109 static void gst_xml_registry_paths_end_element (GMarkupParseContext *context,
110 const gchar *element_name,
113 static void gst_xml_registry_paths_text (GMarkupParseContext *context,
119 static GstRegistryClass *parent_class = NULL;
120 /* static guint gst_xml_registry_signals[LAST_SIGNAL] = { 0 }; */
122 static const GMarkupParser
123 gst_xml_registry_parser =
125 gst_xml_registry_start_element,
126 gst_xml_registry_end_element,
127 gst_xml_registry_text,
128 gst_xml_registry_passthrough,
129 gst_xml_registry_error,
132 static const GMarkupParser
133 gst_xml_registry_paths_parser =
135 gst_xml_registry_paths_start_element,
136 gst_xml_registry_paths_end_element,
137 gst_xml_registry_paths_text,
144 gst_xml_registry_get_type (void)
146 static GType xml_registry_type = 0;
148 if (!xml_registry_type) {
149 static const GTypeInfo xml_registry_info = {
150 sizeof (GstXMLRegistryClass),
153 (GClassInitFunc) gst_xml_registry_class_init,
156 sizeof(GstXMLRegistry),
158 (GInstanceInitFunc) gst_xml_registry_init,
161 xml_registry_type = g_type_register_static (GST_TYPE_REGISTRY,
162 "GstXMLRegistry", &xml_registry_info, 0);
164 return xml_registry_type;
168 gst_xml_registry_class_init (GstXMLRegistryClass *klass)
170 GObjectClass *gobject_class;
171 GstRegistryClass *gstregistry_class;
172 GstXMLRegistryClass *gstxmlregistry_class;
174 gobject_class = (GObjectClass*)klass;
175 gstregistry_class = (GstRegistryClass*)klass;
176 gstxmlregistry_class = (GstXMLRegistryClass*)klass;
178 parent_class = g_type_class_ref (GST_TYPE_REGISTRY);
180 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_xml_registry_get_property);
181 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_xml_registry_set_property);
183 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LOCATION,
184 g_param_spec_string ("location", "Location", "Location of the registry file",
185 NULL, G_PARAM_READWRITE));
187 gstregistry_class->load = GST_DEBUG_FUNCPTR (gst_xml_registry_load);
188 gstregistry_class->save = GST_DEBUG_FUNCPTR (gst_xml_registry_save);
189 gstregistry_class->rebuild = GST_DEBUG_FUNCPTR (gst_xml_registry_rebuild);
191 gstregistry_class->load_plugin = GST_DEBUG_FUNCPTR (gst_xml_registry_load_plugin);
193 gstxmlregistry_class->get_perms_func = GST_DEBUG_FUNCPTR (gst_xml_registry_get_perms_func);
194 gstxmlregistry_class->add_path_list_func = GST_DEBUG_FUNCPTR (gst_xml_registry_add_path_list_func);
195 gstxmlregistry_class->open_func = GST_DEBUG_FUNCPTR (gst_xml_registry_open_func);
196 gstxmlregistry_class->load_func = GST_DEBUG_FUNCPTR (gst_xml_registry_load_func);
197 gstxmlregistry_class->save_func = GST_DEBUG_FUNCPTR (gst_xml_registry_save_func);
198 gstxmlregistry_class->close_func = GST_DEBUG_FUNCPTR (gst_xml_registry_close_func);
202 gst_xml_registry_init (GstXMLRegistry *registry)
204 registry->location = NULL;
205 registry->context = NULL;
206 registry->state = GST_XML_REGISTRY_NONE;
207 registry->current_plugin = NULL;
208 registry->current_feature = NULL;
209 registry->open_tags = NULL;
213 * gst_xml_registry_new:
214 * @name: the name of the registry
215 * @location: the location of the registry file
217 * Create a new xml registry with the given name and location.
219 * Returns: a new GstXMLRegistry with the given name an location.
222 gst_xml_registry_new (const gchar *name, const gchar *location)
224 GstXMLRegistry *xmlregistry;
226 xmlregistry = GST_XML_REGISTRY (g_object_new (GST_TYPE_XML_REGISTRY, NULL));
228 g_object_set (G_OBJECT (xmlregistry), "location", location, NULL);
230 GST_REGISTRY (xmlregistry)->name = g_strdup (name);
232 return GST_REGISTRY (xmlregistry);
236 gst_xml_registry_set_property (GObject* object, guint prop_id,
237 const GValue* value, GParamSpec* pspec)
239 GstXMLRegistry *registry;
241 registry = GST_XML_REGISTRY (object);
245 if (registry->open) {
246 CLASS (object)->close_func (registry);
247 g_return_if_fail (registry->open == FALSE);
250 if (registry->location)
251 g_free (registry->location);
253 registry->location = g_strdup (g_value_get_string (value));
254 GST_REGISTRY (registry)->flags = 0x0;
256 if (CLASS (object)->get_perms_func)
257 CLASS (object)->get_perms_func (registry);
259 if (CLASS (object)->add_path_list_func)
260 CLASS (object)->add_path_list_func (registry);
263 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
269 gst_xml_registry_get_property (GObject* object, guint prop_id,
270 GValue* value, GParamSpec* pspec)
272 GstXMLRegistry *registry;
274 registry = GST_XML_REGISTRY (object);
278 g_value_set_string (value, g_strdup (registry->location));
281 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
286 /* this function returns the biggest of the path's mtime and ctime
287 * mtime is updated through an actual write (data)
288 * ctime is updated through changing inode information
289 * so this function returns the last time *anything* changed to this path
292 get_time(const char * path)
295 if (stat(path, &statbuf)) return 0;
296 if (statbuf.st_mtime > statbuf.st_ctime) return statbuf.st_mtime;
297 return statbuf.st_ctime;
302 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
305 make_dir (gchar *filename)
310 if (strrchr (filename, '/') == NULL)
313 dirname = g_strndup(filename, strrchr(filename, '/') - filename);
315 if (stat (dirname, &dirstat) == -1 && errno == ENOENT) {
316 if (mkdir (dirname, dirmode) != 0) {
317 if (make_dir (dirname) != TRUE) {
321 if (mkdir (dirname, dirmode) != 0)
332 gst_xml_registry_get_perms_func (GstXMLRegistry *registry)
337 /* if the dir does not exist, make it. if that can't be done, flags = 0x0.
338 if the file can be appended to, it's writable. if it can then be read,
340 After that check if it exists. */
342 if (make_dir (registry->location) != TRUE) {
343 /* we can't do anything with it, leave flags as 0x0 */
347 mod_time = get_time (registry->location);
349 if ((temp = fopen (registry->location, "a"))) {
350 GST_REGISTRY (registry)->flags |= GST_REGISTRY_WRITABLE;
354 if ((temp = fopen (registry->location, "r"))) {
355 GST_REGISTRY (registry)->flags |= GST_REGISTRY_READABLE;
359 if (g_file_test (registry->location, G_FILE_TEST_EXISTS)) {
360 GST_REGISTRY (registry)->flags |= GST_REGISTRY_EXISTS;
364 struct utimbuf utime_buf;
366 /* set the modification time back to its previous value */
367 utime_buf.actime = mod_time;
368 utime_buf.modtime = mod_time;
369 utime (registry->location, &utime_buf);
370 } else if (GST_REGISTRY (registry)->flags & GST_REGISTRY_WRITABLE) {
371 /* it did not exist before, so delete it */
372 unlink (registry->location);
377 gst_xml_registry_add_path_list_func (GstXMLRegistry *registry)
380 GMarkupParseContext *context;
383 GError *error = NULL;
385 context = g_markup_parse_context_new (&gst_xml_registry_paths_parser, 0,
388 if (! (reg = fopen (registry->location, "r"))) {
392 /* slightly allocate more as gmarkup reads too much */
393 text = g_malloc0 (BLOCK_SIZE + 32);
395 size = fread (text, 1, BLOCK_SIZE, reg);
398 g_markup_parse_context_parse (context, text, size, &error);
401 GST_ERROR ("parsing registry %s: %s\n",
402 registry->location, error->message);
408 if (registry->state == GST_XML_REGISTRY_PATHS_DONE)
411 size = fread (text, 1, BLOCK_SIZE, reg);
420 plugin_times_older_than_recurse(gchar *path, time_t regtime)
423 struct dirent *dirent;
426 time_t pathtime = get_time(path);
428 if (pathtime > regtime) {
429 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING,
430 "time for %s was %ld; more recent than registry time of %ld\n",
431 path, (long)pathtime, (long)regtime);
437 while ((dirent = readdir(dir))) {
438 /* don't want to recurse in place or backwards */
439 if (strcmp(dirent->d_name,".") && strcmp(dirent->d_name,"..")) {
440 pluginname = g_strjoin("/",path,dirent->d_name,NULL);
441 if (!plugin_times_older_than_recurse(pluginname , regtime)) {
455 plugin_times_older_than(GList *paths, time_t regtime)
457 /* return true iff regtime is more recent than the times of all the files
458 * in the plugin dirs.
462 GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING,
463 "comparing plugin times from %s with %ld\n",
464 (gchar *)paths->data, (long) regtime);
465 if(!plugin_times_older_than_recurse(paths->data, regtime))
467 paths = g_list_next(paths);
473 gst_xml_registry_open_func (GstXMLRegistry *registry, GstXMLRegistryMode mode)
475 GstRegistry *gst_registry;
478 gst_registry = GST_REGISTRY (registry);
479 paths = gst_registry->paths;
481 g_return_val_if_fail (registry->open == FALSE, FALSE);
483 /* if it doesn't exist, first try to build it, and check if it worked
484 * if it's not readable, return false
485 * if it's out of date, rebuild it */
486 if (mode == GST_XML_REGISTRY_READ) {
487 if (!(gst_registry->flags & GST_REGISTRY_EXISTS))
489 /* if it's not writable, then don't bother */
490 if (!(gst_registry->flags & GST_REGISTRY_WRITABLE))
492 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry isn't writable");
495 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry doesn't exist, trying to build...");
496 gst_registry_rebuild (gst_registry);
497 gst_registry_save (gst_registry);
498 /* FIXME: verify that the flags actually get updated ! */
499 if (!(gst_registry->flags & GST_REGISTRY_EXISTS))
504 /* at this point we know it exists */
505 g_return_val_if_fail (gst_registry->flags & GST_REGISTRY_READABLE, FALSE);
507 if (!plugin_times_older_than (paths, get_time (registry->location))) {
508 if (gst_registry->flags & GST_REGISTRY_WRITABLE) {
509 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry out of date, rebuilding...");
511 gst_registry_rebuild (gst_registry);
513 gst_registry_save (gst_registry);
515 if (!plugin_times_older_than (paths, get_time (registry->location))) {
516 GST_CAT_INFO (GST_CAT_GST_INIT, "Registry still out of date, something is wrong...");
520 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "Can't write to this registry and it's out of date, ignoring it");
525 registry->regfile = fopen (registry->location, "r");
527 else if (mode == GST_XML_REGISTRY_WRITE)
529 g_return_val_if_fail (gst_registry->flags & GST_REGISTRY_WRITABLE, FALSE);
531 registry->regfile = fopen (registry->location, "w");
534 if (!registry->regfile)
537 registry->open = TRUE;
543 gst_xml_registry_load_func (GstXMLRegistry *registry, gchar *data, gssize *size)
545 *size = fread (data, 1, *size, registry->regfile);
551 gst_xml_registry_save_func (GstXMLRegistry *registry, gchar *format, ...)
555 va_start (var_args, format);
557 vfprintf (registry->regfile, format, var_args);
565 gst_xml_registry_close_func (GstXMLRegistry *registry)
567 fclose (registry->regfile);
569 registry->open = FALSE;
575 gst_xml_registry_load (GstRegistry *registry)
577 GstXMLRegistry *xmlregistry;
580 GError *error = NULL;
584 xmlregistry = GST_XML_REGISTRY (registry);
586 timer = g_timer_new();
588 xmlregistry->context = g_markup_parse_context_new (&gst_xml_registry_parser, 0, registry, NULL);
590 if (!CLASS (xmlregistry)->open_func (xmlregistry, GST_XML_REGISTRY_READ)) {
594 text = g_malloc0 (BLOCK_SIZE + 32);
597 CLASS (xmlregistry)->load_func (xmlregistry, text, &size);
600 g_markup_parse_context_parse (xmlregistry->context, text, size, &error);
603 GST_ERROR ("parsing registry: %s\n", error->message);
605 CLASS (xmlregistry)->close_func (xmlregistry);
610 CLASS (xmlregistry)->load_func (xmlregistry, text, &size);
615 g_timer_stop (timer);
617 seconds = g_timer_elapsed (timer, NULL);
618 g_timer_destroy (timer);
620 GST_INFO ( "registry: loaded %s in %f seconds\n (%s)",
621 registry->name, seconds, xmlregistry->location);
623 CLASS (xmlregistry)->close_func (xmlregistry);
629 static GstRegistryReturn
630 gst_xml_registry_load_plugin (GstRegistry *registry, GstPlugin *plugin)
632 GError *error = NULL;
633 GstPlugin *loaded_plugin;
635 /* FIXME: add gerror support */
636 loaded_plugin = gst_plugin_load_file (plugin->filename, &error);
639 g_warning ("could not load plugin %s: %s", plugin->desc.name, error->message);
641 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
642 } else if (loaded_plugin != plugin) {
643 g_critical ("how to remove plugins?");
646 return GST_REGISTRY_OK;
650 gst_xml_registry_parse_plugin (GMarkupParseContext *context, const gchar *tag, const gchar *text,
651 gsize text_len, GstXMLRegistry *registry, GError **error)
653 GstPlugin *plugin = registry->current_plugin;
655 if (!strcmp (tag, "name")) {
656 plugin->desc.name = g_strndup (text, text_len);
658 else if (!strcmp (tag, "description")) {
659 plugin->desc.description = g_strndup (text, text_len);
661 else if (!strcmp (tag, "filename")) {
662 plugin->filename = g_strndup (text, text_len);
664 else if (!strcmp (tag, "version")) {
665 plugin->desc.version = g_strndup (text, text_len);
667 else if (!strcmp (tag, "copyright")) {
668 plugin->desc.copyright = g_strndup (text, text_len);
670 else if (!strcmp (tag, "license")) {
671 plugin->desc.license = g_strndup (text, text_len);
673 else if (!strcmp (tag, "package")) {
674 plugin->desc.package = g_strndup (text, text_len);
676 else if (!strcmp (tag, "origin")) {
677 plugin->desc.origin = g_strndup (text, text_len);
684 add_to_char_array (gchar ***array, gchar *value)
687 gchar **old = *array;
690 /* expensive, but cycles are cheap... */
693 new = g_new0 (gchar *, i + 2);
704 gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
705 gsize text_len, GstXMLRegistry *registry, GError **error)
707 GstElementFactory *factory = GST_ELEMENT_FACTORY (registry->current_feature);
709 if (!strcmp (tag, "name")) {
710 gchar *name = g_strndup (text, text_len);
711 gst_plugin_feature_set_name (registry->current_feature, name);
714 else if (!strcmp (tag, "longname")) {
715 g_free (factory->details.longname);
716 factory->details.longname = g_strndup (text, text_len);
718 else if (!strcmp(tag, "class")) {
719 g_free (factory->details.klass);
720 factory->details.klass = g_strndup (text, text_len);
722 else if (!strcmp(tag, "description")) {
723 g_free (factory->details.description);
724 factory->details.description = g_strndup (text, text_len);
726 else if (!strcmp(tag, "author")) {
727 g_free (factory->details.author);
728 factory->details.author = g_strndup (text, text_len);
730 else if (!strcmp(tag, "rank")) {
734 rank = strtol (text, &ret, 0);
735 if (ret == text + text_len) {
736 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
738 } else if (!strcmp (tag, "uri_type")) {
739 if (strncasecmp (text, "sink", 4) == 0) {
740 factory->uri_type = GST_URI_SINK;
741 } else if (strncasecmp (text, "source", 5) == 0) {
742 factory->uri_type = GST_URI_SRC;
744 } else if (!strcmp (tag, "uri_protocol")) {
745 add_to_char_array (&factory->uri_protocols, g_strndup (text, text_len));
747 else if (!strcmp(tag, "interface")) {
748 gchar *tmp = g_strndup (text, text_len);
749 __gst_element_factory_add_interface (factory, tmp);
757 gst_xml_registry_parse_type_find_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
758 gsize text_len, GstXMLRegistry *registry, GError **error)
760 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (registry->current_feature);
762 if (!strcmp (tag, "name")) {
763 registry->current_feature->name = g_strndup (text, text_len);
765 else if (!strcmp(tag, "rank")) {
768 rank = strtol (text, &ret, 0);
769 if (ret == text + text_len) {
770 gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE (factory), rank);
774 else if (!strcmp (tag, "caps")) {
775 factory->caps = g_strndup (text, text_len);
777 else if (!strcmp(tag, "extension")) {
778 add_to_char_array (&factory->extensions, g_strndup (text, text_len));
785 gst_xml_registry_parse_scheduler_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
786 gsize text_len, GstXMLRegistry *registry, GError **error)
788 GstSchedulerFactory *factory = GST_SCHEDULER_FACTORY (registry->current_feature);
790 if (!strcmp (tag, "name")) {
791 registry->current_feature->name = g_strndup (text, text_len);
793 else if (!strcmp (tag, "longdesc")) {
794 factory->longdesc = g_strndup (text, text_len);
800 gst_xml_registry_parse_autoplug_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
801 gsize text_len, GstXMLRegistry *registry, GError **error)
803 GstAutoplugFactory *factory = GST_AUTOPLUG_FACTORY (registry->current_feature);
805 if (!strcmp (tag, "name")) {
806 registry->current_feature->name = g_strndup (text, text_len);
808 else if (!strcmp (tag, "longdesc")) {
809 factory->longdesc = g_strndup (text, text_len);
815 gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
816 gsize text_len, GstXMLRegistry *registry, GError **error)
818 GstIndexFactory *factory = GST_INDEX_FACTORY (registry->current_feature);
820 if (!strcmp (tag, "name")) {
821 registry->current_feature->name = g_strndup (text, text_len);
823 else if (!strcmp (tag, "longdesc")) {
824 factory->longdesc = g_strndup (text, text_len);
830 gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
831 gsize text_len, GstXMLRegistry *registry, GError **error)
833 if (!strcmp (tag, "nametemplate")) {
834 registry->name_template = g_strndup (text, text_len);
836 else if (!strcmp (tag, "direction")) {
837 if (!strncmp(text, "sink", text_len)) {
838 registry->direction = GST_PAD_SINK;
840 else if (!strncmp(text, "src", text_len)) {
841 registry->direction = GST_PAD_SRC;
844 else if (!strcmp (tag, "presence")) {
845 if (!strncmp(text, "always", text_len)) {
846 registry->presence = GST_PAD_ALWAYS;
848 else if (!strncmp(text, "sometimes", text_len)) {
849 registry->presence = GST_PAD_SOMETIMES;
851 else if (!strncmp(text, "request", text_len)) {
852 registry->presence = GST_PAD_REQUEST;
859 gst_xml_registry_parse_capscomp (GMarkupParseContext *context, const gchar *tag, const gchar *text,
860 gsize text_len, GstXMLRegistry *registry, GError **error)
862 if (!strcmp (tag, "name")) {
863 registry->caps_name = g_strndup (text, text_len);
865 else if (!strcmp (tag, "type")) {
866 registry->caps_mime = g_strndup (text, text_len);
872 find_index_for (const gchar *name, const gchar **attribute_names)
876 while (attribute_names[i]) {
877 if (!strcmp (attribute_names[i], name))
885 gst_xml_registry_start_element (GMarkupParseContext *context,
886 const gchar *element_name,
887 const gchar **attribute_names,
888 const gchar **attribute_values,
889 gpointer user_data, GError **error)
891 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
893 xmlregistry->open_tags = g_list_prepend (xmlregistry->open_tags,
894 g_strdup (element_name));
896 switch (xmlregistry->state) {
897 case GST_XML_REGISTRY_NONE:
898 if (!strcmp (element_name, "GST-PluginRegistry")) {
899 xmlregistry->state = GST_XML_REGISTRY_TOP;
902 case GST_XML_REGISTRY_TOP:
903 if (!strncmp (element_name, "plugin", 6)) {
904 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
905 xmlregistry->parser = gst_xml_registry_parse_plugin;
906 xmlregistry->current_plugin = (GstPlugin *) g_new0 (GstPlugin, 1);
909 case GST_XML_REGISTRY_PLUGIN:
910 if (!strncmp (element_name, "feature", 7)) {
912 GstPluginFeature *feature = NULL;
914 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
916 while (attribute_names[i]) {
917 if (!strncmp (attribute_names[i], "typename", 8)) {
918 feature = GST_PLUGIN_FEATURE (g_object_new (g_type_from_name (attribute_values[i]), NULL));
924 xmlregistry->current_feature = feature;
926 if (GST_IS_ELEMENT_FACTORY (feature)) {
927 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
929 factory->padtemplates = NULL;
930 xmlregistry->parser = gst_xml_registry_parse_element_factory;
933 else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
934 xmlregistry->parser = gst_xml_registry_parse_type_find_factory;
936 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
937 xmlregistry->parser = gst_xml_registry_parse_scheduler_factory;
938 GST_SCHEDULER_FACTORY (feature)->type = 0;
940 else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
941 xmlregistry->parser = gst_xml_registry_parse_autoplug_factory;
943 else if (GST_IS_INDEX_FACTORY (feature)) {
944 xmlregistry->parser = gst_xml_registry_parse_index_factory;
947 g_warning ("unkown feature type");
952 case GST_XML_REGISTRY_FEATURE:
953 if (!strncmp (element_name, "padtemplate", 11)) {
954 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
955 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
956 xmlregistry->name_template = NULL;
957 xmlregistry->direction = 0;
958 xmlregistry->presence = 0;
959 xmlregistry->caps = NULL;
962 case GST_XML_REGISTRY_PADTEMPLATE:
963 if (!strncmp (element_name, "caps", 4)) {
964 xmlregistry->state = GST_XML_REGISTRY_CAPS;
965 xmlregistry->parser = NULL;
968 case GST_XML_REGISTRY_CAPS:
969 if (!strncmp (element_name, "capscomp", 8)) {
970 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
971 xmlregistry->parser = gst_xml_registry_parse_capscomp;
974 case GST_XML_REGISTRY_CAPSCOMP:
975 if (!strncmp (element_name, "properties", 10)) {
976 xmlregistry->state = GST_XML_REGISTRY_PROPERTIES;
977 xmlregistry->parser = NULL;
978 xmlregistry->props = gst_props_empty_new ();
981 case GST_XML_REGISTRY_PROPERTIES:
984 GstPropsEntry *entry = NULL;
986 name_index = find_index_for ("name", attribute_names);
990 if (!strncmp (element_name, "list", 4)) {
991 xmlregistry->in_list = TRUE;
992 xmlregistry->list_name = g_strdup (attribute_values[name_index]);
995 if (!strncmp (element_name, "int", 3)) {
999 if ((index = find_index_for ("value", attribute_names)) < 0)
1001 sscanf (attribute_values[index], "%d", &value);
1003 entry = gst_props_entry_new (attribute_values[name_index],
1004 GST_PROPS_INT (value));
1006 else if (!strncmp (element_name, "range", 5)) {
1008 gint min_idx, max_idx;
1010 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
1012 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
1014 sscanf (attribute_values[min_idx], "%d", &min);
1015 sscanf (attribute_values[max_idx], "%d", &max);
1017 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_INT_RANGE (min, max));
1019 else if (!strncmp (element_name, "float", 5)) {
1023 if ((index = find_index_for ("value", attribute_names)) < 0)
1025 sscanf (attribute_values[index], "%f", &value);
1027 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT (value));
1029 else if (!strncmp (element_name, "floatrange", 10)) {
1031 gint min_idx, max_idx;
1033 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
1035 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
1037 sscanf (attribute_values[min_idx], "%f", &min);
1038 sscanf (attribute_values[max_idx], "%f", &max);
1040 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT_RANGE (min, max));
1042 else if (!strncmp (element_name, "boolean", 7)) {
1043 gboolean value = TRUE;
1046 if ((index = find_index_for ("value", attribute_names)) < 0)
1048 if (!strcmp (attribute_values[index], "false"))
1051 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_BOOLEAN (value));
1053 else if (!strncmp (element_name, "fourcc", 6)) {
1057 if ((index = find_index_for ("hexvalue", attribute_names)) < 0)
1059 sscanf (attribute_values[index], "%08x", &value);
1061 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FOURCC (value));
1063 else if (!strncmp (element_name, "string", 6)) {
1066 if ((index = find_index_for ("value", attribute_names)) < 0)
1069 entry = gst_props_entry_new (attribute_values[name_index],
1070 GST_PROPS_STRING (attribute_values[index]));
1072 /* add property to list or parent */
1074 if (xmlregistry->in_list)
1075 xmlregistry->entry_list = g_list_prepend (xmlregistry->entry_list, entry);
1077 gst_props_add_entry (xmlregistry->props, entry);
1087 gst_xml_registry_end_element (GMarkupParseContext *context,
1088 const gchar *element_name,
1089 gpointer user_data, GError **error)
1091 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1092 gchar *open_tag = (gchar *)xmlregistry->open_tags->data;
1094 xmlregistry->open_tags = g_list_remove (xmlregistry->open_tags, open_tag);
1097 switch (xmlregistry->state) {
1098 case GST_XML_REGISTRY_TOP:
1099 if (!strcmp (element_name, "GST-PluginRegistry")) {
1100 xmlregistry->state = GST_XML_REGISTRY_NONE;
1103 case GST_XML_REGISTRY_PLUGIN:
1104 if (!strcmp (element_name, "plugin")) {
1105 xmlregistry->state = GST_XML_REGISTRY_TOP;
1106 xmlregistry->parser = NULL;
1107 gst_registry_add_plugin (GST_REGISTRY (xmlregistry), xmlregistry->current_plugin);
1110 case GST_XML_REGISTRY_FEATURE:
1111 if (!strcmp (element_name, "feature")) {
1112 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
1113 xmlregistry->parser = gst_xml_registry_parse_plugin;
1114 gst_plugin_add_feature (xmlregistry->current_plugin, xmlregistry->current_feature);
1115 xmlregistry->current_feature = NULL;
1118 case GST_XML_REGISTRY_PADTEMPLATE:
1119 if (!strcmp (element_name, "padtemplate")) {
1120 GstPadTemplate *template;
1122 template = gst_pad_template_new (xmlregistry->name_template,
1123 xmlregistry->direction,
1124 xmlregistry->presence,
1125 xmlregistry->caps, NULL);
1127 g_free (xmlregistry->name_template);
1128 xmlregistry->name_template = NULL;
1129 xmlregistry->caps = NULL;
1131 __gst_element_factory_add_pad_template (GST_ELEMENT_FACTORY (xmlregistry->current_feature),
1133 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
1134 xmlregistry->parser = gst_xml_registry_parse_element_factory;
1137 case GST_XML_REGISTRY_CAPS:
1138 if (!strcmp (element_name, "caps")) {
1139 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
1140 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1143 case GST_XML_REGISTRY_CAPSCOMP:
1144 if (!strcmp (element_name, "capscomp")) {
1147 xmlregistry->state = GST_XML_REGISTRY_CAPS;
1148 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1150 caps = gst_caps_new (xmlregistry->caps_name, xmlregistry->caps_mime, xmlregistry->props);
1151 g_free (xmlregistry->caps_mime);
1152 g_free (xmlregistry->caps_name);
1154 xmlregistry->caps = gst_caps_append (xmlregistry->caps, caps);
1155 xmlregistry->props = NULL;
1158 case GST_XML_REGISTRY_PROPERTIES:
1159 if (!strncmp (element_name, "list", 4)) {
1160 GstPropsEntry *entry;
1162 xmlregistry->entry_list = g_list_reverse (xmlregistry->entry_list);
1164 entry = gst_props_entry_new (xmlregistry->list_name,
1165 GST_PROPS_GLIST (xmlregistry->entry_list));
1167 gst_props_add_entry (xmlregistry->props, entry);
1168 g_list_free (xmlregistry->entry_list);
1169 g_free (xmlregistry->list_name);
1171 xmlregistry->entry_list = NULL;
1172 xmlregistry->list_name = NULL;
1173 xmlregistry->in_list = FALSE;
1175 else if (!strcmp (element_name, "properties")) {
1176 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
1177 xmlregistry->parser = NULL;
1186 gst_xml_registry_text (GMarkupParseContext *context, const gchar *text,
1187 gsize text_len, gpointer user_data, GError **error)
1189 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1192 if (xmlregistry->open_tags) {
1193 open_tag = (gchar *)xmlregistry->open_tags->data;
1195 if (!strcmp (open_tag, "plugin-path")) {
1196 //gst_plugin_add_path (g_strndup (text, text_len));
1198 else if (xmlregistry->parser) {
1199 xmlregistry->parser (context, open_tag, text, text_len, xmlregistry, error);
1205 gst_xml_registry_passthrough (GMarkupParseContext *context, const gchar *passthrough_text,
1206 gsize text_len, gpointer user_data, GError **error)
1211 gst_xml_registry_error (GMarkupParseContext *context, GError *error,
1214 GST_ERROR ("%s\n", error->message);
1218 gst_xml_registry_paths_start_element (GMarkupParseContext *context,
1219 const gchar *element_name,
1220 const gchar **attribute_names,
1221 const gchar **attribute_values,
1222 gpointer user_data, GError **error)
1224 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1226 switch (xmlregistry->state) {
1227 case GST_XML_REGISTRY_NONE:
1228 if (!strcmp (element_name, "GST-PluginRegistry")) {
1229 xmlregistry->state = GST_XML_REGISTRY_TOP;
1232 case GST_XML_REGISTRY_TOP:
1233 if (!strcmp (element_name, "gst-registry-paths")) {
1234 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1237 case GST_XML_REGISTRY_PATHS:
1238 if (!strcmp (element_name, "path")) {
1239 xmlregistry->state = GST_XML_REGISTRY_PATH;
1248 gst_xml_registry_paths_end_element (GMarkupParseContext *context,
1249 const gchar *element_name,
1250 gpointer user_data, GError **error)
1252 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1254 switch (xmlregistry->state) {
1255 case GST_XML_REGISTRY_PATH:
1256 if (!strcmp (element_name, "path")) {
1257 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1260 case GST_XML_REGISTRY_PATHS:
1261 if (!strcmp (element_name, "gst-plugin-paths")) {
1262 xmlregistry->state = GST_XML_REGISTRY_PATHS_DONE;
1271 gst_xml_registry_paths_text (GMarkupParseContext *context, const gchar *text,
1272 gsize text_len, gpointer user_data, GError **error)
1274 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1276 if (xmlregistry->state == GST_XML_REGISTRY_PATH)
1277 gst_registry_add_path (GST_REGISTRY (xmlregistry), g_strndup (text, text_len));
1283 #define PUT_ESCAPED(tag,value) \
1285 const gchar *toconv = value; \
1287 gchar *v = g_markup_escape_text (toconv, strlen (toconv)); \
1288 CLASS (xmlregistry)->save_func (xmlregistry, "<%s>%s</%s>\n", tag, v, tag); \
1292 #define PUT_ESCAPED_INT(tag,value) \
1294 gchar *save = g_strdup_printf ("%ld", (glong) value); \
1295 CLASS (xmlregistry)->save_func (xmlregistry, "<%s>%s</%s>\n", tag, save, tag); \
1301 gst_xml_registry_save_props_func (GstPropsEntry *entry,
1302 GstXMLRegistry *xmlregistry)
1306 name = gst_props_entry_get_name (entry);
1308 switch (gst_props_entry_get_props_type (entry)) {
1309 case GST_PROPS_INT_TYPE:
1312 gst_props_entry_get_int (entry, &value);
1313 CLASS (xmlregistry)->save_func (xmlregistry, "<int name=\"%s\" value=\"%d\"/>\n", name, value);
1316 case GST_PROPS_INT_RANGE_TYPE:
1319 gst_props_entry_get_int_range (entry, &min, &max);
1320 CLASS (xmlregistry)->save_func (xmlregistry, "<range name=\"%s\" min=\"%d\" max=\"%d\"/>\n", name, min, max);
1323 case GST_PROPS_FLOAT_TYPE:
1326 gst_props_entry_get_float (entry, &value);
1327 CLASS (xmlregistry)->save_func (xmlregistry, "<float name=\"%s\" value=\"%f\"/>\n", name, value);
1330 case GST_PROPS_FLOAT_RANGE_TYPE:
1333 gst_props_entry_get_float_range (entry, &min, &max);
1334 CLASS (xmlregistry)->save_func (xmlregistry, "<floatrange name=\"%s\" min=\"%f\" max=\"%f\"/>\n", name, min, max);
1337 case GST_PROPS_FOURCC_TYPE:
1340 gst_props_entry_get_fourcc_int (entry, &fourcc);
1341 CLASS (xmlregistry)->save_func (xmlregistry, "<!-- "GST_FOURCC_FORMAT" -->\n",
1342 GST_FOURCC_ARGS (fourcc));
1343 CLASS (xmlregistry)->save_func (xmlregistry, "<fourcc name=\"%s\" hexvalue=\"%08x\"/>\n", name, fourcc);
1346 case GST_PROPS_BOOLEAN_TYPE:
1349 gst_props_entry_get_boolean (entry, &value);
1350 CLASS (xmlregistry)->save_func (xmlregistry, "<boolean name=\"%s\" value=\"%s\"/>\n", name, (value ? "true" : "false"));
1353 case GST_PROPS_STRING_TYPE:
1356 gst_props_entry_get_string (entry, &value);
1357 CLASS (xmlregistry)->save_func (xmlregistry, "<string name=\"%s\" value=\"%s\"/>\n", name, value);
1361 g_warning ("trying to save unknown property type %d", gst_props_entry_get_props_type (entry));
1368 gst_xml_registry_save_props (GstXMLRegistry *xmlregistry, GstProps *props)
1372 proplist = props->properties;
1375 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
1377 switch (gst_props_entry_get_props_type (entry)) {
1378 case GST_PROPS_LIST_TYPE:
1382 gst_props_entry_get_list (entry, &list);
1384 CLASS (xmlregistry)->save_func (xmlregistry, "<list name=\"%s\">\n", gst_props_entry_get_name (entry));
1385 g_list_foreach ((GList *)list, (GFunc) gst_xml_registry_save_props_func, xmlregistry);
1386 CLASS (xmlregistry)->save_func (xmlregistry, "</list>\n");
1390 gst_xml_registry_save_props_func (entry, xmlregistry);
1393 proplist = g_list_next (proplist);
1399 gst_xml_registry_save_caps (GstXMLRegistry *xmlregistry, GstCaps *caps)
1402 CLASS (xmlregistry)->save_func (xmlregistry, "<capscomp>\n");
1403 PUT_ESCAPED ("name", caps->name);
1404 PUT_ESCAPED ("type", gst_caps_get_mime (caps));
1406 if (caps->properties) {
1407 CLASS (xmlregistry)->save_func (xmlregistry, "<properties>\n");
1408 gst_xml_registry_save_props (xmlregistry, caps->properties);
1409 CLASS (xmlregistry)->save_func (xmlregistry, "</properties>\n");
1411 CLASS (xmlregistry)->save_func (xmlregistry, "</capscomp>\n");
1418 gst_xml_registry_save_pad_template (GstXMLRegistry *xmlregistry, GstPadTemplate *template)
1422 PUT_ESCAPED ("nametemplate", template->name_template);
1423 CLASS (xmlregistry)->save_func (xmlregistry, "<direction>%s</direction>\n", (template->direction == GST_PAD_SINK? "sink":"src"));
1425 switch (template->presence) {
1426 case GST_PAD_ALWAYS:
1427 presence = "always";
1429 case GST_PAD_SOMETIMES:
1430 presence = "sometimes";
1432 case GST_PAD_REQUEST:
1433 presence = "request";
1436 presence = "unknown";
1439 CLASS (xmlregistry)->save_func (xmlregistry, "<presence>%s</presence>\n", presence);
1441 if (GST_PAD_TEMPLATE_CAPS (template)) {
1442 CLASS (xmlregistry)->save_func (xmlregistry, "<caps>\n");
1443 gst_xml_registry_save_caps (xmlregistry, GST_PAD_TEMPLATE_CAPS (template));
1444 CLASS (xmlregistry)->save_func (xmlregistry, "</caps>\n");
1450 gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *feature)
1452 PUT_ESCAPED ("name", feature->name);
1454 if (feature->rank > 0) {
1455 gint rank = feature->rank;
1456 CLASS (xmlregistry)->save_func (xmlregistry, "<rank>%d</rank>\n", rank);
1459 if (GST_IS_ELEMENT_FACTORY (feature)) {
1460 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
1463 PUT_ESCAPED ("longname", factory->details.longname);
1464 PUT_ESCAPED ("class", factory->details.klass);
1465 PUT_ESCAPED ("description", factory->details.description);
1466 PUT_ESCAPED ("author", factory->details.author);
1468 walk = factory->padtemplates;
1471 GstPadTemplate *template = GST_PAD_TEMPLATE (walk->data);
1473 CLASS (xmlregistry)->save_func (xmlregistry, "<padtemplate>\n");
1474 gst_xml_registry_save_pad_template (xmlregistry, template);
1475 CLASS (xmlregistry)->save_func (xmlregistry, "</padtemplate>\n");
1477 walk = g_list_next (walk);
1480 walk = factory->interfaces;
1482 PUT_ESCAPED ("interface", (gchar *) walk->data);
1483 walk = g_list_next (walk);
1486 if (GST_URI_TYPE_IS_VALID (factory->uri_type)) {
1489 PUT_ESCAPED ("uri_type", factory->uri_type == GST_URI_SINK ? "sink" : "source");
1490 g_assert (factory->uri_protocols);
1491 protocol = factory->uri_protocols;
1493 PUT_ESCAPED ("uri_protocol", *protocol);
1498 else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
1499 GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (feature);
1502 if (factory->caps) {
1503 CLASS (xmlregistry)->save_func (xmlregistry, "<caps>\n");
1504 gst_xml_registry_save_caps (xmlregistry, factory->caps);
1505 CLASS (xmlregistry)->save_func (xmlregistry, "</caps>\n");
1507 if (factory->extensions) {
1508 while (factory->extensions[i]) {
1509 PUT_ESCAPED ("extension", factory->extensions[i]);
1514 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
1515 PUT_ESCAPED ("longdesc", GST_SCHEDULER_FACTORY (feature)->longdesc);
1517 else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
1518 PUT_ESCAPED ("longdesc", GST_AUTOPLUG_FACTORY (feature)->longdesc);
1520 else if (GST_IS_INDEX_FACTORY (feature)) {
1521 PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
1527 gst_xml_registry_save_plugin (GstXMLRegistry *xmlregistry, GstPlugin *plugin)
1531 PUT_ESCAPED ("name", plugin->desc.name);
1532 PUT_ESCAPED ("description", plugin->desc.description);
1533 PUT_ESCAPED ("filename", plugin->filename);
1534 PUT_ESCAPED ("version", plugin->desc.version);
1535 PUT_ESCAPED ("license", plugin->desc.license);
1536 PUT_ESCAPED ("copyright", plugin->desc.copyright);
1537 PUT_ESCAPED ("package", plugin->desc.package);
1538 PUT_ESCAPED ("origin", plugin->desc.origin);
1540 walk = plugin->features;
1543 GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
1545 CLASS (xmlregistry)->save_func (xmlregistry, "<feature typename=\"%s\">\n", g_type_name (G_OBJECT_TYPE (feature)));
1546 gst_xml_registry_save_feature (xmlregistry, feature);
1547 CLASS (xmlregistry)->save_func (xmlregistry, "</feature>\n");
1549 walk = g_list_next (walk);
1556 gst_xml_registry_save (GstRegistry *registry)
1559 GstXMLRegistry *xmlregistry;
1561 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
1562 g_return_val_if_fail (registry->flags & GST_REGISTRY_WRITABLE, FALSE);
1564 xmlregistry = GST_XML_REGISTRY (registry);
1566 if (!CLASS (xmlregistry)->open_func (xmlregistry, GST_XML_REGISTRY_WRITE)) {
1570 CLASS (xmlregistry)->save_func (xmlregistry, "<?xml version=\"1.0\"?>\n");
1571 CLASS (xmlregistry)->save_func (xmlregistry, "<GST-PluginRegistry>\n");
1573 walk = g_list_last (gst_registry_get_path_list (GST_REGISTRY (registry)));
1575 CLASS (xmlregistry)->save_func (xmlregistry, "<gst-plugin-paths>\n");
1577 CLASS (xmlregistry)->save_func (xmlregistry, "<path>");
1578 CLASS (xmlregistry)->save_func (xmlregistry, (gchar*)walk->data);
1579 CLASS (xmlregistry)->save_func (xmlregistry, "</path>\n");
1580 walk = g_list_previous (walk);
1582 CLASS (xmlregistry)->save_func (xmlregistry, "</gst-plugin-paths>\n");
1584 walk = g_list_last (registry->plugins);
1587 GstPlugin *plugin = GST_PLUGIN (walk->data);
1589 CLASS (xmlregistry)->save_func (xmlregistry, "<plugin>\n");
1590 gst_xml_registry_save_plugin (xmlregistry, plugin);
1591 CLASS (xmlregistry)->save_func (xmlregistry, "</plugin>\n");
1593 walk = g_list_previous (walk);
1595 CLASS (xmlregistry)->save_func (xmlregistry, "</GST-PluginRegistry>\n");
1597 CLASS (xmlregistry)->close_func (xmlregistry);
1603 gst_xml_registry_rebuild_recurse (GstXMLRegistry *registry,
1604 const gchar *directory)
1610 dir = g_dir_open (directory, 0, NULL);
1613 const gchar *dirent;
1615 while ((dirent = g_dir_read_name (dir))) {
1618 if (*dirent == '=') {
1619 /* =build, =inst, etc. -- automake distcheck directories */
1623 dirname = g_strjoin ("/", directory, dirent, NULL);
1624 ret = g_list_concat (ret, gst_xml_registry_rebuild_recurse (registry, dirname));
1629 if ((temp = strstr (directory, G_MODULE_SUFFIX)) &&
1630 (!strcmp (temp, G_MODULE_SUFFIX))) {
1631 ret = g_list_prepend (ret, g_strdup (directory));
1639 gst_xml_registry_rebuild (GstRegistry *registry)
1641 GList *walk = NULL, *plugins = NULL, *prune = NULL;
1642 GError *error = NULL;
1645 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (registry);
1647 walk = registry->paths;
1650 gchar *path = (gchar *) walk->data;
1652 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING,
1653 "Rebuilding registry %p in directory %s...", registry, path);
1655 plugins = g_list_concat (plugins,
1656 gst_xml_registry_rebuild_recurse (xmlregistry,
1659 walk = g_list_next (walk);
1662 plugins = g_list_reverse (plugins);
1665 length = g_list_length (plugins);
1669 g_assert (walk->data);
1670 plugin = gst_plugin_load_file ((gchar *) walk->data, NULL);
1672 prune = g_list_prepend (prune, walk->data);
1673 gst_registry_add_plugin (registry, plugin);
1676 walk = g_list_next (walk);
1681 plugins = g_list_remove (plugins, walk->data);
1682 g_free (walk->data);
1683 walk = g_list_next (walk);
1685 g_list_free (prune);
1687 } while (g_list_length (plugins) != length);
1691 if ((plugin = gst_plugin_load_file ((gchar *) walk->data, &error))) {
1692 g_warning ("Bizarre behavior: plugin %s actually loaded",
1693 (gchar *) walk->data);
1694 gst_registry_add_plugin (registry, plugin);
1696 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "Plugin %s failed to load: %s",
1697 (gchar *) walk->data, error->message);
1699 g_free (walk->data);
1700 g_error_free (error);
1704 walk = g_list_next (walk);