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

        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	<math.h>

#include	"base.h"
#include	"base_ct.h"
#include	"intrface.h"
#include	"gtracker.h"
#include	"samp.h"
#include	"Sample.h"
#include	"sliders.h"
#include	"SplEdWindow.h"
#include	"resource.h"
#include	"rsc01.h"
#include	"WaveForm.h"



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



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



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



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

int	SplEdWindow::color_window = Graphic::COL_GREY_GRAD + 2;

int	SplEdWindow::color_background [SplEdWindow_NBR_SPL_TYPES] [2] =
{
	{
		Graphic::COL_WHITE,
		Graphic::COL_BLACK
	},
	{
		Graphic::COL_WHITE,
		Graphic::COL_BLACK
	}
};

int	SplEdWindow::color_center_line [SplEdWindow_NBR_SPL_TYPES] =
{
	Graphic::COL_BLUE_GRAD + 6,
	Graphic::COL_BLUE_GRAD + 6
};

int	SplEdWindow::color_6db_line [SplEdWindow_NBR_SPL_TYPES] =
{
	Graphic::COL_GREY_GRAD + 5,
	Graphic::COL_GREY_GRAD + 5
};

int	SplEdWindow::color_channel_separator [SplEdWindow_NBR_SPL_TYPES] =
{
	Graphic::COL_BLACK,
	Graphic::COL_BLACK
};

int	SplEdWindow::color_data [SplEdWindow_NBR_SPL_TYPES] [3] =
{
	{
		Graphic::COL_BLUE_GRAD + 2,
		Graphic::COL_BLUE_GRAD + 5,
		Graphic::COL_CYAN_GRAD + 5
	},
	{
		Graphic::COL_RED_GRAD + 2,
		Graphic::COL_RED_GRAD + 5,
		Graphic::COL_YELLOW_GRAD + 5
	}
};



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



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



SplEdWindow::SplEdWindow (void)
{
	const SLID_INFO	slider_h =
	{
		RSC_OBJ_SE_MAIN_HSL_SBAR,
		RSC_OBJ_SE_MAIN_HSL_SBAR_SLIDER,
		0, 0, 0, 0, 0, -1,
		SLID_DIRECTION_HORIZONTAL,
		true, false, 0, 0
	};
// Modif d'initialisation par MF : changed_pos_flag = true

	const SLID_INFO	slider_v =
	{
		RSC_OBJ_SE_MAIN_VSL_SBAR,
		RSC_OBJ_SE_MAIN_VSL_SBAR_SLIDER,
		0, 0, 0, 0, 0, -1,
		SLID_DIRECTION_VERTICAL,
		true, false, 0, 0
	};
// Modif d'initialisation par MF : changed_pos_flag = true

	_h_slider = slider_h;
	_v_slider = slider_v;
}



SplEdWindow::~SplEdWindow (void)
{
}



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

void	SplEdWindow::redraw (void)
{
	RSC_display_object (RSC_OBJ_SE_MAIN);

	refresh ();
}



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

void	SplEdWindow::refresh (void)
{
	Sample_VIEW	view;

	/* Verifie le zoom */
	SAMP_get_sample_view (GTK_sample_nbr, view);
	view.h_zoom = MIN (view.h_zoom,
	                   (int) ceil (log (  (double)SAMP_get_sample_length (GTK_sample_nbr)
	                                    / RSC_get_width (RSC_OBJ_SE_MAIN_SPL)) / LN2));
	SAMP_set_sample_view (GTK_sample_nbr, view);

	/* Verifie la position */
	SAMP_get_sample_view (GTK_sample_nbr, view);
	view.h_pos = MIN (view.h_pos, SAMP_get_sample_length (GTK_sample_nbr) - get_max_nbr_disp_spl ());
	SAMP_set_sample_view (GTK_sample_nbr, view);

	
	/* La courbe du sample */
		display_wave (GTK_sample_nbr, RSC_OBJ_SE_MAIN_SPL);

	/* Les sliders */
	SAMP_get_sample_view (GTK_sample_nbr, view);
	_h_slider.virtual_len = SAMP_get_sample_length (GTK_sample_nbr);
	_h_slider.virtual_pos = view.h_pos;
	_h_slider.virtual_win = MIN (get_max_nbr_disp_spl (), _h_slider.virtual_len);
	SLID_display_slider (&_h_slider);

	_v_slider.virtual_len = 2 * 10000L;
	_v_slider.virtual_pos = (long) floor (((1.0 - view.v_pos - 1.0 / view.v_zoom) * 10000L) + 0.5);
	_v_slider.virtual_win = (long) (2L * 10000L / view.v_zoom);
	SLID_display_slider (&_v_slider);

	refresh_dynamic (true);
}



