/*****************************************************************************

        GRAOUMF TRACKER 2
        Author: Laurent de Soras, 1996-2016

--- Legal stuff ---

This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.

*****************************************************************************/



/*\\\ FICHIERS INCLUDE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

#include	<stdio.h>

#include	"base.h"
#include	"base_ct.h"
#include	"edstring.h"
#include	"EditString.h"
#include	"FxPreset.h"
#include	"gtracker.h"
#include	"intrface.h"
#include	"log.h"
#include	"PatEdMenuFx.h"
#include	"PatEdMenuFxDisto.h"
#include	"player.h"
#include	"resource.h"
#include	"rsc01.h"



/*\\\ CONSTANTES PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ CONSTANTES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ TYPES & STRUCTURES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ DEFINITION DES VARIABLES DE CLASSE PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ DEFINITION DES VARIABLES DE CLASSE PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*\\\ METHODES PUBLIQUES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/*==========================================================================*/
/*      Nom: check_ok                                                       */
/*      Description: Verifie l'intergrite de l'objet.                       */
/*      Retour: 0 si l'objet parait correct.                                */
/*==========================================================================*/

signed int	PatEdMenuFxDisto::check_ok (void) const
{
	if (this == NULL)
	{
		LOG_printf ("PatEdMenuFxDisto::check_ok: Error: \"this\" pointer is NULL.\n");
		return (-1);
	}

	return (0);
}



/*==========================================================================*/
/*      Nom: self_display                                                   */
/*      Description: Affiche "textuellement" le contenu courant de l'objet. */
/*==========================================================================*/

void	PatEdMenuFxDisto::self_display (void) const
{

	/*** A faire ***/

}



/*==========================================================================*/
/*      Nom: redraw                                                         */
/*      Description: Affiche la composante d'interface.                     */
/*==========================================================================*/

void	PatEdMenuFxDisto::redraw (void)
{
	RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN);

	refresh ();
}



/*==========================================================================*/
/*      Nom: refresh                                                        */
/*      Description: Rafraichit l'affichage des donnees.                    */
/*==========================================================================*/

void	PatEdMenuFxDisto::refresh (void)
{
	/* Teste si la piste sur laquelle on est est valide */
	if (   GTK_fx_real_time_mode_flag
	    && _pannel_ptr->get_track_nbr () >= GTK_nbr_tracks [Pattern_TYPE_FX])
	{
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX_VAL, "");
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX_VAL);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX_VAL, "");
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX_VAL);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX_VAL, "");
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX_VAL);
	}

	refresh_dynamic (true);
}



/*==========================================================================*/
/*      Nom: refresh_dynamic                                                */
/*      Description: Rafraichit l'affichage des donnees dynamiques.         */
/*        - force_flag: true indique qu'on doit forcer le rafraichissement. */
/*==========================================================================*/

