/*
    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>
*/
#ifndef __GDAM_MODEL_TURNTABLE_H_
#define __GDAM_MODEL_TURNTABLE_H_

typedef struct _GdamTurntable GdamTurntable;
typedef struct _GdamTurntableClass GdamTurntableClass;

#include "gdamproducer.h"

/*
 * This component emulates a DJ Turntable.  It provides
 * playback of a song (most commonly an mp3 file) along
 * with control over position and resampling rate.
 */

#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/wait.h>
#include <gdam/client/gdamchannel.h>
#include "gdammodel.h"
#include "gdamsongdatabase.h"
#include "gdaminfomanager.h"

GtkType gdam_turntable_get_type();
#define GDAM_TYPE_TURNTABLE              (gdam_turntable_get_type ())
#define GDAM_TURNTABLE(obj)              (GTK_CHECK_CAST ((obj), GDAM_TYPE_TURNTABLE, GdamTurntable))
#define GDAM_TURNTABLE_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GDAM_TYPE_TURNTABLE, GdamTurntableClass))
#define GDAM_IS_TURNTABLE(obj)           (GTK_CHECK_TYPE ((obj), GDAM_TYPE_TURNTABLE))
#define GDAM_IS_TURNTABLE_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GDAM_TYPE_TURNTABLE))

#define GDAM_TURNTABLE_NUM_CUE_POINTS 5

struct _GdamTurntableClass {
	GdamProducerClass		producer_class;
	void			(*update_beatnum) (GdamTurntable*  turntable,
						   gdouble	   beatnum);
	void			(*update_sync_preview) 	  
						  (GdamTurntable*  turntable,
						   gdouble	   preview);
	void			(*update_jump_preview) 	  
						  (GdamTurntable*  turntable,
						   gdouble	   preview);
};

struct _GdamTurntable {
	GdamProducer		base;
	GdamProducer*		producer;
	gboolean		user_dragging_position;
	//gboolean		anchored;
	double			gain, rate;
	double			bpm_factor;
	double			seek_factor;
	double			track_length;

	/*
	 * The resample's source id.
	 * The gain is GDAM_MODEL(turntable)->source_id.
	 * The "mp3" is GDAM_MODEL(turntable->producer)->source_id.
	 */
	guint			resample_id;

	/* Subscription notification connection ids. */
	guint			eof_sub_id, pos_sub_id;

	/* We connect to our producer's source_id func, but we need
	 * to disconnect from it. */
	//guint			sub_set_source_handle;
        guint 			sub_set_beat_info_handle;
        guint 			sub_set_position_handle;
        guint 			sub_update_length_handle;
	  /*  Used to follow extended beatinfo ranges.  */
	int			beatinfo_index;
	gdouble			next_first_beat;
	gdouble			prev_last_beat;
	gboolean		making_synch_preview_request;
	gboolean		beatinfo_locked;
	gboolean		tempo_locked;

          /* Cue points which can be created and jumped to. */
        gdouble                 cue_points[GDAM_TURNTABLE_NUM_CUE_POINTS];
};

GdamTurntable* gdam_turntable_new            (GdamChannel*      channel);
void 	       	gdam_turntable_free	     (GdamTurntable* 	turntable);
void           	gdam_turntable_zero           (GdamTurntable*   turntable);
void         	gdam_turntable_start          (GdamTurntable*   turntable);
/*  Seek to a relative position within the producer.  delta_time is a
 *  producer time, ie not scaled by rate.
 */
void           	gdam_turntable_seek          (GdamTurntable*    turntable,
                                              gdouble           delta_time);
void           	gdam_turntable_seek_by_beats (GdamTurntable*    turntable,
				              gdouble           num_beats); 
/* Seek to a point within the producer, timing the jump so that phase is
 * preserved.  target_time is a producer time, ie not scaled by rate. 
 */
void 		gdam_turntable_seek_in_beat  (GdamTurntable*    turntable, 
					      gdouble           target_time);
void            gdam_turntable_set_producer  (GdamTurntable*    turntable,
                                              GdamProducer*     producer);
GdamProducer*   gdam_turntable_get_producer  (GdamTurntable*    turntable);
void 		gdam_turntable_set_rate      (GdamTurntable*    turntable, 
					      float 		newrate);
void 		gdam_turntable_set_anchored  (GdamTurntable*    turntable, 
					      gboolean 		anchored);
/* Compute the number of beats a particular time corresponds to.  The time
 * is a turntable time, ie scaled by rate.
 */
float          	gdam_turntable_get_beat_number(GdamTurntable*      turntab,
                                               float               time);
void 		gdam_turntable_update_jump_preview	     
					     (GdamTurntable* 	turntable, 
					      float 		newval);
void 		gdam_turntable_cycle_beat_info(GdamTurntable* turntable);


/*  Return the firstbeat value which describes the producer's current output */
gdouble 	gdam_turntable_get_current_producer_fb
						(GdamTurntable* turntable);
/*  Return the bpm value which describes the producer's current output */
gdouble 	gdam_turntable_get_current_producer_bpm
						(GdamTurntable* turntable);
/*  Return the firstbeat value which describes the turntable's current output */
gdouble 	gdam_turntable_get_current_fb   (GdamTurntable* turntable);
/*  Return the bpm value which describes the turntable's current output */
gdouble 	gdam_turntable_get_current_bpm  (GdamTurntable* turntable);


/*
 * These are utility functions used internally and by the skin.
 *
 */ 
void    turntable_set_tempo		   (GdamTurntable* turntable, 
					    gdouble 	   new_tempo);
void    turntable_do_sync                  (GdamTurntable* turntable);
void 	turntable_do_sync_preview	   (GdamTurntable* turntable);

#endif
