7 GStreamer uses XML to save a complete media pipeline. This
8 opens a lot of possibilities for end user apps, eg: save
9 constructed pipelines for later reuse, send pipelines over
10 the wire to render data elsewhere etc...
12 We will also allow the end user app to insert its own tags
13 into the GStreamer generated XML in order to give more
14 context to the elements. An example of such an app would be
15 gsteditor; while the GStreamer core will save the plain
16 element hierarchy, the editor will insert its own tags into
17 the XML tree to describe the elements positions, the
18 signals and other project data that might need to be
21 And inherent problem with XML is that the use and naming of
22 the tags can be done in an arbitrary way. The GStreamer core
23 will, for example, use the 'element' and 'pad' tags to store
24 the element and pad objects. The description and the nesting
25 of the tags are described in a DTD (document type definition)
26 or soon with the proposed 'new' standard of the W3C; Schemas.
28 We can see obvious problems when a user app (unaware of the
29 core tags) is also trying to use the 'element' tag for its
30 own purposes. The core might try to load the 'element' tag
31 desscribing the user app data and the user app might get fed
32 with XML data of the GStreamer core.
34 In this document we try to describe how we will solve this problem
41 To avoid the tag conflicts we mentioned, the W3C has incorporated
44 Were a typical XML document without namespaces would look like:
56 Tha same document with namespaces look like this:
59 <gst:GST-Pipeline xmlns:gst="http://gstreamer.net/gst-core/1.0/">
61 <gst:name>bin</gst:name>
68 In front of each tag we add, in this case, gst:. gst: is called the
69 namespace of the document and is declared with a statement:
71 <... xmlns:gst="http://gstreamer.net/gst-core/1.0/">
73 In this case we define a new namespace 'gst:' that is tied to the URL
74 http://gstreamer.net/gst-core/1.0/. This URL is typically based on
75 a domain you control and doesn't have to point to something valid on
76 the internet. Note that the following document is exactly the same
77 as the one mentioned above:
80 <core:GST-Pipeline xmlns:core="http://gstreamer.net/gst-core/1.0/">
82 <core:name>bin</gst:name>
89 GStreamer currently uses xmlns:gst="http://gstreamer.net/gst-core/1.0" as
90 the namespace used for saving the core pipeline.
92 3) multi-namespace documents
93 ----------------------------
95 Suppose we have a user app that wants to insert its own XML tags into
96 the core GStreamer XML pipelines, for the examples sake we will use the
97 editor as an example. The editor will insert XML tags inside each
98 element that describes the position and size of the element as it was
99 laid out in the editor.
101 For the examples sake, the tags that are used to descibe this meta data
102 will also be names 'element' in order to demonstrate the namespaces.
104 The editor will use its own namespace, being:
105 xmlns:editor="http://gstreamer.net/gst-editor/1.0". This namespace is
106 added to the XML documents header and all the elements the editor will
107 save will have this namespace attached to it. Our interleaved XML
108 document might look like this:
110 <?xml version="1.0"?>
111 <gst:GST-Pipeline xmlns:gst="http://gstreamer.net/gst-core/1.0/"
112 xmlns:editor="http://gstreamer.net/gst-editor/1.0/">
114 <gst:name>bin</gst:name>
119 <editor:position x="100" y="50"/>
124 As you can see, the namespaces clearly separate the same XML tags
128 4) implementation considerations
129 --------------------------------
131 The GStreamer core doesn't know about user apps inserting data into the
132 XML, it does not look at XML tags not within its namespace when it
133 performs the parsing of the XML tree. The core, however, must be
134 able to hand over the XML tree to the user app so it can perform the
135 parsing of its tags inside its namespace. We therefore need hooks inside
136 the framework to accomplish this.
138 We also need hooks inside the GStreamer core to signal a user app that
139 it can now insert its tags into the XML tree.
144 GstObject has an abstract class method
146 xmlNodePtr (*save_thyself) (GstObject *object, xmlNodePtr parent)
148 A real element or pad will implement this function and construct an XML
149 representation of itself with the parent xmlNodePtr as the parent.
150 An element will typically call the save_thyself function of its
151 parent class before saving itself.
153 The XML save procedure on a GstObject is performed with:
155 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
157 Wich will call the elements implementation of the save_thyself function.
159 An app that wants to insert its XML tags has to connect to a signal of
160 the GstObject object called xml_saved. The object and the parent
161 xmlNodePtr will be passed to the signal handler of the user app, which
162 can then insert its tags.
164 The user app has no problem inserting its namespace into the xmlDoc and
165 neither will the GStreamer core.
170 The real problem lies in the loading of the XML tree. Before we load
171 the objects, we don't have anything to connect a signal to, so
172 another method has to be invented to signal the user app of the
173 freshly loaded objects.
175 One obvious solution would be to attach a class signal to the
176 GstObject class that would be fired whenever an object is created from
177 an XML document. Unfortunatly Gtk+ (or glib2.0) doesn't have class
178 signals so we need something else. Another problem with the class
179 signals would be that the user app would also be notified of object
180 creation outside its context. For example, if two threads perform an
181 XML load at the same time, the objects created in the first thread
182 would also notify the listener in the second thread. Both threads then
183 have to take care of not trying to parse XML documents that are from
184 the other thread, this obvously can get messy and we have to deal
185 with it without bothering the user app.
187 We'll continue with some random ramblings...
191 To solve this problem we can create a special method in gstobject
193 gst_object_loaded_notify_add (GstObjectLoadedCallback *callback,
196 this method would add the specified callback function to a list of
197 listeners and would perform the callback function if an object is
198 created (this can be done in the init method). The problem remains
199 though because we do not know the xmlNodePtr when we call the
200 callback. This seems messy.
204 After the object has performed its restore_thyself, it is responsible
205 for signaling a object_loaded signal with the object and the xmlNodePtr
208 At object creation, the signal is connected to a singleton object managed
209 by GstObject that can proxy the signal to the user app. This looks a
210 lot like a class signal. apps could also specify the xmlNodePtr they
211 are interested in and the signal would only be proxied to the app
212 if the xmlNodePtrs are from the same xmlDoc.
214 Solution 2 seems like a reasonable solution for now...