#include <gst/gst.h>

GstElement *pipeline, *audio;

static gboolean
bus_call(GstBus *bus, GstMessage *msg, gpointer data)
{
	GMainLoop *loop = (GMainLoop *) data;

	switch (GST_MESSAGE_TYPE(msg))
	{
		case GST_MESSAGE_EOS:
		{
			g_print("EOS\n");
			g_main_loop_quit(loop);
			break;
		}
		case GST_MESSAGE_ERROR:
		{
			gchar *debug;
			GError *err;

			gst_message_parse_error(msg, &err, &debug);
			g_free(debug);

			g_print("%s\n", err->message);
			g_error_free(err);

			g_main_loop_quit(loop);
			break;
		}
		default:
			break;
	}

	return TRUE;
}

static void
cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data)
{
	GstCaps *caps;
	GstStructure *str;
	GstPad *audiopad;

	audiopad = gst_element_get_static_pad (audio, "sink");
	if (GST_PAD_IS_LINKED (audiopad))
	{
		g_object_unref (audiopad);
		return;
	}

	caps = gst_pad_get_caps (pad);
	str = gst_caps_get_structure (caps, 0);
	if (!g_strrstr (gst_structure_get_name (str), "audio"))
	{
		gst_caps_unref (caps);
		gst_object_unref (audiopad);
		return;
	}
	gst_caps_unref (caps);

	gst_pad_link (pad, audiopad);
}

int
main (int argc, char ** argv)
{
	GMainLoop *loop;
	GstElement *src, *dec, *conv, *resample, *filter, *sink;
	GstCaps *filtercaps;
	GstPad *audiopad;
	GstBus *bus;
	gchar *path, *filename;

	gst_init (&argc, &argv);
	loop = g_main_loop_new (NULL, FALSE);

	if (argc != 2)
	{
		g_print ("Error: no supplied file!\n");
		return 1;
	}

	pipeline = gst_pipeline_new ("pipeline");

	bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
	gst_bus_add_watch (bus, bus_call, loop);
	gst_object_unref (bus);

	src = gst_element_factory_make ("filesrc", NULL);
	g_object_set (G_OBJECT (src), "location", argv[1], NULL);
	dec = gst_element_factory_make ("decodebin", NULL);
	g_signal_connect (dec, "new-decoded-pad", G_CALLBACK (cb_newpad), NULL);
	gst_bin_add_many (GST_BIN (pipeline), src, dec, NULL);
	gst_element_link (src, dec);

	audio = gst_bin_new ("audiobin");
	conv = gst_element_factory_make ("audioconvert", NULL);

	/* Here's the bit of magic */
	resample = gst_element_factory_make("audioresample", NULL);
	filter = gst_element_factory_make("capsfilter", NULL);
	filtercaps = gst_caps_new_full(gst_structure_new("audio/x-raw-int",
				"channels", G_TYPE_INT, 2,
				"width", G_TYPE_INT, 16,
				"depth", G_TYPE_INT, 16,
				"endianness", G_TYPE_INT, 1234,
				"rate", G_TYPE_INT, 44100,
				"signed", G_TYPE_BOOLEAN, TRUE,
				NULL), NULL);
	g_object_set(GST_OBJECT(filter), "caps", filtercaps, NULL);
	gst_caps_unref(filtercaps);

	audiopad = gst_element_get_static_pad(conv, "sink");
	sink = gst_element_factory_make ("filesink", NULL);
	
	/* Generate filename */
	filename = g_path_get_basename(argv[1]);
	path = g_strconcat("/tmp/ecdb/", filename, ".wav", NULL);
	g_object_set(G_OBJECT(sink), "location", path, NULL);

	free(filename);
	free(path);

	gst_bin_add_many(GST_BIN (audio), conv, resample, filter, sink, NULL);
	gst_element_link_many(conv, resample, filter, sink, NULL);
	gst_element_add_pad (audio, gst_ghost_pad_new ("sink", audiopad));
	gst_object_unref (audiopad);
	gst_bin_add (GST_BIN (pipeline), audio);

	gst_element_set_state (pipeline, GST_STATE_PLAYING);
	g_main_loop_run (loop);

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

	return 0;
}
