コード例 #1
0
/* Common operations. */
static int add_elem_set(struct elem_set_trial *trial)
{
	snd_ctl_elem_info_t *info;
	char name[64] = {0};
	int err;

	snprintf(name, 64, "userspace-control-element-%s",
		 snd_ctl_elem_type_name(trial->type));

	snd_ctl_elem_info_alloca(&info);
	snd_ctl_elem_info_set_interface(info, SND_CTL_ELEM_IFACE_MIXER);
	snd_ctl_elem_info_set_name(info, name);
	snd_ctl_elem_info_set_dimension(info, trial->dimension);

	err = trial->add_elem_set(trial, info);
	if (err >= 0)
		snd_ctl_elem_info_get_id(info, trial->id);

	return err;
}
コード例 #2
0
ファイル: amixer.c プロジェクト: IcaroL2ORK/pd
static const char *control_type(snd_ctl_elem_info_t *info)
{
  return snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info));
}
コード例 #3
0
static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *top)
{
	snd_ctl_elem_value_t *ctl;
	snd_ctl_elem_info_t *info;
	snd_config_t *control, *comment, *item, *value;
	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_inactive(info) ||
				!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;
	}

	err = snd_config_compound_add(top, num_str(snd_ctl_elem_info_get_numid(info)), 0, &control);
	if (err < 0) {
		error("snd_config_compound_add: %s", snd_strerror(err));
		return err;
	}
	err = snd_config_compound_add(control, "comment", 1, &comment);
	if (err < 0) {
		error("snd_config_compound_add: %s", 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");
	if (snd_ctl_elem_info_is_user(info))
		strcat(buf, " user");
	err = snd_config_string_add(comment, "access", buf + 1);
	if (err < 0) {
		error("snd_config_string_add: %s", snd_strerror(err));
		return err;
	}

	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);
	err = snd_config_string_add(comment, "type", s);
	if (err < 0) {
		error("snd_config_string_add: %s", snd_strerror(err));
		return err;
	}
	err = snd_config_integer_add(comment, "count", count);
	if (err < 0) {
		error("snd_config_integer_add: %s", snd_strerror(err));
		return err;
	}

	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)
			sprintf(buf, "%li - %li (step %li)", min, max, step);
		else
			sprintf(buf, "%li - %li", min, max);
		err = snd_config_string_add(comment, "range", buf);
		if (err < 0) {
			error("snd_config_string_add: %s", snd_strerror(err));
			return err;
		}
		if (snd_ctl_elem_info_is_tlv_readable(info)) {
			err = add_tlv_comments(handle, id, info, comment);
			if (err < 0)
				return err;
		}
		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)
			sprintf(buf, "%Li - %Li (step %Li)", min, max, step);
		else
			sprintf(buf, "%Li - %Li", min, max);
		err = snd_config_string_add(comment, "range", buf);
		if (err < 0) {
			error("snd_config_string_add: %s", snd_strerror(err));
			return err;
		}
		break;
	}
	case SND_CTL_ELEM_TYPE_ENUMERATED:
	{
		unsigned int items;
		err = snd_config_compound_add(comment, "item", 1, &item);
		if (err < 0) {
			error("snd_config_compound_add: %s", snd_strerror(err));
			return err;
		}
		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;
			}
			err = snd_config_string_add(item, num_str(idx), snd_ctl_elem_info_get_item_name(info));
			if (err < 0) {
				error("snd_config_string_add: %s", snd_strerror(err));
				return err;
			}
		}
		break;
	}
	default:
		break;
	}
	s = snd_ctl_elem_iface_name(snd_ctl_elem_info_get_interface(info));
	err = snd_config_string_add(control, "iface", s);
	if (err < 0) {
		error("snd_config_string_add: %s", snd_strerror(err));
		return err;
	}
	if (device != 0) {
		err = snd_config_integer_add(control, "device", device);
		if (err < 0) {
			error("snd_config_integer_add: %s", snd_strerror(err));
			return err;
		}
	}
	if (subdevice != 0) {
		err = snd_config_integer_add(control, "subdevice", subdevice);
		if (err < 0) {
			error("snd_config_integer_add: %s", snd_strerror(err));
			return err;
		}
	}
	err = snd_config_string_add(control, "name", name);
	if (err < 0) {
		error("snd_config_string_add: %s", snd_strerror(err));
		return err;
	}
	if (index != 0) {
		err = snd_config_integer_add(control, "index", index);
		if (err < 0) {
			error("snd_config_integer_add: %s", snd_strerror(err));
			return err;
		}
	}

	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';
		err = snd_config_string_add(control, "value", buf);
		if (err < 0) {
			error("snd_config_string_add: %s", snd_strerror(err));
			return err;
		}
		return 0;
	}
	default:
		break;
	}

	if (count == 1) {
		switch (type) {
		case SND_CTL_ELEM_TYPE_BOOLEAN:
			err = snd_config_string_add(control, "value", snd_ctl_elem_value_get_boolean(ctl, 0) ? "true" : "false");
			if (err < 0) {
				error("snd_config_string_add: %s", snd_strerror(err));
				return err;
			}
			return 0;
		case SND_CTL_ELEM_TYPE_INTEGER:
			err = snd_config_integer_add(control, "value", snd_ctl_elem_value_get_integer(ctl, 0));
			if (err < 0) {
				error("snd_config_integer_add: %s", snd_strerror(err));
				return err;
			}
			return 0;
		case SND_CTL_ELEM_TYPE_INTEGER64:
			err = snd_config_integer64_add(control, "value", snd_ctl_elem_value_get_integer64(ctl, 0));
			if (err < 0) {
				error("snd_config_integer64_add: %s", snd_strerror(err));
				return err;
			}
			return 0;
		case SND_CTL_ELEM_TYPE_ENUMERATED:
		{
			unsigned int v = snd_ctl_elem_value_get_enumerated(ctl, 0);
			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(control, "value", s);
			} else {
				err = snd_config_integer_add(control, "value", v);
			}
			if (err < 0)
				error("snd_config add: %s", snd_strerror(err));
			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;
}
コード例 #4
0
int main(void)
{
	struct elem_set_trial trial = {0};
	unsigned int i;
	int err;

	snd_ctl_elem_id_alloca(&trial.id);

	err = snd_ctl_open(&trial.handle, "hw:0", 0);
	if (err < 0)
		return EXIT_FAILURE;

	err = snd_ctl_subscribe_events(trial.handle, 1);
	if (err < 0)
		return EXIT_FAILURE;

	/* Test all of types. */
	for (i = 0; i < SND_CTL_ELEM_TYPE_LAST; ++i) {
		trial.type = i + 1;

		/* Assign type-dependent operations. */
		switch (trial.type) {
		case SND_CTL_ELEM_TYPE_BOOLEAN:
			trial.element_count = 900;
			trial.member_count = 128;
			trial.dimension[0] = 4;
			trial.dimension[1] = 4;
			trial.dimension[2] = 8;
			trial.dimension[3] = 0;
			trial.add_elem_set = add_bool_elem_set;
			trial.check_elem_props = NULL;
			trial.change_elem_members = change_bool_elem_members;
			break;
		case SND_CTL_ELEM_TYPE_INTEGER:
			trial.element_count = 900;
			trial.member_count = 128;
			trial.dimension[0] = 128;
			trial.dimension[1] = 0;
			trial.dimension[2] = 0;
			trial.dimension[3] = 0;
			trial.add_elem_set = add_int_elem_set;
			trial.check_elem_props = check_int_elem_props;
			trial.change_elem_members = change_int_elem_members;
			break;
		case SND_CTL_ELEM_TYPE_ENUMERATED:
			trial.element_count = 900;
			trial.member_count = 128;
			trial.dimension[0] = 16;
			trial.dimension[1] = 8;
			trial.dimension[2] = 0;
			trial.dimension[3] = 0;
			trial.add_elem_set = add_enum_elem_set;
			trial.check_elem_props = check_enum_elem_props;
			trial.change_elem_members = change_enum_elem_members;
			break;
		case SND_CTL_ELEM_TYPE_BYTES:
			trial.element_count = 900;
			trial.member_count = 512;
			trial.dimension[0] = 8;
			trial.dimension[1] = 4;
			trial.dimension[2] = 8;
			trial.dimension[3] = 2;
			trial.add_elem_set = add_bytes_elem_set;
			trial.check_elem_props = NULL;
			trial.change_elem_members = change_bytes_elem_members;
			break;
		case SND_CTL_ELEM_TYPE_IEC958:
			trial.element_count = 1;
			trial.member_count = 1;
			trial.dimension[0] = 0;
			trial.dimension[1] = 0;
			trial.dimension[2] = 0;
			trial.dimension[3] = 0;
			trial.add_elem_set = add_iec958_elem_set;
			trial.check_elem_props = NULL;
			trial.change_elem_members = change_iec958_elem_members;
			break;
		case SND_CTL_ELEM_TYPE_INTEGER64:
		default:
			trial.element_count = 900;
			trial.member_count = 64;
			trial.dimension[0] = 0;
			trial.dimension[1] = 0;
			trial.dimension[2] = 0;
			trial.dimension[3] = 0;
			trial.add_elem_set = add_int64_elem_set;
			trial.check_elem_props = check_int64_elem_props;
			trial.change_elem_members = change_int64_elem_members;
			break;
		}

		/* Test an operation to add an element set. */
		err = add_elem_set(&trial);
		if (err < 0) {
			printf("Fail to add an element set with %s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}
		err = check_event(&trial, SND_CTL_EVENT_MASK_ADD,
				  trial.element_count);
		if (err < 0) {
			printf("Fail to check some events to add elements with "
			       "%s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}

		/* Check properties of each element in this element set. */
		err = check_elem_set_props(&trial);
		if (err < 0) {
			printf("Fail to check propetries of each element with "
			       "%s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}

		/*
		 * Test operations to change the state of members in each
		 * element in the element set.
		 */
		err = check_elems(&trial);
		if (err < 0) {
			printf("Fail to change status of each element with %s "
			       "type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}
		err = check_event(&trial, SND_CTL_EVENT_MASK_VALUE,
				  trial.element_count);
		if (err < 0) {
			printf("Fail to check some events to change status of "
			       "each elements with %s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}

		/*
		 * Test an operation to change threshold data of this element set,
		 * except for IEC958 type.
		 */
		if (trial.type != SND_CTL_ELEM_TYPE_IEC958) {
			err = check_tlv(&trial);
			if (err < 0) {
				printf("Fail to change threshold level of an "
				       "element set with %s type.\n",
				       snd_ctl_elem_type_name(trial.type));
				break;
			}
			err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1);
			if (err < 0) {
				printf("Fail to check an event to change "
				       "threshold level of an an element set "
				       "with %s type.\n",
				       snd_ctl_elem_type_name(trial.type));
				break;
			}
		}

		/* Test an operation to remove elements in this element set. */
		err = snd_ctl_elem_remove(trial.handle, trial.id);
		if (err < 0) {
			printf("Fail to remove elements with %s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}
		err = check_event(&trial, SND_CTL_EVENT_MASK_REMOVE,
						  trial.element_count);
		if (err < 0) {
			printf("Fail to check some events to remove each "
			       "element with %s type.\n",
			       snd_ctl_elem_type_name(trial.type));
			break;
		}
	}

	if (err < 0) {
		printf("%s\n", snd_strerror(err));

		/* To ensure. */
		snd_ctl_elem_remove(trial.handle, trial.id);
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}