/*==========================================================================*/
/*      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	SplEdWindow::manage (int sel_object, int sel_elder)
{
	Sample_VIEW view;

	int current_x;
	Sample_SELECTION selection;
	int window_top;
	float v_pix_float;
	int channel_top;
	int channel_bottom;
	int channel_center;
	int channel;
	int nbr_channel;
	bool flag_refresh = false; 

	static int	last_pressed = 0;
	static int	start_x = 0;
	static int	start_channel = 0;
	static int  last_x = 0;
	SAMP_get_sample_view (GTK_sample_nbr, view);

	switch (sel_object)
	{

	/* Fenetre des donnees */
	case	RSC_OBJ_SE_MAIN_SPL:
		window_top = RSC_absolute_object_pixypos[sel_object];
		nbr_channel = SAMP_get_sample_stereo (GTK_sample_nbr);
		v_pix_float = (float) (RSC_get_height (sel_object) - nbr_channel) / (nbr_channel * 2);

		if (INTR_mouse.k == 1)
		{
			if (last_pressed == 0)
			{
				last_pressed = INTR_mouse.last_pressed;
				start_x = INTR_mouse.x - RSC_absolute_object_pixxpos [sel_object];
				channel = 0;
				channel_top = window_top;
				while (INTR_mouse.y > channel_top)
				{
					channel++;
					channel_top = (int) (window_top + v_pix_float * 2 * channel + channel);
					channel_bottom = (int) (window_top +  v_pix_float * 2 * (channel + 1) + channel);
					channel_center = (int) (window_top +  v_pix_float * (2 * channel + 1) + channel);
				}
				channel--;
				start_channel = channel;
				flag_refresh = true;
			}
			else if (INTR_mouse.last_released <= last_pressed)
			{
				/* Gestion de la longueur de selection */
				float h_spl_per_pix;
				h_spl_per_pix = (float) get_max_nbr_disp_spl() / (float) RSC_get_width (sel_object);

				current_x = INTR_mouse.x - RSC_absolute_object_pixxpos [sel_object];
				SAMP_get_sample_selection (GTK_sample_nbr, selection);
				selection.start = (long) ceil ((float) MIN(start_x, current_x) * h_spl_per_pix) + view.h_pos;
				selection.length =  (long) ceil ((float) ( MAX(start_x, current_x) -  MIN(start_x, current_x) + 1)
											* h_spl_per_pix);

				selection.flag = true;
				if (last_x != INTR_mouse.x)
				{
					flag_refresh = true;
				}
				/* Gestion des cannaux selectionnes */
				
				channel = 0;
				channel_top = window_top;

				while (INTR_mouse.y > channel_top)
				{
					channel++;
					channel_top = (int) (window_top + v_pix_float * 2 * channel + channel);
				}
				channel --;
				
				if (channel == start_channel)
				{
					channel_center = (int) (window_top +  v_pix_float * (2 * channel + 1) + channel);
					if (INTR_mouse.y > channel_center)
					{
						if (   (selection.start_channel != start_channel)
							 || (selection.nbr_channel != MAX(2, nbr_channel)))
						{
							selection.start_channel = start_channel;
							selection.nbr_channel = MAX(2, nbr_channel);
							flag_refresh = true;
						}
					}
					else
					{
						if (   (selection.start_channel != MAX(start_channel - 1, 0))
							 || (selection.nbr_channel != start_channel - selection.start_channel + 1))
						{
							selection.start_channel = MAX(start_channel - 1, 0);
							selection.nbr_channel = start_channel - selection.start_channel + 1;
							flag_refresh = true;
						}
					}

				}
				else
				{
					selection.start_channel = MIN(channel,start_channel);
					selection.nbr_channel = MAX(channel,start_channel) - selection.start_channel + 1;
				}
				SAMP_set_sample_selection (GTK_sample_nbr, selection);
				if (flag_refresh)
				{
					INTR_sample_editor_interface_ptr->refresh ();
					refresh();
				}
				last_x = INTR_mouse.x;
				}
			else
			{
				last_x = 0;
				last_pressed = 0;
				flag_refresh = false;
			}
		}
		else
		{
			last_x = 0;
			last_pressed = 0;
			flag_refresh = false;
		}
		break;

	/* Zoom In horizontal */
	case	RSC_OBJ_SE_MAIN_HSL_ZIN:
		view.h_zoom --;
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Zoom Out horizontal */
	case	RSC_OBJ_SE_MAIN_HSL_ZOUT:
		view.h_zoom ++;
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Fleche vers la gauche */
	case	RSC_OBJ_SE_MAIN_HSL_LEFT:
		view.h_pos -= MAX (  get_max_nbr_disp_spl ()
		                   * INTR_inc_speed [3] [RSC_mouse_key] / 10, 1);
		view.h_pos = MIN (view.h_pos, SAMP_get_sample_length (GTK_sample_nbr) - get_max_nbr_disp_spl ());
		view.h_pos = MAX (view.h_pos, 0);
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Fleche vers la droite */
	case	RSC_OBJ_SE_MAIN_HSL_RIGHT:
		view.h_pos += MAX (  get_max_nbr_disp_spl ()
		                   * INTR_inc_speed [3] [RSC_mouse_key] / 10, 1);
		view.h_pos = MIN (view.h_pos, SAMP_get_sample_length (GTK_sample_nbr) - get_max_nbr_disp_spl ());
		view.h_pos = MAX (view.h_pos, 0);
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Slider */
	case	RSC_OBJ_SE_MAIN_HSL_SBAR:
	case	RSC_OBJ_SE_MAIN_HSL_SBAR_SLIDER:
		SLID_gere_slider (&_h_slider, sel_object);
		if (_h_slider.changed_pos_flag)
		{
			view.h_pos = _h_slider.virtual_pos;
			view.h_pos = MIN (view.h_pos, SAMP_get_sample_length (GTK_sample_nbr) - get_max_nbr_disp_spl ());
			view.h_pos = MAX (view.h_pos, 0);
			SAMP_set_sample_view (GTK_sample_nbr, view);
			refresh ();
		}
		break;

	/* Zoom In vertical */
	case	RSC_OBJ_SE_MAIN_VSL_ZIN:
		view.v_zoom = view.v_zoom * 2;
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Zoom Out vertical */
	case	RSC_OBJ_SE_MAIN_VSL_ZOUT:
		view.v_zoom = view.v_zoom / 2;
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Fleche vers le haut */
	case	RSC_OBJ_SE_MAIN_VSL_UP:
		view.v_pos +=   2.0f * INTR_inc_speed [3] [RSC_mouse_key]
		              / (view.v_zoom * 10);
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Fleche vers le bas */
	case	RSC_OBJ_SE_MAIN_VSL_DOWN:
		view.v_pos -=   2.0f * INTR_inc_speed [3] [RSC_mouse_key]
		              / (view.v_zoom * 10);
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh ();
		break;

	/* Slider */
	case	RSC_OBJ_SE_MAIN_VSL_SBAR:
	case	RSC_OBJ_SE_MAIN_VSL_SBAR_SLIDER:
		SLID_gere_slider (&_v_slider, sel_object);
		if (_v_slider.changed_pos_flag)
		{
			view.v_pos = - 1.0f / view.v_zoom - ((float) _v_slider.virtual_pos / 10000L) + 1.0f;
			SAMP_set_sample_view (GTK_sample_nbr, view);
			refresh ();
		}
		break;

	/* Fenetre des curseurs de bouclage */
	case	RSC_OBJ_SE_MAIN_LOOP:
		INTR_dialog_box ("", "Not implemented", "Cancel", 0, 0);
		/*** A faire ***/
		break;

	/* Centrage de la vision */
	case	RSC_OBJ_SE_MAIN_CENTER:
		/* centrage  selon l'axe des abscisse */
		SAMP_get_sample_selection (GTK_sample_nbr, selection);
		
		while (selection.length > get_max_nbr_disp_spl ())
		{
			view.h_zoom ++;
			SAMP_set_sample_view (GTK_sample_nbr, view);
			SAMP_get_sample_view (GTK_sample_nbr, view);
			}
		
		if (selection.flag)
		{
			view.h_pos = MAX(selection.start + (selection.length - get_max_nbr_disp_spl ()) / 2, 0);
			view.h_pos = MIN(view.h_pos, SAMP_get_sample_length (GTK_sample_nbr));
		}
		SAMP_set_sample_view (GTK_sample_nbr, view);
		refresh();
		break;
	}
}



