#include "ls_gtk.h"

int PerfLevels;
struct GTK_Widgets gtk;
struct PERF_Cur *PerfCur;

struct PERF_Ranges PerfRanges;
ADLODParameters PerfParams;
ADLODPerformanceLevels *PLevels;
//ADLPMActivity
GdkColor color;
//GdkColor color_red;
//GdkColor color_green;
//GdkColor color_blue;


//typedef struct {
//  guint32 pixel;
//  guint16 red;
//  guint16 green;
//  guint16 blue;
//} GdkColor;

char Perf_Alloc(void){
	int num1 = 0;
	int ret_val = LSADL_OD5_ODParameters_Get(iAdapterIndex, &PerfParams);
	if(ret_val != ADL_OK){
		printf("LSADL_OD5_ODParameters_Get(\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		return FALSE;
	}
	/*
	color_red.red     = 255;
	color_red.green   = 5;
	color_red.blue    = 5;
	color_green.red   = 5;
	color_green.green = 255;
	color_green.blue  = 5;
	color_blue.red    = 5;
	color_blue.green  = 5;
	color_blue.blue   = 255;
	gdk_color_parse("red", &color_red);
	gdk_color_parse("green", &color_green);
	gdk_color_parse("blue", &color_blue);
	*/
	PerfLevels            = PerfParams.iNumberOfPerformanceLevels;
	PerfRanges.gpu_min    = PerfParams.sEngineClock.iMin;
	PerfRanges.gpu_max    = PerfParams.sEngineClock.iMax;
	PerfRanges.gpu_step   = 1;
	//PerfRanges.gpu_step   = PerfParams.sEngineClock.iStep;

	PerfRanges.mem_min    = PerfParams.sMemoryClock.iMin;
	PerfRanges.mem_max    = PerfParams.sMemoryClock.iMax;
	PerfRanges.mem_step   = 1;
	//PerfRanges.mem_step   = PerfParams.sMemoryClock.iStep;

	PerfRanges.vddc_min   = PerfParams.sVddc.iMin;
	PerfRanges.vddc_max   = PerfParams.sVddc.iMax;
	PerfRanges.vddc_step  = PerfParams.sVddc.iStep;
	
	PerfRanges.gpu_min    /= 100;
	PerfRanges.gpu_max    /= 100;
	//PerfRanges.gpu_step   /= 100;
	PerfRanges.mem_min    /= 100;
	PerfRanges.mem_max    /= 100;
	//PerfRanges.mem_step   /= 100;
	PerfRanges.vddc_min   /= 1000;
	PerfRanges.vddc_max   /= 1000;
	PerfRanges.vddc_step  /= 1000;


	num1 = sizeof(ADLODPerformanceLevels)+sizeof(ADLODPerformanceLevel)*(PerfLevels-1);
	PLevels = (ADLODPerformanceLevels *)malloc(num1);
	if(PLevels == NULL){
		return FALSE;
	}
	PLevels->iSize = num1;
	ret_val = LSADL_OD5_ODPerformanceLevels_Get(iAdapterIndex, 1, PLevels);
	if(ret_val != ADL_OK){
		printf("LSADL_OD5_ODPerformanceLevels_Get(\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		return FALSE;
	}

	//allocate memory
	PerfCur           = (struct PERF_Cur *)malloc(sizeof(struct PERF_Cur)*PerfLevels);
	if(PerfCur == NULL){
		free(PLevels);
		return FALSE;
	}

	for(num1=0; num1<PerfLevels; num1++){
		//printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iEngineClock);
		//printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iMemoryClock);
		//printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iVddc);
		PerfCur[num1].id   = num1;
		PerfCur[num1].gpu  = PLevels->aLevels[num1].iEngineClock;
		PerfCur[num1].mem  = PLevels->aLevels[num1].iMemoryClock;
		PerfCur[num1].vddc = PLevels->aLevels[num1].iVddc;
		PerfCur[num1].gpu /= 100;
		PerfCur[num1].mem /= 100;
		PerfCur[num1].vddc /= 1000;
		//printf("%lf %lf %lf\n", PerfCur[num1].gpu, PerfCur[num1].mem, PerfCur[num1].vddc);
	}
	return TRUE;
}

char Perf_Dealloc(void){
    free(PerfCur);
	free(PLevels);

	return TRUE;
}

static void on_destroy(GtkWidget *widget, gpointer mw){
	gtk_widget_destroy(mw);
}

void *Refresh_Func(void *empty){
	char value[16];
	int ret_val = 0;
	int num1 = 0;
	gdouble dtmp = 0;
	ADLPMActivity current;

	while(No_Exit == 1){
		sleep(2);
//		for(num1=0; num1<PerfLevels; num1++){
//			printf("%d: %lf %lf %lf\n", num1, (double)(PerfCur[num1].gpu), (double)(PerfCur[num1].mem), (double)(PerfCur[num1].vddc));
//			gtk_adjustment_set_value(((struct PERF_Cur )PerfCur[num1]).gpu_adj, PerfCur[num1].gpu);
//			gtk_adjustment_set_value(((struct PERF_Cur )PerfCur[num1]).mem_adj, PerfCur[num1].mem);
//			gtk_adjustment_set_value(((struct PERF_Cur )PerfCur[num1]).vddc_adj, PerfCur[num1].vddc);

			//gtk_spin_button_set_value(GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).gpu_b), PerfCur[num1].gpu);
		//	gtk_spin_button_set_value(GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).mem_b), PerfCur[num1].mem);
		//	gtk_spin_button_set_value(GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).vddc_b), PerfCur[num1].vddc);
//(uint32_t)gtk_spin_button_get_value_as_int( (GtkSpinButton *)(((struct GTK_Widgets *)data)->gpu_button) );

//gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).gpu_b), ((struct PERF_Cur )PerfCur[num1]).gpu_adj);
//gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).mem_b), ((struct PERF_Cur )PerfCur[num1]).mem_adj);
//gtk_spin_button_set_adjustment( GTK_SPIN_BUTTON(((struct PERF_Cur )PerfCur[num1]).vddc_b), ((struct PERF_Cur )PerfCur[num1]).vddc_adj);

//gtk_spin_button_set_value( GtkSpinButton *spin_button,
//                                gfloat         value );


//			gtk_widget_show( GTK_WIDGET(((struct PERF_Cur )PerfCur[num1]).gpu_b) );
//			gtk_widget_show( GTK_WIDGET(((struct PERF_Cur )PerfCur[num1]).mem_b) );
//			gtk_widget_show( GTK_WIDGET(((struct PERF_Cur )PerfCur[num1]).vddc_b) );
//		}
		//printf("here !\n");
		//query temps

		ret_val = LSADL_OD5_CurrentActivity_Get(iAdapterIndex, &current);
		if(ret_val != ADL_OK){
			printf("Cannot get the number of od5 power state!\n");
			Print_Code(ret_val);
			printf("Exiting!\n");
			No_Exit = 0;
			break;
		}

		ret_val = current.iCurrentPerformanceLevel;
		//PerfCur[ret_val].table_labels
		for(num1=0; num1<PerfLevels; num1++){
			if(num1 == ret_val){
				(void)sprintf(value, "-->%d", ret_val);
			}else{
				(void)sprintf(value, "%d", num1);
			}
			gtk_label_set_text((GtkLabel *)PerfCur[num1].table_labels, (const gchar *)value);
			gtk_widget_show(PerfCur[num1].table_labels);
		}
		ret_val = LSADL_OD5_Temperature_Get(iAdapterIndex, 0, &iTemperature);
		if(ret_val != ADL_OK){
			printf("Cannot get the number of od5 temperature!\n");
			Print_Code(ret_val);
			printf("Exiting!\n");
			No_Exit = 0;
			break;
		}
		dtmp = (double)iTemperature.iTemperature/1000;
		(void)sprintf(value, "Temp: %.02lf", dtmp);
		gtk_label_set_text((GtkLabel *)gtk.table_labels[5], (const gchar *)value);
		//update labels

/*
		if(dtmp > 40){
			gdk_color_parse("red", &color);
			gtk_widget_modify_fg(((struct GTK_Widgets) gtk).table_labels[5], GTK_STATE_NORMAL, &color);
		}else{
			gdk_color_parse("green", &color);
			gtk_widget_modify_fg(((struct GTK_Widgets) gtk).table_labels[5], GTK_STATE_NORMAL, &color);
		}
*/
		//refresh the labels
		gtk_widget_show(((struct GTK_Widgets) gtk).table_labels[5]);
		//gtk_widget_show_all(((struct GTK_Widgets)gtk).main_win);
	}
	pthread_exit(NULL);
}

void *GTK_Func(void *empty){
	//uint32_t num1 = 0;
	//struct GTK_Widgets gtk;
	int ret_val = 0;
	int num1 = 0;
	/*
	ADLODParameters lpOdParams;
	ADLODPerformanceLevels *lpOdPerfLevels;
	gdouble mem_min = 0;
	gdouble mem_max = 0;
	gdouble mem_step = 0;
	gdouble mem_cur = 0;
	gdouble gpu_min = 0;
	gdouble gpu_max = 0;
	gdouble gpu_step = 0;
	gdouble gpu_cur = 0;
	gdouble vddc_min = 0;
	gdouble vddc_max = 0;
	gdouble vddc_step = 0;
	gdouble vddc_cur = 0;
	*/
	char tmp[10];
	gdouble temp_num = 0;
	//struct PERF_Cur *PerfCur;
	//ADLODParameterRange gpu_range;
	//ADLODParameterRange mem_range;
	//ADLODParameterRange vddc_range;
	gtk.main_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_set_border_width(GTK_CONTAINER(gtk.main_win), 2);
	gtk_window_set_default_size(GTK_WINDOW(gtk.main_win), 800, 600);
	gtk_window_set_title(GTK_WINDOW(gtk.main_win), "lsadl v0.0.1");
	gtk.main_vbox = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(gtk.main_win), gtk.main_vbox);
	gtk.main_menubar = gtk_menu_bar_new();
	gtk.main_filemenu = gtk_menu_new();
	gtk.main_file = gtk_menu_item_new_with_label("File");
	gtk.main_results = gtk_menu_item_new_with_label("API Results");
	gtk.main_quit = gtk_menu_item_new_with_label("Quit");
	
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk.main_file), gtk.main_filemenu);
	gtk_menu_shell_append(GTK_MENU_SHELL(gtk.main_filemenu), gtk.main_results);
	gtk_menu_shell_append(GTK_MENU_SHELL(gtk.main_filemenu), gtk.main_quit);
	gtk_menu_shell_append(GTK_MENU_SHELL(gtk.main_menubar), gtk.main_file);


	gtk_box_pack_start(GTK_BOX(gtk.main_vbox), gtk.main_menubar, FALSE, FALSE, 3);

	//get number of perflevels
	//LSADL_OD5_ODPerformanceLevels_Get(iAdapterIndex, 1, ADLODPerformanceLevels *lpOdPerformanceLevels)
	/*
	ret_val = LSADL_OD5_ODParameters_Get(iAdapterIndex, &lpOdParams);
	if(ret_val != ADL_OK){
		printf("LSADL_OD5_ODParameters_Get(\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		No_Exit = 0;
		// FIXME
	}
	PerfLevels = lpOdParams.iNumberOfPerformanceLevels;
	gpu_min    = lpOdParams.sEngineClock.iMin;
	gpu_max    = lpOdParams.sEngineClock.iMax;
	gpu_step   = lpOdParams.sEngineClock.iStep;
	mem_min    = lpOdParams.sMemoryClock.iMin;
	mem_max    = lpOdParams.sMemoryClock.iMax;
	mem_step   = lpOdParams.sMemoryClock.iStep;
	vddc_min   = lpOdParams.sVddc.iMin;
	vddc_max   = lpOdParams.sVddc.iMax;
	vddc_step  = lpOdParams.sVddc.iStep;


	//(void)memset((void *)&lpOdPerformanceLevels, '\0', sizeof(struct ADLODPerformanceLevels));
	//lpOdPerformanceLevels.aLevels = NULL;
	num1 = sizeof(ADLODPerformanceLevels)+sizeof(ADLODPerformanceLevel)*(PerfLevels-1);
	lpOdPerfLevels = (ADLODPerformanceLevels *)malloc(num1);
	lpOdPerfLevels->iSize = num1;
	//lpOdPerformanceLevels.aLevels = (struct ADLODPerformanceLevel *)malloc(sizeof(struct ADLODPerformanceLevel)*PerfLevels);
	//'struct ADLODPerformanceLevel[1]' from type 'void *'

	ret_val = LSADL_OD5_ODPerformanceLevels_Get(iAdapterIndex, 1, lpOdPerfLevels);
	if(ret_val != ADL_OK){
		printf("LSADL_OD5_ODPerformanceLevels_Get(\n");
		Print_Code(ret_val);
		printf("Exiting!\n");
		No_Exit = 0;
	}

	//allocate memory
	PerfCur           = (struct PERF_Cur *)malloc(sizeof(struct PERF_Cur)*PerfLevels);
	gtk.apply_button  = (GtkWidget **)malloc(sizeof(GtkWidget *)*PerfLevels);

	gtk.gpu_adj       = (GtkAdjustment **)malloc(sizeof(GtkAdjustment *)*PerfLevels);
	gtk.mem_adj       = (GtkAdjustment **)malloc(sizeof(GtkAdjustment *)*PerfLevels);
	gtk.vddc_adj      = (GtkAdjustment **)malloc(sizeof(GtkAdjustment *)*PerfLevels);
	gtk.fan_adj       = (GtkAdjustment **)malloc(sizeof(GtkAdjustment *)*PerfLevels);

	gtk.mem_button    = (GtkWidget **)malloc(sizeof(GtkWidget *)*PerfLevels);
	gtk.gpu_button    = (GtkWidget **)malloc(sizeof(GtkWidget *)*PerfLevels);
	gtk.vddc_button   = (GtkWidget **)malloc(sizeof(GtkWidget *)*PerfLevels);
	gtk.fan_button    = (GtkWidget **)malloc(sizeof(GtkWidget *)*PerfLevels);

	gtk.table_labels  = (GtkWidget **)malloc(sizeof(GtkWidget *)*(PerfLevels+6));

//iSize = sizeof( ADLODPerformanceLevels ) + sizeof( ADLODPerformanceLevel ) * (ADLODParameters.iNumberOfPerformanceLevels - 1);
	//ret_val = LSADL_OD5_ODPerformanceLevels_Get(iAdapterIndex, 1, &lpOdPerformanceLevels);

	for(num1=0; num1<PerfLevels; num1++){
		printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iEngineClock);
		printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iMemoryClock);
		printf("%d: %d\n", num1, lpOdPerfLevels->aLevels[num1].iVddc);

		PerfCur[num1].gpu  = (lpOdPerfLevels->aLevels[num1]).iEngineClock;
		PerfCur[num1].mem  = (lpOdPerfLevels->aLevels[num1]).iMemoryClock;
		PerfCur[num1].vddc = (lpOdPerfLevels->aLevels[num1]).iVddc;
		PerfCur[num1].gpu /= 100;
		PerfCur[num1].mem /= 100;
		PerfCur[num1].vddc /= 1000;


		printf("%lf %lf %lf\n", PerfCur[num1].gpu, PerfCur[num1].mem, PerfCur[num1].vddc);
		

	}
	*/


