From: Jaroslav Kysela Date: Wed, 4 Jul 2001 13:54:13 +0000 (+0000) Subject: Major change to sequencer API. X-Git-Tag: v1.0.3~757 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=88e5e451516e7496a86a96ea8a38e63e522b6b22;p=alsa-lib.git 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. --- 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); }