#include <gst/gst.h>

typedef struct
{
  GMainLoop *loop;
  GstElement *pipeline;
} State;

static void
quit_cb (GstElement * pipeline, GstMessage * msg, State * state)
{
  g_main_loop_quit (state->loop);
}

static void
pad_added_cb (GstElement *dbin, GstPad *pad, State *state)
{

  GstElement *sink = gst_element_factory_make ("fakesink", NULL);
  g_autoptr (GstPad) sinkpad = gst_element_get_static_pad (sink, "sink");

  gst_bin_add (GST_BIN (state->pipeline), sink);
  gst_element_sync_state_with_parent (sink);

  gst_pad_link (pad, sinkpad);

  g_signal_handlers_disconnect_by_func (dbin, pad_added_cb, sink);
}

static void
decode (State *state, const gchar *uri)
{
  GstElement *dbin;
  GstElement *src;
  g_autoptr (GstBus) bus = NULL;
  GError *error = NULL;

  state->pipeline = gst_pipeline_new (NULL);
  src = gst_element_make_from_uri (GST_URI_SRC, uri, NULL, &error);

  g_assert (src && !error);


  dbin = gst_element_factory_make ("decodebin3", NULL);

  gst_bin_add_many (GST_BIN (state->pipeline), src, dbin, NULL);
  gst_element_link (src, dbin);

  g_signal_connect (dbin, "pad-added", G_CALLBACK (pad_added_cb), state);

  bus = gst_pipeline_get_bus (GST_PIPELINE (state->pipeline));
  gst_bus_add_signal_watch (bus);

  g_signal_connect (bus, "message::eos", G_CALLBACK (quit_cb), state);
  g_signal_connect (bus, "message::error", G_CALLBACK (quit_cb), state);

  gst_element_set_state (state->pipeline, GST_STATE_PLAYING);

  g_main_loop_run (state->loop);

  gst_element_set_state (state->pipeline, GST_STATE_NULL);

  g_signal_handlers_disconnect_by_func (state->pipeline, quit_cb, state);
  gst_object_unref (state->pipeline);
}

int
main (int ac, char **av)
{
  State *state = g_new0 (State, 1);
  state->loop = g_main_loop_new (NULL, FALSE);

  gst_init (NULL, NULL);

  if (ac != 2) {
    g_print ("Usage: %s URI\n", av[0]);
    return 1;
  }

  while (TRUE) {
    decode (state, av[1]);
  }

  g_main_loop_unref (state->loop);
  g_free (state);
}
