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/gsttype.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 fprintf (stderr, "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 fprintf(stderr, "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;
634 /* FIXME: add gerror support */
635 if (!gst_plugin_load_plugin (plugin, &error)) {
637 g_warning ("could not load plugin %s: %s", plugin->name, error->message);
639 return GST_REGISTRY_PLUGIN_LOAD_ERROR;
642 return GST_REGISTRY_OK;
646 gst_xml_registry_parse_plugin (GMarkupParseContext *context, const gchar *tag, const gchar *text,
647 gsize text_len, GstXMLRegistry *registry, GError **error)
649 GstPlugin *plugin = registry->current_plugin;
651 if (!strcmp (tag, "name")) {
652 plugin->name = g_strndup (text, text_len);
654 else if (!strcmp (tag, "longname")) {
655 plugin->longname = g_strndup (text, text_len);
657 else if (!strcmp (tag, "filename")) {
658 plugin->filename = g_strndup (text, text_len);
665 gst_xml_registry_parse_element_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
666 gsize text_len, GstXMLRegistry *registry, GError **error)
668 GstElementFactory *factory = GST_ELEMENT_FACTORY (registry->current_feature);
670 if (!strcmp (tag, "name")) {
671 g_free (registry->current_feature->name);
672 registry->current_feature->name = g_strndup (text, text_len);
674 else if (!strcmp (tag, "longname")) {
675 g_free (factory->details->longname);
676 factory->details->longname = g_strndup (text, text_len);
678 else if (!strcmp(tag, "class")) {
679 g_free (factory->details->klass);
680 factory->details->klass = g_strndup (text, text_len);
682 else if (!strcmp(tag, "description")) {
683 g_free (factory->details->description);
684 factory->details->description = g_strndup (text, text_len);
686 else if (!strcmp(tag, "license")) {
687 g_free (factory->details->license);
688 factory->details->license = g_strndup (text, text_len);
690 else if (!strcmp(tag, "version")) {
691 g_free (factory->details->version);
692 factory->details->version = g_strndup (text, text_len);
694 else if (!strcmp(tag, "author")) {
695 g_free (factory->details->author);
696 factory->details->author = g_strndup (text, text_len);
698 else if (!strcmp(tag, "copyright")) {
699 g_free (factory->details->copyright);
700 factory->details->copyright = g_strndup (text, text_len);
702 else if (!strcmp(tag, "rank")) {
705 rank = strtol (text, &ret, 0);
706 if (ret == text + text_len) {
707 gst_element_factory_set_rank (factory, rank);
715 gst_xml_registry_parse_type_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
716 gsize text_len, GstXMLRegistry *registry, GError **error)
718 GstTypeFactory *factory = GST_TYPE_FACTORY (registry->current_feature);
720 if (!strcmp (tag, "name")) {
721 registry->current_feature->name = g_strndup (text, text_len);
723 else if (!strcmp (tag, "mime")) {
724 factory->mime = g_strndup (text, text_len);
726 else if (!strcmp(tag, "extensions")) {
727 factory->exts = g_strndup (text, text_len);
734 gst_xml_registry_parse_scheduler_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
735 gsize text_len, GstXMLRegistry *registry, GError **error)
737 GstSchedulerFactory *factory = GST_SCHEDULER_FACTORY (registry->current_feature);
739 if (!strcmp (tag, "name")) {
740 registry->current_feature->name = g_strndup (text, text_len);
742 else if (!strcmp (tag, "longdesc")) {
743 factory->longdesc = g_strndup (text, text_len);
749 gst_xml_registry_parse_autoplug_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
750 gsize text_len, GstXMLRegistry *registry, GError **error)
752 GstAutoplugFactory *factory = GST_AUTOPLUG_FACTORY (registry->current_feature);
754 if (!strcmp (tag, "name")) {
755 registry->current_feature->name = g_strndup (text, text_len);
757 else if (!strcmp (tag, "longdesc")) {
758 factory->longdesc = g_strndup (text, text_len);
764 gst_xml_registry_parse_index_factory (GMarkupParseContext *context, const gchar *tag, const gchar *text,
765 gsize text_len, GstXMLRegistry *registry, GError **error)
767 GstIndexFactory *factory = GST_INDEX_FACTORY (registry->current_feature);
769 if (!strcmp (tag, "name")) {
770 registry->current_feature->name = g_strndup (text, text_len);
772 else if (!strcmp (tag, "longdesc")) {
773 factory->longdesc = g_strndup (text, text_len);
779 gst_xml_registry_parse_uri_handler (GMarkupParseContext *context, const gchar *tag, const gchar *text,
780 gsize text_len, GstXMLRegistry *registry, GError **error)
782 GstURIHandler *handler = GST_URI_HANDLER (registry->current_feature);
784 if (!strcmp (tag, "name")) {
785 registry->current_feature->name = g_strndup (text, text_len);
787 else if (!strcmp (tag, "uri")) {
788 handler->uri = g_strndup (text, text_len);
790 else if (!strcmp (tag, "longdesc")) {
791 handler->longdesc = g_strndup (text, text_len);
793 else if (!strcmp (tag, "element")) {
794 handler->element = g_strndup (text, text_len);
796 else if (!strcmp (tag, "property")) {
797 handler->property = g_strndup (text, text_len);
803 gst_xml_registry_parse_padtemplate (GMarkupParseContext *context, const gchar *tag, const gchar *text,
804 gsize text_len, GstXMLRegistry *registry, GError **error)
806 if (!strcmp (tag, "nametemplate")) {
807 registry->name_template = g_strndup (text, text_len);
809 else if (!strcmp (tag, "direction")) {
810 if (!strncmp(text, "sink", text_len)) {
811 registry->direction = GST_PAD_SINK;
813 else if (!strncmp(text, "src", text_len)) {
814 registry->direction = GST_PAD_SRC;
817 else if (!strcmp (tag, "presence")) {
818 if (!strncmp(text, "always", text_len)) {
819 registry->presence = GST_PAD_ALWAYS;
821 else if (!strncmp(text, "sometimes", text_len)) {
822 registry->presence = GST_PAD_SOMETIMES;
824 else if (!strncmp(text, "request", text_len)) {
825 registry->presence = GST_PAD_REQUEST;
832 gst_xml_registry_parse_capscomp (GMarkupParseContext *context, const gchar *tag, const gchar *text,
833 gsize text_len, GstXMLRegistry *registry, GError **error)
835 if (!strcmp (tag, "name")) {
836 registry->caps_name = g_strndup (text, text_len);
838 else if (!strcmp (tag, "type")) {
839 registry->caps_mime = g_strndup (text, text_len);
845 find_index_for (const gchar *name, const gchar **attribute_names)
849 while (attribute_names[i]) {
850 if (!strcmp (attribute_names[i], name))
858 gst_xml_registry_start_element (GMarkupParseContext *context,
859 const gchar *element_name,
860 const gchar **attribute_names,
861 const gchar **attribute_values,
862 gpointer user_data, GError **error)
864 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
866 xmlregistry->open_tags = g_list_prepend (xmlregistry->open_tags,
867 g_strdup (element_name));
869 switch (xmlregistry->state) {
870 case GST_XML_REGISTRY_NONE:
871 if (!strcmp (element_name, "GST-PluginRegistry")) {
872 xmlregistry->state = GST_XML_REGISTRY_TOP;
875 case GST_XML_REGISTRY_TOP:
876 if (!strncmp (element_name, "plugin", 6)) {
877 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
878 xmlregistry->parser = gst_xml_registry_parse_plugin;
879 xmlregistry->current_plugin = (GstPlugin *) g_new0 (GstPlugin, 1);
882 case GST_XML_REGISTRY_PLUGIN:
883 if (!strncmp (element_name, "feature", 7)) {
885 GstPluginFeature *feature = NULL;
887 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
889 while (attribute_names[i]) {
890 if (!strncmp (attribute_names[i], "typename", 8)) {
891 feature = GST_PLUGIN_FEATURE (g_object_new (g_type_from_name (attribute_values[i]), NULL));
897 xmlregistry->current_feature = feature;
899 if (GST_IS_ELEMENT_FACTORY (feature)) {
900 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
902 factory->details_dynamic = TRUE;
903 factory->details = g_new0(GstElementDetails, 1);
904 factory->padtemplates = NULL;
905 xmlregistry->parser = gst_xml_registry_parse_element_factory;
908 else if (GST_IS_TYPE_FACTORY (feature)) {
909 xmlregistry->parser = gst_xml_registry_parse_type_factory;
911 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
912 xmlregistry->parser = gst_xml_registry_parse_scheduler_factory;
913 GST_SCHEDULER_FACTORY (feature)->type = 0;
915 else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
916 xmlregistry->parser = gst_xml_registry_parse_autoplug_factory;
918 else if (GST_IS_INDEX_FACTORY (feature)) {
919 xmlregistry->parser = gst_xml_registry_parse_index_factory;
921 else if (GST_IS_URI_HANDLER (feature)) {
922 xmlregistry->parser = gst_xml_registry_parse_uri_handler;
925 g_warning ("unkown feature type");
930 case GST_XML_REGISTRY_FEATURE:
931 if (!strncmp (element_name, "padtemplate", 11)) {
932 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
933 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
934 xmlregistry->name_template = NULL;
935 xmlregistry->direction = 0;
936 xmlregistry->presence = 0;
937 xmlregistry->caps = NULL;
940 case GST_XML_REGISTRY_PADTEMPLATE:
941 if (!strncmp (element_name, "caps", 4)) {
942 xmlregistry->state = GST_XML_REGISTRY_CAPS;
943 xmlregistry->parser = NULL;
946 case GST_XML_REGISTRY_CAPS:
947 if (!strncmp (element_name, "capscomp", 8)) {
948 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
949 xmlregistry->parser = gst_xml_registry_parse_capscomp;
952 case GST_XML_REGISTRY_CAPSCOMP:
953 if (!strncmp (element_name, "properties", 10)) {
954 xmlregistry->state = GST_XML_REGISTRY_PROPERTIES;
955 xmlregistry->parser = NULL;
956 xmlregistry->props = gst_props_empty_new ();
959 case GST_XML_REGISTRY_PROPERTIES:
962 GstPropsEntry *entry = NULL;
964 name_index = find_index_for ("name", attribute_names);
968 if (!strncmp (element_name, "list", 4)) {
969 xmlregistry->in_list = TRUE;
970 xmlregistry->list_name = g_strdup (attribute_values[name_index]);
973 if (!strncmp (element_name, "int", 3)) {
977 if ((index = find_index_for ("value", attribute_names)) < 0)
979 sscanf (attribute_values[index], "%d", &value);
981 entry = gst_props_entry_new (attribute_values[name_index],
982 GST_PROPS_INT (value));
984 else if (!strncmp (element_name, "range", 5)) {
986 gint min_idx, max_idx;
988 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
990 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
992 sscanf (attribute_values[min_idx], "%d", &min);
993 sscanf (attribute_values[max_idx], "%d", &max);
995 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_INT_RANGE (min, max));
997 else if (!strncmp (element_name, "float", 5)) {
1001 if ((index = find_index_for ("value", attribute_names)) < 0)
1003 sscanf (attribute_values[index], "%f", &value);
1005 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT (value));
1007 else if (!strncmp (element_name, "floatrange", 10)) {
1009 gint min_idx, max_idx;
1011 if ((min_idx = find_index_for ("min", attribute_names)) < 0)
1013 if ((max_idx = find_index_for ("max", attribute_names)) < 0)
1015 sscanf (attribute_values[min_idx], "%f", &min);
1016 sscanf (attribute_values[max_idx], "%f", &max);
1018 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FLOAT_RANGE (min, max));
1020 else if (!strncmp (element_name, "boolean", 7)) {
1021 gboolean value = TRUE;
1024 if ((index = find_index_for ("value", attribute_names)) < 0)
1026 if (!strcmp (attribute_values[index], "false"))
1029 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_BOOLEAN (value));
1031 else if (!strncmp (element_name, "fourcc", 6)) {
1035 if ((index = find_index_for ("hexvalue", attribute_names)) < 0)
1037 sscanf (attribute_values[index], "%08x", &value);
1039 entry = gst_props_entry_new (attribute_values[name_index], GST_PROPS_FOURCC (value));
1041 else if (!strncmp (element_name, "string", 6)) {
1044 if ((index = find_index_for ("value", attribute_names)) < 0)
1047 entry = gst_props_entry_new (attribute_values[name_index],
1048 GST_PROPS_STRING (attribute_values[index]));
1050 /* add property to list or parent */
1052 if (xmlregistry->in_list)
1053 xmlregistry->entry_list = g_list_prepend (xmlregistry->entry_list, entry);
1055 gst_props_add_entry (xmlregistry->props, entry);
1065 gst_xml_registry_end_element (GMarkupParseContext *context,
1066 const gchar *element_name,
1067 gpointer user_data, GError **error)
1069 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1070 gchar *open_tag = (gchar *)xmlregistry->open_tags->data;
1072 xmlregistry->open_tags = g_list_remove (xmlregistry->open_tags, open_tag);
1075 switch (xmlregistry->state) {
1076 case GST_XML_REGISTRY_TOP:
1077 if (!strcmp (element_name, "GST-PluginRegistry")) {
1078 xmlregistry->state = GST_XML_REGISTRY_NONE;
1081 case GST_XML_REGISTRY_PLUGIN:
1082 if (!strcmp (element_name, "plugin")) {
1083 xmlregistry->state = GST_XML_REGISTRY_TOP;
1084 xmlregistry->parser = NULL;
1085 gst_registry_add_plugin (GST_REGISTRY (xmlregistry), xmlregistry->current_plugin);
1088 case GST_XML_REGISTRY_FEATURE:
1089 if (!strcmp (element_name, "feature")) {
1090 if (GST_IS_TYPE_FACTORY (xmlregistry->current_feature)) {
1091 GstTypeFactory *factory = GST_TYPE_FACTORY (xmlregistry->current_feature);
1092 gst_type_register (factory);
1094 xmlregistry->state = GST_XML_REGISTRY_PLUGIN;
1095 xmlregistry->parser = gst_xml_registry_parse_plugin;
1096 gst_plugin_add_feature (xmlregistry->current_plugin, xmlregistry->current_feature);
1097 xmlregistry->current_feature = NULL;
1099 else if (!strcmp (element_name, "typefind")) {
1100 GstTypeFactory *factory = GST_TYPE_FACTORY (xmlregistry->current_feature);
1102 factory->typefindfunc = gst_type_type_find_dummy;
1105 case GST_XML_REGISTRY_PADTEMPLATE:
1106 if (!strcmp (element_name, "padtemplate")) {
1107 GstPadTemplate *template;
1109 template = gst_pad_template_new (xmlregistry->name_template,
1110 xmlregistry->direction,
1111 xmlregistry->presence,
1112 xmlregistry->caps, NULL);
1114 g_free (xmlregistry->name_template);
1115 xmlregistry->name_template = NULL;
1116 xmlregistry->caps = NULL;
1118 gst_element_factory_add_pad_template (GST_ELEMENT_FACTORY (xmlregistry->current_feature),
1120 xmlregistry->state = GST_XML_REGISTRY_FEATURE;
1121 xmlregistry->parser = gst_xml_registry_parse_element_factory;
1124 case GST_XML_REGISTRY_CAPS:
1125 if (!strcmp (element_name, "caps")) {
1126 xmlregistry->state = GST_XML_REGISTRY_PADTEMPLATE;
1127 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1130 case GST_XML_REGISTRY_CAPSCOMP:
1131 if (!strcmp (element_name, "capscomp")) {
1134 xmlregistry->state = GST_XML_REGISTRY_CAPS;
1135 xmlregistry->parser = gst_xml_registry_parse_padtemplate;
1137 caps = gst_caps_new (xmlregistry->caps_name, xmlregistry->caps_mime, xmlregistry->props);
1138 g_free (xmlregistry->caps_mime);
1139 g_free (xmlregistry->caps_name);
1141 xmlregistry->caps = gst_caps_append (xmlregistry->caps, caps);
1142 xmlregistry->props = NULL;
1145 case GST_XML_REGISTRY_PROPERTIES:
1146 if (!strncmp (element_name, "list", 4)) {
1147 GstPropsEntry *entry;
1149 xmlregistry->entry_list = g_list_reverse (xmlregistry->entry_list);
1151 entry = gst_props_entry_new (xmlregistry->list_name,
1152 GST_PROPS_GLIST (xmlregistry->entry_list));
1154 gst_props_add_entry (xmlregistry->props, entry);
1155 g_list_free (xmlregistry->entry_list);
1156 g_free (xmlregistry->list_name);
1158 xmlregistry->entry_list = NULL;
1159 xmlregistry->list_name = NULL;
1160 xmlregistry->in_list = FALSE;
1162 else if (!strcmp (element_name, "properties")) {
1163 xmlregistry->state = GST_XML_REGISTRY_CAPSCOMP;
1164 xmlregistry->parser = NULL;
1173 gst_xml_registry_text (GMarkupParseContext *context, const gchar *text,
1174 gsize text_len, gpointer user_data, GError **error)
1176 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1179 if (xmlregistry->open_tags) {
1180 open_tag = (gchar *)xmlregistry->open_tags->data;
1182 if (!strcmp (open_tag, "plugin-path")) {
1183 //gst_plugin_add_path (g_strndup (text, text_len));
1185 else if (xmlregistry->parser) {
1186 xmlregistry->parser (context, open_tag, text, text_len, xmlregistry, error);
1192 gst_xml_registry_passthrough (GMarkupParseContext *context, const gchar *passthrough_text,
1193 gsize text_len, gpointer user_data, GError **error)
1198 gst_xml_registry_error (GMarkupParseContext *context, GError *error,
1201 g_print ("error %s\n", error->message);
1205 gst_xml_registry_paths_start_element (GMarkupParseContext *context,
1206 const gchar *element_name,
1207 const gchar **attribute_names,
1208 const gchar **attribute_values,
1209 gpointer user_data, GError **error)
1211 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1213 switch (xmlregistry->state) {
1214 case GST_XML_REGISTRY_NONE:
1215 if (!strcmp (element_name, "GST-PluginRegistry")) {
1216 xmlregistry->state = GST_XML_REGISTRY_TOP;
1219 case GST_XML_REGISTRY_TOP:
1220 if (!strcmp (element_name, "gst-registry-paths")) {
1221 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1224 case GST_XML_REGISTRY_PATHS:
1225 if (!strcmp (element_name, "path")) {
1226 xmlregistry->state = GST_XML_REGISTRY_PATH;
1235 gst_xml_registry_paths_end_element (GMarkupParseContext *context,
1236 const gchar *element_name,
1237 gpointer user_data, GError **error)
1239 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1241 switch (xmlregistry->state) {
1242 case GST_XML_REGISTRY_PATH:
1243 if (!strcmp (element_name, "path")) {
1244 xmlregistry->state = GST_XML_REGISTRY_PATHS;
1247 case GST_XML_REGISTRY_PATHS:
1248 if (!strcmp (element_name, "gst-plugin-paths")) {
1249 xmlregistry->state = GST_XML_REGISTRY_PATHS_DONE;
1258 gst_xml_registry_paths_text (GMarkupParseContext *context, const gchar *text,
1259 gsize text_len, gpointer user_data, GError **error)
1261 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (user_data);
1263 if (xmlregistry->state == GST_XML_REGISTRY_PATH)
1264 gst_registry_add_path (GST_REGISTRY (xmlregistry), g_strndup (text, text_len));
1270 #define PUT_ESCAPED(tag,value) \
1272 const gchar *toconv = value; \
1274 gchar *v = g_markup_escape_text (toconv, strlen (toconv)); \
1275 CLASS (xmlregistry)->save_func (xmlregistry, "<%s>%s</%s>\n", tag, v, tag); \
1281 gst_xml_registry_save_props_func (GstPropsEntry *entry,
1282 GstXMLRegistry *xmlregistry)
1286 name = gst_props_entry_get_name (entry);
1288 switch (gst_props_entry_get_props_type (entry)) {
1289 case GST_PROPS_INT_TYPE:
1292 gst_props_entry_get_int (entry, &value);
1293 CLASS (xmlregistry)->save_func (xmlregistry, "<int name=\"%s\" value=\"%d\"/>\n", name, value);
1296 case GST_PROPS_INT_RANGE_TYPE:
1299 gst_props_entry_get_int_range (entry, &min, &max);
1300 CLASS (xmlregistry)->save_func (xmlregistry, "<range name=\"%s\" min=\"%d\" max=\"%d\"/>\n", name, min, max);
1303 case GST_PROPS_FLOAT_TYPE:
1306 gst_props_entry_get_float (entry, &value);
1307 CLASS (xmlregistry)->save_func (xmlregistry, "<float name=\"%s\" value=\"%f\"/>\n", name, value);
1310 case GST_PROPS_FLOAT_RANGE_TYPE:
1313 gst_props_entry_get_float_range (entry, &min, &max);
1314 CLASS (xmlregistry)->save_func (xmlregistry, "<floatrange name=\"%s\" min=\"%f\" max=\"%f\"/>\n", name, min, max);
1317 case GST_PROPS_FOURCC_TYPE:
1320 gst_props_entry_get_fourcc_int (entry, &fourcc);
1321 CLASS (xmlregistry)->save_func (xmlregistry, "<!-- "GST_FOURCC_FORMAT" -->\n",
1322 GST_FOURCC_ARGS (fourcc));
1323 CLASS (xmlregistry)->save_func (xmlregistry, "<fourcc name=\"%s\" hexvalue=\"%08x\"/>\n", name, fourcc);
1326 case GST_PROPS_BOOLEAN_TYPE:
1329 gst_props_entry_get_boolean (entry, &value);
1330 CLASS (xmlregistry)->save_func (xmlregistry, "<boolean name=\"%s\" value=\"%s\"/>\n", name, (value ? "true" : "false"));
1333 case GST_PROPS_STRING_TYPE:
1336 gst_props_entry_get_string (entry, &value);
1337 CLASS (xmlregistry)->save_func (xmlregistry, "<string name=\"%s\" value=\"%s\"/>\n", name, value);
1341 g_warning ("trying to save unknown property type %d", gst_props_entry_get_props_type (entry));
1348 gst_xml_registry_save_props (GstXMLRegistry *xmlregistry, GstProps *props)
1352 proplist = props->properties;
1355 GstPropsEntry *entry = (GstPropsEntry *) proplist->data;
1357 switch (gst_props_entry_get_props_type (entry)) {
1358 case GST_PROPS_LIST_TYPE:
1362 gst_props_entry_get_list (entry, &list);
1364 CLASS (xmlregistry)->save_func (xmlregistry, "<list name=\"%s\">\n", gst_props_entry_get_name (entry));
1365 g_list_foreach ((GList *)list, (GFunc) gst_xml_registry_save_props_func, xmlregistry);
1366 CLASS (xmlregistry)->save_func (xmlregistry, "</list>\n");
1370 gst_xml_registry_save_props_func (entry, xmlregistry);
1373 proplist = g_list_next (proplist);
1379 gst_xml_registry_save_caps (GstXMLRegistry *xmlregistry, GstCaps *caps)
1382 CLASS (xmlregistry)->save_func (xmlregistry, "<capscomp>\n");
1383 PUT_ESCAPED ("name", caps->name);
1384 PUT_ESCAPED ("type", gst_type_find_by_id (caps->id)->mime);
1386 if (caps->properties) {
1387 CLASS (xmlregistry)->save_func (xmlregistry, "<properties>\n");
1388 gst_xml_registry_save_props (xmlregistry, caps->properties);
1389 CLASS (xmlregistry)->save_func (xmlregistry, "</properties>\n");
1391 CLASS (xmlregistry)->save_func (xmlregistry, "</capscomp>\n");
1398 gst_xml_registry_save_pad_template (GstXMLRegistry *xmlregistry, GstPadTemplate *template)
1402 PUT_ESCAPED ("nametemplate", template->name_template);
1403 CLASS (xmlregistry)->save_func (xmlregistry, "<direction>%s</direction>\n", (template->direction == GST_PAD_SINK? "sink":"src"));
1405 switch (template->presence) {
1406 case GST_PAD_ALWAYS:
1407 presence = "always";
1409 case GST_PAD_SOMETIMES:
1410 presence = "sometimes";
1412 case GST_PAD_REQUEST:
1413 presence = "request";
1416 presence = "unknown";
1419 CLASS (xmlregistry)->save_func (xmlregistry, "<presence>%s</presence>\n", presence);
1421 if (GST_PAD_TEMPLATE_CAPS (template)) {
1422 CLASS (xmlregistry)->save_func (xmlregistry, "<caps>\n");
1423 gst_xml_registry_save_caps (xmlregistry, GST_PAD_TEMPLATE_CAPS (template));
1424 CLASS (xmlregistry)->save_func (xmlregistry, "</caps>\n");
1430 gst_xml_registry_save_feature (GstXMLRegistry *xmlregistry, GstPluginFeature *feature)
1432 PUT_ESCAPED ("name", feature->name);
1434 if (feature->rank > 0) {
1435 gint rank = feature->rank;
1436 CLASS (xmlregistry)->save_func (xmlregistry, "<rank>%d</rank>\n", rank);
1439 if (GST_IS_ELEMENT_FACTORY (feature)) {
1440 GstElementFactory *factory = GST_ELEMENT_FACTORY (feature);
1443 PUT_ESCAPED ("longname", factory->details->longname);
1444 PUT_ESCAPED ("class", factory->details->klass);
1445 PUT_ESCAPED ("description", factory->details->description);
1446 PUT_ESCAPED ("license", factory->details->license);
1447 PUT_ESCAPED ("version", factory->details->version);
1448 PUT_ESCAPED ("author", factory->details->author);
1449 PUT_ESCAPED ("copyright", factory->details->copyright);
1451 templates = factory->padtemplates;
1454 GstPadTemplate *template = GST_PAD_TEMPLATE (templates->data);
1456 CLASS (xmlregistry)->save_func (xmlregistry, "<padtemplate>\n");
1457 gst_xml_registry_save_pad_template (xmlregistry, template);
1458 CLASS (xmlregistry)->save_func (xmlregistry, "</padtemplate>\n");
1460 templates = g_list_next (templates);
1463 else if (GST_IS_TYPE_FACTORY (feature)) {
1464 GstTypeFactory *factory = GST_TYPE_FACTORY (feature);
1466 PUT_ESCAPED ("mime", factory->mime);
1467 PUT_ESCAPED ("extensions", factory->exts);
1468 if (factory->typefindfunc) {
1469 CLASS (xmlregistry)->save_func (xmlregistry, "<typefind/>\n");
1472 else if (GST_IS_SCHEDULER_FACTORY (feature)) {
1473 PUT_ESCAPED ("longdesc", GST_SCHEDULER_FACTORY (feature)->longdesc);
1475 else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
1476 PUT_ESCAPED ("longdesc", GST_AUTOPLUG_FACTORY (feature)->longdesc);
1478 else if (GST_IS_INDEX_FACTORY (feature)) {
1479 PUT_ESCAPED ("longdesc", GST_INDEX_FACTORY (feature)->longdesc);
1481 else if (GST_IS_URI_HANDLER (feature)) {
1482 GstURIHandler *handler = GST_URI_HANDLER (feature);
1484 PUT_ESCAPED ("uri", handler->uri);
1485 PUT_ESCAPED ("longdesc", handler->longdesc);
1486 PUT_ESCAPED ("element", handler->element);
1487 PUT_ESCAPED ("property", handler->property);
1494 gst_xml_registry_save_plugin (GstXMLRegistry *xmlregistry, GstPlugin *plugin)
1498 PUT_ESCAPED ("name", plugin->name);
1499 PUT_ESCAPED ("longname", plugin->longname);
1500 PUT_ESCAPED ("filename", plugin->filename);
1502 walk = plugin->features;
1505 GstPluginFeature *feature = GST_PLUGIN_FEATURE (walk->data);
1507 CLASS (xmlregistry)->save_func (xmlregistry, "<feature typename=\"%s\">\n", g_type_name (G_OBJECT_TYPE (feature)));
1508 gst_xml_registry_save_feature (xmlregistry, feature);
1509 CLASS (xmlregistry)->save_func (xmlregistry, "</feature>\n");
1511 walk = g_list_next (walk);
1518 gst_xml_registry_save (GstRegistry *registry)
1521 GstXMLRegistry *xmlregistry;
1523 g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
1524 g_return_val_if_fail (registry->flags & GST_REGISTRY_WRITABLE, FALSE);
1526 xmlregistry = GST_XML_REGISTRY (registry);
1528 if (!CLASS (xmlregistry)->open_func (xmlregistry, GST_XML_REGISTRY_WRITE)) {
1532 CLASS (xmlregistry)->save_func (xmlregistry, "<?xml version=\"1.0\"?>\n");
1533 CLASS (xmlregistry)->save_func (xmlregistry, "<GST-PluginRegistry>\n");
1535 walk = g_list_last (gst_registry_get_path_list (GST_REGISTRY (registry)));
1537 CLASS (xmlregistry)->save_func (xmlregistry, "<gst-plugin-paths>\n");
1539 CLASS (xmlregistry)->save_func (xmlregistry, "<path>");
1540 CLASS (xmlregistry)->save_func (xmlregistry, (gchar*)walk->data);
1541 CLASS (xmlregistry)->save_func (xmlregistry, "</path>\n");
1542 walk = g_list_previous (walk);
1544 CLASS (xmlregistry)->save_func (xmlregistry, "</gst-plugin-paths>\n");
1546 walk = g_list_last (registry->plugins);
1549 GstPlugin *plugin = GST_PLUGIN (walk->data);
1551 CLASS (xmlregistry)->save_func (xmlregistry, "<plugin>\n");
1552 gst_xml_registry_save_plugin (xmlregistry, plugin);
1553 CLASS (xmlregistry)->save_func (xmlregistry, "</plugin>\n");
1555 walk = g_list_previous (walk);
1557 CLASS (xmlregistry)->save_func (xmlregistry, "</GST-PluginRegistry>\n");
1559 CLASS (xmlregistry)->close_func (xmlregistry);
1565 gst_xml_registry_rebuild_recurse (GstXMLRegistry *registry,
1566 const gchar *directory)
1571 dir = g_dir_open (directory, 0, NULL);
1574 const gchar *dirent;
1576 while ((dirent = g_dir_read_name (dir))) {
1579 if (*dirent == '=') {
1580 /* =build, =inst, etc. -- automake distcheck directories */
1584 dirname = g_strjoin ("/", directory, dirent, NULL);
1585 ret = g_list_concat (ret, gst_xml_registry_rebuild_recurse (registry, dirname));
1590 if (strstr (directory, ".so")) {
1593 if ((temp = strstr (directory, ".so")) &&
1594 (!strcmp (temp, ".so"))) {
1595 ret = g_list_prepend (ret, gst_plugin_new (directory));
1604 gst_xml_registry_rebuild (GstRegistry *registry)
1606 GList *walk = NULL, *plugins = NULL, *prune = NULL;
1607 GError *error = NULL;
1609 GstXMLRegistry *xmlregistry = GST_XML_REGISTRY (registry);
1611 walk = registry->paths;
1614 gchar *path = (gchar *) walk->data;
1616 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING,
1617 "Rebuilding registry %p in directory %s...", registry, path);
1619 plugins = g_list_concat (plugins,
1620 gst_xml_registry_rebuild_recurse (xmlregistry,
1623 walk = g_list_next (walk);
1626 plugins = g_list_reverse (plugins);
1629 length = g_list_length (plugins);
1633 g_assert (walk->data);
1634 if (gst_plugin_load_plugin (GST_PLUGIN (walk->data), NULL)) {
1635 prune = g_list_prepend (prune, walk->data);
1636 gst_registry_add_plugin (registry, GST_PLUGIN (walk->data));
1639 walk = g_list_next (walk);
1644 plugins = g_list_remove (plugins, walk->data);
1645 walk = g_list_next (walk);
1647 g_list_free (prune);
1649 } while (g_list_length (plugins) != length);
1653 if (gst_plugin_load_plugin (GST_PLUGIN (walk->data), &error)) {
1654 g_warning ("Bizarre behavior: plugin %s actually loaded",
1655 ((GstPlugin *) walk->data)->filename);
1657 GST_CAT_INFO (GST_CAT_PLUGIN_LOADING, "Plugin %s failed to load: %s",
1658 ((GstPlugin *) walk->data)->filename, error->message);
1659 g_print ("Plugin %s failed to load\n",
1660 ((GstPlugin *) walk->data)->filename);
1662 g_free (((GstPlugin *) walk->data)->filename);
1663 g_free (walk->data);
1664 g_error_free (error);
1668 walk = g_list_next (walk);