diff --git a/docs/manual/highlevel-xml.xml b/docs/manual/highlevel-xml.xml index 04cf7f9a95..e330616636 100644 --- a/docs/manual/highlevel-xml.xml +++ b/docs/manual/highlevel-xml.xml @@ -1,264 +1,17 @@ - XML in <application>GStreamer</application> + XML in <application>GStreamer</application> (deprecated) - GStreamer can use XML to store and load - its pipeline definitions. + GStreamer used to provide functions to + save pipeline definitions into XML format and later restore them + again from XML. - We will show you how you can save a pipeline to XML and how you can reload that - XML file again for later use. + This never really worked properly for all but the most simple use cases + though, and is also pretty much impossible to make work correctly in a + useful way due to the dynamic nature of almost all non-trivial GStreamer + pipelines. Consequently, this API has been deprecated and will be + removed at some point. Don't use it. - - - Turning GstElements into XML - - - We create a simple pipeline and write it to stdout with - gst_xml_write_file (). The following code constructs an MP3 player - pipeline and then writes out the XML both to stdout - and to a file. Use this program with one argument: the MP3 file on disk. - - - - -#include <stdlib.h> -#include <gst/gst.h> - -gboolean playing; - -int -main (int argc, char *argv[]) -{ - GstElement *filesrc, *osssink, *decode; - GstElement *pipeline; - - gst_init (&argc,&argv); - - if (argc != 2) { - g_print ("usage: %s <mp3 filename>\n", argv[0]); - exit (-1); - } - - /* create a new pipeline to hold the elements */ - pipeline = gst_element_factory_make ("pipeline", "pipeline"); - g_assert (pipeline != NULL); - - /* create a disk reader */ - filesrc = gst_element_factory_make ("filesrc", "disk_source"); - g_assert (filesrc != NULL); - g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); - - /* and an audio sink */ - osssink = gst_element_factory_make ("osssink", "play_audio"); - g_assert (osssink != NULL); - - decode = gst_element_factory_make ("mad", "decode"); - g_assert (decode != NULL); - - /* add objects to the main pipeline */ - gst_bin_add_many (GST_BIN (pipeline), filesrc, decode, osssink, NULL); - - gst_element_link_many (filesrc, decode, osssink, NULL); - - /* write the pipeline to stdout */ - gst_xml_write_file (GST_ELEMENT (pipeline), stdout); - - /* write the bin to a file */ - gst_xml_write_file (GST_ELEMENT (pipeline), fopen ("xmlTest.gst", "w")); - - exit (0); -} - - - - The most important line is: - - - gst_xml_write_file (GST_ELEMENT (pipeline), stdout); - - - gst_xml_write_file () will turn the given element into an xmlDocPtr that - is then formatted and saved to a file. To save to disk, pass the result - of a fopen(2) as the second argument. - - - The complete element hierarchy will be saved along with the inter element - pad links and the element parameters. Future GStreamer - versions will also allow you to store the signals in the XML file. - - - - - Loading a GstElement from an XML file - - Before an XML file can be loaded, you must create a GstXML object. - A saved XML file can then be loaded with the - gst_xml_parse_file (xml, filename, rootelement) method. - The root element can optionally left NULL. The following code example loads - the previously created XML file and runs it. - - -#include <stdlib.h> -#include <gst/gst.h> - -int -main(int argc, char *argv[]) -{ - GstXML *xml; - GstElement *pipeline; - gboolean ret; - - gst_init (&argc, &argv); - - xml = gst_xml_new (); - - ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL); - g_assert (ret == TRUE); - - pipeline = gst_xml_get_element (xml, "pipeline"); - g_assert (pipeline != NULL); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - g_sleep (4); - - gst_element_set_state (pipeline, GST_STATE_NULL); - - exit (0); -} - - - gst_xml_get_element (xml, "name") can be used to get a specific element - from the XML file. - - - gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements - in the XML file. - - - In addition to loading a file, you can also load from a xmlDocPtr and - an in-memory buffer using gst_xml_parse_doc and gst_xml_parse_memory - respectively. Both of these methods return a gboolean indicating - success or failure of the requested action. - - - - Adding custom XML tags into the core XML data - - - It is possible to add custom XML tags to the core XML created with - gst_xml_write. This feature can be used by an application to add more - information to the save plugins. The editor will for example insert - the position of the elements on the screen using the custom XML tags. - - - It is strongly suggested to save and load the custom XML tags using - a namespace. This will solve the problem of having your XML tags - interfere with the core XML tags. - - - To insert a hook into the element saving procedure you can link - a signal to the GstElement using the following piece of code: - - -xmlNsPtr ns; - - ... - ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test"); - ... - pipeline = gst_element_factory_make ("pipeline", "pipeline"); - g_signal_connect (G_OBJECT (pipeline), "object_saved", - G_CALLBACK (object_saved), g_strdup ("decoder pipeline")); - ... - - - When the thread is saved, the object_save method will be called. Our example - will insert a comment tag: - - -static void -object_saved (GstObject *object, xmlNodePtr parent, gpointer data) -{ - xmlNodePtr child; - - child = xmlNewChild (parent, ns, "comment", NULL); - xmlNewChild (child, ns, "text", (gchar *)data); -} - - - Adding the custom tag code to the above example you will get an XML file - with the custom tags in it. Here's an excerpt: - - - ... - <gst:element> - <gst:name>pipeline</gst:name> - <gst:type>pipeline</gst:type> - <gst:version>0.1.0</gst:version> - ... - </gst:children> - <test:comment> - <test:text>decoder pipeline</test:text> - </test:comment> - </gst:element> - ... - - - To retrieve the custom XML again, you need to attach a signal to - the GstXML object used to load the XML data. You can then parse your - custom XML from the XML tree whenever an object is loaded. - - - - We can extend our previous example with the following piece of - code. - - - - xml = gst_xml_new (); - - g_signal_connect (G_OBJECT (xml), "object_loaded", - G_CALLBACK (xml_loaded), xml); - - ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL); - g_assert (ret == TRUE); - - - - Whenever a new object has been loaded, the xml_loaded function will - be called. This function looks like: - - -static void -xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data) -{ - xmlNodePtr children = self->xmlChildrenNode; - - while (children) { - if (!strcmp (children->name, "comment")) { - xmlNodePtr nodes = children->xmlChildrenNode; - - while (nodes) { - if (!strcmp (nodes->name, "text")) { - gchar *name = g_strdup (xmlNodeGetContent (nodes)); - g_print ("object %s loaded with comment '%s'\n", - gst_object_get_name (object), name); - } - nodes = nodes->next; - } - } - children = children->next; - } -} - - - As you can see, you'll get a handle to the GstXML object, the - newly loaded GstObject and the xmlNodePtr that was used to create - this object. In the above example we look for our special tag inside - the XML tree that was used to load the object and we print our - comment to the console. - -