/*
    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_BUFFER_MANAGER_H_
#define __GDAM_BUFFER_MANAGER_H_

#include "gdammodel.h"

/* Map from buffer_id => GdamBufferManagerInfo. */
extern GHashTable* gdam_buffer_manager_buffers;


typedef struct _GdamBufferManagerInfo GdamBufferManagerInfo;
typedef struct _GdamBufferManagerNotifier GdamBufferManagerNotifier;

typedef void (*GdamBufferChangedFunc)(GdamBufferManagerInfo*      info,
                                      gpointer                    func_data);

struct _GdamBufferManagerInfo {
	guint			buffer_id;
	GdamChannel*		channel;
	char*			description;
	gint64			length;
	GdamBeatInfo*		beat_info;

	/* Set this if you never want the buffer deleted (for sine wave...) */
	gboolean		is_permanent;
	gboolean		is_readonly;

	gboolean		is_querying;
	gboolean		redo_query;

	GSList*			connections;
};

/* Used to receive notification for when buffers become available
 * and unavailable. */
struct _GdamBufferManagerNotifier {
	void		      (*buffer_add_callback)   (GdamBufferManagerInfo*,
	                                                gpointer user_data);
	void		      (*buffer_remove_callback)(GdamBufferManagerInfo*,
	                                                gpointer user_data);
	void		      (*buffer_change_callback)(GdamBufferManagerInfo*,
	                                                gpointer user_data);
	gpointer		user_data;
};
	                           
void           gdam_buffer_manager_init         (GdamChannel* channel);

void           gdam_buffer_set_default          (guint        buffer_id);
guint          gdam_buffer_get_default          ();
void           gdam_buffer_set_model_default    (GdamModel*   model,
                                                 guint        buffer_id);

/* the model must accept the "detach_from_buffer" signal and remove
 *        references at that point.
 * However, if you don't need the buffer id, you should call
 * gdam_buffer_manager_unref(rv, model). */
guint          gdam_buffer_manager_obtain_id    (GdamModel*   model);

/* A model uses this to indicate it no longer needs
 * the buffer_id (this must be called once per reference).
 * Don't do this if a detach_from_buffer has been delivered. */
void           gdam_buffer_manager_unref        (guint        buffer_id,
                                                 GdamModel*   model);

void           gdam_buffer_manager_refresh      (guint   buffer_id);

/* For duplicating an existing buffer id. */
void           gdam_buffer_manager_ref          (guint   buffer_id,
                                                 GdamModel*);

/* Give the manager an info to track -- it will automatically be deleted.
 * Also the length will be computed by the manager. */
void           gdam_buffer_manager_add_buffer   (GdamBufferManagerInfo* info);
/* Never give out this id again, but allow sources
 * which have a reference to keep it. */
void           gdam_buffer_manager_soft_destroy (guint buffer_id);

/* Deliver the "detach_from_buffer" signal to all referers,
 * and stop maintaining any reference to the buffer_id. */
void           gdam_buffer_manager_hard_destroy(guint buffer_id);

GdamBufferManagerInfo*  gdam_buffer_manager_info_by_id(guint buffer_id);
GdamBufferManagerInfo*  gdam_buffer_manager_info_by_desc(const char* desc);
gboolean       gdam_buffer_manager_is_readonly(guint buffer_id);

/* Used to track the buffers available in the manager. */
void           gdam_buffer_manager_subscribe   (GdamBufferManagerNotifier*);
void           gdam_buffer_manager_unsubscribe (GdamBufferManagerNotifier*);

/* Track just a single buffer. */
int            gdam_buffer_manager_connect     (int               buffer_id,
                                                GdamBufferChangedFunc func,
						gpointer          func_data);
void           gdam_buffer_manager_reconnect   (int               conn_id,
                                                int               new_buf_id);
void           gdam_buffer_manager_disconnect  (int               conn_id);

/* Cache an arbitrary source... */
void           gdam_buffer_manager_start_caching
				(GdamRequestBuilder*   request_builder,
				 int                   local_src_id,
				 GdamChannel*          channel,
				 gboolean              use_buffer_manager,
				 const char*           description,
			     void (*cached)(int buffer_id, gpointer user_data),
		             void (*cache_failed)(gpointer user_data),
				 gpointer              user_data);

/* Some common buffers... */
guint          gdam_buffer_manager_get_named(const char* named_buffer);

/* An array of strings as char*. */
GPtrArray*     gdam_buffer_manager_get_names();

void gdam_buffer_manager_set_bpm (guint buffer_id, float bpm);
void gdam_buffer_manager_set_first_beat (guint buffer_id, float first_beat);
/* Set the bpm based on the number of beats within the sample. */
void gdam_buffer_manager_set_num_beats (guint buffer_id, float num_beats);

#endif
