#include <gst/gst.h>

#include <string.h>

static void
on_underrun (GstElement *object, GstElement *sink)
{
  gst_element_set_state (sink, GST_STATE_PAUSED);
}

static void
on_running (GstElement *object, GstElement *sink)
{
  gst_element_set_state (sink, GST_STATE_PLAYING);
}

static void
on_overrun (GstElement *object, GstElement *sink)
{
  gst_element_set_state (sink, GST_STATE_PLAYING);
}

static void
on_rmdemux_pad_added (GstElement *element, GstPad *pad, GstElement *pipeline)
{
  GstElement *realdec, *sink, *conv, *e, *f;
  gchar *caps = gst_caps_to_string (GST_PAD_CAPS (pad));

  g_message ("Caps: %s", caps);
  if (!strncmp (caps, "audio", 5)) {
    g_free (caps);
    g_assert ((realdec = gst_element_factory_make ("ffdec_cook", NULL)));
    gst_bin_add (GST_BIN (pipeline), realdec);
    g_assert (gst_element_link (element, realdec));
    g_assert ((conv = gst_element_factory_make ("audioconvert", NULL)));
    gst_bin_add (GST_BIN (pipeline), conv);
    g_assert (gst_element_link (realdec, conv));
    g_assert ((sink = gst_element_factory_make ("autoaudiosink", NULL)));
    gst_bin_add (GST_BIN (pipeline), sink);
    g_assert (gst_element_link (conv, sink));
    g_assert (gst_element_set_state (sink, GST_STATE_PLAYING) ==
        GST_STATE_CHANGE_ASYNC);
    return;
  }
  g_free (caps);
  g_assert ((realdec = gst_element_factory_make ("realdec", NULL)));
  gst_bin_add (GST_BIN (pipeline), realdec);
  g_assert (gst_element_link (element, realdec));
  g_assert ((f = gst_element_factory_make ("queue", NULL)));
  gst_bin_add (GST_BIN (pipeline), f);
  g_assert (gst_element_link (realdec, f));
  g_object_set (G_OBJECT (f),
      "max-size-buffers", 0,
      "min-treshold-time", 3 * GST_SECOND, NULL);
  g_assert (gst_element_set_state (f, GST_STATE_PLAYING) ==
      GST_STATE_CHANGE_SUCCESS);
  g_assert ((e = gst_element_factory_make ("timeoverlay", NULL)));
  gst_bin_add (GST_BIN (pipeline), e);
  g_assert (gst_element_link (f, e));
  g_assert ((conv = gst_element_factory_make ("ffmpegcolorspace", NULL)));
  gst_bin_add (GST_BIN (pipeline), conv);
  g_assert (gst_element_link (e, conv));
  g_assert ((sink = gst_element_factory_make ("xvimagesink", NULL)));
  gst_bin_add (GST_BIN (pipeline), sink);
  g_assert (gst_element_link (conv, sink));
  g_signal_connect (G_OBJECT (f), "underrun", G_CALLBACK (on_underrun), sink);
  g_signal_connect (G_OBJECT (f), "running", G_CALLBACK (on_running), sink);
  g_signal_connect (G_OBJECT (f), "overrun", G_CALLBACK (on_overrun), sink);
  g_assert (gst_element_set_state (sink, GST_STATE_PLAYING) ==
      GST_STATE_CHANGE_ASYNC);
}

static void
on_rtspsrc_pad_added (GstElement *element, GstPad *pad, GstElement *pipeline)
{
  GstElement *rmdemux;

  rmdemux = gst_element_factory_make ("rmdemux", NULL);
  g_assert (rmdemux);
  g_signal_connect (rmdemux, "pad_added", G_CALLBACK (on_rmdemux_pad_added),
      pipeline);
  gst_bin_add (GST_BIN (pipeline), rmdemux);
  g_assert (gst_element_link (element, rmdemux));
}

int
main (int argc, char **argv)
{
  GstElement *e, *pipeline;
  GstStateChangeReturn ret;
  GstBus *bus;
  GstMessage *message;
  GError *err;
  gchar *d;

  gst_init (&argc, &argv);

  pipeline = gst_element_factory_make ("pipeline", NULL);
  g_assert (pipeline);

  e = gst_element_factory_make ("rtspsrc", NULL);
  g_assert (e);
  g_object_set (e, "location",
      "rtsp://213.254.239.50/tagesschau/realmedia/"
      "2006/0513/TV-20060513-2030-2801.rv.hi.rm", NULL);
  g_signal_connect (e, "pad_added", G_CALLBACK (on_rtspsrc_pad_added), pipeline);
  gst_bin_add (GST_BIN (pipeline), e);

  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret != GST_STATE_CHANGE_SUCCESS)
    g_error ("Could not set state: %i", ret);

  bus = gst_element_get_bus (GST_ELEMENT (pipeline));
  while (TRUE) {
    g_assert ((message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1)));
    if (message->type == GST_MESSAGE_EOS) {
      gst_message_unref (message);
      break;
    } else
      switch (message->type) {
      case GST_MESSAGE_WARNING:
        g_assert_not_reached ();
      case GST_MESSAGE_ERROR:
        gst_message_parse_error (message, &err, &d);
        g_error ("Error: %s (%s)", err->message, d);
      case GST_MESSAGE_STATE_CHANGED:
        break;
      default:
        g_message ("Message type %d unhandled.", message->type);
      }
    gst_message_unref (message);
  }

  g_object_unref (pipeline);

  return 0;
}
