Commit 7ccc2cf9 authored by Wim Taymans's avatar Wim Taymans

Externalized the plugin information in /etc/gstreamer/reg.xml

Original commit message from CVS:
Externalized the plugin information in /etc/gstreamer/reg.xml
- no need to do a plugin_load_all()
- plugins are loaded when needed
- typedetect functions are loaded when needed (still buggy)
- no need to check for the existance of the plugin in the codecs
- added gstreamer-register to create the reg.xml file
- renamed launch to gstreamer-launch
- plugins need to register the typefactory they provide
modified the plugins to meet the new design
modified the plugins to correctly set their pad types
autoplugging can be done without loading the plugins now
parent a703c01d
......@@ -21,20 +21,21 @@ int main(int argc,char *argv[])
}
gst_init(&argc,&argv);
gst_plugin_load_all();
g_print("\n");
/* create a new bin to hold the elements */
pipeline = gst_pipeline_new("pipeline");
g_assert(pipeline != NULL);
/* create a disk reader */
disksrc = gst_elementfactory_make("disksrc", "disk_source");
g_assert(disksrc != NULL);
gtk_object_set(GTK_OBJECT(disksrc),"location", argv[1],NULL);
gtk_signal_connect(GTK_OBJECT(disksrc),"eos",
GTK_SIGNAL_FUNC(eos),NULL);
/* and an audio sink */
audiosink = gst_elementfactory_make("audiosink", "play_audio");
g_assert(audiosink != NULL);
/* add objects to the main pipeline */
gst_bin_add(GST_BIN(pipeline), disksrc);
......
......@@ -32,10 +32,10 @@ extern gint _gst_trace_on;
void gst_init(int *argc,char **argv[]) {
GstTrace *gst_trace;
gtk_init(argc,argv);
if (!g_thread_supported()) g_thread_init (NULL);
gtk_init(argc,argv);
_gst_type_initialize();
_gst_plugin_initialize();
_gst_buffer_initialize();
......@@ -48,8 +48,8 @@ void gst_init(int *argc,char **argv[]) {
gst_elementfactory_register(gst_elementfactory_new(
"thread",gst_thread_get_type(),&gst_thread_details));
gst_plugin_load("libgsttypes.so");
gst_plugin_load("libgstelements.so");
//gst_plugin_load_elementfactory("gsttypes");
//gst_plugin_load("libgstelements.so");
_gst_trace_on = 0;
if (_gst_trace_on) {
......
......@@ -199,6 +199,9 @@ GstElement *gst_elementfactory_create(GstElementFactory *factory,
// FIXME this name is wrong, probably so is the one above it
GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name);
xmlNodePtr gst_elementfactory_save_thyself(GstElementFactory *factory, xmlNodePtr parent);
GstElementFactory *gst_elementfactory_load_thyself(xmlNodePtr parent);
int gst_element_loopfunc_wrapper(int argc,char **argv);
#ifdef __cplusplus
......
......@@ -18,6 +18,7 @@
*/
#include <gst/gstelement.h>
#include <gst/gstplugin.h>
/* global list of registered elementfactories */
......@@ -113,6 +114,9 @@ GstElement *gst_elementfactory_create(GstElementFactory *factory,
GstElementClass *oclass;
g_return_val_if_fail(factory != NULL, NULL);
factory = gst_plugin_load_elementfactory(factory->name);
g_return_val_if_fail(factory->type != 0, NULL);
// create an instance of the element
......@@ -133,6 +137,7 @@ GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name) {
GstElementFactory *factory;
GstElement *element;
gst_plugin_load_elementfactory(factoryname);
factory = gst_elementfactory_find(factoryname);
if (factory == NULL) return NULL;
element = gst_elementfactory_create(factory,name);
......@@ -151,3 +156,89 @@ void gst_elementfactory_add_sink(GstElementFactory *elementfactory, guint16 id)
elementfactory->sink_types = g_list_prepend(elementfactory->sink_types, GUINT_TO_POINTER(type));
}
xmlNodePtr gst_elementfactory_save_thyself(GstElementFactory *factory, xmlNodePtr parent) {
GList *types;
xmlNodePtr subtree;
xmlNewChild(parent,NULL,"name",factory->name);
xmlNewChild(parent,NULL,"longname", factory->details->longname);
xmlNewChild(parent,NULL,"class", factory->details->class);
xmlNewChild(parent,NULL,"description", factory->details->description);
xmlNewChild(parent,NULL,"version", factory->details->version);
xmlNewChild(parent,NULL,"author", factory->details->author);
xmlNewChild(parent,NULL,"copyright", factory->details->copyright);
types = factory->src_types;
if (types) {
subtree = xmlNewChild(parent,NULL,"sources",NULL);
while (types) {
guint16 typeid = GPOINTER_TO_UINT(types->data);
GstType *type = gst_type_find_by_id(typeid);
gst_type_save_thyself(type, subtree);
types = g_list_next(types);
}
}
types = factory->sink_types;
if (types) {
subtree = xmlNewChild(parent,NULL,"sinks",NULL);
while (types) {
guint16 typeid = GPOINTER_TO_UINT(types->data);
GstType *type = gst_type_find_by_id(typeid);
gst_type_save_thyself(type, subtree);
types = g_list_next(types);
}
}
return parent;
}
GstElementFactory *gst_elementfactory_load_thyself(xmlNodePtr parent) {
GstElementFactory *factory = g_new0(GstElementFactory, 1);
xmlNodePtr children = parent->childs;
factory->details = g_new0(GstElementDetails, 1);
factory->sink_types = NULL;
factory->src_types = NULL;
while (children) {
if (!strcmp(children->name, "name")) {
factory->name = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "longname")) {
factory->details->longname = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "class")) {
factory->details->class = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "description")) {
factory->details->description = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "version")) {
factory->details->version = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "author")) {
factory->details->author = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "copyright")) {
factory->details->copyright = g_strdup(xmlNodeGetContent(children));
}
if (!strcmp(children->name, "sources")) {
guint16 typeid = gst_type_load_thyself(children);
gst_type_add_src(typeid, factory);
}
if (!strcmp(children->name, "sinks")) {
guint16 typeid = gst_type_load_thyself(children);
gst_type_add_sink(typeid, factory);
}
children = children->next;
}
return factory;
}
......@@ -28,6 +28,8 @@
#include "config.h"
#undef PLUGINS_USE_SRCDIR
/* list of loaded modules and its sequence number */
GList *_gst_modules;
gint _gst_modules_seqno;
......@@ -37,34 +39,49 @@ gint _gst_plugins_seqno;
/* list of paths to check for plugins */
GList *_gst_plugin_paths;
GList *_gst_libraries;
gint _gst_libraries_seqno;
/* whether or not to spew library load issues */
gboolean _gst_plugin_spew = FALSE;
void _gst_plugin_initialize() {
xmlDocPtr doc;
_gst_modules = NULL;
_gst_modules_seqno = 0;
_gst_plugins = NULL;
_gst_plugins_seqno = 0;
_gst_plugin_paths = NULL;
_gst_libraries = NULL;
_gst_libraries_seqno = 0;
/* add the main (installed) library path */
_gst_plugin_paths = g_list_prepend(_gst_plugin_paths,PLUGINS_DIR);
_gst_plugin_paths = g_list_append(_gst_plugin_paths,PLUGINS_DIR);
/* if this is set, we add build-directory paths to the list */
#ifdef PLUGINS_USE_SRCDIR
/* the catch-all plugins directory */
_gst_plugin_paths = g_list_prepend(_gst_plugin_paths,
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
PLUGINS_SRCDIR "/plugins");
/* the libreary directory */
_gst_plugin_paths = g_list_prepend(_gst_plugin_paths,
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
PLUGINS_SRCDIR "/libs");
/* location libgstelements.so */
_gst_plugin_paths = g_list_prepend(_gst_plugin_paths,
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/elements");
_gst_plugin_paths = g_list_prepend(_gst_plugin_paths,
_gst_plugin_paths = g_list_append(_gst_plugin_paths,
PLUGINS_SRCDIR "/gst/types");
#endif /* PLUGINS_USE_SRCDIR */
doc = xmlParseFile("/etc/gstreamer/reg.xml");
if (!doc || strcmp(doc->root->name, "GST-PluginRegistry")) {
g_print("gstplugin: registry needs rebuild\n");
gst_plugin_load_all();
return;
}
gst_plugin_load_thyself(doc->root);
}
static gboolean gst_plugin_load_recurse(gchar *directory,gchar *name) {
......@@ -128,8 +145,23 @@ void gst_plugin_load_all() {
* Returns: whether the library was loaded or not
*/
gboolean gst_library_load(gchar *name) {
gboolean res;
GList *libraries = _gst_libraries;
while (libraries) {
if (!strcmp((gchar *)libraries->data, name)) return TRUE;
libraries = g_list_next(libraries);
}
// for now this is the same
return gst_plugin_load(name);
res = gst_plugin_load(name);
if (res) {
_gst_libraries = g_list_prepend(_gst_libraries, name);
}
return res;
}
/**
......@@ -145,7 +177,7 @@ gboolean gst_plugin_load(gchar *name) {
GList *path;
gchar *libspath;
// g_print("attempting to load plugin '%s'\n",name);
//g_print("attempting to load plugin '%s'\n",name);
path = _gst_plugin_paths;
while (path != NULL) {
......@@ -177,20 +209,35 @@ gboolean gst_plugin_load_absolute(gchar *name) {
GModule *module;
GstPluginInitFunc initfunc;
GstPlugin *plugin;
GList *plugins;
//g_print("trying to absolute load '%s\n",name);
if (g_module_supported() == FALSE) {
g_print("wow, you built this on a platform without dynamic loading???\n");
g_print("gstplugin: wow, you built this on a platform without dynamic loading???\n");
return FALSE;
}
plugins = _gst_plugins;
while (plugins) {
plugin = (GstPlugin *)plugins->data;
if (!strcmp(plugin->filename, name) && plugin->loaded) {
_gst_plugins = g_list_append(_gst_plugins,plugin);
return TRUE;
}
plugins = g_list_next(plugins);
}
//g_print("trying to absolute load '%s\n",name);
module = g_module_open(name,G_MODULE_BIND_LAZY);
if (module != NULL) {
if (g_module_symbol(module,"plugin_init",(gpointer *)&initfunc)) {
if ((plugin = (initfunc)(module))) {
GList *factories;
g_print("gstplugin: plugin %s loaded\n", plugin->name);
plugin->filename = g_strdup(name);
plugin->loaded = TRUE;
_gst_modules = g_list_append(_gst_modules,module);
_gst_modules_seqno++;
_gst_plugins = g_list_append(_gst_plugins,plugin);
......@@ -203,7 +250,7 @@ gboolean gst_plugin_load_absolute(gchar *name) {
return TRUE;
}
}
return TRUE;
return TRUE;
} else if (_gst_plugin_spew) {
// if (strstr(g_module_error(),"No such") == NULL)
gst_info("error loading plugin: %s\n",g_module_error());
......@@ -227,6 +274,7 @@ GstPlugin *gst_plugin_new(gchar *name) {
plugin->longname = NULL;
plugin->types = NULL;
plugin->elements = NULL;
plugin->loaded = FALSE;
return plugin;
}
......@@ -253,7 +301,7 @@ void gst_plugin_set_longname(GstPlugin *plugin,gchar *longname) {
*
* Returns: pointer to the #GstPlugin if found, NULL otherwise
*/
GstPlugin *gst_plugin_find(gchar *name) {
GstPlugin *gst_plugin_find(const gchar *name) {
GList *plugins = _gst_plugins;
g_return_val_if_fail(name != NULL, NULL);
......@@ -262,8 +310,9 @@ GstPlugin *gst_plugin_find(gchar *name) {
GstPlugin *plugin = (GstPlugin *)plugins->data;
// g_print("plugin name is '%s'\n",plugin->name);
if (plugin->name) {
if (!strcmp(plugin->name,name))
if (!strcmp(plugin->name,name)) {
return plugin;
}
}
plugins = g_list_next(plugins);
}
......@@ -289,7 +338,7 @@ GstElementFactory *gst_plugin_find_elementfactory(gchar *name) {
factories = ((GstPlugin *)(plugins->data))->elements;
while (factories) {
factory = (GstElementFactory*)(factories->data);
if (!strcmp(gst_element_get_name(GST_ELEMENT(factory)),name))
if (!strcmp(factory->name,name))
return (GstElementFactory*)(factory);
factories = g_list_next(factories);
}
......@@ -299,6 +348,69 @@ GstElementFactory *gst_plugin_find_elementfactory(gchar *name) {
return NULL;
}
GstElementFactory *gst_plugin_load_elementfactory(gchar *name) {
GList *plugins, *factories;
GstElementFactory *factory = NULL;
GstPlugin *plugin;
g_return_val_if_fail(name != NULL, NULL);
plugins = _gst_plugins;
while (plugins) {
plugin = (GstPlugin *)plugins->data;
factories = plugin->elements;
while (factories) {
factory = (GstElementFactory*)(factories->data);
if (!strcmp(factory->name,name)) {
if (!plugin->loaded) {
g_print("gstplugin: loading element factory %s from plugin %s\n", name, plugin->name);
_gst_plugins = g_list_remove(_gst_plugins, plugin);
if (!gst_plugin_load_absolute(plugin->filename)) {
g_print("gstplugin: error loading element factory %s from plugin %s\n", name, plugin->name);
}
factory = gst_plugin_find_elementfactory(factory->name);
}
return factory;
}
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return factory;
}
void gst_plugin_load_typefactory(gchar *mime) {
GList *plugins, *factories;
GstTypeFactory *factory;
GstPlugin *plugin;
g_return_if_fail(mime != NULL);
plugins = _gst_plugins;
while (plugins) {
plugin = (GstPlugin *)plugins->data;
factories = plugin->types;
while (factories) {
factory = (GstTypeFactory*)(factories->data);
if (!strcmp(factory->mime,mime)) {
if (!plugin->loaded) {
g_print("gstplugin: loading type factory for \"%s\" from plugin %s\n", mime, plugin->name);
_gst_plugins = g_list_remove(_gst_plugins, plugin);
if (!gst_plugin_load_absolute(plugin->filename)) {
g_print("gstplugin: error loading type factory \"%s\" from plugin %s\n", mime, plugin->name);
}
}
return;
}
factories = g_list_next(factories);
}
plugins = g_list_next(plugins);
}
return;
}
/**
* gst_plugin_add_factory:
* @plugin: plugin to add factory to
......@@ -314,6 +426,14 @@ void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory) {
plugin->elements = g_list_append(plugin->elements,factory);
}
void gst_plugin_add_type(GstPlugin *plugin,GstTypeFactory *factory) {
g_return_if_fail(plugin != NULL);
g_return_if_fail(factory != NULL);
// g_print("adding factory to plugin\n");
plugin->types = g_list_append(plugin->types,factory);
}
/**
* gst_plugin_get_list:
*
......@@ -324,3 +444,97 @@ void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory) {
GList *gst_plugin_get_list() {
return _gst_plugins;
}
xmlNodePtr gst_plugin_save_thyself(xmlNodePtr parent) {
xmlNodePtr tree, subtree;
GList *plugins = NULL, *elements = NULL, *types = NULL;
plugins = gst_plugin_get_list();
while (plugins) {
GstPlugin *plugin = (GstPlugin *)plugins->data;
tree = xmlNewChild(parent,NULL,"plugin",NULL);
xmlNewChild(tree,NULL,"name",plugin->name);
xmlNewChild(tree,NULL,"longname",plugin->longname);
xmlNewChild(tree,NULL,"filename",plugin->filename);
types = plugin->types;
while (types) {
GstTypeFactory *factory = (GstTypeFactory *)types->data;
subtree = xmlNewChild(tree,NULL,"type",NULL);
gst_typefactory_save_thyself(factory, subtree);
types = g_list_next(types);
}
elements = plugin->elements;
while (elements) {
GstElementFactory *factory = (GstElementFactory *)elements->data;
subtree = xmlNewChild(tree,NULL,"element",NULL);
gst_elementfactory_save_thyself(factory, subtree);
elements = g_list_next(elements);
}
plugins = g_list_next(plugins);
}
return parent;
}
void gst_plugin_load_thyself(xmlNodePtr parent) {
xmlNodePtr kinderen;
gint elementcount = 0;
gint typecount = 0;
kinderen = parent->childs; // Dutch invasion :-)
while (kinderen) {
if (!strcmp(kinderen->name, "plugin")) {
xmlNodePtr field = kinderen->childs;
GstPlugin *plugin = (GstPlugin *)g_malloc(sizeof(GstPlugin));
plugin->elements = NULL;
plugin->types = NULL;
plugin->loaded = FALSE;
while (field) {
if (!strcmp(field->name, "name")) {
if (gst_plugin_find(xmlNodeGetContent(field))) {
g_free(plugin);
plugin = NULL;
break;
}
else {
plugin->name = g_strdup(xmlNodeGetContent(field));
}
}
else if (!strcmp(field->name, "longname")) {
plugin->longname = g_strdup(xmlNodeGetContent(field));
}
else if (!strcmp(field->name, "filename")) {
plugin->filename = g_strdup(xmlNodeGetContent(field));
}
else if (!strcmp(field->name, "element")) {
GstElementFactory *factory = gst_elementfactory_load_thyself(field);
plugin->elements = g_list_prepend(plugin->elements, factory);
elementcount++;
}
else if (!strcmp(field->name, "type")) {
GstTypeFactory *factory = gst_typefactory_load_thyself(field);
guint16 typeid = gst_type_find_by_mime(factory->mime);
if (!typeid) {
typeid = gst_type_register(factory);
}
plugin->types = g_list_prepend(plugin->types, factory);
typecount++;
}
field = field->next;
}
if (plugin) {
_gst_plugins = g_list_prepend(_gst_plugins, plugin);
}
}
kinderen = kinderen->next;
}
g_print("gstplugin: added %d registered factories and %d types\n", elementcount, typecount);
}
......@@ -37,7 +37,8 @@ struct _GstPlugin {
GList *types; /* list of types provided */
GList *elements; /* list of elements provided */
GList *identifiers; /* list of identifiers */
gboolean loaded; /* if the plugin is in memory */
};
......@@ -53,9 +54,16 @@ gboolean gst_library_load(gchar *name);
gboolean gst_plugin_load_absolute(gchar *name);
void gst_plugin_add_factory(GstPlugin *plugin,GstElementFactory *factory);
void gst_plugin_add_type(GstPlugin *plugin,GstTypeFactory *factory);
GstPlugin *gst_plugin_find(gchar *name);
GstPlugin *gst_plugin_find(const gchar *name);
GList *gst_plugin_get_list();
GstElementFactory *gst_plugin_find_elementfactory(gchar *name);
GstElementFactory *gst_plugin_load_elementfactory(gchar *name);
void gst_plugin_load_typefactory(gchar *mime);
xmlNodePtr gst_plugin_save_thyself(xmlNodePtr parent);
void gst_plugin_load_thyself(xmlNodePtr parent);
#endif /* __GST_PLUGIN_H__ */
......@@ -43,6 +43,8 @@ struct _gst_type_node
};
typedef struct _gst_type_node gst_type_node;
static gboolean gst_type_typefind_dummy(GstBuffer *buffer, gpointer priv);
/* we keep a (spase) matrix in the hashtable like:
*
* type_id list of factories hashed by src type_id
......@@ -58,6 +60,7 @@ typedef struct _gst_type_node gst_type_node;
**/
void _gst_type_initialize() {
_gst_types = NULL;
_gst_maxtype = 1; /* type 0 is undefined */
......@@ -70,10 +73,9 @@ guint16 gst_type_register(GstTypeFactory *factory) {
g_return_val_if_fail(factory != NULL, 0);
// id = gst_type_find_by_mime(factory->mime);
id = 0;
id = gst_type_find_by_mime(factory->mime);
if (!id) {
type = (GstType *)g_malloc(sizeof(GstType));
type = g_new0(GstType, 1);
type->id = _gst_maxtype++;
type->mime = factory->mime;
......@@ -85,6 +87,7 @@ guint16 gst_type_register(GstTypeFactory *factory) {
_gst_types = g_list_prepend(_gst_types,type);
id = type->id;
} else {
type = gst_type_find_by_id(id);
/* now we want to try to merge the types and return the original */
......@@ -92,19 +95,22 @@ guint16 gst_type_register(GstTypeFactory *factory) {
/* FIXME: do extension merging here, not that easy */
/* if there is no existing typefind function, try to use new one */
if (!type->typefindfunc && factory->typefindfunc)
if ((type->typefindfunc == gst_type_typefind_dummy ||
type->typefindfunc == NULL) && factory->typefindfunc)
type->typefindfunc = factory->typefindfunc;
}
return id;
}
guint16 gst_type_find_by_mime(gchar *mime) {
GList *walk = _gst_types;
static guint16 gst_type_find_by_mime_func(gchar *mime) {
GList *walk;
GstType *type;
gint typelen,mimelen;
gchar *search, *found;
walk = _gst_types;
// DEBUG("searching for '%s'\n",mime);
mimelen = strlen(mime);
while (walk) {
......@@ -132,6 +138,18 @@ guint16 gst_type_find_by_mime(gchar *mime) {
return 0;