diff --git a/examples/xml/createxml.c b/examples/xml/createxml.c index 36810a823f..9a32100230 100644 --- a/examples/xml/createxml.c +++ b/examples/xml/createxml.c @@ -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 */ diff --git a/examples/xml/runxml.c b/examples/xml/runxml.c index b3f8739cf1..38b521939e 100644 --- a/examples/xml/runxml.c +++ b/examples/xml/runxml.c @@ -14,6 +14,7 @@ int main(int argc,char *argv[]) { GstXML *xml; GstElement *bin; + GstElement *disk; gst_init(&argc,&argv); diff --git a/gst/Makefile.am b/gst/Makefile.am index e21c0404ed..441a203346 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -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) diff --git a/gst/elements/gstaudiosink.c b/gst/elements/gstaudiosink.c index fc09a75803..337456862b 100644 --- a/gst/elements/gstaudiosink.c +++ b/gst/elements/gstaudiosink.c @@ -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); diff --git a/gst/gstbin.c b/gst/gstbin.c index 38ad526966..b88e4f17a7 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -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)) diff --git a/gst/gstelement.c b/gst/gstelement.c index 40c06dbb43..1a3d1ca7b8 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -18,7 +18,7 @@ */ #include - +#include /* 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. diff --git a/gst/gstelement.h b/gst/gstelement.h index 4024cd0335..9e94ecd220 100644 --- a/gst/gstelement.h +++ b/gst/gstelement.h @@ -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); diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c index d1d6796bcb..145f067d0a 100644 --- a/gst/gstelementfactory.c +++ b/gst/gstelementfactory.c @@ -17,6 +17,10 @@ * Boston, MA 02111-1307, USA. */ +//#define DEBUG_ENABLED + +#include + #include #include @@ -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; diff --git a/gst/gstpad.c b/gst/gstpad.c index 92661c85c5..accfd018e2 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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) { diff --git a/gst/gstpad.h b/gst/gstpad.h index 9e2083ee89..e92eff360f 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -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 diff --git a/gst/gstthread.c b/gst/gstthread.c index c26f018e1e..157a241bba 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -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; } diff --git a/gst/gstxml.c b/gst/gstxml.c index c4ef8f2bc0..9ad5d763c2 100644 --- a/gst/gstxml.c +++ b/gst/gstxml.c @@ -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; } diff --git a/gst/gstxml.h b/gst/gstxml.h index a0adf592ee..c152f3a126 100644 --- a/gst/gstxml.h +++ b/gst/gstxml.h @@ -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 */ diff --git a/plugins/elements/gstaudiosink.c b/plugins/elements/gstaudiosink.c index fc09a75803..337456862b 100644 --- a/plugins/elements/gstaudiosink.c +++ b/plugins/elements/gstaudiosink.c @@ -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); diff --git a/tests/old/examples/xml/createxml.c b/tests/old/examples/xml/createxml.c index 36810a823f..9a32100230 100644 --- a/tests/old/examples/xml/createxml.c +++ b/tests/old/examples/xml/createxml.c @@ -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 */ diff --git a/tests/old/examples/xml/runxml.c b/tests/old/examples/xml/runxml.c index b3f8739cf1..38b521939e 100644 --- a/tests/old/examples/xml/runxml.c +++ b/tests/old/examples/xml/runxml.c @@ -14,6 +14,7 @@ int main(int argc,char *argv[]) { GstXML *xml; GstElement *bin; + GstElement *disk; gst_init(&argc,&argv);