#include <stdio.h>
#include <math.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include "graindialog.h"

static void minspeed_callback(GtkWidget* minspeedspin, gpointer data){
	looper_data_t* looperdata = (looper_data_t*)data;
	GtkWidget* maxspeedspin = 
		g_object_get_data (G_OBJECT(minspeedspin),"maxspeedspin");

	looperdata_lock(looperdata);
	looperdata_set_mingrainspeed(looperdata,
		(double)gtk_spin_button_get_value ((GtkSpinButton*)minspeedspin));
	looperdata_unlock(looperdata);
	if (looperdata->mingrainspeed > looperdata->maxgrainspeed){
		gtk_spin_button_set_value ((GtkSpinButton*)maxspeedspin,
		(gdouble)looperdata->mingrainspeed);
	}
}

static void maxspeed_callback(GtkWidget* maxspeedspin, gpointer data){
        looper_data_t* looperdata = (looper_data_t*)data;
        GtkWidget* minspeedspin =
                g_object_get_data (G_OBJECT(maxspeedspin),"minspeedspin");

        looperdata_lock(looperdata);
	looperdata_set_maxgrainspeed(looperdata,
                (double)gtk_spin_button_get_value ((GtkSpinButton*)maxspeedspin));
        looperdata_unlock(looperdata);
        if (looperdata->maxgrainspeed < looperdata->mingrainspeed){
                gtk_spin_button_set_value ((GtkSpinButton*)minspeedspin,
                (gdouble)looperdata->maxgrainspeed);
        }
}

static void minlength_callback(GtkWidget* minlengthspin, gpointer data){
        looper_data_t* looperdata = (looper_data_t*)data;
        GtkWidget* maxlengthspin =
                g_object_get_data (G_OBJECT(minlengthspin),"maxlengthspin");

        looperdata_lock(looperdata);
        looperdata_set_mingrainlength(looperdata,
                (long)gtk_spin_button_get_value ((GtkSpinButton*)minlengthspin));
        looperdata_unlock(looperdata);
        gtk_spin_button_set_value ((GtkSpinButton*)maxlengthspin,
                (gdouble)looperdata_get_maxgrainlength(looperdata));
}

static void maxlength_callback(GtkWidget* maxlengthspin, gpointer data){
        looper_data_t* looperdata = (looper_data_t*)data;
        GtkWidget* minlengthspin =
                g_object_get_data (G_OBJECT(maxlengthspin),"minlengthspin");

        looperdata_lock(looperdata);
        looperdata_set_maxgrainlength(looperdata,
                (long)gtk_spin_button_get_value ((GtkSpinButton*)maxlengthspin));
        looperdata_unlock(looperdata);
        gtk_spin_button_set_value ((GtkSpinButton*)minlengthspin,
                (gdouble)looperdata_get_mingrainlength(looperdata));
}

static void channelspin_callback(GtkWidget* channelspin, gpointer data){
	looper_data_t* looperdata = (looper_data_t*)data;
	looperdata_lock(looperdata);
		looperdata_set_midichannel(looperdata,
			(int)gtk_spin_button_get_value ((GtkSpinButton*)channelspin));
	looperdata_unlock(looperdata);
}

static void grainpitch_nomidi_callback(GtkToggleButton* modeselect, gpointer data){
	looper_data_t* looperdata = (looper_data_t*)data;

	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){
		looperdata_lock(looperdata);
		looperdata_set_grainpitchmode(looperdata,GRAINPITCH_RANGE);
		looperdata_unlock(looperdata);
	}
}


static void grainpitch_auto_callback(GtkWidget* modeselect, gpointer data){
        looper_data_t* looperdata = (looper_data_t*)data;

        if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){
                looperdata_lock(looperdata);
                looperdata_set_grainpitchmode(looperdata,GRAINPITCH_AUTO);
                looperdata_unlock(looperdata);
        }
}
static void grainpitch_midi_callback(GtkWidget* modeselect, gpointer data){
        looper_data_t* looperdata = (looper_data_t*)data;

        if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){
                looperdata_lock(looperdata);
                looperdata_set_grainpitchmode(looperdata,GRAINPITCH_CHORD);
                looperdata_unlock(looperdata);
        }
}


