Loading and saving of XML pipeline descriptions.

Original commit message from CVS:
Loading and saving of XML pipeline descriptions.
GladeXML like operation implemented (you can retrieve parts of a pipeline)
This commit is contained in:
Wim Taymans 2000-09-27 19:33:10 +00:00
parent 9fec44e1c5
commit 4e7f031df7
16 changed files with 299 additions and 33 deletions

View file

@ -16,9 +16,11 @@ int main(int argc,char *argv[])
gst_init(&argc,&argv);
/* create a new thread to hold the elements */
thread = gst_thread_new("thread");
//thread = gst_thread_new("thread");
thread = gst_elementfactory_make("thread", "thread");
g_assert(thread != NULL);
thread2 = gst_thread_new("thread2");
thread2 = gst_elementfactory_make("thread", "thread2");
//thread2 = gst_thread_new("thread2");
g_assert(thread2 != NULL);
/* create a new bin to hold the elements */

View file

@ -14,6 +14,7 @@ int main(int argc,char *argv[])
{
GstXML *xml;
GstElement *bin;
GstElement *disk;
gst_init(&argc,&argv);

View file

@ -76,7 +76,7 @@ noinst_HEADERS = \
gsti386.h \
gstppc.h
CFLAGS += -O2 -Wall
CFLAGS += -g -O2 -Wall
libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS)
libgst_la_LDFLAGS = -version-info $(STREAMER_CURRENT):$(STREAMER_REVISION):$(STREAMER_AGE)

View file

@ -153,7 +153,8 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
g_return_if_fail(audiosink != NULL);
g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
g_return_if_fail(audiosink->fd > 0);
if (audiosink->fd == -1) return;
ioctl(audiosink->fd,SNDCTL_DSP_RESET,0);

View file

