
<!-- ############ chapter ############# -->

<chapter id="chapter-building-pads">
  <title>Specifying the pads</title>
  <para>
    As explained before, pads are the port through which data goes in and out
    of your element, and that makes them a very important item in the process
    of element creation. In the boilerplate code, we have seen how static pad
    templates take care of registering pad templates with the element class.
    Here, we will see how to create actual elements, use an <function>_event
    ()</function>-function to configure for a particular format and how to
    register functions to let data flow through the element.
  </para>
  <para>
    In the element <function>_init ()</function> function, you create the pad
    from the pad template that has been registered with the element class in
    the <function>_class_init ()</function> function. After creating the pad,
    you have to set a <function>_chain ()</function> function pointer that will
    receive and process the input data on the sinkpad.
    You can optionally also set an <function>_event ()</function> function
    pointer and a <function>_query ()</function> function pointer.
    Alternatively, pads can also operate in looping mode, which means that they
    can pull data themselves. More on this topic later. After that, you have
    to register the pad with the element. This happens like this:
  </para>
  <programlisting><!-- example-begin init.func a --><!--
#include "filter.h"
#include &lt;string.h&gt;

static GstStateChangeReturn
gst_my_filter_change_state (GstElement * element, GstStateChange transition);

G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);

static void
gst_my_filter_class_init (gpointer klass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  static GstStaticPadTemplate sink_template =
  GST_STATIC_PAD_TEMPLATE (
    "sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
  );
  static GstStaticPadTemplate src_template =
  GST_STATIC_PAD_TEMPLATE (
    "src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
  );

  gst_element_class_set_static_metadata (element_class,
    "An example plugin",
    "Example/FirstExample",
    "Shows the basic structure of a plugin",
    "your name <your.name@your.isp>");

  gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&src_template));
  gst_element_class_add_pad_template (element_class,
        gst_static_pad_template_get (&sink_template));
}

static void
gst_my_filter_class_init (GstMyFilterClass * klass)
{
  GST_ELEMENT_CLASS (klass)->change_state = gst_my_filter_change_state;
}
--><!-- example-end init.func a -->
<!-- example-begin init.func c --><!--
static GstFlowReturn	gst_my_filter_chain	 (GstPad        *pad,
                                                  GstObject     *parent,
						  GstBuffer     *buf);
static gboolean		gst_my_filter_sink_event (GstPad        *pad,
                                                  GstObject     *parent,
						  GstEvent      *event);
static gboolean 	gst_my_filter_src_query  (GstPad        *pad,
                                                  GstObject     *parent,
                                                  GstQuery      *query);
static gboolean 	gst_my_filter_sink_query (GstPad        *pad,
                                                  GstObject     *parent,
                                                  GstQuery      *query);
--><!-- example-end init.func c -->
<!-- example-begin init.func d -->

static void
gst_my_filter_init (GstMyFilter *filter)
{
  /* pad through which data comes in to the element */
  filter-&gt;sinkpad = gst_pad_new_from_static_template (
	&amp;sink_template, "sink");
  /* pads are configured here with gst_pad_set_*_function () */
<!-- example-end init.func d -->
<!-- example-begin init.func e --><!--
  gst_pad_set_chain_function (filter-&gt;sinkpad, gst_my_filter_chain);
  gst_pad_set_event_function (filter-&gt;sinkpad, gst_my_filter_sink_event);
  gst_pad_set_query_function (filter-&gt;sinkpad, gst_my_filter_sink_query);
--><!-- example-end init.func e -->
<!-- example-begin init.func f -->
  gst_element_add_pad (GST_ELEMENT (filter), filter-&gt;sinkpad);

  /* pad through which data goes out of the element */
  filter-&gt;srcpad = gst_pad_new_from_static_template (
	&amp;src_template, "src");
  /* pads are configured here with gst_pad_set_*_function () */
<!-- example-end init.func f -->
<!-- example-begin init.func g --><!--
  gst_pad_set_query_function (filter-&gt;srcpad, gst_my_filter_src_query);
--><!-- example-end init.func g -->
<!-- example-begin init.func h -->
  gst_element_add_pad (GST_ELEMENT (filter), filter-&gt;srcpad);

  /* properties initial value */
  filter->silent = FALSE;
}
  <!-- example-end init.func h --></programlisting>

<!-- example-begin pads.c --><!--
#include "init.func"

static gboolean
gst_my_filter_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  return gst_pad_event_default (pad, parent, event);
}

static GstFlowReturn
gst_my_filter_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  return gst_pad_push (GST_MY_FILTER (parent)->srcpad, buf);
}

static GstStateChangeReturn
gst_my_filter_change_state (GstElement * element, GstStateChange transition)
{
  return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS,
      change_state, (element, transition), GST_STATE_CHANGE_SUCCESS);
}

#include "register.func"
--><!-- example-end pads.c -->
</chapter>