void	PatEdMenuFxDisto::refresh_dynamic (bool force_flag)
{
	int		type;
	double	gain;
	double	threshold;
	double	attenuation;
	int		fader_pos;
	char		nbr6_0 [6+1];
	const FxPreset_DISTO	*param_ptr;

	static int	old_type = -1;
	static double	old_gain = -1.0;
	static double	old_threshold = -1.0;
	static double	old_attenuation = -1.0;
	static int	old_gain_pos = -1;
	static int	old_threshold_pos = -1;
	static int	old_attenuation_pos = -1;

	if (GTK_fx_real_time_mode_flag)
	{
		const Player &	player = Player::use_instance ();
		if (player.get_fx_preset (_pannel_ptr->get_track_nbr (), 0))
		{
			/* On s'en va si l'effet est indisponible */
			return;
		}
	}

	param_ptr = &FXP_get_parameters (0).disto;

	/* Type */
	type = param_ptr->type;
	if (   force_flag
	    || type != old_type)
	{
		old_type = type;
		switch (type)
		{
		case	FxPreset_DISTO_TYPE_BOOST:
			RSC_select_radio_button_display (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_BOOST,
			                                 RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_BOOST);
			break;
		case	FxPreset_DISTO_TYPE_PUNCH:
			RSC_select_radio_button_display (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_PUNCH,
			                                 RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_BOOST);
			break;
		}
	}

	/* Gain */
	gain = param_ptr->gain;
	if (   force_flag
	    || gain != old_gain)
	{
		old_gain = gain;

		/* Value */
		BASE_double_to_fix (nbr6_0, gain, 2, 3);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX_VAL);

		/* Fader */
		fader_pos = BASE_get_fader_pos (gain, 0.0, 60.0, 256, false);
		if (old_gain_pos != fader_pos || force_flag)
		{
			old_gain_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Threshold */
	threshold = param_ptr->threshold;
	if (   force_flag
	    || threshold != old_threshold)
	{
		old_threshold = threshold;

		/* Value */
		BASE_double_to_fix (nbr6_0, threshold, 2, 3);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX_VAL);

		/* Fader */
		fader_pos = BASE_get_fader_pos (threshold, 0.0, 60.0, 256, false);
		if (old_threshold_pos != fader_pos || force_flag)
		{
			old_threshold_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Attenuation */
	attenuation = param_ptr->sec_gain;
	if (   force_flag
	    || attenuation != old_attenuation)
	{
		old_attenuation = attenuation;

		/* Value */
		BASE_double_to_fix (nbr6_0, attenuation, 2, 3);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX_VAL);

		/* Fader */
		fader_pos = BASE_get_fader_pos (attenuation, 0.0, 60.0, 256, false);
		if (old_attenuation_pos != fader_pos || force_flag)
		{
			old_attenuation_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}
}



/*==========================================================================*/
/*      Nom: manage                                                         */
/*      Description: Gere la composante d'interface                         */
/*      Parametres en entree:                                               */
/*        - sel_object: objet detecte par le gestionnaire d'interface       */
/*        - sel_elder: aine de sel_object                                   */
/*==========================================================================*/

void	PatEdMenuFxDisto::manage (int sel_object, int sel_elder)
{
	FxPreset_EFFECT_CONF	conf;
	/* Mis a 1 pour indiquer que le preset doit etre change, 2 pour forcer
		egalement le redraw dynamique (valeur changee au clavier). */
	int		changed_state;
	long		auto_val;
	signed int	slider_pos;
	double	val_dbl;
	char		nbr15_0 [15+1];
	
	conf = FXP_get_parameters (0);
	changed_state = 0;
	auto_val = 0;

	switch (sel_object)
	{
	/* Boost */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_BOOST:
		conf.disto.type = FxPreset_DISTO_TYPE_BOOST;
		changed_state = 1;
		break;

	/* Punch */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_TYPE_PUNCH:
		conf.disto.type = FxPreset_DISTO_TYPE_PUNCH;
		changed_state = 1;
		break;

	/* Gain */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX:
		BASE_double_to_float (nbr15_0, conf.disto.gain, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.disto.gain = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Gain + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_U:
		conf.disto.gain += INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Gain - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_D:
		conf.disto.gain -= INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Gain fader */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_GAIN_GAIN_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.disto.gain = BASE_get_fader_val (slider_pos, 0.0, 60.0, 256, false);
		changed_state = 1;
		break;

	/* Threshold */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX:
		BASE_double_to_float (nbr15_0, conf.disto.threshold, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.disto.threshold = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Threshold + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_U:
		conf.disto.threshold += INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Threshold - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_D:
		conf.disto.threshold -= INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Threshold fader */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_HT_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.disto.threshold = BASE_get_fader_val (slider_pos, 0.0, 60.0, 256, false);
		changed_state = 1;
		break;

	/* Threshold */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX:
		BASE_double_to_float (nbr15_0, conf.disto.sec_gain, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.disto.sec_gain = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Threshold + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_U:
		conf.disto.sec_gain += INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Threshold - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_D:
		conf.disto.sec_gain -= INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Attenuation fader */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO_PUNCH_GA_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.disto.sec_gain = BASE_get_fader_val (slider_pos, 0.0, 60.0, 256, false);
		changed_state = 1;
		break;
	}

	/* Met a jour l'effet */
	if (changed_state != 0)
	{
		FXP_set_parameters (0, conf);
		if (GTK_fx_real_time_mode_flag)
		{
			Player &			player = Player::use_instance ();
			player.set_fx_preset (_pannel_ptr->get_track_nbr (), 0, auto_val);
			GTK_modified_flag = true;
		}
		refresh_dynamic (changed_state == 2);
	}
}



/*==========================================================================*/
/*      Nom: activate                                                       */
/*      Description: Active ou desactive le menu. Celui-ci n'est pas        */
/*                   reaffiche.                                             */
/*      Parametres en entree:                                               */
/*        - activated_flag: indique si le menu doit etre active ou          */
/*                          desactive.                                      */
/*==========================================================================*/

void	PatEdMenuFxDisto::activate (bool activated_flag)
{
	RSC_pos_flag (RSC_OBJ_MP_SUBM_FX_FXPAN_DISTO, RSC_ATTR_NOTDISP, ! activated_flag);
}



/*==========================================================================*/
/*      Nom: set_owner                                                      */
/*      Description: Associe l'objet courant a un objet PatEdMenuFx.        */
/*      Parametres en entree:                                               */
/*        - pannel_ptr: pointeur sur l'objet PatEdMenuFx qui possede cet    */
/*                      objet.                                              */
/*==========================================================================*/

void	PatEdMenuFxDisto::set_owner (PatEdMenuFx *pannel_ptr)
{
	_pannel_ptr = pannel_ptr;
}



/*\\\ METHODES PRIVEES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/



/****************************************************************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/



/*==========================================================================*/
/*      Nom:                                                                */
/*      Description:                                                        */
/*      Parametres en entree:                                               */
/*      Parametres en sortie:                                               */
/*      Parametres en entree/sortie:                                        */
/*      Retour:                                                             */
/*==========================================================================*/
