2 <title>XML in <application>GStreamer</application></title>
4 <application>GStreamer</application> uses XML to store and load
5 its pipeline definitions. XML is also used internally to manage the
6 plugin registry. The plugin registry is a file that contains the definition
7 of all the plugins <application>GStreamer</application> knows about to have
8 quick access to the specifics of the plugins.
12 We will show you how you can save a pipeline to XML and how you can reload that
13 XML file again for later use.
16 <sect1 id="sec-xml-write">
17 <title>Turning GstElements into XML</title>
20 We create a simple pipeline and write it to stdout with
21 gst_xml_write_file (). The following code constructs an MP3 player
22 pipeline with two threads and then writes out the XML both to stdout
23 and to a file. Use this program with one argument: the MP3 file on disk.
27 /* example-begin xml-mp3.c */
28 #include <stdlib.h>
29 #include <gst/gst.h>
34 main (int argc, char *argv[])
36 GstElement *filesrc, *osssink, *queue, *queue2, *decode;
38 GstElement *thread, *thread2;
40 gst_init (&argc,&argv);
43 g_print ("usage: %s <mp3 filename>\n", argv[0]);
47 /* create a new thread to hold the elements */
48 thread = gst_element_factory_make ("thread", "thread");
49 g_assert (thread != NULL);
50 thread2 = gst_element_factory_make ("thread", "thread2");
51 g_assert (thread2 != NULL);
53 /* create a new bin to hold the elements */
54 bin = gst_bin_new ("bin");
55 g_assert (bin != NULL);
57 /* create a disk reader */
58 filesrc = gst_element_factory_make ("filesrc", "disk_source");
59 g_assert (filesrc != NULL);
60 g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
62 queue = gst_element_factory_make ("queue", "queue");
63 queue2 = gst_element_factory_make ("queue", "queue2");
65 /* and an audio sink */
66 osssink = gst_element_factory_make ("osssink", "play_audio");
67 g_assert (osssink != NULL);
69 decode = gst_element_factory_make ("mad", "decode");
70 g_assert (decode != NULL);
72 /* add objects to the main bin */
73 gst_bin_add (GST_BIN (bin), filesrc);
74 gst_bin_add (GST_BIN (bin), queue);
76 gst_bin_add (GST_BIN (thread), decode);
77 gst_bin_add (GST_BIN (thread), queue2);
79 gst_bin_add (GST_BIN (thread2), osssink);
81 gst_pad_link (gst_element_get_pad (filesrc,"src"),
82 gst_element_get_pad (queue,"sink"));
84 gst_pad_link (gst_element_get_pad (queue,"src"),
85 gst_element_get_pad (decode,"sink"));
86 gst_pad_link (gst_element_get_pad (decode,"src"),
87 gst_element_get_pad (queue2,"sink"));
89 gst_pad_link (gst_element_get_pad (queue2,"src"),
90 gst_element_get_pad (osssink,"sink"));
92 gst_bin_add (GST_BIN (bin), thread);
93 gst_bin_add (GST_BIN (bin), thread2);
95 /* write the bin to stdout */
96 gst_xml_write_file (GST_ELEMENT (bin), stdout);
98 /* write the bin to a file */
99 gst_xml_write_file (GST_ELEMENT (bin), fopen ("xmlTest.gst", "w"));
103 /* example-end xml-mp3.c */
106 The most important line is:
109 gst_xml_write_file (GST_ELEMENT (bin), stdout);
112 gst_xml_write_file () will turn the given element into an xmlDocPtr that
113 is then formatted and saved to a file. To save to disk, pass the result
114 of a fopen(2) as the second argument.
117 The complete element hierarchy will be saved along with the inter element
118 pad links and the element parameters. Future <application>GStreamer</application>
119 versions will also allow you to store the signals in the XML file.
123 <sect1 id="sec-xml-load">
124 <title>Loading a GstElement from an XML file</title>
126 Before an XML file can be loaded, you must create a GstXML object.
127 A saved XML file can then be loaded with the
128 gst_xml_parse_file (xml, filename, rootelement) method.
129 The root element can optionally left NULL. The following code example loads
130 the previously created XML file and runs it.
133 #include <stdlib.h>
134 #include <gst/gst.h>
137 main(int argc, char *argv[])
143 gst_init (&argc, &argv);
145 xml = gst_xml_new ();
147 ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
148 g_assert (ret == TRUE);
150 bin = gst_xml_get_element (xml, "bin");
151 g_assert (bin != NULL);
153 gst_element_set_state (bin, GST_STATE_PLAYING);
155 while (gst_bin_iterate(GST_BIN(bin)));
157 gst_element_set_state (bin, GST_STATE_NULL);
163 gst_xml_get_element (xml, "name") can be used to get a specific element
167 gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements
171 In addition to loading a file, you can also load a from a xmlDocPtr and
172 an in memory buffer using gst_xml_parse_doc and gst_xml_parse_memory
173 respectively. Both of these methods return a gboolean indicating
174 success or failure of the requested action.
177 <sect1 id="sec-xml-custom">
178 <title>Adding custom XML tags into the core XML data</title>
181 It is possible to add custom XML tags to the core XML created with
182 gst_xml_write. This feature can be used by an application to add more
183 information to the save plugins. The editor will for example insert
184 the position of the elements on the screen using the custom XML tags.
187 It is strongly suggested to save and load the custom XML tags using
188 a namespace. This will solve the problem of having your XML tags
189 interfere with the core XML tags.
192 To insert a hook into the element saving procedure you can link
193 a signal to the GstElement using the following piece of code:
199 ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test");
201 thread = gst_element_factory_make ("thread", "thread");
202 g_signal_connect (G_OBJECT (thread), "object_saved",
203 G_CALLBACK (object_saved), g_strdup ("decoder thread"));
207 When the thread is saved, the object_save method will be caled. Our example
208 will insert a comment tag:
212 object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
216 child = xmlNewChild (parent, ns, "comment", NULL);
217 xmlNewChild (child, ns, "text", (gchar *)data);
221 Adding the custom tag code to the above example you will get an XML file
222 with the custom tags in it. Here's an excerpt:
227 <gst:name>thread</gst:name>
228 <gst:type>thread</gst:type>
229 <gst:version>0.1.0</gst:version>
231 </gst:children>
233 <test:text>decoder thread</test:text>
234 </test:comment>
239 To retrieve the custom XML again, you need to attach a signal to
240 the GstXML object used to load the XML data. You can then parse your
241 custom XML from the XML tree whenever an object is loaded.
245 We can extend our previous example with the following piece of
250 xml = gst_xml_new ();
252 g_signal_connect (G_OBJECT (xml), "object_loaded",
253 G_CALLBACK (xml_loaded), xml);
255 ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
256 g_assert (ret == TRUE);
260 Whenever a new object has been loaded, the xml_loaded function will
261 be called. This function looks like:
265 xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
267 xmlNodePtr children = self->xmlChildrenNode;
270 if (!strcmp (children->name, "comment")) {
271 xmlNodePtr nodes = children->xmlChildrenNode;
274 if (!strcmp (nodes->name, "text")) {
275 gchar *name = g_strdup (xmlNodeGetContent (nodes));
276 g_print ("object %s loaded with comment '%s'\n",
277 gst_object_get_name (object), name);
279 nodes = nodes->next;
282 children = children->next;
287 As you can see, you'll get a handle to the GstXML object, the
288 newly loaded GstObject and the xmlNodePtr that was used to create
289 this object. In the above example we look for our special tag inside
290 the XML tree that was used to load the object and we print our
291 comment to the console.