#pragma once #include #include #if defined(SND_LIB_VERSION) #if __has_include() && SND_LIB_VERSION >= ((1 << 16) | (2 << 8) | 6) #define LIBREMIDI_ALSA_HAS_RAMWIDI 1 #define LIBREMIDI_ALSA_HAS_RAWMIDI_TREAD 1 #endif #if __has_include() && SND_LIB_VERSION >= ((1 << 16) | (2 << 8) | 10) #define LIBREMIDI_ALSA_HAS_UMP 1 #endif #endif namespace libremidi { struct libasound { // Useful one-liner: // nm -A * | grep ' snd_' | grep -v '@' | cut -f 2 -d 'U' | sort | uniq | sed 's/ snd_//' | sed 's/_/, /' | awk ' { print "LIBREMIDI_SYMBOL_DEF(snd_"$1 " " $2 ");" }' explicit libasound() : library{"libasound.so.2"} { if (!library) { available = false; return; } strerror = library.symbol("snd_strerror"); if (!strerror) available = false; } static const libasound& instance() { static const libasound self; return self; } dylib_loader library; decltype(&::snd_strerror) strerror{}; bool available{true}; struct card_t { explicit card_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_card, get_name) LIBREMIDI_SYMBOL_INIT(snd_card, next) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_card, get_name) LIBREMIDI_SYMBOL_DEF(snd_card, next) } card{library}; struct ctl_t { explicit ctl_t(const dylib_loader& library) : rawmidi{library} #if LIBREMIDI_ALSA_HAS_UMP , ump{library} #endif { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_ctl, close) LIBREMIDI_SYMBOL_INIT(snd_ctl, open) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_ctl, close) LIBREMIDI_SYMBOL_DEF(snd_ctl, open) struct rawmidi_t { explicit rawmidi_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_ctl_rawmidi, info) LIBREMIDI_SYMBOL_INIT(snd_ctl_rawmidi, next_device) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_ctl_rawmidi, info) LIBREMIDI_SYMBOL_DEF(snd_ctl_rawmidi, next_device) } rawmidi; #if LIBREMIDI_ALSA_HAS_UMP struct ump_t { explicit ump_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_ctl_ump, block_info) LIBREMIDI_SYMBOL_INIT(snd_ctl_ump, endpoint_info) LIBREMIDI_SYMBOL_INIT(snd_ctl_ump, next_device) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_ctl_ump, block_info) LIBREMIDI_SYMBOL_DEF(snd_ctl_ump, endpoint_info) LIBREMIDI_SYMBOL_DEF(snd_ctl_ump, next_device) } ump; #endif } ctl{library}; struct midi_t { explicit midi_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_midi, event_decode) LIBREMIDI_SYMBOL_INIT(snd_midi, event_encode) LIBREMIDI_SYMBOL_INIT(snd_midi, event_free) LIBREMIDI_SYMBOL_INIT(snd_midi, event_init) LIBREMIDI_SYMBOL_INIT(snd_midi, event_new) LIBREMIDI_SYMBOL_INIT(snd_midi, event_no_status) LIBREMIDI_SYMBOL_INIT(snd_midi, event_resize_buffer) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_midi, event_decode) LIBREMIDI_SYMBOL_DEF(snd_midi, event_encode) LIBREMIDI_SYMBOL_DEF(snd_midi, event_free) LIBREMIDI_SYMBOL_DEF(snd_midi, event_init) LIBREMIDI_SYMBOL_DEF(snd_midi, event_new) LIBREMIDI_SYMBOL_DEF(snd_midi, event_no_status) LIBREMIDI_SYMBOL_DEF(snd_midi, event_resize_buffer) } midi{library}; #if LIBREMIDI_ALSA_HAS_RAMWIDI struct rawmidi_t { explicit rawmidi_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_rawmidi, close) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_get_name) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_get_subdevice_name) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_get_subdevices_count) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_set_device) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_set_stream) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_set_subdevice) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, info_sizeof) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, open) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_current) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_get_buffer_size) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_set_clock_type) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_set_no_active_sensing) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_set_read_mode) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, params_sizeof) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, poll_descriptors) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, poll_descriptors_count) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, poll_descriptors_revents) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, read) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, status) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, status_get_avail) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, status_sizeof) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, tread) LIBREMIDI_SYMBOL_INIT(snd_rawmidi, write) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_rawmidi, close) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_get_name) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_get_subdevice_name) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_get_subdevices_count) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_set_device) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_set_stream) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_set_subdevice) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, info_sizeof) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, open) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_current) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_get_buffer_size) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_set_clock_type) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_set_no_active_sensing) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_set_read_mode) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, params_sizeof) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, poll_descriptors) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, poll_descriptors_count) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, poll_descriptors_revents) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, read) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, status) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, status_get_avail) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, status_sizeof) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, tread) LIBREMIDI_SYMBOL_DEF(snd_rawmidi, write) } rawmidi{library}; #endif struct seq_t { explicit seq_t(const dylib_loader& library) #if LIBREMIDI_ALSA_HAS_UMP : ump{library} #endif { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_seq, alloc_queue) LIBREMIDI_SYMBOL_INIT(snd_seq, client_id) LIBREMIDI_SYMBOL_INIT(snd_seq, client_info_get_client) LIBREMIDI_SYMBOL_INIT(snd_seq, client_info_get_name) LIBREMIDI_SYMBOL_INIT(snd_seq, client_info_set_client) LIBREMIDI_SYMBOL_INIT(snd_seq, client_info_sizeof) LIBREMIDI_SYMBOL_INIT(snd_seq, close) LIBREMIDI_SYMBOL_INIT(snd_seq, connect_from) LIBREMIDI_SYMBOL_INIT(snd_seq, control_queue) LIBREMIDI_SYMBOL_INIT(snd_seq, create_port) LIBREMIDI_SYMBOL_INIT(snd_seq, delete_port) LIBREMIDI_SYMBOL_INIT(snd_seq, drain_output) LIBREMIDI_SYMBOL_INIT(snd_seq, event_input) LIBREMIDI_SYMBOL_INIT(snd_seq, event_input_pending) LIBREMIDI_SYMBOL_INIT(snd_seq, event_output) LIBREMIDI_SYMBOL_INIT(snd_seq, free_event) LIBREMIDI_SYMBOL_INIT(snd_seq, free_queue) LIBREMIDI_SYMBOL_INIT(snd_seq, get_any_client_info) LIBREMIDI_SYMBOL_INIT(snd_seq, get_any_port_info) LIBREMIDI_SYMBOL_INIT(snd_seq, get_port_info) LIBREMIDI_SYMBOL_INIT(snd_seq, open) LIBREMIDI_SYMBOL_INIT(snd_seq, poll_descriptors) LIBREMIDI_SYMBOL_INIT(snd_seq, poll_descriptors_count) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_get_addr) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_get_capability) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_get_name) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_get_port) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_get_type) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_capability) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_client) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_midi_channels) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_name) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_port) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_timestamping) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_timestamp_queue) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_timestamp_real) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_set_type) LIBREMIDI_SYMBOL_INIT(snd_seq, port_info_sizeof) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_free) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_malloc) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_set_dest) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_set_sender) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_set_time_real) LIBREMIDI_SYMBOL_INIT(snd_seq, port_subscribe_set_time_update) LIBREMIDI_SYMBOL_INIT(snd_seq, query_next_client) LIBREMIDI_SYMBOL_INIT(snd_seq, query_next_port) LIBREMIDI_SYMBOL_INIT(snd_seq, queue_tempo_set_ppq) LIBREMIDI_SYMBOL_INIT(snd_seq, queue_tempo_set_tempo) LIBREMIDI_SYMBOL_INIT(snd_seq, queue_tempo_sizeof) LIBREMIDI_SYMBOL_INIT(snd_seq, set_client_name) LIBREMIDI_SYMBOL_INIT(snd_seq, set_port_info) LIBREMIDI_SYMBOL_INIT(snd_seq, set_queue_tempo) LIBREMIDI_SYMBOL_INIT(snd_seq, subscribe_port) LIBREMIDI_SYMBOL_INIT(snd_seq, unsubscribe_port) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_seq, alloc_queue) LIBREMIDI_SYMBOL_DEF(snd_seq, client_id) LIBREMIDI_SYMBOL_DEF(snd_seq, client_info_get_client) LIBREMIDI_SYMBOL_DEF(snd_seq, client_info_get_name) LIBREMIDI_SYMBOL_DEF(snd_seq, client_info_set_client) LIBREMIDI_SYMBOL_DEF(snd_seq, client_info_sizeof) LIBREMIDI_SYMBOL_DEF(snd_seq, close) LIBREMIDI_SYMBOL_DEF(snd_seq, connect_from) LIBREMIDI_SYMBOL_DEF(snd_seq, control_queue) LIBREMIDI_SYMBOL_DEF(snd_seq, create_port) LIBREMIDI_SYMBOL_DEF(snd_seq, delete_port) LIBREMIDI_SYMBOL_DEF(snd_seq, drain_output) LIBREMIDI_SYMBOL_DEF(snd_seq, event_input) LIBREMIDI_SYMBOL_DEF(snd_seq, event_input_pending) LIBREMIDI_SYMBOL_DEF(snd_seq, event_output) LIBREMIDI_SYMBOL_DEF(snd_seq, free_event) LIBREMIDI_SYMBOL_DEF(snd_seq, free_queue) LIBREMIDI_SYMBOL_DEF(snd_seq, get_any_client_info) LIBREMIDI_SYMBOL_DEF(snd_seq, get_any_port_info) LIBREMIDI_SYMBOL_DEF(snd_seq, get_port_info) LIBREMIDI_SYMBOL_DEF(snd_seq, open) LIBREMIDI_SYMBOL_DEF(snd_seq, poll_descriptors) LIBREMIDI_SYMBOL_DEF(snd_seq, poll_descriptors_count) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_get_addr) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_get_capability) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_get_name) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_get_port) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_get_type) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_capability) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_client) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_midi_channels) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_name) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_port) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_timestamping) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_timestamp_queue) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_timestamp_real) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_set_type) LIBREMIDI_SYMBOL_DEF(snd_seq, port_info_sizeof) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_free) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_malloc) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_set_dest) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_set_sender) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_set_time_real) LIBREMIDI_SYMBOL_DEF(snd_seq, port_subscribe_set_time_update) LIBREMIDI_SYMBOL_DEF(snd_seq, query_next_client) LIBREMIDI_SYMBOL_DEF(snd_seq, query_next_port) LIBREMIDI_SYMBOL_DEF(snd_seq, queue_tempo_set_ppq) LIBREMIDI_SYMBOL_DEF(snd_seq, queue_tempo_set_tempo) LIBREMIDI_SYMBOL_DEF(snd_seq, queue_tempo_sizeof) LIBREMIDI_SYMBOL_DEF(snd_seq, set_client_name) LIBREMIDI_SYMBOL_DEF(snd_seq, set_port_info) LIBREMIDI_SYMBOL_DEF(snd_seq, set_queue_tempo) LIBREMIDI_SYMBOL_DEF(snd_seq, subscribe_port) LIBREMIDI_SYMBOL_DEF(snd_seq, unsubscribe_port) #if LIBREMIDI_ALSA_HAS_UMP struct ump_t { explicit ump_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_seq, set_client_midi_version) LIBREMIDI_SYMBOL_INIT(snd_seq_ump, event_input) LIBREMIDI_SYMBOL_INIT(snd_seq_ump, event_output) LIBREMIDI_SYMBOL_INIT(snd_seq_ump, event_output_direct) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_seq, set_client_midi_version) LIBREMIDI_SYMBOL_DEF(snd_seq_ump, event_input) LIBREMIDI_SYMBOL_DEF(snd_seq_ump, event_output) LIBREMIDI_SYMBOL_DEF(snd_seq_ump, event_output_direct) } ump; #endif } seq{library}; #if LIBREMIDI_ALSA_HAS_UMP struct ump_t { explicit ump_t(const dylib_loader& library) { if (!library) { available = false; return; } LIBREMIDI_SYMBOL_INIT(snd_ump, block_info_get_name) LIBREMIDI_SYMBOL_INIT(snd_ump, block_info_sizeof) LIBREMIDI_SYMBOL_INIT(snd_ump, close) LIBREMIDI_SYMBOL_INIT(snd_ump, endpoint_info_get_name) LIBREMIDI_SYMBOL_INIT(snd_ump, endpoint_info_sizeof) LIBREMIDI_SYMBOL_INIT(snd_ump, open) LIBREMIDI_SYMBOL_INIT(snd_ump, poll_descriptors) LIBREMIDI_SYMBOL_INIT(snd_ump, poll_descriptors_count) LIBREMIDI_SYMBOL_INIT(snd_ump, poll_descriptors_revents) LIBREMIDI_SYMBOL_INIT(snd_ump, rawmidi) LIBREMIDI_SYMBOL_INIT(snd_ump, rawmidi_params) LIBREMIDI_SYMBOL_INIT(snd_ump, rawmidi_params_current) LIBREMIDI_SYMBOL_INIT(snd_ump, read) LIBREMIDI_SYMBOL_INIT(snd_ump, tread) LIBREMIDI_SYMBOL_INIT(snd_ump, write) } bool available{true}; LIBREMIDI_SYMBOL_DEF(snd_ump, block_info_get_name) LIBREMIDI_SYMBOL_DEF(snd_ump, block_info_sizeof) LIBREMIDI_SYMBOL_DEF(snd_ump, close) LIBREMIDI_SYMBOL_DEF(snd_ump, endpoint_info_get_name) LIBREMIDI_SYMBOL_DEF(snd_ump, endpoint_info_sizeof) LIBREMIDI_SYMBOL_DEF(snd_ump, open) LIBREMIDI_SYMBOL_DEF(snd_ump, poll_descriptors) LIBREMIDI_SYMBOL_DEF(snd_ump, poll_descriptors_count) LIBREMIDI_SYMBOL_DEF(snd_ump, poll_descriptors_revents) LIBREMIDI_SYMBOL_DEF(snd_ump, rawmidi) LIBREMIDI_SYMBOL_DEF(snd_ump, rawmidi_params) LIBREMIDI_SYMBOL_DEF(snd_ump, rawmidi_params_current) LIBREMIDI_SYMBOL_DEF(snd_ump, read) LIBREMIDI_SYMBOL_DEF(snd_ump, tread) LIBREMIDI_SYMBOL_DEF(snd_ump, write) } ump{library}; #endif }; #undef snd_dylib_alloca #define snd_dylib_alloca(ptr, access, type) \ { \ *ptr = (snd_##access##_##type##_t*)alloca(snd.access.type##_sizeof()); \ memset(*ptr, 0, snd.access.type##_sizeof()); \ } #define snd_dylib_alloca2(ptr, access1, access2, type) \ { \ *ptr = (snd_##access1##_access2##_##type##_t*)alloca(snd.access1.access2.type##_sizeof()); \ memset(*ptr, 0, snd.access1.access2.type##_sizeof()); \ } #undef snd_rawmidi_info_alloca #define snd_rawmidi_info_alloca(ptr) snd_dylib_alloca(ptr, rawmidi, info) #undef snd_rawmidi_params_alloca #define snd_rawmidi_params_alloca(ptr) snd_dylib_alloca(ptr, rawmidi, params) #undef snd_rawmidi_status_alloca #define snd_rawmidi_status_alloca(ptr) snd_dylib_alloca(ptr, rawmidi, status) #undef snd_seq_client_info_alloca #define snd_seq_client_info_alloca(ptr) snd_dylib_alloca(ptr, seq, client_info) #undef snd_seq_port_info_alloca #define snd_seq_port_info_alloca(ptr) snd_dylib_alloca(ptr, seq, port_info) #undef snd_seq_queue_tempo_alloca #define snd_seq_queue_tempo_alloca(ptr) snd_dylib_alloca(ptr, seq, queue_tempo) #if LIBREMIDI_ALSA_HAS_UMP #undef snd_ump_block_info_alloca #define snd_ump_block_info_alloca(ptr) snd_dylib_alloca(ptr, ump, block_info) #undef snd_ump_endpoint_info_alloca #define snd_ump_endpoint_info_alloca(ptr) snd_dylib_alloca(ptr, ump, endpoint_info) #endif }