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

GRAOUMF TRACKER 2

Copyright (c) 1996 - 2002 Laurent de Soras

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

Contact the author : laurent@ohmforce.com
More information about this license : http://www.gnu.org/licenses/gpl.html

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



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

#include	<stdio.h>
#include	<stdlib.h>
#include	<math.h>

#include	"base.h"
#include	"base_ct.h"
#include	"edstring.h"
#include	"EditString.h"
#include	"filter.h"
#include	"gtracker.h"
#include	"intrface.h"
#include	"log.h"
#include	"PatEdMenuFx.h"
#include	"PatEdMenuFxResFilt.h"
#include	"player.h"
#include	"Popup.h"
#include	"resource.h"
#include	"rsc01.h"
#include	"WaveForm.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	PatEdMenuFxResFilt::check_ok (void) const
{
	if (this == NULL)
	{
		LOG_printf ("PatEdMenuFxResFilt::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	PatEdMenuFxResFilt::self_display (void) const
{

	/*** A faire ***/

}



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

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

	refresh ();
}



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

void	PatEdMenuFxResFilt::refresh (void)
{
	const char	*unit_0;

	unit_0 = INTR_time_unit_name_0_ptr [INTR_freq_unit];

	/* Unite de la frequence principale */
	RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_UNIT, unit_0);
	RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_UNIT);

	/* Unite de la frequence du LFO */
	RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_UNIT, unit_0);
	RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_UNIT);

	refresh_dynamic (true);
}



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

void	PatEdMenuFxResFilt::refresh_dynamic (bool force_flag)
{
	const FxPreset_RESFILT	*param_ptr;
	char		nbr6_0 [6+1];
	int		fader_pos;
	double	val;
	int		val_int;

	static int		old_type = -1;
	static int		old_order = -1;
	static double	old_main_freq = -1;
	static int		old_main_freq_pos = -1;
	static double	old_q = -1;
	static int		old_q_pos = -1;
	static int		old_lfo_flag = -1;
	static int		old_lfo_waveform = -1;
	static double	old_lfo_freq = -1;
	static int		old_lfo_freq_pos = -1;
	static double	old_lfo_depth = -1;
	static int		old_lfo_depth_pos = -1;
	static double	old_lfo_phase = -1;
	static int		old_lfo_phase_pos = -1;
	static int		old_mb_flag = -1;
	static double	old_mb_df = -1;
	static int		old_mb_df_pos = -1;
	static int		old_nbr_cells = -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).resfilt;

	/* Type de filtre */
	val_int = param_ptr->type;
	if (old_type != val_int || force_flag)
	{
		old_type = val_int;
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_TYPE_VAL,
		                FILT_biquad_name_0 [val_int]);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_TYPE_VAL);
	}

	/* Ordre de chaque cellule du filtre */
	val_int = param_ptr->nbr_biquads << 1;
	if (old_order != val_int || force_flag)
	{
		old_order = val_int;
		sprintf (nbr6_0, "%3d", val_int);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_BOX_VAL);
	}

	/* Frequence principale */
	val = param_ptr->freq;
	if (old_main_freq != val || force_flag)
	{
		old_main_freq = val;
		INTR_freq_2_string (nbr6_0, INTR_freq_unit, val, 6);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_VAL);

		fader_pos = BASE_get_fader_pos (val, 40.0, 16000.0, 128, true);
		if (old_main_freq_pos != fader_pos || force_flag)
		{
			old_main_freq_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Facteur Q */
	val = param_ptr->q;
	if (old_q != val || force_flag)
	{
		old_q = val;
		BASE_double_to_fix (nbr6_0, val, 3, 2);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_BOX_VAL);

		fader_pos = BASE_get_fader_pos (val, 0.01, 100.0, 128, true);
		if (old_q_pos != fader_pos || force_flag)
		{
			old_q_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* LFO actif */
	val_int = param_ptr->lfo_flag ? 1 : 0;
	if (old_lfo_flag != val_int || force_flag)
	{
		old_lfo_flag = val_int;
		RSC_select_object_display (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_ACTIVE_CB, val_int != 0);
	}

	/* Forme d'onde LFO */
	val_int = param_ptr->lfo_waveform;
	if (old_lfo_waveform != val_int || force_flag)
	{
		old_lfo_waveform = val_int;
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_WF_VAL,
		                WaveForm::name_0_ptr [val_int]);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_WF_VAL);
	}

	/* Frequence LFO */
	val = param_ptr->lfo_freq;
	if (old_lfo_freq != val || force_flag)
	{
		old_lfo_freq = val;
		INTR_freq_2_string (nbr6_0, INTR_freq_unit, val, 6);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_VAL);

		fader_pos = BASE_get_fader_pos (val, 0.01, 100, 128, true);
		if (old_lfo_freq_pos != fader_pos || force_flag)
		{
			old_lfo_freq_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Amplitude LFO */
	val = param_ptr->lfo_depth;
	if (old_lfo_depth != val || force_flag)
	{
		old_lfo_depth = val;
		BASE_double_to_fix (nbr6_0, val, 2, 3);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_BOX_VAL);

		fader_pos = BASE_get_fader_pos (val, 0.0, 24.0, 128, false);
		if (old_lfo_depth_pos != fader_pos || force_flag)
		{
			old_lfo_depth_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Phase LFO */
	val = param_ptr->lfo_phase;
	if (old_lfo_phase != val || force_flag)
	{
		old_lfo_phase = val;

		fader_pos = BASE_get_fader_pos (val, 0.0, 1.0, 128, false);
		if (old_lfo_phase_pos != fader_pos || force_flag)
		{
			old_lfo_phase_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_PHASE_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_PHASE_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Multiband mode actif */
	val_int = param_ptr->cell_flag ? 1 : 0;
	if (old_mb_flag != val_int || force_flag)
	{
		old_mb_flag = val_int;
		RSC_select_object_display (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_ACTIVE_CB, val_int != 0);
	}

	/* Delta F Multiband */
	val = param_ptr->cell_ratio;
	if (old_mb_df != val || force_flag)
	{
		old_mb_df = val;
		BASE_double_to_fix (nbr6_0, val, 2, 3);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_BOX_VAL);

		fader_pos = BASE_get_fader_pos (val, 0.0, 24.0, 128, false);
		if (old_mb_df_pos != fader_pos || force_flag)
		{
			old_mb_df_pos = fader_pos;
			RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_FADER);
			RSC_display_image (RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B), 0, 0, -1, -1,
			                   RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_FADER_PIC,
			                   fader_pos, 0, 255);
		}
	}

	/* Nombre de cellules */
	val_int = param_ptr->nbr_cells;
	if (old_nbr_cells != val_int || force_flag)
	{
		old_nbr_cells = val_int;
		sprintf (nbr6_0, "%3d", val_int);
		RSC_set_string (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_BOX_VAL, nbr6_0);
		RSC_display_object (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_BOX_VAL);
	}
}



