/*
 *  Application interface library for the ALSA driver
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
 *
 *
 *   This library is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2 of
 *   the License, or (at your option) any later version.
 *
 *   This program 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 Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifndef __ASOUNDLIB_H
#define __ASOUNDLIB_H

#include <linux/asound.h>
#include <linux/asequencer.h>
#include <unistd.h>
#include <fcntl.h>

#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
/*
 *  version.h
 */

#define SND_LIB_MAJOR		0
#define SND_LIB_MINOR		5
#define SND_LIB_SUBMINOR	9
#define SND_LIB_VERSION		((SND_LIB_MAJOR<<16)|\
				 (SND_LIB_MINOR<<8)|\
				  SND_LIB_SUBMINOR)
#define SND_LIB_VERSION_STR	"0.5.9"

/* OBSOLETE DEFINES WHICH WON'T BE IN 0.3.0 FINAL!!! */
#define SOUNDLIB_VERSION_MAJOR		SND_LIB_MAJOR
#define SOUNDLIB_VERSION_MINOR		SND_LIB_MINOR
#define SOUNDLIB_VERSION_SUBMINOR	SND_LIB_SUBMINOR

/*
 *  error.h
 */

#define SND_ERROR_BEGIN				500000
#define SND_ERROR_INCOMPATIBLE_VERSION		(SND_ERROR_BEGIN+0)