int	SplEdWindow::get_width (void)
{
	return (RSC_get_width (RSC_OBJ_SE_MAIN));
}



int	SplEdWindow::get_height (void)
{
	return (RSC_get_height (RSC_OBJ_SE_MAIN));
}



void	SplEdWindow::set_width (int width)
{
	int		x;
	int		y;
	int		x2;
	int		y2;
	int		width_for_slider;

	width = MAX (width, 150);	// On fixe quand meme une valeur minimum

	RSC_set_width (RSC_OBJ_SE_MAIN, width);

	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_CENTER, x, y);
	width_for_slider =   width
	                   - RSC_CHAR_W - RSC_get_width (RSC_OBJ_SE_MAIN_CENTER)
	                   - RSC_CHAR_W - x;

	/* Fixe la taille de la fenetre et de l'indicateur de loop */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_SPL, x, y);
	RSC_set_width (RSC_OBJ_SE_MAIN_SPL, width - RSC_CHAR_W - x);
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_LOOP, x, y);
	RSC_set_width (RSC_OBJ_SE_MAIN_LOOP, width - RSC_CHAR_W - x);

	/* Colle la fleche gauche du slider horizontal sur la droite */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_HSL_RIGHT, x, y);
	x = width_for_slider - RSC_get_width (RSC_OBJ_SE_MAIN_HSL_RIGHT);
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_HSL_RIGHT, x, y);

	/* Change la taille du slider horizontal en fonction
	   de sa position et de celle de la fleche droite */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_HSL_SBAR, x2, y2);
	RSC_set_width (RSC_OBJ_SE_MAIN_HSL_SBAR, x - x2);
	SLID_check_slider (&_h_slider);
}



void	SplEdWindow::set_height (int height)
{
	int		x;
	int		y;
	int		x2;
	int		y2;
	int		height_for_window;
	int		height_for_slider;

	height = MAX (height, 150);	// On fixe quand meme une valeur minimum

	RSC_set_height (RSC_OBJ_SE_MAIN, height);

	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL, x, y);
	height_for_slider =   height - 4
	                    - RSC_get_height (RSC_OBJ_SE_MAIN_CENTER) - 4
	                    - RSC_get_height (RSC_OBJ_SE_MAIN_VSL_ZOUT)
	                    - RSC_get_height (RSC_OBJ_SE_MAIN_VSL_ZIN) - y;

	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_SPL, x, y);
	height_for_window =   height - 4
	                    - RSC_get_height (RSC_OBJ_SE_MAIN_HSL_SBAR) - 4
	                    - RSC_get_height (RSC_OBJ_SE_MAIN_LOOP) - 4 - y;

	/* Colle le slider horizontal et le bonton de centrage vers le bas */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_HSL, x, y);
	y = height - 4 - RSC_get_height (RSC_OBJ_SE_MAIN_HSL_SBAR);
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_HSL, x, y);

	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_CENTER, x, y);
	y = height - 4 - RSC_get_height (RSC_OBJ_SE_MAIN_CENTER);
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_CENTER, x, y);

	/* Colle la fleche bas du slider */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL_DOWN, x, y);
	y = height_for_slider - RSC_get_height (RSC_OBJ_SE_MAIN_VSL_DOWN);
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_VSL_DOWN, x, y);

	/* Colle Zoom In sous le bas du slider */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL_ZIN, x, y);
	y = height_for_slider;
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_VSL_ZIN, x, y);

	/* Colle Zoom Out sous Zoom In */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL_ZOUT, x, y);
	y = height_for_slider + RSC_get_height (RSC_OBJ_SE_MAIN_VSL_ZIN);
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_VSL_ZOUT, x, y);

	/* Change la taille du slider vertical en fonction
	   de sa position et de celle de la fleche vers le bas */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL_DOWN, x, y);
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_VSL_SBAR, x2, y2);
	RSC_set_height (RSC_OBJ_SE_MAIN_VSL_SBAR, y - y2);
	SLID_check_slider (&_v_slider);

	/* Change la taille de la fenetre */
	RSC_set_height (RSC_OBJ_SE_MAIN_SPL, height_for_window);

	/* Colle sur le bas les curseurs de loop */
	RSC_get_relative_object_position (RSC_OBJ_SE_MAIN_SPL, x, y);
	y += height_for_window + 4;
	RSC_set_relative_object_position (RSC_OBJ_SE_MAIN_LOOP, x, y);
}



