new proggy I never checked in
[platform/upstream/gstreamer.git] / docs / manual / highlevel-xml.xml
1 <chapter id="cha-xml">
2   <title>XML in <application>GStreamer</application></title>
3   <para> 
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.
9   </para>
10
11   <para>
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. 
14   </para>
15   
16   <sect1 id="sec-xml-write">
17     <title>Turning GstElements into XML</title>
18
19     <para>
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.
24     </para>
25
26     <programlisting>
27 /* example-begin xml-mp3.c */
28 #include &lt;stdlib.h&gt;
29 #include &lt;gst/gst.h&gt;
30
31 gboolean playing;
32
33 int 
34 main (int argc, char *argv[]) 
35 {
36   GstElement *filesrc, *osssink, *queue, *queue2, *decode;
37   GstElement *bin;
38   GstElement *thread, *thread2;
39
40   gst_init (&amp;argc,&amp;argv);
41
42   if (argc != 2) {
43     g_print ("usage: %s &lt;mp3 filename&gt;\n", argv[0]);
44     exit (-1);
45   }
46
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);
52
53   /* create a new bin to hold the elements */
54   bin = gst_bin_new ("bin");
55   g_assert (bin != NULL);
56
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);
61
62   queue = gst_element_factory_make ("queue", "queue");
63   queue2 = gst_element_factory_make ("queue", "queue2");
64
65   /* and an audio sink */
66   osssink = gst_element_factory_make ("osssink", "play_audio");
67   g_assert (osssink != NULL);
68
69   decode = gst_element_factory_make ("mad", "decode");
70   g_assert (decode != NULL);
71
72   /* add objects to the main bin */
73   gst_bin_add (GST_BIN (bin), filesrc);
74   gst_bin_add (GST_BIN (bin), queue);
75
76   gst_bin_add (GST_BIN (thread), decode);
77   gst_bin_add (GST_BIN (thread), queue2);
78
79   gst_bin_add (GST_BIN (thread2), osssink);
80   
81   gst_pad_link (gst_element_get_pad (filesrc,"src"),
82                    gst_element_get_pad (queue,"sink"));
83
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"));
88
89   gst_pad_link (gst_element_get_pad (queue2,"src"),
90                    gst_element_get_pad (osssink,"sink"));
91
92   gst_bin_add (GST_BIN (bin), thread);
93   gst_bin_add (GST_BIN (bin), thread2);
94
95   /* write the bin to stdout */
96   gst_xml_write_file (GST_ELEMENT (bin), stdout);
97
98   /* write the bin to a file */
99   gst_xml_write_file (GST_ELEMENT (bin), fopen ("xmlTest.gst", "w"));
100
101   exit (0);
102 }
103 /* example-end xml-mp3.c */
104     </programlisting>
105     <para>
106       The most important line is:
107     </para>
108     <programlisting>
109   gst_xml_write_file (GST_ELEMENT (bin), stdout);
110     </programlisting>
111     <para>
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.
115     </para>
116     <para>
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.
120     </para>
121   </sect1>
122
123   <sect1 id="sec-xml-load">
124     <title>Loading a GstElement from an XML file</title>
125     <para>
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.
131     </para>
132     <programlisting>
133 #include &lt;stdlib.h&gt;
134 #include &lt;gst/gst.h&gt;
135
136 int 
137 main(int argc, char *argv[]) 
138 {
139   GstXML *xml;
140   GstElement *bin;
141   gboolean ret;
142
143   gst_init (&amp;argc, &amp;argv);
144
145   xml = gst_xml_new ();
146
147   ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
148   g_assert (ret == TRUE);
149
150   bin = gst_xml_get_element (xml, "bin");
151   g_assert (bin != NULL);
152   
153   gst_element_set_state (bin, GST_STATE_PLAYING);
154
155   while (gst_bin_iterate(GST_BIN(bin)));
156
157   gst_element_set_state (bin, GST_STATE_NULL);
158
159   exit (0);
160 }
161     </programlisting>
162     <para>
163       gst_xml_get_element (xml, "name") can be used to get a specific element 
164       from the XML file. 
165     </para>
166     <para>
167       gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements
168       in the XML file.
169     </para>
170     <para>
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.
175     </para>
176   </sect1>
177   <sect1 id="sec-xml-custom">
178     <title>Adding custom XML tags into the core XML data</title>
179
180     <para>
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.
185     </para>
186     <para>
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.
190     </para>
191     <para>
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:
194     </para>
195     <programlisting>
196 xmlNsPtr ns;
197
198   ...
199   ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test");
200     ...
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"));
204     ...
205     </programlisting>
206     <para>
207       When the thread is saved, the object_save method will be caled. Our example
208       will insert a comment tag:
209     </para>
210     <programlisting>
211 static void
212 object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
213 {
214   xmlNodePtr child;
215
216   child = xmlNewChild (parent, ns, "comment", NULL);
217   xmlNewChild (child, ns, "text", (gchar *)data);
218 }
219     </programlisting>
220     <para>
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:
223     </para>
224     <programlisting>
225           ...
226         &lt;gst:element&gt;
227           &lt;gst:name&gt;thread&lt;/gst:name&gt;
228           &lt;gst:type&gt;thread&lt;/gst:type&gt;
229           &lt;gst:version&gt;0.1.0&lt;/gst:version&gt;
230           ...
231         &lt;/gst:children&gt;
232         &lt;test:comment&gt;
233           &lt;test:text&gt;decoder thread&lt;/test:text&gt;
234         &lt;/test:comment&gt;
235       &lt;/gst:element&gt;
236           ...
237     </programlisting>
238     <para>
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.
242     </para>
243
244     <para>
245       We can extend our previous example with the following piece of
246       code.
247     </para>
248
249     <programlisting>
250   xml = gst_xml_new ();
251
252   g_signal_connect (G_OBJECT (xml), "object_loaded", 
253                      G_CALLBACK (xml_loaded), xml);
254
255   ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
256   g_assert (ret == TRUE);
257     </programlisting>
258
259     <para>
260       Whenever a new object has been loaded, the xml_loaded function will
261       be called. This function looks like:
262     </para>
263     <programlisting>
264 static void
265 xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
266 {
267   xmlNodePtr children = self-&gt;xmlChildrenNode;
268
269   while (children) {
270     if (!strcmp (children-&gt;name, "comment")) {
271       xmlNodePtr nodes = children-&gt;xmlChildrenNode;
272
273       while (nodes) {
274         if (!strcmp (nodes-&gt;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);
278         }
279         nodes = nodes-&gt;next;
280       }
281     }
282     children = children-&gt;next;
283   }
284 }
285     </programlisting>
286     <para>
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.
292     </para>
293   </sect1>
294
295 </chapter>