#ifdef __cplusplus
extern "C" {
#endif

const char *snd_strerror( int errnum );

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                              control.h                                   *
 *                          Control Interface                               *
 *                                                                          *
 ****************************************************************************/

typedef struct snd_ctl_callbacks {
	void *private_data;	/* should be used by an application */
	void (*rebuild) (void *private_data);
	void (*xswitch) (void *private_data, int cmd,
			 int iface, int device, int channel,
			 snd_switch_list_item_t *item);
	void *reserved[29];	/* reserved for the future use - must be NULL!!! */
} snd_ctl_callbacks_t;

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_ctl snd_ctl_t;

int snd_card_load(int card);
int snd_cards(void);
unsigned int snd_cards_mask(void);
int snd_card_name(const char *name);
int snd_card_get_name(int card, char **name);
int snd_card_get_longname(int card, char **name);

int snd_defaults_card(void);
int snd_defaults_mixer_card(void);
int snd_defaults_mixer_device(void);
int snd_defaults_pcm_card(void);
int snd_defaults_pcm_device(void);
int snd_defaults_rawmidi_card(void);
int snd_defaults_rawmidi_device(void);

int snd_ctl_open(snd_ctl_t **handle, int card);
int snd_ctl_close(snd_ctl_t *handle);
int snd_ctl_file_descriptor(snd_ctl_t *handle);
int snd_ctl_hw_info(snd_ctl_t *handle, struct snd_ctl_hw_info *info);
int snd_ctl_switch_list(snd_ctl_t *handle, snd_switch_list_t * list);
int snd_ctl_switch_read(snd_ctl_t *handle, snd_switch_t * sw);
int snd_ctl_switch_write(snd_ctl_t *handle, snd_switch_t * sw);
int snd_ctl_hwdep_info(snd_ctl_t *handle, int dev, snd_hwdep_info_t * info);
int snd_ctl_pcm_info(snd_ctl_t *handle, int dev, snd_pcm_info_t * info);
int snd_ctl_pcm_channel_info(snd_ctl_t *handle, int dev, int channel, int subdev, snd_pcm_channel_info_t * info);
int snd_ctl_pcm_channel_prefer_subdevice(snd_ctl_t *handle, int dev, int channel, int subdev);
int snd_ctl_mixer_info(snd_ctl_t *handle, int dev, snd_mixer_info_t * info);
int snd_ctl_rawmidi_info(snd_ctl_t *handle, int dev, snd_rawmidi_info_t * info);
int snd_ctl_read(snd_ctl_t *handle, snd_ctl_callbacks_t * callbacks);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                               mixer.h                                    *
 *                           Mixer Interface                                *
 *                                                                          *
 ****************************************************************************/

typedef struct snd_mixer_callbacks {
	void *private_data;	/* should be used with an application */
	void (*rebuild) (void *private_data);
	void (*element) (void *private_data, int cmd, snd_mixer_eid_t *eid);
	void (*group) (void *private_data, int cmd, snd_mixer_gid_t *gid);
	void *reserved[28];	/* reserved for the future use - must be NULL!!! */
} snd_mixer_callbacks_t;

typedef struct {
	char *name;
	int weight;
} snd_mixer_weight_entry_t;

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_mixer snd_mixer_t;

int snd_mixer_open(snd_mixer_t **handle, int card, int device);
int snd_mixer_close(snd_mixer_t *handle);
int snd_mixer_file_descriptor(snd_mixer_t *handle);
int snd_mixer_info(snd_mixer_t *handle, snd_mixer_info_t * info);
int snd_mixer_elements(snd_mixer_t *handle, snd_mixer_elements_t * elements);
int snd_mixer_routes(snd_mixer_t *handle, snd_mixer_routes_t * routes);
int snd_mixer_groups(snd_mixer_t *handle, snd_mixer_groups_t * groups);
int snd_mixer_group_read(snd_mixer_t *handle, snd_mixer_group_t * group);
int snd_mixer_group_write(snd_mixer_t *handle, snd_mixer_group_t * group);
int snd_mixer_element_info(snd_mixer_t *handle, snd_mixer_element_info_t * info);
int snd_mixer_element_read(snd_mixer_t *handle, snd_mixer_element_t * element);
int snd_mixer_element_write(snd_mixer_t *handle, snd_mixer_element_t * element);
int snd_mixer_get_filter(snd_mixer_t *handle, snd_mixer_filter_t * filter);
int snd_mixer_put_filter(snd_mixer_t *handle, snd_mixer_filter_t * filter);
int snd_mixer_read(snd_mixer_t *handle, snd_mixer_callbacks_t * callbacks);

void snd_mixer_set_bit(unsigned int *bitmap, int bit, int val);
int snd_mixer_get_bit(unsigned int *bitmap, int bit);

const char *snd_mixer_channel_name(int channel);

int snd_mixer_element_has_info(snd_mixer_eid_t *eid);
int snd_mixer_element_info_build(snd_mixer_t *handle, snd_mixer_element_info_t * info);
int snd_mixer_element_info_free(snd_mixer_element_info_t * info);
int snd_mixer_element_has_control(snd_mixer_eid_t *eid);
int snd_mixer_element_build(snd_mixer_t *handle, snd_mixer_element_t * element);
int snd_mixer_element_free(snd_mixer_element_t * element);

void snd_mixer_sort_eid_name_index(snd_mixer_eid_t *list, int count);
void snd_mixer_sort_eid_table(snd_mixer_eid_t *list, int count, snd_mixer_weight_entry_t *table);
void snd_mixer_sort_gid_name_index(snd_mixer_gid_t *list, int count);
void snd_mixer_sort_gid_table(snd_mixer_gid_t *list, int count, snd_mixer_weight_entry_t *table);
extern snd_mixer_weight_entry_t *snd_mixer_default_weights;

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                                pcm.h                                     *
 *                        Digital Audio Interface                           *
 *                                                                          *
 ****************************************************************************/

#define SND_PCM_OPEN_PLAYBACK		0x0001
#define SND_PCM_OPEN_CAPTURE		0x0002
#define SND_PCM_OPEN_DUPLEX		0x0003
#define SND_PCM_OPEN_NONBLOCK		0x1000

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_pcm snd_pcm_t;
typedef struct snd_pcm_loopback snd_pcm_loopback_t;

int snd_pcm_open(snd_pcm_t **handle, int card, int device, int mode);
int snd_pcm_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode);
int snd_pcm_close(snd_pcm_t *handle);
int snd_pcm_file_descriptor(snd_pcm_t *handle, int channel);
int snd_pcm_nonblock_mode(snd_pcm_t *handle, int nonblock);
int snd_pcm_info(snd_pcm_t *handle, snd_pcm_info_t * info);
int snd_pcm_channel_info(snd_pcm_t *handle, snd_pcm_channel_info_t * info);
int snd_pcm_channel_params(snd_pcm_t *handle, snd_pcm_channel_params_t * params);
int snd_pcm_channel_setup(snd_pcm_t *handle, snd_pcm_channel_setup_t * setup);
int snd_pcm_channel_status(snd_pcm_t *handle, snd_pcm_channel_status_t * status);
int snd_pcm_playback_prepare(snd_pcm_t *handle);
int snd_pcm_capture_prepare(snd_pcm_t *handle);
int snd_pcm_channel_prepare(snd_pcm_t *handle, int channel);
int snd_pcm_playback_go(snd_pcm_t *handle);
int snd_pcm_capture_go(snd_pcm_t *handle);
int snd_pcm_channel_go(snd_pcm_t *handle, int channel);
int snd_pcm_sync_go(snd_pcm_t *handle, snd_pcm_sync_t *sync);
int snd_pcm_playback_drain(snd_pcm_t *handle);
int snd_pcm_playback_flush(snd_pcm_t *handle);
int snd_pcm_capture_flush(snd_pcm_t *handle);
int snd_pcm_channel_flush(snd_pcm_t *handle, int channel);
int snd_pcm_playback_pause(snd_pcm_t *handle, int enable);
ssize_t snd_pcm_transfer_size(snd_pcm_t *handle, int channel);
ssize_t snd_pcm_write(snd_pcm_t *handle, const void *buffer, size_t size);
ssize_t snd_pcm_read(snd_pcm_t *handle, void *buffer, size_t size);
ssize_t snd_pcm_writev(snd_pcm_t *pcm, const struct iovec *vector, int count);
ssize_t snd_pcm_readv(snd_pcm_t *pcm, const struct iovec *vector, int count);
int snd_pcm_mmap(snd_pcm_t *handle, int channel, snd_pcm_mmap_control_t **control, void **buffer);
int snd_pcm_munmap(snd_pcm_t *handle, int channel);

/* misc */