/*==========================================================================*/
/*      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	PatEdMenuFxResFilt::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;
	int		cnt;
	Popup		popup_menu;
	signed long	code;
	signed int	line;
	signed int	slider_pos;
	double	val_dbl;
	long		auto_val;
	char		nbr15_0 [15+1];

	conf = FXP_get_parameters (0);
	changed_state = 0;
	auto_val = 0;

	switch (sel_object)
	{

	/* Type de filtre */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_TYPE:
		for (cnt = 0; cnt < FILT_NBR_BIQUAD_TYPES; cnt ++)
		{
			popup_menu.add_line (FILT_biquad_name_0 [cnt], cnt);
		}
		line = popup_menu.select_radio_by_code (conf.resfilt.type);
		code = popup_menu.manage (line);
		if (code >= 0)
		{
			conf.resfilt.type = (int) code;
			changed_state = 1;
		}
		break;

	/* Ordre */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_BOX:
		sprintf (nbr15_0, "%3d", conf.resfilt.nbr_biquads << 1);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_BOX_VAL,
		                      3, EditString_TYPE_DEC) == 0)
		{
			conf.resfilt.nbr_biquads = atoi (nbr15_0) >> 1;
			changed_state = 1;
		}
		break;

	/* Ordre + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_U:
		conf.resfilt.nbr_biquads += INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Ordre - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_ORDER_D:
		conf.resfilt.nbr_biquads -= INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Frequence */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX:
		INTR_set_freq_intr (INTR_CHGTYPE_KBD, 0,
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.freq);
		changed_state = 2;
		break;

	/* Unite de la frequence */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_UNIT:
		INTR_select_time_unit (INTR_freq_unit);
		refresh ();
		break;

	/* Frequence + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_U:
		INTR_set_freq_intr (INTR_CHGTYPE_REL, INTR_inc_speed [0] [RSC_mouse_key],
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.freq);
		changed_state = 1;
		break;

	/* Frequence - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_D:
		INTR_set_freq_intr (INTR_CHGTYPE_REL, -INTR_inc_speed [0] [RSC_mouse_key],
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.freq);
		changed_state = 1;
		break;

	/* Fader frequence */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_FREQ_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.freq = BASE_get_fader_val (slider_pos, 40.0, 16000.0, 128, true);
		changed_state = 1;
		break;

	/* Q */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_BOX:
		BASE_double_to_float (nbr15_0, conf.resfilt.q, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.resfilt.q = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Q + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_U:
		conf.resfilt.q *= exp (INTR_inc_speed [0] [RSC_mouse_key] * LN10 / 64);
		changed_state = 1;
		break;

	/* Q - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_D:
		conf.resfilt.q *= exp (-INTR_inc_speed [0] [RSC_mouse_key] * LN10 / 64);
		changed_state = 1;
		break;

	/* Fader Q */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MAIN_Q_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.q = BASE_get_fader_val (slider_pos, 0.01, 100.0, 128, true);
		changed_state = 1;
		break;

	/* LFO actif */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_ACTIVE_CB:
		conf.resfilt.lfo_flag = ! conf.resfilt.lfo_flag;
		changed_state = 1;
		break;

	/* Forme d'onde */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_WF:
		for (cnt = 0; cnt < WaveForm_NBR_BASE_FORMS; cnt ++)
		{
			popup_menu.add_line (WaveForm::name_0_ptr [cnt], cnt);
		}
		line = popup_menu.select_radio_by_code (conf.resfilt.lfo_waveform);
		code = popup_menu.manage (line);
		if (code >= 0)
		{
			conf.resfilt.lfo_waveform = (int) code;
			changed_state = 1;
		}
		break;

	/* Frequence du LFO */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX:
		INTR_set_freq_intr (INTR_CHGTYPE_KBD, 0,
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.lfo_freq);
		changed_state = 2;
		break;

	/* Unite de la frequence du LFO */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_UNIT:
		INTR_select_time_unit (INTR_freq_unit);
		refresh ();
		break;

	/* Frequence LFO + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_U:
		INTR_set_freq_intr (INTR_CHGTYPE_REL, INTR_inc_speed [0] [RSC_mouse_key],
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.lfo_freq);
		changed_state = 1;
		break;

	/* Frequence LFO - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_D:
		INTR_set_freq_intr (INTR_CHGTYPE_REL, -INTR_inc_speed [0] [RSC_mouse_key],
		                    RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_BOX_VAL,
		                    INTR_freq_unit, conf.resfilt.lfo_freq);
		changed_state = 1;
		break;

	/* Fader de la frequence du LFO */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_FREQ_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.lfo_freq = BASE_get_fader_val (slider_pos, 0.01, 100.0, 128, true);
		changed_state = 1;
		break;

	/* Profondeur du LFO */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_BOX:
		BASE_double_to_float (nbr15_0, conf.resfilt.lfo_depth, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.resfilt.lfo_depth = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Profondeur + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_U:
		conf.resfilt.lfo_depth += (double)INTR_inc_speed [0] [RSC_mouse_key] / 10;
		changed_state = 1;
		break;

	/* Profondeur - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_D:
		conf.resfilt.lfo_depth -= (double)INTR_inc_speed [0] [RSC_mouse_key] / 10;
		changed_state = 1;
		break;

	/* Fader de la profondeur */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_DEPTH_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.lfo_depth = BASE_get_fader_val (slider_pos, 0.0, 24.0, 128, false);
		changed_state = 1;
		break;

	/* Fader de la phase */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_PHASE_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_LFO_PHASE_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.lfo_phase = BASE_get_fader_val (slider_pos, 0.0, 1.0, 128, false);
		auto_val = FxPreset_AUTO_VAL_RESFILT_LFO_PHASE;
		changed_state = 1;
		break;

	/* Mode multibande actif */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_ACTIVE_CB:
		conf.resfilt.cell_flag = ! conf.resfilt.cell_flag;
		changed_state = 1;
		break;

	/* Delta-F */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_BOX:
		BASE_double_to_float (nbr15_0, conf.resfilt.cell_ratio, 15);
		BASE_trim_string (nbr15_0);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_BOX_VAL,
		                      15, EditString_TYPE_FLO) == 0)
		{
			if (sscanf (nbr15_0, "%lf", &val_dbl) == 1)
			{
				conf.resfilt.cell_ratio = val_dbl;
				changed_state = 1;
			}
			else
			{
				refresh_dynamic (true);
			}
		}
		break;

	/* Delta-F + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_U:
		conf.resfilt.cell_ratio += (double)INTR_inc_speed [0] [RSC_mouse_key] / 10;
		changed_state = 1;
		break;

	/* Delta-F - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_D:
		conf.resfilt.cell_ratio -= (double)INTR_inc_speed [0] [RSC_mouse_key] / 10;
		changed_state = 1;
		break;

	/* Fader du delta-F */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_FADER_PIC:
		slider_pos = INTR_mouse.x - RSC_absolute_object_pixxpos [RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_DF_FADER_PIC];
		slider_pos -= RSC_get_gfx_ptr (RSC_GFX_KNOB_2_H_B)->get_width () / 2;
		conf.resfilt.cell_ratio = BASE_get_fader_val (slider_pos, 0.0, 24.0, 128, false);
		changed_state = 1;
		break;

	/* Nombre de bandes */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_BOX:
		sprintf (nbr15_0, "%3d", conf.resfilt.nbr_cells);
		if (EDIT_edit_string (nbr15_0, RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_BOX_VAL,
		                      3, EditString_TYPE_DEC) == 0)
		{
			conf.resfilt.nbr_cells = atoi (nbr15_0);
			changed_state = 1;
		}
		break;

	/* Nombre de bandes + */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_U:
		conf.resfilt.nbr_cells += INTR_inc_speed [0] [RSC_mouse_key];
		changed_state = 1;
		break;

	/* Nombre de bandes - */
	case	RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT_MB_NBR_D:
		conf.resfilt.nbr_cells -= INTR_inc_speed [0] [RSC_mouse_key];
		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	PatEdMenuFxResFilt::activate (bool activated_flag)
{
	RSC_pos_flag (RSC_OBJ_MP_SUBM_FX_FXPAN_RESFILT, 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	PatEdMenuFxResFilt::set_owner (PatEdMenuFx *pannel_ptr)
{
	_pannel_ptr = pannel_ptr;
}



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



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



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