mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
docs/pwg/advanced_interfaces.xml: Docs for mixer interface. Also a check for website uploading.
Original commit message from CVS: 2004-01-28 Ronald Bultje <rbultje@ronald.bitfreak.net> * docs/pwg/advanced_interfaces.xml: Docs for mixer interface. Also a check for website uploading.
This commit is contained in:
parent
1ad4c7a804
commit
fad4a520cd
2 changed files with 213 additions and 2 deletions
|
@ -1,3 +1,8 @@
|
|||
2004-01-28 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* docs/pwg/advanced_interfaces.xml:
|
||||
Docs for mixer interface. Also a check for website uploading.
|
||||
|
||||
2004-01-28 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* docs/HACKING:
|
||||
|
|
|
@ -43,15 +43,221 @@
|
|||
<sect1 id="sect1-iface-general" xreflabel="How to Implement Interfaces">
|
||||
<title>How to Implement Interfaces</title>
|
||||
<para>
|
||||
WRITEME
|
||||
Implementing interfaces is intiated in the <function>_get_type ()</function>
|
||||
of your element. You can register one or more interfaces after having
|
||||
registered the type itself. Some interfaces have dependencies on other
|
||||
interfaces or can only be registered by certain types of elements. You
|
||||
will be notified of doing that wrongly when using the element: it will
|
||||
quit with failed assertions, which will explain what went wrong. In the
|
||||
case of GStreamer, the only dependency that <emphasis>some</emphasis>
|
||||
interfaces have is <classname>GstImplementsInterface</classname>. Per
|
||||
interface, we will indicate clearly when it depends on this extension.
|
||||
If it does, you need to register support for <emphasis>that</emphasis>
|
||||
interface before registering support for the interface that you're
|
||||
wanting to support. The example below explains how to add support for a
|
||||
simple interface with no further dependencies. For a small explanation
|
||||
on <classname>GstImplementsInterface</classname>, see the next section
|
||||
about the mixer interface: <xref linkend="sect1-iface-mixer"/>.
|
||||
</para>
|
||||
<programlisting>
|
||||
static void gst_my_filter_some_interface_init (GstSomeInterface *iface);
|
||||
|
||||
GType
|
||||
gst_my_filter_get_type (void)
|
||||
{
|
||||
static GType my_filter_type = 0;
|
||||
|
||||
if (!my_filter_type) {
|
||||
static const GTypeInfo my_filter_info = {
|
||||
sizeof (GstMyFilterClass),
|
||||
(GBaseInitFunc) gst_my_filter_base_init,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_my_filter_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstMyFilter),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_my_filter_init
|
||||
};
|
||||
static const GInterfaceInfo some_interface_info = {
|
||||
(GInterfaceInitFunc) gst_my_filter_some_interface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
my_filter_type =
|
||||
g_type_register_static (GST_TYPE_MY_FILTER,
|
||||
"GstMyFilter",
|
||||
&my_filter_info, 0);
|
||||
g_type_add_interface_static (my_filter_type,
|
||||
GST_TYPE_SOME_INTERFACE,
|
||||
&some_interface_info);
|
||||
}
|
||||
|
||||
return my_filter_type;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_my_filter_some_interface_init (GstSomeInterface *iface)
|
||||
{
|
||||
/* here, you would set virtual function pointers in the interface */
|
||||
}
|
||||
</programlisting>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect1-iface-mixer" xreflabel="Mixer Interface">
|
||||
<title>Mixer Interface</title>
|
||||
<para>
|
||||
WRITEME
|
||||
The goal of the mixer interface is to provide a simple yet powerful API
|
||||
to applications for audio hardware mixer/volume control. Most soundcards
|
||||
have hardware mixers, where volume can be changed, they can be muted,
|
||||
inputs can be modified to mix their content into what will be read from
|
||||
the device by applications (in our case: audio source plugins). The
|
||||
mixer interface is the way to control those. The mixer interface can
|
||||
also be used for volume control in software (e.g. the <quote>volume</quote>
|
||||
element). The end goal of this interface is to allow development of
|
||||
hardware volume control applications and for the control of audio volume
|
||||
and input/output settings.
|
||||
</para>
|
||||
<para>
|
||||
The mixer interface requires the <classname>GstImplementsInterface</classname>
|
||||
interface to be implemented by the element. The example below will
|
||||
feature both, so it serves as an example for the
|
||||
<classname>GstImplementsInterface</classname>, too. In the
|
||||
<classname>GstImplementsInterface</classname>, it is required to set a
|
||||
function pointer for the <function>supported ()</function> function. If
|
||||
you don't, this function will always return FALSE (default
|
||||
implementation) and the mixer interface implementation will not work. For
|
||||
the mixer interface, the only required function is
|
||||
<function>list_tracks ()</function>. All other function pointers in the
|
||||
mixer interface are optional, although it is strongly recommended to set
|
||||
function pointers for at least the <function>get_volume ()</function> and
|
||||
<function>set_volume ()</function> functions. The API reference for this
|
||||
interface documents the goal of each function, so we will limit ourselves
|
||||
to the implementation here.
|
||||
</para>
|
||||
<programlisting>
|
||||
typedef struct _GstMyFilter {
|
||||
[..]
|
||||
gint volume;
|
||||
GList *tracks;
|
||||
} GstMyFilter;
|
||||
|
||||
static void gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface);
|
||||
static void gst_my_filter_mixer_interface_init (GstMixerClass *iface);
|
||||
|
||||
GType
|
||||
gst_my_filter_get_type (void)
|
||||
{
|
||||
[..]
|
||||
static const GInterfaceInfo implements_interface_info = {
|
||||
(GInterfaceInitFunc) gst_my_filter_implements_interface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
static const GInterfaceInfo mixer_interface_info = {
|
||||
(GInterfaceInitFunc) gst_my_filter_mixer_interface_init,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
[..]
|
||||
g_type_add_interface_static (my_filter_type,
|
||||
GST_TYPE_IMPLEMENTS_INTERFACE,
|
||||
&implements_interface_info);
|
||||
g_type_add_interface_static (my_filter_type,
|
||||
GST_TYPE_MIXER,
|
||||
&mixer_interface_info);
|
||||
[..]
|
||||
}
|
||||
|
||||
static void
|
||||
gst_my_filter_init (GstMyFilter *filter)
|
||||
{
|
||||
GstMixerTrack *track = NULL;
|
||||
[..]
|
||||
filter->volume = 100;
|
||||
filter->tracks = NULL;
|
||||
track = g_object_new (GST_TYPE_MIXER_TRACK, NULL);
|
||||
track->label = g_strdup ("MyTrack");
|
||||
track->num_channels = 1;
|
||||
track->min_volume = 0;
|
||||
track->max_volume = 100;
|
||||
track->flags = GST_MIXER_TRACK_SOFTWARE;
|
||||
filter->tracks = g_list_append (filter->tracks, track);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_my_filter_interface_supported (GstImplementsInterface *iface,
|
||||
GType iface_type)
|
||||
{
|
||||
g_return_val_if_fail (iface_type == GST_TYPE_MIXER, FALSE);
|
||||
|
||||
/* for the sake of this example, we'll always support it. However, normally,
|
||||
* you would check whether the device you've opened supports mixers. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_my_filter_implements_interface_init (GstImplementsInterfaceClass *iface)
|
||||
{
|
||||
iface->supported = gst_my_filter_interface_supported;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the list of support tracks (inputs, outputs)
|
||||
* on this element instance. Elements usually build this list during
|
||||
* _init () or when going from NULL to READY.
|
||||
*/
|
||||
|
||||
static const GList *
|
||||
gst_my_filter_mixer_list_tracks (GstMixer *mixer)
|
||||
{
|
||||
GstMyFilter *filter = GST_MY_FILTER (mixer);
|
||||
|
||||
return filter->tracks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set volume. volumes is an array of size track->num_channels, and
|
||||
* each value in the array gives the wanted volume for one channel
|
||||
* on the track.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_my_filter_mixer_set_volume (GstMixer *mixer,
|
||||
GstMixerTrack *track,
|
||||
gint *volumes)
|
||||
{
|
||||
GstMyFilter *filter = GST_MY_FILTER (mixer);
|
||||
|
||||
filter->volume = volumes[0];
|
||||
|
||||
g_print ("Volume set to %d\n", filter->volume);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_my_filter_mixer_get_volume (GstMixer *mixer,
|
||||
GstMixerTrack *track,
|
||||
gint *volumes)
|
||||
{
|
||||
GstMyFilter *filter = GST_MY_FILTER (mixer);
|
||||
|
||||
volumes[0] = filter->volume;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_my_filter_mixer_interface_init (GstMixerClass *iface)
|
||||
{
|
||||
/* the mixer interface requires a definition of the mixer type:
|
||||
* hardware or software? */
|
||||
GST_MIXER_TYPE (iface) = GST_MIXER_SOFTWARE;
|
||||
|
||||
/* virtual function pointers */
|
||||
iface->list_tracks = gst_my_filter_mixer_list_tracks;
|
||||
iface->set_volume = gst_my_filter_mixer_set_volume;
|
||||
iface->get_volume = gst_my_filter_mixer_get_volume;
|
||||
}
|
||||
</programlisting>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="sect1-iface-tuner" xreflabel="Tuner Interface">
|
||||
|
|
Loading…
Reference in a new issue