int snd_pcm_format_signed(int format);
int snd_pcm_format_unsigned(int format);
int snd_pcm_format_linear(int format);
int snd_pcm_format_little_endian(int format);
int snd_pcm_format_big_endian(int format);
int snd_pcm_format_width(int format);			/* in bits */
int snd_pcm_format_physical_width(int format);		/* in bits */
int snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
ssize_t snd_pcm_format_size(int format, size_t samples);
unsigned char snd_pcm_format_silence(int format);
const char *snd_pcm_get_format_name(int format);

#ifdef __cplusplus
}
#endif

/*
 *  Plug-In interface (ala C++)
 */

typedef struct snd_stru_pcm_plugin snd_pcm_plugin_t;

typedef enum {
	INIT = 0,
	PREPARE = 1,
	DRAIN = 2,
	FLUSH = 3
} snd_pcm_plugin_action_t;

#define snd_pcm_plugin_extra_data(plugin) (((char *)plugin) + sizeof(*plugin))

struct snd_stru_pcm_plugin {
	char *name;				   /* plug-in name */
	int (*transfer_src_ptr)(snd_pcm_plugin_t *plugin, char **src_ptr, size_t *src_size);
	ssize_t (*transfer)(snd_pcm_plugin_t *plugin,
			    char *src_ptr, size_t src_size,
			    char *dst_ptr, size_t dst_size);
	ssize_t (*src_size)(snd_pcm_plugin_t *plugin, size_t dst_size);
	ssize_t (*dst_size)(snd_pcm_plugin_t *plugin, size_t src_size);
	int (*action)(snd_pcm_plugin_t *plugin, snd_pcm_plugin_action_t action);
	snd_pcm_plugin_t *prev;
	snd_pcm_plugin_t *next;
	void *private_data;
	void (*private_free)(snd_pcm_plugin_t *plugin, void *private_data);
};

