/*
    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_REQUEST_H_
#define __GDAM_REQUEST_H_

#include <glib.h>
#include <gdam/common/gdambuffer.h>
#include <gdam/common/gdamarg.h>

typedef struct _GdamRequestGetIntStruct GdamRequestGetIntStruct;
typedef struct _GdamRequestGet2IntStruct GdamRequestGet2IntStruct;
typedef struct _GdamRequestGetTimeStruct GdamRequestGetTimeStruct;
typedef struct _GdamRequestGetDataStruct GdamRequestGetDataStruct;

typedef void (*GdamRequestGotIntFunc) (gint       id,
                                       gpointer   user_data);
typedef void (*GdamRequestGotStringFunc)(const char* string,
                                       gpointer   user_data);
typedef void (*GdamRequestGot2IntFunc)(gint       int_a,
                                       gint       int_b,
                                       gpointer   user_data);
typedef void (*GdamRequestGotStringArrayFunc)
                                      (int        num_strings,
                                       char**     strings,
                                       gpointer   user_data);
typedef void (*GdamRequestGotTimeFunc)(GdamTime   id,
                                       gpointer   user_data);
typedef void (*GdamRequestGotArgsFunc)(int        num_args,
                                       GdamArg*   args,
                                       gpointer   user_data);
typedef void (*GdamRequestGotDataFunc)(int	  length,
				       gpointer   data,
                                       gpointer   user_data);

/* This function must free `int_array'. */
typedef void (*GdamRequestGetIntArrayFunc)
                                      (int        num_ints,
				       int*       int_array,
				       gpointer   user_data);

struct _GdamRequestGetIntStruct {
	gboolean		was_success;
	int			rv;
};
struct _GdamRequestGet2IntStruct {
	gboolean		was_success;
	int			rv[2];
};
struct _GdamRequestGetTimeStruct {
	gboolean		was_success;
	GdamTime		rv;
};
struct _GdamRequestGetDataStruct {
	gboolean		was_success;
	int			length;
	gpointer		data;
};

/* A GdamRequestGotIntFunc that fills a GdamRequestGetIntStruct*
 * as its user data. */
void     gdam_request_get_int(gint id, gpointer user_data);

/* A GdamRequestGot2IntFunc that fills a GdamRequestGet2IntStruct*
 * as its user data. */
void     gdam_request_get_2int(gint id, gint id2, gpointer user_data);

/* A GdamRequestGotTimeFunc that fills a GdamRequestGetTimeStruct*
 * as its user data. */
void     gdam_request_get_time(GdamTime, gpointer user_data);

/* A GdamRequestGotDataFunc that fills a GdamRequestGetDataStruct*
 * as its user data. */
void     gdam_request_get_data(int length, gpointer data, gpointer user_data);

/* A ghookfunc to be used to mark failure in a GdamRequestGet{Int/Time}Struct*,
 * or a gboolean*. */
void     gdam_request_get_failure(gpointer user_data);

/* A ghookfunc to be used to mark failure in a gboolean*. */
void     gdam_request_get_success(gpointer user_data);


typedef struct _GdamRequest GdamRequest;

struct _GdamRequest {
	GdamBuffer		request_command;

	/* for create requests */
	int			local_id;

	/* These fields may be used for function pointers
	 * with different prototypes. */
	GHookFunc		success;
	GHookFunc		failure;

	gpointer		user_data;

	gboolean	      (*marshal)(GdamRequest*             request,
	                                 GdamBuffer*              response);

	/* Generic subcomponents. */
	int			num_subs;
	gpointer*		subs;

	/* For waitable requests which have been added to the channel. */
	guint			request_id;

};