void	SplEdWindow::get_coordinates (int &pix_x, int &pix_y)
{
	pix_x = RSC_absolute_object_pixxpos [RSC_OBJ_SE_MAIN];
	pix_y = RSC_absolute_object_pixypos [RSC_OBJ_SE_MAIN];
}



void	SplEdWindow::move_to (int pix_x, int pix_y)
{
	RSC_set_absolute_object_position (RSC_OBJ_SE_MAIN, pix_x, pix_y);
}



long	SplEdWindow::get_real_nbr_disp_spl (void)
{
	Sample_VIEW view;
	long	window_spl_length;

	SAMP_get_sample_view (GTK_sample_nbr, view);
	window_spl_length = get_max_nbr_disp_spl ();
	if (view.h_pos + window_spl_length > SAMP_get_sample_length (GTK_sample_nbr))
	{
		window_spl_length = SAMP_get_sample_length (GTK_sample_nbr) - view.h_pos;
	}

	return (window_spl_length);
}



long	SplEdWindow::get_max_nbr_disp_spl (void)
{
	Sample_VIEW view;
	long	window_spl_length;
	long	h_pix_per_spl;
	long	h_spl_per_pix;

	SAMP_get_sample_view (GTK_sample_nbr, view);
	if (view.h_zoom >= 0)
	{
		h_spl_per_pix = 1 << view.h_zoom;
		h_pix_per_spl = 1;
	}
	else
	{
		h_spl_per_pix = 1;
		h_pix_per_spl= 1 << (-view.h_zoom);
	}
	window_spl_length = (RSC_get_width (RSC_OBJ_SE_MAIN_SPL) & ~(h_pix_per_spl - 1))/ h_pix_per_spl * h_spl_per_pix;

	return (window_spl_length);
}



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



signed int	SplEdWindow::display_wave (int sample, int object)
{
/*************************************************************************************************************************/
// Ajouts par Lolo

/*	long			h_pos;
	signed int	h_zoom;
	double		v_pos;
	double		v_zoom;*/
	Sample_VIEW	view;
	Sample_SELECTION	selection;
	int			window_pix_length;
	int			window_pix_height;

	SAMP_get_sample_view (sample, view);
	SAMP_get_sample_selection (sample, selection);
	window_pix_length = RSC_get_width (object);
	window_pix_height = RSC_get_height (object);

	/* Il est temps d'initialiser une vue par defaut */
	if (view.h_zoom == Sample_H_ZOOM_TO_INIT)
	{
		double	spp;
		long		total_sample_len;
	
		total_sample_len = SAMP_get_sample_length (sample);
		
		/* On essaie de faire tenir le sample dans la fenetre */
		if (total_sample_len > 0)
		{
			spp = (double)total_sample_len / window_pix_length;
			view.h_zoom = (signed int) ceil (log (spp) / LN2);
		}

		else
		{
			view.h_zoom = 8;		// Par defaut.
		}

		/* On sauve les parametres */
		SAMP_set_sample_view (sample, view);
	}
// Fin des ajouts par Lolo
/*************************************************************************************************************************/

	INTR_graph_ptr->hide_mouse();

	if (SplEdMainLoop::edit_mode == SplEdMainLoop_MODE_LOOP)
	{
		display_wave_loop (sample, object);
	}
	else
	{
		display_wave_normal (sample, object);
	}

	INTR_graph_ptr->show_mouse ();

	return 0;
}

