All pastes #155623 Raw Edit

Stuff

public text v1 · immutable
#155623 ·published 2006-08-31 05:21 UTC
rendered paste body
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <alsa/asoundlib.h>

#define error(a, b...) do{ \
	char __tmp__[255]; \
	snprintf(__tmp__, 255, a, ##b); \
	fprintf(stderr, "%s:%s:%i	ERROR: %s\n", __FILE__, __FUNCTION__, __LINE__, __tmp__); \
	fflush(stderr); \
}while(0)

#define debug(a, b...) do{ \
	char __tmp__[255]; \
	snprintf(__tmp__, 255, a, ##b); \
	printf("%s\n", __tmp__); \
}while(0)

char *id_str(snd_ctl_elem_id_t *id)
{
	static char str[128];
	assert(id);
	sprintf(str, "%i,%i,%i,%s,%i",
		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));
	return str;
}

char *num_str(long n)
{
	static char str[32];
	sprintf(str, "%ld", n);
	return str;
}


static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id)
{
	snd_ctl_elem_value_t *ctl;
	snd_ctl_elem_info_t *info;
	const char *s;
	char buf[256];
	unsigned int idx;
	int err;
	unsigned int device, subdevice, index;
	const char *name;
	snd_ctl_elem_type_t type;
	unsigned int count;
	snd_ctl_elem_value_alloca(&ctl);
	snd_ctl_elem_info_alloca(&info);
	snd_ctl_elem_info_set_id(info, id);
	err = snd_ctl_elem_info(handle, info);
	if (err < 0) {
		error("Cannot read control info '%s': %s", id_str(id), snd_strerror(err));
		return err;
	}

	if (!snd_ctl_elem_info_is_readable(info))
		return 0;

	snd_ctl_elem_value_set_id(ctl, id);
	err = snd_ctl_elem_read(handle, ctl);
	if (err < 0) {
		error("Cannot read control '%s': %s", id_str(id), snd_strerror(err));
		return err;
	}

	buf[0] = '\0';
	buf[1] = '\0';
	if (snd_ctl_elem_info_is_readable(info))
		strcat(buf, " read");
	if (snd_ctl_elem_info_is_writable(info))
		strcat(buf, " write");
	if (snd_ctl_elem_info_is_inactive(info))
		strcat(buf, " inactive");
	if (snd_ctl_elem_info_is_volatile(info))
		strcat(buf, " volatile");
	if (snd_ctl_elem_info_is_locked(info))
		strcat(buf, " locked");

	type = snd_ctl_elem_info_get_type(info);
	device = snd_ctl_elem_info_get_device(info);
	subdevice = snd_ctl_elem_info_get_subdevice(info);
	index = snd_ctl_elem_info_get_index(info);
	name = snd_ctl_elem_info_get_name(info);
	count = snd_ctl_elem_info_get_count(info);
	s = snd_ctl_elem_type_name(type);

	s = snd_ctl_elem_iface_name(snd_ctl_elem_info_get_interface(info));
	debug("iface: %s", s);

	if (device != 0) {
		debug("device: %i", device);
	}
	if (subdevice != 0) {
		debug("subdevice: %i", subdevice);
	}

	debug("name: %s", name);

	if (index != 0) {
		debug("index: %i", index);
	}

	switch (type) {
		case SND_CTL_ELEM_TYPE_BOOLEAN:
			break;

		case SND_CTL_ELEM_TYPE_INTEGER: {
			long min = snd_ctl_elem_info_get_min(info);
			long max = snd_ctl_elem_info_get_max(info);
			long step = snd_ctl_elem_info_get_step(info);
			if (step)
				debug("%li - %li (step %li)", min, max, step);
			else
				debug("%li - %li", min, max);

			break;
		}

		case SND_CTL_ELEM_TYPE_INTEGER64: {
			long long min = snd_ctl_elem_info_get_min64(info);
			long long max = snd_ctl_elem_info_get_max64(info);
			long long step = snd_ctl_elem_info_get_step64(info);
			if (step)
				debug("%Li - %Li (step %Li)", min, max, step);
			else
				debug("%Li - %Li", min, max);
			break;
		}

		case SND_CTL_ELEM_TYPE_ENUMERATED: {
			unsigned int items;
			char tmp[256];

			items = snd_ctl_elem_info_get_items(info);
			for (idx = 0; idx < items; idx++) {
				snd_ctl_elem_info_set_item(info, idx);
				err = snd_ctl_elem_info(handle, info);
				if (err < 0) {
					error("snd_ctl_card_info: %s", snd_strerror(err));
					return err;
				}

				debug("\t%s, %s", num_str(idx), snd_ctl_elem_info_get_item_name(info));
			}
			break;
		}
		default:
			break;
	}

	switch (type) {
		case SND_CTL_ELEM_TYPE_BYTES:
		case SND_CTL_ELEM_TYPE_IEC958: {
			size_t size = type == SND_CTL_ELEM_TYPE_BYTES ? count : sizeof(snd_aes_iec958_t);
			char buf[size * 2 + 1];
			char *p = buf;
			char *hex = "0123456789abcdef";
			const unsigned char *bytes = (const unsigned char *)snd_ctl_elem_value_get_bytes(ctl);

			for (idx = 0; idx < size; idx++) {
				int v = bytes[idx];
				*p++ = hex[v >> 4];
				*p++ = hex[v & 0x0f];
			}

			*p = '\0';

			debug("value: %u", buf);

			return 0;
		}

		default:
			break;
	}

	if (count == 1) {
		switch (type) {
			case SND_CTL_ELEM_TYPE_BOOLEAN:
				debug("value: %s", snd_ctl_elem_value_get_boolean(ctl, 0) ? "true" : "false");
				return 0;

			case SND_CTL_ELEM_TYPE_INTEGER:
				debug("value: %i", snd_ctl_elem_value_get_integer(ctl, 0));
				return 0;

			case SND_CTL_ELEM_TYPE_INTEGER64:
				debug("value: %lli", snd_ctl_elem_value_get_integer64(ctl, 0));
				return 0;

			case SND_CTL_ELEM_TYPE_ENUMERATED: {
				unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, 0);

				debug("(enum) value: %i", v);

				return 0;
			}

			default:
				error("Unknown control type: %d\n", type);
				return -EINVAL;
		}
	}

