#include #include void print_card_info(snd_ctl_card_info_t *info) { printf("Card #%d: id=%s, driver=%s, name=%s, longname=%s, mixername=%s, components=%s\n", snd_ctl_card_info_get_card(info), snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_driver(info), snd_ctl_card_info_get_name(info), snd_ctl_card_info_get_longname(info), snd_ctl_card_info_get_mixername(info), snd_ctl_card_info_get_components(info)); } void print_elem_id(snd_ctl_elem_id_t *id) { printf("elem_id: numid=%d, interface=%s, device=%d, subdevice=%d, name=%s, index=%d\n", snd_ctl_elem_id_get_numid(id), snd_ctl_elem_iface_name(snd_ctl_elem_id_get_interface(id)), snd_ctl_elem_id_get_device(id), snd_ctl_elem_id_get_subdevice(id), snd_ctl_elem_id_get_name(id), snd_ctl_elem_id_get_index(id)); } void print_elem_info(snd_ctl_elem_list_t *list, unsigned int i) { snd_ctl_elem_id_t *id; printf("Element #%d: numid=%d, interface=%s, device=%d, subdevice=%d, name=%s, index=%d, elem_id follows:\n\t", i, snd_ctl_elem_list_get_numid(list, i), snd_ctl_elem_iface_name(snd_ctl_elem_list_get_interface(list, i)), snd_ctl_elem_list_get_device(list, i), snd_ctl_elem_list_get_subdevice(list, i), snd_ctl_elem_list_get_name(list, i), snd_ctl_elem_list_get_index(list, i)); if (snd_ctl_elem_id_malloc(&id)) { printf("Error allocating snd_ctl_elem_id_t, aborting\n"); return; } snd_ctl_elem_list_get_id(list, i, id); print_elem_id(id); snd_ctl_elem_id_free(id); } void print_power_state(unsigned int state) { char *str; switch(state & SND_CTL_POWER_MASK) { case SND_CTL_POWER_D0: str = "D0"; break; case SND_CTL_POWER_D1: str = "D1"; break; case SND_CTL_POWER_D2: str = "D2"; break; case SND_CTL_POWER_D3hot: str = "D3 hot"; break; case SND_CTL_POWER_D3cold: str = "D3 cold"; break; default: str = "Unknown"; } printf("Power state = %s\n", str); } void print_ctl_type(snd_ctl_type_t type) { char *str; switch(type) { case SND_CTL_TYPE_HW: str = "Kernel level CTL"; break; case SND_CTL_TYPE_SHM: str = "Shared memory client CTL"; break; case SND_CTL_TYPE_INET: str = "INET client CTL"; break; case SND_CTL_TYPE_EXT: str = "External control plugin"; break; default: str = "Unknown"; } printf("CTL type = %s\n", str); } void print_pcm_hw_params(snd_pcm_t *pcm) { snd_pcm_hw_params_t *params; if (snd_pcm_hw_params_malloc(¶ms)) { printf("Error allocating hw params, skipping\n"); return; } if (snd_pcm_hw_params_any(pcm, params)) { printf("Error getting hw params, skipping\n"); snd_pcm_hw_params_free(params); return; } snd_pcm_hw_params_free(params); } void print_pcm_devices(snd_ctl_t *handle) { int card; int device = -1; char deviceascii[25]; snd_ctl_card_info_t *card_info; snd_pcm_t *pcm_playback, *pcm_capture; int playback, capture; if (snd_ctl_card_info_malloc(&card_info)) { printf("Error allocating snd_ctl_card_info_t structure, aborting print_pcm_devices\n"); return; } if (snd_ctl_card_info(handle, card_info)) { printf("Error getting card info, aborting print_pcm_devices\n"); snd_ctl_card_info_free(card_info); return; } card = snd_ctl_card_info_get_card(card_info); snd_ctl_card_info_free(card_info); while (!snd_ctl_pcm_next_device(handle, &device) && device >= 0) { printf("Found PCM device #%d\n", device); snprintf(deviceascii, sizeof(deviceascii), "hw:%d,%d", card, device); playback = capture = -1; playback = snd_pcm_open(&pcm_playback, deviceascii, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); capture = snd_pcm_open(&pcm_capture, deviceascii, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); printf("Playback=%s, Capture=%s, Full Duplex=%s\n", playback ? "no" : "yes", capture ? "no" : "yes", (!playback && !capture) ? "yes" : "no"); printf("Playback capabilities:\n"); print_pcm_hw_params(pcm_playback); printf("Capture capabilities:\n"); print_pcm_hw_params(pcm_capture); if (!playback && snd_pcm_close(pcm_playback)) { printf("Error closing PCM device #%d, LEAKING MEMORY\n", device); } if (!capture && snd_pcm_close(pcm_capture)) { printf("Error closing PCM device #%d, LEAKING MEMORY\n", device); } } } int main(int argc, char **argv) { int card = -1; char cardascii[14]; snd_ctl_t *handle; snd_ctl_card_info_t *card_info; snd_ctl_elem_list_t *elem_list; unsigned int used, count, power_state; while (snd_card_next(&card) >= 0 && card >= 0) { snprintf(cardascii, sizeof(cardascii), "hw:%d", card); if (snd_ctl_open(&handle, cardascii, 0)) { printf("Error opening card #%d, skipping\n", card); continue; } if (snd_ctl_card_info_malloc(&card_info)) { printf("Error allocating snd_ctl_card_info_t structure, skipping\n"); snd_ctl_close(handle); continue; } if (snd_ctl_card_info(handle, card_info)) { printf("Error getting info for card #%d, skipping\n", card); snd_ctl_close(handle); snd_ctl_card_info_free(card_info); continue; } print_card_info(card_info); snd_ctl_card_info_free(card_info); if (snd_ctl_elem_list_malloc(&elem_list)) { printf("Error allocating snd_ctl_elem_list_t, skipping\n"); snd_ctl_close(handle); continue; } if (snd_ctl_elem_list(handle, elem_list)) { printf("Error getting element list, skipping\n"); snd_ctl_close(handle); snd_ctl_elem_list_free(elem_list); continue; } used = snd_ctl_elem_list_get_used(elem_list); count = snd_ctl_elem_list_get_count(elem_list); printf("Element used = %d, count = %d. Allocating space for %d entries...\n", used, count, count); if (snd_ctl_elem_list_alloc_space(elem_list, count)) { printf("Error allocating element list space, skipping\n"); snd_ctl_close(handle); snd_ctl_elem_list_free(elem_list); continue; } if (snd_ctl_elem_list(handle, elem_list)) { printf("Error getting element list, skipping\n"); snd_ctl_close(handle); snd_ctl_elem_list_free(elem_list); snd_ctl_elem_list_free_space(elem_list); continue; } used = snd_ctl_elem_list_get_used(elem_list); count = snd_ctl_elem_list_get_count(elem_list); printf("Element used = %d, count = %d\n", used, count); for (unsigned int i = 0; i < used; i++) { print_elem_info(elem_list, i); } snd_ctl_elem_list_free_space(elem_list); snd_ctl_elem_list_free(elem_list); if (snd_ctl_get_power_state(handle, &power_state)) { printf("Error getting power state, skipping\n"); snd_ctl_close(handle); continue; } print_power_state(power_state); print_ctl_type(snd_ctl_type(handle)); print_pcm_devices(handle); snd_ctl_close(handle); } printf("No more cards!\n"); return 0; }