Initialize Tizen 2.3
[framework/multimedia/gstreamer0.10.git] / mobile / docs / pwg / advanced-interfaces.xml
1 <chapter id="chapter-advanced-interfaces">
2   <title>Interfaces</title>
3   <para>
4     Previously, in the chapter <xref linkend="chapter-building-args"/>, we have
5     introduced the concept of GObject properties of controlling an element's
6     behaviour. This is very powerful, but it has two big disadvantages:
7     first of all, it is too generic, and second, it isn't dynamic.
8   </para>
9   <para>
10     The first disadvantage is related to the customizability of the end-user
11     interface that will be built to control the element. Some properties are
12     more important than others. Some integer properties are better shown in a
13     spin-button widget, whereas others would be better represented by a slider
14     widget. Such things are not possible because the UI has no actual meaning
15     in the application. A UI widget that represents a bitrate property is the
16     same as a UI widget that represents the size of a video, as long as both
17     are of the same <classname>GParamSpec</classname> type. Another problem,
18     is that things like parameter grouping, function grouping, or parameter
19     coupling are not
20     really possible.
21   </para>
22   <para>
23     The second problem with parameters are that they are not dynamic. In
24     many cases, the allowed values for a property are not fixed, but depend
25     on things that can only be detected at runtime. The names of inputs for
26     a TV card in a video4linux source element, for example, can only be
27     retrieved from the kernel driver when we've opened the device; this only
28     happens when the element goes into the READY state. This means that we
29     cannot create an enum property type to show this to the user.
30   </para>
31   <para>
32     The solution to those problems is to create very specialized types of
33     controls for certain often-used controls. We use the concept of interfaces
34     to achieve this. The basis of this all is the glib
35     <classname>GTypeInterface</classname> type. For each case where we think
36     it's useful, we've created interfaces which can be implemented by elements
37     at their own will. We've also created a small extension to
38     <classname>GTypeInterface</classname> (which is static itself, too) which
39     allows us to query for interface availability based on runtime properties.
40     This extension is called <ulink type="http"
41     url="../../gstreamer/html/GstImplementsInterface.html"><classname>
42     GstImplementsInterface</classname></ulink>.
43   </para>
44   <para>
45     One important note: interfaces do <emphasis>not</emphasis> replace
46     properties. Rather, interfaces should be built <emphasis>next to</emphasis>
47     properties. There are two important reasons for this. First of all, 
48     properties
49     can be saved in XML files. Second, properties can be specified on the
50     commandline (<filename>gst-launch</filename>).
51   </para>
52
53   <sect1 id="section-iface-general" xreflabel="How to Implement Interfaces">
54     <title>How to Implement Interfaces</title>
55     <para>
56       Implementing interfaces is initiated in the <function>_get_type ()</function>
57       of your element. You can register one or more interfaces after having
58       registered the type itself. Some interfaces have dependencies on other
59       interfaces or can only be registered by certain types of elements. You
60       will be notified of doing that wrongly when using the element: it will
61       quit with failed assertions, which will explain what went wrong. In the
62       case of GStreamer, the only dependency that <emphasis>some</emphasis>
63       interfaces have is <ulink type="http"
64       url="../../gstreamer/html/GstImplementsInterface.html"><classname>
65       GstImplementsInterface</classname></ulink>. Per
66       interface, we will indicate clearly when it depends on this extension.
67       If it does, you need to register support for <emphasis>that</emphasis>
68       interface before registering support for the interface that you're
69       wanting to support. The example below explains how to add support for a
70       simple interface with no further dependencies. For a small explanation
71       on <ulink type="http" url="../../gstreamer/html/GstImplementsInterface.html">
72       <classname>GstImplementsInterface</classname></ulink>, see the next section
73       about the mixer interface: <xref linkend="section-iface-mixer"/>.
74     </para>
75     <programlisting>
76 static void     gst_my_filter_some_interface_init       (GstSomeInterface *iface);
77
78 GType
79 gst_my_filter_get_type (void)
80 {
81   static GType my_filter_type = 0;
82                                                                                 
83   if (!my_filter_type) {
84     static const GTypeInfo my_filter_info = {
85       sizeof (GstMyFilterClass),
86       (GBaseInitFunc) gst_my_filter_base_init,
87       NULL,
88       (GClassInitFunc) gst_my_filter_class_init,
89       NULL,
90       NULL,
91       sizeof (GstMyFilter),
92       0,
93       (GInstanceInitFunc) gst_my_filter_init
94     };
95     static const GInterfaceInfo some_interface_info = {
96       (GInterfaceInitFunc) gst_my_filter_some_interface_init,
97       NULL,
98       NULL
99     };
100
101     my_filter_type =
102         g_type_register_static (GST_TYPE_MY_FILTER,
103                                 "GstMyFilter",
104                                 &amp;my_filter_info, 0);
105     g_type_add_interface_static (my_filter_type,
106                                  GST_TYPE_SOME_INTERFACE,
107                                  &amp;some_interface_info);
108   }
109
110   return my_filter_type;
111 }
112
113 static void
114 gst_my_filter_some_interface_init (GstSomeInterface *iface)
115 {
116   /* here, you would set virtual function pointers in the interface */
117 }
118     </programlisting>
119   </sect1>
120
121   <sect1 id="section-iface-uri" xreflabel="URI interface">
122     <title>URI interface</title>
123     <para>
124       WRITEME
125     </para>
126   </sect1>
127
128   <sect1 id="section-iface-mixer" xreflabel="Mixer Interface">
129     <title>Mixer Interface</title>
130     <para>
131       The goal of the mixer interface is to provide a simple yet powerful API
132       to applications for audio hardware mixer/volume control. Most soundcards
133       have hardware mixers, where volume can be changed, they can be muted,
134       inputs can be modified to mix their content into what will be read from
135       the device by applications (in our case: audio source plugins). The
136       mixer interface is the way to control those. The mixer interface can
137       also be used for volume control in software (e.g. the <quote>volume</quote>
138       element). The end goal of this interface is to allow development of
139       hardware volume control applications and for the control of audio volume
140       and input/output settings.
141     </para>
142     <para>
143       The mixer interface requires the <ulink type="http"
144       url="../../gstreamer/html/GstImplementsInterface.html"><classname>
145       GstImplementsInterface</classname></ulink>
146       interface to be implemented by the element. The example below will
147       feature both, so it serves as an example for the <ulink type="http"
148       url="../../gstreamer/html/GstImplementsInterface.html"><classname>
149       GstImplementsInterface</classname></ulink>, too. In this
150       interface, it is required to set a function pointer for the <function>
151       supported ()</function> function.
152       If you don't, this function will always return FALSE (default
153       implementation) and the mixer interface implementation will not work. For
154       the mixer interface, the only required function is
155       <function>list_tracks ()</function>. All other function pointers in the
156       mixer interface are optional, although it is strongly recommended to set
157       function pointers for at least the <function>get_volume ()</function> and
158       <function>set_volume ()</function> functions. The API reference for this
159       interface documents the goal of each function, so we will limit ourselves
160       to the implementation here.
161     </para>
162     <para>
163       The following example shows a mixer implementation for a software N-to-1
164       element. It does not show the actual process of stream mixing, that is
165       far too complicated for this guide.
166     </para>
167     <programlisting>
168 #include &lt;gst/mixer/mixer.h&gt;
169
170 typedef struct _GstMyFilter {
171 [..]
172   gint volume;
173   GList *tracks;
174 } GstMyFilter;
175
176 static void     gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface);
177 static void     gst_my_filter_mixer_interface_init      (GstMixerClass *iface);
178
179 GType
180 gst_my_filter_get_type (void)
181 {
182 [..]
183     static const GInterfaceInfo implements_interface_info = {
184       (GInterfaceInitFunc) gst_my_filter_implements_interface_init,
185       NULL,
186       NULL
187     };
188     static const GInterfaceInfo mixer_interface_info = {
189       (GInterfaceInitFunc) gst_my_filter_mixer_interface_init,
190       NULL,
191       NULL
192     };
193 [..]
194     g_type_add_interface_static (my_filter_type,
195                                  GST_TYPE_IMPLEMENTS_INTERFACE,
196                                  &amp;implements_interface_info);
197     g_type_add_interface_static (my_filter_type,
198                                  GST_TYPE_MIXER,
199                                  &amp;mixer_interface_info);
200 [..]
201 }
202
203 static void
204 gst_my_filter_init (GstMyFilter *filter)
205 {
206   GstMixerTrack *track = NULL;
207 [..]
208   filter->volume = 100;
209   filter->tracks = NULL;
210   track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
211   track->label = g_strdup ("MyTrack");
212   track->num_channels = 1;
213   track->min_volume = 0;
214   track->max_volume = 100;
215   track->flags = GST_MIXER_TRACK_SOFTWARE;
216   filter->tracks = g_list_append (filter->tracks, track);
217 }
218
219 static gboolean
220 gst_my_filter_interface_supported (GstImplementsInterface *iface,
221                                    GType                   iface_type)
222 {
223   g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
224
225   /* for the sake of this example, we'll always support it. However, normally,
226    * you would check whether the device you've opened supports mixers. */
227   return TRUE;
228 }
229
230 static void
231 gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface)
232 {
233   iface->supported = gst_my_filter_interface_supported;
234 }
235
236 /*
237  * This function returns the list of support tracks (inputs, outputs)
238  * on this element instance. Elements usually build this list during
239  * _init () or when going from NULL to READY.
240  */
241
242 static const GList *
243 gst_my_filter_mixer_list_tracks (GstMixer *mixer)
244 {
245   GstMyFilter *filter = GST_MY_FILTER (mixer);
246
247   return filter->tracks;
248 }
249
250 /*
251  * Set volume. volumes is an array of size track->num_channels, and
252  * each value in the array gives the wanted volume for one channel
253  * on the track.
254  */
255
256 static void
257 gst_my_filter_mixer_set_volume (GstMixer      *mixer,
258                                 GstMixerTrack *track,
259                                 gint          *volumes)
260 {
261   GstMyFilter *filter = GST_MY_FILTER (mixer);
262
263   filter->volume = volumes[0];
264
265   g_print ("Volume set to %d\n", filter->volume);
266 }
267
268 static void
269 gst_my_filter_mixer_get_volume (GstMixer      *mixer,
270                                 GstMixerTrack *track,
271                                 gint          *volumes)
272 {
273   GstMyFilter *filter = GST_MY_FILTER (mixer);
274
275   volumes[0] = filter->volume;
276 }
277
278 static void
279 gst_my_filter_mixer_interface_init (GstMixerClass *iface)
280 {
281   /* the mixer interface requires a definition of the mixer type:
282    * hardware or software? */
283   GST_MIXER_TYPE (iface) = GST_MIXER_SOFTWARE;
284
285   /* virtual function pointers */
286   iface->list_tracks = gst_my_filter_mixer_list_tracks;
287   iface->set_volume  = gst_my_filter_mixer_set_volume;
288   iface->get_volume  = gst_my_filter_mixer_get_volume;
289 }
290     </programlisting>
291     <para>
292       The mixer interface is very audio-centric. However, with the software
293       flag set, the mixer can be used to mix any kind of stream in a N-to-1
294       element to join (not aggregate!) streams together into one output stream.
295       Conceptually, that's called mixing too. You can always use the element
296       factory's <quote>category</quote> to indicate type of your element. In
297       a software element that mixes random streams, you would not be required
298       to implement the <function>_get_volume ()</function> or
299       <function>_set_volume ()</function> functions. Rather, you would only
300       implement the <function>_set_record ()</function> to enable or disable
301       tracks in the output stream. to make sure that a mixer-implementing
302       element is of a certain type, check the element factory's category.
303     </para>
304   </sect1>
305
306   <sect1 id="section-iface-tuner" xreflabel="Tuner Interface">
307     <title>Tuner Interface</title>
308     <para>
309       As opposed to the mixer interface, that's used to join together N streams
310       into one output stream by mixing all streams together, the tuner
311       interface is used in N-to-1 elements too, but instead of mixing the input
312       streams, it will select one stream and push the data of that stream to
313       the output stream. It will discard the data of all other streams. There
314       is a flag that indicates whether this is a software-tuner (in which case
315       it is a pure software implementation, with N sink pads and 1 source pad)
316       or a hardware-tuner, in which case it only has one source pad, and the
317       whole stream selection process is done in hardware. The software case can
318       be used in elements such as <emphasis>switch</emphasis>. The hardware
319       case can be used in elements with channel selection, such as video source
320       elements (v4lsrc, v4l2src, etc.). If you need a specific element type,
321       use the element factory's <quote>category</quote> to make sure that the
322       element is of the type that you need. Note that the interface itself is
323       highly analog-video-centric.
324     </para>
325     <para>
326       This interface requires the <ulink type="http"
327       url="../../gstreamer/html/GstImplementsInterface.html"><classname>
328       GstImplementsInterface</classname></ulink>
329       interface to work correctly.
330     </para>
331     <para>
332       The following example shows how to implement the tuner interface in an
333       element. It does not show the actual process of stream selection, that
334       is irrelevant for this section.
335     </para>
336     <programlisting>
337 #include &lt;gst/tuner/tuner.h&gt;
338
339 typedef struct _GstMyFilter {
340 [..]
341   gint active_input;
342   GList *channels;
343 } GstMyFilter;
344
345 static void     gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface);
346 static void     gst_my_filter_tuner_interface_init      (GstTunerClass *iface);
347
348 GType
349 gst_my_filter_get_type (void)
350 {
351 [..]
352     static const GInterfaceInfo implements_interface_info = {
353       (GInterfaceInitFunc) gst_my_filter_implements_interface_init,
354       NULL,
355       NULL
356     };
357     static const GInterfaceInfo tuner_interface_info = {
358       (GInterfaceInitFunc) gst_my_filter_tuner_interface_init,
359       NULL,
360       NULL
361     };
362 [..]
363     g_type_add_interface_static (my_filter_type,
364                                  GST_TYPE_IMPLEMENTS_INTERFACE,
365                                  &amp;implements_interface_info);
366     g_type_add_interface_static (my_filter_type,
367                                  GST_TYPE_TUNER,
368                                  &amp;tuner_interface_info);
369 [..]
370 }
371
372 static void
373 gst_my_filter_init (GstMyFilter *filter)
374 {
375   GstTunerChannel *channel = NULL;
376 [..]
377   filter->active_input = 0;
378   filter->channels = NULL;
379   channel = g_object_new (GST_TYPE_TUNER_CHANNEL, NULL);
380   channel->label = g_strdup ("MyChannel");
381   channel->flags = GST_TUNER_CHANNEL_INPUT;
382   filter->channels = g_list_append (filter->channels, channel);
383 }
384
385 static gboolean
386 gst_my_filter_interface_supported (GstImplementsInterface *iface,
387                                    GType                   iface_type)
388 {
389   g_return_val_if_fail (iface_type == GST_TYPE_TUNER, FALSE);
390
391   /* for the sake of this example, we'll always support it. However, normally,
392    * you would check whether the device you've opened supports tuning. */
393   return TRUE;
394 }
395
396 static void
397 gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface)
398 {
399   iface->supported = gst_my_filter_interface_supported;
400 }
401
402 static const GList *
403 gst_my_filter_tuner_list_channels (GstTuner *tuner)
404 {
405   GstMyFilter *filter = GST_MY_FILTER (tuner);
406
407   return filter->channels;
408 }
409
410 static GstTunerChannel *
411 gst_my_filter_tuner_get_channel (GstTuner *tuner)
412 {
413   GstMyFilter *filter = GST_MY_FILTER (tuner);
414
415   return g_list_nth_data (filter->channels,
416                           filter->active_input);
417 }
418
419 static void
420 gst_my_filter_tuner_set_channel (GstTuner        *tuner,
421                                  GstTunerChannel *channel)
422 {
423   GstMyFilter *filter = GST_MY_FILTER (tuner);
424
425   filter->active_input = g_list_index (filter->channels, channel);
426   g_assert (filter->active_input >= 0);
427 }
428
429 static void
430 gst_my_filter_tuner_interface_init (GstTunerClass *iface)
431 {
432   iface->list_channels = gst_my_filter_tuner_list_channels;
433   iface->get_channel   = gst_my_filter_tuner_get_channel;
434   iface->set_channel   = gst_my_filter_tuner_set_channel;
435 }
436     </programlisting>
437     <para>
438       As said, the tuner interface is very analog video-centric. It features
439       functions for selecting an input or output, and on inputs, it features
440       selection of a tuning frequency if the channel supports frequency-tuning
441       on that input. Likewise, it allows signal-strength-acquiring if the input
442       supports that. Frequency tuning can be used for radio or cable-TV tuning.
443       Signal-strength is an indication of the signal and can be used for
444       visual feedback to the user or for autodetection. Next to that, it also
445       features norm selection, which is only useful for analog video elements.
446     </para>
447   </sect1>
448
449   <sect1 id="section-iface-colorbalance" xreflabel="Color Balance Interface">
450     <title>Color Balance Interface</title>
451     <para>
452       WRITEME
453     </para>
454   </sect1>
455
456   <sect1 id="section-iface-propprobe" xreflabel="Property Probe Interface">
457     <title>Property Probe Interface</title>
458     <para>
459       Property probing is a generic solution to the problem that properties'
460       value lists in an enumeration are static. We've shown enumerations in
461       <xref linkend="chapter-building-args"/>. Property probing tries to accomplish
462       a goal similar to enumeration lists: to have a limited, explicit list of
463       allowed values for a property. There are two differences between
464       enumeration lists and probing. Firstly, enumerations only allow strings
465       as values; property probing works for any value type. Secondly, the
466       contents of a probed list of allowed values may change during the life
467       of an element. The contents of an enumeration list are static. Currently,
468       property probing is being used for detection of devices (e.g. for OSS
469       elements, Video4linux elements, etc.). It could - in theory - be used
470       for any property, though.
471     </para>
472     <para>
473       Property probing stores the list of allowed (or recommended) values in a
474       <classname>GValueArray</classname> and returns that to the user.
475       <symbol>NULL</symbol> is a valid return value, too. The process of
476       property probing is separated over two virtual functions: one for probing
477       the property to create a <classname>GValueArray</classname>, and one to
478       retrieve the current <classname>GValueArray</classname>. Those two are
479       separated because probing might take a long time (several seconds). Also,
480       this simplifies interface implementation in elements. For the application,
481       there are functions that wrap those two. For more information on this,
482       have a look at the API reference for the
483       <!-- FIXME: add link, but this is in ./gst-plugins/gst-libs/gst/propertyprobe/propertyprobe.c-->
484       <classname>GstPropertyProbe</classname> interface.
485     </para>
486     <para>
487       Below is a example of property probing for the audio filter element; it
488       will probe for allowed values for the <quote>silent</quote> property.
489       Indeed, this value is a <type>gboolean</type> so it doesn't
490       make much sense. Then again, it's only an example.
491     </para>
492     <programlisting>
493 #include &lt;gst/propertyprobe/propertyprobe.h&gt;
494
495 static void     gst_my_filter_probe_interface_init      (GstPropertyProbeInterface *iface);
496
497 GType
498 gst_my_filter_get_type (void)
499 {
500 [..]
501     static const GInterfaceInfo probe_interface_info = {
502       (GInterfaceInitFunc) gst_my_filter_probe_interface_init,
503       NULL,
504       NULL
505     };
506 [..]
507     g_type_add_interface_static (my_filter_type,
508                                  GST_TYPE_PROPERTY_PROBE,
509                                  &amp;probe_interface_info);
510 [..]
511 }
512
513 static const GList *
514 gst_my_filter_probe_get_properties (GstPropertyProbe *probe)
515 {
516   GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
517   static GList *props = NULL;
518
519   if (!props) {
520     GParamSpec *pspec;
521
522     pspec = g_object_class_find_property (klass, "silent");
523     props = g_list_append (props, pspec);
524   }
525
526   return props;
527 }
528
529 static gboolean
530 gst_my_filter_probe_needs_probe (GstPropertyProbe *probe,
531                                  guint             prop_id,
532                                  const GParamSpec *pspec)
533 {
534   gboolean res = FALSE;
535
536   switch (prop_id) {
537     case ARG_SILENT:
538       res = FALSE;
539       break;
540     default:
541       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
542       break;
543   }
544
545   return res;
546 }
547
548 static void
549 gst_my_filter_probe_probe_property (GstPropertyProbe *probe,
550                                     guint             prop_id,
551                                     const GParamSpec *pspec)
552 {
553   switch (prop_id) {
554     case ARG_SILENT:
555       /* don't need to do much here... */
556       break;
557     default:
558       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
559       break;
560   }
561 }
562
563 static GValueArray *
564 gst_my_filter_get_silent_values (GstMyFilter *filter)
565 {
566   GValueArray *array = g_value_array_new (2);
567   GValue value = { 0 };
568
569   g_value_init (&amp;value, G_TYPE_BOOLEAN);
570
571   /* add TRUE */
572   g_value_set_boolean (&amp;value, TRUE);
573   g_value_array_append (array, &amp;value);
574
575   /* add FALSE */
576   g_value_set_boolean (&amp;value, FALSE);
577   g_value_array_append (array, &amp;value);
578
579   g_value_unset (&amp;value);
580
581   return array;
582 }
583
584 static GValueArray *
585 gst_my_filter_probe_get_values (GstPropertyProbe *probe,
586                                 guint             prop_id,
587                                 const GParamSpec *pspec)
588 {
589   GstMyFilter *filter = GST_MY_FILTER (probe);
590   GValueArray *array = NULL;
591
592   switch (prop_id) {
593     case ARG_SILENT:
594       array = gst_my_filter_get_silent_values (filter);
595       break;
596     default:
597       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
598       break;
599   }
600
601   return array;
602 }
603
604 static void
605 gst_my_filter_probe_interface_init (GstPropertyProbeInterface *iface)
606 {
607   iface->get_properties = gst_my_filter_probe_get_properties;
608   iface->needs_probe    = gst_my_filter_probe_needs_probe;
609   iface->probe_property = gst_my_filter_probe_probe_property;
610   iface->get_values     = gst_my_filter_probe_get_values;
611 }
612     </programlisting>
613     <para>
614       You don't need to support any functions for getting or setting values.
615       All that is handled via the standard <classname>GObject</classname>
616       <function>_set_property ()</function> and <function>_get_property ()</function>
617       functions.
618     </para>
619   </sect1>
620
621   <sect1 id="section-iface-xoverlay" xreflabel="X Overlay Interface">
622     <title>X Overlay Interface</title>
623     <para>
624       An X Overlay is basically a video output in a XFree86 drawable. Elements
625       implementing this interface will draw video in a X11 window. Through this
626       interface, applications will be proposed 2 different modes to work with
627       a plugin implementing it. The first mode is a passive mode where the plugin
628       owns, creates and destroys the X11 window. The second mode is an active
629       mode where the application handles the X11 window creation and then tell
630       the plugin where it should output video. Let's get a bit deeper in those
631       modes...
632     </para>
633     <para>
634       A plugin drawing video output in a X11 window will need to have that
635       window at one stage or another. Passive mode simply means that no window
636       has been given to the plugin before that stage, so the plugin created the
637       window by itself. In that case the plugin is responsible of destroying
638       that window when it's not needed any more and it has to tell the
639       applications that a window has been created so that the application can
640       use it. This is done using the <classname>have_xwindow_id</classname>
641       signal that can be emitted from the plugin with the
642       <function>gst_x_overlay_got_xwindow_id</function> method.
643     </para>
644     <para>
645       As you probably guessed already active mode just means sending a X11
646       window to the plugin so that video output goes there. This is done using
647       the <function>gst_x_overlay_set_xwindow_id</function> method.
648     </para>
649     <para>
650       It is possible to switch from one mode to another at any moment, so the
651       plugin implementing this interface has to handle all cases. There are only
652       2 methods that plugins writers have to implement and they most probably
653       look like that :
654     </para>
655     <programlisting><![CDATA[
656 static void
657 gst_my_filter_set_xwindow_id (GstXOverlay *overlay, XID xwindow_id)
658 {
659   GstMyFilter *my_filter = GST_MY_FILTER (overlay);
660
661   if (my_filter->window)
662     gst_my_filter_destroy_window (my_filter->window);
663     
664   my_filter->window = xwindow_id;
665 }
666
667 static void
668 gst_my_filter_get_desired_size (GstXOverlay *overlay,
669                                 guint *width, guint *height)
670 {
671   GstMyFilter *my_filter = GST_MY_FILTER (overlay);
672
673   *width = my_filter->width;
674   *height = my_filter->height;
675 }
676
677 static void
678 gst_my_filter_xoverlay_init (GstXOverlayClass *iface)
679 {
680   iface->set_xwindow_id = gst_my_filter_set_xwindow_id;
681   iface->get_desired_size = gst_my_filter_get_desired_size;
682 }
683     ]]></programlisting>
684     <para>
685       You will also need to use the interface methods to fire signals when 
686       needed such as in the pad link function where you will know the video
687       geometry and maybe create the window.
688     </para>
689     <programlisting><![CDATA[
690 static MyFilterWindow *
691 gst_my_filter_window_create (GstMyFilter *my_filter, gint width, gint height)
692 {
693   MyFilterWindow *window = g_new (MyFilterWindow, 1);
694   ...
695   gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (my_filter), window->win);
696 }
697
698 static GstPadLinkReturn
699 gst_my_filter_sink_link (GstPad *pad, const GstCaps *caps)
700 {
701   GstMyFilter *my_filter = GST_MY_FILTER (overlay);
702   gint width, height;
703   gboolean ret;
704   ...
705   ret = gst_structure_get_int (structure, "width", &width);
706   ret &= gst_structure_get_int (structure, "height", &height);
707   if (!ret) return GST_PAD_LINK_REFUSED;
708   
709   if (!my_filter->window)
710     my_filter->window = gst_my_filter_create_window (my_filter, width, height);
711
712   gst_x_overlay_got_desired_size (GST_X_OVERLAY (my_filter),
713                                   width, height);
714   ...
715 }
716     ]]></programlisting>
717   </sect1>
718
719   <sect1 id="section-iface-navigation" xreflabel="Navigation Interface">
720     <title>Navigation Interface</title>
721     <para>
722       WRITEME
723     </para>
724   </sect1>
725 </chapter>