static void
gst_test_element_class_init (GstTestElementClass * klass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstPadTemplate *templ;

  gst_element_class_set_metadata (element_class, "Test element",
      "Element", "Does nothing", "Foo Bar <*****@*****.**>");

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 0);

  fail_unless (gst_element_class_get_pad_template (element_class,
          "test") == NULL);

  gst_element_class_add_pad_template (element_class,
      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 1);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test")) != NULL);
  fail_unless (gst_caps_is_any (templ->caps));

  gst_element_class_add_pad_template (element_class,
      gst_pad_template_new ("test2", GST_PAD_SRC, GST_PAD_ALWAYS,
          GST_CAPS_ANY));

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 2);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test2")) != NULL);
  fail_unless (gst_caps_is_any (templ->caps));

  /* Add "test" again, with NONE caps this time */
  gst_element_class_add_pad_template (element_class,
      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS,
          GST_CAPS_NONE));

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 2);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test")) != NULL);
  fail_unless (gst_caps_is_empty (templ->caps));
}
static gboolean
element_is_valid_filter (GstElement * element, gboolean * isdynamic)
{
  gboolean havesink = FALSE;
  gboolean havesrc = FALSE;
  gboolean done = FALSE;
  GstIterator *pads;
  GValue item = { 0, };

  if (isdynamic)
    *isdynamic = FALSE;

  pads = gst_element_iterate_pads (element);

  while (!done) {
    switch (gst_iterator_next (pads, &item)) {
      case GST_ITERATOR_OK:
      {
        GstPad *pad = g_value_get_object (&item);

        if (gst_pad_get_direction (pad) == GST_PAD_SRC)
          havesrc = TRUE;
        else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
          havesink = TRUE;

        g_value_reset (&item);
        break;
      }
      case GST_ITERATOR_RESYNC:
        gst_iterator_resync (pads);
        havesrc = FALSE;
        havesink = FALSE;
        break;
      default:
        /* ERROR and DONE */
        done = TRUE;
        break;
    }
  }

  g_value_unset (&item);
  gst_iterator_free (pads);

  /* just look at the element's class, not the factory, since there might
   * not be a factory (in case of python elements) or the factory is the
   * wrong one (in case of a GstBin sub-class) and doesn't have complete
   * information. */
  {
    GList *tmp =
        gst_element_class_get_pad_template_list (GST_ELEMENT_GET_CLASS
        (element));

    while (tmp) {
      GstPadTemplate *template = (GstPadTemplate *) tmp->data;

      if (template->direction == GST_PAD_SRC)
static void
gst_test_element2_class_init (GstTestElement2Class * klass)
{
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
  GstPadTemplate *templ;

  gst_element_class_set_metadata (element_class, "Test element 2",
      "Element", "Does nothing", "Foo Bar <*****@*****.**>");

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 2);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test")) != NULL);
  fail_unless (gst_caps_is_empty (templ->caps));

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test2")) != NULL);
  fail_unless (gst_caps_is_any (templ->caps));

  /* Add "test" pad with ANY caps, should have "test" pad with EMPTY caps before */
  gst_element_class_add_pad_template (element_class,
      gst_pad_template_new ("test", GST_PAD_SRC, GST_PAD_ALWAYS, GST_CAPS_ANY));

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 2);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test")) != NULL);
  fail_unless (gst_caps_is_any (templ->caps));


  gst_element_class_add_pad_template (element_class,
      gst_pad_template_new ("test4", GST_PAD_SRC, GST_PAD_ALWAYS,
          GST_CAPS_ANY));

  fail_unless_equals_int (g_list_length (gst_element_class_get_pad_template_list
          (element_class)), 3);

  fail_unless ((templ =
          gst_element_class_get_pad_template (element_class, "test4")) != NULL);
  fail_unless (gst_caps_is_any (templ->caps));
}
static GValueArray *
gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe,
    guint prop_id, const GParamSpec * pspec)
{
  GstElementClass *klass;
  const GList *templates;
  snd_pcm_stream_t mode = -1;
  GValueArray *array;
  GValue value = { 0, };
  GList *l, *list;

  if (!g_str_equal (pspec->name, "device")) {
    G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
    return NULL;
  }

  klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe));

  /* I'm pretty sure ALSA has a good way to do this. However, their cool
   * auto-generated documentation is pretty much useless if you try to
   * do function-wise look-ups. */
  /* we assume one pad template at max [zero=mixer] */
  templates = gst_element_class_get_pad_template_list (klass);
  if (templates) {
    if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC)
      mode = SND_PCM_STREAM_CAPTURE;
    else
      mode = SND_PCM_STREAM_PLAYBACK;
  }

  list = gst_alsa_get_device_list (mode);

  if (list == NULL) {
    GST_LOG_OBJECT (probe, "No devices found");
    return NULL;
  }

  array = g_value_array_new (g_list_length (list));
  g_value_init (&value, G_TYPE_STRING);
  for (l = list; l != NULL; l = l->next) {
    GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data);
    g_value_take_string (&value, (gchar *) l->data);
    l->data = NULL;
    g_value_array_append (array, &value);
  }
  g_value_unset (&value);
  g_list_free (list);

  return array;
}
static GstPadTemplate *
_find_element_pad_template (GstElement * element,
    GstPadDirection direction, GstPadPresence presence)
{
  GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
  GList *templ_list = gst_element_class_get_pad_template_list (klass);
  GstPadTemplate *templ;

  /* find suitable template */
  while (templ_list) {
    templ = (GstPadTemplate *) templ_list->data;

    if (GST_PAD_TEMPLATE_DIRECTION (templ) != direction
        || GST_PAD_TEMPLATE_PRESENCE (templ) != presence) {
      templ_list = templ_list->next;
      templ = NULL;
      continue;
    }

    break;
  }

  return templ;
}