/*
    GDAM - Geoff & Dave's Audio Mixer
    Copyright (C) 1999    Dave Benson, Geoff Matters.

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

    This library 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
    Lesser General Public License for more details.

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

    Contact:
        daveb@ffem.org <Dave Benson>
        geoff@ugcs.caltech.edu <Geoff Matters>
*/

#include <glib.h>

#ifndef __GDAM_BEAT_INFO_H_
#define __GDAM_BEAT_INFO_H_

/*  Describes a range of time (in seconds) for which a certain bpm and
 *  firstbeat value describe the tempo and phase of the music.  */
typedef struct _GdamBeatInfoRange GdamBeatInfoRange;
struct _GdamBeatInfoRange {
	double        		bpm;
	double        		first_beat;
	double        		range_start;
	double        		range_end;
	char			*name;
};

/*  Describes a loop within the source, start time and length are
 *  in seconds. */
typedef struct _GdamLoopInfo {
	char* name;
	float start;
	float length;
} GdamLoopInfo;

/* Describes the arrangement of beats in the output of a model. 
 * DO NOT ACCESS DIRECTLY under normal circumstances, use the 
 * get_* functions which return data appropriate to a position
 * within the song.  */

/* TODO: consider making afirstbeat et al into a full range in the range 
 * list, and keep an index to it... or perhaps keep the fb value to use
 * for finding which range is the default?
 */
typedef struct _GdamBeatInfo GdamBeatInfo;
struct _GdamBeatInfo {
	double        		afirst_beat;
	double        		abpm;
	char                   *aname;
	double        		arange_start;
	double        		arange_end;
	GList*			range_list;
	GList*	   		loop_list;
};

GdamBeatInfo*	gdam_beat_info_new	();
GdamBeatInfo*	gdam_beat_info_copy	(const GdamBeatInfo*	beat_info);
double		gdam_beat_info_get_bpm	(const GdamBeatInfo*	beat_info,
				       	 float			position);
double		gdam_beat_info_get_first_beat	
					(const GdamBeatInfo*	beat_info,
				       	 float			position);
double		gdam_beat_info_get_beat_length	
					(const GdamBeatInfo*	beat_info,
				       	 float			position);
void		gdam_beat_info_set_bpm	(GdamBeatInfo*		beat_info,
					 double			new_bpm);
void		gdam_beat_info_set_first_beat	
					(GdamBeatInfo*		beat_info,
					 double			new_first_beat);
void		gdam_beat_info_destroy	(GdamBeatInfo*		beat_info);
gboolean	gdam_beat_info_add_loop (GdamBeatInfo*          beat_info,
					 const char*	        name,
					 gdouble 	   	start,
					 gdouble 	   	length);
const GList*	gdam_beat_info_get_loops(const GdamBeatInfo*    beat_info);

/* Given a position within the source, this function guesses the index
 * of the beatinfo range which the position is in.  A return value of
 * zero means to use the default bpm/fb values.  A value of n > 0 means
 * the range is indexed [n-1] in the list of extended beatinfo.
 * This function only returns ranges which have bpms defined.
 */
int 		gdam_beat_info_guess_range_index
					(const GdamBeatInfo*    beat_info, 
					 gdouble 		time);
/* Similar to guess_range_index but considers index points (ranges with a
 * bpm of zero)
 */
int 		gdam_beat_info_guess_index_index
					(const GdamBeatInfo*    beat_info, 
					 gdouble 		time);
gdouble 	gdam_beat_info_guess_range_end
					(const GdamBeatInfo*    beat_info, 
					 int 			index);
/* Given a position, determine which index point is the next.  The return
 * value has the same meaning as for guess_range_index, except that a 
 * negative number means no index was found.
 */
int 		gdam_beat_info_guess_next_index 
					(const GdamBeatInfo*    beat_info, 
					 gdouble 		time);

/* Return the next and prior beat to a given time. */
gdouble         gdam_beat_info_get_next (const GdamBeatInfo    *beat_info,
					 gdouble                time);
gdouble         gdam_beat_info_get_prev (const GdamBeatInfo    *beat_info,
					 gdouble                time);

/* Get the firstbeat/bpm from an indexed beatinfo range.  An index of zero
 * means the default value, otherwise it is the value at range_list[n-1]
 */
gdouble 	gdam_beat_info_get_range_first_beat 
					(const GdamBeatInfo*    beat_info, 
					 int 			range_index);
gdouble 	gdam_beat_info_get_range_bpm 
					(const GdamBeatInfo*    beat_info, 
					 int 			range_index);
const char* 	gdam_beat_info_get_range_name 
					(const GdamBeatInfo*    beat_info, 
					 int 			range_index);
void    	gdam_beat_info_set_range_first_beat 
					(GdamBeatInfo*          beat_info, 
					 int 			range_index,
					 gdouble		first_beat);
void    	gdam_beat_info_set_range_bpm 
					(GdamBeatInfo*          beat_info, 
					 int 			range_index,
					 gdouble		bpm);
void        	gdam_beat_info_set_range_name 
					(GdamBeatInfo*          beat_info, 
					 int 			range_index,
					 const char 	       *name);
				       


#endif
