#include <gst/gst.h>


typedef struct
{
    GMainLoop *mainloop;
    GstElement *pipeline;
    GstElement *decoder; // weak ref
    GstElement *sink; // weak ref
    GstBus *bus;
} AppData;

static void on_pad_added (GstElement *element,
                          GstPad *pad,
                          gpointer user_data)
{
    AppData *data = (AppData*)user_data;
    GstCaps *caps = gst_pad_get_caps (pad);
    GstStructure *structure = gst_caps_get_structure (caps, 0);
    const char *name = gst_structure_get_name (structure);

    if (g_str_has_prefix (name, "audio/"))
    {
        GstPad *sink_pad =
            gst_element_get_static_pad (data->sink, "sink");

        gst_pad_link (pad, sink_pad);

        // only play the first 5 seconds
        gst_element_seek (data->pipeline, 1.0, GST_FORMAT_TIME,
                          GST_SEEK_FLAG_FLUSH,
                          GST_SEEK_TYPE_SET, 0,
                          GST_SEEK_TYPE_SET, 5 * GST_SECOND);

        gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
    }
    gst_caps_unref (caps);
}

static void on_eos (GstBus *bus,
                    GstMessage *message,
                    gpointer user_data)
{
    AppData *data = (AppData*)user_data;
    gst_element_set_state (data->pipeline, GST_STATE_NULL);

    g_main_loop_quit (data->mainloop);
}


int main (int argc, char** argv)
{
    gst_init (&argc, &argv);
    AppData d;

    if (argc != 2)
        g_error ("must specify file URI on commandline");

    d.mainloop = g_main_loop_new (NULL, FALSE);
    d.pipeline = gst_pipeline_new (0);
    d.decoder = gst_element_factory_make ("uridecodebin", 0);
    d.sink = gst_element_factory_make ("pulsesink", 0);
    d.bus = gst_pipeline_get_bus (GST_PIPELINE (d.pipeline));

    gst_bin_add_many (GST_BIN (d.pipeline),
                      d.decoder, d.sink, NULL);

    g_object_set (d.decoder,
                  "uri", argv[1],
                  NULL);
    g_signal_connect (d.decoder, "pad-added",
                      G_CALLBACK (on_pad_added), &d);

    gst_bus_add_signal_watch (d.bus);

    g_signal_connect (d.bus, "message::eos",
                      G_CALLBACK (on_eos), &d);

    gst_element_set_state (d.pipeline, GST_STATE_PAUSED);

    g_main_loop_run (d.mainloop);

    g_object_unref (d.bus);
    g_object_unref (d.pipeline);
}