signed int	SplEdWindow::display_wave_normal (int sample, int object)
{
	int nbr_channel;
	float v_pix_float;
	int v_pix_pos;
	int v_pix_neg;
	int sample_type;						// type du sample : d2d, memory...
	BYTE *sample_data_ptr;				// pointeur de sur les donnees du sample.
	long h_spl_per_pix;					// nombre de sample par pixel horizontalement >1.
	long h_pix_per_spl;					// nombre de pixel par sample horizontalement >1.
	long window_spl_length;				// longueur de la fenêtre en echantillons.
	long sample_length;					// longueur du sample en echantillons.
	long bytes_per_channel;				// nombre d'octet representant un echantillon.
	int sample_stereo;					// vaut 2 si stereo 1 si mono.
	int window_pix_length;				// longueur de la fenêtre en pixels.
	int window_pix_height;				// largeur de la fenêtre en pixels.
	int wave_pix_length;					// longueur du sample affiché en pixels.
	int buffer_id;							// numéro d'ID du buffer du pixel en cours.
	int window_top;						// ordonnée du haut de la fenetre.
	int window_bottom;					// ordonnée du bas de la fenetre.
	int	depassement;

	double v_channel;
	double v_max;
	double v_min;
	int channel_top;
	int channel_center;
	int channel_bottom;
	int y_6db_line_pos;					// ligne à -6 dB y > 0
	int y_6db_line_neg;					// ligne à -6 dB y < 0
	int y_center_line;					// ordonnée center line
	int selection_on;
	bool flag_6db_line_pos;
	bool flag_6db_line_neg;
	bool flag_center_line;
	bool flag_data_overflow;
	long			h_pos;
	signed int	h_zoom;
	double		v_pos;
	double		v_zoom;
	Sample_VIEW	view;
	Sample_SELECTION	selection;

	SAMP_get_sample_view (sample, view);
	SAMP_get_sample_selection (sample, selection);

	window_pix_length = RSC_get_width (object);
	window_pix_height = RSC_get_height (object);

	h_pos = view.h_pos;
	h_zoom = view.h_zoom;
	v_pos = view.v_pos;
	v_zoom = view.v_zoom;
	

	/* Initialisation des variables h_pix et h_pix_per_spl */
	sample_type = SAMP_get_sample_type(sample);
	if (h_zoom > 0)
	{
		h_spl_per_pix = 1 << h_zoom;
		h_pix_per_spl = 1;
		depassement = 1;
	}
	else
	{
		h_spl_per_pix = 1;
		h_pix_per_spl= 1 << (-h_zoom);
		depassement = 0;
	}
	h_pos &= ~(h_spl_per_pix - 1);
	bytes_per_channel = SAMP_get_sample_resolution (sample) >> 3;
	sample_stereo = SAMP_get_sample_stereo (sample);
	sample_length = SAMP_get_sample_length (sample);

	window_spl_length = (window_pix_length & ~(h_pix_per_spl - 1))/ h_pix_per_spl * h_spl_per_pix;
	if ( h_pos + window_spl_length > sample_length)
	{
		window_spl_length = sample_length - h_pos;
	}

	wave_pix_length = (window_spl_length & ~(h_spl_per_pix - 1)) / h_spl_per_pix;
	
	buffer_id = 0;
	window_top = RSC_absolute_object_pixypos[object];
	window_bottom = window_top + window_pix_height;

	/* Dessin du Wave */
	INTR_graph_ptr->hide_mouse();	// la souris est effacée
	nbr_channel = SAMP_get_sample_stereo (sample);
	v_pix_float = (float) (window_pix_height - nbr_channel) / (nbr_channel * 2);

for (int i = 0; i < window_pix_length; i++)
{
	for (int channel = 0; channel < nbr_channel; channel++)
	{
		channel_top = (int) (window_top + v_pix_float * 2 * channel + channel);
		channel_bottom = (int) (window_top +  v_pix_float * 2 * (channel + 1) + channel);
		channel_center = (int) (window_top +  v_pix_float * (2 * channel + 1) + channel);
		v_pix_pos = (channel_center - channel_top);
		v_pix_neg = (channel_bottom - channel_center);

		/*  parametrages des lignes de niveau */
		// ligne centrale
		if (v_pos > 0)
		{
			y_center_line = channel_center + (int) (v_pos * v_zoom * v_pix_neg);
		}
		else
		{
			y_center_line = channel_center + (int) (v_pos * v_zoom * v_pix_pos);
		}

		flag_center_line = true;
		if ( (y_center_line < channel_top) || (y_center_line > channel_bottom))
		{
			flag_center_line = false;
		}
		// lignes à -6db
		
		y_6db_line_pos = channel_center - (int) ((0.5 - v_pos) * v_zoom * v_pix_pos);
		y_6db_line_neg = channel_center - (int) ((-0.5 - v_pos) * v_zoom * v_pix_neg);
		flag_6db_line_pos = true;
		flag_6db_line_neg = true;
		if ( (y_6db_line_pos < channel_top) || (y_6db_line_pos > channel_bottom))
		{
			flag_6db_line_pos = false;
		}
		if ( (y_6db_line_neg < channel_top) || (y_6db_line_neg > channel_bottom))
		{
			flag_6db_line_neg = false;
		}

//		for (int i = 0; i < window_pix_length; i++)
//		{
			if (i < wave_pix_length)
			{
				int n_spl;
				n_spl = h_spl_per_pix;
				if (h_pos + i * h_spl_per_pix + n_spl > sample_length )
				{
					n_spl = sample_length - (h_pos + i * h_spl_per_pix);
					depassement = 0;
				}
				
				sample_data_ptr = SAMP_get_access_buffer_ptr (sample, h_pos + i * h_spl_per_pix, n_spl + depassement, buffer_id, /*BOOL write_flag*/FALSE, FALSE);
				v_max = -1;
				v_min = 1;
				if (bytes_per_channel == 2)
				{
					for (int j = 0; j < n_spl + depassement; j++)
					{
					v_channel = ((double) *((SWORD*) (sample_data_ptr + (j * nbr_channel + channel) * bytes_per_channel))) / 32768 ;
					v_max = MAX(v_max, v_channel);
					v_min = MIN(v_min, v_channel);
					}
				}
				else
				{
					for (int j = 0; j < n_spl + depassement; j++)
					{
					v_channel = ((double) *((SBYTE*) (sample_data_ptr + (j * nbr_channel + channel) * bytes_per_channel))) / 128;
					v_max = MAX(v_max, v_channel);
					v_min = MIN(v_min, v_channel);
					}
				}
				/* Traçage du pixel */
				flag_data_overflow = false;

				// Mise à l'echelle de v_max_left
				v_max =  (v_max - v_pos) * v_zoom;
				if (v_max < -1)
				{
					v_max = -1;
					flag_data_overflow = true;

			  }
				else if (v_max > 1)
				{
					v_max = 1;
					if (h_zoom <= 0)
					{
						flag_data_overflow = true;
					}
				}
				else
				{
				}
				
				// Mise à l'echelle de v_min
				v_min = (v_min - v_pos) * v_zoom;
				if (v_min < -1)
				{
					v_min = -1;
					if (h_zoom <= 0)
					{
						flag_data_overflow = true;
					}
				}
				else if (v_min > 1)
				{
					v_min = 1;
					flag_data_overflow = true;
				}
				else
				{
				}

				// procedure graphique
				int x, y1, y2,spl;

				x = i * h_pix_per_spl + RSC_absolute_object_pixxpos[object];
				if (v_max > 0)
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_pos));
				}
				else
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_neg));
				}
				if (v_min > 0)
				{
					y2 = channel_center - (int) (v_min * ((double) v_pix_pos));
				}
				else
				{
					y2 = channel_center - (int) (v_min * ((double) v_pix_neg));
				}
				
				spl = h_pos + i * h_spl_per_pix;

				if ((selection.flag)&&(spl >= selection.start)&&(spl < (selection.start + selection.length))&&
					(channel >= selection.start_channel)&&((channel - selection.start_channel) < selection.nbr_channel))
				{
					selection_on = 1;
				}
				else
				{
					selection_on = 0;
				}

				for (int k = 0; k < h_pix_per_spl; k++)
				{
					// background
					INTR_graph_ptr->display_vline(x, channel_top, y1 - channel_top, color_background [sample_type] [selection_on]);	
					INTR_graph_ptr->display_vline(x, y2 + 1, channel_bottom - y2, color_background [sample_type] [selection_on]);
					// center line
					if (flag_center_line)
					{
						INTR_graph_ptr->display_point(x, y_center_line, color_center_line [sample_type]);
					}
					// 6 dB lines
					if (flag_6db_line_pos)
					{
						INTR_graph_ptr->display_point(x, y_6db_line_pos, color_6db_line [sample_type]);
					}
					if (flag_6db_line_neg)
					{
						INTR_graph_ptr->display_point(x, y_6db_line_neg, color_6db_line [sample_type]);
					}
					// separator line
					if (channel > 0)
					{
						INTR_graph_ptr->display_point(x, channel_top - 1, color_channel_separator [sample_type]); 
					}
					// data 
					if (flag_data_overflow)
					{
						INTR_graph_ptr->display_vline(x, y1, y2 - y1 + 1, color_background [sample_type] [selection_on]); // ligne du graphique
					}
					else
					{
						INTR_graph_ptr->display_vline(x, y1, y2 - y1 + 1, color_data [sample_type] [selection_on]); // ligne du graphique
					}
					x++ ; 
				}
	
			}
			else
			{
				int x;
				if (i == wave_pix_length)
				{
					i = i * h_pix_per_spl;
				}
				x = i + RSC_absolute_object_pixxpos[object];
				//fond de la fenêtre
				INTR_graph_ptr->display_vline(x,channel_top,channel_bottom - channel_top + 1, color_window);
				// center line
				if (flag_center_line)
				{
					INTR_graph_ptr->display_point(x, y_center_line, color_center_line [sample_type]);
				}
				// 6 dB lines
				if (flag_6db_line_pos)
				{
					INTR_graph_ptr->display_point(x, y_6db_line_pos, color_6db_line [sample_type]);
				}
				if (flag_6db_line_neg)
				{
					INTR_graph_ptr->display_point(x, y_6db_line_neg, color_6db_line [sample_type]);
				}
				// separator line
				if (channel>0)
				{
					INTR_graph_ptr->display_point(x, channel_top - 1, color_channel_separator [sample_type]); 
				}
			}
