From fad4a520cdf0d9a178a2f3c33d698b1d39453ba9 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 28 Jan 2004 12:20:40 +0000 Subject: [PATCH] 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 * docs/pwg/advanced_interfaces.xml: Docs for mixer interface. Also a check for website uploading. --- ChangeLog | 5 + docs/pwg/advanced-interfaces.xml | 210 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 213 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93a61e8..cb3b68a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2004-01-28 Ronald Bultje + + * docs/pwg/advanced_interfaces.xml: + Docs for mixer interface. Also a check for website uploading. + 2004-01-28 Thomas Vander Stichele * docs/HACKING: diff --git a/docs/pwg/advanced-interfaces.xml b/docs/pwg/advanced-interfaces.xml index 48c377c..df5c0ea 100644 --- a/docs/pwg/advanced-interfaces.xml +++ b/docs/pwg/advanced-interfaces.xml @@ -43,15 +43,221 @@ How to Implement Interfaces - WRITEME + Implementing interfaces is intiated in the _get_type () + 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 some + interfaces have is GstImplementsInterface. Per + interface, we will indicate clearly when it depends on this extension. + If it does, you need to register support for that + 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 GstImplementsInterface, see the next section + about the mixer interface: . + +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 */ +} + Mixer Interface - 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 volume + 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. + + The mixer interface requires the GstImplementsInterface + interface to be implemented by the element. The example below will + feature both, so it serves as an example for the + GstImplementsInterface, too. In the + GstImplementsInterface, it is required to set a + function pointer for the supported () 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 + list_tracks (). All other function pointers in the + mixer interface are optional, although it is strongly recommended to set + function pointers for at least the get_volume () and + set_volume () functions. The API reference for this + interface documents the goal of each function, so we will limit ourselves + to the implementation here. + + +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; +} + -- 2.7.4