/*	err = snd_config_compound_add(control, "value", 1, &value);
	if (err < 0) {
		error("snd_config_compound_add: %s", snd_strerror(err));
		return err;
	}

	switch (type) {
	case SND_CTL_ELEM_TYPE_BOOLEAN:
		for (idx = 0; idx < count; idx++) {
			err = snd_config_string_add(value, num_str(idx), snd_ctl_elem_value_get_boolean(ctl, idx) ? "true" : "false");
			if (err < 0) {
				error("snd_config_string_add: %s", snd_strerror(err));
				return err;
			}
		}
		break;
	case SND_CTL_ELEM_TYPE_INTEGER:
		for (idx = 0; idx < count; idx++) {
			err = snd_config_integer_add(value, num_str(idx), snd_ctl_elem_value_get_integer(ctl, idx));
			if (err < 0) {
				error("snd_config_integer_add: %s", snd_strerror(err));
				return err;
			}
		}
		break;
	case SND_CTL_ELEM_TYPE_INTEGER64:
		for (idx = 0; idx < count; idx++) {
			err = snd_config_integer64_add(value, num_str(idx), snd_ctl_elem_value_get_integer64(ctl, idx));
			if (err < 0) {
				error("snd_config_integer64_add: %s", snd_strerror(err));
				return err;
			}
		}
		break;
	case SND_CTL_ELEM_TYPE_ENUMERATED:
		for (idx = 0; idx < count; idx++) {
			unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, idx);
			snd_config_t *c;
			err = snd_config_search(item, num_str(v), &c);
			if (err == 0) {
				err = snd_config_get_string(c, &s);
				assert(err == 0);
				err = snd_config_string_add(value, num_str(idx), s);
			} else {
				err = snd_config_integer_add(value, num_str(idx), v);
			}
			if (err < 0) {
				error("snd_config add: %s", snd_strerror(err));
				return err;
			}
		}
		break;
	default:
		error("Unknown control type: %d\n", type);
		return -EINVAL;
	}*/

	return 0;
}

static int get_controls(int cardno)
{
	snd_ctl_t *handle;
	snd_ctl_card_info_t *info;
	snd_ctl_elem_list_t *list;
	unsigned int idx;
	int err;
	char name[32];
	unsigned int count;
	const char *id;
	snd_ctl_card_info_alloca(&info);
	snd_ctl_elem_list_alloca(&list);

	sprintf(name, "hw:%d", cardno);
	err = snd_ctl_open(&handle, name, SND_CTL_READONLY);
	if (err < 0) {
		error("snd_ctl_open error: %s", snd_strerror(err));
		return err;
	}
	err = snd_ctl_card_info(handle, info);
	if (err < 0) {
		error("snd_ctl_card_info error: %s", snd_strerror(err));
		goto _close;
	}
	err = snd_ctl_elem_list(handle, list);
	if (err < 0) {
		error("Cannot determine controls: %s", snd_strerror(err));
		goto _close;
	}
	count = snd_ctl_elem_list_get_count(list);
	if (count < 0) {
		err = 0;
		goto _close;
	}

	if (count == 0) {
		err = 0;
		goto _close;
	}
	snd_ctl_elem_list_set_offset(list, 0);
	if (snd_ctl_elem_list_alloc_space(list, count) < 0) {
		error("No enough memory...");
		goto _close;
	}
	if ((err = snd_ctl_elem_list(handle, list)) < 0) {
		error("Cannot determine controls (2): %s", snd_strerror(err));
		goto _free;
	}
	for (idx = 0; idx < count; ++idx) {
		snd_ctl_elem_id_t *id;
		snd_ctl_elem_id_alloca(&id);
		snd_ctl_elem_list_get_id(list, idx, id);
		err = get_control(handle, id);
		if (err < 0)
			goto _free;
	}

	err = 0;
 _free:
	snd_ctl_elem_list_free_space(list);
 _close:
	snd_ctl_close(handle);
	return err;
}

int main(int argc, char **argv)
{
	int card = 0;
	char *string = NULL;

	while(card > -1) {
		snd_card_get_name(card, &string);
		printf("Card name: \"%s\"\n", string);

		get_controls(card);

		snd_card_next(&card);
	}
}