void graindialog_new(GtkWidget* parent, looper_data_t* data, int id){
	GtkAdjustment 	*adj;
	GtkTooltips     *tooltips;
        GtkWidget       *dialog;
        GtkWidget       *minspeedlabel;
        GtkWidget       *maxspeedlabel;
        GtkWidget       *minlengthlabel;
        GtkWidget       *maxlengthlabel;
        /*GtkWidget       *envelopelabel;*/
	GtkWidget	*speedtable;
	GtkWidget	*lengthtable;
	GtkWidget	*settingsbox;
	GtkWidget	*modebox;
        GtkWidget       *mainbox;               /* hbox */
        GtkWidget       *speedframe;
        GtkWidget       *lengthframe;
	GtkWidget	*modeframe;
	GtkWidget	*modeselect;
	GtkWidget	*channelspin;
	GSList 		*group;

/*      GtkWidget       *envelopeselector;   */ /* combobox   */
        GtkWidget       *minspeedspin;          /* spinbutton */
        GtkWidget       *maxspeedspin;         	/* spinbutton */
        GtkWidget       *minlengthspin;         /* spinbutton */
        GtkWidget       *maxlengthspin;        	/* spinbutton */
/*
	GtkWidget	*testcurve;
*/
	/*gint result;*/
	int actual_mode;

	tooltips = gtk_tooltips_new ();

	speedtable = gtk_table_new (2, 2, TRUE);
	lengthtable = gtk_table_new (2, 2, TRUE);
	
	minspeedlabel = gtk_label_new ("min");
	maxspeedlabel = gtk_label_new ("max");
	minlengthlabel = gtk_label_new ("min");
	gtk_tooltips_set_tip(tooltips,minlengthlabel,"minimum length for a grain",NULL);
	maxlengthlabel = gtk_label_new ("max");
	/*envelopelabel = gtk_label_new ("volume envelopes:");*/

/*
	testcurve = gtk_curve_new();
	gtk_curve_set_range ((GtkCurve*)testcurve,0., 1., 0., 1.);
	gtk_curve_set_gamma ((GtkCurve*)testcurve,3);
	gtk_widget_set_size_request (testcurve, 100, 100);
*/

	/* envelopeselector */

        adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_mingrainspeed(data),
				 -50.0, 50.0, .1, 1, 4);
        minspeedspin = gtk_spin_button_new (adj, 1, 4);
	adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_maxgrainspeed(data),
				 -50.0, 50.0, .1, 1, 4);
	maxspeedspin = gtk_spin_button_new (adj, 1, 4);

	adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_mingrainlength(data),
				10,44100,10,100,0);
	minlengthspin = gtk_spin_button_new (adj, 1, 0);
	adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_maxgrainlength(data),
				10,44100,10,100,0);
	maxlengthspin = gtk_spin_button_new (adj, 1, 0);

	g_object_set_data (G_OBJECT (minspeedspin),"maxspeedspin",maxspeedspin);
	g_object_set_data (G_OBJECT (maxspeedspin),"minspeedspin",minspeedspin);
	g_signal_connect (G_OBJECT (minspeedspin), "value_changed",
                        G_CALLBACK (minspeed_callback), (gpointer) data);
        g_signal_connect (G_OBJECT (maxspeedspin), "value_changed",
                        G_CALLBACK (maxspeed_callback), (gpointer) data);

	g_object_set_data (G_OBJECT (minlengthspin),"maxlengthspin",maxlengthspin);
	g_object_set_data (G_OBJECT (maxlengthspin),"minlengthspin",minlengthspin);
        g_signal_connect (G_OBJECT (minlengthspin), "value_changed",
                        G_CALLBACK (minlength_callback), (gpointer) data);
        g_signal_connect (G_OBJECT (maxlengthspin), "value_changed",
                        G_CALLBACK (maxlength_callback), (gpointer) data);
	
	gtk_tooltips_set_tip(tooltips,minspeedspin,"min. speed for a single grain",NULL);
	gtk_tooltips_set_tip(tooltips,maxspeedspin,"max. speed for a single grain",NULL);
	gtk_tooltips_set_tip(tooltips,minlengthspin,
		"min. length (in samples) for a single grain",NULL);
	gtk_tooltips_set_tip(tooltips,maxlengthspin,
		"max. length (in samples) for a single grain",NULL);

	speedframe = gtk_frame_new ("grain speed");
	gtk_frame_set_shadow_type((GtkFrame*)speedframe, GTK_SHADOW_ETCHED_IN);

	gtk_table_attach((GtkTable*)speedtable, minspeedlabel, 0, 1, 0, 1, GTK_FILL,GTK_FILL,3,3);
	gtk_table_attach((GtkTable*)speedtable, maxspeedlabel, 1, 2, 0, 1, GTK_FILL,GTK_FILL,3,3);
	gtk_table_attach((GtkTable*)speedtable, minspeedspin, 0, 1, 1, 2, GTK_FILL,GTK_FILL,3,3);
	gtk_table_attach((GtkTable*)speedtable, maxspeedspin, 1, 2, 1, 2, GTK_FILL,GTK_FILL,3,3);

	gtk_container_add (GTK_CONTAINER (speedframe),speedtable);

	lengthframe = gtk_frame_new ("grain length");
        gtk_frame_set_shadow_type((GtkFrame*)lengthframe, GTK_SHADOW_ETCHED_IN);

        gtk_table_attach((GtkTable*)lengthtable, minlengthlabel, 0, 1, 0, 1, GTK_FILL,GTK_FILL,3,3);
        gtk_table_attach((GtkTable*)lengthtable, maxlengthlabel, 1, 2, 0, 1, GTK_FILL,GTK_FILL,3,3);
        gtk_table_attach((GtkTable*)lengthtable, minlengthspin, 0, 1, 1, 2, GTK_FILL,GTK_FILL,3,3);
        gtk_table_attach((GtkTable*)lengthtable, maxlengthspin, 1, 2, 1, 2, GTK_FILL,GTK_FILL,3,3);

        gtk_container_add (GTK_CONTAINER (lengthframe),lengthtable);


	settingsbox = gtk_hbox_new(FALSE,5);
	gtk_box_pack_start (GTK_BOX(settingsbox), speedframe, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX(settingsbox), lengthframe, FALSE, FALSE, 0);	


	/* the midi mode selctor (radiobuttons): */

	actual_mode = looperdata_get_grainpitchmode(data);

	modebox = gtk_hbox_new(FALSE,5);

        adj = (GtkAdjustment *) gtk_adjustment_new ((gdouble)looperdata_get_midichannel(data),
                                0,16,1,1,1);
        channelspin = gtk_spin_button_new (adj, 1, 0);
	gtk_tooltips_set_tip(tooltips, channelspin,"midi channel filter (0 = all)",NULL);

        g_signal_connect (G_OBJECT (channelspin), "value_changed",
                        G_CALLBACK (channelspin_callback), (gpointer) data);
	gtk_box_pack_start (GTK_BOX (modebox), channelspin, TRUE, TRUE, 0);
	gtk_widget_show (channelspin);

	modeselect = gtk_radio_button_new_with_label (NULL, "no midi");
    	gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0);
	if (actual_mode == GRAINPITCH_RANGE)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE);
        else
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE);
	g_signal_connect (G_OBJECT (modeselect), "toggled",
                G_CALLBACK (grainpitch_nomidi_callback), data);
    	gtk_widget_show (modeselect);
	
	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (modeselect));
	modeselect = gtk_radio_button_new_with_label (group, "automatic");
	if (actual_mode == GRAINPITCH_AUTO)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE);
        else
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE);
	g_signal_connect (G_OBJECT (modeselect), "toggled",
		G_CALLBACK (grainpitch_auto_callback), data);

	gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0);
        gtk_widget_show (modeselect);

	modeselect = gtk_radio_button_new_with_label_from_widget (
			GTK_RADIO_BUTTON (modeselect), "just midi");
	if (actual_mode == GRAINPITCH_CHORD)
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE);
	else
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE);
	g_signal_connect (G_OBJECT (modeselect), "toggled",
                G_CALLBACK (grainpitch_midi_callback), data);

        gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0);
        gtk_widget_show (modeselect);

	modeframe = gtk_frame_new ("grain midi mode"); 
        gtk_frame_set_shadow_type((GtkFrame*)modeframe, GTK_SHADOW_ETCHED_IN);
	gtk_container_add (GTK_CONTAINER (modeframe), modebox);


	/* the main layout box: */
	mainbox = gtk_vbox_new (FALSE,5);
	gtk_box_pack_start (GTK_BOX(mainbox), settingsbox, FALSE, FALSE, 0);
	gtk_box_pack_start (GTK_BOX(mainbox), modeframe, FALSE, FALSE, 0);

	
	dialog = gtk_dialog_new_with_buttons ("settings for granular player",
                        (GtkWindow*)parent,
                        /*GTK_DIALOG_MODAL |*/ GTK_DIALOG_DESTROY_WITH_PARENT,
                        GTK_STOCK_OK,
                        GTK_RESPONSE_ACCEPT,
                        NULL);

	gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),mainbox);
/*
	gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),testcurve);
*/

	gtk_widget_show_all (dialog);

	/*result = */ gtk_dialog_run (GTK_DIALOG (dialog));
/*
	switch (result){
                case GTK_RESPONSE_ACCEPT:
			printf ("dialog done\n");
                        break;
                default:
			printf ("dialog cancelled\n");
                        break;
        }
*/
        gtk_widget_destroy (dialog);
}

