#include <stdio.h>
#include <gst/gst.h>

int
main (int argc, char *argv[])
{
  gboolean terminate = FALSE, event_send = FALSE, toc_parsed = FALSE;
  gint64 start, stop;
  const gchar *uid;
  GList *list;
  GstElement *pipeline;
  GstBus *bus;
  GstEvent *event;
  GstMessage *msg;
  GstToc *toc;
  GstTocEntry *entry;

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

  /* Run debug mode */
  //gst_debug_set_threshold_for_name ("flacparse", GST_LEVEL_LOG);

  /* Build the pipeline */
  pipeline = gst_element_factory_make ("playbin", NULL);
  g_object_set (pipeline, "uri",
      "file:///home/dark-al/gst/tests/flac/test2.flac", NULL);

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

  /* Get bus from pipeline */
  bus = gst_element_get_bus (pipeline);

  do {
    /* Wait message */
    msg =
        gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_TOC | GST_MESSAGE_STATE_CHANGED |
        GST_MESSAGE_EOS);

    /* Print tags from TOC */
    if (msg) {
      switch (GST_MESSAGE_TYPE (msg)) {
        case GST_MESSAGE_TOC:
          if (!toc_parsed) {
            gst_message_parse_toc (msg, &toc, NULL);
            if (toc) {
              g_print ("TOC\n");
              list = gst_toc_get_entries (toc);
              while (list) {
                entry = list->data;
                gst_toc_entry_get_start_stop_times (entry, &start, &stop);
                uid = gst_toc_entry_get_uid (entry);
                g_print (" uid: %s", uid);
                if (GST_CLOCK_TIME_IS_VALID (start)) {
                  g_print (" start: %" GST_TIME_FORMAT, GST_TIME_ARGS (start));
                }
                if (GST_CLOCK_TIME_IS_VALID (stop)) {
                  g_print (" stop: %" GST_TIME_FORMAT, GST_TIME_ARGS (stop));
                }
                g_print ("\n");
                list = g_list_next (list);
              }
            }
            toc_parsed = TRUE;
          }
          break;
        case GST_MESSAGE_EOS:
          g_print ("End-Of-Stream reached.\n");
          terminate = TRUE;
          break;
        case GST_MESSAGE_STATE_CHANGED:
          /* We are only interested in state-changed messages from the pipeline */
          if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) {
            GstState old_state, new_state, pending_state;
            gst_message_parse_state_changed (msg, &old_state, &new_state,
                &pending_state);
            g_print ("Pipeline state changed from %s to %s:\n",
                gst_element_state_get_name (old_state),
                gst_element_state_get_name (new_state));
          }
          break;
        case GST_MESSAGE_ASYNC_DONE:
          g_print ("Enter TOC entry UID:\n");
          scanf ("%s", uid);
          event = gst_event_new_toc_select (uid);
          event_send = gst_element_send_event (pipeline, event);
          if (event_send)
            g_print ("Event send successfully!\n");
          else
            g_print ("Event send fail!\n");
          break;
      }
    }
  } while (!terminate);

  /* Free resources */
  if (msg != NULL)
    gst_message_unref (msg);
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}
