#include <gst/gst.h>
   


static GstTask *my_task;
static GRecMutex my_task_mutex;

static GstClockID my_clock_id;

static void
my_task_fun (gpointer user_data)
{
  GST_OBJECT_LOCK (my_task);

  while (GST_TASK_STATE (my_task) != GST_TASK_STOPPED) {
    GstClockReturn res;

    GST_TASK_WAIT (my_task);

     do {
      if (G_UNLIKELY (my_clock_id == NULL))
        break;

      res = gst_clock_id_wait (my_clock_id, NULL);

      switch (res) {
        case GST_CLOCK_OK:
          g_message ("task GST_CLOCK_OK");
          break;
        case GST_CLOCK_BADTIME:
        case GST_CLOCK_UNSUPPORTED:
        case GST_CLOCK_ERROR:
        break;
        case GST_CLOCK_UNSCHEDULED:
          g_message ("task GST_CLOCK_UNSCHEDULED");
          break;
        case GST_CLOCK_EARLY:
          g_message ("task GST_CLOCK_EARLY");
        break;
        case GST_CLOCK_BUSY:
        case GST_CLOCK_DONE:
        default:
          break;
      }
    } while (res == GST_CLOCK_OK
        || res == GST_CLOCK_EARLY
        || res == GST_CLOCK_BUSY
        || res == GST_CLOCK_DONE);
  }
  g_message ("task exiting");
  GST_OBJECT_UNLOCK (my_task);
}


static void
set_timer (GstElement *pipeline)
{
  GstClock *clock;
  if ((clock = GST_ELEMENT_CLOCK (pipeline)) == NULL)
    g_message ("No clock");
  else {
    GstClockTime next_timeout, period;
    next_timeout = gst_clock_get_time (clock) /*+ 10*GST_MSECOND*/;
    period = 1*GST_MSECOND;
    if (!my_clock_id) {
      my_clock_id = gst_clock_new_periodic_id (clock,
         next_timeout, period);

    } else if (!gst_clock_periodic_id_reinit (clock, my_clock_id,
          next_timeout, period)) {
      gst_clock_id_unref(my_clock_id);
      my_clock_id = gst_clock_new_periodic_id (clock,
         next_timeout, period);
    }
    g_message ("set timer");
    GST_TASK_SIGNAL (my_task);
  }
}

static void
unschedule_timer (void)
{
  if (my_clock_id) {
    g_message ("unschedule current timer");
    gst_clock_id_unschedule (my_clock_id);
  }
}

int main(int argc, char *argv[]) {
  GstElement *pipeline;
  GstBus *bus;
  GstMessage *msg;
  my_clock_id = NULL;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);


  g_rec_mutex_init (&my_task_mutex);
  my_task = gst_task_new (my_task_fun, NULL, NULL);
  gst_task_set_lock (my_task, &my_task_mutex);


  /* Build the pipeline */
  pipeline = gst_parse_launch ("audiotestsrc ! fakesink", NULL);

  /* Start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);

  g_message ("task starting");

  gst_task_start (my_task);


  while (1) {

    unschedule_timer ();

    GST_OBJECT_LOCK (my_task);
    set_timer (pipeline);
    GST_OBJECT_UNLOCK (my_task);
    usleep(600);
  }




  g_message ("task stopping");
  gst_task_stop (my_task);

  gst_task_join (my_task);
  gst_object_unref (my_task);
  my_task = NULL;
  g_rec_mutex_clear (&my_task_mutex);

  if (my_clock_id) {
    gst_clock_id_unref (my_clock_id);
    my_clock_id = NULL;
  }

  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);


  return 0;
}
