/*
    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_INPUT_DEVICE_H_
#define __GDAM_INPUT_DEVICE_H_



typedef struct _GdamInputDevice GdamInputDevice;
typedef struct _GdamInputDeviceClass GdamInputDeviceClass;
typedef struct _GdamInputTrap GdamInputTrap;

#include "gdammodel.h"
#include "gdaminputevent.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

GtkType gdam_input_device_get_type();
#define GDAM_TYPE_INPUT_DEVICE			(gdam_input_device_get_type ())
#define GDAM_INPUT_DEVICE(obj)              (GTK_CHECK_CAST ((obj), GDAM_TYPE_INPUT_DEVICE, GdamInputDevice))
#define GDAM_INPUT_DEVICE_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GDAM_TYPE_INPUT_DEVICE, GdamInputDeviceClass))
#define GDAM_IS_INPUT_DEVICE(obj)           (GTK_CHECK_TYPE ((obj), GDAM_TYPE_INPUT_DEVICE))
#define GDAM_IS_INPUT_DEVICE_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GDAM_TYPE_INPUT_DEVICE))


/* A function you can register to receive a particular subsets
 * of the input event stream.  We call this a ``hook'';  you
 * make a hook with ``gdam_input_device_connect''.
 *
 * Return whether the event was `handled' meaning `do not propagate'.
 */
typedef  gboolean (*GdamInputHookFunc)    (GdamInputEvent     *input_event,
                                           gpointer            user_data);

/* A function you can use to iterate over all known traps. (used by ui code) */
typedef  void     (*GdamInputTrapIterator)(GdamInputTrap      *trap,
                                           gpointer            iter_data);

/*
 *                         GdamInputTrap
 *
 * This should correspond to a particular knob or slider usually,
 * with the list of action to run on that event.
 */
struct _GdamInputTrap {
	GdamInputEvent*		event;

	char*			name;
	gboolean		name_is_generated;
	guint			trap_id;

	GSList*			hooks;
};
GdamInputTrap*   gdam_input_trap_find        (GdamInputEvent*    input_event);
GdamInputTrap   *gdam_input_trap_find_or_create
                                             (GdamInputEvent    *input_event);
guint            gdam_input_hook_connect     (GdamInputTrap     *trap,
				              GdamInputHookFunc  hook_func,
				              GDestroyNotify     destroy,
                                              gpointer           user_data,
                                              GtkObject         *alive_object);
void             gdam_input_hook_disconnect  (guint              hook_id);
void             gdam_input_hook_block       (guint              hook_id);
void             gdam_input_hook_unblock     (guint              hook_id);

GdamInputTrap   *gdam_input_trap_get_by_id   (guint              trap_id);
GdamInputTrap   *gdam_input_trap_get_default();
void             gdam_input_trap_set_default(GdamInputTrap      *trap);

/* device may be NULL, indicating that the iteration should be
 * over all devices.
 */
void             gdam_input_trap_forall      (GdamInputDevice*   device,
					      GdamInputTrapIterator iter_func,
					      gpointer           iter_data);


/* Note:  if `input_trap' is NULL, then the appropriate trap
 *        is found from the input_event's device. 
 *
 * Returns whether the event was handled (ie had a hook which returned TRUE)
 */
gboolean         gdam_input_trap_emit        (GdamInputTrap     *input_trap,
                                              GdamInputEvent    *input_event);
void             gdam_input_trap_set_name    (GdamInputTrap     *trap,
                                              const char        *name);
const char      *gdam_input_trap_get_name    (GdamInputTrap     *trap);

/*
 * The Devices themselves.
 */

struct _GdamInputDeviceClass {
  GtkObjectClass	  object_class;

	/* Called when a new button or knob is detected. */
  void                  (*new_trap)    (GdamInputDevice  *input_device, 
					GdamInputTrap    *input_trap);

  gboolean              (*event)       (GdamInputDevice  *input_device, 
					GdamInputEvent   *event,
					GdamInputTrap    *input_trap);

  gboolean              (*open)        (GdamInputDevice  *input_device);
  void                  (*close)       (GdamInputDevice  *input_device);

};
struct _GdamInputDevice 
{
  GtkObject               object;
  char                   *device_name;
  GSList                 *traps;
};

GdamInputDevice* gdam_input_device_get_by_name(const char* name);
GdamInputDevice* gdam_input_device_get_by_type(const char* type);


guint gdam_input_hook_connect_range  (GdamInputTrap   *trap,
                                      GtkObject       *object,
                                      const char      *arg_name,
                                      gdouble          min_value,
				      gdouble          max_value,
				      gboolean         is_logarithmic,
				      gboolean         is_exponent);
guint gdam_input_hook_connect_const  (GdamInputTrap   *trap,
                                      GtkObject       *object,
                                      GdamArg         *arg);
guint gdam_input_hook_connect_const_full(GdamInputTrap*   trap,
                                         GtkObject*       object,
				         GdamArg*         arg,
					 gboolean	  is_delta,
					 gboolean         is_factor);
guint gdam_input_hook_connect_variable (GdamInputTrap   *trap,
                                        GtkObject       *object,
				        GdamArg         *arg,
				        gdouble		factor,
				        int		is_delta);
guint gdam_input_hook_connect_signal (GdamInputTrap   *trap,
                                      GtkObject       *object,
                                      const char      *signal_name,
                                      const char      *handler_name);

/* Configure the global database of input devices. */
void     gdam_input_device_configure (const char      *dev_name,
                                      const char      *patch_filename,
                                      const char      *device_type);
gboolean gdam_input_device_load_database(const char   *database);


gboolean gdam_input_device_open(GdamInputDevice *input_device,
                                const char      *device_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