//ADLODParameterRange 	sEngineClock
//ADLODParameterRange 	sMemoryClock
//ADLODParameterRange 	sVddc



	gtk.table = gtk_table_new(PerfLevels+2, 6, TRUE); //h, w

	gtk.table_labels[0] = gtk_label_new("PerfLevel");
	gtk.table_labels[1] = gtk_label_new("GPU");
	gtk.table_labels[2] = gtk_label_new("MEM");
	gtk.table_labels[3] = gtk_label_new("Vddc");
	gtk.table_labels[4] = gtk_label_new("empty");
	gtk.table_labels[5] = gtk_label_new("Temp: 0");
	gtk_table_attach(GTK_TABLE(gtk.table), gtk.table_labels[0],        0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
	gtk_table_attach(GTK_TABLE(gtk.table), gtk.table_labels[1],        1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
	gtk_table_attach(GTK_TABLE(gtk.table), gtk.table_labels[2],        2, 3, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
	gtk_table_attach(GTK_TABLE(gtk.table), gtk.table_labels[3],        3, 4, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
	gtk_table_attach(GTK_TABLE(gtk.table), gtk.table_labels[4],        4, 5, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
	for(num1=0; num1<PerfLevels; num1++){
		(void)sprintf(tmp, "%d", num1);
		//gtk.table_labels[6+num1] = gtk_label_new((const gchar *)tmp);
		PerfCur[num1].table_labels = gtk_label_new((const gchar *)tmp);
		temp_num = PerfCur[num1].gpu;
		PerfCur[num1].gpu_adj  = (GtkAdjustment *)gtk_adjustment_new(temp_num,   PerfRanges.gpu_min,  PerfRanges.gpu_max,  PerfRanges.gpu_step,  PerfRanges.gpu_step, 0.0);
		temp_num = PerfCur[num1].mem;
		PerfCur[num1].mem_adj  = (GtkAdjustment *)gtk_adjustment_new(temp_num,   PerfRanges.mem_min,  PerfRanges.mem_max,  PerfRanges.mem_step,  PerfRanges.mem_step, 0.0);
		temp_num = PerfCur[num1].vddc;
		PerfCur[num1].vddc_adj = (GtkAdjustment *)gtk_adjustment_new(temp_num,  PerfRanges.vddc_min, PerfRanges.vddc_max, PerfRanges.vddc_step, PerfRanges.vddc_step, 0.0);

		PerfCur[num1].gpu_b    = gtk_spin_button_new(PerfCur[num1].gpu_adj,  1, 3);
		PerfCur[num1].mem_b    = gtk_spin_button_new(PerfCur[num1].mem_adj,  1, 3);
		PerfCur[num1].vddc_b   = gtk_spin_button_new(PerfCur[num1].vddc_adj, 1, 3);
		//gtk_spin_button_set_digits(
		//gtk_spin_button_set_digits(
		//gtk_spin_button_set_digits(
		PerfCur[num1].apply_b  = gtk_button_new_with_label("Apply");
		gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(PerfCur[num1].table_labels),    0, 1, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
		gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(PerfCur[num1].gpu_b),      1, 2, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
		gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(PerfCur[num1].mem_b),      2, 3, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
		gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(PerfCur[num1].vddc_b),     3, 4, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
		gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(PerfCur[num1].apply_b),    6, 7, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);
		g_signal_connect(G_OBJECT(PerfCur[num1].apply_b), "clicked", G_CALLBACK(apply_cb), (gpointer)&(PerfCur[num1]));
	}

	//gtk.fixed1 = gtk_fixed_new();
	//gtk_fixed_put(GTK_FIXED(gtk.fixed1), gtk.table_labels[5], 0, 0);
	//gtk_widget_set_size_request(gtk.table_labels[5], 30, 30);
	//gtk_container_add (GTK_CONTAINER(window1), fixed1);

	//gdk_color_parse("green", &color);
	//gtk_widget_modify_fg(((struct GTK_Widgets) gtk).table_labels[5], GTK_STATE_NORMAL, &color);
	//gtk_widget_modify_bg(GTK_WIDGET(gtk.table_labels[5]), GTK_STATE_NORMAL, &color);

	gtk_table_attach(GTK_TABLE(gtk.table), GTK_WIDGET(((struct GTK_Widgets) gtk).table_labels[5]),        0, 1, 1+num1, 2+num1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);

	//gtk_box_pack_end(GTK_BOX(gtk.main_vbox), gtk.table, TRUE, TRUE, 3);


	gtk.scrolled_win = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gtk.scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(gtk.scrolled_win), gtk.table);


	gtk_box_pack_end(GTK_BOX(gtk.main_vbox), gtk.scrolled_win, TRUE, TRUE, 3);
	
	

	g_signal_connect(gtk.main_win, "destroy", G_CALLBACK(exit_cb), NULL);
	g_signal_connect(G_OBJECT(gtk.main_quit), "activate", G_CALLBACK(exit_cb), NULL);
	g_signal_connect(G_OBJECT(gtk.main_results), "activate", G_CALLBACK(API_Funcs_Found_Popup_cb), NULL);
	//"button-release-event"
	//g_signal_connect(G_OBJECT(gtk.apply_button), "clicked", G_CALLBACK(apply_cb), (gpointer)&gtk);
	gtk_widget_show_all(gtk.main_win);
	gtk_main();

	pthread_exit(NULL);
}




gboolean exit_cb(GtkWidget *widget, gpointer data){
	gtk_main_quit();
	No_Exit = 0;
	return TRUE;
}

gboolean apply_cb(GtkWidget *widget, gpointer data){
	gdouble gpu  = gtk_spin_button_get_value( (GtkSpinButton *)(((struct PERF_Cur *)data)->gpu_b) );
	gdouble mem  = gtk_spin_button_get_value( (GtkSpinButton *)(((struct PERF_Cur *)data)->mem_b) );
	gdouble vddc = gtk_spin_button_get_value( (GtkSpinButton *)(((struct PERF_Cur *)data)->vddc_b) );
	printf("requested: %.03lf %.03lf %.03lf\n", (double)gpu, (double)mem, (double)vddc);
	int ret_val = 0;

	int perf_id = (int)(((struct PERF_Cur *)data)->id);
	int gpu_bak  = PLevels->aLevels[perf_id].iEngineClock;
	int mem_bak  = PLevels->aLevels[perf_id].iMemoryClock;
	int vddc_bak = PLevels->aLevels[perf_id].iVddc;

	PLevels->aLevels[perf_id].iEngineClock = floor(gpu*100);
	PLevels->aLevels[perf_id].iMemoryClock = floor(mem*100);
	PLevels->aLevels[perf_id].iVddc        = floor(vddc*1000);

	printf("Attempting: %d %d %d\n", PLevels->aLevels[perf_id].iEngineClock, PLevels->aLevels[perf_id].iMemoryClock, PLevels->aLevels[perf_id].iVddc);

    ret_val = LSADL_OD5_ODPerformanceLevels_Set(iAdapterIndex, PLevels);
    if(ret_val != ADL_OK){
        printf("LSADL_OD5_ODPerformanceLevels_Set(\n");
        Print_Code(ret_val);
        printf("Failed!\n");
		//should just set defaults instead !! FIXME:
		PLevels->aLevels[perf_id].iEngineClock = gpu_bak;
		PLevels->aLevels[perf_id].iMemoryClock = mem_bak;
		PLevels->aLevels[perf_id].iVddc        = vddc_bak;
        return FALSE;
    }

		PerfCur[perf_id].gpu  = PLevels->aLevels[perf_id].iEngineClock;
		PerfCur[perf_id].mem  = PLevels->aLevels[perf_id].iMemoryClock;
		PerfCur[perf_id].vddc = PLevels->aLevels[perf_id].iVddc;
		PerfCur[perf_id].gpu /= 100;
		PerfCur[perf_id].mem /= 100;
		PerfCur[perf_id].vddc /= 1000;
	printf("Success!\n");

	//uint32_t s_size = strlen("nvidia-settings -a GPU2DClockFreqs=1000,1000")+1;
	//char *setting = malloc(sizeof(char)*s_size);
	//(void)memset(setting, '\0', s_size);
	//(void)sprintf(setting, "GPUOverclockingState=1");
	//printf("%s\n", setting);

	//system("

	//(void)sprintf(setting, "nvidia-settings -a GPU2DClockFreqs=%u,%u", gpu, mem);
	//printf("%s\n", setting);
	//system("nvidia-settings -a GPUOverclockingState=1");
	//system(setting);
	gtk_widget_show_all( ((struct GTK_Widgets)gtk).main_win );
	//printf("set:: GPU: %u MEM: %u\n", gpu, mem);
//	gtk_widget_show_all(((struct GTK_Widgets *)data)->main_win);
	//nvidia-settings -a GPUOverclockingState=1
	//nvidia-settings -a GPU2DClockFreqs=200,800
	//free(setting);

	return TRUE;
}

gboolean API_Funcs_Found_Popup_cb(GtkWidget *widget, gpointer data){
	int num1 = 0;
    GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_container_set_border_width(GTK_CONTAINER(win), 2);
    gtk_window_set_default_size(GTK_WINDOW(win), 600, 400);
    gtk_window_set_title(GTK_WINDOW(win), "API Status");
    GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(win), vbox);
    //player  type  min_dice_will_roll  min_score_will_keep
    GtkWidget *top_table = gtk_table_new(LSADL_FUNCS, 3, TRUE);
    //ng.top_table = gtk_table_new(4, gs.Num_Players+2, TRUE);
	GtkWidget *top_table_labels[3];
    top_table_labels[0] = gtk_label_new("Function:");
    top_table_labels[1] = gtk_label_new("Status:");
    top_table_labels[2] = gtk_label_new("Note:");
    //top_table_labels[3] = gtk_label_new("Min score will keep");
	GtkWidget *all_labels[LSADL_FUNCS*3];

    gtk_table_attach(GTK_TABLE(top_table), top_table_labels[0],  0, 1, 0, 1, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 5);
    gtk_table_attach(GTK_TABLE(top_table), top_table_labels[1],  1, 2, 0, 1, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 5);
    gtk_table_attach(GTK_TABLE(top_table), top_table_labels[2],  2, 3, 0, 1, GTK_EXPAND|GTK_FILL, GTK_EXPAND|GTK_FILL, 5, 5);
    //gtk_table_attach(GTK_TABLE(top_table), top_table_labels[3],  3, 4, 0, 1, GTK_EXPAND|GTK_FILL, 0, GTK_EXPAND|GTK_FILL, 0);

	for(num1=0; num1<LSADL_FUNCS; num1+=3){
		all_labels[num1] = gtk_label_new((const gchar *)ADL_Func_Names[num1]);
		if(ADL_Func_Enabled[num1] == 1)
			all_labels[num1+1] = gtk_label_new((const gchar *)"Enabled");
		else
			all_labels[num1+1] = gtk_label_new((const gchar *)"Disabled");
		if(ADL_Func_Notes[num1] == FUNC_FOUND_IN_API)
			all_labels[num1+2] = gtk_label_new((const gchar *)"Found in API");
		else if(ADL_Func_Notes[num1] == FUNC_MISSING_FROM_API)
			all_labels[num1+2] = gtk_label_new((const gchar *)"Missing From API");
		else
			all_labels[num1+2] = gtk_label_new((const gchar *)"Disabled by LSADL");
		gtk_table_attach(GTK_TABLE(top_table), all_labels[num1],  0, 1, num1+1, num1+2, GTK_SHRINK, GTK_SHRINK, 5, 5);
		gtk_table_attach(GTK_TABLE(top_table), all_labels[num1+1],  1, 2, num1+1, num1+2, GTK_SHRINK, GTK_SHRINK, 5, 5);
		gtk_table_attach(GTK_TABLE(top_table), all_labels[num1+2],  2, 3, num1+1, num1+2, GTK_SHRINK, GTK_SHRINK, 5, 5);
	}
	//bottom_table = gtk_table_new(4, 5, TRUE);
	GtkWidget *close_button = gtk_button_new_with_label("Close");
	
    GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), top_table);
    gtk_box_pack_start(GTK_BOX(vbox), scrolled_win, TRUE, TRUE, 3);
    gtk_box_pack_end(GTK_BOX(vbox), close_button, FALSE, FALSE, 3);
	g_signal_connect(win, "destroy", G_CALLBACK(on_destroy), (gpointer)(win));
	g_signal_connect(G_OBJECT(close_button), "clicked", G_CALLBACK(on_destroy), (gpointer)(win));
	gtk_widget_show_all(win);

	return TRUE;
}