From 88e5e451516e7496a86a96ea8a38e63e522b6b22 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 4 Jul 2001 13:54:13 +0000 Subject: [PATCH] Major change to sequencer API. The sequencer API is totally recoded with the style of "encapsulation" in other api. The structure becomes opaque and accessed only via functions. Other changes: - There is no longer group in client and port info. - snd_seq_query_subs_t is renamed to snd_seq_query_subscribe_t. - snd_seq_delete_port takes only the port id argument instead of port_info structure. - snd_seq_input/output_buffer_size are renamed as snd_seq_get_input/output_buffer_size. Similarly snd_seq_resize_input/output_buffer are renamed as snd_seq_set_input/output_buffer_size. - snd_seq_get_named_queue is renamed to snd_seq_query_named_queue. - Sync codes are removed temporarily from API. - Subscription conditions are accessed via the corresponding functions. convert_time is named now as time_update. - snd_seq_get/set_queue_owner are removed. Use snd_seq_get/set_queue_info instead. - Instrument put/get/remove structure is unified as snd_instr_header_t. --- include/Makefile.am | 2 +- include/instr.h | 121 +- include/local.h | 22 + include/seq.h | 953 +++++++----- include/seq_event.h | 432 ++++++ include/seqmid.h | 436 ++++-- src/instr/fm.c | 22 +- src/instr/iwffff.c | 24 +- src/instr/simple.c | 20 +- src/seq/Makefile.am | 2 +- src/seq/seq.c | 3031 +++++++++++++++++++++++++++++++------- src/seq/seq_event.c | 55 + src/seq/seq_hw.c | 24 +- src/seq/seq_local.h | 7 +- src/seq/seq_midi_event.c | 76 +- src/seq/seqmid.c | 306 ++-- test/playmidi1.c | 47 +- test/seq-decoder.c | 618 +++----- test/seq-sender.c | 176 +-- test/seq.c | 85 +- 20 files changed, 4589 insertions(+), 1870 deletions(-) create mode 100644 include/seq_event.h create mode 100644 src/seq/seq_event.c diff --git a/include/Makefile.am b/include/Makefile.am index 72e0b1d6..14ba36fe 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -7,7 +7,7 @@ header_files=header.h version.h global.h input.h output.h error.h \ conf.h pcm.h rawmidi.h timer.h \ hwdep.h hwdep_m4.h control.h \ mixer.h \ - seq.h seqmid.h seq_midi_event.h \ + seq_event.h seq.h seqmid.h seq_midi_event.h \ conv.h instr.h footer.h noinst_HEADERS=$(header_files) search.h list.h aserver.h local.h diff --git a/include/instr.h b/include/instr.h index bff722cd..cabd02fb 100644 --- a/include/instr.h +++ b/include/instr.h @@ -11,41 +11,144 @@ * \{ */ -/* FM instrument support */ +/* instrument get/put */ +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _snd_instr_header snd_instr_header_t; + +size_t snd_instr_header_sizeof(void); +#define snd_instr_header_alloca(ptr) \ +do {\ + assert(ptr);\ + *ptr = (snd_instr_header_t *)alloca(snd_instr_header_sizeof());\ + memset(*ptr, 0, snd_instr_header_sizeof());\ +} while (0) +int snd_instr_header_malloc(snd_instr_header_t **ptr, size_t len); +void snd_instr_header_free(snd_instr_header_t *ptr); +void snd_instr_header_copy(snd_instr_header_t *dst, const snd_instr_header_t *src); + +const snd_seq_instr_t *snd_instr_header_get_id(const snd_instr_header_t *info); +snd_seq_instr_cluster_t snd_instr_header_get_cluster(const snd_instr_header_t *info); +unsigned int snd_instr_header_get_cmd(const snd_instr_header_t *info); +size_t snd_instr_header_get_len(const snd_instr_header_t *info); +const char *snd_instr_header_get_name(const snd_instr_header_t *info); +int snd_instr_header_get_type(const snd_instr_header_t *info); +const char *snd_instr_header_get_format(const snd_instr_header_t *info); +const snd_seq_instr_t *snd_instr_header_get_alias(const snd_instr_header_t *info); +void *snd_instr_header_get_data(const snd_instr_header_t *info); +int snd_instr_header_get_follow_alias(const snd_instr_header_t *info); + +void snd_instr_header_set_id(snd_instr_header_t *info, const snd_seq_instr_t *id); +void snd_instr_header_set_cluster(snd_instr_header_t *info, snd_seq_instr_cluster_t cluster); +void snd_instr_header_set_cmd(snd_instr_header_t *info, unsigned int cmd); +void snd_instr_header_set_len(snd_instr_header_t *info, size_t len); +void snd_instr_header_set_name(snd_instr_header_t *info, const char *name); +void snd_instr_header_set_type(snd_instr_header_t *info, int type); +void snd_instr_header_set_format(snd_instr_header_t *info, const char *format); +void snd_instr_header_set_alias(snd_instr_header_t *info, const snd_seq_instr_t *instr); +void snd_instr_header_set_follow_alias(snd_instr_header_t *info, int bool); + +#ifdef __cplusplus +} +#endif + +/** + * Instrument abstraction layer + * - based on events + */ + +/** instrument types */ +#define SND_SEQ_INSTR_ATYPE_DATA 0 /**< instrument data */ +#define SND_SEQ_INSTR_ATYPE_ALIAS 1 /**< instrument alias */ + +/** instrument ASCII identifiers */ +#define SND_SEQ_INSTR_ID_DLS1 "DLS1" /**< DLS1 */ +#define SND_SEQ_INSTR_ID_DLS2 "DLS2" /**< DLS2 */ +#define SND_SEQ_INSTR_ID_SIMPLE "Simple Wave" /**< Simple Wave */ +#define SND_SEQ_INSTR_ID_SOUNDFONT "SoundFont" /**< SoundFont */ +#define SND_SEQ_INSTR_ID_GUS_PATCH "GUS Patch" /**< Gravis Patch */ +#define SND_SEQ_INSTR_ID_INTERWAVE "InterWave FFFF" /**< InterWave FFFF */ +#define SND_SEQ_INSTR_ID_OPL2_3 "OPL2/3 FM" /**< OPL2/3 FM */ +#define SND_SEQ_INSTR_ID_OPL4 "OPL4" /**< OPL4 */ + +/** instrument types */ +#define SND_SEQ_INSTR_TYPE0_DLS1 (1<<0) /**< MIDI DLS v1 */ +#define SND_SEQ_INSTR_TYPE0_DLS2 (1<<1) /**< MIDI DLS v2 */ +#define SND_SEQ_INSTR_TYPE1_SIMPLE (1<<0) /**< Simple Wave */ +#define SND_SEQ_INSTR_TYPE1_SOUNDFONT (1<<1) /**< EMU SoundFont */ +#define SND_SEQ_INSTR_TYPE1_GUS_PATCH (1<<2) /**< Gravis UltraSound Patch */ +#define SND_SEQ_INSTR_TYPE1_INTERWAVE (1<<3) /**< InterWave FFFF */ +#define SND_SEQ_INSTR_TYPE2_OPL2_3 (1<<0) /**< Yamaha OPL2/3 FM */ +#define SND_SEQ_INSTR_TYPE2_OPL4 (1<<1) /**< Yamaha OPL4 */ + +/** put commands */ +#define SND_SEQ_INSTR_PUT_CMD_CREATE 0 /**< create a new layer */ +#define SND_SEQ_INSTR_PUT_CMD_REPLACE 1 /**< replace the old layer with new one */ +#define SND_SEQ_INSTR_PUT_CMD_MODIFY 2 /**< modify the existing layer */ +#define SND_SEQ_INSTR_PUT_CMD_ADD 3 /**< add one to the existing layer */ +#define SND_SEQ_INSTR_PUT_CMD_REMOVE 4 /**< remove the layer */ + +/** get commands */ +#define SND_SEQ_INSTR_GET_CMD_FULL 0 /**< get the full data stream */ +#define SND_SEQ_INSTR_GET_CMD_PARTIAL 1 /**< get the partial data stream */ + +/** free commands */ +#define SND_SEQ_INSTR_FREE_CMD_ALL 0 /**< remove all matching instruments */ +#define SND_SEQ_INSTR_FREE_CMD_PRIVATE 1 /**< remove only private instruments */ +#define SND_SEQ_INSTR_FREE_CMD_CLUSTER 2 /**< remove only cluster instruments */ +#define SND_SEQ_INSTR_FREE_CMD_SINGLE 3 /**< remove single instrument */ + + +/** + * FM instrument support + */ + +/** FM instrument data structure */ typedef void snd_instr_fm_t; #ifdef __cplusplus extern "C" { #endif -int snd_instr_fm_convert_to_stream(snd_instr_fm_t *fm, const char *name, snd_seq_instr_put_t **put, size_t *size); -int snd_instr_fm_convert_from_stream(snd_seq_instr_get_t *data, size_t size, snd_instr_fm_t **fm); +int snd_instr_fm_convert_to_stream(snd_instr_fm_t *fm, const char *name, snd_instr_header_t **put, size_t *size); +int snd_instr_fm_convert_from_stream(snd_instr_header_t *data, size_t size, snd_instr_fm_t **fm); int snd_instr_fm_free(snd_instr_fm_t *fm); #ifdef __cplusplus } #endif -/* Simple Wave support */ +/** + * Simple Wave support + */ + +/** simple instrument data structure */ 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, size_t *size); -int snd_instr_simple_convert_from_stream(snd_seq_instr_get_t *data, size_t size, snd_instr_simple_t **simple); +int snd_instr_simple_convert_to_stream(snd_instr_simple_t *simple, const char *name, snd_instr_header_t **put, size_t *size); +int snd_instr_simple_convert_from_stream(snd_instr_header_t *data, size_t size, snd_instr_simple_t **simple); int snd_instr_simple_free(snd_instr_simple_t *simple); #ifdef __cplusplus } #endif -/* InterWave FFFF support */ +/** + * InterWave FFFF support + */ + +/** IW FFFF instrument data structure */ typedef void snd_instr_iwffff_t; +/** IW FFFF handler */ typedef struct _snd_iwffff_handle snd_iwffff_handle_t; #ifdef __cplusplus @@ -57,8 +160,8 @@ int snd_instr_iwffff_open_rom(snd_iwffff_handle_t **handle, int card, int bank, 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, size_t *size); -int snd_instr_iwffff_convert_from_stream(snd_seq_instr_get_t *data, size_t size, snd_instr_iwffff_t **iwffff); +int snd_instr_iwffff_convert_to_stream(snd_instr_iwffff_t *iwffff, const char *name, snd_instr_header_t **data, size_t *size); +int snd_instr_iwffff_convert_from_stream(snd_instr_header_t *data, size_t size, snd_instr_iwffff_t **iwffff); int snd_instr_iwffff_free(snd_instr_iwffff_t *iwffff); #ifdef __cplusplus diff --git a/include/local.h b/include/local.h index 55b6181a..7e1a526d 100644 --- a/include/local.h +++ b/include/local.h @@ -46,6 +46,28 @@ #define _snd_hwdep_info sndrv_hwdep_info +#define _SND_SEQ_IN_LOCAL 1 +#define _snd_seq_queue_tempo sndrv_seq_queue_tempo +#define _snd_seq_client_info sndrv_seq_client_info +#define _snd_seq_port_info sndrv_seq_port_info +#define _snd_seq_system_info sndrv_seq_system_info +#define _snd_seq_queue_info sndrv_seq_queue_info +#define _snd_seq_queue_status sndrv_seq_queue_status +#define _snd_seq_queue_timer sndrv_seq_queue_timer +#define _snd_seq_port_subscribe sndrv_seq_port_subscribe +#define _snd_seq_query_subscribe sndrv_seq_query_subs +#define _snd_seq_client_pool sndrv_seq_client_pool +#define _snd_seq_remove_events sndrv_seq_remove_events +#define _snd_instr_header sndrv_seq_instr_header + +typedef struct sndrv_seq_addr snd_seq_addr_t; +#define snd_seq_tick_time_t sndrv_seq_tick_time_t +typedef struct sndrv_seq_real_time snd_seq_real_time_t; +typedef union sndrv_seq_timestamp snd_seq_timestamp_t; +typedef struct sndrv_seq_instr snd_seq_instr_t; +typedef struct sndrv_seq_event snd_seq_event_t; +#define snd_seq_instr_cluster_t sndrv_seq_instr_cluster_t + #include "asoundlib.h" #include "list.h" diff --git a/include/seq.h b/include/seq.h index 844b4c06..e5f8e0f9 100644 --- a/include/seq.h +++ b/include/seq.h @@ -1,386 +1,443 @@ -/**************************************************************************** - * * - * seq.h * - * Sequencer * - * * - ****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif /** - * \defgroup Sequencer Sequencer Interface - * Sequencer Interface + * \defgroup SeqGlobal Sequencer System + * Global System Interface + * \ingroup Sequencer * \{ */ -typedef sndrv_seq_tick_time_t snd_seq_tick_time_t; -typedef sndrv_seq_position_t snd_seq_position_t; -typedef sndrv_seq_frequency_t snd_seq_frequency_t; -typedef sndrv_seq_instr_cluster_t snd_seq_instr_cluster_t; -typedef struct sndrv_seq_port_info snd_seq_port_info_t; -typedef struct sndrv_seq_port_subscribe snd_seq_port_subscribe_t; -typedef struct sndrv_seq_event snd_seq_event_t; -typedef struct sndrv_seq_addr snd_seq_addr_t; -typedef struct sndrv_seq_ev_volume snd_seq_ev_volume_t; -typedef struct sndrv_seq_ev_loop snd_seq_ev_loop_t; -typedef struct sndrv_seq_remove_events snd_seq_remove_events_t; -typedef struct sndrv_seq_query_subs snd_seq_query_subs_t; -typedef struct sndrv_seq_real_time snd_seq_real_time_t; -typedef struct sndrv_seq_system_info snd_seq_system_info_t; -typedef struct sndrv_seq_client_info snd_seq_client_info_t; -typedef struct sndrv_seq_queue_info snd_seq_queue_info_t; -typedef struct sndrv_seq_queue_status snd_seq_queue_status_t; -typedef struct sndrv_seq_queue_tempo snd_seq_queue_tempo_t; -typedef struct sndrv_seq_queue_owner snd_seq_queue_owner_t; -typedef struct sndrv_seq_queue_timer snd_seq_queue_timer_t; -typedef struct sndrv_seq_queue_client snd_seq_queue_client_t; -typedef struct sndrv_seq_client_pool snd_seq_client_pool_t; -typedef struct sndrv_seq_instr snd_seq_instr_t; -typedef struct sndrv_seq_instr_data snd_seq_instr_data_t; -typedef struct sndrv_seq_instr_free snd_seq_instr_free_t; -typedef struct sndrv_seq_instr_put snd_seq_instr_put_t; -typedef struct sndrv_seq_instr_get snd_seq_instr_get_t; -typedef union sndrv_seq_timestamp snd_seq_timestamp_t; - -typedef enum sndrv_seq_client_type snd_seq_client_type_t; -typedef enum sndrv_seq_stop_mode snd_seq_stop_mode_t; - -#define snd_seq_event_bounce_ext_data sndrv_seq_event_bounce_ext_data -#define snd_seq_ev_is_result_type sndrv_seq_ev_is_result_type -#define snd_seq_ev_is_channel_type sndrv_seq_ev_is_channel_type -#define snd_seq_ev_is_note_type sndrv_seq_ev_is_note_type -#define snd_seq_ev_is_control_type sndrv_seq_ev_is_control_type -#define snd_seq_ev_is_queue_type sndrv_seq_ev_is_queue_type -#define snd_seq_ev_is_message_type sndrv_seq_ev_is_message_type -#define snd_seq_ev_is_sample_type sndrv_seq_ev_is_sample_type -#define snd_seq_ev_is_user_type sndrv_seq_ev_is_user_type -#define snd_seq_ev_is_fixed_type sndrv_seq_ev_is_fixed_type -#define snd_seq_ev_is_instr_type sndrv_seq_ev_is_instr_type -#define snd_seq_ev_is_variable_type sndrv_seq_ev_is_variable_type -#define snd_seq_ev_is_varipc_type sndrv_seq_ev_is_varipc_type -#define snd_seq_ev_is_reserved sndrv_seq_ev_is_reserved -#define snd_seq_ev_is_direct sndrv_seq_ev_is_direct -#define snd_seq_ev_is_prior sndrv_seq_ev_is_prior -#define snd_seq_ev_length_type sndrv_seq_ev_length_type -#define snd_seq_ev_is_fixed sndrv_seq_ev_is_fixed -#define snd_seq_ev_is_variable sndrv_seq_ev_is_variable -#define snd_seq_ev_is_varusr sndrv_seq_ev_is_varusr -#define snd_seq_ev_is_varipc sndrv_seq_ev_is_varipc -#define snd_seq_ev_timestamp_type sndrv_seq_ev_timestamp_type -#define snd_seq_ev_is_tick sndrv_seq_ev_is_tick -#define snd_seq_ev_is_real sndrv_seq_ev_is_real -#define snd_seq_ev_timemode_type sndrv_seq_ev_timemode_type -#define snd_seq_ev_is_abstime sndrv_seq_ev_is_abstime -#define snd_seq_ev_is_reltime sndrv_seq_ev_is_reltime -#define snd_seq_queue_sync_port sndrv_seq_queue_sync_port -#define snd_seq_queue_owner sndrv_seq_queue_owner - -#ifdef SNDRV_SEQ_SYNC_SUPPORT -#define SND_SEQ_SYNC_SUPPORT SNDRV_SEQ_SYNC_SUPPORT -#endif +/** Sequencer handle */ +typedef struct _snd_seq snd_seq_t; + +/** \internal */ +#define SND_ALLOCA(type,ptr) \ +do {\ + assert(ptr);\ + *ptr = (type##_t *)alloca(type##_sizeof());\ + memset(*ptr, 0, type##_sizeof());\ +} while (0) -#define SND_SEQ_EVENT_SYSTEM SNDRV_SEQ_EVENT_SYSTEM -#define SND_SEQ_EVENT_RESULT SNDRV_SEQ_EVENT_RESULT -#define SND_SEQ_EVENT_NOTE SNDRV_SEQ_EVENT_NOTE -#define SND_SEQ_EVENT_NOTEON SNDRV_SEQ_EVENT_NOTEON -#define SND_SEQ_EVENT_NOTEOFF SNDRV_SEQ_EVENT_NOTEOFF -#define SND_SEQ_EVENT_KEYPRESS SNDRV_SEQ_EVENT_KEYPRESS -#define SND_SEQ_EVENT_CONTROLLER SNDRV_SEQ_EVENT_CONTROLLER -#define SND_SEQ_EVENT_PGMCHANGE SNDRV_SEQ_EVENT_PGMCHANGE -#define SND_SEQ_EVENT_CHANPRESS SNDRV_SEQ_EVENT_CHANPRESS -#define SND_SEQ_EVENT_PITCHBEND SNDRV_SEQ_EVENT_PITCHBEND -#define SND_SEQ_EVENT_CONTROL14 SNDRV_SEQ_EVENT_CONTROL14 -#define SND_SEQ_EVENT_NONREGPARAM SNDRV_SEQ_EVENT_NONREGPARAM -#define SND_SEQ_EVENT_REGPARAM SNDRV_SEQ_EVENT_REGPARAM -#define SND_SEQ_EVENT_SONGPOS SNDRV_SEQ_EVENT_SONGPOS -#define SND_SEQ_EVENT_SONGSEL SNDRV_SEQ_EVENT_SONGSEL -#define SND_SEQ_EVENT_QFRAME SNDRV_SEQ_EVENT_QFRAME -#define SND_SEQ_EVENT_TIMESIGN SNDRV_SEQ_EVENT_TIMESIGN -#define SND_SEQ_EVENT_KEYSIGN SNDRV_SEQ_EVENT_KEYSIGN -#define SND_SEQ_EVENT_START SNDRV_SEQ_EVENT_START -#define SND_SEQ_EVENT_CONTINUE SNDRV_SEQ_EVENT_CONTINUE -#define SND_SEQ_EVENT_STOP SNDRV_SEQ_EVENT_STOP -#define SND_SEQ_EVENT_SETPOS_TICK SNDRV_SEQ_EVENT_SETPOS_TICK -#define SND_SEQ_EVENT_SETPOS_TIME SNDRV_SEQ_EVENT_SETPOS_TIME -#define SND_SEQ_EVENT_TEMPO SNDRV_SEQ_EVENT_TEMPO -#define SND_SEQ_EVENT_CLOCK SNDRV_SEQ_EVENT_CLOCK -#define SND_SEQ_EVENT_TICK SNDRV_SEQ_EVENT_TICK -#define SND_SEQ_EVENT_SYNC SNDRV_SEQ_EVENT_SYNC -#define SND_SEQ_EVENT_SYNC_POS SNDRV_SEQ_EVENT_SYNC_POS -#define SND_SEQ_EVENT_TUNE_REQUEST SNDRV_SEQ_EVENT_TUNE_REQUEST -#define SND_SEQ_EVENT_RESET SNDRV_SEQ_EVENT_RESET -#define SND_SEQ_EVENT_SENSING SNDRV_SEQ_EVENT_SENSING -#define SND_SEQ_EVENT_ECHO SNDRV_SEQ_EVENT_ECHO -#define SND_SEQ_EVENT_OSS SNDRV_SEQ_EVENT_OSS -#define SND_SEQ_EVENT_CLIENT_START SNDRV_SEQ_EVENT_CLIENT_START -#define SND_SEQ_EVENT_CLIENT_EXIT SNDRV_SEQ_EVENT_CLIENT_EXIT -#define SND_SEQ_EVENT_CLIENT_CHANGE SNDRV_SEQ_EVENT_CLIENT_CHANGE -#define SND_SEQ_EVENT_PORT_START SNDRV_SEQ_EVENT_PORT_START -#define SND_SEQ_EVENT_PORT_EXIT SNDRV_SEQ_EVENT_PORT_EXIT -#define SND_SEQ_EVENT_PORT_CHANGE SNDRV_SEQ_EVENT_PORT_CHANGE -#define SND_SEQ_EVENT_PORT_SUBSCRIBED SNDRV_SEQ_EVENT_PORT_SUBSCRIBED -#define SND_SEQ_EVENT_PORT_USED SNDRV_SEQ_EVENT_PORT_USED -#define SND_SEQ_EVENT_PORT_UNSUBSCRIBED SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED -#define SND_SEQ_EVENT_PORT_UNUSED SNDRV_SEQ_EVENT_PORT_UNUSED -#define SND_SEQ_EVENT_SAMPLE SNDRV_SEQ_EVENT_SAMPLE -#define SND_SEQ_EVENT_SAMPLE_CLUSTER SNDRV_SEQ_EVENT_SAMPLE_CLUSTER -#define SND_SEQ_EVENT_SAMPLE_START SNDRV_SEQ_EVENT_SAMPLE_START -#define SND_SEQ_EVENT_SAMPLE_STOP SNDRV_SEQ_EVENT_SAMPLE_STOP -#define SND_SEQ_EVENT_SAMPLE_FREQ SNDRV_SEQ_EVENT_SAMPLE_FREQ -#define SND_SEQ_EVENT_SAMPLE_VOLUME SNDRV_SEQ_EVENT_SAMPLE_VOLUME -#define SND_SEQ_EVENT_SAMPLE_LOOP SNDRV_SEQ_EVENT_SAMPLE_LOOP -#define SND_SEQ_EVENT_SAMPLE_POSITION SNDRV_SEQ_EVENT_SAMPLE_POSITION -#define SND_SEQ_EVENT_SAMPLE_PRIVATE1 SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1 -#define SND_SEQ_EVENT_USR0 SNDRV_SEQ_EVENT_USR0 -#define SND_SEQ_EVENT_USR1 SNDRV_SEQ_EVENT_USR1 -#define SND_SEQ_EVENT_USR2 SNDRV_SEQ_EVENT_USR2 -#define SND_SEQ_EVENT_USR3 SNDRV_SEQ_EVENT_USR3 -#define SND_SEQ_EVENT_USR4 SNDRV_SEQ_EVENT_USR4 -#define SND_SEQ_EVENT_USR5 SNDRV_SEQ_EVENT_USR5 -#define SND_SEQ_EVENT_USR6 SNDRV_SEQ_EVENT_USR6 -#define SND_SEQ_EVENT_USR7 SNDRV_SEQ_EVENT_USR7 -#define SND_SEQ_EVENT_USR8 SNDRV_SEQ_EVENT_USR8 -#define SND_SEQ_EVENT_USR9 SNDRV_SEQ_EVENT_USR9 -#define SND_SEQ_EVENT_INSTR_BEGIN SNDRV_SEQ_EVENT_INSTR_BEGIN -#define SND_SEQ_EVENT_INSTR_END SNDRV_SEQ_EVENT_INSTR_END -#define SND_SEQ_EVENT_INSTR_INFO SNDRV_SEQ_EVENT_INSTR_INFO -#define SND_SEQ_EVENT_INSTR_INFO_RESULT SNDRV_SEQ_EVENT_INSTR_INFO_RESULT -#define SND_SEQ_EVENT_INSTR_FINFO SNDRV_SEQ_EVENT_INSTR_FINFO -#define SND_SEQ_EVENT_INSTR_FINFO_RESULT SNDRV_SEQ_EVENT_INSTR_FINFO_RESULT -#define SND_SEQ_EVENT_INSTR_RESET SNDRV_SEQ_EVENT_INSTR_RESET -#define SND_SEQ_EVENT_INSTR_STATUS SNDRV_SEQ_EVENT_INSTR_STATUS -#define SND_SEQ_EVENT_INSTR_STATUS_RESULT SNDRV_SEQ_EVENT_INSTR_STATUS_RESULT -#define SND_SEQ_EVENT_INSTR_PUT SNDRV_SEQ_EVENT_INSTR_PUT -#define SND_SEQ_EVENT_INSTR_GET SNDRV_SEQ_EVENT_INSTR_GET -#define SND_SEQ_EVENT_INSTR_GET_RESULT SNDRV_SEQ_EVENT_INSTR_GET_RESULT -#define SND_SEQ_EVENT_INSTR_FREE SNDRV_SEQ_EVENT_INSTR_FREE -#define SND_SEQ_EVENT_INSTR_LIST SNDRV_SEQ_EVENT_INSTR_LIST -#define SND_SEQ_EVENT_INSTR_LIST_RESULT SNDRV_SEQ_EVENT_INSTR_LIST_RESULT -#define SND_SEQ_EVENT_INSTR_CLUSTER SNDRV_SEQ_EVENT_INSTR_CLUSTER -#define SND_SEQ_EVENT_INSTR_CLUSTER_GET SNDRV_SEQ_EVENT_INSTR_CLUSTER_GET -#define SND_SEQ_EVENT_INSTR_CLUSTER_RESULT SNDRV_SEQ_EVENT_INSTR_CLUSTER_RESULT -#define SND_SEQ_EVENT_INSTR_CHANGE SNDRV_SEQ_EVENT_INSTR_CHANGE -#define SND_SEQ_EVENT_LENGTH_VARIABLE SNDRV_SEQ_EVENT_LENGTH_VARIABLE -#define SND_SEQ_EVENT_SYSEX SNDRV_SEQ_EVENT_SYSEX -#define SND_SEQ_EVENT_BOUNCE SNDRV_SEQ_EVENT_BOUNCE -#define SND_SEQ_EVENT_USR_VAR0 SNDRV_SEQ_EVENT_USR_VAR0 -#define SND_SEQ_EVENT_USR_VAR1 SNDRV_SEQ_EVENT_USR_VAR1 -#define SND_SEQ_EVENT_USR_VAR2 SNDRV_SEQ_EVENT_USR_VAR2 -#define SND_SEQ_EVENT_USR_VAR3 SNDRV_SEQ_EVENT_USR_VAR3 -#define SND_SEQ_EVENT_USR_VAR4 SNDRV_SEQ_EVENT_USR_VAR4 -#define SND_SEQ_EVENT_LENGTH_VARIPC SNDRV_SEQ_EVENT_LENGTH_VARIPC -#define SND_SEQ_EVENT_IPCSHM SNDRV_SEQ_EVENT_IPCSHM -#define SND_SEQ_EVENT_USR_VARIPC0 SNDRV_SEQ_EVENT_USR_VARIPC0 -#define SND_SEQ_EVENT_USR_VARIPC1 SNDRV_SEQ_EVENT_USR_VARIPC1 -#define SND_SEQ_EVENT_USR_VARIPC2 SNDRV_SEQ_EVENT_USR_VARIPC2 -#define SND_SEQ_EVENT_USR_VARIPC3 SNDRV_SEQ_EVENT_USR_VARIPC3 -#define SND_SEQ_EVENT_USR_VARIPC4 SNDRV_SEQ_EVENT_USR_VARIPC4 -#define SND_SEQ_EVENT_KERNEL_ERROR SNDRV_SEQ_EVENT_KERNEL_ERROR -#define SND_SEQ_EVENT_KERNEL_QUOTE SNDRV_SEQ_EVENT_KERNEL_QUOTE -#define SND_SEQ_EVENT_NONE SNDRV_SEQ_EVENT_NONE -#define SND_SEQ_ADDRESS_UNKNOWN SNDRV_SEQ_ADDRESS_UNKNOWN -#define SND_SEQ_ADDRESS_SUBSCRIBERS SNDRV_SEQ_ADDRESS_SUBSCRIBERS -#define SND_SEQ_ADDRESS_BROADCAST SNDRV_SEQ_ADDRESS_BROADCAST -#define SND_SEQ_QUEUE_DIRECT SNDRV_SEQ_QUEUE_DIRECT -#define SND_SEQ_TIME_STAMP_TICK SNDRV_SEQ_TIME_STAMP_TICK -#define SND_SEQ_TIME_STAMP_REAL SNDRV_SEQ_TIME_STAMP_REAL -#define SND_SEQ_TIME_STAMP_MASK SNDRV_SEQ_TIME_STAMP_MASK -#define SND_SEQ_TIME_MODE_ABS SNDRV_SEQ_TIME_MODE_ABS -#define SND_SEQ_TIME_MODE_REL SNDRV_SEQ_TIME_MODE_REL -#define SND_SEQ_TIME_MODE_MASK SNDRV_SEQ_TIME_MODE_MASK -#define SND_SEQ_EVENT_LENGTH_FIXED SNDRV_SEQ_EVENT_LENGTH_FIXED -#define SND_SEQ_EVENT_LENGTH_VARIABLE SNDRV_SEQ_EVENT_LENGTH_VARIABLE -#define SND_SEQ_EVENT_LENGTH_VARUSR SNDRV_SEQ_EVENT_LENGTH_VARUSR -#define SND_SEQ_EVENT_LENGTH_VARIPC SNDRV_SEQ_EVENT_LENGTH_VARIPC -#define SND_SEQ_EVENT_LENGTH_MASK SNDRV_SEQ_EVENT_LENGTH_MASK -#define SND_SEQ_PRIORITY_NORMAL SNDRV_SEQ_PRIORITY_NORMAL -#define SND_SEQ_PRIORITY_HIGH SNDRV_SEQ_PRIORITY_HIGH -#define SND_SEQ_PRIORITY_MASK SNDRV_SEQ_PRIORITY_MASK -#define SND_SEQ_EVENT_NOTE SNDRV_SEQ_EVENT_NOTE -#define SND_SEQ_EVENT_NOTE SNDRV_SEQ_EVENT_NOTE -#define SND_SEQ_QUEUE_DIRECT SNDRV_SEQ_QUEUE_DIRECT -#define SND_SEQ_PRIORITY_MASK SNDRV_SEQ_PRIORITY_MASK -#define SND_SEQ_EVENT_LENGTH_MASK SNDRV_SEQ_EVENT_LENGTH_MASK -#define SND_SEQ_EVENT_LENGTH_FIXED SNDRV_SEQ_EVENT_LENGTH_FIXED -#define SND_SEQ_EVENT_LENGTH_VARIABLE SNDRV_SEQ_EVENT_LENGTH_VARIABLE -#define SND_SEQ_EVENT_LENGTH_VARUSR SNDRV_SEQ_EVENT_LENGTH_VARUSR -#define SND_SEQ_EVENT_LENGTH_VARIPC SNDRV_SEQ_EVENT_LENGTH_VARIPC -#define SND_SEQ_TIME_STAMP_MASK SNDRV_SEQ_TIME_STAMP_MASK -#define SND_SEQ_TIME_STAMP_TICK SNDRV_SEQ_TIME_STAMP_TICK -#define SND_SEQ_TIME_STAMP_REAL SNDRV_SEQ_TIME_STAMP_REAL -#define SND_SEQ_TIME_MODE_MASK SNDRV_SEQ_TIME_MODE_MASK -#define SND_SEQ_TIME_MODE_ABS SNDRV_SEQ_TIME_MODE_ABS -#define SND_SEQ_TIME_MODE_REL SNDRV_SEQ_TIME_MODE_REL -#define SND_SEQ_CLIENT_SYSTEM SNDRV_SEQ_CLIENT_SYSTEM -#define SND_SEQ_CLIENT_DUMMY SNDRV_SEQ_CLIENT_DUMMY -#define SND_SEQ_CLIENT_OSS SNDRV_SEQ_CLIENT_OSS -#define SND_SEQ_FILTER_BROADCAST SNDRV_SEQ_FILTER_BROADCAST -#define SND_SEQ_FILTER_MULTICAST SNDRV_SEQ_FILTER_MULTICAST -#define SND_SEQ_FILTER_BOUNCE SNDRV_SEQ_FILTER_BOUNCE -#define SND_SEQ_FILTER_USE_EVENT SNDRV_SEQ_FILTER_USE_EVENT -#define SND_SEQ_REMOVE_DEST SNDRV_SEQ_REMOVE_DEST -#define SND_SEQ_REMOVE_DEST_CHANNEL SNDRV_SEQ_REMOVE_DEST_CHANNEL -#define SND_SEQ_REMOVE_TIME_BEFORE SNDRV_SEQ_REMOVE_TIME_BEFORE -#define SND_SEQ_REMOVE_TIME_AFTER SNDRV_SEQ_REMOVE_TIME_AFTER -#define SND_SEQ_REMOVE_EVENT_TYPE SNDRV_SEQ_REMOVE_EVENT_TYPE -#define SND_SEQ_REMOVE_IGNORE_OFF SNDRV_SEQ_REMOVE_IGNORE_OFF -#define SND_SEQ_REMOVE_TAG_MATCH SNDRV_SEQ_REMOVE_TAG_MATCH -#define SND_SEQ_PORT_SYSTEM_TIMER SNDRV_SEQ_PORT_SYSTEM_TIMER -#define SND_SEQ_PORT_SYSTEM_ANNOUNCE SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE -#define SND_SEQ_PORT_CAP_READ SNDRV_SEQ_PORT_CAP_READ -#define SND_SEQ_PORT_CAP_WRITE SNDRV_SEQ_PORT_CAP_WRITE -#define SND_SEQ_PORT_CAP_SYNC_READ SNDRV_SEQ_PORT_CAP_SYNC_READ -#define SND_SEQ_PORT_CAP_SYNC_WRITE SNDRV_SEQ_PORT_CAP_SYNC_WRITE -#define SND_SEQ_PORT_CAP_DUPLEX SNDRV_SEQ_PORT_CAP_DUPLEX -#define SND_SEQ_PORT_CAP_SUBS_READ SNDRV_SEQ_PORT_CAP_SUBS_READ -#define SND_SEQ_PORT_CAP_SUBS_WRITE SNDRV_SEQ_PORT_CAP_SUBS_WRITE -#define SND_SEQ_PORT_CAP_NO_EXPORT SNDRV_SEQ_PORT_CAP_NO_EXPORT -#define SND_SEQ_PORT_TYPE_SPECIFIC SNDRV_SEQ_PORT_TYPE_SPECIFIC -#define SND_SEQ_PORT_TYPE_MIDI_GENERIC SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC -#define SND_SEQ_PORT_TYPE_MIDI_GM SNDRV_SEQ_PORT_TYPE_MIDI_GM -#define SND_SEQ_PORT_TYPE_MIDI_GS SNDRV_SEQ_PORT_TYPE_MIDI_GS -#define SND_SEQ_PORT_TYPE_MIDI_XG SNDRV_SEQ_PORT_TYPE_MIDI_XG -#define SND_SEQ_PORT_TYPE_MIDI_MT32 SNDRV_SEQ_PORT_TYPE_MIDI_MT32 -#define SND_SEQ_PORT_TYPE_SYNTH SNDRV_SEQ_PORT_TYPE_SYNTH -#define SND_SEQ_PORT_TYPE_DIRECT_SAMPLE SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE -#define SND_SEQ_PORT_TYPE_SAMPLE SNDRV_SEQ_PORT_TYPE_SAMPLE -#define SND_SEQ_PORT_TYPE_APPLICATION SNDRV_SEQ_PORT_TYPE_APPLICATION -#define SND_SEQ_GROUP_SYSTEM SNDRV_SEQ_GROUP_SYSTEM -#define SND_SEQ_GROUP_DEVICE SNDRV_SEQ_GROUP_DEVICE -#define SND_SEQ_GROUP_APPLICATION SNDRV_SEQ_GROUP_APPLICATION -#define SND_SEQ_PORT_FLG_GIVEN_PORT SNDRV_SEQ_PORT_FLG_GIVEN_PORT -#define SND_SEQ_QUEUE_FLG_SYNC SNDRV_SEQ_QUEUE_FLG_SYNC -#define SND_SEQ_QUEUE_FLG_SYNC_LOST SNDRV_SEQ_QUEUE_FLG_SYNC_LOST -#define SND_SEQ_SYNC_TICK SNDRV_SEQ_SYNC_TICK -#define SND_SEQ_SYNC_TIME SNDRV_SEQ_SYNC_TIME -#define SND_SEQ_SYNC_MODE SNDRV_SEQ_SYNC_MODE -#define SND_SEQ_SYNC_FMT_PRIVATE_CLOCK SNDRV_SEQ_SYNC_FMT_PRIVATE_CLOCK -#define SND_SEQ_SYNC_FMT_PRIVATE_TIME SNDRV_SEQ_SYNC_FMT_PRIVATE_TIME -#define SND_SEQ_SYNC_FMT_MIDI_CLOCK SNDRV_SEQ_SYNC_FMT_MIDI_CLOCK -#define SND_SEQ_SYNC_FMT_MTC SNDRV_SEQ_SYNC_FMT_MTC -#define SND_SEQ_SYNC_FMT_DTL SNDRV_SEQ_SYNC_FMT_DTL -#define SND_SEQ_SYNC_FMT_SMPTE SNDRV_SEQ_SYNC_FMT_SMPTE -#define SND_SEQ_SYNC_FMT_MIDI_TICK SNDRV_SEQ_SYNC_FMT_MIDI_TICK -#define SND_SEQ_SYNC_FPS_24 SNDRV_SEQ_SYNC_FPS_24 -#define SND_SEQ_SYNC_FPS_25 SNDRV_SEQ_SYNC_FPS_25 -#define SND_SEQ_SYNC_FPS_30_DP SNDRV_SEQ_SYNC_FPS_30_DP -#define SND_SEQ_SYNC_FPS_30_NDP SNDRV_SEQ_SYNC_FPS_30_NDP -#define SND_SEQ_TIMER_ALSA SNDRV_SEQ_TIMER_ALSA -#define SND_SEQ_TIMER_MIDI_CLOCK SNDRV_SEQ_TIMER_MIDI_CLOCK -#define SND_SEQ_TIMER_MIDI_TICK SNDRV_SEQ_TIMER_MIDI_TICK -#define SND_SEQ_QUERY_SUBS_READ SNDRV_SEQ_QUERY_SUBS_READ -#define SND_SEQ_QUERY_SUBS_WRITE SNDRV_SEQ_QUERY_SUBS_WRITE -#define SND_SEQ_INSTR_ATYPE_DATA SNDRV_SEQ_INSTR_ATYPE_DATA -#define SND_SEQ_INSTR_ATYPE_ALIAS SNDRV_SEQ_INSTR_ATYPE_ALIAS -#define SND_SEQ_INSTR_ID_DLS1 SNDRV_SEQ_INSTR_ID_DLS1 -#define SND_SEQ_INSTR_ID_DLS2 SNDRV_SEQ_INSTR_ID_DLS2 -#define SND_SEQ_INSTR_ID_SIMPLE SNDRV_SEQ_INSTR_ID_SIMPLE -#define SND_SEQ_INSTR_ID_SOUNDFONT SNDRV_SEQ_INSTR_ID_SOUNDFONT -#define SND_SEQ_INSTR_ID_GUS_PATCH SNDRV_SEQ_INSTR_ID_GUS_PATCH -#define SND_SEQ_INSTR_ID_INTERWAVE SNDRV_SEQ_INSTR_ID_INTERWAVE -#define SND_SEQ_INSTR_ID_OPL2_3 SNDRV_SEQ_INSTR_ID_OPL2_3 -#define SND_SEQ_INSTR_ID_OPL4 SNDRV_SEQ_INSTR_ID_OPL4 -#define SND_SEQ_INSTR_TYPE0_DLS1 SNDRV_SEQ_INSTR_TYPE0_DLS1 -#define SND_SEQ_INSTR_TYPE0_DLS2 SNDRV_SEQ_INSTR_TYPE0_DLS2 -#define SND_SEQ_INSTR_TYPE1_SIMPLE SNDRV_SEQ_INSTR_TYPE1_SIMPLE -#define SND_SEQ_INSTR_TYPE1_SOUNDFONT SNDRV_SEQ_INSTR_TYPE1_SOUNDFONT -#define SND_SEQ_INSTR_TYPE1_GUS_PATCH SNDRV_SEQ_INSTR_TYPE1_GUS_PATCH -#define SND_SEQ_INSTR_TYPE1_INTERWAVE SNDRV_SEQ_INSTR_TYPE1_INTERWAVE -#define SND_SEQ_INSTR_TYPE2_OPL2_3 SNDRV_SEQ_INSTR_TYPE2_OPL2_3 -#define SND_SEQ_INSTR_TYPE2_OPL4 SNDRV_SEQ_INSTR_TYPE2_OPL4 -#define SND_SEQ_INSTR_PUT_CMD_CREATE SNDRV_SEQ_INSTR_PUT_CMD_CREATE -#define SND_SEQ_INSTR_PUT_CMD_REPLACE SNDRV_SEQ_INSTR_PUT_CMD_REPLACE -#define SND_SEQ_INSTR_PUT_CMD_MODIFY SNDRV_SEQ_INSTR_PUT_CMD_MODIFY -#define SND_SEQ_INSTR_PUT_CMD_ADD SNDRV_SEQ_INSTR_PUT_CMD_ADD -#define SND_SEQ_INSTR_PUT_CMD_REMOVE SNDRV_SEQ_INSTR_PUT_CMD_REMOVE -#define SND_SEQ_INSTR_GET_CMD_FULL SNDRV_SEQ_INSTR_GET_CMD_FULL -#define SND_SEQ_INSTR_GET_CMD_PARTIAL SNDRV_SEQ_INSTR_GET_CMD_PARTIAL -#define SND_SEQ_INSTR_QUERY_FOLLOW_ALIAS SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS -#define SND_SEQ_INSTR_FREE_CMD_ALL SNDRV_SEQ_INSTR_FREE_CMD_ALL -#define SND_SEQ_INSTR_FREE_CMD_PRIVATE SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE -#define SND_SEQ_INSTR_FREE_CMD_CLUSTER SNDRV_SEQ_INSTR_FREE_CMD_CLUSTER -#define SND_SEQ_INSTR_FREE_CMD_SINGLE SNDRV_SEQ_INSTR_FREE_CMD_SINGLE - - -#define SND_SEQ_OPEN_OUTPUT 1 -#define SND_SEQ_OPEN_INPUT 2 -#define SND_SEQ_OPEN_DUPLEX (SND_SEQ_OPEN_OUTPUT|SND_SEQ_OPEN_INPUT) - -#define SND_SEQ_NONBLOCK 1 +/** + * sequencer opening stream types + */ +#define SND_SEQ_OPEN_OUTPUT 1 /**< open for output (write) */ +#define SND_SEQ_OPEN_INPUT 2 /**< open for input (read) */ +#define SND_SEQ_OPEN_DUPLEX (SND_SEQ_OPEN_OUTPUT|SND_SEQ_OPEN_INPUT) /**< open for both input and output (read/write) */ + +/** + * sequencer opening mode + */ +#define SND_SEQ_NONBLOCK 1 /**< non-blocking mode */ typedef enum _snd_seq_type { - SND_SEQ_TYPE_HW, - SND_SEQ_TYPE_SHM, - SND_SEQ_TYPE_INET, + SND_SEQ_TYPE_HW, /**< hardware */ + SND_SEQ_TYPE_SHM, /**< shared memory (NYI) */ + SND_SEQ_TYPE_INET, /**< network (NYI) */ } snd_seq_type_t; -/* Sequencer handle */ -typedef struct _snd_seq snd_seq_t; +/** special client (port) ids */ +#define SND_SEQ_ADDRESS_UNKNOWN 253 /**< unknown source */ +#define SND_SEQ_ADDRESS_SUBSCRIBERS 254 /**< send event to all subscribed ports */ +#define SND_SEQ_ADDRESS_BROADCAST 255 /**< send event to all queues/clients/ports/channels */ -#ifdef __cplusplus -extern "C" { -#endif +/** known client numbers */ +#define SND_SEQ_CLIENT_SYSTEM 0 /**< system client */ +#define SND_SEQ_CLIENT_DUMMY 62 /**< dummy ports */ +#define SND_SEQ_CLIENT_OSS 63 /**< oss sequencer emulator */ +/* + */ int snd_seq_open(snd_seq_t **handle, const char *name, int streams, int mode); +const char *snd_seq_name(snd_seq_t *seq); +snd_seq_type_t snd_seq_type(snd_seq_t *seq); int snd_seq_close(snd_seq_t *handle); int snd_seq_poll_descriptors_count(snd_seq_t *handle, short events); int snd_seq_poll_descriptors(snd_seq_t *handle, struct pollfd *pfds, unsigned int space, short events); int snd_seq_nonblock(snd_seq_t *handle, int nonblock); 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, size_t size); -int snd_seq_resize_input_buffer(snd_seq_t *handle, size_t size); + +size_t snd_seq_get_output_buffer_size(snd_seq_t *handle); +size_t snd_seq_get_input_buffer_size(snd_seq_t *handle); +int snd_seq_set_output_buffer_size(snd_seq_t *handle, size_t size); +int snd_seq_set_input_buffer_size(snd_seq_t *handle, size_t size); + +/** system information container */ +typedef struct _snd_seq_system_info snd_seq_system_info_t; + +size_t snd_seq_system_info_sizeof(void); +/** allocate a system_info container in heap */ +#define snd_seq_system_info_alloca(ptr) \ + SND_ALLOCA(snd_seq_system_info, ptr) +int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr); +void snd_seq_system_info_free(snd_seq_system_info_t *ptr); +void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src); + +int snd_seq_system_info_get_queues(const snd_seq_system_info_t *info); +int snd_seq_system_info_get_clients(const snd_seq_system_info_t *info); +int snd_seq_system_info_get_ports(const snd_seq_system_info_t *info); +int snd_seq_system_info_get_channels(const snd_seq_system_info_t *info); + int snd_seq_system_info(snd_seq_t *handle, snd_seq_system_info_t *info); + +/** \} */ + + +/** + * \defgroup SeqClient Sequencer Client Interface + * Sequencer Client Interface + * \ingroup Sequencer + * \{ + */ + +/** client information container */ +typedef struct _snd_seq_client_info snd_seq_client_info_t; + +/** client types */ +typedef enum snd_seq_client_type { + SND_SEQ_USER_CLIENT = 1, /**< user client */ + SND_SEQ_KERNEL_CLIENT = 2 /**< kernel client */ +} snd_seq_client_type_t; + +size_t snd_seq_client_info_sizeof(void); +/** allocate a client_info container in heap */ +#define snd_seq_client_info_alloca(ptr) \ + SND_ALLOCA(snd_seq_client_info, ptr) +int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr); +void snd_seq_client_info_free(snd_seq_client_info_t *ptr); +void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src); + +int snd_seq_client_info_get_client(const snd_seq_client_info_t *info); +snd_seq_client_type_t snd_seq_client_info_get_type(const snd_seq_client_info_t *info); +const char *snd_seq_client_info_get_name(snd_seq_client_info_t *info); +int snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t *info); +int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info); +const unsigned char *snd_seq_client_info_get_event_filter(const snd_seq_client_info_t *info); +int snd_seq_client_info_get_num_ports(const snd_seq_client_info_t *info); +int snd_seq_client_info_get_event_lost(const snd_seq_client_info_t *info); + +void snd_seq_client_info_set_client(snd_seq_client_info_t *info, int client); +void snd_seq_client_info_set_name(snd_seq_client_info_t *info, const char *name); +void snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t *info, int bool); +void snd_seq_client_info_set_error_bounce(snd_seq_client_info_t *info, int bool); +void snd_seq_client_info_set_event_filter(snd_seq_client_info_t *info, unsigned char *filter); + 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_query_next_client(snd_seq_t *handle, snd_seq_client_info_t *info); + +/* + */ + +/** client pool information container */ +typedef struct _snd_seq_client_pool snd_seq_client_pool_t; + +size_t snd_seq_client_pool_sizeof(void); +/** allocate a client_pool container in heap */ +#define snd_seq_client_pool_alloca(ptr) \ + SND_ALLOCA(snd_seq_client_pool, ptr) +int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr); +void snd_seq_client_pool_free(snd_seq_client_pool_t *ptr); +void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src); + +int snd_seq_client_pool_get_client(const snd_seq_client_pool_t *info); +size_t snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t *info); +size_t snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t *info); +size_t snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t *info); +size_t snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t *info); +size_t snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t *info); +void snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t *info, size_t size); +void snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t *info, size_t size); +void snd_seq_client_pool_set_output_room(snd_seq_client_pool_t *info, size_t size); + +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); + + +/** \} */ + + +/** + * \defgroup SeqPort Sequencer Port Interface + * Sequencer Port Interface + * \ingroup Sequencer + * \{ + */ + +/** port information container */ +typedef struct _snd_seq_port_info snd_seq_port_info_t; + +/** known port numbers */ +#define SND_SEQ_PORT_SYSTEM_TIMER 0 /**< system timer port */ +#define SND_SEQ_PORT_SYSTEM_ANNOUNCE 1 /**< sysem announce port */ + +/** port capabilities (32 bits) */ +#define SND_SEQ_PORT_CAP_READ (1<<0) /**< readable from this port */ +#define SND_SEQ_PORT_CAP_WRITE (1<<1) /**< writable to this port */ + +#define SND_SEQ_PORT_CAP_SYNC_READ (1<<2) /**< allow read subscriptions */ +#define SND_SEQ_PORT_CAP_SYNC_WRITE (1<<3) /**< allow write subscriptions */ + +#define SND_SEQ_PORT_CAP_DUPLEX (1<<4) /**< allow read/write duplex */ + +#define SND_SEQ_PORT_CAP_SUBS_READ (1<<5) /**< allow read subscription */ +#define SND_SEQ_PORT_CAP_SUBS_WRITE (1<<6) /**< allow write subscription */ +#define SND_SEQ_PORT_CAP_NO_EXPORT (1<<7) /**< routing not allowed */ + +/** port type */ +#define SND_SEQ_PORT_TYPE_SPECIFIC (1<<0) /**< hardware specific */ +#define SND_SEQ_PORT_TYPE_MIDI_GENERIC (1<<1) /**< generic MIDI device */ +#define SND_SEQ_PORT_TYPE_MIDI_GM (1<<2) /**< General MIDI compatible device */ +#define SND_SEQ_PORT_TYPE_MIDI_GS (1<<3) /**< GS compatible device */ +#define SND_SEQ_PORT_TYPE_MIDI_XG (1<<4) /**< XG compatible device */ +#define SND_SEQ_PORT_TYPE_MIDI_MT32 (1<<5) /**< MT-32 compatible device */ +#define SND_SEQ_PORT_TYPE_SYNTH (1<<10) /**< Synth device */ +#define SND_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /**< Sampling device (support sample download) */ +#define SND_SEQ_PORT_TYPE_SAMPLE (1<<12) /**< Sampling device (sample can be downloaded at any time) */ +#define SND_SEQ_PORT_TYPE_APPLICATION (1<<20) /**< application (sequencer/editor) */ + + +size_t snd_seq_port_info_sizeof(void); +/** allocate a port_info container in heap */ +#define snd_seq_port_info_alloca(ptr) \ + SND_ALLOCA(snd_seq_port_info, ptr) +int snd_seq_port_info_malloc(snd_seq_port_info_t **ptr); +void snd_seq_port_info_free(snd_seq_port_info_t *ptr); +void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src); + +int snd_seq_port_info_get_client(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_port(const snd_seq_port_info_t *info); +const snd_seq_addr_t *snd_seq_port_info_get_addr(const snd_seq_port_info_t *info); +const char *snd_seq_port_info_get_name(const snd_seq_port_info_t *info); +unsigned int snd_seq_port_info_get_capability(const snd_seq_port_info_t *info); +unsigned int snd_seq_port_info_get_type(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_read_use(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_write_use(const snd_seq_port_info_t *info); +int snd_seq_port_info_get_port_specified(const snd_seq_port_info_t *info); + +void snd_seq_port_info_set_client(snd_seq_port_info_t *info, int client); +void snd_seq_port_info_set_port(snd_seq_port_info_t *info, int port); +void snd_seq_port_info_set_addr(snd_seq_port_info_t *info, const snd_seq_addr_t *addr); +void snd_seq_port_info_set_name(snd_seq_port_info_t *info, const char *name); +void snd_seq_port_info_set_capability(snd_seq_port_info_t *info, unsigned int capability); +void snd_seq_port_info_set_type(snd_seq_port_info_t *info, unsigned int type); +void snd_seq_port_info_set_midi_channels(snd_seq_port_info_t *info, int channels); +void snd_seq_port_info_set_midi_voices(snd_seq_port_info_t *info, int voices); +void snd_seq_port_info_set_synth_voices(snd_seq_port_info_t *info, int voices); +void snd_seq_port_info_set_port_specified(snd_seq_port_info_t *info, int bool); + 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_delete_port(snd_seq_t *handle, int port); 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_query_next_port(snd_seq_t *handle, snd_seq_port_info_t *info); + +/** \} */ + + +/** + * \defgroup SeqSubscribe Sequencer Port Subscription + * Sequencer Port Subscription + * \ingroup Sequencer + * \{ + */ + +/** port subscription container */ +typedef struct _snd_seq_port_subscribe snd_seq_port_subscribe_t; + +size_t snd_seq_port_subscribe_sizeof(void); +/** allocate a port_subscribe container in heap */ +#define snd_seq_port_subscribe_alloca(ptr) \ + SND_ALLOCA(snd_seq_port_subscribe, ptr) +int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr); +void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *ptr); +void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src); + +const snd_seq_addr_t *snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t *info); +const snd_seq_addr_t *snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t *info); +int snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t *info); +int snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t *info); +int snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t *info); +int snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t *info); + +void snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr); +void snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr); +void snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t *info, int q); +void snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t *info, int bool); +void snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t *info, int bool); +void snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t *info, int bool); + 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); -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); + +/* + */ + +/** subscription query container */ +typedef struct _snd_seq_query_subscribe snd_seq_query_subscribe_t; + +/** type of query subscription */ +typedef enum { + SND_SEQ_QUERY_SUBS_READ, /**< query read subscriptions */ + SND_SEQ_QUERY_SUBS_WRITE /**< query write subscriptions */ +} snd_seq_query_subs_type_t; + +size_t snd_seq_query_subscribe_sizeof(void); +/** allocate a query_subscribe container in heap */ +#define snd_seq_query_subscribe_alloca(ptr) \ + SND_ALLOCA(snd_seq_query_subscribe, ptr) +int snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t **ptr); +void snd_seq_query_subscribe_free(snd_seq_query_subscribe_t *ptr); +void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src); + +int snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t *info); +const snd_seq_addr_t *snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t *info); +snd_seq_query_subs_type_t snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t *info); +const snd_seq_addr_t *snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t *info); +int snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t *info); + +void snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t *info, int client); +void snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t *info, int port); +void snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t *info, const snd_seq_addr_t *addr); +void snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t *info, snd_seq_query_subs_type_t type); +void snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t *info, int index); + +int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs); + +/** \} */ + + +/** + * \defgroup SeqQueue Sequencer Queue Interface + * Sequencer Queue Interface + * \ingroup Sequencer + * \{ + */ + +/** queue information container */ +typedef struct _snd_seq_queue_info snd_seq_queue_info_t; +/** queue status container */ +typedef struct _snd_seq_queue_status snd_seq_queue_status_t; +/** queue tempo container */ +typedef struct _snd_seq_queue_tempo snd_seq_queue_tempo_t; +/** queue timer information container */ +typedef struct _snd_seq_queue_timer snd_seq_queue_timer_t; + +/** special queue ids */ +#define SND_SEQ_QUEUE_DIRECT 253 /**< direct dispatch */ + +size_t snd_seq_queue_info_sizeof(void); +/** allocate a queue_info container in heap */ +#define snd_seq_queue_info_alloca(ptr) \ + SND_ALLOCA(snd_seq_queue_info, ptr) +int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr); +void snd_seq_queue_info_free(snd_seq_queue_info_t *ptr); +void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src); + +int snd_seq_queue_info_get_queue(const snd_seq_queue_info_t *info); +const char *snd_seq_queue_info_get_name(const snd_seq_queue_info_t *info); +int snd_seq_queue_info_get_owner(const snd_seq_queue_info_t *info); +int snd_seq_queue_info_get_locked(const snd_seq_queue_info_t *info); +unsigned int snd_seq_queue_info_get_flags(const snd_seq_queue_info_t *info); + +void snd_seq_queue_info_set_name(snd_seq_queue_info_t *info, const char *name); +void snd_seq_queue_info_set_owner(snd_seq_queue_info_t *info, int owner); +void snd_seq_queue_info_set_locked(snd_seq_queue_info_t *info, int locked); +void snd_seq_queue_info_set_flags(snd_seq_queue_info_t *info, unsigned int flags); + int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info); int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name); int snd_seq_alloc_queue(snd_seq_t *handle); -#ifdef SND_SEQ_SYNC_SUPPORT -int snd_seq_alloc_sync_queue(snd_seq_t *seq, const char *name); -#endif 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, const 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); -#ifdef SND_SEQ_SYNC_SUPPORT -typedef struct sndrv_seq_queue_sync snd_seq_queue_sync_t; -int snd_seq_add_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest, snd_seq_queue_sync_t *info); -int snd_seq_remove_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest); -int snd_seq_add_sync_std_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest, int format, int time_format, unsigned char *opt_info); -#define snd_seq_add_sync_master_clock(seq,q,dest) snd_seq_add_sync_std_master(seq, q, dest, SND_SEQ_SYNC_FMT_MIDI_CLOCK, 0, 0) -#define snd_seq_add_sync_master_mtc(seq,q,dest,tfmt) snd_seq_add_sync_std_master(seq, q, dest, SND_SEQ_SYNC_FMT_MTC, tfmt, 0) - -int snd_seq_set_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src, snd_seq_queue_sync_t *info); -int snd_seq_reset_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src); -#endif +int snd_seq_query_named_queue(snd_seq_t *seq, const char *name); -const char *snd_seq_name(snd_seq_t *seq); -snd_seq_type_t snd_seq_type(snd_seq_t *seq); +int snd_seq_get_queue_usage(snd_seq_t *handle, int q); +int snd_seq_set_queue_usage(snd_seq_t *handle, int q, int used); + +/* + */ +size_t snd_seq_queue_status_sizeof(void); +/** allocate a queue_status container in heap */ +#define snd_seq_queue_status_alloca(ptr) \ + SND_ALLOCA(snd_seq_queue_status, ptr) +int snd_seq_queue_status_malloc(snd_seq_queue_status_t **ptr); +void snd_seq_queue_status_free(snd_seq_queue_status_t *ptr); +void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src); + +int snd_seq_queue_status_get_queue(const snd_seq_queue_status_t *info); +int snd_seq_queue_status_get_events(const snd_seq_queue_status_t *info); +snd_seq_tick_time_t snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t *info); +const snd_seq_real_time_t *snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t *info); +unsigned int snd_seq_queue_status_get_status(const snd_seq_queue_status_t *info); + +int snd_seq_get_queue_status(snd_seq_t *handle, int q, snd_seq_queue_status_t *status); + +/* + */ +size_t snd_seq_queue_tempo_sizeof(void); +/** allocate a queue_tempo container in heap */ +#define snd_seq_queue_tempo_alloca(ptr) \ + SND_ALLOCA(snd_seq_queue_tempo, ptr) +int snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t **ptr); +void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *ptr); +void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src); + +int snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t *info); +unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info); +int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info); +void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo); +void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq); + +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); + +/* + */ +size_t snd_seq_queue_timer_sizeof(void); +/** allocate a queue_timer container in heap */ +#define snd_seq_queue_timer_alloca(ptr) \ + SND_ALLOCA(snd_seq_queue_timer, ptr) +int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr); +void snd_seq_queue_timer_free(snd_seq_queue_timer_t *ptr); +void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src); + +int snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t *info); +int snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t *info); +const snd_timer_id_t *snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t *info); +unsigned int snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t *info); + +void snd_seq_queue_timer_set_type(snd_seq_queue_timer_t *info, int type); +void snd_seq_queue_timer_set_id(snd_seq_queue_timer_t *info, const snd_timer_id_t *id); +void snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t *info, unsigned int resolution); + +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); + +/** \} */ + +/** + * \defgroup SeqEvent Sequencer Event API + * Sequencer Event API + * \ingroup Sequencer + * \{ + */ -/* event routines */ snd_seq_event_t *snd_seq_create_event(void); int snd_seq_free_event(snd_seq_event_t *ev); ssize_t snd_seq_event_length(snd_seq_event_t *ev); @@ -396,15 +453,211 @@ int snd_seq_drop_output(snd_seq_t *handle); int snd_seq_drop_output_buffer(snd_seq_t *handle); int snd_seq_drop_input(snd_seq_t *handle); int snd_seq_drop_input_buffer(snd_seq_t *handle); + +/** event removal conditionals */ +typedef struct _snd_seq_remove_events snd_seq_remove_events_t; + +/** Remove conditional flags */ +#define SND_SEQ_REMOVE_INPUT (1<<0) /**< Flush input queues */ +#define SND_SEQ_REMOVE_OUTPUT (1<<1) /**< Flush output queues */ +#define SND_SEQ_REMOVE_DEST (1<<2) /**< Restrict by destination q:client:port */ +#define SND_SEQ_REMOVE_DEST_CHANNEL (1<<3) /**< Restrict by channel */ +#define SND_SEQ_REMOVE_TIME_BEFORE (1<<4) /**< Restrict to before time */ +#define SND_SEQ_REMOVE_TIME_AFTER (1<<5) /**< Restrict to time or after */ +#define SND_SEQ_REMOVE_TIME_TICK (1<<6) /**< Time is in ticks */ +#define SND_SEQ_REMOVE_EVENT_TYPE (1<<7) /**< Restrict to event type */ +#define SND_SEQ_REMOVE_IGNORE_OFF (1<<8) /**< Do not flush off events */ +#define SND_SEQ_REMOVE_TAG_MATCH (1<<9) /**< Restrict to events with given tag */ + +size_t snd_seq_remove_events_sizeof(void); +/** allocate a remove_events container in heap */ +#define snd_seq_remove_events_alloca(ptr) \ + SND_ALLOCA(snd_seq_remove_events, ptr) +int snd_seq_remove_events_malloc(snd_seq_remove_events_t **ptr); +void snd_seq_remove_events_free(snd_seq_remove_events_t *ptr); +void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src); + +unsigned int snd_seq_remove_events_get_condition(const snd_seq_remove_events_t *info); +int snd_seq_remove_events_get_queue(const snd_seq_remove_events_t *info); +const snd_seq_timestamp_t *snd_seq_remove_events_get_time(const snd_seq_remove_events_t *info); +const snd_seq_addr_t *snd_seq_remove_events_get_dest(const snd_seq_remove_events_t *info); +int snd_seq_remove_events_get_channel(const snd_seq_remove_events_t *info); +int snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t *info); +int snd_seq_remove_events_get_tag(const snd_seq_remove_events_t *info); + +void snd_seq_remove_events_set_condition(snd_seq_remove_events_t *info, unsigned int flags); +void snd_seq_remove_events_set_queue(snd_seq_remove_events_t *info, int queue); +void snd_seq_remove_events_set_time(snd_seq_remove_events_t *info, const snd_seq_timestamp_t *time); +void snd_seq_remove_events_set_dest(snd_seq_remove_events_t *info, const snd_seq_addr_t *addr); +void snd_seq_remove_events_set_channel(snd_seq_remove_events_t *info, int channel); +void snd_seq_remove_events_set_event_type(snd_seq_remove_events_t *info, int type); +void snd_seq_remove_events_set_tag(snd_seq_remove_events_t *info, int tag); + int snd_seq_remove_events(snd_seq_t *handle, snd_seq_remove_events_t *info); -/* misc */ + +/** \} */ + +/** + * \defgroup SeqMisc Sequencer Miscellaneous + * Sequencer Mescellaneous + * \ingroup Sequencer + * \{ + */ + 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 +/** \} */ + + +/** + * \defgroup SeqEvType Sequencer Event Type Checks + * Sequencer Event Type Checks + * \ingroup Sequencer + * \{ + */ + +/* event type macros */ +enum { + SND_SEQ_EVFLG_RESULT, + SND_SEQ_EVFLG_NOTE, + SND_SEQ_EVFLG_CONTROL, + SND_SEQ_EVFLG_QUEUE, + SND_SEQ_EVFLG_SYSTEM, + SND_SEQ_EVFLG_MESSAGE, + SND_SEQ_EVFLG_CONNECTION, + SND_SEQ_EVFLG_SAMPLE, + SND_SEQ_EVFLG_USERS, + SND_SEQ_EVFLG_INSTR, + SND_SEQ_EVFLG_QUOTE, + SND_SEQ_EVFLG_NONE, + SND_SEQ_EVFLG_RAW, + SND_SEQ_EVFLG_FIXED, + SND_SEQ_EVFLG_VARIABLE, + SND_SEQ_EVFLG_VARUSR, + SND_SEQ_EVFLG_IPC +}; + +enum { + SND_SEQ_EVFLG_NOTE_ONEARG, + SND_SEQ_EVFLG_NOTE_TWOARG +}; +enum { + SND_SEQ_EVFLG_QUEUE_NOARG, + SND_SEQ_EVFLG_QUEUE_TICK, + SND_SEQ_EVFLG_QUEUE_TIME, + SND_SEQ_EVFLG_QUEUE_VALUE +}; + +/** + * Exported event type table + * + * This table is referred by snd_seq_ev_is_xxx. + */ +extern const unsigned int snd_seq_event_types[]; + +#define _SND_SEQ_TYPE(x) (1<<(x)) /* 24bit */ +#define _SND_SEQ_TYPE_OPT(x) ((x)<<24) /* 8bit */ + +#define snd_seq_type_check(ev,x) (snd_seq_event_types[(ev)->type] & _SND_SEQ_TYPE(x)) + +/** event type check: result events */ +#define snd_seq_ev_is_result_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_RESULT) +/** event type check: note events */ +#define snd_seq_ev_is_note_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_NOTE) +/** event type check: control events */ +#define snd_seq_ev_is_control_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_CONTROL) +/** event type check: channel specific events */ +#define snd_seq_ev_is_channel_type(ev) \ + (snd_seq_event_types[(ev)->type] & (_SND_SEQ_TYPE(SND_SEQ_EVFLG_NOTE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_CONTROL))) + +/** event type check: queue control events */ +#define snd_seq_ev_is_queue_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_QUEUE) +/** event type check: system status messages */ +#define snd_seq_ev_is_message_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_MESSAGE) +/** event type check: system status messages */ +#define snd_seq_ev_is_subscribe_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_CONNECTION) +/** event type check: sample messages */ +#define snd_seq_ev_is_sample_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_SAMPLE) +/** event type check: user-defined messages */ +#define snd_seq_ev_is_user_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_USERS) +/** event type check: instrument layer events */ +#define snd_seq_ev_is_instr_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_INSTR) +/** event type check: fixed length events */ +#define snd_seq_ev_is_fixed_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_FIXED) +/** event type check: variable length events */ +#define snd_seq_ev_is_variable_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_VARIABLE) +/** event type check: user pointer events */ +#define snd_seq_ev_is_varusr_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_VARUSR) +/** event type check: ipc events */ +#define snd_seq_ev_is_varipc_type(ev) \ + snd_seq_type_check(ev, SND_SEQ_EVFLG_IPC) +/** event type check: reserved for kernel */ +#define snd_seq_ev_is_reserved(ev) \ + (! snd_seq_event_types[(ev)->type]) + +/** + * macros to check event flags + */ +/** prior events */ +#define snd_seq_ev_is_prior(ev) \ + (((ev)->flags & SND_SEQ_PRIORITY_MASK) == SND_SEQ_PRIORITY_HIGH) + +/** get the data length type */ +#define snd_seq_ev_length_type(ev) \ + ((ev)->flags & SND_SEQ_EVENT_LENGTH_MASK) +/** fixed length events */ +#define snd_seq_ev_is_fixed(ev) \ + (snd_seq_ev_length_type(ev) == SND_SEQ_EVENT_LENGTH_FIXED) +/** variable length events */ +#define snd_seq_ev_is_variable(ev) \ + (snd_seq_ev_length_type(ev) == SND_SEQ_EVENT_LENGTH_VARIABLE) +/** variable length on user-space */ +#define snd_seq_ev_is_varusr(ev) \ + (snd_seq_ev_length_type(ev) == SND_SEQ_EVENT_LENGTH_VARUSR) +/** variable length on IPC shm */ +#define snd_seq_ev_is_varipc(ev) \ + (snd_seq_ev_length_type(ev) == SND_SEQ_EVENT_LENGTH_VARIPC) + +/** time-stamp type */ +#define snd_seq_ev_timestamp_type(ev) \ + ((ev)->flags & SND_SEQ_TIME_STAMP_MASK) +/** event is in tick time */ +#define snd_seq_ev_is_tick(ev) \ + (snd_seq_ev_timestamp_type(ev) == SND_SEQ_TIME_STAMP_TICK) +/** event is in real-time */ +#define snd_seq_ev_is_real(ev) \ + (snd_seq_ev_timestamp_type(ev) == SND_SEQ_TIME_STAMP_REAL) + +/** time-mode type */ +#define snd_seq_ev_timemode_type(ev) \ + ((ev)->flags & SND_SEQ_TIME_MODE_MASK) +/** scheduled in absolute time */ +#define snd_seq_ev_is_abstime(ev) \ + (snd_seq_ev_timemode_type(ev) == SND_SEQ_TIME_MODE_ABS) +/** scheduled in relative time */ +#define snd_seq_ev_is_reltime(ev) \ + (snd_seq_ev_timemode_type(ev) == SND_SEQ_TIME_MODE_REL) + +/** direct dispatched events */ +#define snd_seq_ev_is_direct(ev) \ + ((ev)->queue == SND_SEQ_QUEUE_DIRECT) /** \} */ +#ifdef __cplusplus +} +#endif diff --git a/include/seq_event.h b/include/seq_event.h new file mode 100644 index 00000000..b8a6fc16 --- /dev/null +++ b/include/seq_event.h @@ -0,0 +1,432 @@ +/** + * \defgroup Sequencer Sequencer Interface + * Sequencer Interface + * \{ + */ + +/** \} */ + +/** + * \defgroup SeqEvents Sequencer Event Definitions + * Sequencer Event Definitions + * \ingroup Sequencer + * \{ + */ + +/** + * Sequencer event data type + */ +typedef unsigned char snd_seq_event_type_t; + +enum snd_seq_event_type { + /** system status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_SYSTEM = 0, + /** returned result status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_RESULT, + + /** note on and off with duration; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTE = 5, + /** note on; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEON, + /** note off; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEOFF, + /** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_KEYPRESS, + + /** controller; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROLLER = 10, + /** program change; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_PGMCHANGE, + /** channel pressure; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CHANPRESS, + /** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ + SND_SEQ_EVENT_PITCHBEND, + /** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROL14, + /** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_NONREGPARAM, + /** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_REGPARAM, + + /** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGPOS = 20, + /** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGSEL, + /** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_QFRAME, + /** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_TIMESIGN, + /** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_KEYSIGN, + + /** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_START = 30, + /** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CONTINUE, + /** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_STOP, + /** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TICK, + /** Set realtime queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TIME, + /** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TEMPO, + /** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CLOCK, + /** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TICK, + /** Sync signal; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SYNC, + /** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SYNC_POS, + + /** Tune request; event data type = none */ + SND_SEQ_EVENT_TUNE_REQUEST = 40, + /** Reset to power-on state; event data type = none */ + SND_SEQ_EVENT_RESET, + /** Active sensing event; event data type = none */ + SND_SEQ_EVENT_SENSING, + + /** Echo-back event; event data type = any type */ + SND_SEQ_EVENT_ECHO = 50, + /** OSS emulation raw event; event data type = any type */ + SND_SEQ_EVENT_OSS, + + /** New client has connected; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_START, + /** Client has left the system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_EXIT, + /** Client status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_CHANGE, + /** New port was created; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_START, + /** Port was deleted from system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_EXIT, + /** Port status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_CHANGE, + + /** Ports connected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_SUBSCRIBED, + /** Ports disconnected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_UNSUBSCRIBED, + + /** Sample select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE = 70, + /** Sample cluster select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE_CLUSTER, + /** voice start */ + SND_SEQ_EVENT_SAMPLE_START, + /** voice stop */ + SND_SEQ_EVENT_SAMPLE_STOP, + /** playback frequency */ + SND_SEQ_EVENT_SAMPLE_FREQ, + /** volume and balance */ + SND_SEQ_EVENT_SAMPLE_VOLUME, + /** sample loop */ + SND_SEQ_EVENT_SAMPLE_LOOP, + /** sample position */ + SND_SEQ_EVENT_SAMPLE_POSITION, + /** private (hardware dependent) event */ + SND_SEQ_EVENT_SAMPLE_PRIVATE1, + + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR0 = 90, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR1, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR2, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR3, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR4, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR5, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR6, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR7, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR8, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR9, + + /** begin of instrument management */ + SND_SEQ_EVENT_INSTR_BEGIN = 100, + /** end of instrument management */ + SND_SEQ_EVENT_INSTR_END, + /** query instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO, + /** result of instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO_RESULT, + /** query instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO, + /** result of instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO_RESULT, + /** reset instrument instrument memory */ + SND_SEQ_EVENT_INSTR_RESET, + /** get instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS, + /** result of instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS_RESULT, + /** put an instrument to port */ + SND_SEQ_EVENT_INSTR_PUT, + /** get an instrument from port */ + SND_SEQ_EVENT_INSTR_GET, + /** result of instrument query */ + SND_SEQ_EVENT_INSTR_GET_RESULT, + /** free instrument(s) */ + SND_SEQ_EVENT_INSTR_FREE, + /** get instrument list */ + SND_SEQ_EVENT_INSTR_LIST, + /** result of instrument list */ + SND_SEQ_EVENT_INSTR_LIST_RESULT, + /** set cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER, + /** get cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_GET, + /** result of cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_RESULT, + /** instrument change */ + SND_SEQ_EVENT_INSTR_CHANGE, + + /** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_SYSEX = 130, + /** error event; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_BOUNCE, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR0 = 135, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR1, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR2, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR3, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR4, + + /** NOP; ignored in any case */ + SND_SEQ_EVENT_NONE = 255 +}; + + +#ifndef _SND_SEQ_IN_LOCAL + +/** Sequencer event address */ +typedef struct snd_seq_addr { + unsigned char client; /**< Client id */ + unsigned char port; /**< Port id */ +} snd_seq_addr_t; + +/** Connection (subscription) between ports */ +typedef struct snd_seq_connect { + snd_seq_addr_t sender; /**< sender address */ + snd_seq_addr_t dest; /**< destination address */ +} snd_seq_connect_t; + + +/** Real-time data record */ +typedef struct snd_seq_real_time { + unsigned int tv_sec; /**< seconds */ + unsigned int tv_nsec; /**< nanoseconds */ +} snd_seq_real_time_t; + +/** (MIDI) Tick-time data record */ +typedef unsigned int snd_seq_tick_time_t; + +/** unioned time stamp */ +typedef union snd_seq_timestamp { + snd_seq_tick_time_t tick; /**< tick-time */ + struct snd_seq_real_time time; /**< real-time */ +} snd_seq_timestamp_t; + + +/** + * Event mode flags + * + * NOTE: only 8 bits available! + */ +#define SND_SEQ_TIME_STAMP_TICK (0<<0) /**< timestamp in clock ticks */ +#define SND_SEQ_TIME_STAMP_REAL (1<<0) /**< timestamp in real time */ +#define SND_SEQ_TIME_STAMP_MASK (1<<0) /**< mask for timestamp bits */ + +#define SND_SEQ_TIME_MODE_ABS (0<<1) /**< absolute timestamp */ +#define SND_SEQ_TIME_MODE_REL (1<<1) /**< relative to current time */ +#define SND_SEQ_TIME_MODE_MASK (1<<1) /**< mask for time mode bits */ + +#define SND_SEQ_EVENT_LENGTH_FIXED (0<<2) /**< fixed event size */ +#define SND_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /**< variable event size */ +#define SND_SEQ_EVENT_LENGTH_VARUSR (2<<2) /**< variable event size - user memory space */ +#define SND_SEQ_EVENT_LENGTH_VARIPC (3<<2) /**< variable event size - IPC */ +#define SND_SEQ_EVENT_LENGTH_MASK (3<<2) /**< mask for event length bits */ + +#define SND_SEQ_PRIORITY_NORMAL (0<<4) /**< normal priority */ +#define SND_SEQ_PRIORITY_HIGH (1<<4) /**< event should be processed before others */ +#define SND_SEQ_PRIORITY_MASK (1<<4) /**< mask for priority bits */ + + +/** Note event */ +typedef struct snd_seq_ev_note { + unsigned char channel; /**< channel number */ + unsigned char note; /**< note */ + unsigned char velocity; /**< velocity */ + unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ + unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ +} snd_seq_ev_note_t; + +/** Controller event */ +typedef struct snd_seq_ev_ctrl { + unsigned char channel; /**< channel number */ + unsigned char unused[3]; /**< reserved */ + unsigned int param; /**< control parameter */ + signed int value; /**< control value */ +} snd_seq_ev_ctrl_t; + +/** generic set of bytes (12x8 bit) */ +typedef struct snd_seq_ev_raw8 { + unsigned char d[12]; /**< 8 bit value */ +} snd_seq_ev_raw8_t; + +/** generic set of integers (3x32 bit) */ +typedef struct snd_seq_ev_raw32 { + unsigned int d[3]; /**< 32 bit value */ +} snd_seq_ev_raw32_t; + +/** external stored data */ +typedef struct snd_seq_ev_ext { + size_t len; /**< length of data */ + void *ptr; /**< pointer to data (note: can be 64-bit) */ +} snd_seq_ev_ext_t; + +/** external stored data - IPC shared memory */ +typedef struct snd_seq_ev_ipcshm { + size_t len; /**< length of data */ + key_t ipc; /**< IPC key */ +} snd_seq_ev_ipcshm_t; + +/** Instrument cluster type */ +typedef unsigned int snd_seq_instr_cluster_t; + +/** Instrument type */ +typedef struct snd_seq_instr { + snd_seq_instr_cluster_t cluster; /**< cluster id */ + unsigned int std; /**< instrument standard id; the upper byte means a private instrument (owner - client id) */ + unsigned short bank; /**< instrument bank id */ + unsigned short prg; /**< instrument program id */ +} snd_seq_instr_t; + +/** sample number */ +typedef struct snd_seq_ev_sample { + unsigned int std; /**< sample standard id */ + unsigned short bank; /**< sample bank id */ + unsigned short prg; /**< sample program id */ +} snd_seq_ev_sample_t; + +/** sample cluster */ +typedef struct snd_seq_ev_cluster { + snd_seq_instr_cluster_t cluster; /**< cluster id */ +} snd_seq_ev_cluster_t; + +/** sample position */ +typedef unsigned int snd_seq_position_t; /**< playback position (in samples) * 16 */ + +/** sample stop mode */ +typedef enum snd_seq_stop_mode { + SND_SEQ_SAMPLE_STOP_IMMEDIATELY = 0, /**< terminate playing immediately */ + SND_SEQ_SAMPLE_STOP_VENVELOPE = 1, /**< finish volume envelope */ + SDN_SEQ_SAMPLE_STOP_LOOP = 2 /**< terminate loop and finish wave */ +} snd_seq_stop_mode_t; + +/** sample frequency */ +typedef int snd_seq_frequency_t; /**< playback frequency in HZ * 16 */ + +/** sample volume control; if any value is set to -1 == do not change */ +typedef struct snd_seq_ev_volume { + signed short volume; /**< range: 0-16383 */ + signed short lr; /**< left-right balance; range: 0-16383 */ + signed short fr; /**< front-rear balance; range: 0-16383 */ + signed short du; /**< down-up balance; range: 0-16383 */ +} snd_seq_ev_volume_t; + +/** simple loop redefinition */ +typedef struct snd_seq_ev_loop { + unsigned int start; /**< loop start (in samples) * 16 */ + unsigned int end; /**< loop end (in samples) * 16 */ +} snd_seq_ev_loop_t; + +/** Sample control events */ +typedef struct snd_seq_ev_sample_control { + unsigned char channel; /**< channel */ + unsigned char unused[3]; /**< reserved */ + union { + snd_seq_ev_sample_t sample; + snd_seq_ev_cluster_t cluster; + snd_seq_position_t position; + snd_seq_stop_mode_t stop_mode; + snd_seq_frequency_t frequency; + snd_seq_ev_volume_t volume; + snd_seq_ev_loop_t loop; + unsigned char raw8[8]; + } param; /**< control parameters */ +} snd_seq_ev_sample_control_t; + + + +/** INSTR_BEGIN event */ +typedef struct snd_seq_ev_instr_begin { + int timeout; /**< zero = forever, otherwise timeout in ms */ +} snd_seq_ev_instr_begin_t; + +/** Result events */ +typedef struct snd_seq_result { + int event; /**< processed event type */ + int result; /**< status */ +} snd_seq_result_t; + + +/** queue timer control */ +typedef struct snd_seq_ev_queue_control { + unsigned char queue; /**< affected queue */ + unsigned char unused[3]; /**< reserved */ + union { + signed int value; /**< affected value (e.g. tempo) */ + snd_seq_timestamp_t time; /**< time */ + unsigned int position; /**< sync position */ + unsigned int d32[2]; /**< any data */ + unsigned char d8[8]; /**< any data */ + } param; /**< data value union */ +} snd_seq_ev_queue_control_t; + + +/** Sequencer event */ +typedef struct snd_seq_event { + snd_seq_event_type_t type; /**< event type */ + unsigned char flags; /**< event flags */ + unsigned char tag; /**< tag */ + + unsigned char queue; /**< schedule queue */ + snd_seq_timestamp_t time; /**< schedule time */ + + snd_seq_addr_t source; /**< source address */ + snd_seq_addr_t dest; /**< destination address */ + + union { + snd_seq_ev_note_t note; + snd_seq_ev_ctrl_t control; + snd_seq_ev_raw8_t raw8; + snd_seq_ev_raw32_t raw32; + snd_seq_ev_ext_t ext; + snd_seq_ev_ipcshm_t ipcshm; + snd_seq_ev_queue_control_t queue; + snd_seq_timestamp_t time; + snd_seq_addr_t addr; + snd_seq_connect_t connect; + snd_seq_result_t result; + snd_seq_ev_instr_begin_t instr_begin; + snd_seq_ev_sample_control_t sample; + } data; /**< event data... */ +} snd_seq_event_t; + +#endif /* _SND_SEQ_IN_LOCAL */ + + +/** \} */ diff --git a/include/seqmid.h b/include/seqmid.h index 63dc11c5..8951807c 100644 --- a/include/seqmid.h +++ b/include/seqmid.h @@ -4,6 +4,10 @@ * * ****************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + /** * \defgroup SeqMiddle Sequencer Middle Level Interface * Sequencer Middle Level Interface @@ -11,213 +15,395 @@ * \{ */ -#ifdef __cplusplus -extern "C" { -#endif +/** + * \brief initialize event record + * \param ev event record pointer + */ +#define snd_seq_ev_clear(ev) \ + memset(ev, 0, sizeof(snd_seq_event_t)) -/* 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); +/** + * \brief set the explicit destination + * \param ev event record + * \param c destination client id + * \param p destination port id + */ +#define snd_seq_ev_set_dest(ev,c,p) \ + ((ev)->dest.client = (c), (ev)->dest.port = (p)) -/* - * use/unuse a queue +/** + * \brief set broadcasting to subscribers + * \param ev event record */ -int snd_seq_use_queue(snd_seq_t *seq, int q, int use); +#define snd_seq_ev_set_subs(ev) \ + ((ev)->dest.client = SND_SEQ_ADDRESS_SUBSCRIBERS,\ + (ev)->dest.port = SND_SEQ_ADDRESS_UNKNOWN) -/* 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. +/** + * \brief set broadcasting to all clients/ports + * \param ev event record */ -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); +#define snd_seq_ev_set_broadcast(ev) \ + ((ev)->dest.client = SND_SEQ_ADDRESS_BROADCAST,\ + (ev)->dest.port = SND_SEQ_ADDRESS_BROADCAST) -/* create a port - simple version - return the port number */ -int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, - unsigned int caps, unsigned int type); -/* delete the port */ -int snd_seq_delete_simple_port(snd_seq_t *seq, int port); +/** + * \brief set the source port + * \param ev event record + * \param p source port id + */ +#define snd_seq_ev_set_source(ev,p) \ + ((ev)->source.port = (p)) -/* 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); +/** + * \brief set direct passing mode (without queued) + * \param ev event instance + */ +#define snd_seq_ev_set_direct(ev) \ + ((ev)->queue = SNDRV_SEQ_QUEUE_DIRECT) -/* - * set client information +/** + * \brief set tick-scheduling mode on queue + * \param ev event instance + * \param q queue id to schedule + * \param relative relative time-stamp if non-zero + * \param ttick tick time-stap to be delivered */ -int snd_seq_set_client_name(snd_seq_t *seq, const char *name); -int snd_seq_set_client_group(snd_seq_t *seq, const 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); +#define snd_seq_ev_schedule_tick(ev, q, relative, ttick) \ + ((ev)->flags &= ~(SNDRV_SEQ_TIME_STAMP_MASK | SNDRV_SEQ_TIME_MODE_MASK),\ + (ev)->flags |= SNDRV_SEQ_TIME_STAMP_TICK,\ + (ev)->flags |= (relative) ? SNDRV_SEQ_TIME_MODE_REL : SNDRV_SEQ_TIME_MODE_ABS,\ + (ev)->time.tick = (ttick),\ + (ev)->queue = (q)) -/* - * reset client input/output pool +/** + * \brief set real-time-scheduling mode on queue + * \param ev event instance + * \param q queue id to schedule + * \param relative relative time-stamp if non-zero + * \param rtime time-stamp to be delivered */ -int snd_seq_reset_pool_output(snd_seq_t *seq); -int snd_seq_reset_pool_input(snd_seq_t *seq); +#define snd_seq_ev_schedule_real(ev, q, relative, rtime) \ + ((ev)->flags &= ~( SNDRV_SEQ_TIME_STAMP_MASK | SNDRV_SEQ_TIME_MODE_MASK),\ + (ev)->flags |= SNDRV_SEQ_TIME_STAMP_REAL,\ + (ev)->flags |= (relative) ? SNDRV_SEQ_TIME_MODE_REL : SNDRV_SEQ_TIME_MODE_ABS,\ + (ev)->time.time = *(rtime),\ + (ev)->queue = (q)) -/* - * equivalent macros +/** + * \brief set event priority + * \param ev event instance + * \param high_prior 1 for high priority mode */ -#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)) +#define snd_seq_ev_set_priority(ev, high_prior) \ + ((ev)->flags &= ~SNDRV_SEQ_PRIORITY_MASK,\ + (ev)->flags |= (high_prior) ? SNDRV_SEQ_PRIORITY_HIGH : SNDRV_SEQ_PRIORITY_NORMAL) -/* - * queue controls +/** + * \brief set fixed data + * \param ev event instance + * + * Sets the event length mode as fixed size. + */ +#define snd_seq_ev_set_fixed(ev) \ + ((ev)->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK,\ + (ev)->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED) + +/** + * \brief set variable data + * \param ev event instance + * \param datalen length of the external data + * \param dataptr pointer of the external data + * + * Sets the event length mode as variable length and stores the data. + */ +#define snd_seq_ev_set_variable(ev, datalen, dataptr) \ + ((ev)->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK,\ + (ev)->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE,\ + (ev)->data.ext.len = (datalen),\ + (ev)->data.ext.ptr = (dataptr)) + +/** + * \brief set varusr data + * \param ev event instance + * \param len length of the external data + * \param ptr pointer of the external data + * + * Sets the event length mode as variable user-space data and stores the data. + */ +#define snd_seq_ev_set_varusr(ev, datalen, dataptr) \ + ((ev)->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK,\ + (ev)->flags |= SNDRV_SEQ_EVENT_LENGTH_VARUSR,\ + (ev)->data.ext.len = (datalen),\ + (ev)->data.ext.ptr = (dataptr)) + +/** + * \brief set queue controls + * \param ev event record + * \param typ event type + * \param q queue id + * \param val control value */ -#define snd_seq_ev_set_queue_control(ev,t,q,val) \ - ((ev)->type = (t),\ +#define snd_seq_ev_set_queue_control(ev, typ, q, val) \ + ((ev)->type = (typ),\ 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) \ + +/** + * \brief set the start queue event + * \param ev event record + * \param q queud id to start + */ +#define snd_seq_ev_set_queue_start(ev, q) \ + snd_seq_ev_set_queue_control(ev, SND_SEQ_EVENT_START, q, 0) + +/** + * \brief set the stop queue event + * \param ev event record + * \param q queud id to stop + */ +#define snd_seq_ev_set_queue_stop(ev, q) \ + snd_seq_ev_set_queue_control(ev, SND_SEQ_EVENT_STOP, q, 0) + +/** + * \brief set the stop queue event + * \param ev event record + * \param q queud id to continue + */ +#define snd_seq_ev_set_queue_continue(ev, q) \ + snd_seq_ev_set_queue_control(ev, SND_SEQ_EVENT_CONTINUE, q, 0) + +/** + * \brief set the stop queue event + * \param ev event record + * \param q queud id to change tempo + * \param val the new tempo value + */ +#define snd_seq_ev_set_queue_tempo(ev, q, val) \ + snd_seq_ev_set_queue_control(ev, SND_SEQ_EVENT_TEMPO, q, val) + +/** + * \brief set the real-time position of a queue + * \param ev event record + * \param q queud id to change tempo + * \param rtime the new real-time pointer + */ +#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) \ + +/** + * \brief set the tick-time position of a queue + * \param ev event record + * \param q queud id to change tempo + * \param ttime the new tick-time + */ +#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) \ +/* set and send a queue control event */ +int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev); + +/** + * \brief start the specified queue + * \param seq sequencer handle + * \param q queue id to start + * \param ev optional event record (see #snd_seq_control_queue) + */ +#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) \ + +/** + * \brief stop the specified queue + * \param seq sequencer handle + * \param q queue id to stop + * \param ev optional event record (see #snd_seq_control_queue) + */ +#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) \ + +/** + * \brief continue the specified queue + * \param seq sequencer handle + * \param q queue id to continue + * \param ev optional event record (see #snd_seq_control_queue) + */ +#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) \ + +/** + * \brief change the tempo of the specified queue + * \param seq sequencer handle + * \param q queue id + * \param tempo the new tempo value + * \param ev optional event record (see #snd_seq_control_queue) + */ +#define snd_seq_change_queue_tempo(seq, q, tempo, ev) \ snd_seq_control_queue(seq, q, SND_SEQ_EVENT_TEMPO, tempo, ev) +/* create a port - simple version - return the port number */ +int snd_seq_create_simple_port(snd_seq_t *seq, const 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); + /* - * macros to set standard event data + * set client information */ -#define snd_seq_ev_set_note(ev,ch,key,vel,dur) \ +int snd_seq_set_client_name(snd_seq_t *seq, const char *name); +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, size_t size); +int snd_seq_set_client_pool_output_room(snd_seq_t *seq, size_t size); +int snd_seq_set_client_pool_input(snd_seq_t *seq, size_t size); + +/* + * parse the given string and get the sequencer address + */ +int snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *str); + +/* + * 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); + +/** + * \brief set note event + * \param ev event record + * \param ch channel number + * \param key note key + * \param vel velocity + * \param dur duration (in tick or msec) + */ +#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)->data.note.duration = (dur)) + +/** + * \brief set note-on event + * \param ev event record + * \param ch channel number + * \param key note key + * \param vel velocity + */ +#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) \ + +/** + * \brief set note-off event + * \param ev event record + * \param ch channel number + * \param key note key + * \param vel velocity + */ +#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)) + +/** + * \brief set key-pressure event + * \param ev event record + * \param ch channel number + * \param key note key + * \param vel velocity + */ #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)) + +/** + * \brief set MIDI controller event + * \param ev event record + * \param ch channel number + * \param cc controller number + * \param val control value + */ #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)) + +/** + * \brief set program change event + * \param ev event record + * \param ch channel number + * \param val program number + */ #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)) + +/** + * \brief set pitchbend event + * \param ev event record + * \param ch channel number + * \param val pitch bend; zero centered from -8192 to 8191 + */ #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)) + +/** + * \brief set channel pressure event + * \param ev event record + * \param ch channel number + * \param val channel pressure value + */ #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)) + +/** + * \brief set sysex event + * \param ev event record + * \param datalen length of sysex data + * \param dataptr sysex data pointer + * + * the sysex data must contain the start byte 0xf0 and the end byte 0xf7. + */ #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 -/** \} */ - diff --git a/src/instr/fm.c b/src/instr/fm.c index bdc409b8..6d31a702 100644 --- a/src/instr/fm.c +++ b/src/instr/fm.c @@ -27,7 +27,7 @@ #include #include -int snd_instr_fm_free(snd_instr_simple_t *fm) +int snd_instr_fm_free(snd_instr_fm_t *fm) { if (fm == NULL) return 0; @@ -37,11 +37,10 @@ int snd_instr_fm_free(snd_instr_simple_t *fm) int snd_instr_fm_convert_to_stream(snd_instr_fm_t *fm, const char *name, - snd_seq_instr_put_t **__data, + snd_instr_header_t **__data, size_t *__size) { - snd_seq_instr_put_t *put; - snd_seq_instr_data_t *data; + snd_instr_header_t *put; fm_instrument_t *instr; fm_xinstrument_t *xinstr; int idx; @@ -51,18 +50,15 @@ int snd_instr_fm_convert_to_stream(snd_instr_fm_t *fm, instr = (fm_instrument_t *)fm; *__data = NULL; *__size = 0; - put = (snd_seq_instr_put_t *)malloc(sizeof(*put) + sizeof(fm_xinstrument_t)); - if (put == NULL) + if (snd_instr_header_malloc(&put, sizeof(fm_xinstrument_t)) < 0) return -ENOMEM; /* build header */ - memset(put, 0, sizeof(*put)); - data = &put->data; if (name) - strncpy(data->name, name, sizeof(data->name)-1); - data->type = SND_SEQ_INSTR_ATYPE_DATA; - strcpy(data->data.format, SND_SEQ_INSTR_ID_OPL2_3); + snd_instr_header_set_name(put, name); + snd_instr_header_set_type(put, SND_SEQ_INSTR_ATYPE_DATA); + snd_instr_header_set_format(put, SND_SEQ_INSTR_ID_OPL2_3); /* build data section */ - xinstr = (fm_xinstrument_t *)(data + 1); + xinstr = (fm_xinstrument_t *)snd_instr_header_get_data(put); xinstr->stype = FM_STRU_INSTR; xinstr->share_id[0] = __cpu_to_le32(instr->share_id[0]); xinstr->share_id[1] = __cpu_to_le32(instr->share_id[1]); @@ -93,7 +89,7 @@ int snd_instr_fm_convert_to_stream(snd_instr_fm_t *fm, return 0; } -int snd_instr_fm_convert_from_stream(snd_seq_instr_get_t *__data ATTRIBUTE_UNUSED, +int snd_instr_fm_convert_from_stream(snd_instr_header_t *__data ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED, snd_instr_fm_t **simple ATTRIBUTE_UNUSED) { diff --git a/src/instr/iwffff.c b/src/instr/iwffff.c index 770b2b29..df1fd172 100644 --- a/src/instr/iwffff.c +++ b/src/instr/iwffff.c @@ -740,11 +740,10 @@ static int copy_env_to_stream(iwffff_xenv_t *xenv, iwffff_env_t *env, __u32 styp int snd_instr_iwffff_conv_to_stream(snd_instr_iwffff_t *iwffff, const char *name, - snd_seq_instr_put_t **__data, + snd_instr_header_t **__data, long *__size) { - snd_seq_instr_put_t *put; - snd_seq_instr_data_t *data; + snd_instr_header_t *put; int size; char *ptr; iwffff_instrument_t *instr; @@ -759,19 +758,16 @@ int snd_instr_iwffff_conv_to_stream(snd_instr_iwffff_t *iwffff, instr = (iwffff_instrument_t *)iwffff; *__data = NULL; *__size = 0; - size = sizeof(*data) + iwffff_size(iwffff); - put = (snd_seq_instr_put_t *)malloc(sizeof(*put) + size); - if (put == NULL) + size = iwffff_size(iwffff); + if (snd_instr_header_malloc(&put, size) < 0) return -ENOMEM; /* build header */ - memset(put, 0, sizeof(*put)); - data = &put->data; if (name) - strncpy(data->name, name, sizeof(data->name)-1); - data->type = SND_SEQ_INSTR_ATYPE_DATA; - strcpy(data->data.format, SND_SEQ_INSTR_ID_INTERWAVE); + snd_instr_header_set_name(put, name); + snd_instr_header_set_type(put, SND_SEQ_INSTR_ATYPE_DATA); + snd_instr_header_set_format(put, SND_SEQ_INSTR_ID_INTERWAVE); /* build data section */ - xinstr = (iwffff_xinstrument_t *)(data + 1); + xinstr = (iwffff_xinstrument_t *)snd_instr_header_get_data(put); xinstr->stype = IWFFFF_STRU_INSTR; xinstr->exclusion = __cpu_to_le16(instr->exclusion); xinstr->layer_type = __cpu_to_le16(instr->layer_type); @@ -827,11 +823,11 @@ int snd_instr_iwffff_conv_to_stream(snd_instr_iwffff_t *iwffff, } /* write result */ *__data = put; - *__size = size; + *__size = sizeof(*put) + size; return 0; } -int snd_instr_iwffff_convert_from_stream(snd_seq_instr_get_t *data ATTRIBUTE_UNUSED, +int snd_instr_iwffff_convert_from_stream(snd_instr_header_t *data ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED, snd_instr_iwffff_t **iwffff ATTRIBUTE_UNUSED) { diff --git a/src/instr/simple.c b/src/instr/simple.c index 776ead19..3200210a 100644 --- a/src/instr/simple.c +++ b/src/instr/simple.c @@ -50,11 +50,10 @@ static long simple_size(simple_instrument_t *instr) int snd_instr_simple_convert_to_stream(snd_instr_simple_t *simple, const char *name, - snd_seq_instr_put_t **__data, + snd_instr_header_t **__data, size_t *__size) { - snd_seq_instr_put_t *put; - snd_seq_instr_data_t *data; + snd_instr_header_t *put; int size; char *ptr; simple_instrument_t *instr; @@ -66,18 +65,15 @@ int snd_instr_simple_convert_to_stream(snd_instr_simple_t *simple, *__data = NULL; *__size = 0; size = simple_size(simple); - put = (snd_seq_instr_put_t *)malloc(sizeof(*put) + sizeof(simple_xinstrument_t) + size); - if (put == NULL) + if (snd_instr_header_malloc(&put, sizeof(simple_xinstrument_t) + size) < 0) return -ENOMEM; /* build header */ - memset(put, 0, sizeof(*put)); - data = &put->data; if (name) - strncpy(data->name, name, sizeof(data->name)-1); - data->type = SND_SEQ_INSTR_ATYPE_DATA; - strcpy(data->data.format, SND_SEQ_INSTR_ID_SIMPLE); + snd_instr_header_set_name(put, name); + snd_instr_header_set_type(put, SND_SEQ_INSTR_ATYPE_DATA); + snd_instr_header_set_format(put, SND_SEQ_INSTR_ID_SIMPLE); /* build data section */ - xinstr = (simple_xinstrument_t *)(data + 1); + xinstr = (simple_xinstrument_t *)snd_instr_header_get_data(put); xinstr->stype = SIMPLE_STRU_INSTR; xinstr->share_id[0] = __cpu_to_le32(instr->share_id[0]); xinstr->share_id[1] = __cpu_to_le32(instr->share_id[1]); @@ -101,7 +97,7 @@ int snd_instr_simple_convert_to_stream(snd_instr_simple_t *simple, return 0; } -int snd_instr_simple_convert_from_stream(snd_seq_instr_get_t *__data ATTRIBUTE_UNUSED, +int snd_instr_simple_convert_from_stream(snd_instr_header_t *__data ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED, snd_instr_simple_t **simple ATTRIBUTE_UNUSED) { diff --git a/src/seq/Makefile.am b/src/seq/Makefile.am index 0b65749f..003b0a6f 100644 --- a/src/seq/Makefile.am +++ b/src/seq/Makefile.am @@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES=libseq.la -libseq_la_SOURCES = seq_hw.c seq.c seqmid.c seq_midi_event.c +libseq_la_SOURCES = seq_hw.c seq.c seq_event.c seqmid.c seq_midi_event.c noinst_HEADERS = seq_local.h all: libseq.la diff --git a/src/seq/seq.c b/src/seq/seq.c index 3933dc9c..a2676ad6 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -4,10 +4,6 @@ * \author Abramo Bagnara * \author Takashi Iwai * \date 2000-2001 - * - * THE SEQUENCER INTERFACE WILL BE CHANGED IN NEAR FUTURE. - * This interface is still not compliant to alsa 1.0 encapsulation. - * */ /* @@ -33,6 +29,13 @@ #include #include "seq_local.h" +/**************************************************************************** + * * + * seq.h * + * Sequencer * + * * + ****************************************************************************/ + /** * \brief get identifier of sequencer handle * \param seq sequencer handle @@ -167,27 +170,24 @@ static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root, * kept and passed to most of the other sequencer functions. * \param name The sequencer's "name". This is \em not a name you make * up for your own purposes; it has special significance to the ALSA - * library. So far only \c "hw" type is supported. - * Just pass \c "hw" for this. + * library. Usually you need to pass \c "default" here. * \param streams The read/write mode of the sequencer. Can be one of * three values: - * - \c SND_SEQ_OPEN_OUTPUT - open the sequencer for output only - * - \c SND_SEQ_OPEN_INPUT - open the sequencer for input only - * - \c SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input - * I suppose that you'd always want to use \c SND_SEQ_OPEN_DUPLEX here; - * I can't think of a reason for using either of the other two. + * - #SND_SEQ_OPEN_OUTPUT - open the sequencer for output only + * - #SND_SEQ_OPEN_INPUT - open the sequencer for input only + * - #SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input * \note Internally, these are translated to \c O_WRONLY, \c O_RDONLY and * \O_RDWR respectively and used as the second argument to the C library * open() call. - * \param mode Optional modifier. Can be either 0, or \c - * SND_SEQ_NONBLOCK, which will make read/write operations - * non-blocking. This can also be set later using snd_seq_nonblock(). + * \param mode Optional modifier. Can be either 0, or + * #SND_SEQ_NONBLOCK, which will make read/write operations + * non-blocking. This can also be set later using #snd_seq_nonblock(). * \return 0 on success otherwise a negative error code * * Creates a new handle and opens a connection to the kernel * sequencer interface. * After a client is created successfully, an event - * with \c SND_SEQ_EVENT_CLIENT_START is broadcasted to announce port. + * with #SND_SEQ_EVENT_CLIENT_START is broadcasted to announce port. */ int snd_seq_open(snd_seq_t **seqp, const char *name, int streams, int mode) @@ -202,12 +202,12 @@ int snd_seq_open(snd_seq_t **seqp, const char *name, /** * \brief Close the sequencer - * \param handle Handle returned from snd_seq_open() + * \param handle Handle returned from #snd_seq_open() * \return 0 on success otherwise a negative error code * * Closes the sequencer client and releases its resources. * After a client is closed, an event with - * \c SND_SEQ_EVENT_CLIENT_EXIT is broadcasted to announce port. + * #SND_SEQ_EVENT_CLIENT_EXIT is broadcasted to announce port. * The connection between other clients are disconnected. * Call this just before exiting your program. */ @@ -256,7 +256,7 @@ int snd_seq_poll_descriptors_count(snd_seq_t *seq, short events) } /** - * \brief get poll descriptors + * \brief Get poll descriptors * \param seq sequencer handle * \param pfds array of poll descriptors * \param space space in the poll descriptor array @@ -286,7 +286,7 @@ int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int s } /** - * \brief set nonblock mode + * \brief Set nonblock mode * \param seq sequencer handle * \param nonblock 0 = block, 1 = nonblock mode * \return 0 on success otherwise a negative error code @@ -294,7 +294,7 @@ int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int s * Change the blocking mode of the given client. * In block mode, the client falls into sleep when it fills the * output memory pool with full events. The client will be woken up - *after a certain amount of free space becomes available. + * after a certain amount of free space becomes available. */ int snd_seq_nonblock(snd_seq_t *seq, int nonblock) { @@ -311,7 +311,7 @@ int snd_seq_nonblock(snd_seq_t *seq, int nonblock) } /** - * \brief get the client id + * \brief Get the client id * \param seq sequencer handle * \return the client id * @@ -327,7 +327,7 @@ int snd_seq_client_id(snd_seq_t *seq) } /** - * \brief return the size of output buffer + * \brief Return the size of output buffer * \param seq sequencer handle * \return the size of output buffer in bytes * @@ -335,7 +335,7 @@ int snd_seq_client_id(snd_seq_t *seq) * This buffer is used to store decoded byte-stream of output events * before transferring to sequencer. */ -int snd_seq_output_buffer_size(snd_seq_t *seq) +size_t snd_seq_get_output_buffer_size(snd_seq_t *seq) { assert(seq); if (!seq->obuf) @@ -344,14 +344,14 @@ int snd_seq_output_buffer_size(snd_seq_t *seq) } /** - * \brief return the size of input buffer + * \brief Return the size of input buffer * \param seq sequencer handle * \return the size of input buffer in bytes * * Obtains the size of input buffer. * This buffer is used to read byte-stream of input events from sequencer. */ -int snd_seq_input_buffer_size(snd_seq_t *seq) +size_t snd_seq_get_input_buffer_size(snd_seq_t *seq) { assert(seq); if (!seq->ibuf) @@ -360,14 +360,14 @@ int snd_seq_input_buffer_size(snd_seq_t *seq) } /** - * \brief change the size of output buffer + * \brief Change the size of output buffer * \param seq sequencer handle * \param size the size of output buffer to be changed in bytes * \return 0 on success otherwise a negative error code * * Changes the size of output buffer. */ -int snd_seq_resize_output_buffer(snd_seq_t *seq, size_t size) +int snd_seq_set_output_buffer_size(snd_seq_t *seq, size_t size) { assert(seq && seq->obuf); assert(size >= sizeof(snd_seq_event_t)); @@ -385,14 +385,14 @@ int snd_seq_resize_output_buffer(snd_seq_t *seq, size_t size) } /** - * \brief resize the input buffer + * \brief Resize the input buffer * \param seq sequencer handle * \param size the size of input buffer to be changed in bytes * \return 0 on success otherwise a negative error code * * Changes the size of input buffer. */ -int snd_seq_resize_input_buffer(snd_seq_t *seq, size_t size) +int snd_seq_set_input_buffer_size(snd_seq_t *seq, size_t size) { assert(seq && seq->ibuf); assert(size >= sizeof(snd_seq_event_t)); @@ -410,637 +410,1989 @@ int snd_seq_resize_input_buffer(snd_seq_t *seq, size_t size) return 0; } + /** - * \brief obtain the sequencer system information - * \param seq sequencer handle - * \param info the pointer to be stored - * \return 0 on success otherwise a negative error code - * - * Stores the global system information of ALSA sequencer system. - * The returned data contains - * the maximum available numbers of queues, clients, ports and channels. + * \brief Get size of #snd_seq_system_info_t + * \return size in bytes */ -int snd_seq_system_info(snd_seq_t *seq, snd_seq_system_info_t * info) +size_t snd_seq_system_info_sizeof() { - assert(seq && info); - return seq->ops->system_info(seq, info); + return sizeof(snd_seq_system_info_t); } /** - * \brief obtain the information of the given client - * \param seq sequencer handle - * \param client client id - * \param info the pointer to be stored - * \return 0 on success otherwise a negative error code - * - * Obtains the information of the client with a client id specified by - * info argument. - * The obtained information is written on info parameter. + * \brief Allocate an empty #snd_seq_system_info_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code */ -int snd_seq_get_any_client_info(snd_seq_t *seq, int client, snd_seq_client_info_t * info) +int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr) { - assert(seq && info && client >= 0); - memset(info, 0, sizeof(snd_seq_client_info_t)); - info->client = client; - return seq->ops->get_client_info(seq, info); + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_system_info_t)); + if (!*ptr) + return -ENOMEM; + return 0; } /** - * \brief obtain the current client information - * \param seq sequencer handle - * \param info the pointer to be stored - * \return 0 on success otherwise a negative error code - * - * Obtains the information of the current client stored on info. - * client and type fields are ignored. + * \brief Frees a previously allocated #snd_seq_system_info_t + * \param pointer to object to free */ -int snd_seq_get_client_info(snd_seq_t *seq, snd_seq_client_info_t * info) +void snd_seq_system_info_free(snd_seq_system_info_t *obj) { - return snd_seq_get_any_client_info(seq, seq->client, info); + free(obj); } /** - * \brief set the current client information - * \param seq sequencer handle - * \param info the client info data to set - * \return 0 on success otherwise a negative error code - * - * Obtains the information of the current client stored on info. - * client and type fields are ignored. + * \brief Copy one #snd_seq_system_info_t to another + * \param dst pointer to destination + * \param src pointer to source */ -int snd_seq_set_client_info(snd_seq_t *seq, snd_seq_client_info_t * info) +void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src) { - assert(seq && info); - info->client = seq->client; - info->type = USER_CLIENT; - return seq->ops->set_client_info(seq, info); + assert(dst && src); + *dst = *src; } -/*----------------------------------------------------------------*/ /** - * \brief create a sequencer port on the current client - * \param seq sequencer handle - * \param port port information for the new port - * \return 0 on success otherwise a negative error code - * - * Creates a sequencer port on the current client. - * The attributes of created port is specified in info argument. - * - * The client field in info argument is overwritten with the current client id. - * Behavior of port creation depends on a flag defined in - * flags field. The flags field is a bit mask containing - * miscellaneous conditions. - * If \c SND_SEQ_PORT_FLG_GIVEN_PORT is included in flags field, - * the port number in port field in info argument - * is used as the id of created port. - * Otherwise, the first empty port id is searched and used. - * The obtained id index of the created port is stored on - * port field in return. - * - * The capability and cap_group are bit-masks to specify the access - * capability of the port from other clients and from the same group, - * respectively. The capability bit flags are defined as follows: - * - \c SND_SEQ_PORT_CAP_READ Readable from this port - * - \c SND_SEQ_PORT_CAP_WRITE Writable to this port. - * - \c SND_SEQ_PORT_CAP_SYNC_READ For synchronization (not implemented) - * - \c SND_SEQ_PORT_CAP_SYNC_WRITE For synchronization (not implemented) - * - \c SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported - * - \c SND_SEQ_PORT_SUBS_READ Read subscription is allowed - * - \c SND_SEQ_PORT_SUBS_WRITE Write subscription is allowed - * - \c SND_SEQ_PORT_SUBS_NO_EXPORT Subscription management from 3rd client is disallowed - * - * The type field is used to specify the type of the port. - * It is a bitmask defined as follows: - * - \c SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port - * - \c SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device - * - \c SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device - * - \c SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device - * - \c SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device - * - \c SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device - * - \c SND_SEQ_PORT_TYPE_SYNTH Synth device - * - \c SND_SEQ_PORT_TYPE_DIRECT_SAMPLE Sampling device (supporting download) - * - \c SND_SEQ_PORT_TYPE_SAMPLE Sampling device (sample can be downloaded at any time) - * - \c SND_SEQ_PORT_TYPE_APPLICATION Application (suquencer/editor) - * - * The midi_channels, midi_voices and synth_voices fields are number of channels and - * voices of this port. These values could be zero as default. - * The read_use, write_use and kernel fields are at creation. - * They should be zero-cleared. + * \brief Get maximum number of queues + * \param info #snd_seq_system_info_t container + * \return maximum number of queues */ -int snd_seq_create_port(snd_seq_t *seq, snd_seq_port_info_t * port) +int snd_seq_system_info_get_queues(const snd_seq_system_info_t *info) { - assert(seq && port); - port->client = seq->client; - return seq->ops->create_port(seq, port); + assert(info); + return info->queues; } /** - * \brief delete a sequencer port on the current client - * \param seq sequencer handle - * \param port port to be deleted - * \return 0 on success otherwise a negative error code - * - * Deletes the existing sequencer port on the current client. - * The port id must be specified in port field in info argument. - * The client field is ignored. + * \brief Get maximum number of clients + * \param info #snd_seq_system_info_t container + * \return maximum number of clients */ -int snd_seq_delete_port(snd_seq_t *seq, snd_seq_port_info_t * port) +int snd_seq_system_info_get_clients(const snd_seq_system_info_t *info) { - assert(seq && port); - port->client = seq->client; - return seq->ops->delete_port(seq, port); + assert(info); + return info->clients; } /** - * \brief obatin the information of a port on an arbitrary client - * \param seq sequencer handle - * \param client client id to get - * \param port port id to get - * \param info pointer information returns - * \return 0 on success otherwise a negative error code + * \brief Get maximum number of ports + * \param info #snd_seq_system_info_t container + * \return maximum number of ports */ -int snd_seq_get_any_port_info(snd_seq_t *seq, int client, int port, snd_seq_port_info_t * info) +int snd_seq_system_info_get_ports(const snd_seq_system_info_t *info) { - assert(seq && info && client >= 0 && port >= 0); - memset(info, 0, sizeof(snd_seq_port_info_t)); - info->client = client; - info->port = port; - return seq->ops->get_port_info(seq, info); + assert(info); + return info->ports; } /** - * \brief obatin the information of a port on the current client - * \param seq sequencer handle - * \param port port id to get - * \param info pointer information returns - * \return 0 on success otherwise a negative error code + * \brief Get maximum number of channels + * \param info #snd_seq_system_info_t container + * \return maximum number of channels */ -int snd_seq_get_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info) +int snd_seq_system_info_get_channels(const snd_seq_system_info_t *info) { - return snd_seq_get_any_port_info(seq, seq->client, port, info); + assert(info); + return info->channels; } + /** - * \brief set the information of a port on the current client + * \brief obtain the sequencer system information * \param seq sequencer handle - * \param port port to be set - * \param info port information to be set + * \param info the pointer to be stored * \return 0 on success otherwise a negative error code + * + * Stores the global system information of ALSA sequencer system. + * The returned data contains + * the maximum available numbers of queues, clients, ports and channels. */ -int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info) +int snd_seq_system_info(snd_seq_t *seq, snd_seq_system_info_t * info) { - assert(seq && info && port >= 0); - info->port = port; - return seq->ops->set_port_info(seq, info); + assert(seq && info); + return seq->ops->system_info(seq, info); } -/*----------------------------------------------------------------*/ -/* - * subscription - */ +/*----------------------------------------------------------------*/ /** - * \brief obtain subscription information - * \param seq sequencer handle - * \param sub pointer to return the subscription information - * \return 0 on success otherwise a negative error code + * \brief get size of #snd_seq_client_info_t + * \return size in bytes */ -int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +size_t snd_seq_client_info_sizeof() { - assert(seq && sub); - return seq->ops->get_port_subscription(seq, sub); + return sizeof(snd_seq_client_info_t); } /** - * \brief subscribe a port connection - * \param seq sequencer handle - * \param sub subscription information - * \return 0 on success otherwise a negative error code - * - * Subscribes a connection between two ports. - * The subscription information is stored in sub argument. + * \brief allocate an empty #snd_seq_client_info_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code */ -int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr) { - assert(seq && sub); - return seq->ops->subscribe_port(seq, sub); + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_client_info_t)); + if (!*ptr) + return -ENOMEM; + return 0; } /** - * \brief unsubscribe a connection between ports - * \param seq sequencer handle - * \param sub subscription information to disconnect - * \return 0 on success otherwise a negative error code - * - * Unsubscribes a connection between two ports, - * described in sender and dest fields in sub argument. + * \brief frees a previously allocated #snd_seq_client_info_t + * \param pointer to object to free */ -int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +void snd_seq_client_info_free(snd_seq_client_info_t *obj) { - assert(seq && sub); - return seq->ops->unsubscribe_port(seq, sub); + free(obj); } /** - * \brief query port subscriber list - * \param seq sequencer handle - * \param subs subscription to query - * \return 0 on success otherwise a negative error code - * - * Queries the subscribers accessing to a port. - * The query information is specified in subs argument. - * + * \brief copy one #snd_seq_client_info_t to another + * \param dst pointer to destination + * \param src pointer to source */ -int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subs_t * subs) +void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src) { - assert(seq && subs); - return seq->ops->query_port_subscribers(seq, subs); + assert(dst && src); + *dst = *src; } -/*----------------------------------------------------------------*/ -/* - * queue handlers +/** + * \brief Get client id of a client_info container + * \param info client_info container + * \return client id */ +int snd_seq_client_info_get_client(const snd_seq_client_info_t *info) +{ + assert(info); + return info->client; +} /** - * \brief obtain the running state of the queue - * \param seq sequencer handle - * \param q queue id to query - * \param status pointer to store the current status - * \return 0 on success otherwise a negative error code + * \brief Get client type of a client_info container + * \param info client_info container + * \return client type * - * Obtains the running state of the specified queue q. + * The client type is either #SEQ_CLIENT_TYPE_KERNEL or #SEQ_CLIENT_TYPE_USER + * for kernel or user client respectively. */ -int snd_seq_get_queue_status(snd_seq_t *seq, int q, snd_seq_queue_status_t * status) +snd_seq_client_type_t snd_seq_client_info_get_type(const snd_seq_client_info_t *info) { - assert(seq && status); - memset(status, 0, sizeof(snd_seq_queue_status_t)); - status->queue = q; - return seq->ops->get_queue_status(seq, status); + assert(info); + return info->type; } /** - * \brief obtain the current tempo of the queue - * \param seq sequencer handle - * \param q queue id to be queried - * \param tempo pointer to store the current tempo - * \return 0 on success otherwise a negative error code + * \brief Get the name of a client_info container + * \param info client_info container + * \return name string */ -int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo) +const char *snd_seq_client_info_get_name(snd_seq_client_info_t *info) { - assert(seq && tempo); - memset(tempo, 0, sizeof(snd_seq_queue_tempo_t)); - tempo->queue = q; - return seq->ops->get_queue_tempo(seq, tempo); + assert(info); + return info->name; } /** - * \brief set the tempo of the queue - * \param seq sequencer handle - * \param q queue id to change the tempo - * \param tempo tempo information - * \return 0 on success otherwise a negative error code + * \brief Get the broadcast filter usage of a client_info container + * \param info client_info container + * \return 1 if broadcast is accepted */ -int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo) +int snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t *info) { - assert(seq && tempo); - tempo->queue = q; - return seq->ops->set_queue_tempo(seq, tempo); + assert(info); + return (info->filter & SNDRV_SEQ_FILTER_BROADCAST) ? 1 : 0; } /** - * \brief obtain the owner information of the queue - * \param seq sequencer handle - * \param q queue id to query - * \param owner pointer to store the owner information - * \return 0 on success otherwise a negative error code + * \brief Get the error-bounce usage of a client_info container + * \param info client_info container + * \return 1 if error-bounce is enabled */ -int snd_seq_get_queue_owner(snd_seq_t *seq, int q, snd_seq_queue_owner_t * owner) +int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info) { - assert(seq && owner); - memset(owner, 0, sizeof(snd_seq_queue_owner_t)); - owner->queue = q; - return seq->ops->get_queue_owner(seq, owner); + assert(info); + return (info->filter & SNDRV_SEQ_FILTER_BOUNCE) ? 1 : 0; } /** - * \biref set the owner information of the queue - * \param seq sequencer handle - * \param q queue id to change the ownership - * \param owner owner information - * \return 0 on success otherwise a negative error code + * \brief Get the event filter bitmap of a client_info container + * \param info client_info container + * \return NULL if no event filter, or pointer to event filter bitmap */ -int snd_seq_set_queue_owner(snd_seq_t *seq, int q, snd_seq_queue_owner_t * owner) +const unsigned char *snd_seq_client_info_get_event_filter(const snd_seq_client_info_t *info) { - assert(seq && owner); - owner->queue = q; - return seq->ops->set_queue_owner(seq, owner); + assert(info); + if (info->filter & SNDRV_SEQ_FILTER_USE_EVENT) + return info->event_filter; + else + return NULL; } /** - * \brief obtain the queue timer information - * \param seq sequencer handle - * \param q queue id to query - * \param timer pointer to store the timer information - * \return 0 on success otherwise a negative error code + * \brief Get the number of opened ports of a client_info container + * \param info client_info container + * \return number of opened ports */ -int snd_seq_get_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer) +int snd_seq_client_info_get_num_ports(const snd_seq_client_info_t *info) { - assert(seq && timer); - memset(timer, 0, sizeof(snd_seq_queue_timer_t)); - timer->queue = q; - return seq->ops->get_queue_timer(seq, timer); + assert(info); + return info->num_ports; } /** - * \brief set the queue timer information - * \param seq sequencer handle - * \param q queue id to change the timer - * \param timer timer information - * \return 0 on success otherwise a negative error code + * \brief Get the number of lost events of a client_info container + * \param info client_info container + * \return number of lost events */ -int snd_seq_set_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer) +int snd_seq_client_info_get_event_lost(const snd_seq_client_info_t *info) { - assert(seq && timer); - timer->queue = q; - return seq->ops->set_queue_timer(seq, timer); + assert(info); + return info->event_lost; } /** - * \brief obtain queue access information - * \param seq sequencer handle - * \param q queue id to query - * \param info pointer to store the queue access information - * \return 0 on success otherwise a negative error code + * \brief Set the client id of a client_info container + * \param info client_info container + * \param client client id */ -int snd_seq_get_queue_client(snd_seq_t *seq, int q, snd_seq_queue_client_t * info) +void snd_seq_client_info_set_client(snd_seq_client_info_t *info, int client) { - assert(seq && info); - memset(info, 0, sizeof(snd_seq_queue_client_t)); - info->queue = q; - info->client = seq->client; - return seq->ops->get_queue_client(seq, info); + assert(info); + info->client = client; } /** - * \brief set queue access information - * \param seq sequencer handle - * \param q queue id to change access information - * \param info access information - * \return 0 on success otherwise a negative error code + * \brief Set the name of a client_info container + * \param info client_info container + * \param name name string */ -int snd_seq_set_queue_client(snd_seq_t *seq, int q, snd_seq_queue_client_t * info) +void snd_seq_client_info_set_name(snd_seq_client_info_t *info, const char *name) { - assert(seq && info); - info->queue = q; - info->client = seq->client; - return seq->ops->set_queue_client(seq, info); + assert(info && name); + strncpy(info->name, name, sizeof(info->name)); } /** - * \brief create a queue - * \param seq sequencer handle - * \param info queue information to initialize - * \return the queue id (zero or positive) on success otherwise a negative error code + * \brief Set the broadcast filter usage of a client_info container + * \param info client_info container + * \param bool non-zero if broadcast is accepted */ -int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info) +void snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t *info, int bool) { - int err; - assert(seq && info); - info->owner = seq->client; - err = seq->ops->create_queue(seq, info); - if (err < 0) - return err; - return info->queue; + assert(info); + if (bool) + info->filter |= SNDRV_SEQ_FILTER_BROADCAST; + else + info->filter &= ~SNDRV_SEQ_FILTER_BROADCAST; } /** - * \brief allocate a queue with the speicified name - * \param seq sequencer handle - * \param name the name of the new queue - * \return the queue id (zero or positive) on success otherwise a negative error code - */ -int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name) + * \brief Set the error-bounce usage of a client_info container + * \param info client_info container + * \param bool non-zero if error is bounced + */ +void snd_seq_client_info_set_error_bounce(snd_seq_client_info_t *info, int bool) { - snd_seq_queue_info_t info; - memset(&info, 0, sizeof(info)); - info.locked = 1; - if (name) - strncpy(info.name, name, sizeof(info.name) - 1); - return snd_seq_create_queue(seq, &info); + assert(info); + if (bool) + info->filter |= SNDRV_SEQ_FILTER_BOUNCE; + else + info->filter &= ~SNDRV_SEQ_FILTER_BOUNCE; } /** - * \brief allocate a queue - * \param seq sequencer handle - * \return the queue id (zero or positive) on success otherwise a negative error code - */ -int snd_seq_alloc_queue(snd_seq_t *seq) + * \brief Set the event filter bitmap of a client_info container + * \param info client_info container + * \param filter event filter bitmap + */ +void snd_seq_client_info_set_event_filter(snd_seq_client_info_t *info, unsigned char *filter) { - return snd_seq_alloc_named_queue(seq, NULL); + assert(info); + if (! filter) + info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT; + else { + info->filter |= SNDRV_SEQ_FILTER_USE_EVENT; + memcpy(info->event_filter, filter, sizeof(info->event_filter)); + } } -#ifdef SND_SEQ_SYNC_SUPPORT + /** - * \brief allocate a synchronizable queue + * \brief obtain the information of the given client + * \param seq sequencer handle + * \param client client id + * \param info the pointer to be stored + * \return 0 on success otherwise a negative error code + * + * Obtains the information of the client with a client id specified by + * info argument. + * The obtained information is written on info parameter. + */ +int snd_seq_get_any_client_info(snd_seq_t *seq, int client, snd_seq_client_info_t *info) +{ + assert(seq && info && client >= 0); + memset(info, 0, sizeof(snd_seq_client_info_t)); + info->client = client; + return seq->ops->get_client_info(seq, info); +} + +/** + * \brief obtain the current client information + * \param seq sequencer handle + * \param info the pointer to be stored + * \return 0 on success otherwise a negative error code + * + * Obtains the information of the current client stored on info. + * client and type fields are ignored. + */ +int snd_seq_get_client_info(snd_seq_t *seq, snd_seq_client_info_t *info) +{ + return snd_seq_get_any_client_info(seq, seq->client, info); +} + +/** + * \brief set the current client information + * \param seq sequencer handle + * \param info the client info data to set + * \return 0 on success otherwise a negative error code + * + * Obtains the information of the current client stored on info. + * client and type fields are ignored. + */ +int snd_seq_set_client_info(snd_seq_t *seq, snd_seq_client_info_t *info) +{ + assert(seq && info); + info->client = seq->client; + info->type = USER_CLIENT; + return seq->ops->set_client_info(seq, info); +} + +/** + * \brief query the next matching client + * \param seq sequencer handle + * \param info query pattern and result + * + * Queries the next matching client with the given condition in + * info argument. + * The search begins at the client with an id one greater than + * client field in info. + * If name field in info is not empty, the client name is compared. + * If a matching client is found, its attributes are stored o + * info and returns zero. + * Otherwise returns a negative error code. + */ +int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info) +{ + assert(seq && info); + return seq->ops->query_next_client(seq, info); +} + + +/*----------------------------------------------------------------*/ + + +/* + * Port + */ + +/** + * \brief get size of #snd_seq_port_info_t + * \return size in bytes + */ +size_t snd_seq_port_info_sizeof() +{ + return sizeof(snd_seq_port_info_t); +} + +/** + * \brief allocate an empty #snd_seq_port_info_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_port_info_malloc(snd_seq_port_info_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_port_info_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_port_info_t + * \param pointer to object to free + */ +void snd_seq_port_info_free(snd_seq_port_info_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_port_info_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get client id of a port_info container + * \param info port_info container + * \return client id + */ +int snd_seq_port_info_get_client(const snd_seq_port_info_t *info) +{ + assert(info); + return info->addr.client; +} + +/** + * \brief Get port id of a port_info container + * \param info port_info container + * \return port id + */ +int snd_seq_port_info_get_port(const snd_seq_port_info_t *info) +{ + assert(info); + return info->addr.port; +} + +/** + * \brief Get client/port address of a port_info container + * \param info port_info container + * \return client/port address pointer + */ +const snd_seq_addr_t *snd_seq_port_info_get_addr(const snd_seq_port_info_t *info) +{ + assert(info); + return &info->addr; +} + +/** + * \brief Get the name of a port_info container + * \param info port_info container + * \return name string + */ +const char *snd_seq_port_info_get_name(const snd_seq_port_info_t *info) +{ + assert(info); + return info->name; +} + +/** + * \brief Get the capability bits of a port_info container + * \param info port_info container + * \return capability bits + */ +unsigned int snd_seq_port_info_get_capability(const snd_seq_port_info_t *info) +{ + assert(info); + return info->capability; +} + +/** + * \brief Get the type bits of a port_info container + * \param info port_info container + * \return port type bits + */ +unsigned int snd_seq_port_info_get_type(const snd_seq_port_info_t *info) +{ + assert(info); + return info->type; +} + +/** + * \brief Get the number of read subscriptions of a port_info container + * \param info port_info container + * \return number of read subscriptions + */ +int snd_seq_port_info_get_read_use(const snd_seq_port_info_t *info) +{ + assert(info); + return info->read_use; +} + +/** + * \brief Get the number of write subscriptions of a port_info container + * \param info port_info container + * \return number of write subscriptions + */ +int snd_seq_port_info_get_write_use(const snd_seq_port_info_t *info) +{ + assert(info); + return info->write_use; +} + +/** + * \brief Get the midi channels of a port_info container + * \param info port_info container + * \return number of midi channels (default 0) + */ +int snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t *info) +{ + assert(info); + return info->midi_channels; +} + +/** + * \brief Get the midi voices of a port_info container + * \param info port_info container + * \return number of midi voices (default 0) + */ +int snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t *info) +{ + assert(info); + return info->midi_voices; +} + +/** + * \brief Get the synth voices of a port_info container + * \param info port_info container + * \return number of synth voices (default 0) + */ +int snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t *info) +{ + assert(info); + return info->synth_voices; +} + +/** + * \brief Get the port-specified mode of a port_info container + * \param info port_info container + * \return 1 if port id is specified at creation + */ +int snd_seq_port_info_get_port_specified(const snd_seq_port_info_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? 1 : 0; +} + +/** + * \brief Set the client id of a port_info container + * \param info port_info container + * \param client client id + */ +void snd_seq_port_info_set_client(snd_seq_port_info_t *info, int client) +{ + assert(info); + info->addr.client = client; +} + +/** + * \brief Set the port id of a port_info container + * \param info port_info container + * \param port port id + */ +void snd_seq_port_info_set_port(snd_seq_port_info_t *info, int port) +{ + assert(info); + info->addr.port = port; +} + +/** + * \brief Set the client/port address of a port_info container + * \param info port_info container + * \param addr client/port address + */ +void snd_seq_port_info_set_addr(snd_seq_port_info_t *info, const snd_seq_addr_t *addr) +{ + assert(info); + info->addr = *addr; +} + +/** + * \brief Set the name of a port_info container + * \param info port_info container + * \param name name string + */ +void snd_seq_port_info_set_name(snd_seq_port_info_t *info, const char *name) +{ + assert(info && name); + strncpy(info->name, name, sizeof(info->name)); +} + +/** + * \brief set the capability bits of a port_info container + * \param info port_info container + * \param capability capability bits + */ +void snd_seq_port_info_set_capability(snd_seq_port_info_t *info, unsigned int capability) +{ + assert(info); + info->capability = capability; +} + +/** + * \brief Get the type bits of a port_info container + * \param info port_info container + * \return port type bits + */ +void snd_seq_port_info_set_type(snd_seq_port_info_t *info, unsigned int type) +{ + assert(info); + info->type = type; +} + +/** + * \brief set the midi channels of a port_info container + * \param info port_info container + * \param channels midi channels (default 0) + */ +void snd_seq_port_info_set_midi_channels(snd_seq_port_info_t *info, int channels) +{ + assert(info); + info->midi_channels = channels; +} + +/** + * \brief set the midi voices of a port_info container + * \param info port_info container + * \param voices midi voices (default 0) + */ +void snd_seq_port_info_set_midi_voices(snd_seq_port_info_t *info, int voices) +{ + assert(info); + info->midi_voices = voices; +} + +/** + * \brief set the synth voices of a port_info container + * \param info port_info container + * \param voices synth voices (default 0) + */ +void snd_seq_port_info_set_synth_voices(snd_seq_port_info_t *info, int voices) +{ + assert(info); + info->synth_voices = voices; +} + +/** + * \brief Set the port-specifiied mode of a port_info container + * \param info port_info container + * \param bool non-zero if specifying the port id at creation + */ +void snd_seq_port_info_set_port_specified(snd_seq_port_info_t *info, int bool) +{ + assert(info); + if (bool) + info->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT; + else + info->flags &= ~SNDRV_SEQ_PORT_FLG_GIVEN_PORT; +} + + +/** + * \brief create a sequencer port on the current client + * \param seq sequencer handle + * \param port port information for the new port + * \return 0 on success otherwise a negative error code + * + * Creates a sequencer port on the current client. + * The attributes of created port is specified in \a info argument. + * + * The client field in \a info argument is overwritten with the current client id. + * The port id to be created can be specified via #snd_seq_port_info_set_port_specified. + * You can get the created port id by reading the port pointer via #snd_seq_port_info_get_port. + * + * Each port has the capability bit-masks to specify the access capability + * of the port from other clients. + * The capability bit flags are defined as follows: + * - #SND_SEQ_PORT_CAP_READ Readable from this port + * - #SND_SEQ_PORT_CAP_WRITE Writable to this port. + * - #SND_SEQ_PORT_CAP_SYNC_READ For synchronization (not implemented) + * - #SND_SEQ_PORT_CAP_SYNC_WRITE For synchronization (not implemented) + * - #SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported + * - #SND_SEQ_PORT_CAP_SUBS_READ Read subscription is allowed + * - #SND_SEQ_PORT_CAP_SUBS_WRITE Write subscription is allowed + * - #SND_SEQ_PORT_CAP_SUBS_NO_EXPORT Subscription management from 3rd client is disallowed + * + * Each port has also the type bitmasks defined as follows: + * - #SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port + * - #SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device + * - #SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device + * - #SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device + * - #SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device + * - #SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device + * - #SND_SEQ_PORT_TYPE_SYNTH Synth device + * - #SND_SEQ_PORT_TYPE_DIRECT_SAMPLE Sampling device (supporting download) + * - #SND_SEQ_PORT_TYPE_SAMPLE Sampling device (sample can be downloaded at any time) + * - #SND_SEQ_PORT_TYPE_APPLICATION Application (suquencer/editor) + * + * A port may contain speicific midi channels, midi voices and synth voices. + * These values could be zero as default. + */ +int snd_seq_create_port(snd_seq_t *seq, snd_seq_port_info_t * port) +{ + assert(seq && port); + port->addr.client = seq->client; + return seq->ops->create_port(seq, port); +} + +/** + * \brief delete a sequencer port on the current client + * \param seq sequencer handle + * \param port port to be deleted + * \return 0 on success otherwise a negative error code + * + * Deletes the existing sequencer port on the current client. + */ +int snd_seq_delete_port(snd_seq_t *seq, int port) +{ + snd_seq_port_info_t pinfo; + assert(seq); + memset(&pinfo, 0, sizeof(pinfo)); + pinfo.addr.client = seq->client; + pinfo.addr.port = port; + return seq->ops->delete_port(seq, &pinfo); +} + +/** + * \brief obatin the information of a port on an arbitrary client + * \param seq sequencer handle + * \param client client id to get + * \param port port id to get + * \param info pointer information returns + * \return 0 on success otherwise a negative error code + */ +int snd_seq_get_any_port_info(snd_seq_t *seq, int client, int port, snd_seq_port_info_t * info) +{ + assert(seq && info && client >= 0 && port >= 0); + memset(info, 0, sizeof(snd_seq_port_info_t)); + info->addr.client = client; + info->addr.port = port; + return seq->ops->get_port_info(seq, info); +} + +/** + * \brief obatin the information of a port on the current client + * \param seq sequencer handle + * \param port port id to get + * \param info pointer information returns + * \return 0 on success otherwise a negative error code + */ +int snd_seq_get_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info) +{ + return snd_seq_get_any_port_info(seq, seq->client, port, info); +} + +/** + * \brief set the information of a port on the current client + * \param seq sequencer handle + * \param port port to be set + * \param info port information to be set + * \return 0 on success otherwise a negative error code + */ +int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info) +{ + assert(seq && info && port >= 0); + info->addr.client = seq->client; + info->addr.port = port; + return seq->ops->set_port_info(seq, info); +} + +/** + * \brief query the next matching port + * \param seq sequencer handle + * \param info query pattern and result + + * Queries the next matching port on the client specified in + * \a info argument. + * The search begins at the next port specified in + * port field of \a info argument. + * For finding the first port at a certain client, give -1. + * + * If a matching port is found, its attributes are stored on + * \a info and function returns zero. + * Otherwise, a negative error code is returned. + */ +int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info) +{ + assert(seq && info); + return seq->ops->query_next_port(seq, info); +} + + +/*----------------------------------------------------------------*/ + +/* + * subscription + */ + + +/** + * \brief get size of #snd_seq_port_subscribe_t + * \return size in bytes + */ +size_t snd_seq_port_subscribe_sizeof() +{ + return sizeof(snd_seq_port_subscribe_t); +} + +/** + * \brief allocate an empty #snd_seq_port_subscribe_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_port_subscribe_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_port_subscribe_t + * \param pointer to object to free + */ +void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_port_subscribe_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get sender address of a port_subscribe container + * \param info port_subscribe container + * \param addr sender address + */ +const snd_seq_addr_t *snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return &info->sender; +} + +/** + * \brief Get destination address of a port_subscribe container + * \param info port_subscribe container + * \param addr destination address + */ +const snd_seq_addr_t *snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return &info->dest; +} + +/** + * \brief Get the queue id of a port_subscribe container + * \param info port_subscribe container + * \return queue id + */ +int snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return info->queue; +} + +/** + * \brief Get the exclusive mode of a port_subscribe container + * \param info port_subscribe container + * \return 1 if exclusive mode + */ +int snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0; +} + +/** + * \brief Get the time-update mode of a port_subscribe container + * \param info port_subscribe container + * \return 1 if update timestamp + */ +int snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0; +} + +/** + * \brief Get the real-time update mode of a port_subscribe container + * \param info port_subscribe container + * \return 1 if real-time update mode + */ +int snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 1 : 0; +} + +/** + * \brief Set sender address of a port_subscribe container + * \param info port_subscribe container + * \param addr sender address + */ +void snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr) +{ + assert(info); + memcpy(&info->sender, addr, sizeof(*addr)); +} + +/** + * \brief Set destination address of a port_subscribe container + * \param info port_subscribe container + * \param addr destination address + */ +void snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr) +{ + assert(info); + memcpy(&info->dest, addr, sizeof(*addr)); +} + +/** + * \brief Set the queue id of a port_subscribe container + * \param info port_subscribe container + * \param q queue id + */ +void snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t *info, int q) +{ + assert(info); + info->queue = q; +} + +/** + * \brief Set the exclusive mode of a port_subscribe container + * \param info port_subscribe container + * \param bool non-zero to enable + */ +void snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t *info, int bool) +{ + assert(info); + if (bool) + info->flags |= SNDRV_SEQ_PORT_SUBS_EXCLUSIVE; + else + info->flags &= ~SNDRV_SEQ_PORT_SUBS_EXCLUSIVE; +} + +/** + * \brief Set the time-update mode of a port_subscribe container + * \param info port_subscribe container + * \param bool non-zero to enable + */ +void snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t *info, int bool) +{ + assert(info); + if (bool) + info->flags |= SNDRV_SEQ_PORT_SUBS_TIMESTAMP; + else + info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIMESTAMP; +} + +/** + * \brief Set the real-time mode of a port_subscribe container + * \param info port_subscribe container + * \param bool non-zero to enable + */ +void snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t *info, int bool) +{ + assert(info); + if (bool) + info->flags |= SNDRV_SEQ_PORT_SUBS_TIME_REAL; + else + info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIME_REAL; +} + + +/** + * \brief obtain subscription information + * \param seq sequencer handle + * \param sub pointer to return the subscription information + * \return 0 on success otherwise a negative error code + */ +int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +{ + assert(seq && sub); + return seq->ops->get_port_subscription(seq, sub); +} + +/** + * \brief subscribe a port connection + * \param seq sequencer handle + * \param sub subscription information + * \return 0 on success otherwise a negative error code + * + * Subscribes a connection between two ports. + * The subscription information is stored in sub argument. + */ +int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +{ + assert(seq && sub); + return seq->ops->subscribe_port(seq, sub); +} + +/** + * \brief unsubscribe a connection between ports + * \param seq sequencer handle + * \param sub subscription information to disconnect + * \return 0 on success otherwise a negative error code + * + * Unsubscribes a connection between two ports, + * described in sender and dest fields in sub argument. + */ +int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +{ + assert(seq && sub); + return seq->ops->unsubscribe_port(seq, sub); +} + + +/** + * \brief get size of #snd_seq_query_subscribe_t + * \return size in bytes + */ +size_t snd_seq_query_subscribe_sizeof() +{ + return sizeof(snd_seq_query_subscribe_t); +} + +/** + * \brief allocate an empty #snd_seq_query_subscribe_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_query_subscribe_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_query_subscribe_t + * \param pointer to object to free + */ +void snd_seq_query_subscribe_free(snd_seq_query_subscribe_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_query_subscribe_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get the client id of a query_subscribe container + * \param info query_subscribe container + * \return client id + */ +int snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->root.client; +} + +/** + * \brief Get the port id of a query_subscribe container + * \param info query_subscribe container + * \return port id + */ +int snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->root.port; +} + +/** + * \brief Get the client/port address of a query_subscribe container + * \param info query_subscribe container + * \return client/port address pointer + */ +const snd_seq_addr_t *snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return &info->root; +} + +/** + * \brief Get the query type of a query_subscribe container + * \param info query_subscribe container + * \return query type + */ +snd_seq_query_subs_type_t snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->type; +} + +/** + * \brief Get the index of subscriber of a query_subscribe container + * \param info query_subscribe container + * \return subscriber's index + */ +int snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->index; +} + +/** + * \brief Get the number of subscriptiosn of a query_subscribe container + * \param info query_subscribe container + * \return number of subscriptions + */ +int snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->num_subs; +} + +/** + * \brief Get the address of subscriber of a query_subscribe container + * \param info query_subscribe container + * \return subscriber's address pointer + */ +const snd_seq_addr_t *snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return &info->addr; +} + +/** + * \brief Get the queue id of subscriber of a query_subscribe container + * \param info query_subscribe container + * \return subscriber's queue id + */ +int snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return info->queue; +} + +/** + * \brief Get the exclusive mode of a query_subscribe container + * \param info query_subscribe container + * \return 1 if exclusive mode + */ +int snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0; +} + +/** + * \brief Get the time-update mode of a query_subscribe container + * \param info query_subscribe container + * \return 1 if update timestamp + */ +int snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0; +} + +/** + * \brief Get the real-time update mode of a query_subscribe container + * \param info query_subscribe container + * \return 1 if real-time update mode + */ +int snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0; +} + +/** + * \brief Set the client id of a query_subscribe container + * \param info query_subscribe container + * \param client client id + */ +void snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t *info, int client) +{ + assert(info); + info->root.client = client; +} + +/** + * \brief Set the port id of a query_subscribe container + * \param info query_subscribe container + * \param port port id + */ +void snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t *info, int port) +{ + assert(info); + info->root.port = port; +} + +/** + * \brief Set the client/port address of a query_subscribe container + * \param info query_subscribe container + * \param addr client/port address pointer + */ +void snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t *info, const snd_seq_addr_t *addr) +{ + assert(info); + info->root = *addr; +} + +/** + * \brief Set the query type of a query_subscribe container + * \param info query_subscribe container + * \param type query type + */ +void snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t *info, snd_seq_query_subs_type_t type) +{ + assert(info); + info->type = type; +} + +/** + * \brief Set the subscriber's index to be queried + * \param info query_subscribe container + * \param index index to be queried + */ +void snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t *info, int index) +{ + assert(info); + info->index = index; +} + + +/** + * \brief query port subscriber list + * \param seq sequencer handle + * \param subs subscription to query + * \return 0 on success otherwise a negative error code + * + * Queries the subscribers accessing to a port. + * The query information is specified in subs argument. + * + */ +int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs) +{ + assert(seq && subs); + return seq->ops->query_port_subscribers(seq, subs); +} + +/*----------------------------------------------------------------*/ + +/* + * queue handlers + */ + +/** + * \brief get size of #snd_seq_queue_info_t + * \return size in bytes + */ +size_t snd_seq_queue_info_sizeof() +{ + return sizeof(snd_seq_queue_info_t); +} + +/** + * \brief allocate an empty #snd_seq_queue_info_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_queue_info_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_queue_info_t + * \param pointer to object to free + */ +void snd_seq_queue_info_free(snd_seq_queue_info_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_queue_info_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get the queue id of a queue_info container + * \param info queue_info container + * \return queue id + */ +int snd_seq_queue_info_get_queue(const snd_seq_queue_info_t *info) +{ + assert(info); + return info->queue; +} + +/** + * \brief Get the name of a queue_info container + * \param info queue_info container + * \return name string + */ +const char *snd_seq_queue_info_get_name(const snd_seq_queue_info_t *info) +{ + assert(info); + return info->name; +} + +/** + * \brief Get the owner client id of a queue_info container + * \param info queue_info container + * \return owner client id + */ +int snd_seq_queue_info_get_owner(const snd_seq_queue_info_t *info) +{ + assert(info); + return info->owner; +} + +/** + * \brief Get the lock status of a queue_info container + * \param info queue_info container + * \return lock status --- non-zero = locked + */ +int snd_seq_queue_info_get_locked(const snd_seq_queue_info_t *info) +{ + assert(info); + return info->locked; +} + +/** + * \brief Get the conditional bit flags of a queue_info container + * \param info queue_info container + * \return conditional bit flags + */ +unsigned int snd_seq_queue_info_get_flags(const snd_seq_queue_info_t *info) +{ + assert(info); + return info->flags; +} + +/** + * \brief Set the name of a queue_info container + * \param info queue_info container + * \param name name string + */ +void snd_seq_queue_info_set_name(snd_seq_queue_info_t *info, const char *name) +{ + assert(info && name); + strncpy(info->name, name, sizeof(info->name)); +} + +/** + * \brief Set the owner client id of a queue_info container + * \param info queue_info container + * \param owner client id + */ +void snd_seq_queue_info_set_owner(snd_seq_queue_info_t *info, int owner) +{ + assert(info); + info->owner = owner; +} + +/** + * \brief Set the lock status of a queue_info container + * \param info queue_info container + * \param locked lock status + */ +void snd_seq_queue_info_set_locked(snd_seq_queue_info_t *info, int locked) +{ + assert(info); + info->locked = locked; +} + +/** + * \brief Set the conditional bit flags of a queue_info container + * \param info queue_info container + * \param flags contidional bit flags + */ +void snd_seq_queue_info_set_flags(snd_seq_queue_info_t *info, unsigned int flags) +{ + assert(info); + info->flags = flags; +} + + +/** + * \brief create a queue + * \param seq sequencer handle + * \param info queue information to initialize + * \return the queue id (zero or positive) on success otherwise a negative error code + */ +int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info) +{ + int err; + assert(seq && info); + info->owner = seq->client; + err = seq->ops->create_queue(seq, info); + if (err < 0) + return err; + return info->queue; +} + +/** + * \brief allocate a queue with the speicified name * \param seq sequencer handle * \param name the name of the new queue * \return the queue id (zero or positive) on success otherwise a negative error code + */ +int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name) +{ + snd_seq_queue_info_t info; + memset(&info, 0, sizeof(info)); + info.locked = 1; + if (name) + strncpy(info.name, name, sizeof(info.name) - 1); + return snd_seq_create_queue(seq, &info); +} + +/** + * \brief allocate a queue + * \param seq sequencer handle + * \return the queue id (zero or positive) on success otherwise a negative error code + */ +int snd_seq_alloc_queue(snd_seq_t *seq) +{ + return snd_seq_alloc_named_queue(seq, NULL); +} + +/** + * \breif delete the specified queue + * \param seq sequencer handle + * \param q queue id to delete + * \return 0 on success otherwise a negative error code + */ +int snd_seq_free_queue(snd_seq_t *seq, int q) +{ + snd_seq_queue_info_t info; + assert(seq); + memset(&info, 0, sizeof(info)); + info.queue = q; + return seq->ops->delete_queue(seq, &info); +} + +/** + * \brief obtain queue attributes + * \param seq sequencer handle + * \param q queue id to query + * \param info information returned + * \return 0 on success otherwise a negative error code + */ +int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info) +{ + assert(seq && info); + info->queue = q; + return seq->ops->get_queue_info(seq, info); +} + +/** + * \brief change the queue attributes + * \param seq sequencer handle + * \param q queue id to change + * \param info information changed + * \return 0 on success otherwise a negative error code + */ +int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info) +{ + assert(seq && info); + info->queue = q; + return seq->ops->set_queue_info(seq, info); +} + +/** + * \brief query the matching queue with the specified name + * \param seq sequencer handle + * \param name the name string to query + * \return the queue id if found or negative error code + * + * Searches the matching queue with the specified name string. + */ +int snd_seq_query_named_queue(snd_seq_t *seq, const char *name) +{ + int err; + snd_seq_queue_info_t info; + assert(seq && name); + strncpy(info.name, name, sizeof(info.name)); + err = seq->ops->get_named_queue(seq, &info); + if (err < 0) + return err; + return info.queue; +} + +/** + * \brief Get the queue usage flag to the client + * \param seq sequencer handle + * \param q queue id + * \param client client id + * \return 1 = client is allowed to access the queue, 0 = not allowed, + * otherwise a negative error code + */ +int snd_seq_get_queue_usage(snd_seq_t *seq, int q) +{ + struct sndrv_seq_queue_client info; + int err; + assert(seq); + memset(&info, 0, sizeof(info)); + info.queue = q; + info.client = seq->client; + if ((err = seq->ops->get_queue_client(seq, &info)) < 0) + return err; + return info.used; +} + +/* + * \brief Set the queue usage flag to the client + * \param seq sequencer handle + * \param q queue id + * \param client client id + * \param used non-zero if the client is allowed + * \return 0 on success otherwise a negative error code + */ +int snd_seq_set_queue_usage(snd_seq_t *seq, int q, int used) +{ + struct sndrv_seq_queue_client info; + assert(seq); + memset(&info, 0, sizeof(info)); + info.queue = q; + info.client = seq->client; + info.used = used ? 1 : 0; + return seq->ops->set_queue_client(seq, &info); +} + + +/** + * \brief get size of #snd_seq_queue_status_t + * \return size in bytes + */ +size_t snd_seq_queue_status_sizeof() +{ + return sizeof(snd_seq_queue_status_t); +} + +/** + * \brief allocate an empty #snd_seq_queue_status_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_queue_status_malloc(snd_seq_queue_status_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_queue_status_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_queue_status_t + * \param pointer to object to free + */ +void snd_seq_queue_status_free(snd_seq_queue_status_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_queue_status_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get the queue id of a queue_status container + * \param info queue_status container + * \return queue id + */ +int snd_seq_queue_status_get_queue(const snd_seq_queue_status_t *info) +{ + assert(info); + return info->queue; +} + +/** + * \brief Get the number of events of a queue_status container + * \param info queue_status container + * \return number of events + */ +int snd_seq_queue_status_get_events(const snd_seq_queue_status_t *info) +{ + assert(info); + return info->events; +} + +/** + * \brief Get the tick time of a queue_status container + * \param info queue_status container + * \return tick time + */ +snd_seq_tick_time_t snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t *info) +{ + assert(info); + return info->tick; +} + +/** + * \brief Get the real time of a queue_status container + * \param info queue_status container + * \param time real time + */ +const snd_seq_real_time_t *snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t *info) +{ + assert(info); + return &info->time; +} + +/** + * \brief Get the running status bits of a queue_status container + * \param info queue_status container + * \return running status bits + */ +unsigned int snd_seq_queue_status_get_status(const snd_seq_queue_status_t *info) +{ + assert(info); + return info->running; +} + + +/** + * \brief obtain the running state of the queue + * \param seq sequencer handle + * \param q queue id to query + * \param status pointer to store the current status + * \return 0 on success otherwise a negative error code + * + * Obtains the running state of the specified queue q. + */ +int snd_seq_get_queue_status(snd_seq_t *seq, int q, snd_seq_queue_status_t * status) +{ + assert(seq && status); + memset(status, 0, sizeof(snd_seq_queue_status_t)); + status->queue = q; + return seq->ops->get_queue_status(seq, status); +} + + +/** + * \brief get size of #snd_seq_queue_tempo_t + * \return size in bytes + */ +size_t snd_seq_queue_tempo_sizeof() +{ + return sizeof(snd_seq_queue_tempo_t); +} + +/** + * \brief allocate an empty #snd_seq_queue_tempo_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_queue_tempo_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_queue_tempo_t + * \param pointer to object to free */ -int snd_seq_alloc_sync_queue(snd_seq_t *seq, const char *name) +void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *obj) { - snd_seq_queue_info_t info; - memset(&info, 0, sizeof(info)); - info.locked = 1; - if (name) - strncpy(info.name, name, sizeof(info.name) - 1); - info.flags = SND_SEQ_QUEUE_FLG_SYNC; - return snd_seq_create_queue(seq, &info); + free(obj); } -#endif /** - * \breif delete the specified queue - * \param seq sequencer handle - * \param q queue id to delete - * \return 0 on success otherwise a negative error code + * \brief copy one #snd_seq_queue_tempo_t to another + * \param dst pointer to destination + * \param src pointer to source */ -int snd_seq_free_queue(snd_seq_t *seq, int q) +void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src) { - snd_seq_queue_info_t info; - assert(seq); - memset(&info, 0, sizeof(info)); - info.queue = q; - return seq->ops->delete_queue(seq, &info); + assert(dst && src); + *dst = *src; } + /** - * \brief obtain queue attributes - * \param seq sequencer handle - * \param q queue id to query - * \param info information returned - * \return 0 on success otherwise a negative error code + * \brief Get the queue id of a queue_status container + * \param info queue_status container + * \return queue id */ -int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info) +int snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t *info) { - assert(seq && info); - info->queue = q; - return seq->ops->get_queue_info(seq, info); + assert(info); + return info->queue; } /** - * \brief change the queue attributes + * \brief Get the tempo of a queue_status container + * \param info queue_status container + * \return tempo value + */ +unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info) +{ + assert(info); + return info->tempo; +} + +/** + * \brief Get the ppq of a queue_status container + * \param info queue_status container + * \return ppq value + */ +int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info) +{ + assert(info); + return info->ppq; +} + +/** + * \brief Set the tempo of a queue_status container + * \param info queue_status container + * \param tempo tempo value + */ +void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo) +{ + assert(info); + info->tempo = tempo; +} + +/** + * \brief Set the ppq of a queue_status container + * \param info queue_status container + * \param ppq ppq value + */ +void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq) +{ + assert(info); + info->ppq = ppq; +} + + +/** + * \brief obtain the current tempo of the queue * \param seq sequencer handle - * \param q queue id to change - * \param info information changed + * \param q queue id to be queried + * \param tempo pointer to store the current tempo * \return 0 on success otherwise a negative error code */ -int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info) +int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo) { - assert(seq && info); - info->queue = q; - return seq->ops->set_queue_info(seq, info); + assert(seq && tempo); + memset(tempo, 0, sizeof(snd_seq_queue_tempo_t)); + tempo->queue = q; + return seq->ops->get_queue_tempo(seq, tempo); } /** - * \brief query the queue with the specified name + * \brief set the tempo of the queue * \param seq sequencer handle - * \param name name to query - * \return the queue id if found or a negative error code + * \param q queue id to change the tempo + * \param tempo tempo information + * \return 0 on success otherwise a negative error code */ -int snd_seq_get_named_queue(snd_seq_t *seq, const char *name) +int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo) { - int err; - snd_seq_queue_info_t info; - assert(seq && name); - strncpy(info.name, name, sizeof(info.name)); - err = seq->ops->get_named_queue(seq, &info); - if (err < 0) - return err; - return info.queue; + assert(seq && tempo); + tempo->queue = q; + return seq->ops->set_queue_tempo(seq, tempo); } + /*----------------------------------------------------------------*/ -#ifdef SND_SEQ_SYNC_SUPPORT -/* - * sync stuff +/** + * \brief get size of #snd_seq_queue_timer_t + * \return size in bytes */ +size_t snd_seq_queue_timer_sizeof() +{ + return sizeof(snd_seq_queue_timer_t); +} /** - * \brief add sync master - * \param seq sequencer handle - * \param queue queue id to change - * \param dest destination of the sync slave - * \param info sync information + * \brief allocate an empty #snd_seq_queue_timer_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code */ -int snd_seq_add_sync_master(snd_seq_t *seq, - int queue, - snd_seq_addr_t *dest, - snd_seq_queue_sync_t *info) +int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr) { - snd_seq_port_subscribe_t subs; + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_queue_timer_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} - memset(&subs, 0, sizeof(subs)); - subs.convert_time = 1; - if (info->format & SND_SEQ_SYNC_TIME) - subs.realtime = 1; - subs.sync = 1; - subs.sender.client = SND_SEQ_CLIENT_SYSTEM; - subs.sender.port = snd_seq_queue_sync_port(queue); - subs.dest = *dest; - subs.queue = queue; - subs.opt.sync_info = *info; - return snd_seq_subscribe_port(seq, &subs); +/** + * \brief frees a previously allocated #snd_seq_queue_timer_t + * \param pointer to object to free + */ +void snd_seq_queue_timer_free(snd_seq_queue_timer_t *obj) +{ + free(obj); } /** - * \brief add a standard sync master - * \param seq sequencer handle - * \param queue queue id - * \param dest destination of the sync slave - * \param format sync format - * \param time_format time format - * \param optinfo optional information + * \brief copy one #snd_seq_queue_timer_t to another + * \param dst pointer to destination + * \param src pointer to source */ -int snd_seq_add_sync_std_master(snd_seq_t *seq, - int queue, - snd_seq_addr_t *dest, - int format, int time_format, - unsigned char *optinfo) +void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src) { - snd_seq_queue_sync_t sync_info; + assert(dst && src); + *dst = *src; +} - memset(&sync_info, 0, sizeof(sync_info)); - sync_info.format = format; - sync_info.time_format = time_format; - if (optinfo) - memcpy(sync_info.info, optinfo, sizeof(sync_info.info)); - return snd_seq_add_sync_master(seq, queue, dest, &sync_info); +/** + * \brief Get the queue id of a queue_timer container + * \param info queue_timer container + * \return queue id + */ +int snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t *info) +{ + assert(info); + return info->queue; } /** - * \brief remove the specified sync master + * \brief Get the timer type of a queue_timer container + * \param info queue_timer container + * \return timer type */ -int snd_seq_remove_sync_master(snd_seq_t *seq, int queue, snd_seq_addr_t *dest) +int snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t *info) { - snd_seq_port_subscribe_t subs; - - memset(&subs, 0, sizeof(subs)); - subs.sync = 1; - subs.sender.client = SND_SEQ_CLIENT_SYSTEM; - subs.sender.port = snd_seq_queue_sync_port(queue); - subs.dest = *dest; - subs.queue = queue; - return snd_seq_unsubscribe_port(seq, &subs); + assert(info); + return info->type; } - /** - * \brief set the sync slave mode + * \brief Get the timer id of a queue_timer container + * \param info queue_timer container + * \return timer id pointer */ -int snd_seq_set_sync_slave(snd_seq_t *seq, - int queue, - snd_seq_addr_t *src, - snd_seq_queue_sync_t *info) +const snd_timer_id_t *snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t *info) { - snd_seq_port_subscribe_t subs; + assert(info); + return &info->u.alsa.id; +} - memset(&subs, 0, sizeof(subs)); - subs.convert_time = 1; - if (info->format & SND_SEQ_SYNC_TIME) - subs.realtime = 1; - subs.sync = 1; - subs.sender = *src; - subs.dest.client = SND_SEQ_CLIENT_SYSTEM; - subs.dest.port = snd_seq_queue_sync_port(queue); - subs.queue = queue; - subs.opt.sync_info = *info; - return snd_seq_subscribe_port(seq, &subs); +/** + * \brief Get the timer resolution of a queue_timer container + * \param info queue_timer container + * \return timer resolution + */ +unsigned int snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t *info) +{ + assert(info); + return info->u.alsa.resolution; } /** - * \brief reset the sync slave mode + * \brief Set the timer type of a queue_timer container + * \param info queue_timer container + * \param type timer type + */ +void snd_seq_queue_timer_set_type(snd_seq_queue_timer_t *info, int type) +{ + assert(info); + info->type = type; +} + +/** + * \brief Set the timer id of a queue_timer container + * \param info queue_timer container + * \param id timer id pointer */ -int snd_seq_reset_sync_slave(snd_seq_t *seq, int queue, snd_seq_addr_t *src) +void snd_seq_queue_timer_set_id(snd_seq_queue_timer_t *info, const snd_timer_id_t *id) { - snd_seq_port_subscribe_t subs; + assert(info && id); + info->u.alsa.id = *id; +} - memset(&subs, 0, sizeof(subs)); - subs.sync = 1; - subs.sender = *src; - subs.dest.client = SND_SEQ_CLIENT_SYSTEM; - subs.dest.port = snd_seq_queue_sync_port(queue); - subs.queue = queue; - return snd_seq_unsubscribe_port(seq, &subs); +/** + * \brief Set the timer resolution of a queue_timer container + * \param info queue_timer container + * \param resolution timer resolution + */ +void snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t *info, unsigned int resolution) +{ + assert(info); + info->u.alsa.resolution = resolution; } -#endif +/** + * \brief obtain the queue timer information + * \param seq sequencer handle + * \param q queue id to query + * \param timer pointer to store the timer information + * \return 0 on success otherwise a negative error code + */ +int snd_seq_get_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer) +{ + assert(seq && timer); + memset(timer, 0, sizeof(snd_seq_queue_timer_t)); + timer->queue = q; + return seq->ops->get_queue_timer(seq, timer); +} + +/** + * \brief set the queue timer information + * \param seq sequencer handle + * \param q queue id to change the timer + * \param timer timer information + * \return 0 on success otherwise a negative error code + */ +int snd_seq_set_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer) +{ + assert(seq && timer); + timer->queue = q; + return seq->ops->set_queue_timer(seq, timer); +} /*----------------------------------------------------------------*/ @@ -1072,7 +2424,7 @@ ssize_t snd_seq_event_length(snd_seq_event_t *ev) { ssize_t len = sizeof(snd_seq_event_t); assert(ev); - if (snd_seq_ev_is_variable(ev)) + if (sndrv_seq_ev_is_variable(ev)) len += ev->data.ext.len; return len; } @@ -1129,7 +2481,7 @@ int snd_seq_event_output_buffer(snd_seq_t *seq, snd_seq_event_t *ev) return -EAGAIN; memcpy(seq->obuf + seq->obufused, ev, sizeof(snd_seq_event_t)); seq->obufused += sizeof(snd_seq_event_t); - if (snd_seq_ev_is_variable(ev)) { + if (sndrv_seq_ev_is_variable(ev)) { memcpy(seq->obuf + seq->obufused, ev->data.ext.ptr, ev->data.ext.len); seq->obufused += ev->data.ext.len; } @@ -1275,7 +2627,7 @@ static int snd_seq_event_retrieve_buffer(snd_seq_t *seq, snd_seq_event_t **retp) *retp = ev = &seq->ibuf[seq->ibufptr]; seq->ibufptr++; seq->ibuflen--; - if (! snd_seq_ev_is_variable(ev)) + if (! sndrv_seq_ev_is_variable(ev)) return 1; ncells = (ev->data.ext.len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t); if (seq->ibuflen < ncells) { @@ -1404,53 +2756,251 @@ int snd_seq_drop_input_buffer(snd_seq_t *seq) } /** - * \brief remove all events on output buffer - * \param seq sequencer handle - * - * Removes all events on both user-space output buffer and - * output memory pool on kernel. + * \brief remove all events on output buffer + * \param seq sequencer handle + * + * Removes all events on both user-space output buffer and + * output memory pool on kernel. + */ +int snd_seq_drop_output(snd_seq_t *seq) +{ + snd_seq_remove_events_t rminfo; + assert(seq); + seq->obufused = 0; /* drain output buffer */ + + memset(&rminfo, 0, sizeof(rminfo)); + rminfo.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT; + + return snd_seq_remove_events(seq, &rminfo); +} + +/** + * \brief clear input buffer and and remove events in sequencer queue + * \param seq sequencer handle + */ +int snd_seq_drop_input(snd_seq_t *seq) +{ + snd_seq_remove_events_t rminfo; + assert(seq); + + seq->ibufptr = 0; /* drain input buffer */ + seq->ibuflen = 0; + + memset(&rminfo, 0, sizeof(rminfo)); + rminfo.remove_mode = SNDRV_SEQ_REMOVE_INPUT; + + return snd_seq_remove_events(seq, &rminfo); +} + + +/** + * \brief get size of #snd_seq_remove_events_t + * \return size in bytes + */ +size_t snd_seq_remove_events_sizeof() +{ + return sizeof(snd_seq_remove_events_t); +} + +/** + * \brief allocate an empty #snd_seq_remove_events_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_seq_remove_events_malloc(snd_seq_remove_events_t **ptr) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_remove_events_t)); + if (!*ptr) + return -ENOMEM; + return 0; +} + +/** + * \brief frees a previously allocated #snd_seq_remove_events_t + * \param pointer to object to free + */ +void snd_seq_remove_events_free(snd_seq_remove_events_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_seq_remove_events_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get the removal condition bits + * \param info remove_events container + * \return removal condition bits + */ +unsigned int snd_seq_remove_events_get_condition(const snd_seq_remove_events_t *info) +{ + assert(info); + return info->remove_mode; +} + +/** + * \brief Get the queue as removal condition + * \param info remove_events container + * \return queue id + */ +int snd_seq_remove_events_get_queue(const snd_seq_remove_events_t *info) +{ + assert(info); + return info->queue; +} + +/** + * \brief Get the event timestamp as removal condition + * \param info remove_events container + * \return time stamp + */ +const snd_seq_timestamp_t *snd_seq_remove_events_get_time(const snd_seq_remove_events_t *info) +{ + assert(info); + return &info->time; +} + +/** + * \brief Get the event destination address as removal condition + * \param info remove_events container + * \return destination address + */ +const snd_seq_addr_t *snd_seq_remove_events_get_dest(const snd_seq_remove_events_t *info) +{ + assert(info); + return &info->dest; +} + +/** + * \brief Get the event channel as removal condition + * \param info remove_events container + * \return channel number + */ +int snd_seq_remove_events_get_channel(const snd_seq_remove_events_t *info) +{ + assert(info); + return info->channel; +} + +/** + * \brief Get the event type as removal condition + * \param info remove_events container + * \return event type + */ +int snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t *info) +{ + assert(info); + return info->type; +} + +/** + * \brief Get the event tag id as removal condition + * \param info remove_events container + * \return tag id + */ +int snd_seq_remove_events_get_tag(const snd_seq_remove_events_t *info) +{ + assert(info); + return info->tag; +} + +/** + * \brief Set the removal condition bits + * \param info remove_events container + * \param flags removal condition bits + */ +void snd_seq_remove_events_set_condition(snd_seq_remove_events_t *info, unsigned int flags) +{ + assert(info); + info->remove_mode = flags; +} + +/** + * \brief Set the queue as removal condition + * \param info remove_events container + * \param queue queue id + */ +void snd_seq_remove_events_set_queue(snd_seq_remove_events_t *info, int queue) +{ + assert(info); + info->queue = queue; +} + +/** + * \brief Set the timestamp as removal condition + * \param info remove_events container + * \param time timestamp pointer + */ +void snd_seq_remove_events_set_time(snd_seq_remove_events_t *info, const snd_seq_timestamp_t *time) +{ + assert(info); + info->time = *time; +} + +/** + * \brief Set the destination address as removal condition + * \param info remove_events container + * \param addr destination address + */ +void snd_seq_remove_events_set_dest(snd_seq_remove_events_t *info, const snd_seq_addr_t *addr) +{ + assert(info); + info->dest = *addr; +} + +/** + * \brief Set the channel as removal condition + * \param info remove_events container + * \param channel channel number */ -int snd_seq_drop_output(snd_seq_t *seq) +void snd_seq_remove_events_set_channel(snd_seq_remove_events_t *info, int channel) { - snd_seq_remove_events_t rminfo; - assert(seq); - seq->obufused = 0; /* drain output buffer */ - - memset(&rminfo, 0, sizeof(rminfo)); - rminfo.output = 1; - - return snd_seq_remove_events(seq, &rminfo); + assert(info); + info->channel = channel; } /** - * \brief clear input buffer and and remove events in sequencer queue - * \param seq sequencer handle + * \brief Set the event type as removal condition + * \param info remove_events container + * \param type event type */ -int snd_seq_drop_input(snd_seq_t *seq) +void snd_seq_remove_events_set_event_type(snd_seq_remove_events_t *info, int type) { - snd_seq_remove_events_t rminfo; - assert(seq); - - seq->ibufptr = 0; /* drain input buffer */ - seq->ibuflen = 0; - - memset(&rminfo, 0, sizeof(rminfo)); - rminfo.input = 1; + assert(info); + info->type = type; +} - return snd_seq_remove_events(seq, &rminfo); +/** + * \brief Set the event tag as removal condition + * \param info remove_events container + * \param tag tag id + */ +void snd_seq_remove_events_set_tag(snd_seq_remove_events_t *info, int tag) +{ + assert(info); + info->tag = tag; } + /* compare timestamp between events */ /* return 1 if a >= b; otherwise return 0 */ -static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, - snd_seq_tick_time_t *b) +static inline int snd_seq_compare_tick_time(sndrv_seq_tick_time_t *a, sndrv_seq_tick_time_t *b) { /* compare ticks */ return (*a >= *b); } -static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, - snd_seq_real_time_t *b) +static inline int snd_seq_compare_real_time(struct sndrv_seq_real_time *a, struct sndrv_seq_real_time *b) { /* compare real time */ if (a->tv_sec > b->tv_sec) @@ -1461,54 +3011,53 @@ static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, } /* Routine to match events to be removed */ -static int remove_match(snd_seq_remove_events_t *info, - snd_seq_event_t *ev) +static int remove_match(snd_seq_remove_events_t *info, snd_seq_event_t *ev) { int res; - if (info->remove_mode & SND_SEQ_REMOVE_DEST) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) { if (ev->dest.client != info->dest.client || ev->dest.port != info->dest.port) return 0; } - if (info->remove_mode & SND_SEQ_REMOVE_DEST_CHANNEL) { - if (! snd_seq_ev_is_channel_type(ev)) + if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) { + if (! sndrv_seq_ev_is_channel_type(ev)) return 0; /* data.note.channel and data.control.channel are identical */ if (ev->data.note.channel != info->channel) return 0; } - if (info->remove_mode & SND_SEQ_REMOVE_TIME_AFTER) { - if (info->tick) + if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); else res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); if (!res) return 0; } - if (info->remove_mode & SND_SEQ_REMOVE_TIME_BEFORE) { - if (info->tick) + if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK) res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick); else res = snd_seq_compare_real_time(&ev->time.time, &info->time.time); if (res) return 0; } - if (info->remove_mode & SND_SEQ_REMOVE_EVENT_TYPE) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) { if (ev->type != info->type) return 0; } - if (info->remove_mode & SND_SEQ_REMOVE_IGNORE_OFF) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) { /* Do not remove off events */ switch (ev->type) { - case SND_SEQ_EVENT_NOTEOFF: - /* case SND_SEQ_EVENT_SAMPLE_STOP: */ + case SNDRV_SEQ_EVENT_NOTEOFF: + /* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */ return 0; default: break; } } - if (info->remove_mode & SND_SEQ_REMOVE_TAG_MATCH) { + if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) { if (info->tag != ev->tag) return 0; } @@ -1519,28 +3068,27 @@ static int remove_match(snd_seq_remove_events_t *info, /** * \brief remove events on input/output buffers * \param seq sequencer handle + * \param rmp remove event container * * Removes matching events with the given condition from input/output buffers. * The removal condition is specified in rmp argument. */ int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp) { - if (rmp->input) { + if (rmp->remove_mode & SNDRV_SEQ_REMOVE_INPUT) { /* * First deal with any events that are still buffered * in the library. */ - if (rmp->remove_mode == 0) - snd_seq_drop_input_buffer(seq); - /* other modes are not supported yet */ + snd_seq_drop_input_buffer(seq); } - if (rmp->output) { + if (rmp->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) { /* * First deal with any events that are still buffered * in the library. */ - if (rmp->remove_mode == 0) { + if (rmp->remove_mode & ~(SNDRV_SEQ_REMOVE_INPUT|SNDRV_SEQ_REMOVE_OUTPUT)) { /* The simple case - remove all */ snd_seq_drop_output_buffer(seq); } else { @@ -1575,78 +3123,174 @@ int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp) */ /** - * \brief obtain the pool information of the current client - * \param seq sequencer handle - * \param info information to be stored + * \brief get size of #snd_seq_client_pool_t + * \return size in bytes */ -int snd_seq_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info) +size_t snd_seq_client_pool_sizeof() { - assert(seq && info); - info->client = seq->client; - return seq->ops->get_client_pool(seq, info); + return sizeof(snd_seq_client_pool_t); } /** - * \brief set the pool information - * \param seq sequencer handle - * \param info information to update - * - * Sets the pool information of the current client. - * The client field in info is replaced automatically with the current id. + * \brief allocate an empty #snd_seq_client_pool_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code */ -int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info) +int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr) { - assert(seq && info); - info->client = seq->client; - return seq->ops->set_client_pool(seq, info); + assert(ptr); + *ptr = calloc(1, sizeof(snd_seq_client_pool_t)); + if (!*ptr) + return -ENOMEM; + return 0; } -/*----------------------------------------------------------------*/ +/** + * \brief frees a previously allocated #snd_seq_client_pool_t + * \param pointer to object to free + */ +void snd_seq_client_pool_free(snd_seq_client_pool_t *obj) +{ + free(obj); +} -/* - * query functions +/** + * \brief copy one #snd_seq_client_pool_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src) +{ + assert(dst && src); + *dst = *src; +} + + +/** + * \brief Get the client id of a queue_info container + * \param info client_pool container + * \return client id */ +int snd_seq_client_pool_get_client(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->client; +} /** - * \brief query the next matching client + * \brief Get the output pool size of a queue_info container + * \param info client_pool container + * \return output pool size + */ +size_t snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->output_pool; +} + +/** + * \brief Get the input pool size of a queue_info container + * \param info client_pool container + * \return input pool size + */ +size_t snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->input_pool; +} + +/** + * \brief Get the output room size of a queue_info container + * \param info client_pool container + * \return output room size + */ +size_t snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->output_room; +} + +/** + * \brief Get the available size on output pool of a queue_info container + * \param info client_pool container + * \return available output size + */ +size_t snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->output_free; +} + +/** + * \brief Get the available size on input pool of a queue_info container + * \param info client_pool container + * \return available input size + */ +size_t snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t *info) +{ + assert(info); + return info->input_free; +} + +/** + * \brief Set the output pool size of a queue_info container + * \param info client_pool container + * \param size output pool size + */ +void snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t *info, size_t size) +{ + assert(info); + info->output_pool = size; +} + +/** + * \brief Set the input pool size of a queue_info container + * \param info client_pool container + * \param size input pool size + */ +void snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t *info, size_t size) +{ + assert(info); + info->input_pool = size; +} + +/** + * \brief Set the output room size of a queue_info container + * \param info client_pool container + * \param size output room size + */ +void snd_seq_client_pool_set_output_room(snd_seq_client_pool_t *info, size_t size) +{ + assert(info); + info->output_room = size; +} + + +/** + * \brief obtain the pool information of the current client * \param seq sequencer handle - * \param info query pattern and result - * - * Queries the next matching client with the given condition in - * info argument. - * The search begins at the client with an id one greater than - * client field in info. - * If name field in info is not empty, the client name is compared. - * If a matching client is found, its attributes are stored o - * info and returns zero. - * Otherwise returns a negative error code. + * \param info information to be stored */ -int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info) +int snd_seq_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info) { assert(seq && info); - return seq->ops->query_next_client(seq, info); + info->client = seq->client; + return seq->ops->get_client_pool(seq, info); } /** - * \brief query the next matching port + * \brief set the pool information * \param seq sequencer handle - * \param info query pattern and result - - * Queries the next matching port from the port - * on the client given in info argument. - * The search begins at the next port specified in - * port field of info. - * For finding the first port at a certain client, give -1 to - * port field. - * If name field is not empty, the name is checked. - * If a matching port is found, its attributes are stored on - * info and function returns zero. - * Otherwise, a negative error code is returned. + * \param info information to update + * + * Sets the pool information of the current client. + * The client field in \a info is replaced automatically with the current id. */ -int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info) +int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info) { assert(seq && info); - return seq->ops->query_next_port(seq, info); + info->client = seq->client; + return seq->ops->set_client_pool(seq, info); } /*----------------------------------------------------------------*/ @@ -1683,3 +3327,264 @@ int snd_seq_get_bit(int nr, void *array) return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0; } + +/** + * instrument layer + */ + +/** + * \brief get size of #snd_instr_header_t + * \return size in bytes + */ +size_t snd_instr_header_sizeof(void) +{ + return sizeof(snd_instr_header_t); +} + +/** + * \brief allocate an empty #snd_instr_header_t using standard malloc + * \param ptr returned pointer + * \param len additional data length + * \return 0 on success otherwise negative error code + */ +int snd_instr_header_malloc(snd_instr_header_t **ptr, size_t len) +{ + assert(ptr); + *ptr = calloc(1, sizeof(snd_instr_header_t) + len); + if (!*ptr) + return -ENOMEM; + (*ptr)->len = len; + return 0; +} + +/** + * \brief frees a previously allocated #snd_instr_header_t + * \param pointer to object to free + */ +void snd_instr_header_free(snd_instr_header_t *obj) +{ + free(obj); +} + +/** + * \brief copy one #snd_instr_header_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_instr_header_copy(snd_instr_header_t *dst, const snd_instr_header_t *src) +{ + assert(dst && src); + *dst = *src; +} + +/** + * \brief Get the instrument id of an instr_header container + * \param info instr_header container + * \return instrument id pointer + */ +const snd_seq_instr_t *snd_instr_header_get_id(const snd_instr_header_t *info) +{ + assert(info); + return &info->id.instr; +} + +/** + * \brief Get the cluster id of an instr_header container + * \param info instr_header container + * \return cluster id + */ +snd_seq_instr_cluster_t snd_instr_header_get_cluster(const snd_instr_header_t *info) +{ + assert(info); + return info->id.cluster; +} + +/** + * \brief Get the command of an instr_header container + * \param info instr_header container + * \return command type + */ +unsigned int snd_instr_header_get_cmd(const snd_instr_header_t *info) +{ + assert(info); + return info->cmd; +} + +/** + * \brief Get the length of extra data of an instr_header container + * \param info instr_header container + * \return the length in bytes + */ +size_t snd_instr_header_get_len(const snd_instr_header_t *info) +{ + assert(info); + return info->len; +} + +/** + * \brief Get the data name of an instr_header container + * \param info instr_header container + * \return the name string + */ +const char *snd_instr_header_get_name(const snd_instr_header_t *info) +{ + assert(info); + return info->data.name; +} + +/** + * \brief Get the data type of an instr_header container + * \param info instr_header container + * \return the data type + */ +int snd_instr_header_get_type(const snd_instr_header_t *info) +{ + assert(info); + return info->data.type; +} + +/** + * \brief Get the data format of an instr_header container + * \param info instr_header container + * \return the data format string + */ +const char *snd_instr_header_get_format(const snd_instr_header_t *info) +{ + assert(info); + return info->data.data.format; +} + +/** + * \brief Get the data alias of an instr_header container + * \param info instr_header container + * \return the data alias id + */ +const snd_seq_instr_t *snd_instr_header_get_alias(const snd_instr_header_t *info) +{ + assert(info); + return &info->data.data.alias; +} + +/** + * \brief Get the extra data pointer of an instr_header container + * \param info instr_header container + * \return the extra data pointer + */ +void *snd_instr_header_get_data(const snd_instr_header_t *info) +{ + assert(info); + return (void*)((char*)info + sizeof(*info)); +} + +/** + * \brief Get the flag to follow alias of an instr_header container + * \param info instr_header container + * \return 1 if follow alias + */ +int snd_instr_header_get_follow_alias(const snd_instr_header_t *info) +{ + assert(info); + return (info->flags & SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS) ? 1 : 0; +} + +/** + * \brief Set the instrument id of an instr_header container + * \param info instr_header container + * \param id instrumen id pointer + */ +void snd_instr_header_set_id(snd_instr_header_t *info, const snd_seq_instr_t *id) +{ + assert(info && id); + info->id.instr = *id; +} + +/** + * \brief Set the cluster id of an instr_header container + * \param info instr_header container + * \param cluster cluster id + */ +void snd_instr_header_set_cluster(snd_instr_header_t *info, snd_seq_instr_cluster_t cluster) +{ + assert(info); + info->id.cluster = cluster; +} + +/** + * \brief Set the command of an instr_header container + * \param info instr_header container + * \param cmd command type + */ +void snd_instr_header_set_cmd(snd_instr_header_t *info, unsigned int cmd) +{ + assert(info); + info->cmd = cmd; +} + +/** + * \brief Set the length of extra data of an instr_header container + * \param info instr_header container + * \param len size of extra data in bytes + */ +void snd_instr_header_set_len(snd_instr_header_t *info, size_t len) +{ + assert(info); + info->len = len; +} + +/** + * \brief Set the data name of an instr_header container + * \param info instr_header container + * \param name the name string + */ +void snd_instr_header_set_name(snd_instr_header_t *info, const char *name) +{ + assert(info && name); + strncpy(info->data.name, name, sizeof(info->data.name)); +} + +/** + * \brief Set the data type of an instr_header container + * \param info instr_header container + * \param type the data type + */ +void snd_instr_header_set_type(snd_instr_header_t *info, int type) +{ + assert(info); + info->data.type = type; +} + +/** + * \brief Set the data format of an instr_header container + * \param info instr_header container + * \param format the data format string + */ +void snd_instr_header_set_format(snd_instr_header_t *info, const char *format) +{ + assert(info && format); + strncpy(info->data.data.format, format, sizeof(info->data.data.format)); +} + +/** + * \brief Set the data alias id of an instr_header container + * \param info instr_header container + * \param instr alias instrument id + */ +void snd_instr_header_set_alias(snd_instr_header_t *info, const snd_seq_instr_t *instr) +{ + assert(info && instr); + info->data.data.alias = *instr; +} + +/** + * \brief Set the flag to follow alias of an instr_header container + * \param info instr_header container + * \param bool 1 if follow alias + */ +void snd_instr_header_set_follow_alias(snd_instr_header_t *info, int bool) +{ + assert(info); + if (bool) + info->flags |= SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS; + else + info->flags &= ~SNDRV_SEQ_INSTR_QUERY_FOLLOW_ALIAS; +} diff --git a/src/seq/seq_event.c b/src/seq/seq_event.c new file mode 100644 index 00000000..d50f4420 --- /dev/null +++ b/src/seq/seq_event.c @@ -0,0 +1,55 @@ +/** + * \file seq/seq_event.c + * \author Takashi Iwai + * \date 2001 + */ + +#include "../../include/asoundlib.h" + +#define FIXED_EV(x) (_SND_SEQ_TYPE(SND_SEQ_EVFLG_FIXED) | _SND_SEQ_TYPE(x)) + +const unsigned int snd_seq_event_types[256] = { + [SND_SEQ_EVENT_SYSTEM ... SND_SEQ_EVENT_RESULT] + = FIXED_EV(SND_SEQ_EVFLG_RESULT), + [SND_SEQ_EVENT_NOTE] + = FIXED_EV(SND_SEQ_EVFLG_NOTE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_NOTE_TWOARG), + [SND_SEQ_EVENT_NOTEON ... SND_SEQ_EVENT_KEYPRESS] + = FIXED_EV(SND_SEQ_EVFLG_NOTE), + [SND_SEQ_EVENT_CONTROLLER ... SND_SEQ_EVENT_REGPARAM] + = FIXED_EV(SND_SEQ_EVFLG_CONTROL), + [SND_SEQ_EVENT_START ... SND_SEQ_EVENT_STOP] + = FIXED_EV(SND_SEQ_EVFLG_QUEUE), + [SND_SEQ_EVENT_SETPOS_TICK] + = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TICK), + [SND_SEQ_EVENT_SETPOS_TIME] + = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_TIME), + [SND_SEQ_EVENT_TEMPO ... SND_SEQ_EVENT_SYNC_POS] + = FIXED_EV(SND_SEQ_EVFLG_QUEUE) | _SND_SEQ_TYPE_OPT(SND_SEQ_EVFLG_QUEUE_VALUE), + [SND_SEQ_EVENT_TUNE_REQUEST ... SND_SEQ_EVENT_SENSING] + = FIXED_EV(SND_SEQ_EVFLG_NONE), + [SND_SEQ_EVENT_ECHO ... SND_SEQ_EVENT_OSS] + = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_SYSTEM), + [SND_SEQ_EVENT_CLIENT_START ... SND_SEQ_EVENT_PORT_CHANGE] + = FIXED_EV(SND_SEQ_EVFLG_MESSAGE), + [SND_SEQ_EVENT_PORT_SUBSCRIBED ... SND_SEQ_EVENT_PORT_UNSUBSCRIBED] + = FIXED_EV(SND_SEQ_EVFLG_CONNECTION), + [SND_SEQ_EVENT_SAMPLE ... SND_SEQ_EVENT_SAMPLE_PRIVATE1] + = FIXED_EV(SND_SEQ_EVFLG_SAMPLE), + [SND_SEQ_EVENT_USR0 ... SND_SEQ_EVENT_USR9] + = FIXED_EV(SND_SEQ_EVFLG_RAW) | FIXED_EV(SND_SEQ_EVFLG_USERS), + [SND_SEQ_EVENT_INSTR_BEGIN ... SND_SEQ_EVENT_INSTR_CHANGE] + = _SND_SEQ_TYPE(SND_SEQ_EVFLG_INSTR) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARUSR), + [SND_SEQ_EVENT_SYSEX ... SND_SEQ_EVENT_BOUNCE] + = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE), + [SND_SEQ_EVENT_USR_VAR0 ... SND_SEQ_EVENT_USR_VAR4] + = _SND_SEQ_TYPE(SND_SEQ_EVFLG_VARIABLE) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS), +#if 0 // NYI + [SND_SEQ_EVENT_IPCSHM] + = _SND_SEQ_TYPE(SND_SEQ_EVFLG_IPC), + [SND_SEQ_EVENT_USR_VARIPC0 ... SND_SEQ_EVENT_USR_VARIPC4] + = _SND_SEQ_TYPE(SND_SEQ_EVFLG_IPC) | _SND_SEQ_TYPE(SND_SEQ_EVFLG_USERS), +#endif + [SND_SEQ_EVENT_NONE] + = FIXED_EV(SND_SEQ_EVFLG_NONE), +}; + diff --git a/src/seq/seq_hw.c b/src/seq/seq_hw.c index 1fab56ab..b5af002c 100644 --- a/src/seq/seq_hw.c +++ b/src/seq/seq_hw.c @@ -174,7 +174,7 @@ static int snd_seq_hw_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t return 0; } -static int snd_seq_hw_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subs_t * subs) +static int snd_seq_hw_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs) { snd_seq_hw_t *hw = seq->private_data; if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_QUERY_SUBS, subs) < 0) { @@ -214,26 +214,6 @@ static int snd_seq_hw_set_queue_tempo(snd_seq_t *seq, snd_seq_queue_tempo_t * te return 0; } -static int snd_seq_hw_get_queue_owner(snd_seq_t *seq, snd_seq_queue_owner_t * owner) -{ - snd_seq_hw_t *hw = seq->private_data; - if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER, owner) < 0) { - SYSERR("SNDRV_SEQ_IOCTL_GET_QUEUE_OWNER failed"); - return -errno; - } - return 0; -} - -static int snd_seq_hw_set_queue_owner(snd_seq_t *seq, snd_seq_queue_owner_t * owner) -{ - snd_seq_hw_t *hw = seq->private_data; - if (ioctl(hw->fd, SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER, owner) < 0) { - SYSERR("SNDRV_SEQ_IOCTL_SET_QUEUE_OWNER failed"); - return -errno; - } - return 0; -} - static int snd_seq_hw_get_queue_timer(snd_seq_t *seq, snd_seq_queue_timer_t * timer) { snd_seq_hw_t *hw = seq->private_data; @@ -409,8 +389,6 @@ snd_seq_ops_t snd_seq_hw_ops = { get_queue_status: snd_seq_hw_get_queue_status, get_queue_tempo: snd_seq_hw_get_queue_tempo, set_queue_tempo: snd_seq_hw_set_queue_tempo, - get_queue_owner: snd_seq_hw_get_queue_owner, - set_queue_owner: snd_seq_hw_set_queue_owner, get_queue_timer: snd_seq_hw_get_queue_timer, set_queue_timer: snd_seq_hw_set_queue_timer, get_queue_client: snd_seq_hw_get_queue_client, diff --git a/src/seq/seq_local.h b/src/seq/seq_local.h index 165ec856..5eed15e0 100644 --- a/src/seq/seq_local.h +++ b/src/seq/seq_local.h @@ -32,6 +32,9 @@ #define SND_SEQ_IBUF_SIZE 500 /* in event_size aligned */ #define DEFAULT_TMPBUF_SIZE 20 +typedef struct sndrv_seq_queue_client snd_seq_queue_client_t; + + typedef struct { int (*close)(snd_seq_t *seq); int (*nonblock)(snd_seq_t *seq, int nonblock); @@ -45,12 +48,10 @@ typedef struct { int (*get_port_subscription)(snd_seq_t *seq, snd_seq_port_subscribe_t * sub); int (*subscribe_port)(snd_seq_t *seq, snd_seq_port_subscribe_t * sub); int (*unsubscribe_port)(snd_seq_t *seq, snd_seq_port_subscribe_t * sub); - int (*query_port_subscribers)(snd_seq_t *seq, snd_seq_query_subs_t * subs); + int (*query_port_subscribers)(snd_seq_t *seq, snd_seq_query_subscribe_t * subs); int (*get_queue_status)(snd_seq_t *seq, snd_seq_queue_status_t * status); int (*get_queue_tempo)(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo); int (*set_queue_tempo)(snd_seq_t *seq, snd_seq_queue_tempo_t * tempo); - int (*get_queue_owner)(snd_seq_t *seq, snd_seq_queue_owner_t * owner); - int (*set_queue_owner)(snd_seq_t *seq, snd_seq_queue_owner_t * owner); int (*get_queue_timer)(snd_seq_t *seq, snd_seq_queue_timer_t * timer); int (*set_queue_timer)(snd_seq_t *seq, snd_seq_queue_timer_t * timer); int (*get_queue_client)(snd_seq_t *seq, snd_seq_queue_client_t * client); diff --git a/src/seq/seq_midi_event.c b/src/seq/seq_midi_event.c index dbdcd910..5740fe11 100644 --- a/src/seq/seq_midi_event.c +++ b/src/seq/seq_midi_event.c @@ -72,31 +72,31 @@ static struct status_event_list_t { event_decode_t decode; } status_event[] = { /* 0x80 - 0xf0 */ - {SND_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, - {SND_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, - {SND_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, - {SND_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, - {SND_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, - {SND_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, - {SND_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */ + {SNDRV_SEQ_EVENT_NOTEOFF, 2, note_event, note_decode}, + {SNDRV_SEQ_EVENT_NOTEON, 2, note_event, note_decode}, + {SNDRV_SEQ_EVENT_KEYPRESS, 2, note_event, note_decode}, + {SNDRV_SEQ_EVENT_CONTROLLER, 2, two_param_ctrl_event, two_param_decode}, + {SNDRV_SEQ_EVENT_PGMCHANGE, 1, one_param_ctrl_event, one_param_decode}, + {SNDRV_SEQ_EVENT_CHANPRESS, 1, one_param_ctrl_event, one_param_decode}, + {SNDRV_SEQ_EVENT_PITCHBEND, 2, pitchbend_ctrl_event, pitchbend_decode}, + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf0 */ /* 0xf0 - 0xff */ - {SND_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ - {SND_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ - {SND_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ - {SND_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */ - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */ - {SND_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */ - {SND_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */ - {SND_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ - {SND_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ - {SND_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ - {SND_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */ - {SND_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ - {SND_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ + {SNDRV_SEQ_EVENT_SYSEX, 1, NULL, NULL}, /* sysex: 0xf0 */ + {SNDRV_SEQ_EVENT_QFRAME, 1, one_param_event, one_param_decode}, /* 0xf1 */ + {SNDRV_SEQ_EVENT_SONGPOS, 2, songpos_event, songpos_decode}, /* 0xf2 */ + {SNDRV_SEQ_EVENT_SONGSEL, 1, one_param_event, one_param_decode}, /* 0xf3 */ + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf4 */ + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf5 */ + {SNDRV_SEQ_EVENT_TUNE_REQUEST, 0, NULL, NULL}, /* 0xf6 */ + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf7 */ + {SNDRV_SEQ_EVENT_CLOCK, 0, NULL, NULL}, /* 0xf8 */ + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xf9 */ + {SNDRV_SEQ_EVENT_START, 0, NULL, NULL}, /* 0xfa */ + {SNDRV_SEQ_EVENT_CONTINUE, 0, NULL, NULL}, /* 0xfb */ + {SNDRV_SEQ_EVENT_STOP, 0, NULL, NULL}, /* 0xfc */ + {SNDRV_SEQ_EVENT_NONE, 0, NULL, NULL}, /* 0xfd */ + {SNDRV_SEQ_EVENT_SENSING, 0, NULL, NULL}, /* 0xfe */ + {SNDRV_SEQ_EVENT_RESET, 0, NULL, NULL}, /* 0xff */ }; static int extra_decode_ctrl14(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev); @@ -105,9 +105,9 @@ static struct extra_event_list_t { int event; int (*decode)(snd_midi_event_t *dev, unsigned char *buf, int len, snd_seq_event_t *ev); } extra_event[] = { - {SND_SEQ_EVENT_CONTROL14, extra_decode_ctrl14}, - /*{SND_SEQ_EVENT_NONREGPARAM, extra_decode_nrpn},*/ - /*{SND_SEQ_EVENT_REGPARAM, extra_decode_rpn},*/ + {SNDRV_SEQ_EVENT_CONTROL14, extra_decode_ctrl14}, + /*{SNDRV_SEQ_EVENT_NONREGPARAM, extra_decode_nrpn},*/ + /*{SNDRV_SEQ_EVENT_REGPARAM, extra_decode_rpn},*/ }; #define numberof(ary) (sizeof(ary)/sizeof(ary[0])) @@ -201,7 +201,7 @@ long snd_midi_event_encode(snd_midi_event_t *dev, unsigned char *buf, long count long result = 0; int rc; - ev->type = SND_SEQ_EVENT_NONE; + ev->type = SNDRV_SEQ_EVENT_NONE; while (count-- > 0) { rc = snd_midi_event_encode_byte(dev, *buf++, ev); @@ -230,8 +230,8 @@ int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev if (c >= MIDI_CMD_COMMON_CLOCK) { /* real-time event */ ev->type = status_event[ST_SPECIAL + c - 0xf0].event; - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED; + ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; + ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; return 1; } @@ -258,16 +258,16 @@ int snd_midi_event_encode_byte(snd_midi_event_t *dev, int c, snd_seq_event_t *ev } if (dev->qlen == 0) { ev->type = status_event[dev->type].event; - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED; + ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; + ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED; if (status_event[dev->type].encode) /* set data values */ status_event[dev->type].encode(dev, ev); rc = 1; } else if (dev->type == ST_SYSEX) { if (c == MIDI_CMD_COMMON_SYSEX_END || dev->read >= dev->bufsize) { - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_VARIABLE; + ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK; + ev->flags |= SNDRV_SEQ_EVENT_LENGTH_VARIABLE; ev->data.ext.len = dev->read; ev->data.ext.ptr = dev->buf; if (c != MIDI_CMD_COMMON_SYSEX_END) @@ -333,7 +333,7 @@ long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count long qlen; unsigned int type; - if (ev->type == SND_SEQ_EVENT_NONE) + if (ev->type == SNDRV_SEQ_EVENT_NONE) return -ENOENT; for (type = 0; type < numberof(status_event); type++) { @@ -358,9 +358,9 @@ long snd_midi_event_decode(snd_midi_event_t *dev, unsigned char *buf, long count qlen = ev->data.ext.len; if (count < qlen) return -ENOMEM; - switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) { - case SND_SEQ_EVENT_LENGTH_FIXED: - case SND_SEQ_EVENT_LENGTH_VARIPC: + switch (ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) { + case SNDRV_SEQ_EVENT_LENGTH_FIXED: + case SNDRV_SEQ_EVENT_LENGTH_VARIPC: return -EINVAL; /* invalid event */ } memcpy(dev->buf, ev->data.ext.ptr, qlen); diff --git a/src/seq/seqmid.c b/src/seq/seqmid.c index d9a8c463..a1a6d0d8 100644 --- a/src/seq/seqmid.c +++ b/src/seq/seqmid.c @@ -25,114 +25,10 @@ #include #include #include +#include #include #include "seq_local.h" -/** - * \brief set direct passing mode (without queued) - * \param ev event instance - */ -void snd_seq_ev_set_direct(snd_seq_event_t *ev) -{ - ev->queue = SND_SEQ_QUEUE_DIRECT; -} - -/** - * \brief set tick-scheduling mode on queue - * \param ev event instance - * \param q queue id to schedule - * \param relative relative time-stamp if non-zero - * \param tick tick time-stap to be delivered - */ -void snd_seq_ev_schedule_tick(snd_seq_event_t *ev, int q, int relative, - snd_seq_tick_time_t tick) -{ - ev->flags &= ~(SND_SEQ_TIME_STAMP_MASK | SND_SEQ_TIME_MODE_MASK); - ev->flags |= SND_SEQ_TIME_STAMP_TICK; - ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS; - ev->time.tick = tick; - ev->queue = q; -} - -/** - * \brief set real-time-scheduling mode on queue - * \param ev event instance - * \param q queue id to schedule - * \param relative relative time-stamp if non-zero - * \param _time time-stamp to be delivered - */ -void snd_seq_ev_schedule_real(snd_seq_event_t *ev, int q, int relative, - snd_seq_real_time_t *_time) -{ - ev->flags &= ~( SND_SEQ_TIME_STAMP_MASK | SND_SEQ_TIME_MODE_MASK); - ev->flags |= SND_SEQ_TIME_STAMP_REAL; - ev->flags |= relative ? SND_SEQ_TIME_MODE_REL : SND_SEQ_TIME_MODE_ABS; - ev->time.time = *_time; - ev->queue = q; -} - -/** - * \brief set event priority - * \param ev event instance - * \param high_prior 1 for high priority mode - */ -void snd_seq_ev_set_priority(snd_seq_event_t *ev, int high_prior) -{ - ev->flags &= ~SND_SEQ_PRIORITY_MASK; - ev->flags |= high_prior ? SND_SEQ_PRIORITY_HIGH : SND_SEQ_PRIORITY_NORMAL; -} - -/** - * \brief set fixed data - * - * Sets the event length mode as fixed size. - */ -void snd_seq_ev_set_fixed(snd_seq_event_t *ev) -{ - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_FIXED; -} - -/** - * \brief set variable data - * - * Sets the event length mode as variable length and stores the data. - */ -void snd_seq_ev_set_variable(snd_seq_event_t *ev, int len, void *ptr) -{ - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_VARIABLE; - ev->data.ext.len = len; - ev->data.ext.ptr = ptr; -} - -/** - * \brief set varusr data - * - * Sets the event length mode as variable user-space data and stores the data. - */ -void snd_seq_ev_set_varusr(snd_seq_event_t *ev, int len, void *ptr) -{ - ev->flags &= ~SND_SEQ_EVENT_LENGTH_MASK; - ev->flags |= SND_SEQ_EVENT_LENGTH_VARUSR; - ev->data.ext.len = len; - ev->data.ext.ptr = ptr; -} - - -/** - * \brief use or unuse a queue - */ -int snd_seq_use_queue(snd_seq_t *seq, int q, int use) -{ - snd_seq_queue_client_t info; - - memset(&info, 0, sizeof(info)); - info.used = use; - return snd_seq_set_queue_client(seq, q, &info); -} - - /** * \brief queue controls - start/stop/continue * \param seq sequencer handle @@ -141,8 +37,11 @@ int snd_seq_use_queue(snd_seq_t *seq, int q, int use) * \param value event value * \param ev event instance * - * if ev is NULL, send events immediately. - * otherwise, duplicate the given event data. + * This function sets up general queue control event and sends it. + * To send at scheduled time, set the schedule in \a ev. + * If \a ev is NULL, the event is composed locally and sent immediately + * to the specified queue. In any cases, you need to call #snd_seq_drain_event + * apropriately to feed the event. */ int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev) { @@ -156,38 +55,16 @@ int snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_ev return snd_seq_event_output(seq, ev); } -/** - * \brief reset queue position - * - * new values of both real-time and tick values must be given. - */ -int snd_seq_setpos_queue(snd_seq_t *seq, int q, snd_seq_timestamp_t *rtime, snd_seq_event_t *ev) -{ - snd_seq_event_t tmpev; - int result; - - if (ev == NULL) { - snd_seq_ev_clear(&tmpev); - ev = &tmpev; - snd_seq_ev_set_direct(ev); - } - /* stop the timer */ - result = snd_seq_stop_queue(seq, q, ev); - /* reset queue position */ - snd_seq_ev_set_queue_pos_real(ev, q, &rtime->time); - result = snd_seq_event_output(seq, ev); - snd_seq_ev_set_queue_pos_tick(ev, q, rtime->tick); - result = snd_seq_event_output(seq, ev); - /* continue the timer */ - result = snd_seq_continue_queue(seq, q, ev); - - return result; -} /** * \brief create a port - simple version + * \param seq sequencer handle + * \param name the name of the port + * \param caps capability bits + * \param type type bits + * \return the created port number or negative error code * - * return the port number + * Creates a port with the given capability and type bits. */ int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, unsigned int caps, unsigned int type) @@ -199,35 +76,38 @@ int snd_seq_create_simple_port(snd_seq_t *seq, const char *name, if (name) strncpy(pinfo.name, name, sizeof(pinfo.name) - 1); pinfo.capability = caps; - pinfo.cap_group = caps; pinfo.type = type; pinfo.midi_channels = 16; pinfo.midi_voices = 64; /* XXX */ pinfo.synth_voices = 0; /* XXX */ - pinfo.kernel = NULL; result = snd_seq_create_port(seq, &pinfo); if (result < 0) return result; else - return pinfo.port; + return pinfo.addr.port; } /** * \brief delete the port + * \param seq sequencer handle + * \param port port id + * \return 0 on success or negavie error code */ int snd_seq_delete_simple_port(snd_seq_t *seq, int port) { - snd_seq_port_info_t pinfo; - - memset(&pinfo, 0, sizeof(pinfo)); - pinfo.port = port; - - return snd_seq_delete_port(seq, &pinfo); + return snd_seq_delete_port(seq, port); } /** - * \brief sipmle subscription (w/o exclusive & time conversion) + * \brief simple subscription (w/o exclusive & time conversion) + * \param myport the port id as receiver + * \param src_client sender client id + * \param src_port sender port id + * \return 0 on success or negative error code + * + * Connect from the given sender client:port to the given destination port in the + * current client. */ int snd_seq_connect_from(snd_seq_t *seq, int myport, int src_client, int src_port) { @@ -245,6 +125,13 @@ int snd_seq_connect_from(snd_seq_t *seq, int myport, int src_client, int src_por /** * \brief sipmle subscription (w/o exclusive & time conversion) + * \param myport the port id as sender + * \param dest_client destination client id + * \param dest_port destination port id + * \return 0 on success or negative error code + * + * Connect from the given receiver port in the current client + * to the given destination client:port. */ int snd_seq_connect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port) { @@ -261,7 +148,14 @@ int snd_seq_connect_to(snd_seq_t *seq, int myport, int dest_client, int dest_por } /** - * \brief sipmle disconnection (w/o exclusive & time conversion) + * \brief simple disconnection + * \param myport the port id as receiver + * \param src_client sender client id + * \param src_port sender port id + * \return 0 on success or negative error code + * + * Remove connection from the given sender client:port + * to the given destination port in the current client. */ int snd_seq_disconnect_from(snd_seq_t *seq, int myport, int src_client, int src_port) { @@ -278,7 +172,14 @@ int snd_seq_disconnect_from(snd_seq_t *seq, int myport, int src_client, int src_ } /** - * \brief sipmle disconnection (w/o exclusive & time conversion) + * \brief simple disconnection + * \param myport the port id as sender + * \param dest_client destination client id + * \param dest_port destination port id + * \return 0 on success or negative error code + * + * Remove connection from the given sender client:port + * to the given destination port in the current client. */ int snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port) { @@ -297,8 +198,12 @@ int snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_ /* * set client information */ + /** * \brief set client name + * \param seq sequencer handle + * \param name name string + * \return 0 on success or negative error code */ int snd_seq_set_client_name(snd_seq_t *seq, const char *name) { @@ -312,35 +217,10 @@ int snd_seq_set_client_name(snd_seq_t *seq, const char *name) } /** - * \brief set client group - */ -int snd_seq_set_client_group(snd_seq_t *seq, const char *name) -{ - snd_seq_client_info_t info; - int err; - - if ((err = snd_seq_get_client_info(seq, &info)) < 0) - return err; - strncpy(info.group, name, sizeof(info.group) - 1); - return snd_seq_set_client_info(seq, &info); -} - -/** - * \brief set client filter - */ -int snd_seq_set_client_filter(snd_seq_t *seq, unsigned int filter) -{ - snd_seq_client_info_t info; - int err; - - if ((err = snd_seq_get_client_info(seq, &info)) < 0) - return err; - info.filter = filter; - return snd_seq_set_client_info(seq, &info); -} - -/** - * \brief set client event filter + * \brief add client event filter + * \param seq sequencer handle + * \param event_type event type to be added + * \return 0 on success or negative error code */ int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type) { @@ -349,15 +229,18 @@ int snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type) if ((err = snd_seq_get_client_info(seq, &info)) < 0) return err; - info.filter |= SND_SEQ_FILTER_USE_EVENT; + info.filter |= SNDRV_SEQ_FILTER_USE_EVENT; snd_seq_set_bit(event_type, info.event_filter); return snd_seq_set_client_info(seq, &info); } /** * \brief change the output pool size of the given client + * \param seq sequencer handle + * \param size output pool size + * \return 0 on success or negative error code */ -int snd_seq_set_client_pool_output(snd_seq_t *seq, int size) +int snd_seq_set_client_pool_output(snd_seq_t *seq, size_t size) { snd_seq_client_pool_t info; int err; @@ -370,8 +253,11 @@ int snd_seq_set_client_pool_output(snd_seq_t *seq, int size) /** * \brief change the output room size of the given client + * \param seq sequencer handle + * \param size output room size + * \return 0 on success or negative error code */ -int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size) +int snd_seq_set_client_pool_output_room(snd_seq_t *seq, size_t size) { snd_seq_client_pool_t info; int err; @@ -384,8 +270,11 @@ int snd_seq_set_client_pool_output_room(snd_seq_t *seq, int size) /** * \brief change the input pool size of the given client + * \param seq sequencer handle + * \param size input pool size + * \return 0 on success or negative error code */ -int snd_seq_set_client_pool_input(snd_seq_t *seq, int size) +int snd_seq_set_client_pool_input(snd_seq_t *seq, size_t size) { snd_seq_client_pool_t info; int err; @@ -398,27 +287,74 @@ int snd_seq_set_client_pool_input(snd_seq_t *seq, int size) /** * \brief reset client output pool + * \param seq sequencer handle + * \return 0 on success or negative error code */ int snd_seq_reset_pool_output(snd_seq_t *seq) { - snd_seq_remove_events_t rmp; + struct sndrv_seq_remove_events rmp; memset(&rmp, 0, sizeof(rmp)); - rmp.output = 1; - rmp.remove_mode = 0; /* remove all */ + rmp.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT; /* remove all outputs */ return snd_seq_remove_events(seq, &rmp); } /** * \brief reset client input pool + * \param seq sequencer handle + * \return 0 on success or negative error code */ int snd_seq_reset_pool_input(snd_seq_t *seq) { snd_seq_remove_events_t rmp; memset(&rmp, 0, sizeof(rmp)); - rmp.input = 1; - rmp.remove_mode = 0; /* remove all */ + rmp.remove_mode = SNDRV_SEQ_REMOVE_INPUT; /* remove all inputs */ return snd_seq_remove_events(seq, &rmp); } +/** + * \brief parse the given string and get the sequencer address + * \param seq sequencer handle + * \param addr the address pointer to be returned + * \param arg the string to be parsed + * \return 0 on success or negative error code + */ +int snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *arg) +{ + char *p; + int client, port; + + assert(seq && addr && arg); + + if ((p = strpbrk(arg, ":.")) == NULL) + return -EINVAL; + if ((port = atoi(p + 1)) < 0) + return -EINVAL; + addr->port = port; + if (isdigit(*arg)) { + client = atoi(arg); + if (client < 0) + return -EINVAL; + addr->client = client; + } else { + /* convert from the name */ + snd_seq_client_info_t cinfo; + int len; + + *p = 0; + len = (int)(p - arg); /* length of client name */ + if (len <= 0) + return -EINVAL; + cinfo.client = -1; + while (snd_seq_query_next_client(seq, &cinfo) >= 0) { + if (! strncmp(cinfo.name, arg, len)) { + addr->client = cinfo.client; + return 0; + } + } + return -ENOENT; /* not found */ + } + return 0; +} + diff --git a/test/playmidi1.c b/test/playmidi1.c index a7b20467..7fc7baa7 100644 --- a/test/playmidi1.c +++ b/test/playmidi1.c @@ -114,13 +114,11 @@ static void write_ev(snd_seq_event_t *ev) return; } while ((rc = snd_seq_event_output(seq_handle, ev)) < 0) { - int seqfd; - fd_set fds; - seqfd = snd_seq_poll_descriptor(seq_handle); - FD_ZERO(&fds); - FD_SET(seqfd, &fds); - if ((rc = select(seqfd + 1, NULL, &fds, NULL, NULL)) < 0) { - printf("select error = %i (%s)\n", rc, snd_strerror(rc)); + int npfds = snd_seq_poll_descriptors_count(seq_handle, POLLOUT); + struct pollfd *pfds = alloca(sizeof(*pfds) * npfds); + snd_seq_poll_descriptors(seq_handle, pfds, npfds, POLLOUT); + if ((rc = poll(pfds, npfds, -1)) < 0) { + printf("poll error = %i (%s)\n", rc, snd_strerror(errno)); exit(1); } } @@ -147,7 +145,7 @@ static void mytext(int type, int leng, char *msg) static void do_header(int format, int ntracks, int division) { - snd_seq_queue_tempo_t tempo; + snd_seq_queue_tempo_t *tempo; if (verbose >= VERB_INFO) printf("smf format %d, %d tracks, %d ppq\n", format, ntracks, division); @@ -159,15 +157,16 @@ static void do_header(int format, int ntracks, int division) exit(1); } /* set ppq */ + snd_seq_queue_tempo_alloca(&tempo); /* ppq must be set before starting timer */ - if (snd_seq_get_queue_tempo(seq_handle, dest_queue, &tempo) < 0) { + if (snd_seq_get_queue_tempo(seq_handle, dest_queue, tempo) < 0) { perror("get_queue_tempo"); exit(1); } - if (tempo.ppq != ppq) { - slave_ppq = tempo.ppq; - tempo.ppq = ppq; - if (snd_seq_set_queue_tempo(seq_handle, dest_queue, &tempo) < 0) { + if (snd_seq_queue_tempo_get_ppq(tempo) != ppq) { + slave_ppq = snd_seq_queue_tempo_get_ppq(tempo); + snd_seq_queue_tempo_set_ppq(tempo, ppq); + if (snd_seq_set_queue_tempo(seq_handle, dest_queue, tempo) < 0) { perror("set_queue_tempo"); if (!slave) exit(1); @@ -176,7 +175,7 @@ static void do_header(int format, int ntracks, int division) } else slave_ppq = ppq; if (verbose >= VERB_INFO) - printf("ALSA Timer updated, PPQ = %d\n", tempo.ppq); + printf("ALSA Timer updated, PPQ = %d\n", snd_seq_queue_tempo_get_ppq(tempo)); } /* start playing... */ @@ -364,13 +363,11 @@ static snd_seq_event_t *wait_for_event(void) /* read event - using select syscall */ while ((left = snd_seq_event_input(seq_handle, &input_event)) >= 0 && input_event == NULL) { - int seqfd; - fd_set fds; - seqfd = snd_seq_poll_descriptor(seq_handle); - FD_ZERO(&fds); - FD_SET(seqfd, &fds); - if ((left = select(seqfd + 1, &fds, NULL, NULL, NULL)) < 0) { - printf("select error = %i (%s)\n", left, snd_strerror(left)); + int npfds = snd_seq_poll_descriptors_count(seq_handle, POLLIN); + struct pollfd *pfds = alloca(sizeof(*pfds) * npfds); + snd_seq_poll_descriptors(seq_handle, pfds, npfds, POLLIN); + if ((left = poll(pfds, npfds, -1)) < 0) { + printf("poll error = %i (%s)\n", errno, snd_strerror(errno)); exit(1); } } @@ -525,13 +522,13 @@ int main(int argc, char *argv[]) /* open sequencer device */ /* Here we open the device read/write mode. */ /* Because we write SND_SEQ_EVENT_ECHO to myself to sync. */ - tmp = snd_seq_open(&seq_handle, SND_SEQ_OPEN); + tmp = snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0); if (tmp < 0) { perror("open /dev/snd/seq"); exit(1); } - tmp = snd_seq_block_mode(seq_handle, use_blocking_mode); + tmp = snd_seq_nonblock(seq_handle, !use_blocking_mode); if (tmp < 0) { perror("block_mode"); exit(1); @@ -557,7 +554,7 @@ int main(int argc, char *argv[]) /* setup queue */ if (dest_queue >= 0) { - if (snd_seq_use_queue(seq_handle, dest_queue, 1) < 0) { + if (snd_seq_set_queue_usage(seq_handle, dest_queue, 1) < 0) { perror("use queue"); exit(1); } @@ -580,7 +577,7 @@ int main(int argc, char *argv[]) if (slave) { tmp = snd_seq_connect_from(seq_handle, my_port, SND_SEQ_CLIENT_SYSTEM, - snd_seq_queue_sync_port(dest_queue)); + dest_queue + 16 /*snd_seq_queue_sync_port(dest_queue)*/); if (tmp < 0) { perror("subscribe"); exit(1); diff --git a/test/seq-decoder.c b/test/seq-decoder.c index 87e610fe..09cc1100 100644 --- a/test/seq-decoder.c +++ b/test/seq-decoder.c @@ -3,262 +3,99 @@ */ static char *event_names[256] = { - /* 0 */ "System", - /* 1 */ "Result", - /* 2 */ "Reserved 2", - /* 3 */ "Reserved 3", - /* 4 */ "Reserved 4", - /* 5 */ "Note", - /* 6 */ "Note On", - /* 7 */ "Note Off", - /* 8 */ "Key Pressure", - /* 9 */ "Reserved 9", - /* 10 */ "Controller", - /* 11 */ "Program Change", - /* 12 */ "Channel Pressure", - /* 13 */ "Pitchbend", - /* 14 */ "Control14", - /* 15 */ "Nonregparam", - /* 16 */ "Regparam", - /* 17 */ "Reserved 17", - /* 18 */ "Reserved 18", - /* 19 */ "Reserved 19", - /* 20 */ "Song Position", - /* 21 */ "Song Select", - /* 22 */ "Qframe", - /* 23 */ "SMF Time Signature", - /* 24 */ "SMF Key Signature", - /* 25 */ "Reserved 25", - /* 26 */ "Reserved 26", - /* 27 */ "Reserved 27", - /* 28 */ "Reserved 28", - /* 29 */ "Reserved 29", - /* 30 */ "Start", - /* 31 */ "Continue", - /* 32 */ "Stop", - /* 33 */ "Set Position Tick", - /* 34 */ "Set Position Time", - /* 35 */ "Tempo", - /* 36 */ "Clock", - /* 37 */ "Tick", - /* 38 */ "Reserved 38", - /* 39 */ "Reserved 39", - /* 40 */ "Tune Request", - /* 41 */ "Reset", - /* 42 */ "Active Sensing", - /* 43 */ "Reserved 43", - /* 44 */ "Reserved 44", - /* 45 */ "Reserved 45", - /* 46 */ "Reserved 46", - /* 47 */ "Reserved 47", - /* 48 */ "Reserved 48", - /* 49 */ "Reserved 49", - /* 50 */ "Echo", - /* 51 */ "OSS", - /* 52 */ "Reserved 52", - /* 53 */ "Reserved 53", - /* 54 */ "Reserved 54", - /* 55 */ "Reserved 55", - /* 56 */ "Reserved 56", - /* 57 */ "Reserved 57", - /* 58 */ "Reserved 58", - /* 59 */ "Reserved 59", - /* 60 */ "Client Start", - /* 61 */ "Client Exit", - /* 62 */ "Client Change", - /* 63 */ "Port Start", - /* 64 */ "Port Exit", - /* 65 */ "Port Change", - /* 66 */ "Port Subscribed", - /* 67 */ "Port Used", - /* 68 */ "Port Unsubscribed", - /* 69 */ "Port Unused", - /* 70 */ "Sample", - /* 71 */ "Sample Cluster", - /* 72 */ "Sample Start", - /* 73 */ "Sample Stop", - /* 74 */ "Sample Freq", - /* 75 */ "Sample Volume", - /* 76 */ "Sample Loop", - /* 77 */ "Sample Position", - /* 78 */ "Sample Private1", - /* 79 */ "Reserved 79", - /* 80 */ "Reserved 80", - /* 81 */ "Reserved 81", - /* 82 */ "Reserved 82", - /* 83 */ "Reserved 83", - /* 84 */ "Reserved 84", - /* 85 */ "Reserved 85", - /* 86 */ "Reserved 86", - /* 87 */ "Reserved 87", - /* 88 */ "Reserved 88", - /* 89 */ "Reserved 89", - /* 90 */ "User 0", - /* 91 */ "User 1", - /* 92 */ "User 2", - /* 93 */ "User 3", - /* 94 */ "User 4", - /* 95 */ "User 5", - /* 96 */ "User 6", - /* 97 */ "User 7", - /* 98 */ "User 8", - /* 99 */ "User 9", - /* 100 */ "Instr Begin", - /* 101 */ "Instr End", - /* 102 */ "Instr Info", - /* 103 */ "Instr Info Result", - /* 104 */ "Instr Finfo", - /* 105 */ "Instr Finfo Result", - /* 106 */ "Instr Reset", - /* 107 */ "Instr Status", - /* 108 */ "Instr Status Result", - /* 109 */ "Instr Put", - /* 110 */ "Instr Get", - /* 111 */ "Instr Get Result", - /* 112 */ "Instr Free", - /* 113 */ "Instr List", - /* 114 */ "Instr List Result", - /* 115 */ "Instr Cluster", - /* 116 */ "Instr Cluster Get", - /* 117 */ "Instr Cluster Result", - /* 118 */ "Instr Change", - /* 119 */ "Reserved 119", - /* 120 */ "Reserved 120", - /* 121 */ "Reserved 121", - /* 122 */ "Reserved 122", - /* 123 */ "Reserved 123", - /* 124 */ "Reserved 124", - /* 125 */ "Reserved 125", - /* 126 */ "Reserved 126", - /* 127 */ "Reserved 127", - /* 128 */ "Reserved 128", - /* 129 */ "Reserved 129", - /* 130 */ "Sysex", - /* 131 */ "Bounce", - /* 132 */ "Reserved 132", - /* 133 */ "Reserved 133", - /* 134 */ "Reserved 134", - /* 135 */ "User Var0", - /* 136 */ "User Var1", - /* 137 */ "User Var2", - /* 138 */ "User Var3", - /* 139 */ "User Var4", - /* 140 */ "IPC Shm", - /* 141 */ "Reserved 141", - /* 142 */ "Reserved 142", - /* 143 */ "Reserved 143", - /* 144 */ "Reserved 144", - /* 145 */ "User IPC0", - /* 146 */ "User IPC1", - /* 147 */ "User IPC2", - /* 148 */ "User IPC3", - /* 149 */ "User IPC4", - /* 150 */ "Reserved 150", - /* 151 */ "Reserved 151", - /* 152 */ "Reserved 152", - /* 153 */ "Reserved 153", - /* 154 */ "Reserved 154", - /* 155 */ "Reserved 155", - /* 156 */ "Reserved 156", - /* 157 */ "Reserved 157", - /* 158 */ "Reserved 158", - /* 159 */ "Reserved 159", - /* 160 */ "Reserved 160", - /* 161 */ "Reserved 161", - /* 162 */ "Reserved 162", - /* 163 */ "Reserved 163", - /* 164 */ "Reserved 164", - /* 165 */ "Reserved 165", - /* 166 */ "Reserved 166", - /* 167 */ "Reserved 167", - /* 168 */ "Reserved 168", - /* 169 */ "Reserved 169", - /* 170 */ "Reserved 170", - /* 171 */ "Reserved 171", - /* 172 */ "Reserved 172", - /* 173 */ "Reserved 173", - /* 174 */ "Reserved 174", - /* 175 */ "Reserved 175", - /* 176 */ "Reserved 176", - /* 177 */ "Reserved 177", - /* 178 */ "Reserved 178", - /* 179 */ "Reserved 179", - /* 180 */ "Reserved 180", - /* 181 */ "Reserved 181", - /* 182 */ "Reserved 182", - /* 183 */ "Reserved 183", - /* 184 */ "Reserved 184", - /* 185 */ "Reserved 185", - /* 186 */ "Reserved 186", - /* 187 */ "Reserved 187", - /* 188 */ "Reserved 188", - /* 189 */ "Reserved 189", - /* 190 */ "Reserved 190", - /* 191 */ "Reserved 191", - /* 192 */ "Reserved 192", - /* 193 */ "Reserved 193", - /* 194 */ "Reserved 194", - /* 195 */ "Reserved 195", - /* 196 */ "Reserved 196", - /* 197 */ "Reserved 197", - /* 198 */ "Reserved 198", - /* 199 */ "Reserved 199", - /* 200 */ "Reserved 200", - /* 201 */ "Reserved 201", - /* 202 */ "Reserved 202", - /* 203 */ "Reserved 203", - /* 204 */ "Reserved 204", - /* 205 */ "Reserved 205", - /* 206 */ "Reserved 206", - /* 207 */ "Reserved 207", - /* 208 */ "Reserved 208", - /* 209 */ "Reserved 209", - /* 210 */ "Reserved 210", - /* 211 */ "Reserved 211", - /* 212 */ "Reserved 212", - /* 213 */ "Reserved 213", - /* 214 */ "Reserved 214", - /* 215 */ "Reserved 215", - /* 216 */ "Reserved 216", - /* 217 */ "Reserved 217", - /* 218 */ "Reserved 218", - /* 219 */ "Reserved 219", - /* 220 */ "Reserved 220", - /* 221 */ "Reserved 221", - /* 222 */ "Reserved 222", - /* 223 */ "Reserved 223", - /* 224 */ "Reserved 224", - /* 225 */ "Reserved 225", - /* 226 */ "Reserved 226", - /* 227 */ "Reserved 227", - /* 228 */ "Reserved 228", - /* 229 */ "Reserved 229", - /* 230 */ "Reserved 230", - /* 231 */ "Reserved 231", - /* 232 */ "Reserved 232", - /* 233 */ "Reserved 233", - /* 234 */ "Reserved 234", - /* 235 */ "Reserved 235", - /* 236 */ "Reserved 236", - /* 237 */ "Reserved 237", - /* 238 */ "Reserved 238", - /* 239 */ "Reserved 239", - /* 240 */ "Reserved 240", - /* 241 */ "Reserved 241", - /* 242 */ "Reserved 242", - /* 243 */ "Reserved 243", - /* 244 */ "Reserved 244", - /* 245 */ "Reserved 245", - /* 246 */ "Reserved 246", - /* 247 */ "Reserved 247", - /* 248 */ "Reserved 248", - /* 249 */ "Reserved 249", - /* 250 */ "Reserved 250", - /* 251 */ "Reserved 251", - /* 252 */ "Reserved 252", - /* 253 */ "Reserved 253", - /* 254 */ "Reserved 254", - /* 255 */ "None" + [SND_SEQ_EVENT_SYSTEM]= "System", + [SND_SEQ_EVENT_RESULT]= "Result", + [SND_SEQ_EVENT_NOTE]= "Note", + [SND_SEQ_EVENT_NOTEON]= "Note On", + [SND_SEQ_EVENT_NOTEOFF]= "Note Off", + [SND_SEQ_EVENT_KEYPRESS]= "Key Pressure", + [SND_SEQ_EVENT_CONTROLLER]= "Controller", + [SND_SEQ_EVENT_PGMCHANGE]= "Program Change", + [SND_SEQ_EVENT_CHANPRESS]= "Channel Pressure", + [SND_SEQ_EVENT_PITCHBEND]= "Pitchbend", + [SND_SEQ_EVENT_CONTROL14]= "Control14", + [SND_SEQ_EVENT_NONREGPARAM]= "Nonregparam", + [SND_SEQ_EVENT_REGPARAM]= "Regparam", + [SND_SEQ_EVENT_SONGPOS]= "Song Position", + [SND_SEQ_EVENT_SONGSEL]= "Song Select", + [SND_SEQ_EVENT_QFRAME]= "Qframe", + [SND_SEQ_EVENT_TIMESIGN]= "SMF Time Signature", + [SND_SEQ_EVENT_KEYSIGN]= "SMF Key Signature", + [SND_SEQ_EVENT_START]= "Start", + [SND_SEQ_EVENT_CONTINUE]= "Continue", + [SND_SEQ_EVENT_STOP]= "Stop", + [SND_SEQ_EVENT_SETPOS_TICK]= "Set Position Tick", + [SND_SEQ_EVENT_SETPOS_TIME]= "Set Position Time", + [SND_SEQ_EVENT_TEMPO]= "Tempo", + [SND_SEQ_EVENT_CLOCK]= "Clock", + [SND_SEQ_EVENT_TICK]= "Tick", + [SND_SEQ_EVENT_SYNC]= "Sync", + [SND_SEQ_EVENT_SYNC_POS]= "Sync Position", + [SND_SEQ_EVENT_TUNE_REQUEST]= "Tune Request", + [SND_SEQ_EVENT_RESET]= "Reset", + [SND_SEQ_EVENT_SENSING]= "Active Sensing", + [SND_SEQ_EVENT_ECHO]= "Echo", + [SND_SEQ_EVENT_OSS]= "OSS", + [SND_SEQ_EVENT_CLIENT_START]= "Client Start", + [SND_SEQ_EVENT_CLIENT_EXIT]= "Client Exit", + [SND_SEQ_EVENT_CLIENT_CHANGE]= "Client Change", + [SND_SEQ_EVENT_PORT_START]= "Port Start", + [SND_SEQ_EVENT_PORT_EXIT]= "Port Exit", + [SND_SEQ_EVENT_PORT_CHANGE]= "Port Change", + [SND_SEQ_EVENT_PORT_SUBSCRIBED]= "Port Subscribed", + [SND_SEQ_EVENT_PORT_UNSUBSCRIBED]= "Port Unsubscribed", + [SND_SEQ_EVENT_SAMPLE]= "Sample", + [SND_SEQ_EVENT_SAMPLE_CLUSTER]= "Sample Cluster", + [SND_SEQ_EVENT_SAMPLE_START]= "Sample Start", + [SND_SEQ_EVENT_SAMPLE_STOP]= "Sample Stop", + [SND_SEQ_EVENT_SAMPLE_FREQ]= "Sample Freq", + [SND_SEQ_EVENT_SAMPLE_VOLUME]= "Sample Volume", + [SND_SEQ_EVENT_SAMPLE_LOOP]= "Sample Loop", + [SND_SEQ_EVENT_SAMPLE_POSITION]= "Sample Position", + [SND_SEQ_EVENT_SAMPLE_PRIVATE1]= "Sample Private1", + [SND_SEQ_EVENT_USR0]= "User 0", + [SND_SEQ_EVENT_USR1]= "User 1", + [SND_SEQ_EVENT_USR2]= "User 2", + [SND_SEQ_EVENT_USR3]= "User 3", + [SND_SEQ_EVENT_USR4]= "User 4", + [SND_SEQ_EVENT_USR5]= "User 5", + [SND_SEQ_EVENT_USR6]= "User 6", + [SND_SEQ_EVENT_USR7]= "User 7", + [SND_SEQ_EVENT_USR8]= "User 8", + [SND_SEQ_EVENT_USR9]= "User 9", + [SND_SEQ_EVENT_INSTR_BEGIN]= "Instr Begin", + [SND_SEQ_EVENT_INSTR_END]= "Instr End", + [SND_SEQ_EVENT_INSTR_INFO]= "Instr Info", + [SND_SEQ_EVENT_INSTR_INFO_RESULT]= "Instr Info Result", + [SND_SEQ_EVENT_INSTR_FINFO]= "Instr Font Info", + [SND_SEQ_EVENT_INSTR_FINFO_RESULT]= "Instr Font Info Result", + [SND_SEQ_EVENT_INSTR_RESET]= "Instr Reset", + [SND_SEQ_EVENT_INSTR_STATUS]= "Instr Status", + [SND_SEQ_EVENT_INSTR_STATUS_RESULT]= "Instr Status Result", + [SND_SEQ_EVENT_INSTR_PUT]= "Instr Put", + [SND_SEQ_EVENT_INSTR_GET]= "Instr Get", + [SND_SEQ_EVENT_INSTR_GET_RESULT]= "Instr Get Result", + [SND_SEQ_EVENT_INSTR_FREE]= "Instr Free", + [SND_SEQ_EVENT_INSTR_LIST]= "Instr List", + [SND_SEQ_EVENT_INSTR_LIST_RESULT]= "Instr List Result", + [SND_SEQ_EVENT_INSTR_CLUSTER]= "Instr Cluster", + [SND_SEQ_EVENT_INSTR_CLUSTER_GET]= "Instr Cluster Get", + [SND_SEQ_EVENT_INSTR_CLUSTER_RESULT]= "Instr Cluster Result", + [SND_SEQ_EVENT_INSTR_CHANGE]= "Instr Change", + [SND_SEQ_EVENT_SYSEX]= "Sysex", + [SND_SEQ_EVENT_BOUNCE]= "Bounce", + [SND_SEQ_EVENT_USR_VAR0]= "User Var0", + [SND_SEQ_EVENT_USR_VAR1]= "User Var1", + [SND_SEQ_EVENT_USR_VAR2]= "User Var2", + [SND_SEQ_EVENT_USR_VAR3]= "User Var3", + [SND_SEQ_EVENT_USR_VAR4]= "User Var4", + [SND_SEQ_EVENT_IPCSHM]= "IPC Shm", + [SND_SEQ_EVENT_USR_VARIPC0]= "User IPC0", + [SND_SEQ_EVENT_USR_VARIPC1]= "User IPC1", + [SND_SEQ_EVENT_USR_VARIPC2]= "User IPC2", + [SND_SEQ_EVENT_USR_VARIPC3]= "User IPC3", + [SND_SEQ_EVENT_USR_VARIPC4]= "User IPC4", + [SND_SEQ_EVENT_NONE]= "None", }; int decode_event(snd_seq_event_t * ev) @@ -267,15 +104,15 @@ int decode_event(snd_seq_event_t * ev) printf("EVENT>>> Type = %d, flags = 0x%x", ev->type, ev->flags); switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) { - case SND_SEQ_TIME_STAMP_TICK: - printf(", time = %d ticks", - ev->time.tick); - break; - case SND_SEQ_TIME_STAMP_REAL: - printf(", time = %d.%09d", - (int)ev->time.time.tv_sec, - (int)ev->time.time.tv_nsec); - break; + case SND_SEQ_TIME_STAMP_TICK: + printf(", time = %d ticks", + ev->time.tick); + break; + case SND_SEQ_TIME_STAMP_REAL: + printf(", time = %d.%09d", + (int)ev->time.time.tv_sec, + (int)ev->time.time.tv_nsec); + break; } printf("\n%sSource = %d.%d, dest = %d.%d, queue = %d\n", space, @@ -285,114 +122,120 @@ int decode_event(snd_seq_event_t * ev) ev->dest.port, ev->queue); - printf("%sEvent = %s", space, event_names[ev->type]); + if (event_names[ev->type]) + printf("%sEvent = %s", space, event_names[ev->type]); + else + printf("%sEvent = Reserved %d\n", space, ev->type); /* decode actual event data... */ switch (ev->type) { - case SND_SEQ_EVENT_NOTE: - printf("; ch=%d, note=%d, velocity=%d, off_velocity=%d, duration=%d\n", - ev->data.note.channel, - ev->data.note.note, - ev->data.note.velocity, - ev->data.note.off_velocity, - ev->data.note.duration); - break; + case SND_SEQ_EVENT_NOTE: + printf("; ch=%d, note=%d, velocity=%d, off_velocity=%d, duration=%d\n", + ev->data.note.channel, + ev->data.note.note, + ev->data.note.velocity, + ev->data.note.off_velocity, + ev->data.note.duration); + break; - case SND_SEQ_EVENT_NOTEON: - case SND_SEQ_EVENT_NOTEOFF: - case SND_SEQ_EVENT_KEYPRESS: - printf("; ch=%d, note=%d, velocity=%d\n", - ev->data.note.channel, - ev->data.note.note, - ev->data.note.velocity); - break; + case SND_SEQ_EVENT_NOTEON: + case SND_SEQ_EVENT_NOTEOFF: + case SND_SEQ_EVENT_KEYPRESS: + printf("; ch=%d, note=%d, velocity=%d\n", + ev->data.note.channel, + ev->data.note.note, + ev->data.note.velocity); + break; - case SND_SEQ_EVENT_CONTROLLER: - printf("; ch=%d, param=%i, value=%i\n", - ev->data.control.channel, - ev->data.control.param, - ev->data.control.value); - break; + case SND_SEQ_EVENT_CONTROLLER: + printf("; ch=%d, param=%i, value=%i\n", + ev->data.control.channel, + ev->data.control.param, + ev->data.control.value); + break; - case SND_SEQ_EVENT_PGMCHANGE: - printf("; ch=%d, program=%i\n", - ev->data.control.channel, - ev->data.control.value); - break; + case SND_SEQ_EVENT_PGMCHANGE: + printf("; ch=%d, program=%i\n", + ev->data.control.channel, + ev->data.control.value); + break; - case SND_SEQ_EVENT_CHANPRESS: - case SND_SEQ_EVENT_PITCHBEND: - printf("; ch=%d, value=%i\n", - ev->data.control.channel, - ev->data.control.value); - break; + case SND_SEQ_EVENT_CHANPRESS: + case SND_SEQ_EVENT_PITCHBEND: + printf("; ch=%d, value=%i\n", + ev->data.control.channel, + ev->data.control.value); + break; - case SND_SEQ_EVENT_SYSEX: - { - unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t); - int c; - - printf("; len=%d [", ev->data.ext.len); - - for (c = 0; c < ev->data.ext.len; c++) { - printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : ""); - } - printf("]\n"); - } - break; + case SND_SEQ_EVENT_SYSEX: + { + unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t); + unsigned int c; - case SND_SEQ_EVENT_QFRAME: - printf("; frame=0x%02x\n", ev->data.control.value); - break; + printf("; len=%d [", ev->data.ext.len); - case SND_SEQ_EVENT_CLOCK: - case SND_SEQ_EVENT_START: - case SND_SEQ_EVENT_CONTINUE: - case SND_SEQ_EVENT_STOP: - printf("; queue = %i\n", ev->data.queue.queue); - break; + for (c = 0; c < ev->data.ext.len; c++) { + printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : ""); + } + printf("]\n"); + } + break; + + case SND_SEQ_EVENT_QFRAME: + printf("; frame=0x%02x\n", ev->data.control.value); + break; + + case SND_SEQ_EVENT_CLOCK: + case SND_SEQ_EVENT_START: + case SND_SEQ_EVENT_CONTINUE: + case SND_SEQ_EVENT_STOP: + printf("; queue = %i\n", ev->data.queue.queue); + break; - case SND_SEQ_EVENT_SENSING: - printf("\n"); - break; + case SND_SEQ_EVENT_SENSING: + printf("\n"); + break; - case SND_SEQ_EVENT_ECHO: - { - int i; + case SND_SEQ_EVENT_ECHO: + { + int i; - printf("; "); - for (i = 0; i < 8; i++) { - printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n"); - } - } - break; + printf("; "); + for (i = 0; i < 8; i++) { + printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n"); + } + } + break; - case SND_SEQ_EVENT_CLIENT_START: - case SND_SEQ_EVENT_CLIENT_EXIT: - case SND_SEQ_EVENT_CLIENT_CHANGE: - printf("; client=%i\n", ev->data.addr.client); - break; + case SND_SEQ_EVENT_CLIENT_START: + case SND_SEQ_EVENT_CLIENT_EXIT: + case SND_SEQ_EVENT_CLIENT_CHANGE: + printf("; client=%i\n", ev->data.addr.client); + break; - case SND_SEQ_EVENT_PORT_START: - case SND_SEQ_EVENT_PORT_EXIT: - case SND_SEQ_EVENT_PORT_CHANGE: - case SND_SEQ_EVENT_PORT_SUBSCRIBED: - case SND_SEQ_EVENT_PORT_USED: - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: - case SND_SEQ_EVENT_PORT_UNUSED: - printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port); - break; + case SND_SEQ_EVENT_PORT_START: + case SND_SEQ_EVENT_PORT_EXIT: + case SND_SEQ_EVENT_PORT_CHANGE: + printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port); + break; + + case SND_SEQ_EVENT_PORT_SUBSCRIBED: + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + printf("; %i:%i -> %i:%i\n", + ev->data.connect.sender.client, ev->data.connect.sender.port, + ev->data.connect.dest.client, ev->data.connect.dest.port); + break; - default: - printf("; not implemented\n"); + default: + printf("; not implemented\n"); } switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) { - case SND_SEQ_EVENT_LENGTH_FIXED: - return sizeof(snd_seq_event_t); + case SND_SEQ_EVENT_LENGTH_FIXED: + return sizeof(snd_seq_event_t); - case SND_SEQ_EVENT_LENGTH_VARIABLE: - return sizeof(snd_seq_event_t) + ev->data.ext.len; + case SND_SEQ_EVENT_LENGTH_VARIABLE: + return sizeof(snd_seq_event_t) + ev->data.ext.len; } return 0; @@ -411,11 +254,12 @@ void event_decoder_start_timer(snd_seq_t *handle, int queue, int client, int por void event_decoder(snd_seq_t *handle, int argc, char *argv[]) { snd_seq_event_t *ev; - snd_seq_port_info_t port; - snd_seq_port_subscribe_t sub; - fd_set in; - int client, queue, max, err, v1, v2; + snd_seq_port_info_t *pinfo; + snd_seq_port_subscribe_t *sub; + snd_seq_addr_t addr; + int client, port, queue, max, err, v1, v2; char *ptr; + struct pollfd *pfds; if ((client = snd_seq_client_id(handle))<0) { fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client)); @@ -427,33 +271,37 @@ void event_decoder(snd_seq_t *handle, int argc, char *argv[]) return; } printf("Queue ID = %i\n", queue); - if ((err = snd_seq_block_mode(handle, 0))<0) + if ((err = snd_seq_nonblock(handle, 1))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); - bzero(&port, sizeof(port)); - strcpy(port.name, "Input"); - port.capability = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ; - port.capability |= SND_SEQ_PORT_CAP_SUBS_WRITE; - if ((err = snd_seq_create_port(handle, &port)) < 0) { + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_name(pinfo, "Input"); + snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE); + if ((err = snd_seq_create_port(handle, pinfo)) < 0) { fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err)); return; } - event_decoder_start_timer(handle, queue, client, port.port); + port = snd_seq_port_info_get_port(pinfo); + event_decoder_start_timer(handle, queue, client, port); - bzero(&sub, sizeof(sub)); - sub.sender.client = SND_SEQ_CLIENT_SYSTEM; - sub.sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; - sub.dest.client = client; - sub.dest.port = port.port; - sub.queue = queue; - sub.exclusive = 0; - sub.convert_time = 1; - sub.realtime = 1; - if ((err = snd_seq_subscribe_port(handle, &sub))<0) { + snd_seq_port_subscribe_alloca(&sub); + addr.client = SND_SEQ_CLIENT_SYSTEM; + addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; + snd_seq_port_subscribe_set_sender(sub, &addr); + addr.client = client; + addr.port = port; + snd_seq_port_subscribe_set_dest(sub, &addr); + snd_seq_port_subscribe_set_queue(sub, queue); + snd_seq_port_subscribe_set_time_update(sub, 1); + snd_seq_port_subscribe_set_time_real(sub, 1); + if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err)); return; } - sub.sender.port = SND_SEQ_PORT_SYSTEM_TIMER; - if ((err = snd_seq_subscribe_port(handle, &sub))<0) { + + addr.client = SND_SEQ_CLIENT_SYSTEM; + addr.port = SND_SEQ_PORT_SYSTEM_TIMER; + snd_seq_port_subscribe_set_sender(sub, &addr); + if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err)); return; } @@ -462,27 +310,29 @@ void event_decoder(snd_seq_t *handle, int argc, char *argv[]) ptr = argv[max]; if (!ptr) continue; - sub.realtime = 0; + snd_seq_port_subscribe_set_time_real(sub, 0); if (tolower(*ptr) == 'r') { - sub.realtime = 1; + snd_seq_port_subscribe_set_time_real(sub, 1); ptr++; } if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) { fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; } - sub.sender.client = v1; - sub.sender.port = v2; - if ((err = snd_seq_subscribe_port(handle, &sub))<0) { + addr.client = v1; + addr.port = v2; + snd_seq_port_subscribe_set_sender(sub, &addr); + if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err)); return; } } + max = snd_seq_poll_descriptors_count(handle, POLLIN); + pfds = alloca(sizeof(*pfds) * max); while (1) { - FD_ZERO(&in); - FD_SET(max = snd_seq_poll_descriptor(handle), &in); - if (select(max + 1, &in, NULL, NULL, NULL) < 0) + snd_seq_poll_descriptors(handle, pfds, max, POLLIN); + if (poll(pfds, max, -1) < 0) break; do { if ((err = snd_seq_event_input(handle, &ev))<0) diff --git a/test/seq-sender.c b/test/seq-sender.c index 546f0a91..b18d36c3 100644 --- a/test/seq-sender.c +++ b/test/seq-sender.c @@ -1,57 +1,65 @@ -#ifdef USE_PCM +#ifdef USE_PCM // XXX not yet /* * PCM timer layer */ int pcard = 0; int pdevice = 0; -int pfragment_size = 4096; +int period_size = 1024; -void set_format(snd_pcm_t *phandle) +void set_hwparams(snd_pcm_t *phandle) { int err; - snd_pcm_format_t format; + snd_pcm_hw_params_t *params; - bzero(&format, sizeof(format)); - format.sfmt = SND_PCM_FORMAT_S16_LE; - format.channels = 2; - format.rate = 44100; - if ((err = snd_pcm_playback_format(phandle, &format)) < 0) { - fprintf(stderr, "Playback format error: %s\n", snd_strerror(err)); + err = snd_output_stdio_attach(&log, stderr, 0); + if (err < 0) { + fprintf(stderr, "cannot attach output stdio\n"); exit(0); } -} -void set_fragment(snd_pcm_t *phandle) -{ - int err; - snd_pcm_playback_params_t pparams; - - bzero(&pparams, sizeof(pparams)); - pparams.fragment_size = pfragment_size; - pparams.fragments_max = -1; /* maximum */ - pparams.fragments_room = 1; - if ((err = snd_pcm_playback_params(phandle, &pparams)) < 0) { - fprintf(stderr, "Fragment setup error: %s\n", snd_strerror(err)); + snd_pcm_hw_params_alloca(¶ms); + err = snd_pcm_hw_params_any(phandle, params); + if (err < 0) { + fprintf(stderr, "Broken configuration for this PCM: no configurations available\n"); exit(0); } -} - -void show_playback_status(snd_pcm_t *phandle) -{ - int err; - snd_pcm_playback_status_t pstatus; - if ((err = snd_pcm_playback_status(phandle, &pstatus)) < 0) { - fprintf(stderr, "Playback status error: %s\n", snd_strerror(err)); + err = snd_pcm_hw_params_set_access(phandle, params, + SND_PCM_ACCESS_RW_INTERLEAVED); + if (err < 0) { + fprintf(stderr, "Access type not available\n"); + exit(0); + } + err = snd_pcm_hw_params_set_format(phandle, params, SND_PCM_FORMAT_S16_LE); + if (err < 0) { + fprintf(stderr, "cannot set format\n"); exit(0); } - printf("Playback status\n"); - printf(" Real rate : %u\n", pstatus.rate); - printf(" Fragments : %i\n", pstatus.fragments); - printf(" Fragment size : %i\n", pstatus.fragment_size); + err = snd_pcm_hw_params_set_channels(phandle, params, 2); + if (err < 0) { + fprintf(stderr, "cannot set channels 2\n"); + exit(0); + } + err = snd_pcm_hw_params_set_rate_near(phandle, params, 44100, 0); + if (err < 0) { + fprintf(stderr, "cannot set rate\n"); + exit(0); + } + err = snd_pcm_hw_params_set_period_size_near(phandle, params, period_size); + if (err < 0) { + fprintf(stderr, "cannot set period size\n"); + exit(0); + } + err = snd_pcm_hw_params(phandle, params); + if (err < 0) { + fprintf(stderr, "Unable to install hw params:\n"); + exit(0); + } + snd_pcm_hw_params_dump(params, log); } + #endif /* * Simple event sender @@ -89,23 +97,15 @@ void event_sender_start_timer(snd_seq_t *handle, int client, int queue, snd_pcm_ void event_sender_filter(snd_seq_t *handle) { int err; - snd_seq_client_info_t info; - if ((err = snd_seq_get_client_info(handle, &info)) < 0) { - fprintf(stderr, "Unable to get client info: %s\n", snd_strerror(err)); - return; - } - info.filter = SND_SEQ_FILTER_USE_EVENT; - memset(&info.event_filter, 0, sizeof(info.event_filter)); - snd_seq_set_bit(SND_SEQ_EVENT_ECHO, info.event_filter); - if ((err = snd_seq_set_client_info(handle, &info)) < 0) { + if ((err = snd_seq_set_client_event_filter(handle, SND_SEQ_EVENT_ECHO)) < 0) { fprintf(stderr, "Unable to set client info: %s\n", snd_strerror(err)); return; } } void send_event(snd_seq_t *handle, int queue, int client, int port, - snd_seq_port_subscribe_t *sub, int *time) + snd_seq_addr_t *dest, int *time) { int err; snd_seq_event_t ev; @@ -119,8 +119,7 @@ void send_event(snd_seq_t *handle, int queue, int client, int port, ev.type = SND_SEQ_EVENT_ECHO; if ((err = snd_seq_event_output(handle, &ev))<0) fprintf(stderr, "Event output error: %s\n", snd_strerror(err)); - ev.dest.client = sub->dest.client; - ev.dest.port = sub->dest.port; + ev.dest = *dest; ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = 0; ev.data.control.value = 16; @@ -141,10 +140,11 @@ void send_event(snd_seq_t *handle, int queue, int client, int port, void event_sender(snd_seq_t *handle, int argc, char *argv[]) { snd_seq_event_t *ev; - snd_seq_port_info_t port; - snd_seq_port_subscribe_t sub; - fd_set out, in; - int client, queue, max, err, v1, v2, time = 0, pcm_flag = 0; + snd_seq_port_info_t *pinfo; + snd_seq_port_subscribe_t *sub; + snd_seq_addr_t addr; + struct pollfd *pfds; + int client, port, queue, max, err, v1, v2, time = 0, pcm_flag = 0; char *ptr; snd_pcm_t *phandle = NULL; @@ -164,20 +164,22 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) } printf("Queue ID = %i\n", queue); event_sender_filter(handle); - if ((err = snd_seq_block_mode(handle, 0))<0) + if ((err = snd_seq_nonblock(handle, 1))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); - bzero(&port, sizeof(port)); - port.capability = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ; - strcpy(port.name, "Output"); - if ((err = snd_seq_create_port(handle, &port)) < 0) { + + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ); + snd_seq_port_info_set_name(pinfo, "Output"); + if ((err = snd_seq_create_port(handle, pinfo)) < 0) { fprintf(stderr, "Cannot create output port: %s\n", snd_strerror(err)); return; } + port = snd_seq_port_info_get_port(pinfo); - bzero(&sub, sizeof(sub)); - sub.sender.client = client; - sub.sender.port = port.port; - sub.exclusive = 0; + snd_seq_port_subscribe_alloca(&sub); + addr.client = client; + addr.port = port; + snd_seq_port_subscribe_set_sender(sub, &addr); for (max = 0; max < argc; max++) { ptr = argv[max]; @@ -191,26 +193,25 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; } - sub.dest.client = v1; - sub.dest.port = v2; - if ((err = snd_seq_subscribe_port(handle, &sub))<0) { + addr.client = v1; + addr.port = v2; + snd_seq_port_subscribe_set_dest(sub, &addr); + if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err)); return; } } - printf("Destination client = %i, port = %i\n", sub.dest.client, sub.dest.port); + printf("Destination client = %i, port = %i\n", addr.client, addr.port); #ifdef USE_PCM if (pcm_flag) { - if ((err = snd_pcm_open(&phandle, pcard, pdevice, SND_PCM_OPEN_PLAYBACK)) < 0) { + if ((err = snd_pcm_open(&phandle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "Playback open error: %s\n", snd_strerror(err)); exit(0); } - set_format(phandle); - set_fragment(phandle); - show_playback_status(phandle); - pbuf = calloc(1, pfragment_size); + set_hwparams(phandle); + pbuf = calloc(1, period_size * 4); if (pbuf == NULL) { fprintf(stderr, "No enough memory...\n"); exit(0); @@ -220,43 +221,46 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) event_sender_start_timer(handle, client, queue, phandle); /* send the first event */ - send_event(handle, queue, client, port.port, &sub, &time); - + send_event(handle, queue, client, port, &addr, &time); +#ifdef USE_PCM + if (phandle) + max += snd_pcm_poll_descriptors_count(phandle); +#endif + pfds = alloca(sizeof(*pfds) * max); while (1) { - FD_ZERO(&out); - FD_ZERO(&in); - max = snd_seq_poll_descriptor(handle); - FD_SET(snd_seq_poll_descriptor(handle), &in); - if (snd_seq_event_output_pending(handle)) { - FD_SET(snd_seq_poll_descriptor(handle), &out); - } + int nseqs = snd_seq_poll_descriptors_count(handle, POLLOUT|POLLIN); + if (snd_seq_event_output_pending(handle)) + snd_seq_poll_descriptors(handle, pfds, nseqs, POLLOUT|POLLIN); + else + snd_seq_poll_descriptors(handle, pfds, nseqs, POLLIN); + max = nseqs; #ifdef USE_PCM if (phandle) { - if (snd_pcm_poll_descriptor(phandle) > max) - max = snd_pcm_poll_descriptor(phandle); - FD_SET(snd_pcm_poll_descriptor(phandle), &out); + int pmax = snd_pcm_poll_descriptors_count(phandle); + snd_seq_poll_descriptors(phandle, pfds + max, pmax); + max += pmax; } #endif - if (select(max + 1, &in, &out, NULL, NULL) < 0) + if (poll(pfds, max, -1) < 0) break; #ifdef USE_PCM - if (phandle && FD_ISSET(snd_pcm_poll_descriptor(phandle), &out)) { - if (snd_pcm_writei(phandle, pbuf, pfragment_size) != pfragment_size) { + if (phandle && (pfds[nseqs].revents & POLLOUT)) { + if (snd_pcm_writei(phandle, pbuf, period_size) != period_size) { fprintf(stderr, "Playback write error!!\n"); exit(0); } } #endif - if (FD_ISSET(snd_seq_poll_descriptor(handle), &out)) + if (pfds[0].revents & POLLOUT) snd_seq_drain_output(handle); - if (FD_ISSET(snd_seq_poll_descriptor(handle), &in)) { + if (pfds[0].revents & POLLIN) { do { if ((err = snd_seq_event_input(handle, &ev))<0) break; if (!ev) continue; if (ev->type == SND_SEQ_EVENT_ECHO) - send_event(handle, queue, client, port.port, &sub, &time); + send_event(handle, queue, client, port, &addr, &time); decode_event(ev); snd_seq_free_event(ev); } while (err > 0); diff --git a/test/seq.c b/test/seq.c index 9c2faa3c..f18a6fa4 100644 --- a/test/seq.c +++ b/test/seq.c @@ -16,20 +16,19 @@ #define HELPID_VERBOSE 1002 #define HELPID_VERSION 1003 -snd_seq_system_info_t sysinfo; +int max_clients; +int max_ports; +int max_queues; int debug = 0; int verbose = 0; void set_name(snd_seq_t *handle) { int err; - snd_seq_client_info_t info; + char name[64]; - bzero(&info, sizeof(info)); - info.client = snd_seq_client_id(handle); - info.type = USER_CLIENT; - snprintf(info.name, sizeof(info.name), "SeqUtil - %i", getpid()); - if ((err = snd_seq_set_client_info(handle, &info)) < 0) { + sprintf(name, "SeqUtil - %i", getpid()); + if ((err = snd_seq_set_client_name(handle, name)) < 0) { fprintf(stderr, "Set client info error: %s\n", snd_strerror(err)); exit(0); } @@ -38,78 +37,88 @@ void set_name(snd_seq_t *handle) void system_info(snd_seq_t *handle) { int err; + snd_seq_system_info_t *sysinfo; - if ((err = snd_seq_system_info(handle, &sysinfo))<0) { + snd_seq_system_info_alloca(&sysinfo); + if ((err = snd_seq_system_info(handle, sysinfo))<0) { fprintf(stderr, "System info error: %s\n", snd_strerror(err)); exit(0); } + max_clients = snd_seq_system_info_get_clients(sysinfo); + max_ports = snd_seq_system_info_get_ports(sysinfo); + max_queues = snd_seq_system_info_get_ports(sysinfo); } void show_system_info(snd_seq_t *handle) { printf("System info\n"); - printf(" Max queues : %i\n", sysinfo.queues); - printf(" Max clients : %i\n", sysinfo.clients); - printf(" Max ports : %i\n", sysinfo.ports); + printf(" Max queues : %i\n", max_queues); + printf(" Max clients : %i\n", max_clients); + printf(" Max ports : %i\n", max_ports); } void show_queue_status(snd_seq_t *handle, int queue) { int err, idx, min, max; - snd_seq_queue_status_t status; - + snd_seq_queue_status_t *status; + + snd_seq_queue_status_alloca(&status); min = queue < 0 ? 0 : queue; - max = queue < 0 ? sysinfo.queues : queue + 1; + max = queue < 0 ? max_queues : queue + 1; for (idx = min; idx < max; idx++) { - if ((err = snd_seq_get_queue_status(handle, idx, &status))<0) { + if ((err = snd_seq_get_queue_status(handle, idx, status))<0) { if (err == -ENOENT) continue; fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err)); exit(0); } - printf("Queue %i info\n", status.queue); - printf(" Tick : %u\n", status.tick); - printf(" Realtime : %li.%li\n", status.time.tv_sec, status.time.tv_nsec); - printf(" Flags : 0x%x\n", status.flags); + printf("Queue %i info\n", snd_seq_queue_status_get_queue(status)); + printf(" Tick : %u\n", snd_seq_queue_status_get_tick_time(status)); + printf(" Realtime : %i.%i\n", + snd_seq_queue_status_get_real_time(status)->tv_sec, + snd_seq_queue_status_get_real_time(status)->tv_nsec); + printf(" Flags : 0x%x\n", snd_seq_queue_status_get_status(status)); } } void show_port_info(snd_seq_t *handle, int client, int port) { int err, idx, min, max; - snd_seq_port_info_t info; + snd_seq_port_info_t *info; + snd_seq_port_info_alloca(&info); min = port < 0 ? 0 : port; - max = port < 0 ? sysinfo.ports : port + 1; + max = port < 0 ? max_ports : port + 1; for (idx = min; idx < max; idx++) { - if ((err = snd_seq_get_any_port_info(handle, client, idx, &info))<0) { + if ((err = snd_seq_get_any_port_info(handle, client, idx, info))<0) { if (err == -ENOENT) continue; fprintf(stderr, "Port %i/%i info error: %s\n", client, idx, snd_strerror(err)); exit(0); } printf(" Port %i info\n", idx); - printf(" Client : %i\n", info.client); - printf(" Port : %i\n", info.port); - printf(" Name : %s\n", info.name); - printf(" Capability : 0x%x\n", info.capability); - printf(" Type : 0x%x\n", info.type); - printf(" Midi channels : %i\n", info.midi_channels); - printf(" Synth voices : %i\n", info.synth_voices); - printf(" Output subs : %i\n", info.write_use); - printf(" Input subs : %i\n", info.read_use); + printf(" Client : %i\n", snd_seq_port_info_get_client(info)); + printf(" Port : %i\n", snd_seq_port_info_get_port(info)); + printf(" Name : %s\n", snd_seq_port_info_get_name(info)); + printf(" Capability : 0x%x\n", snd_seq_port_info_get_capability(info)); + printf(" Type : 0x%x\n", snd_seq_port_info_get_type(info)); + //printf(" Midi channels : %i\n", info.midi_channels); + //printf(" Synth voices : %i\n", info.synth_voices); + printf(" Output subs : %i\n", snd_seq_port_info_get_write_use(info)); + printf(" Input subs : %i\n", snd_seq_port_info_get_read_use(info)); } } void show_client_info(snd_seq_t *handle, int client) { int err, idx, min, max; - snd_seq_client_info_t info; + snd_seq_client_info_t *info; + snd_seq_client_info_alloca(&info); min = client < 0 ? 0 : client; - max = client < 0 ? sysinfo.clients : client + 1; + max = client < 0 ? max_clients : client + 1; for (idx = min; idx < max; idx++) { - if ((err = snd_seq_get_any_client_info(handle, idx, &info))<0) { + if ((err = snd_seq_get_any_client_info(handle, idx, info))<0) { if (err == -ENOENT) continue; fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err)); @@ -117,9 +126,9 @@ void show_client_info(snd_seq_t *handle, int client) } printf("Client %i info\n", idx); if (verbose) - printf(" Client : %i\n", info.client); - printf(" Type : %s\n", info.type == KERNEL_CLIENT ? "kernel" : "user"); - printf(" Name : %s\n", info.name); + printf(" Client : %i\n", snd_seq_client_info_get_client(info)); + printf(" Type : %s\n", snd_seq_client_info_get_type(info) == SND_SEQ_KERNEL_CLIENT ? "kernel" : "user"); + printf(" Name : %s\n", snd_seq_client_info_get_name(info)); } } @@ -190,7 +199,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "seq: Specify command...\n"); return 0; } - if ((err = snd_seq_open(&handle, SND_SEQ_OPEN))<0) { + if ((err = snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0))<0) { fprintf(stderr, "Open error: %s\n", snd_strerror(err)); exit(0); } -- 2.47.1