GdamRequest*   gdam_request_create_sink  (const char*             device_name,
                                          GdamRequestGotIntFunc   callback,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_feed_sink    (guint                   sink_id,
                                          guint                   source_id,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_close_sink   (guint                   sink_id,
                                          GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);
GdamRequest*   gdam_request_reopen_sink  (guint                   sink_id,
                                          GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_create       (int                     obj_type,
                                          const char*             type,
					  int                     local_id,
					  GdamRequestGotIntFunc   success,
					  GHookFunc               failure,
					  gpointer                user_data,
                                          int                     num_args,
					  ...);
GdamRequest*   gdam_request_create_v     (int                     obj_type,
                                          const char*             type,
					  int                     local_id,
                                          int                     num_args,
					  GdamArg*                args,
					  GdamRequestGotIntFunc   success,
					  GHookFunc               failure,
					  gpointer                user_data);
GdamRequest*   gdam_request_set_gen_args (int                      arena_id,
                                          int                      source_id,
					  int                      num_args,
                                          GdamArg*                 args,
                                          GHookFunc                success,
					  GHookFunc                failure,
					  gpointer                 user_data);
GdamRequest*   gdam_request_set_args     (int                      source_id,
					  int                      num_args,
                                          GdamArg*                 args,
                                          GHookFunc                success,
					  GHookFunc                failure,
					  gpointer                 user_data);

GdamRequest*   gdam_request_get_gen_args (int                      arena_id,
                                          int                      source_id,
					  int                      num_args,
					  const char* const*       arg_names,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);
GdamRequest*   gdam_request_get_args     (int                      source_id,
					  int                      num_args,
					  const char* const*       arg_names,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);

GdamRequest*   gdam_request_get_all_gen_args
                                         (int                      arena_id,
                                          int                      source_id,
					  gboolean                 only_vital,
					  gboolean                 deprecated,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);
GdamRequest*   gdam_request_get_all_args (int                      source_id,
					  gboolean                 only_vital,
					  gboolean                 deprecated,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);

GdamRequest*   gdam_request_call_function(int                      arena_id,
                                          int                      source_id,
					  const char*              func_name,
					  int                      num_args,
					  GdamArg*                 args_in,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);
GdamRequest*   gdam_request_call_class_function
                                         (const char*              class_name,
					  const char*              func_name,
					  int                      num_args,
					  GdamArg*                 args_in,
                                          GdamRequestGotArgsFunc   success,
					  GHookFunc                failure,
					  gpointer                 user_data);
GdamRequest*   gdam_request_set_log_level(int                      flags,
					  GHookFunc                success,
					  GHookFunc                failure,
					  gpointer                 user_data);

GdamRequest*   gdam_request_get_named_buffers
                                         (GdamRequestGotStringArrayFunc,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_add_mix      (guint                   mix_id,
                                          guint                   subsource_id,
					  GdamTime                when,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_ref          (guint                   arena_id,
                                          guint                   source_id,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_unref        (guint                   arena_id,
                                          guint                   source_id,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);
GdamRequest   *gdam_request_chat_message (const char             *username,
					  const char             *message,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest   *gdam_request_set_username (const char             *username,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);

/*
 * If sub_id is zero, then this should return the number
 * of samples output by the source.
 *
 * If sub_id is non-zero, then it must be a child
 * or source_id.
 *    This tells where in `source_id's notion of time
 *    the last read of `sub_id' has filled
 *    up to.  gdam_request_get_time(mix_id, sub_id)
 *        +   gdam_request_get_time(sub_id, 0)
 *    should allow you to start a song in perfect sync
 *    with the current one.
 */
GdamRequest*   gdam_request_source_time  (guint                   source_id,
                                          guint                   sub_id,
                                          GdamRequestGotTimeFunc  callback,
					  GHookFunc               failure,
					  gpointer                user_data);

GdamRequest*   gdam_request_detach_source(guint                   source_id,
                                          GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);
GdamRequest*   gdam_request_seek_relative(guint                   source_id,
					  GdamTime                when,
					  GHookFunc               success,
					  GHookFunc               failure,
					  gpointer                user_data);
GdamRequest*   gdam_request_get_server_side_int 
                                          (const char*            namespac,
                                           const char*            name,
                                           GdamRequestGotIntFunc  callback,
					   GHookFunc              failure,
					   gpointer               user_data);

/* Used to build a "synchronize" argument. */
void           gdam_request_helper_build_sync
                                          (int                    mobile_id,
                                           int                    fixed_id,
					   gdouble                mobile_bpm,
					   gdouble                mobile_start,
					   gdouble                fixed_bpm,
					   gdouble                fixed_start,
					   gint64*		  out_6);

GdamRequest*   gdam_request_synchronize   (int                    mobile_id,
                                           int                    fixed_id,
					   gdouble                mobile_bpm,
					   gdouble                mobile_start,
					   gdouble                fixed_bpm,
					   gdouble                fixed_start,
                                           GHookFunc              success,
					   GHookFunc              failure,
					   gpointer               user_data);
GdamRequest*   gdam_request_sync_preview  (int                    mobile_id,
                                           int                    fixed_id,
					   gdouble                mobile_bpm,
					   gdouble                mobile_start,
					   gdouble                fixed_bpm,
					   gdouble                fixed_start,
                                           GdamRequestGotTimeFunc success,
					   GHookFunc              failure,
					   gpointer               user_data);

GdamRequest*   gdam_request_get_buffer_profile
                                          (int                    buffer_id,
                                           int                    profile_mode,
					   int                    start,
					   int                    length,
					   int                    num_output,
					   GdamRequestGetIntArrayFunc success,
					   GHookFunc              failure,
					   gpointer               user_data);
/*
 * Subscription requests.
 */
GdamRequest*   gdam_request_subscribe_source_ended
                                          (int                     source_id,
                                           GdamRequestGotIntFunc   callback,
					   GHookFunc               failure,
					   gpointer                user_data);
GdamRequest*   gdam_request_subscribe_source_timer
                                          (int                     source_id,
					   int                     period,
                                           GdamRequestGotIntFunc   callback,
					   GHookFunc               failure,
					   gpointer                user_data);
GdamRequest*   gdam_request_unsubscribe   (int                     source_id,
                                           GHookFunc               success,
					   GHookFunc               failure,
					   gpointer                user_data);

/* The callback is invoked with buffer_id, event_connection_id. */
GdamRequest*   gdam_request_start_caching (int                     source_id,
                                           GdamRequestGot2IntFunc  callback,
					   GHookFunc               failure,
					   gpointer                user_data);
GdamRequest*   gdam_request_uncache       (int                     buffer_id,
                                           GHookFunc               success,
					   GHookFunc               failure,
					   gpointer                user_data);

/* Will g_free `requests' array... watch out! */
GdamRequest*   gdam_request_package_v     (int                     num_request,
					   GdamRequest**           requests,
                                           GdamRequestGotIntFunc   callback,
					   GHookFunc               failure,
                                           gpointer                user_data);


void           gdam_request_destroy       (GdamRequest*            request);

/* Deprecated. use s/_source// instead. */
GdamRequest*   gdam_request_create_source(const char*             type,
					  int                     local_id,
					  GdamRequestGotIntFunc   success,
					  GHookFunc               failure,
					  gpointer                user_data,
                                          int                     num_args,
					  ...);
GdamRequest*   gdam_request_create_source_v(const char*             type,
					  int                     local_id,
                                          int                     num_args,
					  GdamArg*                args,
					  GdamRequestGotIntFunc   success,
					  GHookFunc               failure,
					  gpointer                user_data);
#endif
