#include <gst/gst.h>

#define GST_CAT_DEFAULT tee_sticky_event_misordering
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "tee_sticky_event_misordering"

gboolean finish = FALSE;
GMutex mutex;
GCond cond;

static gpointer
add_sinks_thread (gpointer data)
{
  GstElement *tee = GST_ELEMENT (data);
  GstElement *pipeline = GST_ELEMENT_PARENT (tee);
  guint i;

  for (i = 0; i<100; i++) {
    GstElement *fakesink;

    GST_DEBUG ("Adding %d", i);

    fakesink = gst_element_factory_make ("fakesink", NULL);
    gst_bin_add (GST_BIN (pipeline), fakesink);
    gst_element_sync_state_with_parent (fakesink);
    gst_element_link (tee, fakesink);
  }

  g_mutex_lock (&mutex);
  finish = TRUE;
  GST_DEBUG ("All sink added");
  g_cond_signal (&cond);
  g_mutex_unlock (&mutex);

  return NULL;
}

int
main(int argc, char ** argv)
{
  GstElement *pipeline, *fakesrc, *filter, *tee;
  GstElement *fakesink;
  GstCaps *filter_caps;
  GThread *thread;

  gst_init (&argc, &argv);

  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);

  pipeline = gst_pipeline_new (NULL);

  fakesrc = gst_element_factory_make ("fakesrc", NULL);

  filter = gst_element_factory_make ("capsfilter", NULL);
  filter_caps = gst_caps_from_string ("audio/x-raw, rate=(int)44100");
  g_object_set (filter, "caps", filter_caps, NULL);
  gst_caps_unref (filter_caps);
  
  tee = gst_element_factory_make ("tee", NULL);
  fakesink = gst_element_factory_make ("fakesink", NULL);

  gst_bin_add_many (GST_BIN (pipeline), fakesrc, filter, tee, fakesink, NULL);
  gst_element_link_many (fakesrc, filter, tee, fakesink, NULL);

  thread = g_thread_new ("add_sinks", add_sinks_thread, tee);
  g_thread_unref (thread);

  g_usleep (50000);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  g_mutex_lock (&mutex);
  GST_DEBUG ("Waiting for all sinks added");
  while (!finish) {
    g_cond_wait (&cond, &mutex);
  }

  gst_element_set_state (pipeline, GST_STATE_NULL);
  g_object_unref (pipeline);
  gst_deinit ();

  return 0;
}