snd_pcm_plugin_t *snd_pcm_plugin_build(const char *name, int extra);
int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_clear(snd_pcm_t *handle, int channel);
int snd_pcm_plugin_insert(snd_pcm_t *handle, int channel, snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_append(snd_pcm_t *handle, int channel, snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_remove_to(snd_pcm_t *handle, int channel, snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_remove_first(snd_pcm_t *handle, int channel);
snd_pcm_plugin_t *snd_pcm_plugin_first(snd_pcm_t *handle, int channel);
snd_pcm_plugin_t *snd_pcm_plugin_last(snd_pcm_t *handle, int channel);
ssize_t snd_pcm_plugin_transfer_size(snd_pcm_t *handle, int channel, size_t drv_size);
ssize_t snd_pcm_plugin_hardware_size(snd_pcm_t *handle, int channel, size_t trf_size);
int snd_pcm_plugin_info(snd_pcm_t *handle, snd_pcm_channel_info_t *info);
int snd_pcm_plugin_params(snd_pcm_t *handle, snd_pcm_channel_params_t *params);
int snd_pcm_plugin_setup(snd_pcm_t *handle, snd_pcm_channel_setup_t *setup);
int snd_pcm_plugin_status(snd_pcm_t *handle, snd_pcm_channel_status_t *status);
int snd_pcm_plugin_prepare(snd_pcm_t *handle, int channel);
int snd_pcm_plugin_playback_drain(snd_pcm_t *handle);
int snd_pcm_plugin_flush(snd_pcm_t *handle, int channel);
int snd_pcm_plugin_pointer(snd_pcm_t *pcm, int channel, void **ptr, size_t *size);
ssize_t snd_pcm_plugin_write(snd_pcm_t *handle, const void *buffer, size_t size);
ssize_t snd_pcm_plugin_read(snd_pcm_t *handle, void *bufer, size_t size);

/*
 *  Plug-In constructors
 */

/* basic I/O */
int snd_pcm_plugin_build_stream(snd_pcm_t *handle, int channel, snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_block(snd_pcm_t *handle, int channel, snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_mmap(snd_pcm_t *handle, int channel, snd_pcm_plugin_t **r_plugin);
/* conversion plugins */
int snd_pcm_plugin_build_interleave(snd_pcm_format_t *src_format,
				    snd_pcm_format_t *dst_format,
				    snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_linear(snd_pcm_format_t *src_format,
				snd_pcm_format_t *dst_format,
				snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_mulaw(snd_pcm_format_t *src_format,
			       snd_pcm_format_t *dst_format,
			       snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_alaw(snd_pcm_format_t *src_format,
			      snd_pcm_format_t *dst_format,
			      snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_adpcm(snd_pcm_format_t *src_format,
			       snd_pcm_format_t *dst_format,
			       snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_rate(snd_pcm_format_t *src_format,
			      snd_pcm_format_t *dst_format,
			      snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_voices(snd_pcm_format_t *src_format,
				snd_pcm_format_t *dst_format,
				snd_pcm_plugin_t **r_plugin);
int snd_pcm_plugin_build_volbal(snd_pcm_format_t *src_format,
				snd_pcm_format_t *dst_format,
				int *ttable,
				snd_pcm_plugin_t **r_plugin);

/*
 *  Loopback interface
 */

#define SND_PCM_LB_OPEN_PLAYBACK	0
#define SND_PCM_LB_OPEN_CAPTURE		1

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_pcm_loopback_callbacks {
	void *private_data;		/* should be used with an application */
	size_t max_buffer_size;		/* zero = default (64kB) */
	void (*data) (void *private_data, char *buffer, size_t count);
	void (*position_change) (void *private_data, unsigned int pos);
	void (*format_change) (void *private_data, snd_pcm_format_t *format);
	void (*silence) (void *private_data, size_t count);
	void *reserved[31];		/* reserved for the future use - must be NULL!!! */
} snd_pcm_loopback_callbacks_t;

int snd_pcm_loopback_open(snd_pcm_loopback_t **handle, int card, int device, int subdev, int mode);
int snd_pcm_loopback_close(snd_pcm_loopback_t *handle);
int snd_pcm_loopback_file_descriptor(snd_pcm_loopback_t *handle);
int snd_pcm_loopback_block_mode(snd_pcm_loopback_t *handle, int enable);
int snd_pcm_loopback_stream_mode(snd_pcm_loopback_t *handle, int mode);
int snd_pcm_loopback_format(snd_pcm_loopback_t *handle, snd_pcm_format_t * format);
int snd_pcm_loopback_status(snd_pcm_loopback_t *handle, snd_pcm_loopback_status_t * status);
ssize_t snd_pcm_loopback_read(snd_pcm_loopback_t *handle, snd_pcm_loopback_callbacks_t * callbacks);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                              rawmidi.h                                   *
 *                          RawMIDI interface                               *
 *                                                                          *
 ****************************************************************************/

#define SND_RAWMIDI_OPEN_OUTPUT		(O_WRONLY)
#define SND_RAWMIDI_OPEN_OUTPUT_APPEND	(O_WRONLY|O_APPEND|O_NONBLOCK)
#define SND_RAWMIDI_OPEN_INPUT		(O_RDONLY)
#define SND_RAWMIDI_OPEN_DUPLEX		(O_RDWR)
#define SND_RAWMIDI_OPEN_DUPLEX_APPEND	(O_RDWR|O_APPEND|O_NONBLOCK)
#define SND_RAWMIDI_OPEN_NONBLOCK	(O_NONBLOCK)

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_rawmidi snd_rawmidi_t;

int snd_rawmidi_open(snd_rawmidi_t **handle, int card, int device, int mode);
int snd_rawmidi_close(snd_rawmidi_t *handle);
int snd_rawmidi_file_descriptor(snd_rawmidi_t *handle);
int snd_rawmidi_block_mode(snd_rawmidi_t *handle, int enable);
int snd_rawmidi_info(snd_rawmidi_t *handle, snd_rawmidi_info_t * info);
int snd_rawmidi_channel_params(snd_rawmidi_t *handle, snd_rawmidi_params_t * params);
int snd_rawmidi_channel_status(snd_rawmidi_t *handle, snd_rawmidi_status_t * status);
int snd_rawmidi_output_drain(snd_rawmidi_t *handle);
int snd_rawmidi_output_flush(snd_rawmidi_t *handle);
int snd_rawmidi_input_flush(snd_rawmidi_t *handle);
int snd_rawmidi_channel_flush(snd_rawmidi_t *handle, int channel);
ssize_t snd_rawmidi_write(snd_rawmidi_t *handle, const void *buffer, size_t size);
ssize_t snd_rawmidi_read(snd_rawmidi_t *handle, void *buffer, size_t size);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                               timer.h                                    *
 *                           Timer interface                                *
 *                                                                          *
 ****************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_timer snd_timer_t;

int snd_timer_open(snd_timer_t **handle);
int snd_timer_close(snd_timer_t *handle);
int snd_timer_file_descriptor(snd_timer_t *handle);
int snd_timer_general_info(snd_timer_t *handle, snd_timer_general_info_t * info);
int snd_timer_select(snd_timer_t *handle, snd_timer_select_t *tselect);
int snd_timer_info(snd_timer_t *handle, snd_timer_info_t *timer);
int snd_timer_params(snd_timer_t *handle, snd_timer_params_t *params);
int snd_timer_status(snd_timer_t *handle, snd_timer_status_t *status);
int snd_timer_start(snd_timer_t *handle);
int snd_timer_stop(snd_timer_t *handle);
int snd_timer_continue(snd_timer_t *handle);
ssize_t snd_timer_read(snd_timer_t *handle, void *buffer, size_t size);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                               hwdep.h                                    *
 *                     Hardware depedent interface                          *
 *                                                                          *
 ****************************************************************************/

#define SND_HWDEP_OPEN_READ		(O_RDONLY)
#define SND_HWDEP_OPEN_WRITE		(O_WRONLY)
#define SND_HWDEP_OPEN_DUPLEX		(O_RDWR)
#define SND_HWDEP_OPEN_NONBLOCK		(O_NONBLOCK)

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_hwdep snd_hwdep_t;

int snd_hwdep_open(snd_hwdep_t **handle, int card, int device, int mode);
int snd_hwdep_close(snd_hwdep_t *handle);
int snd_hwdep_file_descriptor(snd_hwdep_t *handle);
int snd_hwdep_block_mode(snd_hwdep_t *handle, int enable);
int snd_hwdep_info(snd_hwdep_t *handle, snd_hwdep_info_t * info);
int snd_hwdep_ioctl(snd_hwdep_t *handle, int request, void * arg);
ssize_t snd_hwdep_write(snd_hwdep_t *handle, const void *buffer, size_t size);
ssize_t snd_hwdep_read(snd_hwdep_t *handle, void *buffer, size_t size);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                                seq.h                                     *
 *                              Sequencer                                   *
 *                                                                          *
 ****************************************************************************/

#define SND_SEQ_OPEN_OUT	(O_WRONLY)
#define SND_SEQ_OPEN_IN		(O_RDONLY)
#define SND_SEQ_OPEN		(O_RDWR)

#ifdef __cplusplus
extern "C" {
#endif

typedef struct snd_seq snd_seq_t;

int snd_seq_open(snd_seq_t **handle, int mode);
int snd_seq_close(snd_seq_t *handle);
int snd_seq_file_descriptor(snd_seq_t *handle);
int snd_seq_block_mode(snd_seq_t *handle, int enable);
int snd_seq_client_id(snd_seq_t *handle);
int snd_seq_output_buffer_size(snd_seq_t *handle);
int snd_seq_input_buffer_size(snd_seq_t *handle);
int snd_seq_resize_output_buffer(snd_seq_t *handle, int size);
int snd_seq_resize_input_buffer(snd_seq_t *handle, int size);
int snd_seq_system_info(snd_seq_t *handle, snd_seq_system_info_t *info);
int snd_seq_get_client_info(snd_seq_t *handle, snd_seq_client_info_t *info);
int snd_seq_get_any_client_info(snd_seq_t *handle, int client, snd_seq_client_info_t *info);
int snd_seq_set_client_info(snd_seq_t *handle, snd_seq_client_info_t *info);
int snd_seq_create_port(snd_seq_t *handle, snd_seq_port_info_t *info);
int snd_seq_delete_port(snd_seq_t *handle, snd_seq_port_info_t *info);
int snd_seq_get_port_info(snd_seq_t *handle, int port, snd_seq_port_info_t *info);
int snd_seq_get_any_port_info(snd_seq_t *handle, int client, int port, snd_seq_port_info_t *info);
int snd_seq_set_port_info(snd_seq_t *handle, int port, snd_seq_port_info_t *info);
int snd_seq_get_port_subscription(snd_seq_t *handle, snd_seq_port_subscribe_t *sub);
int snd_seq_subscribe_port(snd_seq_t *handle, snd_seq_port_subscribe_t *sub);
int snd_seq_unsubscribe_port(snd_seq_t *handle, snd_seq_port_subscribe_t *sub);
int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subs_t * subs);
int snd_seq_get_queue_status(snd_seq_t *handle, int q, snd_seq_queue_status_t *status);
int snd_seq_get_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
int snd_seq_set_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo);
int snd_seq_get_queue_owner(snd_seq_t *handle, int q, snd_seq_queue_owner_t *owner);
int snd_seq_set_queue_owner(snd_seq_t *handle, int q, snd_seq_queue_owner_t *owner);
int snd_seq_get_queue_timer(snd_seq_t *handle, int q, snd_seq_queue_timer_t *timer);
int snd_seq_set_queue_timer(snd_seq_t *handle, int q, snd_seq_queue_timer_t *timer);
#ifdef use_seqsync
int snd_seq_get_queue_sync(snd_seq_t *handle, int q, snd_seq_queue_sync_t *sync);
int snd_seq_set_queue_sync(snd_seq_t *handle, int q, snd_seq_queue_sync_t *sync);
#endif
int snd_seq_get_queue_client(snd_seq_t *handle, int q, snd_seq_queue_client_t *queue);
int snd_seq_set_queue_client(snd_seq_t *handle, int q, snd_seq_queue_client_t *queue);
int snd_seq_alloc_named_queue(snd_seq_t *seq, char *name);
int snd_seq_alloc_queue(snd_seq_t *handle);
int snd_seq_free_queue(snd_seq_t *handle, int q);
int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info);
int snd_seq_get_named_queue(snd_seq_t *seq, char *name);
int snd_seq_get_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info);
int snd_seq_set_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info);
int snd_seq_query_next_client(snd_seq_t *handle, snd_seq_client_info_t * info);
int snd_seq_query_next_port(snd_seq_t *handle, snd_seq_port_info_t * info);

/* event routines */
snd_seq_event_t *snd_seq_create_event(void);
int snd_seq_free_event(snd_seq_event_t *ev);
int snd_seq_event_length(snd_seq_event_t *ev);
int snd_seq_event_output(snd_seq_t *handle, snd_seq_event_t *ev);
int snd_seq_event_output(snd_seq_t *handle, snd_seq_event_t *ev);
int snd_seq_event_output_buffer(snd_seq_t *handle, snd_seq_event_t *ev);
int snd_seq_event_output_direct(snd_seq_t *handle, snd_seq_event_t *ev);
int snd_seq_event_input(snd_seq_t *handle, snd_seq_event_t **ev);
int snd_seq_event_input_pending(snd_seq_t *seq, int fetch_sequencer);
int snd_seq_event_input_selective(snd_seq_t *seq, snd_seq_event_t **ev, int type, int blocking);
int snd_seq_flush_output(snd_seq_t *handle);
int snd_seq_event_output_pending(snd_seq_t *seq);
int snd_seq_extract_output(snd_seq_t *handle, snd_seq_event_t **ev);
int snd_seq_drain_output(snd_seq_t *handle);
int snd_seq_drain_output_buffer(snd_seq_t *handle);
int snd_seq_drain_input(snd_seq_t *handle);
int snd_seq_drain_input_buffer(snd_seq_t *handle);
int snd_seq_remove_events(snd_seq_t *handle, snd_seq_remove_events_t *info);
/* misc */
void snd_seq_set_bit(int nr, void *array);
int snd_seq_change_bit(int nr, void *array);
int snd_seq_get_bit(int nr, void *array);

#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                      Sequencer Middle Level                              *
 *                                                                          *
 ****************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/* initialize event record */
void snd_seq_ev_clear(snd_seq_event_t *ev);

/* set destination - following three macros are exclusive */
  /* explicit destination */
void snd_seq_ev_set_dest(snd_seq_event_t *ev, int client, int port);
  /* to subscribers */
void snd_seq_ev_set_subs(snd_seq_event_t *ev);
  /* broadcast to all clients/ports */
void snd_seq_ev_set_broadcast(snd_seq_event_t *ev);

/* set source port */
void snd_seq_ev_set_source(snd_seq_event_t *ev, int port);

/* set scheduling - following three macros are exclusive */
  /* direct event passing without enqueued */
void snd_seq_ev_set_direct(snd_seq_event_t *ev);
  /* scheduled on tick-queue */
void snd_seq_ev_schedule_tick(snd_seq_event_t *ev, int q, int relative,
			      snd_seq_tick_time_t tick);
  /* scheduled on real-time-queue */
void snd_seq_ev_schedule_real(snd_seq_event_t *ev, int q, int relative,
			      snd_seq_real_time_t *time);

/* set event priority (optional) */
void snd_seq_ev_set_priority(snd_seq_event_t *ev, int high_prior);

/* set event data type - following three macros are exclusive */
  /* fixed size event */
void snd_seq_ev_set_fixed(snd_seq_event_t *ev);
  /* variable size event */
void snd_seq_ev_set_variable(snd_seq_event_t *ev, int len, void *ptr);
  /* variable size event - user memory space */
void snd_seq_ev_set_varusr(snd_seq_event_t *ev, int len, void *ptr);

/* set queue control event data */
/* destination is overwritten to Timer port (0:0) */
int snd_seq_ev_set_queue_start(snd_seq_event_t *ev, int q);
int snd_seq_ev_set_queue_stop(snd_seq_event_t *ev, int q);
int snd_seq_ev_set_queue_continue(snd_seq_event_t *ev, int q);
int snd_seq_ev_set_queue_tempo(snd_seq_event_t *ev, int q, int tempo);
int snd_seq_ev_set_queue_control(snd_seq_event_t *ev, int type, int q, int value);
int snd_seq_ev_set_queue_pos_real(snd_seq_event_t *ev, int q, snd_seq_real_time_t *rtime);
int snd_seq_ev_set_queue_pos_tick(snd_seq_event_t *ev, int q, snd_seq_tick_time_t tick);

/*
 * use/unuse a queue
 */
int snd_seq_use_queue(snd_seq_t *seq, int q, int use);

/* set and send a queue control event:
 * to send at scheduled time, set the schedule in ev.
 * if ev is NULL, event is sent immediately (to output queue).
 * Note: to send actually to driver, you need to call snd_seq_flush_event()
 *       apropriately.
 */
int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev);
int snd_seq_start_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
int snd_seq_stop_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
int snd_seq_continue_queue(snd_seq_t *seq, int q, snd_seq_event_t *ev);
int snd_seq_change_queue_tempo(snd_seq_t *seq, int q, int tempo, snd_seq_event_t *ev);
int snd_seq_setpos_queue(snd_seq_t *seq, int q, snd_seq_timestamp_t *rtime, snd_seq_event_t *ev);

/* create a port - simple version - return the port number */
int snd_seq_create_simple_port(snd_seq_t *seq, char *name,
			       unsigned int caps, unsigned int type);
/* delete the port */
int snd_seq_delete_simple_port(snd_seq_t *seq, int port);

/* simple subscription between this port and another port
   (w/o exclusive & time conversion)
   */
int snd_seq_connect_from(snd_seq_t *seq, int my_port, int src_client, int src_port);
int snd_seq_connect_to(snd_seq_t *seq, int my_port, int dest_client, int dest_port);
int snd_seq_disconnect_from(snd_seq_t *seq, int my_port, int src_client, int src_port);
int snd_seq_disconnect_to(snd_seq_t *seq, int my_port, int dest_client, int dest_port);

/*
 * set client information
 */
int snd_seq_set_client_name(snd_seq_t *seq, char *name);
int snd_seq_set_client_group(snd_seq_t *seq, char *name);
int snd_seq_set_client_filter(snd_seq_t *seq, unsigned int filter);
int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type);
int snd_seq_set_client_pool_output(snd_seq_t *seq, int size);
int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size);
int snd_seq_set_client_pool_input(snd_seq_t *seq, int size);

/*
 * reset client input/output pool
 */
int snd_seq_reset_pool_output(snd_seq_t *seq);
int snd_seq_reset_pool_input(snd_seq_t *seq);

/*
 * equivalent macros
 */
#define snd_seq_ev_clear(ev)	memset(ev, 0, sizeof(snd_seq_event_t))
#define snd_seq_ev_set_dest(ev,c,p) \
	((ev)->dest.client = (c), (ev)->dest.port = (p))
#define snd_seq_ev_set_subs(ev) \
	((ev)->dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS,\
	 (ev)->dest.port = SND_SEQ_ADDRESS_UNKNOWN)
#define snd_seq_ev_set_broadcast(ev) \
	((ev)->dest.client = SND_SEQ_ADDRESS_BROADCAST,\
	 (ev)->dest.port = SND_SEQ_ADDRESS_BROADCAST)
#define snd_seq_ev_set_source(ev,p) ((ev)->source.port = (p))

/*
 * queue controls
 */
#define snd_seq_ev_set_queue_control(ev,t,q,val) \
	((ev)->type = (t),\
	 snd_seq_ev_set_dest(ev, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_TIMER),\
	 (ev)->data.queue.queue = (q),\
	 (ev)->data.queue.param.value = (val))
#define snd_seq_ev_set_queue_start(ev,q) \
	snd_seq_ev_set_queue_control(ev,SND_SEQ_EVENT_START,q,0)
#define snd_seq_ev_set_queue_stop(ev,q) \
	snd_seq_ev_set_queue_control(ev,SND_SEQ_EVENT_STOP,q,0)
#define snd_seq_ev_set_queue_continue(ev,q) \
	snd_seq_ev_set_queue_control(ev,SND_SEQ_EVENT_CONTINUE,q,0)
#define snd_seq_ev_set_queue_tempo(ev,q,val) \
	snd_seq_ev_set_queue_control(ev,SND_SEQ_EVENT_TEMPO,q,val)
#define snd_seq_ev_set_queue_pos_real(ev,q,rtime) \
	((ev)->type = SND_SEQ_EVENT_SETPOS_TIME,\
	 snd_seq_ev_set_dest(ev, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_TIMER),\
	 (ev)->data.queue.queue = (q),\
	 (ev)->data.queue.param.time.time = *(rtime))
#define snd_seq_ev_set_queue_pos_tick(ev,q,ttime) \
	((ev)->type = SND_SEQ_EVENT_SETPOS_TICK,\
	 snd_seq_ev_set_dest(ev, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_TIMER),\
	 (ev)->data.queue.queue = (q),\
	 (ev)->data.queue.param.time.tick = (ttime))

#define snd_seq_start_queue(seq,q,ev) \
	snd_seq_control_queue(seq, q, SND_SEQ_EVENT_START, 0, ev)
#define snd_seq_stop_queue(seq,q,ev) \
	snd_seq_control_queue(seq, q, SND_SEQ_EVENT_STOP, 0, ev)
#define snd_seq_continue_queue(seq,q,ev) \
	snd_seq_control_queue(seq, q, SND_SEQ_EVENT_CONTINUE, 0, ev)
#define snd_seq_change_queue_tempo(seq,q,tempo,ev) \
	snd_seq_control_queue(seq, q, SND_SEQ_EVENT_TEMPO, tempo, ev)

/*
 * macros to set standard event data
 */
#define snd_seq_ev_set_note(ev,ch,key,vel,dur) \
	((ev)->type = SND_SEQ_EVENT_NOTE,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.note.channel = (ch),\
	 (ev)->data.note.note = (key),\
	 (ev)->data.note.velocity = (vel),\
	 (ev)->data.note.dulation = (dur))
#define snd_seq_ev_set_noteon(ev,ch,key,vel) \
	((ev)->type = SND_SEQ_EVENT_NOTEON,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.note.channel = (ch),\
	 (ev)->data.note.note = (key),\
	 (ev)->data.note.velocity = (vel))
#define snd_seq_ev_set_noteoff(ev,ch,key,vel) \
	((ev)->type = SND_SEQ_EVENT_NOTEOFF,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.note.channel = (ch),\
	 (ev)->data.note.note = (key),\
	 (ev)->data.note.velocity = (vel))
#define snd_seq_ev_set_keypress(ev,ch,key,vel) \
	((ev)->type = SND_SEQ_EVENT_KEYPRESS,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.note.channel = (ch),\
	 (ev)->data.note.note = (key),\
	 (ev)->data.note.velocity = (vel))
#define snd_seq_ev_set_controller(ev,ch,cc,val) \
	((ev)->type = SND_SEQ_EVENT_CONTROLLER,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.control.channel = (ch),\
	 (ev)->data.control.param = (cc),\
	 (ev)->data.control.value = (val))
#define snd_seq_ev_set_pgmchange(ev,ch,val) \
	((ev)->type = SND_SEQ_EVENT_PGMCHANGE,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.control.channel = (ch),\
	 (ev)->data.control.value = (val))
#define snd_seq_ev_set_pitchbend(ev,ch,val) \
	((ev)->type = SND_SEQ_EVENT_PITCHBEND,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.control.channel = (ch),\
	 (ev)->data.control.value = (val))
#define snd_seq_ev_set_chanpress(ev,ch,val) \
	((ev)->type = SND_SEQ_EVENT_CHANPRESS,\
	 snd_seq_ev_set_fixed(ev),\
	 (ev)->data.control.channel = (ch),\
	 (ev)->data.control.value = (val))
#define snd_seq_ev_set_sysex(ev,datalen,dataptr) \
	((ev)->type = SND_SEQ_EVENT_SYSEX,\
	 snd_seq_ev_set_variable(ev, datalen, dataptr))

/* etc. etc... */


#ifdef __cplusplus
}
#endif

/****************************************************************************
 *                                                                          *
 *                                conv.h                                    *
 *                        Binary Value Conversion                           *
 *                                                                          *
 ****************************************************************************/

#ifdef SND_LITTLE_ENDIAN

#define snd_host_to_LE_16(val)	(val)
#define snd_LE_to_host_16(val)	(val)
#define snd_host_to_LE_32(val)	(val)
#define snd_LE_to_host_32(val)	(val)
#define snd_host_to_BE_16(val)	((((val)>>8)&0xff)|(((val)<<8)&0xff00))
#define snd_BE_to_host_16(val)	snd_host_to_BE_16(val)
#define snd_host_to_BE_32(val)	((((val)>>24)&0xff)|(((val)>>16)&0xff00)|\
                                 (((val)<<16)&0xff0000)|(((val)<<24)&0xff000000))
#define snd_BE_to_host_32(val)	snd_host_to_BE_32(val)

#else                                      

#define snd_host_to_BE_16(val)	(val)
#define snd_BE_to_host_16(val)	(val)
#define snd_host_to_BE_16(val)	(val)
#define snd_BE_to_host_16(val)	(val)
#define snd_host_to_LE_16(val)	((((val)>>8)&0xff)|(((val)<<8)&0xff00))
#define snd_LE_to_host_16(val)	snd_host_to_LE_16(val)
#define snd_host_to_LE_32(val)	((((val)>>24)&0xff)|(((val)>>16)&0xff00)|\
                                 (((val)<<16)&0xff0000)|(((val)<<24)&0xff000000))
#define snd_LE_to_host_32(val)	snd_host_to_LE_32(val)

#endif

/****************************************************************************
 *                                                                          *
 *                               instr.h                                    *
 *                          Instrument Interface                            *
 *                                                                          *
 ****************************************************************************/

/* Simple Wave support */

typedef void snd_instr_simple_t;

#ifdef __cplusplus
extern "C" {
#endif

int snd_instr_simple_convert_to_stream(snd_instr_simple_t *simple, const char *name, snd_seq_instr_put_t **put, long *size);
int snd_instr_simple_convert_from_stream(snd_seq_instr_get_t *data, long size, snd_instr_simple_t **simple);
int snd_instr_simple_free(snd_instr_simple_t *simple);

#ifdef __cplusplus
}
#endif

/* InterWave FFFF support */

typedef void snd_instr_iwffff_t;
typedef struct snd_iwffff_handle snd_iwffff_handle_t;

#ifdef __cplusplus
extern "C" {
#endif

int snd_instr_iwffff_open(snd_iwffff_handle_t **handle, const char *name_fff, const char *name_dta);
int snd_instr_iwffff_open_rom(snd_iwffff_handle_t **handle, int card, int bank, int file);
int snd_instr_iwffff_open_rom_file(snd_iwffff_handle_t **handle, const char *name, int bank, int file);
int snd_instr_iwffff_close(snd_iwffff_handle_t *handle);
int snd_instr_iwffff_load(snd_iwffff_handle_t *handle, int bank, int prg, snd_instr_iwffff_t **iwffff);
int snd_instr_iwffff_convert_to_stream(snd_instr_iwffff_t *iwffff, const char *name, snd_seq_instr_put_t **data, long *size);
int snd_instr_iwffff_convert_from_stream(snd_seq_instr_get_t *data, long size, snd_instr_iwffff_t **iwffff);
int snd_instr_iwffff_free(snd_instr_iwffff_t *iwffff);

#ifdef __cplusplus
}
#endif

/*
 *
 */
 
#endif /* __ASOUNDLIB_H */
