docs/pwg/advanced_interfaces.xml: Docs for mixer interface. Also a check for website...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 28 Jan 2004 12:20:40 +0000 (12:20 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Wed, 28 Jan 2004 12:20:40 +0000 (12:20 +0000)
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.

ChangeLog
docs/pwg/advanced-interfaces.xml

index 93a61e8..cb3b68a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
index 48c377c..df5c0ea 100644 (file)
   <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",
+                               &amp;my_filter_info, 0);
+    g_type_add_interface_static (my_filter_type,
+                                GST_TYPE_SOME_INTERFACE,
+                                 &amp;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,
+                                &amp;implements_interface_info);
+    g_type_add_interface_static (my_filter_type,
+                                GST_TYPE_MIXER,
+                                &amp;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">