6 Interfaces are descriptions on how to handle an object, without actually
7 implementing the object. This allows for multiple objects to be instantiated
8 based on this interface. Each of them can then be handled equally by an
10 Glib, apparently (unchecked), has a way of creating interfaces, probably
11 by means of a class struct without actually defining the object. The object,
12 then, does not define a class and these two add up. Benjamin knows more
13 about interfaces, I didn't study interfaces & glib too deeply, yet. I know
15 Interfaces are cool! It allows for some sort of random element creation
16 without needing to link to the implementation. This is similar to how
17 GStreamer currently handles media plugins. GStreamer itself could be seen
18 as an interface too, in that respect.
20 2) So why do we need interfaces?
21 ================================
22 Because GStreamer doesn't handle it all. GStreamer in itself is a media
23 framework for streams of data from one element to the next. There's lots
24 of things that's media-related, but not handled in this description.
25 Several examples will probably clarify this: think of the Xvideo output
26 plugin. We can create an overlay here (Xv-based), and we currently control
27 this X-connection using glib properties. However, what property name is
28 associated with what control? And does it work the same as v4lsrc's
29 overlay image control?
30 The same goes for a mixer, for image control, audio control, and probably
31 a lot more. The general idea is simple: *this needs to be documented*.
32 But properties aren't all - they simply cannot do this all. Some things
33 cannot be described in a simple one-argument property thing. Of course,
34 we could give a pointer to a struct as argument, but that's merely a hack
35 and requires both plugin and app to know the ABI of the struct. This
36 kills the whole idea of making the plugin independent of the app.
37 In short: we want interfaces for this.
39 3) How to integrate an interface in GStreamer
40 =============================================
41 Let us start with some starting point: an interface is associated
42 with an element. It is a feature exported by that specific element,
43 not by a pipeline or anything more complex. Pipelines are already
44 handled just fine by GStreamer (or you wouldn't be reading all
46 Obviously, a pipeline can be a fallback for an interface. Imagine
47 that we're looking for an audio sink that exposes a mixer, but our
48 fakesink audio output doesn't ("I wonder why"). We could then create
49 a pipeline with the volume element in it to "fake" a mixer. Ideally,
50 the volume element would implement a mixer interface itself.
52 How are we going to do that in programmatic way? We currently use
53 properties. Their huge advantage is that we do not need to care
54 about adding new functions or whatever. Their disadvantage is that
55 they're limited to one argument. Anything more complex requires
56 app/plugin knowledge about the shared data, and that defeats the
57 point of them: to have no dependency on each other. This could be
58 solved partially by using action signals, but that makes the whole
59 picture quite complex (since you use multiple methods for doing one
60 simple thing). Also, they are quite slow compared to functions
61 because of the table lookups. In short: it'd work, but I'm not in
63 OK, so an element exposes interfaces. This allows us to think of
64 the idea of embedding interfaces (dynamically, of course) in the
65 GstElement object. Think of an object being able to register an
66 indefinate number of interfaces per object instance, and a client
67 application could then enumerate interfaces and instantiate one.
68 Glib gives us GInterface for this purpose. The disadvantage of
69 this is that it's on a per-class basis, not a per-instance basis.
70 This is a problem in case of elements where it depends on several
71 properties whether it supports an interface or not. This can be
72 solved by simply making one generic virtual function "supported ()"
73 in a generic derived object of GInterface (GstInterface?).
75 GstInterface is then a generic thing that is inherited by specific
76 interfaces (see examples). Obviously, the client will need to know
77 about the ABI/API of this struct, but that'll happen either way.
78 Surely, there needs to binary linkage, but I don't consider that a
79 bad thing. It does improve performance compared to action signals!
81 So an element contains interfaces. But where are these interfaces
82 described? And who creates them? I suggest that we do that just as
83 we handle gstvideo and gstaudio right now (these libs do *nothing*
84 useful currently, so this'd make them a lot more interesting).
85 These interfaces inherit from GstInterface. The functions that
86 are needed, can be provided through a class object. The element is
87 then responsible for storing variables and so on. gstvideo/audio
88 provides wrapper functions for the class functions. That's also how
89 glib suggest us to use GInterfaces.
91 Plugin and application then handle and retrieve interfaces as
92 documented in the glib documentation, which is available at:
93 http://www.gnome.org/~mathieu/gobject/main.html
95 So the most important part left is to document the interfaces
96 and make sure all elements exporting them work equally. For this,
97 I'll give two examples.
102 /* This small extra virtual function is here to provide an
103 * interface functionality on a per-instance basis rather
104 * than a per-class basis, which is the case for glib.
106 typedef struct _GstInterfaceClass {
107 GTypeInterface parent;
109 /* virtual functions */
110 gboolean (* supported) (GstInterface *iface);
113 There would probably be a convenience function that checks
114 a specific interface's implementation (glib allows for this)
115 and checks for ->supported () to be set and to return TRUE:
118 gst_element_implements_interface (GstElement *element,
121 if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (element),
124 GstInterfaceClass *ifclass;
126 iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
128 ifclass = GST_INTERFACE_GET_CLASS (iface);
130 if (ifclass->supported != NULL &&
131 ifclass->supported (iface) == TRUE) {
139 Let's now add some functions so we can abuse this in case/check
143 gst_interface_cast (gpointer from,
148 /* check cast, give warning+fail if it's invalid */
149 if (!(iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
150 type, GstInterface))) {
154 /* if we're an element, take care that this interface
155 * is actually implemented */
156 if (GST_IS_ELEMENT (from)) {
157 gboolean interface_is_implemented =
158 gst_element_implements_interface (GST_ELEMENT (from),
160 g_return_val_if_fail (interface_is_implemented == TRUE, NULL);
167 gst_interface_check (gpointer from,
172 /* check cast, return FALSE if it fails, don't give a warning... */
173 if (!G_TYPE_CHECK_INSTANCE_CAST (from, type,
178 iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
181 /* now, if we're an element (or derivative), is this thing
182 * actually implemented for real? */
183 if (GST_IS_ELEMENT (from)) {
184 if (!gst_element_implements_interface (GST_ELEMENT (from),
193 #define GST_INTERFACE_CHECK_INSTANCE_CAST(obj, type, cast_t) \
194 ((cast_t *) gst_interface_cast ((obj), (type))
195 #define GST_INTERFACE_CHECK_INSTANCE_TYPE(obj, type) \
196 (gst_interface_check ((obj), (type))
198 We could use this in the GST_IS_... () macros. For example, the
199 macros GST_IS_MIXER () and GST_MIXER () would then look like this:
201 /* Note that this is a non-standard macro, and with a reason! */
202 #define GST_MIXER(obj) \
203 (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), \
206 #define GST_IS_MIXER(obj) \
207 (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), \
210 So the application would just tread it with the known macro, and
211 everything would look extremely simple to the end user.
215 A mixer is a way of controlling volume and input/output channels.
216 This doesn't mean that you control which channel is the subwoofer,
217 all that is supposed to be done automatically. It is really meant
218 as a way of representing system-level volumes and such. It could
219 also be used to turn on/off certain outputs or inputs.
220 As you've noticed, I'm not only talking about output, but also
221 input. Indeed, I want both osssrc *and* osssink to export the
222 same mixer interface! Or at least a very similar one. Volume
223 control works the same for both. You could say that osssrc should
224 enumerate the input channels (such as microphone, line-in). Of
225 course, osssink should not. Or maybe it should, not sure... Maybe,
226 we'd need a parent osselement which implements all mixer channels.
227 And alsa* would surely implement the same interface.
229 /* This is confusing naming... (i.e. FIXME)
230 * A channel is referred to both as the number of simultaneous
231 * sound streams the input can handle as well as the in-/output
235 #define GST_MIXER_CHANNEL_INPUT (1<<0)
236 #define GST_MIXER_CHANNEL_OUTPUT (1<<1)
237 #define GST_MIXER_CHANNEL_MUTE (1<<2)
238 #define GST_MIXER_CHANNEL_RECORD (1<<3)
240 typedef struct _GstMixerChannel {
242 gint current_num_channels,
247 typedef struct _GstMixerClass {
248 GTypeInterface klass;
250 /* virtual functions */
251 GList * (* list_channels) (GstMixer *mixer);
253 void (* set_volume) (GstMixer *mixer,
254 GstMixerChannel *channel,
256 void (* get_volume) (GstMixer *mixer,
257 GstMixerChannel *channel,
260 void (* set_mute) (GstMixer *mixer,
261 GstMixerChannel *channel,
263 void (* set_record) (GstMixer *mixer,
264 GstMixerChannel *channel,
268 libgstmixer.la/so provides wrapper functions for each of the
269 class' virtual functions. Possibly also some macros for
270 GST_MIXER_CHANNEL_HAS_FLAG () or _get_channel ().
272 The rest is done automatically, as described in the already-
273 mentioned glib documentation for GInterface. This includes
274 things like the base_init () function of the GstMixerClass,
275 which fills all the virtual functions for the mixer, and the
276 actual function implementations. The mixer, basically, operates
277 as an element on its own. It gets the file descriptor from
278 the interface->element (every oss... is a osscommon, etc.).
282 Overlay is used in both in- and output, too. Think of v4lsrc,
283 v4l2src, v4lmjpegsrc, xvideosink - all overlays. But where do
284 we position the overlay window? Control of this can be done at
285 various levels: locational control (over the server, asynchronous)
286 or XID control (but that makes you depend on X and limits the
287 ability to broaden it over to non-X elements such as fbsink).
289 However, simplicity *is* an issue here. Do we really care about
290 overlay? In the end, users will have to link against either FB
291 or X anyway, so we might want to create separate interfaces for
292 both. On the other hand, we want to be general too... This is a
293 decision that we need to make as early as possible in this process.
294 For now, I propose making X- and FB-based interfaces.
296 Let's assume that we take X as a basis. Then, overlay becomes as
297 simple as one function. Possible extendible by providing inputs
298 (like in the mixer) and norms, although that only applies to
299 input-to-analog, not to-digital... Others simply return NULL.
301 typedef struct _GstOverlayClass {
302 GTypeInterface klass;
304 /* virtual functions */
305 void (* set_xwindowid) (GstOverlay *overlay,
309 That's all! It would look similar for FB & co.
313 And yes, user input could be an interface too. Even better, it
314 should definately be. And wasn't this one of our key issues for
317 No code here. Go implement it, lazy ass!
319 General ways of thinking: input can come from a plugin, or from
320 the application (we don't have modules for joystick input et all).
321 However, plugins handling input (such as dvdsrc) need to be able
322 to handle each. So we get both input-to-application as well as
323 input-from-application APIs.
325 5) Status of this document
326 ==========================
327 The interfaces are implemented, more (for metadata, framebuffer-
328 overlay, video balancing (brightness), user input etc. are all
331 6) Copyright and blabla
332 =======================
333 (c) Ronald Bultje, 2003 <rbultje@ronald.bitfreak.net> under the
334 terms of the GNU Free Documentation License. See http://www.gnu.org/
337 And no, I'm not for hire. ;).