/*
 * Author: Matthew Waters <matthew@centricular.com>
 *
 * gcc -Wall $(pkg-config --cflags gstreamer-1.0) dynamic_source_mix.c -o dynamic_source_mix $(pkg-config --libs gstreamer-1.0)
 */

#include <gst/gst.h>

struct source
{
  GstElement *pipeline;
  GstElement *mixer;
  GstPad *mix_pad;
  GstElement *source;
};

static struct source *
add_src (GstElement * pipeline, GstElement * mixer)
{
  GstPad *src_pad;
  struct source *ret;

  ret = g_new0 (struct source, 1);

  ret->pipeline = gst_object_ref (pipeline);
  ret->mixer = gst_object_ref (mixer);
  ret->source = gst_element_factory_make ("videotestsrc", NULL);
  gst_bin_add (GST_BIN (pipeline), ret->source);

  ret->mix_pad = gst_element_get_request_pad (mixer, "sink_%u");
  src_pad = gst_element_get_static_pad (ret->source, "src");
  gst_pad_link (src_pad, ret->mix_pad);
  gst_object_unref (src_pad);

  return ret;
}

static void
delete_source (struct source * src)
{
  GstPad *src_pad;

  src_pad = gst_element_get_static_pad (src->source, "src");
  gst_pad_unlink (src_pad, src->mix_pad);
  gst_object_unref (src_pad);

  gst_element_set_state (src->source, GST_STATE_NULL);
  gst_bin_remove (GST_BIN (src->pipeline), src->source);

  gst_element_release_request_pad (src->mixer, src->mix_pad);
  gst_object_unref (src->mix_pad);

  gst_object_unref (src->mixer);
  gst_object_unref (src->pipeline);
  g_free (src);
}

int main (int argc, char *argv[])
{
  GstElement *mix, *sink;
  GstElement *pipeline;
  struct source *source1, *source2;

  gst_init (&argc, &argv);

  pipeline = gst_pipeline_new (NULL);

  mix = gst_element_factory_make ("glvideomixer", "glvideomixer");
  sink = gst_element_factory_make ("glimagesinkelement", "glimagesink");

  gst_bin_add_many (GST_BIN (pipeline), mix, sink, NULL);
  gst_element_link (mix, sink);

  source1 = add_src (pipeline, mix);
  g_object_set (G_OBJECT (source1->mix_pad), "xpos", 400, NULL);
  source2 = add_src (pipeline, mix);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  g_usleep (1000000);

  delete_source (source1);

  g_usleep (1000000);

  gst_element_set_state (pipeline, GST_STATE_NULL);

  delete_source (source2);
  gst_object_unref (pipeline);

  gst_deinit ();

  return 0;
}
