int effect_update(struct razer_fx_render_node *render)
{
	float percentage = daemon_get_parameter_float(daemon_effect_get_parameter_by_index(render->effect,0));
	int x,y;
	struct razer_rgb col;
	#ifdef USE_DEBUGGING
		printf(" (Bar.%d ## %%:%f)",render->id,percentage);
	#endif

	int xmax = (int)((21.0f / 100.0f) * percentage);
	for(x=0;x<render->device->columns_num;x++)
		for(y=0;y<render->device->rows_num;y++)
		{
			float dist = 0.0f;
			if(x-xmax <= 0)
				dist = 1.0f;
			else
			{
				dist = (21.0f / (x-xmax))/21.0f;
			}
			rgb_from_hue(dist,0.3f,0.0f,&col);
			rgb_mix_into(&render->output_frame->rows[y]->column[x],&render->input_frame->rows[y]->column[x],&col,render->opacity);//*render->opacity  //&render->second_input_frame->rows[y]->column[x]
			render->output_frame->update_mask |= 1<<y;
		}
	return(1);
}
int effect_transition_mouse_event_handler(struct razer_fx_render_node *render,struct razer_chroma_event *event)
{
	struct razer_pos_range *range = daemon_get_parameter_pos_range(daemon_effect_get_parameter_by_index(render->effect,0));
	int dir = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1));
	struct razer_pos *pos = daemon_get_parameter_pos(daemon_effect_get_parameter_by_index(render->effect,2));
	float opacity = 0.0f;
	if(event->type == RAZER_CHROMA_EVENT_TYPE_MOUSE && event->sub_type == RAZER_CHROMA_EVENT_SUBTYPE_MOUSE_X_AXIS_MOVEMENT)
	{
		int new_x = event->value + pos->x;
		if(new_x <= range->max->x && new_x >= range->min->x)
			pos->x = new_x;
		//#ifdef USE_DEBUGGING
		//	printf(" (Compute::Mouse Trans.%d ## pos:%d,%d,dir:%d,opacity:%f)",render->id,pos->x,pos->y,dir,opacity);
		//#endif
	}

	if(event->type == RAZER_CHROMA_EVENT_TYPE_MOUSE && event->sub_type == RAZER_CHROMA_EVENT_SUBTYPE_MOUSE_Y_AXIS_MOVEMENT)
	{
		int new_y = event->value + pos->y;
		if(new_y <= range->max->y && new_y >= range->min->y)
			pos->y = new_y;

		//#ifdef USE_DEBUGGING
		//	printf(" (Compute::Mouse Trans.%d ## pos:%d,%d,dir:%d,opacity:%f)",render->id,pos->x,pos->y,dir,opacity);
		//#endif
	}

	if(dir == 0)
		opacity = (float)pos->y / (float)range->max->y;
	else
		opacity = (float)pos->x / (float)range->max->x;
	

	if(render->parent) //compute effects should only be added as sub so this should be always fine
		render->parent->opacity = opacity;
	//daemon_set_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1),dir);	
	//daemon_set_parameter_(daemon_effect_get_parameter_by_index(render->effect,1),dir);	
	return(1);
}
int effect_transition_update(struct razer_fx_render_node *render)
{
	int length_ms = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,0));
	int dir = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1));
	unsigned long start = render->start_ticks;
	unsigned long end = start + length_ms;
	unsigned long ticks_left = end - render->daemon->chroma->update_ms;
	float opacity = 0.0f;
	if(dir == 1)
		opacity = (float)ticks_left / (float)length_ms;
	else
		opacity = 1.0f - ((float)ticks_left / (float)length_ms);
	#ifdef USE_DEBUGGING
		printf(" (Compute::Transition.%d ## length_ms:%d,dir:%d,opacity:%f)",render->id,length_ms,dir,opacity);
	#endif
	if(end<render->daemon->chroma->update_ms)
	{
		if(dir == 1)
		{
			dir = -1;
			if(render->parent) //compute effects should only be added as sub so this should be always fine
				render->parent->opacity = 0.0f;
		}
		else
		{
			dir = 1;
			if(render->parent) //compute effects should only be added as sub so this should be always fine
				render->parent->opacity = 1.0f;
		}
		daemon_set_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1),dir);	
		return(0);
	}
	if(render->parent) //compute effects should only be added as sub so this should be always fine
		render->parent->opacity = opacity;
	daemon_set_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1),dir);	
	return(1);
}
int effect_reset(struct razer_fx_render_node *render)
{
	//reopen input file
	char *filename = daemon_get_parameter_string(daemon_effect_get_parameter_by_index(render->effect,0));
	if(effect_input_file)
	{
		close_wav(effect_input_file);
		effect_input_file = NULL;
	}
	effect_input_file =open_wav(filename);
	#ifdef USE_DEBUGGING
		printf("(fft) opened input wav file:%s,%x\n",filename);
	#endif		
	if(effect_input_file)
		return(1);
	else
		return(0);
}
int effect_update(struct razer_fx_render_node *render)
{
	float magnitude = daemon_get_parameter_float(daemon_effect_get_parameter_by_index(render->effect,1));
	int x,y;
	struct razer_rgb col;
	#ifdef USE_DEBUGGING
		printf(" (Fft.%d ## %%:%f)",render->id);
	#endif

	unsigned long samples_left=0;
	while((samples_left=wav_samples_left(effect_input_file)))
	{
		unsigned int sample = read_wav_stereo_sample(effect_input_file);
		short high = sample >> 16;
		short low = sample & 0xFFFF;
		//add sample to fft buffer
		effect_fft_in[effect_fft_samples_used][0] = (double)high * effect_fft_hamming_buffer[effect_fft_samples_used];///(double)32768;//* windowHanning(step++, N);
  		effect_fft_in[effect_fft_samples_used++][1] = 0.0f;
		//enough samples gathered?
		if(effect_fft_samples_used==effect_fft_samples)
  		{
  			printf("Computing fft, still %d samples left\n",samples_left);
			//compute fft
    		effect_fft_plan = fftw_plan_dft_1d(effect_fft_samples, effect_fft_in, effect_fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
    		fftw_execute(effect_fft_plan);
    		fftw_destroy_plan(effect_fft_plan);
    		effect_fft_samples_used = 0;
 		    double tmp_magnitude = sqrt(effect_fft_out[0][0]*effect_fft_out[0][0] + effect_fft_out[0][1]*effect_fft_out[0][1]);
		    tmp_magnitude = 10./log(10.) * log(tmp_magnitude + 1e-6);
    		printf("new fft mag db:%f\n",tmp_magnitude);
    		double sum = 0.0f;
    		for(int i=0;i<effect_fft_samples/2;i++)
    		{
	 		    double tmp_bin_magnitude = sqrt(effect_fft_out[i][0]*effect_fft_out[i][0] + effect_fft_out[i][1]*effect_fft_out[i][1]);
			    tmp_bin_magnitude = 10./log(10.) * log(tmp_bin_magnitude + 1e-6);
			    sum += tmp_bin_magnitude;
    		}
    		printf("sum:%f\n",sum/(effect_fft_samples/2));
    		magnitude = (float)tmp_magnitude - 50.0f;
    		break;
  		}
	}
	if(!samples_left)
	{
		#ifdef USE_DEBUGGING
			printf("no samples left to analyze, closing input file\n");
		#endif
		close_wav(effect_input_file);
		effect_input_file = NULL;
		return(0);
	}


	//set color to avg magnitude ,transformed to 0.0-1.0 space	

	//calculate hue from magnitude
	rgb_from_hue(magnitude/96,0.3f,0.0f,&col);

	for(x=0;x<22;x++)
		for(y=0;y<6;y++)
		{
			rgb_mix_into(&render->output_frame->rows[y].column[x],&render->input_frame->rows[y].column[x],&col,render->opacity);//*render->opacity  //&render->second_input_frame->rows[y].column[x]
			render->output_frame->update_mask |= 1<<y;
		}
	daemon_set_parameter_float(daemon_effect_get_parameter_by_index(render->effect,1),magnitude);	
	return(1);
}
int effect_random_col_update(struct razer_fx_render_node *render)
{
	int length_ms = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,0));
	int par_index = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,1));
	if(par_index == -1)
		return(0);
	int randomize_now = daemon_get_parameter_int(daemon_effect_get_parameter_by_index(render->effect,2));
	struct razer_rgb *dst_color = daemon_get_parameter_rgb(daemon_effect_get_parameter_by_index(render->effect,3));
	struct razer_rgb *src_color = daemon_get_parameter_rgb(daemon_effect_get_parameter_by_index(render->effect,4));
	if(randomize_now)
	{
		struct razer_rgb *org_color = NULL;
		if(render->parent) 
		{
			org_color = daemon_get_parameter_rgb(daemon_effect_get_parameter_by_index(render->parent->effect,par_index));
		}
		if(org_color)
		{
			src_color->r = org_color->r;
			src_color->g = org_color->g;
			src_color->b = org_color->b;
		}

		dst_color->r = random() % 256;
		dst_color->g = random() % 256;
		dst_color->b = random() % 256;
		daemon_set_parameter_rgb(daemon_effect_get_parameter_by_index(render->effect,3),dst_color);	
		daemon_set_parameter_rgb(daemon_effect_get_parameter_by_index(render->effect,4),src_color);	
		randomize_now = 0;
	}
	unsigned long start = render->start_ticks;
	unsigned long end = start + length_ms;
	unsigned long ticks_left = end - render->daemon->chroma->update_ms;
	float trans = 0.0f;
	trans = (float)ticks_left / (float)length_ms;
	if(end<render->daemon->chroma->update_ms)
	{
		//#ifdef USE_DEBUGGING
		//	printf("\n(Compute::RandomCol.%d ## finished)\n",render->id);
		//#endif
		daemon_set_parameter_rgb(daemon_effect_get_parameter_by_index(render->parent->effect,par_index),dst_color);	
		randomize_now = 1;
		daemon_set_parameter_int(daemon_effect_get_parameter_by_index(render->effect,2),randomize_now);	
		return(0);
	}
	else
	{
		#ifdef USE_DEBUGGING
			printf(" (Compute::RandomCol.%d ## length_ms:%d,trans_color:%d,%d,%d,trans:%f)",render->id,length_ms,dst_color->r,dst_color->g,dst_color->b,trans);
		#endif
		if(render->parent) 
		{
			struct razer_rgb trans_color;
			//trans_color.r=dst_color->r*trans;
			rgb_mix_into(&trans_color,dst_color,src_color,trans);
			daemon_set_parameter_rgb(daemon_effect_get_parameter_by_index(render->parent->effect,par_index),&trans_color);	
		}
	}


	daemon_set_parameter_int(daemon_effect_get_parameter_by_index(render->effect,2),randomize_now);	
	return(1);
}