/****************************************************
 *              GstElement vmetods                  *
 ****************************************************/
static GstPad *
_request_new_pad (GstElement * element, GstPadTemplate * templ,
    const gchar * name, const GstCaps * caps)
{
  GstPad *audioresample_srcpad, *audioconvert_sinkpad, *tmpghost;
  GstPad *ghost;
  GstElement *audioconvert, *audioresample;
  PadInfos *infos = g_slice_new0 (PadInfos);
  GESSmartAdder *self = GES_SMART_ADDER (element);

  infos->adder_pad = gst_element_request_pad (self->adder, templ, NULL, caps);
  if (infos->adder_pad == NULL) {
    GST_WARNING_OBJECT (element, "Could not get any pad from GstAdder");

    return NULL;
  }

  infos->self = self;

  infos->bin = gst_bin_new (NULL);
  audioconvert = gst_element_factory_make ("audioconvert", NULL);
  audioresample = gst_element_factory_make ("audioresample", NULL);

  gst_bin_add_many (GST_BIN (infos->bin), audioconvert, audioresample, NULL);
  gst_element_link_many (audioconvert, audioresample, NULL);

  audioconvert_sinkpad = gst_element_get_static_pad (audioconvert, "sink");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, audioconvert_sinkpad));
  gst_object_unref (audioconvert_sinkpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);

  gst_bin_add (GST_BIN (self), infos->bin);
  ghost = gst_ghost_pad_new (NULL, tmpghost);
  gst_pad_set_active (ghost, TRUE);
  if (!gst_element_add_pad (GST_ELEMENT (self), ghost))
    goto could_not_add;

  audioresample_srcpad = gst_element_get_static_pad (audioresample, "src");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, audioresample_srcpad));
  gst_object_unref (audioresample_srcpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);
  gst_pad_link (tmpghost, infos->adder_pad);

  LOCK (self);
  g_hash_table_insert (self->pads_infos, ghost, infos);
  UNLOCK (self);

  GST_DEBUG_OBJECT (self, "Returning new pad %" GST_PTR_FORMAT, ghost);
  return ghost;

could_not_add:
  {
    GST_ERROR_OBJECT (self, "could not add pad");
    destroy_pad (infos);
    return NULL;
  }
}
/****************************************************
 *              GstElement vmetods                  *
 ****************************************************/
static GstPad *
_request_new_pad (GstElement * element, GstPadTemplate * templ,
    const gchar * name, const GstCaps * caps)
{
  GstPad *videoconvert_srcpad, *videoconvert_sinkpad, *tmpghost;
  PadInfos *infos = g_slice_new0 (PadInfos);
  GESSmartMixer *self = GES_SMART_MIXER (element);
  GstPad *ghost;
  GstElement *videoconvert;

  infos->mixer_pad = gst_element_request_pad (self->mixer,
      gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self->mixer),
          "sink_%u"), NULL, NULL);

  if (infos->mixer_pad == NULL) {
    GST_WARNING_OBJECT (element, "Could not get any pad from GstMixer");
    g_slice_free (PadInfos, infos);

    return NULL;
  }

  infos->self = self;

  infos->bin = gst_bin_new (NULL);
  videoconvert = gst_element_factory_make ("videoconvert", NULL);

  gst_bin_add (GST_BIN (infos->bin), videoconvert);

  videoconvert_sinkpad = gst_element_get_static_pad (videoconvert, "sink");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, videoconvert_sinkpad));
  gst_object_unref (videoconvert_sinkpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);

  gst_bin_add (GST_BIN (self), infos->bin);
  ghost = gst_ghost_pad_new (NULL, tmpghost);
  gst_pad_set_active (ghost, TRUE);
  if (!gst_element_add_pad (GST_ELEMENT (self), ghost))
    goto could_not_add;

  videoconvert_srcpad = gst_element_get_static_pad (videoconvert, "src");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, videoconvert_srcpad));
  gst_object_unref (videoconvert_srcpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);
  gst_pad_link (tmpghost, infos->mixer_pad);

  infos->probe_id =
      gst_pad_add_probe (infos->mixer_pad, GST_PAD_PROBE_TYPE_BUFFER,
      (GstPadProbeCallback) parse_metadata, self, NULL);

  LOCK (self);
  g_hash_table_insert (self->pads_infos, ghost, infos);
  UNLOCK (self);

  GST_DEBUG_OBJECT (self, "Returning new pad %" GST_PTR_FORMAT, ghost);
  return ghost;

could_not_add:
  {
    GST_ERROR_OBJECT (self, "could not add pad");
    destroy_pad (infos);
    return NULL;
  }
}