source: trunk/third/gstreamer/docs/manual/highlevel-xml.xml @ 21448

Revision 21448, 8.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21447, which included commits to RCS files with non-trunk default branches.
RevLine 
[21447]1<chapter id="chapter-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="section-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
31gboolean playing;
32
33int
34main (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_many (GST_BIN (bin), filesrc, queue, NULL);
74
75  gst_bin_add_many (GST_BIN (thread), decode, queue2, NULL);
76
77  gst_bin_add (GST_BIN (thread2), osssink);
78 
79  gst_element_link_many (filesrc, queue, decode, queue2, osssink, NULL);
80
81  gst_bin_add_many (GST_BIN (bin), thread, thread2, NULL);
82
83  /* write the bin to stdout */
84  gst_xml_write_file (GST_ELEMENT (bin), stdout);
85
86  /* write the bin to a file */
87  gst_xml_write_file (GST_ELEMENT (bin), fopen ("xmlTest.gst", "w"));
88
89  exit (0);
90}
91<!-- example-end xml-mp3.c -->
92    </programlisting>
93    <para>
94      The most important line is:
95    </para>
96    <programlisting>
97  gst_xml_write_file (GST_ELEMENT (bin), stdout);
98    </programlisting>
99    <para>
100      gst_xml_write_file () will turn the given element into an xmlDocPtr that
101      is then formatted and saved to a file. To save to disk, pass the result
102      of a fopen(2) as the second argument.
103    </para>
104    <para>
105      The complete element hierarchy will be saved along with the inter element
106      pad links and the element parameters. Future <application>GStreamer</application>
107      versions will also allow you to store the signals in the XML file.
108    </para>
109  </sect1>
110
111  <sect1 id="section-xml-load">
112    <title>Loading a GstElement from an XML file</title>
113    <para>
114      Before an XML file can be loaded, you must create a GstXML object.
115      A saved XML file can then be loaded with the
116      gst_xml_parse_file (xml, filename, rootelement) method.
117      The root element can optionally left NULL. The following code example loads
118      the previously created XML file and runs it.
119    </para>
120    <programlisting>
121#include &lt;stdlib.h&gt;
122#include &lt;gst/gst.h&gt;
123
124int
125main(int argc, char *argv[])
126{
127  GstXML *xml;
128  GstElement *bin;
129  gboolean ret;
130
131  gst_init (&amp;argc, &amp;argv);
132
133  xml = gst_xml_new ();
134
135  ret = gst_xml_parse_file(xml, "xmlTest.gst", NULL);
136  g_assert (ret == TRUE);
137
138  bin = gst_xml_get_element (xml, "bin");
139  g_assert (bin != NULL);
140 
141  gst_element_set_state (bin, GST_STATE_PLAYING);
142
143  while (gst_bin_iterate(GST_BIN(bin)));
144
145  gst_element_set_state (bin, GST_STATE_NULL);
146
147  exit (0);
148}
149    </programlisting>
150    <para>
151      gst_xml_get_element (xml, "name") can be used to get a specific element
152      from the XML file.
153    </para>
154    <para>
155      gst_xml_get_topelements (xml) can be used to get a list of all toplevel elements
156      in the XML file.
157    </para>
158    <para>
159      In addition to loading a file, you can also load a from a xmlDocPtr and
160      an in memory buffer using gst_xml_parse_doc and gst_xml_parse_memory
161      respectively. Both of these methods return a gboolean indicating
162      success or failure of the requested action.
163    </para>
164  </sect1>
165  <sect1 id="section-xml-custom">
166    <title>Adding custom XML tags into the core XML data</title>
167
168    <para>
169      It is possible to add custom XML tags to the core XML created with
170      gst_xml_write. This feature can be used by an application to add more
171      information to the save plugins. The editor will for example insert
172      the position of the elements on the screen using the custom XML tags.
173    </para>
174    <para>
175      It is strongly suggested to save and load the custom XML tags using
176      a namespace. This will solve the problem of having your XML tags
177      interfere with the core XML tags.
178    </para>
179    <para>
180      To insert a hook into the element saving procedure you can link
181      a signal to the GstElement using the following piece of code:
182    </para>
183    <programlisting>
184xmlNsPtr ns;
185
186  ...
187  ns = xmlNewNs (NULL, "http://gstreamer.net/gst-test/1.0/", "test");
188    ...
189  thread = gst_element_factory_make ("thread", "thread");
190  g_signal_connect (G_OBJECT (thread), "object_saved",
191                     G_CALLBACK (object_saved), g_strdup ("decoder thread"));
192    ...
193    </programlisting>
194    <para>
195      When the thread is saved, the object_save method will be called. Our example
196      will insert a comment tag:
197    </para>
198    <programlisting>
199static void
200object_saved (GstObject *object, xmlNodePtr parent, gpointer data)
201{
202  xmlNodePtr child;
203
204  child = xmlNewChild (parent, ns, "comment", NULL);
205  xmlNewChild (child, ns, "text", (gchar *)data);
206}
207    </programlisting>
208    <para>
209      Adding the custom tag code to the above example you will get an XML file
210      with the custom tags in it. Here's an excerpt:
211    </para>
212    <programlisting>
213          ...
214        &lt;gst:element&gt;
215          &lt;gst:name&gt;thread&lt;/gst:name&gt;
216          &lt;gst:type&gt;thread&lt;/gst:type&gt;
217          &lt;gst:version&gt;0.1.0&lt;/gst:version&gt;
218          ...
219        &lt;/gst:children&gt;
220        &lt;test:comment&gt;
221          &lt;test:text&gt;decoder thread&lt;/test:text&gt;
222        &lt;/test:comment&gt;
223      &lt;/gst:element&gt;
224          ...
225    </programlisting>
226    <para>
227      To retrieve the custom XML again, you need to attach a signal to
228      the GstXML object used to load the XML data. You can then parse your
229      custom XML from the XML tree whenever an object is loaded.
230    </para>
231
232    <para>
233      We can extend our previous example with the following piece of
234      code.
235    </para>
236
237    <programlisting>
238  xml = gst_xml_new ();
239
240  g_signal_connect (G_OBJECT (xml), "object_loaded",
241                     G_CALLBACK (xml_loaded), xml);
242
243  ret = gst_xml_parse_file (xml, "xmlTest.gst", NULL);
244  g_assert (ret == TRUE);
245    </programlisting>
246
247    <para>
248      Whenever a new object has been loaded, the xml_loaded function will
249      be called. This function looks like:
250    </para>
251    <programlisting>
252static void
253xml_loaded (GstXML *xml, GstObject *object, xmlNodePtr self, gpointer data)
254{
255  xmlNodePtr children = self-&gt;xmlChildrenNode;
256
257  while (children) {
258    if (!strcmp (children-&gt;name, "comment")) {
259      xmlNodePtr nodes = children-&gt;xmlChildrenNode;
260
261      while (nodes) {
262        if (!strcmp (nodes-&gt;name, "text")) {
263          gchar *name = g_strdup (xmlNodeGetContent (nodes));
264          g_print ("object %s loaded with comment '%s'\n",
265                   gst_object_get_name (object), name);
266        }
267        nodes = nodes-&gt;next;
268      }
269    }
270    children = children-&gt;next;
271  }
272}
273    </programlisting>
274    <para>
275      As you can see, you'll get a handle to the GstXML object, the
276      newly loaded GstObject and the xmlNodePtr that was used to create
277      this object. In the above example we look for our special tag inside
278      the XML tree that was used to load the object and we print our
279      comment to the console.
280    </para>
281  </sect1>
282
283</chapter>
Note: See TracBrowser for help on using the repository browser.