@ -45,6 +45,7 @@ static void gst_bin_create_plan_func(GstBin *bin);
static void gst_bin_iterate_func(GstBin *bin);
static xmlNodePtr gst_bin_save_thyself(GstElement *element,xmlNodePtr parent);
static void gst_bin_restore_thyself(GstElement *element, xmlNodePtr parent, GHashTable *elements);
/* Bin signals and args */
enum {
@ -108,6 +109,7 @@ gst_bin_class_init(GstBinClass *klass) {
gstelement_class->change_state = gst_bin_change_state;
gstelement_class->save_thyself = gst_bin_save_thyself;
gstelement_class->restore_thyself = gst_bin_restore_thyself;
gstelement_class->elementfactory = gst_elementfactory_find("bin");
gtkobject_class->destroy = gst_bin_real_destroy;
@ -337,11 +339,17 @@ GstElement *gst_bin_get_by_name(GstBin *bin,gchar *name) {
g_return_val_if_fail(GST_IS_BIN(bin), NULL);
g_return_val_if_fail(name != NULL, NULL);
g_print("gstbin: lookup element \"%s\" in \"%s\"\n", name, gst_element_get_name(bin));
children = bin->children;
while (children) {
child = GST_ELEMENT(children->data);
if (!strcmp(child->name,name))
return child;
if (GST_IS_BIN(child)) {
GstElement *res = gst_bin_get_by_name(GST_BIN(child), name);
if (res)
return res;
}
children = g_list_next(children);
}
@ -363,7 +371,7 @@ GList *gst_bin_get_list(GstBin *bin) {
return bin->children;
}
static xmlNodePtr gst_bin_save_thyself(GstElement *element,xmlNodePtr parent) {
static xmlNodePtr gst_bin_save_thyself(GstElement *element, xmlNodePtr parent) {
GstBin *bin = GST_BIN(element);
xmlNodePtr childlist;
GList *children;
@ -380,7 +388,32 @@ static xmlNodePtr gst_bin_save_thyself(GstElement *element,xmlNodePtr parent) {
gst_element_save_thyself(child,childlist);
children = g_list_next(children);
}
return childlist;
return childlist;
}
static void gst_bin_restore_thyself(GstElement *element, xmlNodePtr parent, GHashTable *elements) {
GstBin *bin = GST_BIN(element);
xmlNodePtr field = parent->childs;
xmlNodePtr childlist;
g_print("gstbin: restore \"%s\"\n", gst_element_get_name(element));
while (field) {
if (!strcmp(field->name, "children")) {
childlist = field->childs;
while (childlist) {
if (!strcmp(childlist->name, "element")) {
GstElement *element = gst_element_load_thyself(childlist, elements);
gst_bin_add(bin, element);
}
childlist = childlist->next;
}
}
field = field->next;
}
}
void gst_bin_use_cothreads(GstBin *bin, gboolean enabled) {
@ -693,6 +726,8 @@ void gst_bin_iterate_func(GstBin *bin) {
entries = bin->entries;
}
g_assert(entries != NULL);
while (entries) {
entry = GST_ELEMENT(entries->data);
if (GST_IS_SRC(entry))

View file

@ -18,7 +18,7 @@
*/
#include <gst/gstelement.h>
#include <gst/gstxml.h>
/* Element signals and args */
enum {
@ -429,7 +429,7 @@ static gchar *_gst_element_type_names[] = {
* Returns: the new xml node
*/
xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {
xmlNodePtr self, arglist;
xmlNodePtr self;
GList *pads;
GstPad *pad;
GstElementClass *oclass;
@ -448,15 +448,15 @@ xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {
pads = element->pads;
while (pads) {
xmlNodePtr padtag = xmlNewChild(self,NULL,"pad",NULL);
pad = GST_PAD(pads->data);
// figure out if it's a direct pad or a ghostpad
if (GST_ELEMENT(pad->parent) == element)
gst_pad_save_thyself(pad,self);
gst_pad_save_thyself(pad,padtag);
pads = g_list_next(pads);
}
// output all args to the element
arglist = xmlNewChild(self,NULL,"args",NULL);
type = GTK_OBJECT_TYPE(element);
while (type != GTK_TYPE_INVALID) {
GtkArg *args;
@ -470,7 +470,7 @@ xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {
(flags && GTK_ARG_READABLE)) {
xmlNodePtr arg;
gtk_object_getv(GTK_OBJECT(element),1,&args[i]);
arg = xmlNewChild(arglist,NULL,"arg",NULL);
arg = xmlNewChild(self,NULL,"arg",NULL);
xmlNewChild(arg,NULL,"name",args[i].name);
switch (args[i].type) {
case GTK_TYPE_CHAR:
@ -495,7 +495,7 @@ xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {
break;
case GTK_TYPE_ULONG:
xmlNewChild(arg,NULL,"value",
g_strdup_printf("%ld",GTK_VALUE_ULONG(args[i])));
g_strdup_printf("%lu",GTK_VALUE_ULONG(args[i])));
break;
case GTK_TYPE_FLOAT:
xmlNewChild(arg,NULL,"value",
@ -520,6 +520,143 @@ xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent) {
return self;
}
/**
* gst_element_load_thyself:
* @parent: the xml parent node
*
* load the element based on the XML description
*
* Returns: the new element
*/
GstElement *gst_element_load_thyself(xmlNodePtr parent, GHashTable *elements) {
xmlNodePtr children = parent->childs;
GstElement *element;
GstElementClass *oclass;
guchar *name = NULL;
guchar *value = NULL;
guchar *type = NULL;
// first get the needed tags to cunstruct the element
while (children) {
if (!strcmp(children->name, "name")) {
name = g_strdup(xmlNodeGetContent(children));
}
else if (!strcmp(children->name, "type")) {
type = g_strdup(xmlNodeGetContent(children));
}
children = children->next;
}
g_assert(name != NULL);
g_assert(type != NULL);
g_print("gstelement: loading \"%s\" of type \"%s\"\n", name, type);
element = gst_elementfactory_make(type, name);
g_assert(element != NULL);
g_hash_table_insert(elements, gst_element_get_name(element), element);
// we have the element now, set the arguments and pads
children = parent->childs;
while (children) {
if (!strcmp(children->name, "pad")) {
gst_pad_load_and_connect(children, GST_OBJECT(element), elements);
}
else if (!strcmp(children->name, "arg")) {
xmlNodePtr child = children->childs;
while (child) {
if (!strcmp(child->name, "name")) {
name = g_strdup(xmlNodeGetContent(child));
}
else if (!strcmp(child->name, "value")) {
value = g_strdup(xmlNodeGetContent(child));
}
child = child->next;
}
if (name && value) {
GtkType type = GTK_OBJECT_TYPE(element);
GtkArgInfo *info;
gchar *result;
result = gtk_object_arg_get_info(type, name, &info);
if (result) {
g_print("gstelement: %s\n", result);
}
else if (info->arg_flags & GTK_ARG_WRITABLE) {
switch (info->type) {
case GTK_TYPE_STRING:
gtk_object_set(GTK_OBJECT(element), name, value, NULL);
break;
case GTK_TYPE_INT: {
gint i;
sscanf(value, "%d", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_LONG: {
glong i;
sscanf(value, "%ld", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_ULONG: {
gulong i;
sscanf(value, "%lu", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_BOOL: {
gboolean i = FALSE;
if (!strcmp("true", value)) i = TRUE;
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_CHAR: {
gchar i;
sscanf(value, "%c", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_UCHAR: {
guchar i;
sscanf(value, "%c", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_FLOAT: {
gfloat i;
sscanf(value, "%f", &i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
case GTK_TYPE_DOUBLE: {
gdouble i;
sscanf(value, "%g", (float *)&i);
gtk_object_set(GTK_OBJECT(element), name, i, NULL);
break;
}
default:
break;
}
}
}
}
children = children->next;
}
oclass = GST_ELEMENT_CLASS(GTK_OBJECT(element)->klass);
if (oclass->restore_thyself)
(oclass->restore_thyself)(element, parent, elements);
return element;
}
/**
* gst_element_set_manager:
* @element: Element to set manager of.

View file

@ -127,7 +127,7 @@ struct _GstElementClass {
/* create or read XML representation of self */
xmlNodePtr (*save_thyself)(GstElement *element,xmlNodePtr parent);
void (*restore_thyself)(GstElement *element,xmlNodePtr *self);
void (*restore_thyself)(GstElement *element, xmlNodePtr self, GHashTable *elements);
};
struct _GstElementDetails {
@ -149,7 +149,6 @@ struct _GstElementFactory {
GList *sink_types;
};
GtkType gst_element_get_type(void);
GstElement *gst_element_new(void);
@ -181,7 +180,7 @@ GstElementFactory *gst_element_get_factory(GstElement *element);
/* XML write and read */
xmlNodePtr gst_element_save_thyself(GstElement *element,xmlNodePtr parent);
GstElement *gst_element_load_thyself(xmlNodePtr parent, GHashTable *elements);
GstElementFactory *gst_elementfactory_new(gchar *name,GtkType type,
GstElementDetails *details);

View file

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
//#define DEBUG_ENABLED
#include <gst/gst.h>
#include <gst/gstelement.h>
#include <gst/gstplugin.h>
@ -53,6 +57,8 @@ GstElementFactory *gst_elementfactory_find(gchar *name) {
GList *walk;
GstElementFactory *factory;
DEBUG("gstelementfactory: find \"%s\"\n", name);
gst_plugin_load_elementfactory(name);
walk = _gst_elementfactories;
@ -118,11 +124,13 @@ GstElement *gst_elementfactory_create(GstElementFactory *factory,
g_return_val_if_fail(factory != NULL, NULL);
factory = gst_plugin_load_elementfactory(factory->name);
DEBUG("gstelementfactory: create \"%s\" \"%s\"\n", factory->name, name);
if (factory->type == 0) {
factory = gst_elementfactory_find(name);
factory = gst_plugin_load_elementfactory(factory->name);
//factory = gst_elementfactory_find(factory->name);
}
g_return_val_if_fail(factory != NULL, NULL);
g_return_val_if_fail(factory->type != 0, NULL);
// create an instance of the element
@ -155,6 +163,8 @@ GstElement *gst_elementfactory_make(gchar *factoryname,gchar *name) {
GstElementFactory *factory;
GstElement *element;
DEBUG("gstelementfactory: make \"%s\" \"%s\"\n", factoryname, name);
//gst_plugin_load_elementfactory(factoryname);
factory = gst_elementfactory_find(factoryname);
if (factory == NULL) return NULL;

View file

@ -424,23 +424,72 @@ static void gst_pad_real_destroy(GtkObject *object) {
g_list_free(pad->ghostparents);
}
/**
* gst_pad_handle_qos:
* @parent: the parent XML node to read the description from
* @element: the element that has the source pad
* @elements: a hashtable with elements
*
* Read the pad definition from the XML node and connect the given pad
* in element to a pad of an element in the hashtable.
*
* Returns: the new Pad definition.
*/
void gst_pad_load_and_connect(xmlNodePtr parent, GstObject *element, GHashTable *elements) {
xmlNodePtr field = parent->childs;
GstPad *pad, *targetpad;
guchar *peer;
gchar **split;
GstElement *target;
while (field) {
if (!strcmp(field->name, "name")) {
pad = gst_element_get_pad(GST_ELEMENT(element), xmlNodeGetContent(field));
}
else if (!strcmp(field->name, "peer")) {
peer = g_strdup(xmlNodeGetContent(field));
}
field = field->next;
}
g_return_if_fail(pad != NULL);
g_return_if_fail(peer != NULL);
split = g_strsplit(peer, ".", 2);
g_return_if_fail(split[0] != NULL);
g_return_if_fail(split[1] != NULL);
target = (GstElement *)g_hash_table_lookup(elements, split[0]);
if (target == NULL) goto cleanup;
targetpad = gst_element_get_pad(target, split[1]);
g_return_if_fail(targetpad != NULL);
gst_pad_connect(pad, targetpad);
cleanup:
g_strfreev(split);
}
xmlNodePtr gst_pad_save_thyself(GstPad *pad,xmlNodePtr parent) {
xmlNodePtr self;
GstPad *peer;
self = xmlNewChild(parent,NULL,"pad",NULL);
xmlNewChild(self,NULL,"name",pad->name);
xmlNewChild(parent,NULL,"name",pad->name);
if (pad->peer != NULL) {
peer = pad->peer;
// first check to see if the peer's parent's parent is the same
if (pad->parent->parent == peer->parent->parent)
//if (pad->parent->parent == peer->parent->parent)
// we just save it off
xmlNewChild(self,NULL,"peer",g_strdup_printf("%s.%s",
xmlNewChild(parent,NULL,"peer",g_strdup_printf("%s.%s",
GST_ELEMENT(peer->parent)->name,peer->name));
} else
xmlNewChild(self,NULL,"peer","");
xmlNewChild(parent,NULL,"peer","");
return self;
return parent;
}
xmlNodePtr gst_pad_ghost_save_thyself(GstPad *pad,GstElement *bin,xmlNodePtr parent) {

View file

@ -119,6 +119,7 @@ GstBuffer *gst_pad_pull(GstPad *pad);
void gst_pad_handle_qos(GstPad *pad, glong qos_message);
xmlNodePtr gst_pad_save_thyself(GstPad *pad,xmlNodePtr parent);
void gst_pad_load_and_connect(xmlNodePtr parent, GstObject *element, GHashTable *elements);
#ifdef __cplusplus

View file

@ -52,6 +52,7 @@ static void gst_thread_get_arg(GtkObject *object,GtkArg *arg,guint id);
static GstElementStateReturn gst_thread_change_state(GstElement *element);
static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent);
static void gst_thread_restore_thyself(GstElement *element,xmlNodePtr parent, GHashTable *elements);
static void gst_thread_prepare(GstThread *thread);
static void gst_thread_signal_thread(GstThread *thread);
@ -76,7 +77,7 @@ gst_thread_get_type(void) {
(GtkArgGetFunc)NULL,
(GtkClassInitFunc)NULL,
};
thread_type = gtk_type_unique(gst_bin_get_type(),&thread_info);
thread_type = gtk_type_unique(GST_TYPE_BIN,&thread_info);
}
return thread_type;
}
@ -93,13 +94,14 @@ gst_thread_class_init(GstThreadClass *klass) {
gstelement_class = (GstElementClass*)klass;
gstbin_class = (GstBinClass*)klass;
parent_class = gtk_type_class(gst_bin_get_type());
parent_class = gtk_type_class(GST_TYPE_BIN);
gtk_object_add_arg_type("GstThread::create_thread", GTK_TYPE_BOOL,
GTK_ARG_READWRITE, ARG_CREATE_THREAD);
gstelement_class->change_state = gst_thread_change_state;
gstelement_class->save_thyself = gst_thread_save_thyself;
gstelement_class->restore_thyself = gst_thread_restore_thyself;
gstelement_class->elementfactory = gst_elementfactory_find("thread");
gstbin_class->create_plan = gst_thread_create_plan_dummy;
@ -285,10 +287,17 @@ static void gst_thread_signal_thread(GstThread *thread) {
g_mutex_unlock(thread->lock);
}
static void gst_thread_restore_thyself(GstElement *element,xmlNodePtr parent, GHashTable *elements) {
g_print("gstthread: restore\n");
if (GST_ELEMENT_CLASS(parent_class)->restore_thyself)
GST_ELEMENT_CLASS(parent_class)->restore_thyself(element,parent, elements);
}
static xmlNodePtr gst_thread_save_thyself(GstElement *element,xmlNodePtr parent) {
xmlNewChild(parent,NULL,"type","thread");
if (GST_ELEMENT_CLASS(parent_class)->save_thyself)
GST_ELEMENT_CLASS(parent_class)->save_thyself(element,parent);
return NULL;
return NULL;
}

View file

@ -87,6 +87,7 @@ xmlDocPtr gst_xml_write(GstElement *element) {
*/
GstXML *gst_xml_new(const guchar *fname, const guchar *root) {
xmlDocPtr doc;
xmlNodePtr field;
GstXML *xml;
g_return_val_if_fail(fname != NULL, NULL);
@ -104,6 +105,17 @@ GstXML *gst_xml_new(const guchar *fname, const guchar *root) {
xml = GST_XML(gtk_type_new(GST_TYPE_XML));
xml->elements = g_hash_table_new(g_str_hash, g_str_equal);
field = doc->root->childs;
while (field) {
if (!strcmp(field->name, "element")) {
gst_element_load_thyself(field, xml->elements);
}
field = field->next;
}
return xml;
}
@ -119,11 +131,14 @@ GstXML *gst_xml_new(const guchar *fname, const guchar *root) {
* Returns: a pointer to a new GstElement
*/
GstElement *gst_xml_get_element(GstXML *xml, const guchar *name) {
GstElement *element;
g_return_val_if_fail(xml != NULL, NULL);
g_return_val_if_fail(name != NULL, NULL);
g_print("gstxml: getting element \"%s\" (implement me)\n", name);
g_print("gstxml: getting element \"%s\"\n", name);
return NULL;
element = g_hash_table_lookup(xml->elements, name);
return element;
}

View file

@ -44,6 +44,8 @@ typedef struct _GstXMLClass GstXMLClass;
struct _GstXML {
GtkObject object;
GHashTable *elements;
};
struct _GstXMLClass {
@ -59,6 +61,7 @@ xmlDocPtr gst_xml_write(GstElement *element);
GstXML *gst_xml_new(const guchar *fname, const guchar *root);
GstElement *gst_xml_get_element(GstXML *xml, const guchar *name);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View file

@ -153,7 +153,8 @@ void gst_audiosink_sync_parms(GstAudioSink *audiosink) {
g_return_if_fail(audiosink != NULL);
g_return_if_fail(GST_IS_AUDIOSINK(audiosink));
g_return_if_fail(audiosink->fd > 0);
if (audiosink->fd == -1) return;
ioctl(audiosink->fd,SNDCTL_DSP_RESET,0);

View file

@ -16,9 +16,11 @@ int main(int argc,char *argv[])
gst_init(&argc,&argv);
/* create a new thread to hold the elements */
thread = gst_thread_new("thread");
//thread = gst_thread_new("thread");
thread = gst_elementfactory_make("thread", "thread");
g_assert(thread != NULL);
thread2 = gst_thread_new("thread2");
thread2 = gst_elementfactory_make("thread", "thread2");
//thread2 = gst_thread_new("thread2");
g_assert(thread2 != NULL);
/* create a new bin to hold the elements */

View file

@ -14,6 +14,7 @@ int main(int argc,char *argv[])
{
GstXML *xml;
GstElement *bin;
GstElement *disk;
gst_init(&argc,&argv);