//		}
	}

}	
	SAMP_release_access_buffer (buffer_id);	// relache le buffer réservé

	return (0);
}
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/

signed int	SplEdWindow::display_wave_loop (int sample, int object)
{
	int nbr_channel;
	float v_pix_float;
	int v_pix_pos;
	int v_pix_neg;
	int sample_type;						// type du sample : d2d, memory...
	BYTE *sample_data_ptr;				// pointeur de sur les donnees du sample.
	long h_pix_per_spl;					// nombre de pixel par sample horizontalement >1.
	long window_spl_length;				// longueur de la fenêtre en echantillons.
	long sample_length;					// longueur du sample en echantillons.
	long bytes_per_channel;				// nombre d'octet representant un echantillon.
	int sample_stereo;					// vaut 2 si stereo 1 si mono.
	int window_pix_length;				// longueur de la fenêtre en pixels.
	int window_pix_height;				// largeur de la fenêtre en pixels.
	int buffer_id;							// numéro d'ID du buffer du pixel en cours.
	int window_top;						// ordonnée du haut de la fenetre.
	int window_bottom;					// ordonnée du bas de la fenetre.
	int	depassement;

	double v_max;
	int channel_top;
	int channel_center;
	int channel_bottom;
	int y_6db_line_pos;					// ligne à -6 dB y > 0
	int y_6db_line_neg;					// ligne à -6 dB y < 0
	int y_center_line;					// ordonnée center line
	bool flag_data_overflow;
	bool flag_data_overflow_show;
	bool flag_data_overflow_hide;
	bool flag_data_present_show;
	bool flag_data_present_hide;
	bool flag_ping_pong;

	long			h_pos_start;
	long			h_pos_end;
	long			loop_start;
	long			loop_length;
	long			loop_end;
	signed int	h_zoom;
	double		v_pos;
	double		v_zoom;
	Sample_VIEW	view;
	Sample_SELECTION	selection;
	int			v_max_hide;
	int			v_max_show;
	int			v_max_hide_old = -1;
	int			v_max_show_old = -1 ; 

	SAMP_get_sample_view (sample, view);
	SAMP_get_sample_selection (sample, selection);

	window_pix_length = RSC_get_width (object);
	window_pix_height = RSC_get_height (object);

	h_zoom = MIN(view.h_zoom, 0);
	v_pos = view.v_pos;
	v_zoom = view.v_zoom;
	

	window_pix_length = RSC_get_width (object);
	window_pix_height = RSC_get_height (object);




	/* Initialisation des variables h_pix et h_pix_per_spl */
	sample_type = SAMP_get_sample_type(sample);
	
	depassement = 0;
	h_pix_per_spl= 1 << (-h_zoom);

	bytes_per_channel = SAMP_get_sample_resolution (sample) >> 3;
	sample_stereo = SAMP_get_sample_stereo (sample);
	sample_length = SAMP_get_sample_length (sample);

	window_spl_length = (window_pix_length & ~(h_pix_per_spl - 1))/ h_pix_per_spl;

	buffer_id = 0;
	window_top = RSC_absolute_object_pixypos[object];
	window_bottom = window_top + window_pix_height;

	INTR_graph_ptr->hide_mouse();	// la souris est effacée
	nbr_channel = SAMP_get_sample_stereo (sample);
	v_pix_float = (float) (window_pix_height - nbr_channel) / (nbr_channel * 2);

	/* Variables de bouclage */
	flag_ping_pong = (SAMP_get_sample_loop (sample) == WaveForm_LOOP_TYPE_PP);

	loop_start = SAMP_get_sample_repeat (sample);
	loop_length = SAMP_get_sample_replen (sample);
	loop_end = loop_start + loop_length;
	
	h_pos_start = loop_start - window_pix_length / (2 * h_pix_per_spl);
	if (flag_ping_pong)
	{
		h_pos_end = loop_start + window_pix_length / (2 * h_pix_per_spl) - 1;
	}
	else
	{
		h_pos_end = loop_end - window_pix_length / (2 * h_pix_per_spl);
	}

	/*** Dessin du background ***/
	//INTR_graph_ptr->display_vline(x, channel_top, channel_bottom - channel_top + 1, color_background [sample_type] [0]);	
	Graphic_FRAME_INFO cadre;
	cadre.x = RSC_absolute_object_pixxpos[object];
	cadre.y = RSC_absolute_object_pixypos[object];
	cadre.l = window_pix_length;
	cadre.h = window_pix_height;
	cadre.backgc = color_background [sample_type] [0];
	INTR_graph_ptr->display_box(&cadre);
	for (int channel = 0; channel < nbr_channel; channel++)
	{
		channel_top = (int) (window_top + v_pix_float * 2 * channel + channel);
		channel_bottom = (int) (window_top +  v_pix_float * 2 * (channel + 1) + channel);
		channel_center = (int) (window_top +  v_pix_float * (2 * channel + 1) + channel);
		v_pix_pos = (channel_center - channel_top);
		v_pix_neg = (channel_bottom - channel_center);

		/*** parametrages des lignes de niveau ***/
		// ligne centrale
		if (v_pos > 0)
		{
			y_center_line = channel_center + (int) (v_pos * v_zoom * v_pix_neg);
		}
		else
		{
			y_center_line = channel_center + (int) (v_pos * v_zoom * v_pix_pos);
		}
		if ( (y_center_line >= channel_top) && (y_center_line <= channel_bottom))
		{
			INTR_graph_ptr->display_hline(RSC_absolute_object_pixxpos[object], y_center_line, window_pix_length, color_center_line [sample_type]);
		}
		// lignes à -6db
		
		y_6db_line_pos = channel_center - (int) ((0.5 - v_pos) * v_zoom * v_pix_pos);
		y_6db_line_neg = channel_center - (int) ((-0.5 - v_pos) * v_zoom * v_pix_neg);
		if ( (y_6db_line_pos >= channel_top) && (y_6db_line_pos <= channel_bottom))
		{
			INTR_graph_ptr->display_hline(RSC_absolute_object_pixxpos[object], y_6db_line_pos, window_pix_length, color_6db_line [sample_type]);
		}
		if ( (y_6db_line_neg >= channel_top) && (y_6db_line_neg <= channel_bottom))
		{
			INTR_graph_ptr->display_hline(RSC_absolute_object_pixxpos[object], y_6db_line_neg, window_pix_length, color_6db_line [sample_type]);
		}
		// Separator line
		INTR_graph_ptr->display_hline(RSC_absolute_object_pixxpos[object], channel_top - 1, window_pix_length, color_channel_separator [sample_type]);

		/***  Dessin du wave ***/
		for (int i = 0; i < window_spl_length; i++)
		{
			/*****************************/
			/* Calcul de la Boucle START */
			/*****************************/
			int x, y1; 
			int sample_data_ptr_start;
			sample_data_ptr_start = h_pos_start + i ;
			flag_data_present_hide = false;
			flag_data_present_show = false;

			if (   sample_data_ptr_start >= 0
				 && sample_data_ptr_start < sample_length)
			{
				sample_data_ptr = SAMP_get_access_buffer_ptr (sample, sample_data_ptr_start, 1 + depassement, buffer_id, /*BOOL write_flag*/FALSE, FALSE);
				if (bytes_per_channel == 2)
				{
					v_max = ((double) *((SWORD*) (sample_data_ptr + channel * bytes_per_channel))) / 32768 ;
				}
				else
				{
					v_max = ((double) *((SBYTE*) (sample_data_ptr + channel * bytes_per_channel))) / 128;
				}
				/* Traçage du pixel */
				flag_data_overflow = false;

				// Mise à l'echelle de v_max
				v_max =  (v_max - v_pos) * v_zoom;
				if (v_max < -1)
				{
					v_max = -1;
					flag_data_overflow = true;

			  }
				else if (v_max > 1)
				{
					v_max = 1;
					flag_data_overflow = true;
				}
				// procedure graphique

				if (v_max > 0)
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_pos));
				}
				else
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_neg));
				}
				
				if ((sample_data_ptr_start >= loop_start) && (sample_data_ptr_start < loop_end))
				{
					v_max_show = y1;
					flag_data_overflow_show = flag_data_overflow;
					flag_data_present_show = true;
				}
				else
				{
					v_max_hide = y1;
					flag_data_overflow_hide = flag_data_overflow;
					flag_data_present_hide = true;
				}
			}
			/***************************/
			/* Calcul de la Boucle END */
			/***************************/
			if (flag_ping_pong)
			{
				sample_data_ptr_start = h_pos_end - i;
			}
			else
			{
				sample_data_ptr_start = h_pos_end + i;
			}
			if (   sample_data_ptr_start >= 0
				 && sample_data_ptr_start < sample_length)
			{
				sample_data_ptr = SAMP_get_access_buffer_ptr (sample, sample_data_ptr_start, 1, buffer_id, /*BOOL write_flag*/FALSE, FALSE);
				if (bytes_per_channel == 2)
				{
					v_max = ((double) *((SWORD*) (sample_data_ptr + channel * bytes_per_channel))) / 32768 ;
				}
				else
				{
					v_max = ((double) *((SBYTE*) (sample_data_ptr +  channel * bytes_per_channel))) / 128;
				}
				/* Traçage du pixel */
				flag_data_overflow = false;

				// Mise à l'echelle de v_max
				v_max =  (v_max - v_pos) * v_zoom;
				if (v_max < -1)
				{
					v_max = -1;
					flag_data_overflow = true;

			  }
				else if (v_max > 1)
				{
					v_max = 1;
					flag_data_overflow = true;
				}
				
				// procedure graphique
				if (v_max > 0)
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_pos));
				}
				else
				{
					y1 = channel_center - (int) (v_max * ((double) v_pix_neg));
				}
				if ((sample_data_ptr_start >= loop_start) && (sample_data_ptr_start < loop_end))
				{
					v_max_show = y1;
					flag_data_overflow_show = flag_data_overflow;
					flag_data_present_show = true;
				}
				else
				{
					v_max_hide = y1;
					flag_data_overflow_hide = flag_data_overflow;
					flag_data_present_hide = true;
				}
			}
		

				
			x = i * h_pix_per_spl + RSC_absolute_object_pixxpos[object];
	
			// Data
			if (flag_data_present_hide)
			{
				if (!flag_data_overflow_hide)
				{
					INTR_graph_ptr->display_hline(x, v_max_hide, h_pix_per_spl, color_data [sample_type] [2]); // data non bouclée superposée
				}
				if (   (v_max_hide_old > 0)
					 && (v_max_hide_old != v_max_hide))
				{
					INTR_graph_ptr->display_line(x - 1, v_max_hide_old, x, v_max_hide, color_data [sample_type] [2]); // data non bouclée superposée
				}
				v_max_hide_old = v_max_hide;
			}
			if (flag_data_present_show)
			{
				if (!flag_data_overflow_show)
				{
					INTR_graph_ptr->display_hline(x, v_max_show, h_pix_per_spl, color_data [sample_type] [0]); // data bouclee
				}
				if (   (v_max_show_old > 0)
					 && (v_max_show_old != v_max_show))
				{
					INTR_graph_ptr->display_line(x - 1, v_max_show_old, x, v_max_show, color_data [sample_type] [0]); // datat bouclee
				}
				v_max_show_old = v_max_show;
			}
			if (   (sample_data_ptr_start == loop_end && !flag_ping_pong) 
				 || (sample_data_ptr_start == loop_start - 1 && flag_ping_pong))
			{
				INTR_graph_ptr->display_vline(x, channel_top, channel_bottom - channel_top + 1, color_background [sample_type] [1]);	
			}
		}
	}
	SAMP_release_access_buffer (buffer_id);	// relache le buffer réservé
	return (0);
}


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



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