#include <gst/gst.h>
#include <glib.h>
#include <string.h>
#include <unistd.h>

#define N_FILTERS 1
#define DEBUG TRUE

GValueArray **va_right, **va_left;


/****** LOAD_FILTERS **********************************/
/* This function loads all the filters for the audiofilter Gstreamer element */
void load_filters ()
{
	int n_coefs_filter = 512;
	gdouble *filter1_kernel, *filter2_kernel;
	guint i, n_filter;
	FILE *pf;
	char file [200] = "";
	g_type_init ();

	filter1_kernel = (gdouble *) malloc (sizeof(gdouble) * n_coefs_filter);
	filter2_kernel = (gdouble *) malloc (sizeof(gdouble) * n_coefs_filter);

	if (DEBUG) g_print("\nLoading all filter values...");

	va_right = (GValueArray **) malloc (sizeof (GValueArray *) * N_FILTERS);
	va_left = (GValueArray **) malloc (sizeof (GValueArray *) * N_FILTERS);

	for (n_filter = 0; n_filter < N_FILTERS; n_filter++)
	{
		GValue v1 = {0}, v2 = {0};
		va_right[n_filter] = g_value_array_new (n_coefs_filter);
		va_left[n_filter] = g_value_array_new (n_coefs_filter);
		
		sprintf(file, "filter0.txt");

		pf = fopen (file, "r");
	
		if (pf == NULL)
		{
			if (DEBUG) g_print("Impossible to load filter!...");
			for (i=0; i< n_coefs_filter; i++)
			{
				filter1_kernel[i] = 0;
				filter2_kernel[i] = 0;
			}
			filter1_kernel[n_coefs_filter/2] = 10000;
			filter2_kernel[n_coefs_filter/2] = 10000;
		}
		else
		{
			for (i=0; i<n_coefs_filter; i++)
				fscanf(pf,"%lf %lf\n",&(filter1_kernel[i]),&(filter2_kernel[i]));
			fclose(pf);
		}

		for (i=0; i< n_coefs_filter; i++)
		{
			filter1_kernel[i] /= 10000;
			filter2_kernel[i] /= 10000;
		}

		g_value_init (&v1, G_TYPE_DOUBLE);
		g_value_init (&v2, G_TYPE_DOUBLE);
		for (i = 0; i < n_coefs_filter; i++) {
			g_value_set_double (&v1, filter1_kernel[i]);
			g_value_set_double (&v2, filter2_kernel[i]);
			g_value_array_append (va_right[n_filter], &v1);
			g_value_array_append (va_left[n_filter], &v2);
			g_value_reset (&v1);
			g_value_reset (&v2);
		}
	}

	if (DEBUG) g_print("done\n");
}



/************ MAIN FUNCTION ****************************/
int main (int argc, char *argv[])
{
	GstElement *filter1, *filter2, *pipeline;
	gchar launch_string[1000];

	sprintf (launch_string, "filesrc location=introduction.mp3 ! mad ! audioconvert ! deinterleave name=splitter interleave name=merger ! audioconvert ! autoaudiosink \\ \n splitter.src0 ! queue ! audioconvert ! audiofirfilter name=filter1 ! queue ! merger. \\ \n splitter.src1 ! queue ! audioconvert ! audiofirfilter name=filter2 ! queue ! merger.");
//	sprintf (launch_string, "filesrc location=introduction.mp3 ! mad ! audioconvert ! deinterleave name=splitter interleave name=merger ! audioconvert ! autoaudiosink \\ \n splitter.src0 ! queue ! audioconvert ! queue ! merger. \\ \n splitter.src1 ! queue ! audioconvert ! queue ! merger.");

	gst_init (&argc, &argv);
	GError *error = NULL;
	pipeline = gst_parse_launch (launch_string, &error);
	gst_element_abort_state(pipeline);
	if (error)
	{
		g_print( "Error : parsing input pipeline : %s\n", error->message);
		g_error_free (error);
	}

	//g_print(launch_string);

	load_filters();

	if (pipeline) filter1 = gst_bin_get_by_name (GST_BIN (pipeline), "filter1");
	if (pipeline) filter2 = gst_bin_get_by_name (GST_BIN (pipeline), "filter2");

	if (filter1) g_object_set (G_OBJECT (filter1), "kernel", va_right[0], NULL);
	if (filter2) g_object_set (G_OBJECT (filter2), "kernel", va_left[0], NULL);

//	g_value_array_free (*va_right);
//	g_value_array_free (*va_left);

	gst_element_set_state (pipeline, GST_STATE_PLAYING);

	GstBus *bus = NULL;
	GstMessage *msg;

	bus = gst_pipeline_get_bus ((GstPipeline *)pipeline);
	do
	{
		msg = gst_bus_pop_filtered (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR);//, -1);
		if (msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS)
			g_print("\nEOS Message\n");
	}
	while(!(msg && GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS));

	free(va_right);
	free(va_left);

	return 0;
}
