Control API encapsulation. Better names for kernel API. Simpler PCM hw_params API. Added missing const.

This commit is contained in:
Abramo Bagnara 2001-02-06 23:48:29 +00:00
parent 3df0171dc0
commit 0ef8943fb0
4 changed files with 427 additions and 426 deletions

View file

@ -67,7 +67,12 @@ char *id_str(snd_control_id_t *id)
{ {
static char str[128]; static char str[128];
assert(id); assert(id);
sprintf(str, "%i,%i,%i,%s,%i", id->iface, id->device, id->subdevice, id->name, id->index); sprintf(str, "%i,%i,%i,%s,%i",
snd_enum_to_int(snd_control_id_get_interface(id)),
snd_control_id_get_device(id),
snd_control_id_get_subdevice(id),
snd_control_id_get_name(id),
snd_control_id_get_index(id));
return str; return str;
} }
@ -98,7 +103,7 @@ static int snd_config_integer_add(snd_config_t *father, char *id, long integer)
return 0; return 0;
} }
static int snd_config_string_add(snd_config_t *father, char *id, char *string) static int snd_config_string_add(snd_config_t *father, const char *id, const char *string)
{ {
int err; int err;
snd_config_t *leaf; snd_config_t *leaf;
@ -118,7 +123,7 @@ static int snd_config_string_add(snd_config_t *father, char *id, char *string)
return 0; return 0;
} }
static int snd_config_compound_add(snd_config_t *father, char *id, int join, static int snd_config_compound_add(snd_config_t *father, const char *id, int join,
snd_config_t **node) snd_config_t **node)
{ {
int err; int err;
@ -137,33 +142,36 @@ static int snd_config_compound_add(snd_config_t *father, char *id, int join,
static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *top) static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *top)
{ {
snd_control_t ctl; snd_control_t *ctl;
snd_control_info_t info; snd_control_info_t *info;
snd_config_t *control, *comment, *item, *value; snd_config_t *control, *comment, *item, *value;
char *s; const char *s;
char buf[256]; char buf[256];
unsigned int idx; unsigned int idx;
int err; int err;
unsigned int device, subdevice, index;
memset(&info, 0, sizeof(info)); const char *name;
info.id = *id; snd_control_type_t type;
err = snd_ctl_cinfo(handle, &info); unsigned int count;
snd_control_alloca(&ctl);
snd_control_info_alloca(&info);
snd_control_info_set_id(info, id);
err = snd_ctl_cinfo(handle, info);
if (err < 0) { if (err < 0) {
error("Cannot read control info '%s': %s", id_str(id), snd_strerror(err)); error("Cannot read control info '%s': %s", id_str(id), snd_strerror(err));
return err; return err;
} }
if (!(info.access & SND_CONTROL_ACCESS_READ)) if (!snd_control_info_is_readable(info))
return 0; return 0;
memset(&ctl, 0, sizeof(ctl)); snd_control_set_id(ctl, id);
ctl.id = info.id; err = snd_ctl_cread(handle, ctl);
err = snd_ctl_cread(handle, &ctl);
if (err < 0) { if (err < 0) {
error("Cannot read control '%s': %s", id_str(id), snd_strerror(err)); error("Cannot read control '%s': %s", id_str(id), snd_strerror(err));
return err; return err;
} }
err = snd_config_compound_add(top, num_str(info.id.numid), 0, &control); err = snd_config_compound_add(top, num_str(snd_control_info_get_numid(info)), 0, &control);
if (err < 0) { if (err < 0) {
error("snd_config_compound_add: %s", snd_strerror(err)); error("snd_config_compound_add: %s", snd_strerror(err));
return err; return err;
@ -176,154 +184,128 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
buf[0] = '\0'; buf[0] = '\0';
buf[1] = '\0'; buf[1] = '\0';
if (info.access & SND_CONTROL_ACCESS_READ) if (snd_control_info_is_readable(info))
strcat(buf, " read"); strcat(buf, " read");
if (info.access & SND_CONTROL_ACCESS_WRITE) if (snd_control_info_is_writable(info))
strcat(buf, " write"); strcat(buf, " write");
if (info.access & SND_CONTROL_ACCESS_INACTIVE) if (snd_control_info_is_inactive(info))
strcat(buf, " inactive"); strcat(buf, " inactive");
if (snd_control_info_is_volatile(info))
strcat(buf, " volatile");
if (snd_control_info_is_locked(info))
strcat(buf, " locked");
if (snd_control_info_is_indirect(info))
strcat(buf, " indirect");
err = snd_config_string_add(comment, "access", buf + 1); err = snd_config_string_add(comment, "access", buf + 1);
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
switch (info.type) { type = snd_control_info_get_type(info);
case SND_CONTROL_TYPE_BOOLEAN: device = snd_control_info_get_device(info);
s = "bool"; subdevice = snd_control_info_get_subdevice(info);
break; index = snd_control_info_get_index(info);
case SND_CONTROL_TYPE_INTEGER: name = snd_control_info_get_name(info);
s = "integer"; count = snd_control_info_get_count(info);
break; s = snd_control_type_name(type);
case SND_CONTROL_TYPE_ENUMERATED:
s = "enumerated";
break;
case SND_CONTROL_TYPE_BYTES:
s = "bytes";
break;
case SND_CONTROL_TYPE_IEC958:
s = "iec958";
break;
default:
s = "unknown";
break;
}
err = snd_config_string_add(comment, "type", s); err = snd_config_string_add(comment, "type", s);
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
if (info.value.integer.min != 0 || info.value.integer.max != 1 ||
info.value.integer.step != 0)
error("Bad boolean control '%s'", id_str(id));
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
if (info.value.integer.step) {
sprintf(buf, "%li - %li (step %li)", info.value.integer.min, info.value.integer.max, info.value.integer.step); long min = snd_control_info_get_min(info);
long max = snd_control_info_get_max(info);
long step = snd_control_info_get_step(info);
if (step)
sprintf(buf, "%li - %li (step %li)", min, max, step);
else else
sprintf(buf, "%li - %li", info.value.integer.min, info.value.integer.max); sprintf(buf, "%li - %li", min, max);
err = snd_config_string_add(comment, "range", buf); err = snd_config_string_add(comment, "range", buf);
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
break; break;
}
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
{
unsigned int items;
err = snd_config_compound_add(comment, "item", 1, &item); err = snd_config_compound_add(comment, "item", 1, &item);
if (err < 0) { if (err < 0) {
error("snd_config_compound_add: %s", snd_strerror(err)); error("snd_config_compound_add: %s", snd_strerror(err));
return err; return err;
} }
for (idx = 0; idx < info.value.enumerated.items; idx++) { items = snd_control_info_get_items(info);
info.value.enumerated.item = idx; for (idx = 0; idx < items; idx++) {
err = snd_ctl_cinfo(handle, &info); snd_control_info_set_item(info, idx);
err = snd_ctl_cinfo(handle, info);
if (err < 0) { if (err < 0) {
error("snd_ctl_info: %s", snd_strerror(err)); error("snd_ctl_info: %s", snd_strerror(err));
return err; return err;
} }
err = snd_config_string_add(item, num_str(idx), info.value.enumerated.name); err = snd_config_string_add(item, num_str(idx), snd_control_info_get_item_name(info));
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
} }
break; break;
}
default: default:
break; break;
} }
switch (info.id.iface) { s = snd_control_iface_name(snd_control_info_get_interface(info));
case SND_CONTROL_IFACE_CARD:
s = "card";
break;
case SND_CONTROL_IFACE_HWDEP:
s = "hwdep";
break;
case SND_CONTROL_IFACE_MIXER:
s = "mixer";
break;
case SND_CONTROL_IFACE_PCM:
s = "pcm";
break;
case SND_CONTROL_IFACE_RAWMIDI:
s = "rawmidi";
break;
case SND_CONTROL_IFACE_TIMER:
s = "timer";
break;
case SND_CONTROL_IFACE_SEQUENCER:
s = "sequencer";
break;
default:
s = num_str(info.id.iface);
break;
}
err = snd_config_string_add(control, "iface", s); err = snd_config_string_add(control, "iface", s);
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
if (info.id.device != 0) { if (device != 0) {
err = snd_config_integer_add(control, "device", info.id.device); err = snd_config_integer_add(control, "device", device);
if (err < 0) { if (err < 0) {
error("snd_config_integer_add: %s", snd_strerror(err)); error("snd_config_integer_add: %s", snd_strerror(err));
return err; return err;
} }
} }
if (info.id.subdevice != 0) { if (subdevice != 0) {
err = snd_config_integer_add(control, "subdevice", info.id.subdevice); err = snd_config_integer_add(control, "subdevice", subdevice);
if (err < 0) { if (err < 0) {
error("snd_config_integer_add: %s", snd_strerror(err)); error("snd_config_integer_add: %s", snd_strerror(err));
return err; return err;
} }
} }
err = snd_config_string_add(control, "name", info.id.name); err = snd_config_string_add(control, "name", name);
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
if (info.id.index != 0) { if (index != 0) {
err = snd_config_integer_add(control, "index", info.id.index); err = snd_config_integer_add(control, "index", index);
if (err < 0) { if (err < 0) {
error("snd_config_integer_add: %s", snd_strerror(err)); error("snd_config_integer_add: %s", snd_strerror(err));
return err; return err;
} }
} }
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BYTES: case SND_CONTROL_TYPE_BYTES:
case SND_CONTROL_TYPE_IEC958: case SND_CONTROL_TYPE_IEC958:
{ {
size_t count = info.type == SND_CONTROL_TYPE_BYTES ? size_t size = type == SND_CONTROL_TYPE_BYTES ?
info.values_count : sizeof(snd_aes_iec958_t); count : sizeof(snd_aes_iec958_t);
char buf[count * 2 + 1]; char buf[count * 2 + 1];
char *p = buf; char *p = buf;
char *hex = "0123456789abcdef"; char *hex = "0123456789abcdef";
for (idx = 0; idx < count; idx++) { const char *bytes = snd_control_get_bytes(ctl);
int v = ctl.value.bytes.data[idx]; for (idx = 0; idx < size; idx++) {
int v = bytes[idx];
*p++ = hex[v >> 4]; *p++ = hex[v >> 4];
*p++ = hex[v & 0x0f]; *p++ = hex[v & 0x0f];
} }
@ -339,17 +321,17 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
break; break;
} }
if (info.values_count == 1) { if (count == 1) {
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
err = snd_config_string_add(control, "value", ctl.value.integer.value[0] ? "true" : "false"); err = snd_config_string_add(control, "value", snd_control_get_boolean(ctl, 0) ? "true" : "false");
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
} }
return 0; return 0;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
err = snd_config_integer_add(control, "value", ctl.value.integer.value[0]); err = snd_config_integer_add(control, "value", snd_control_get_integer(ctl, 0));
if (err < 0) { if (err < 0) {
error("snd_config_integer_add: %s", snd_strerror(err)); error("snd_config_integer_add: %s", snd_strerror(err));
return err; return err;
@ -357,7 +339,7 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
return 0; return 0;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
{ {
unsigned int v = ctl.value.enumerated.item[0]; unsigned int v = snd_control_get_enumerated(ctl, 0);
snd_config_t *c; snd_config_t *c;
err = snd_config_search(item, num_str(v), &c); err = snd_config_search(item, num_str(v), &c);
if (err == 0) { if (err == 0) {
@ -372,7 +354,7 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
return 0; return 0;
} }
default: default:
error("Unknown control type: %d\n", info.type); error("Unknown control type: %d\n", snd_enum_to_int(type));
return -EINVAL; return -EINVAL;
} }
} }
@ -383,10 +365,10 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
return err; return err;
} }
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
for (idx = 0; idx < info.values_count; idx++) { for (idx = 0; idx < count; idx++) {
err = snd_config_string_add(value, num_str(idx), ctl.value.integer.value[idx] ? "true" : "false"); err = snd_config_string_add(value, num_str(idx), snd_control_get_boolean(ctl, idx) ? "true" : "false");
if (err < 0) { if (err < 0) {
error("snd_config_string_add: %s", snd_strerror(err)); error("snd_config_string_add: %s", snd_strerror(err));
return err; return err;
@ -394,8 +376,8 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
} }
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
for (idx = 0; idx < info.values_count; idx++) { for (idx = 0; idx < count; idx++) {
err = snd_config_integer_add(value, num_str(idx), ctl.value.integer.value[idx]); err = snd_config_integer_add(value, num_str(idx), snd_control_get_integer(ctl, idx));
if (err < 0) { if (err < 0) {
error("snd_config_integer_add: %s", snd_strerror(err)); error("snd_config_integer_add: %s", snd_strerror(err));
return err; return err;
@ -403,8 +385,8 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
} }
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
for (idx = 0; idx < info.values_count; idx++) { for (idx = 0; idx < count; idx++) {
unsigned int v = ctl.value.enumerated.item[idx]; unsigned int v = snd_control_get_enumerated(ctl, idx);
snd_config_t *c; snd_config_t *c;
err = snd_config_search(item, num_str(v), &c); err = snd_config_search(item, num_str(v), &c);
if (err == 0) { if (err == 0) {
@ -421,7 +403,7 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
} }
break; break;
default: default:
error("Unknown control type: %d\n", info.type); error("Unknown control type: %d\n", snd_enum_to_int(type));
return -EINVAL; return -EINVAL;
} }
@ -431,12 +413,16 @@ static int get_control(snd_ctl_t *handle, snd_control_id_t *id, snd_config_t *to
static int get_controls(int cardno, snd_config_t *top) static int get_controls(int cardno, snd_config_t *top)
{ {
snd_ctl_t *handle; snd_ctl_t *handle;
snd_ctl_hw_info_t info; snd_ctl_info_t *info;
snd_config_t *state, *card, *control; snd_config_t *state, *card, *control;
snd_control_list_t list; snd_control_list_t *list;
unsigned int idx; unsigned int idx;
int err; int err;
char name[32]; char name[32];
unsigned int count;
const char *id;
snd_ctl_info_alloca(&info);
snd_control_list_alloca(&list);
sprintf(name, "hw:%d", cardno); sprintf(name, "hw:%d", cardno);
err = snd_ctl_open(&handle, name); err = snd_ctl_open(&handle, name);
@ -444,11 +430,12 @@ static int get_controls(int cardno, snd_config_t *top)
error("snd_ctl_open error: %s", snd_strerror(err)); error("snd_ctl_open error: %s", snd_strerror(err));
return err; return err;
} }
err = snd_ctl_hw_info(handle, &info); err = snd_ctl_info(handle, info);
if (err < 0) { if (err < 0) {
error("snd_ctl_hw_info error: %s", snd_strerror(err)); error("snd_ctl_info error: %s", snd_strerror(err));
goto _close; goto _close;
} }
id = snd_ctl_info_get_id(info);
err = snd_config_search(top, "state", &state); err = snd_config_search(top, "state", &state);
if (err == 0 && if (err == 0 &&
snd_config_type(state) != SND_CONFIG_TYPE_COMPOUND) { snd_config_type(state) != SND_CONFIG_TYPE_COMPOUND) {
@ -463,15 +450,15 @@ static int get_controls(int cardno, snd_config_t *top)
goto _close; goto _close;
} }
} }
err = snd_config_search(state, info.id, &card); err = snd_config_search(state, id, &card);
if (err == 0 && if (err == 0 &&
snd_config_type(state) != SND_CONFIG_TYPE_COMPOUND) { snd_config_type(state) != SND_CONFIG_TYPE_COMPOUND) {
error("config state.%s node is not a compound", info.id); error("config state.%s node is not a compound", id);
err = -EINVAL; err = -EINVAL;
goto _close; goto _close;
} }
if (err < 0) { if (err < 0) {
err = snd_config_compound_add(state, info.id, 0, &card); err = snd_config_compound_add(state, id, 0, &card);
if (err < 0) { if (err < 0) {
error("snd_config_compound_add: %s", snd_strerror(err)); error("snd_config_compound_add: %s", snd_strerror(err));
goto _close; goto _close;
@ -490,36 +477,37 @@ static int get_controls(int cardno, snd_config_t *top)
error("snd_config_compound_add: %s", snd_strerror(err)); error("snd_config_compound_add: %s", snd_strerror(err));
goto _close; goto _close;
} }
memset(&list, 0, sizeof(list)); err = snd_ctl_clist(handle, list);
err = snd_ctl_clist(handle, &list);
if (err < 0) { if (err < 0) {
error("Cannot determine controls: %s", snd_strerror(err)); error("Cannot determine controls: %s", snd_strerror(err));
goto _close; goto _close;
} }
if (list.controls <= 0) { count = snd_control_list_get_count(list);
if (count <= 0) {
err = 0; err = 0;
goto _close; goto _close;
} }
list.controls_request = list.controls; snd_control_list_set_offset(list, 0);
list.controls_offset = list.controls_count = 0; if (snd_control_list_alloc_space(list, count) < 0) {
list.pids = malloc(sizeof(snd_control_id_t) * list.controls_request);
if (!list.pids) {
error("No enough memory..."); error("No enough memory...");
goto _close; goto _close;
} }
if ((err = snd_ctl_clist(handle, &list)) < 0) { if ((err = snd_ctl_clist(handle, list)) < 0) {
error("Cannot determine controls (2): %s", snd_strerror(err)); error("Cannot determine controls (2): %s", snd_strerror(err));
goto _free; goto _free;
} }
for (idx = 0; idx < list.controls_count; ++idx) { for (idx = 0; idx < count; ++idx) {
err = get_control(handle, &list.pids[idx], control); snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_control_list_get_id(list, idx, id);
err = get_control(handle, id, control);
if (err < 0) if (err < 0)
goto _free; goto _free;
} }
err = 0; err = 0;
_free: _free:
free(list.pids); snd_control_list_free_space(list);
_close: _close:
snd_ctl_close(handle); snd_ctl_close(handle);
return err; return err;
@ -528,21 +516,9 @@ static int get_controls(int cardno, snd_config_t *top)
static int config_iface(snd_config_t *n) static int config_iface(snd_config_t *n)
{ {
static struct {
int val;
char *str;
} v[] = {
{ SND_CONTROL_IFACE_CARD, "card" },
{ SND_CONTROL_IFACE_HWDEP, "hwdep" },
{ SND_CONTROL_IFACE_MIXER, "mixer" },
{ SND_CONTROL_IFACE_PCM, "pcm" },
{ SND_CONTROL_IFACE_RAWMIDI, "rawmidi" },
{ SND_CONTROL_IFACE_TIMER, "timer" },
{ SND_CONTROL_IFACE_SEQUENCER, "sequencer" }
};
unsigned long i; unsigned long i;
unsigned int idx; snd_control_iface_t idx;
char *str; const char *str;
switch (snd_enum_to_int(snd_config_type(n))) { switch (snd_enum_to_int(snd_config_type(n))) {
case SND_CONFIG_TYPE_INTEGER: case SND_CONFIG_TYPE_INTEGER:
snd_config_integer_get(n, &i); snd_config_integer_get(n, &i);
@ -553,16 +529,16 @@ static int config_iface(snd_config_t *n)
default: default:
return -1; return -1;
} }
for (idx = 0; idx < sizeof(v) / sizeof(v[0]); ++idx) { for (idx = 0; idx <= SND_CONTROL_IFACE_LAST; snd_enum_incr(idx)) {
if (strcmp(v[idx].str, str) == 0) if (strcasecmp(snd_control_iface_name(idx), str) == 0)
return idx; return snd_enum_to_int(idx);
} }
return -1; return -1;
} }
static int config_bool(snd_config_t *n) static int config_bool(snd_config_t *n)
{ {
char *str; const char *str;
long val; long val;
switch (snd_enum_to_int(snd_config_type(n))) { switch (snd_enum_to_int(snd_config_type(n))) {
case SND_CONFIG_TYPE_INTEGER: case SND_CONFIG_TYPE_INTEGER:
@ -586,9 +562,9 @@ static int config_bool(snd_config_t *n)
static int config_enumerated(snd_config_t *n, snd_ctl_t *handle, static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
snd_control_info_t *info) snd_control_info_t *info)
{ {
char *str; const char *str;
long val; long val;
unsigned int idx; unsigned int idx, items;
switch (snd_enum_to_int(snd_config_type(n))) { switch (snd_enum_to_int(snd_config_type(n))) {
case SND_CONFIG_TYPE_INTEGER: case SND_CONFIG_TYPE_INTEGER:
snd_config_integer_get(n, &val); snd_config_integer_get(n, &val);
@ -599,15 +575,16 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
default: default:
return -1; return -1;
} }
for (idx = 0; idx < info->value.enumerated.items; idx++) { items = snd_control_info_get_items(info);
for (idx = 0; idx < items; idx++) {
int err; int err;
info->value.enumerated.item = idx; snd_control_info_set_item(info, idx);
err = snd_ctl_cinfo(handle, info); err = snd_ctl_cinfo(handle, info);
if (err < 0) { if (err < 0) {
error("snd_ctl_info: %s", snd_strerror(err)); error("snd_ctl_info: %s", snd_strerror(err));
return err; return err;
} }
if (strcmp(str, info->value.enumerated.name) == 0) if (strcmp(str, snd_control_info_get_name(info)) == 0)
return idx; return idx;
} }
return -1; return -1;
@ -615,20 +592,26 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
static int set_control(snd_ctl_t *handle, snd_config_t *control) static int set_control(snd_ctl_t *handle, snd_config_t *control)
{ {
snd_control_t ctl; snd_control_t *ctl;
snd_control_info_t info; snd_control_info_t *info;
snd_config_iterator_t i; snd_config_iterator_t i;
unsigned int numid1, iface1, device1, subdevice1, index1;
const char *name1;
unsigned int numid; unsigned int numid;
snd_control_type_t type;
unsigned int count;
long iface = -1; long iface = -1;
long device = -1; long device = -1;
long subdevice = -1; long subdevice = -1;
char *name = NULL; const char *name = NULL;
long index = -1; long index = -1;
snd_config_t *value = NULL; snd_config_t *value = NULL;
long val; long val;
unsigned int idx; unsigned int idx;
int err; int err;
char *set; char *set;
snd_control_alloca(&ctl);
snd_control_info_alloca(&info);
if (snd_config_type(control) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_type(control) != SND_CONFIG_TYPE_COMPOUND) {
error("control is not a compound"); error("control is not a compound");
return -EINVAL; return -EINVAL;
@ -695,63 +678,70 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
subdevice = 0; subdevice = 0;
if (index < 0) if (index < 0)
index = 0; index = 0;
memset(&info, 0, sizeof(info));
info.id.numid = numid; snd_control_info_set_numid(info, numid);
err = snd_ctl_cinfo(handle, &info); err = snd_ctl_cinfo(handle, info);
if (err < 0) { if (err < 0) {
if (iface >= 0 && name) { if (iface >= 0 && name) {
info.id.numid = 0; snd_control_info_set_numid(info, 0);
info.id.iface = iface; snd_control_info_set_interface(info, snd_int_to_enum(iface));
info.id.device = device; snd_control_info_set_device(info, device);
info.id.subdevice = subdevice; snd_control_info_set_subdevice(info, subdevice);
strncmp(info.id.name, name, sizeof(info.id.name)); snd_control_info_set_name(info, name);
info.id.index = index; snd_control_info_set_index(info, index);
err = snd_ctl_cinfo(handle, &info); err = snd_ctl_cinfo(handle, info);
} }
} }
if (err < 0) { if (err < 0) {
error("failed to obtain info for control #%d (%s)", numid, snd_strerror(err)); error("failed to obtain info for control #%d (%s)", numid, snd_strerror(err));
return -ENOENT; return -ENOENT;
} }
if (info.id.numid != numid) numid1 = snd_control_info_get_numid(info);
error("warning: numid mismatch (%d/%d) for control #%d", numid, info.id.numid, numid); iface1 = snd_enum_to_int(snd_control_info_get_interface(info));
if (info.id.iface != iface) device1 = snd_control_info_get_device(info);
error("warning: iface mismatch (%ld/%d) for control #%d", iface, info.id.iface, numid); subdevice1 = snd_control_info_get_subdevice(info);
if (info.id.device != device) name1 = snd_control_info_get_name(info);
error("warning: device mismatch (%ld/%d) for control #%d", device, info.id.device, numid); index1 = snd_control_info_get_index(info);
if (info.id.subdevice != subdevice) count = snd_control_info_get_count(info);
error("warning: subdevice mismatch (%ld/%d) for control #%d", subdevice, info.id.subdevice, numid); type = snd_control_info_get_type(info);
if (strcmp(info.id.name, name)) if (numid != numid1)
error("warning: name mismatch (%s/%s) for control #%d", name, info.id.name, numid); error("warning: numid mismatch (%d/%d) for control #%d",
if (info.id.index != index) numid, numid1, numid);
error("warning: index mismatch (%ld/%d) for control #%d", index, info.id.index, numid); if (iface != iface1)
error("warning: iface mismatch (%ld/%d) for control #%d", iface, iface1, numid);
if (device != device1)
error("warning: device mismatch (%ld/%d) for control #%d", device, device1, numid);
if (subdevice != subdevice1)
error("warning: subdevice mismatch (%ld/%d) for control #%d", subdevice, subdevice1, numid);
if (strcmp(name, name1))
error("warning: name mismatch (%s/%s) for control #%d", name, name1, numid);
if (index != index1)
error("warning: index mismatch (%ld/%d) for control #%d", index, index1, numid);
if (!(info.access & SND_CONTROL_ACCESS_WRITE)) if (!snd_control_info_is_writable(info))
return 0; return 0;
snd_control_set_numid(ctl, numid);
memset(&ctl, 0, sizeof(ctl)); if (count == 1) {
ctl.id = info.id; switch (snd_enum_to_int(type)) {
if (info.values_count == 1) {
switch (info.type) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
val = config_bool(value); val = config_bool(value);
if (val >= 0) { if (val >= 0) {
ctl.value.integer.value[0] = val; snd_control_set_boolean(ctl, 0, val);
goto _ok; goto _ok;
} }
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
err = snd_config_integer_get(value, &val); err = snd_config_integer_get(value, &val);
if (err == 0) { if (err == 0) {
ctl.value.integer.value[0] = val; snd_control_set_integer(ctl, 0, val);
goto _ok; goto _ok;
} }
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
val = config_enumerated(value, handle, &info); val = config_enumerated(value, handle, info);
if (val >= 0) { if (val >= 0) {
ctl.value.enumerated.item[0] = val; snd_control_set_enumerated(ctl, 0, val);
goto _ok; goto _ok;
} }
break; break;
@ -759,23 +749,23 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
case SND_CONTROL_TYPE_IEC958: case SND_CONTROL_TYPE_IEC958:
break; break;
default: default:
error("Unknow control type: %d", info.type); error("Unknow control type: %d", snd_enum_to_int(type));
return -EINVAL; return -EINVAL;
} }
} }
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BYTES: case SND_CONTROL_TYPE_BYTES:
case SND_CONTROL_TYPE_IEC958: case SND_CONTROL_TYPE_IEC958:
{ {
char *buf; const char *buf;
err = snd_config_string_get(value, &buf); err = snd_config_string_get(value, &buf);
if (err >= 0) { if (err >= 0) {
int c1 = 0; int c1 = 0;
int len = strlen(buf); int len = strlen(buf);
unsigned int idx = 0; unsigned int idx = 0;
int count = info.type == SND_CONTROL_TYPE_BYTES ? int size = type == SND_CONTROL_TYPE_BYTES ?
info.values_count : sizeof(snd_aes_iec958_t); count : sizeof(snd_aes_iec958_t);
if (count * 2 != len) { if (size * 2 != len) {
error("bad control.%d.value contents\n", numid); error("bad control.%d.value contents\n", numid);
return -EINVAL; return -EINVAL;
} }
@ -793,7 +783,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
} }
idx++; idx++;
if (idx % 2 == 0) if (idx % 2 == 0)
ctl.value.bytes.data[idx / 2] = c1 << 4 | c; snd_control_set_byte(ctl, idx / 2, c1 << 4 | c);
else else
c1 = c; c1 = c;
} }
@ -808,24 +798,24 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
return -EINVAL; return -EINVAL;
} }
set = alloca(info.values_count); set = alloca(count);
memset(set, 0, info.values_count); memset(set, 0, count);
snd_config_foreach(i, value) { snd_config_foreach(i, value) {
snd_config_t *n = snd_config_entry(i); snd_config_t *n = snd_config_entry(i);
idx = atoi(snd_config_id(n)); idx = atoi(snd_config_id(n));
if (idx < 0 || idx >= info.values_count || if (idx < 0 || idx >= count ||
set[idx]) { set[idx]) {
error("bad control.%d.value index", numid); error("bad control.%d.value index", numid);
return -EINVAL; return -EINVAL;
} }
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
val = config_bool(n); val = config_bool(n);
if (val < 0) { if (val < 0) {
error("bad control.%d.value.%d content", numid, idx); error("bad control.%d.value.%d content", numid, idx);
return -EINVAL; return -EINVAL;
} }
ctl.value.integer.value[idx] = val; snd_control_set_boolean(ctl, idx, val);
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
err = snd_config_integer_get(n, &val); err = snd_config_integer_get(n, &val);
@ -833,15 +823,15 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx); error("bad control.%d.value.%d content", numid, idx);
return -EINVAL; return -EINVAL;
} }
ctl.value.integer.value[idx] = val; snd_control_set_integer(ctl, idx, val);
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
val = config_enumerated(n, handle, &info); val = config_enumerated(n, handle, info);
if (val < 0) { if (val < 0) {
error("bad control.%d.value.%d content", numid, idx); error("bad control.%d.value.%d content", numid, idx);
return -EINVAL; return -EINVAL;
} }
ctl.value.enumerated.item[idx] = val; snd_control_set_enumerated(ctl, idx, val);
break; break;
case SND_CONTROL_TYPE_BYTES: case SND_CONTROL_TYPE_BYTES:
case SND_CONTROL_TYPE_IEC958: case SND_CONTROL_TYPE_IEC958:
@ -850,14 +840,14 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx); error("bad control.%d.value.%d content", numid, idx);
return -EINVAL; return -EINVAL;
} }
ctl.value.bytes.data[idx] = val; snd_control_set_byte(ctl, idx, val);
break; break;
default: default:
break; break;
} }
set[idx] = 1; set[idx] = 1;
} }
for (idx = 0; idx < info.values_count; ++idx) { for (idx = 0; idx < count; ++idx) {
if (!set[idx]) { if (!set[idx]) {
error("control.%d.value.%d is not specified", numid, idx); error("control.%d.value.%d is not specified", numid, idx);
return -EINVAL; return -EINVAL;
@ -865,9 +855,12 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
} }
_ok: _ok:
err = snd_ctl_cwrite(handle, &ctl); err = snd_ctl_cwrite(handle, ctl);
if (err < 0) { if (err < 0) {
error("Cannot write control '%s': %s", id_str(&ctl.id), snd_strerror(err)); snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_control_get_id(ctl, id);
error("Cannot write control '%s': %s", id_str(id), snd_strerror(err));
return err; return err;
} }
return 0; return 0;
@ -876,11 +869,13 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
static int set_controls(int card, snd_config_t *top) static int set_controls(int card, snd_config_t *top)
{ {
snd_ctl_t *handle; snd_ctl_t *handle;
snd_ctl_hw_info_t info; snd_ctl_info_t *info;
snd_config_t *control; snd_config_t *control;
snd_config_iterator_t i; snd_config_iterator_t i;
int err; int err;
char name[32]; char name[32];
const char *id;
snd_ctl_info_alloca(&info);
sprintf(name, "hw:%d", card); sprintf(name, "hw:%d", card);
err = snd_ctl_open(&handle, name); err = snd_ctl_open(&handle, name);
@ -888,19 +883,20 @@ static int set_controls(int card, snd_config_t *top)
error("snd_ctl_open error: %s", snd_strerror(err)); error("snd_ctl_open error: %s", snd_strerror(err));
return err; return err;
} }
err = snd_ctl_hw_info(handle, &info); err = snd_ctl_info(handle, info);
if (err < 0) { if (err < 0) {
error("snd_ctl_hw_info error: %s", snd_strerror(err)); error("snd_ctl_info error: %s", snd_strerror(err));
goto _close; goto _close;
} }
err = snd_config_searchv(top, &control, "state", info.id, "control", 0); id = snd_ctl_info_get_id(info);
err = snd_config_searchv(top, &control, "state", id, "control", 0);
if (err < 0) { if (err < 0) {
err = 0; err = 0;
fprintf(stderr, "No state is present for card %s\n", info.id); fprintf(stderr, "No state is present for card %s\n", id);
goto _close; goto _close;
} }
if (snd_config_type(control) != SND_CONFIG_TYPE_COMPOUND) { if (snd_config_type(control) != SND_CONFIG_TYPE_COMPOUND) {
error("state.%s.control is not a compound\n", info.id); error("state.%s.control is not a compound\n", id);
return -EINVAL; return -EINVAL;
} }
snd_config_foreach(i, control) { snd_config_foreach(i, control) {

View file

@ -1213,14 +1213,15 @@ mixer_show_procinfo (void)
static void static void
mixer_init (void) mixer_init (void)
{ {
snd_ctl_hw_info_t hw_info; snd_ctl_info_t *hw_info;
snd_ctl_t *ctl_handle; snd_ctl_t *ctl_handle;
int err; int err;
snd_ctl_info_alloca(&hw_info);
if ((err = snd_ctl_open (&ctl_handle, card_id)) < 0) if ((err = snd_ctl_open (&ctl_handle, card_id)) < 0)
mixer_abort (ERR_OPEN, "snd_ctl_open", err); mixer_abort (ERR_OPEN, "snd_ctl_open", err);
if ((err = snd_ctl_hw_info (ctl_handle, &hw_info)) < 0) if ((err = snd_ctl_info (ctl_handle, hw_info)) < 0)
mixer_abort (ERR_FCN, "snd_ctl_hw_info", err); mixer_abort (ERR_FCN, "snd_ctl_info", err);
snd_ctl_close (ctl_handle); snd_ctl_close (ctl_handle);
/* open mixer device /* open mixer device
*/ */
@ -1229,8 +1230,8 @@ mixer_init (void)
/* setup global variables /* setup global variables
*/ */
strcpy(mixer_card_name, hw_info.name); strcpy(mixer_card_name, snd_ctl_info_get_name(hw_info));
strcpy(mixer_device_name, hw_info.mixername); strcpy(mixer_device_name, snd_ctl_info_get_mixername(hw_info));
} }
static void static void

View file

@ -77,26 +77,28 @@ static int info(void)
int err; int err;
snd_ctl_t *handle; snd_ctl_t *handle;
snd_mixer_t *mhandle; snd_mixer_t *mhandle;
snd_ctl_hw_info_t info; snd_ctl_info_t *info;
snd_control_list_t clist; snd_control_list_t *clist;
snd_mixer_simple_control_list_t slist; snd_mixer_simple_control_list_t slist;
snd_ctl_info_alloca(&info);
snd_control_list_alloca(&clist);
if ((err = snd_ctl_open(&handle, card)) < 0) { if ((err = snd_ctl_open(&handle, card)) < 0) {
error("Control device %i open error: %s", card, snd_strerror(err)); error("Control device %i open error: %s", card, snd_strerror(err));
return err; return err;
} }
if ((err = snd_ctl_hw_info(handle, &info)) < 0) { if ((err = snd_ctl_info(handle, info)) < 0) {
error("Control device %i hw info error: %s", card, snd_strerror(err)); error("Control device %i hw info error: %s", card, snd_strerror(err));
return err; return err;
} }
printf("Card %s '%s'/'%s'\n", card, info.id, info.longname); printf("Card %s '%s'/'%s'\n", card, snd_ctl_info_get_id(info),
printf(" Mixer ID : '%s'\n", info.mixerid); snd_ctl_info_get_longname(info));
printf(" Mixer name : '%s'\n", info.mixername); printf(" Mixer ID : '%s'\n", snd_ctl_info_get_mixerid(info));
memset(&clist, 0, sizeof(clist)); printf(" Mixer name : '%s'\n", snd_ctl_info_get_mixername(info));
if ((err = snd_ctl_clist(handle, &clist)) < 0) { if ((err = snd_ctl_clist(handle, clist)) < 0) {
error("snd_ctl_clist failure: %s", snd_strerror(err)); error("snd_ctl_clist failure: %s", snd_strerror(err));
} else { } else {
printf(" Controls : %i\n", clist.controls); printf(" Controls : %i\n", snd_control_list_get_count(clist));
} }
snd_ctl_close(handle); snd_ctl_close(handle);
if ((err = snd_mixer_open(&mhandle, card)) < 0) { if ((err = snd_mixer_open(&mhandle, card)) < 0) {
@ -112,62 +114,26 @@ static int info(void)
return 0; return 0;
} }
static snd_control_id_t __control_id ATTRIBUTE_UNUSED; static const char *control_iface(snd_control_id_t *id)
#define control_name_size (sizeof(__control_id.name)+1)
static char *control_name(const char *name, char *result)
{ {
strncpy(result, name, control_name_size); return snd_control_iface_name(snd_control_id_get_interface(id));
result[control_name_size] = '\0';
return result;
} }
#define control_iface_size 16 static const char *control_type(snd_control_info_t *info)
static char *control_iface(snd_control_iface_t iface, char *result)
{ {
char *s; return snd_control_type_name(snd_control_info_get_type(info));
switch (iface) {
case SND_CONTROL_IFACE_CARD: s = "card"; break;
case SND_CONTROL_IFACE_HWDEP: s = "hwdep"; break;
case SND_CONTROL_IFACE_MIXER: s = "mixer"; break;
case SND_CONTROL_IFACE_PCM: s = "pcm"; break;
case SND_CONTROL_IFACE_RAWMIDI: s = "rawmidi"; break;
case SND_CONTROL_IFACE_TIMER: s = "timer"; break;
case SND_CONTROL_IFACE_SEQUENCER: s = "sequencer"; break;
default: s = "unknown"; break;
}
return strcpy(result, s);
} }
#define control_type_size 16 static const char *control_access(snd_control_info_t *info)
static char *control_type(snd_control_type_t type, char *result)
{
char *s;
switch (type) {
case SND_CONTROL_TYPE_NONE: s = "none"; break;
case SND_CONTROL_TYPE_BOOLEAN: s = "boolean"; break;
case SND_CONTROL_TYPE_INTEGER: s = "integer"; break;
case SND_CONTROL_TYPE_ENUMERATED: s = "enumerated"; break;
case SND_CONTROL_TYPE_BYTES: s = "bytes"; break;
default: s = "unknown"; break;
}
return strcpy(result, s);
}
#define control_access_size 32
static char *control_access(unsigned int access, char *result)
{ {
static char result[10];
char *res = result; char *res = result;
*res++ = (access & SND_CONTROL_ACCESS_READ) ? 'r' : '-'; *res++ = snd_control_info_is_readable(info) ? 'r' : '-';
*res++ = (access & SND_CONTROL_ACCESS_WRITE) ? 'w' : '-'; *res++ = snd_control_info_is_writable(info) ? 'w' : '-';
*res++ = (access & SND_CONTROL_ACCESS_INACTIVE) ? 'i' : '-'; *res++ = snd_control_info_is_inactive(info) ? 'i' : '-';
*res++ = (access & SND_CONTROL_ACCESS_LOCK) ? 'l' : '-'; *res++ = snd_control_info_is_volatile(info) ? 'v' : '-';
*res++ = snd_control_info_is_locked(info) ? 'l' : '-';
*res++ = '\0'; *res++ = '\0';
return result; return result;
} }
@ -329,80 +295,92 @@ static int get_volume_simple(char **ptr, int min, int max, int orig)
static void show_control_id(snd_control_id_t *id) static void show_control_id(snd_control_id_t *id)
{ {
char name[control_name_size]; unsigned int index, device, subdevice;
char iface[control_iface_size]; printf("numid=%u,iface=%s,name='%s'",
snd_control_id_get_numid(id),
printf("numid=%u,iface=%s,name='%s'", id->numid, control_iface(id->iface, iface), control_name(id->name, name)); control_iface(id),
if (id->index) snd_control_id_get_name(id));
printf(",index=%i", id->index); index = snd_control_id_get_index(id);
if (id->device) device = snd_control_id_get_device(id);
printf(",device=%i", id->device); subdevice = snd_control_id_get_subdevice(id);
if (id->subdevice) if (index)
printf(",subdevice=%i", id->subdevice); printf(",index=%i", index);
if (device)
printf(",device=%i", device);
if (subdevice)
printf(",subdevice=%i", subdevice);
} }
static int show_control(const char *space, snd_ctl_t *handle, snd_control_id_t *id, int level) static int show_control(const char *space, snd_ctl_t *handle, snd_control_id_t *id, int level)
{ {
int err; int err;
unsigned int item, idx; unsigned int item, idx;
snd_control_info_t info; snd_control_info_t *info;
snd_control_t control; snd_control_t *control;
char type[control_type_size]; unsigned int count;
char access[control_access_size]; snd_control_type_t type;
snd_control_info_alloca(&info);
memset(&info, 0, sizeof(info)); snd_control_alloca(&control);
info.id = *id; snd_control_info_set_id(info, id);
if ((err = snd_ctl_cinfo(handle, &info)) < 0) { if ((err = snd_ctl_cinfo(handle, info)) < 0) {
error("Control %s cinfo error: %s\n", card, snd_strerror(err)); error("Control %s cinfo error: %s\n", card, snd_strerror(err));
return err; return err;
} }
if (level & 2) { if (level & 2) {
show_control_id(&info.id); snd_control_info_get_id(info, id);
show_control_id(id);
printf("\n"); printf("\n");
} }
printf("%s; type=%s,access=%s,values=%i", space, control_type(info.type, type), control_access(info.access, access), info.values_count); count = snd_control_info_get_count(info);
switch (info.type) { type = snd_control_info_get_type(info);
printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count);
switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
printf(",min=%li,max=%li,step=%li\n", info.value.integer.min, info.value.integer.max, info.value.integer.step); printf(",min=%li,max=%li,step=%li\n",
snd_control_info_get_min(info),
snd_control_info_get_max(info),
snd_control_info_get_step(info));
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
printf(",items=%u\n", info.value.enumerated.items); {
for (item = 0; item < info.value.enumerated.items; item++) { unsigned int items = snd_control_info_get_items(info);
info.value.enumerated.item = item; printf(",items=%u\n", items);
if ((err = snd_ctl_cinfo(handle, &info)) < 0) { for (item = 0; item < items; item++) {
snd_control_info_set_item(info, item);
if ((err = snd_ctl_cinfo(handle, info)) < 0) {
error("Control %s cinfo error: %s\n", card, snd_strerror(err)); error("Control %s cinfo error: %s\n", card, snd_strerror(err));
return err; return err;
} }
printf("%s; Item #%u '%s'\n", space, item, info.value.enumerated.name); printf("%s; Item #%u '%s'\n", space, item, snd_control_info_get_item_name(info));
} }
break; break;
}
default: default:
printf("\n"); printf("\n");
break; break;
} }
if (level & 1) { if (level & 1) {
memset(&control, 0, sizeof(control)); snd_control_set_id(control, id);
control.id = *id; if ((err = snd_ctl_cread(handle, control)) < 0) {
if ((err = snd_ctl_cread(handle, &control)) < 0) {
error("Control %s cread error: %s\n", card, snd_strerror(err)); error("Control %s cread error: %s\n", card, snd_strerror(err));
return err; return err;
} }
printf("%s: values=", space); printf("%s: values=", space);
for (idx = 0; idx < info.values_count; idx++) { for (idx = 0; idx < count; idx++) {
if (idx > 0) if (idx > 0)
printf(","); printf(",");
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
printf("%s", control.value.integer.value[idx] ? "on" : "off"); printf("%s", snd_control_get_boolean(control, idx) ? "on" : "off");
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
printf("%li", control.value.integer.value[idx]); printf("%li", snd_control_get_integer(control, idx));
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
printf("%u", control.value.enumerated.item[idx]); printf("%u", snd_control_get_enumerated(control, idx));
break; break;
case SND_CONTROL_TYPE_BYTES: case SND_CONTROL_TYPE_BYTES:
printf("0x%02x", control.value.bytes.data[idx]); printf("0x%02x", snd_control_get_byte(control, idx));
break; break;
default: default:
printf("?"); printf("?");
@ -419,7 +397,11 @@ static int controls(int level)
int err; int err;
unsigned int idx; unsigned int idx;
snd_ctl_t *handle; snd_ctl_t *handle;
snd_hcontrol_list_t list; unsigned int count;
snd_hcontrol_list_t *list;
snd_control_id_t *id;
snd_hcontrol_list_alloca(&list);
snd_control_id_alloca(&id);
if ((err = snd_ctl_open(&handle, card)) < 0) { if ((err = snd_ctl_open(&handle, card)) < 0) {
error("Control %s open error: %s", card, snd_strerror(err)); error("Control %s open error: %s", card, snd_strerror(err));
@ -429,28 +411,28 @@ static int controls(int level)
error("Control %s hbuild error: %s\n", card, snd_strerror(err)); error("Control %s hbuild error: %s\n", card, snd_strerror(err));
return err; return err;
} }
memset(&list, 0, sizeof(list)); if ((err = snd_ctl_hlist(handle, list)) < 0) {
if ((err = snd_ctl_hlist(handle, &list)) < 0) {
error("Control %s clist error: %s", card, snd_strerror(err)); error("Control %s clist error: %s", card, snd_strerror(err));
return err; return err;
} }
list.pids = (snd_control_id_t *)malloc(list.controls * sizeof(snd_control_id_t)); count = snd_hcontrol_list_get_count(list);
if (list.pids == NULL) { snd_hcontrol_list_set_offset(list, 0);
if (snd_hcontrol_list_alloc_space(list, count) < 0) {
error("Not enough memory"); error("Not enough memory");
return -ENOMEM; return -ENOMEM;
} }
list.controls_request = list.controls; if ((err = snd_ctl_hlist(handle, list)) < 0) {
if ((err = snd_ctl_hlist(handle, &list)) < 0) {
error("Control %s hlist error: %s", card, snd_strerror(err)); error("Control %s hlist error: %s", card, snd_strerror(err));
return err; return err;
} }
for (idx = 0; idx < list.controls; idx++) { for (idx = 0; idx < count; idx++) {
show_control_id(list.pids + idx); snd_hcontrol_list_get_id(list, idx, id);
show_control_id(id);
printf("\n"); printf("\n");
if (level > 0) if (level > 0)
show_control(" ", handle, list.pids + idx, 1); show_control(" ", handle, id, 1);
} }
free(list.pids); snd_hcontrol_list_free_space(list);
snd_ctl_close(handle); snd_ctl_close(handle);
return 0; return 0;
} }
@ -566,44 +548,45 @@ static int parse_control_id(const char *str, snd_control_id_t *id)
str++; str++;
if (!(*str)) if (!(*str))
return -EINVAL; return -EINVAL;
memset(id, 0, sizeof(*id)); snd_control_id_set_interface(id, SND_CONTROL_IFACE_MIXER); /* default */
id->iface = SND_CONTROL_IFACE_MIXER; /* default */
while (*str) { while (*str) {
if (!strncasecmp(str, "numid=", 6)) { if (!strncasecmp(str, "numid=", 6)) {
id->numid = atoi(str += 6); str += 6;
snd_control_id_set_numid(id, atoi(str));
while (isdigit(*str)) while (isdigit(*str))
str++; str++;
} else if (!strncasecmp(str, "iface=", 6)) { } else if (!strncasecmp(str, "iface=", 6)) {
str += 6; str += 6;
if (!strncasecmp(str, "card", 4)) { if (!strncasecmp(str, "card", 4)) {
id->iface = SND_CONTROL_IFACE_CARD; snd_control_id_set_interface(id, SND_CONTROL_IFACE_CARD);
str += 4; str += 4;
} else if (!strncasecmp(str, "mixer", 5)) { } else if (!strncasecmp(str, "mixer", 5)) {
id->iface = SND_CONTROL_IFACE_MIXER; snd_control_id_set_interface(id, SND_CONTROL_IFACE_MIXER);
str += 5; str += 5;
} else if (!strncasecmp(str, "pcm", 3)) { } else if (!strncasecmp(str, "pcm", 3)) {
id->iface = SND_CONTROL_IFACE_PCM; snd_control_id_set_interface(id, SND_CONTROL_IFACE_PCM);
str += 3; str += 3;
} else if (!strncasecmp(str, "rawmidi", 7)) { } else if (!strncasecmp(str, "rawmidi", 7)) {
id->iface = SND_CONTROL_IFACE_RAWMIDI; snd_control_id_set_interface(id, SND_CONTROL_IFACE_RAWMIDI);
str += 7; str += 7;
} else if (!strncasecmp(str, "timer", 5)) { } else if (!strncasecmp(str, "timer", 5)) {
id->iface = SND_CONTROL_IFACE_TIMER; snd_control_id_set_interface(id, SND_CONTROL_IFACE_TIMER);
str += 5; str += 5;
} else if (!strncasecmp(str, "sequencer", 9)) { } else if (!strncasecmp(str, "sequencer", 9)) {
id->iface = SND_CONTROL_IFACE_SEQUENCER; snd_control_id_set_interface(id, SND_CONTROL_IFACE_SEQUENCER);
str += 9; str += 9;
} else { } else {
return -EINVAL; return -EINVAL;
} }
} else if (!strncasecmp(str, "name=", 5)) { } else if (!strncasecmp(str, "name=", 5)) {
char buf[64];
str += 5; str += 5;
ptr = id->name; ptr = buf;
size = 0; size = 0;
if (*str == '\'' || *str == '\"') { if (*str == '\'' || *str == '\"') {
c = *str++; c = *str++;
while (*str && *str != c) { while (*str && *str != c) {
if (size < sizeof(id->name)) { if (size < sizeof(buf)) {
*ptr++ = *str; *ptr++ = *str;
size++; size++;
} }
@ -613,7 +596,7 @@ static int parse_control_id(const char *str, snd_control_id_t *id)
str++; str++;
} else { } else {
while (*str && *str != ',') { while (*str && *str != ',') {
if (size < sizeof(id->name)) { if (size < sizeof(buf)) {
*ptr++ = *str; *ptr++ = *str;
size++; size++;
} }
@ -621,16 +604,20 @@ static int parse_control_id(const char *str, snd_control_id_t *id)
} }
*ptr = '\0'; *ptr = '\0';
} }
snd_control_id_set_name(id, buf);
} else if (!strncasecmp(str, "index=", 6)) { } else if (!strncasecmp(str, "index=", 6)) {
id->index = atoi(str += 6); str += 6;
snd_control_id_set_index(id, atoi(str));
while (isdigit(*str)) while (isdigit(*str))
str++; str++;
} else if (!strncasecmp(str, "device=", 7)) { } else if (!strncasecmp(str, "device=", 7)) {
id->device = atoi(str += 7); str += 7;
snd_control_id_set_device(id, atoi(str));
while (isdigit(*str)) while (isdigit(*str))
str++; str++;
} else if (!strncasecmp(str, "subdevice=", 10)) { } else if (!strncasecmp(str, "subdevice=", 10)) {
id->subdevice = atoi(str += 10); str += 10;
snd_control_id_set_subdevice(id, atoi(str));
while (isdigit(*str)) while (isdigit(*str))
str++; str++;
} }
@ -691,42 +678,47 @@ static int cset(int argc, char *argv[], int roflag)
{ {
int err; int err;
snd_ctl_t *handle; snd_ctl_t *handle;
snd_control_info_t info; snd_control_info_t *info;
snd_control_id_t id; snd_control_id_t *id;
snd_control_t control; snd_control_t *control;
char *ptr; char *ptr;
unsigned int idx; unsigned int idx, count;
long tmp; long tmp;
snd_control_type_t type;
snd_control_info_alloca(&info);
snd_control_id_alloca(&id);
snd_control_alloca(&control);
if (argc < 1) { if (argc < 1) {
fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n"); fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n");
return -EINVAL; return -EINVAL;
} }
if (parse_control_id(argv[0], &id)) { if (parse_control_id(argv[0], id)) {
fprintf(stderr, "Wrong control identifier: %s\n", argv[0]); fprintf(stderr, "Wrong control identifier: %s\n", argv[0]);
return -EINVAL; return -EINVAL;
} }
if (debugflag) { if (debugflag) {
printf("VERIFY ID: "); printf("VERIFY ID: ");
show_control_id(&id); show_control_id(id);
printf("\n"); printf("\n");
} }
if ((err = snd_ctl_open(&handle, card)) < 0) { if ((err = snd_ctl_open(&handle, card)) < 0) {
error("Control %s open error: %s\n", card, snd_strerror(err)); error("Control %s open error: %s\n", card, snd_strerror(err));
return err; return err;
} }
memset(&info, 0, sizeof(info)); snd_control_info_set_id(info, id);
memset(&control, 0, sizeof(control)); if ((err = snd_ctl_cinfo(handle, info)) < 0) {
info.id = id;
control.id = id;
if ((err = snd_ctl_cinfo(handle, &info)) < 0) {
error("Control %s cinfo error: %s\n", card, snd_strerror(err)); error("Control %s cinfo error: %s\n", card, snd_strerror(err));
return err; return err;
} }
type = snd_control_info_get_type(info);
count = snd_control_info_get_count(info);
snd_control_set_id(control, id);
if (!roflag) { if (!roflag) {
ptr = argv[1]; ptr = argv[1];
for (idx = 0; idx < info.values_count && idx < 128 && *ptr; idx++) { for (idx = 0; idx < count && idx < 128 && *ptr; idx++) {
switch (info.type) { switch (snd_enum_to_int(type)) {
case SND_CONTROL_TYPE_BOOLEAN: case SND_CONTROL_TYPE_BOOLEAN:
tmp = 0; tmp = 0;
if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) { if (!strncasecmp(ptr, "on", 2) || !strncasecmp(ptr, "up", 2)) {
@ -740,21 +732,21 @@ static int cset(int argc, char *argv[], int roflag)
while (isdigit(*ptr)) while (isdigit(*ptr))
ptr++; ptr++;
} }
control.value.integer.value[idx] = tmp; snd_control_set_boolean(control, idx, tmp);
break; break;
case SND_CONTROL_TYPE_INTEGER: case SND_CONTROL_TYPE_INTEGER:
tmp = get_integer(&ptr, tmp = get_integer(&ptr,
info.value.integer.min, snd_control_info_get_min(info),
info.value.integer.max); snd_control_info_get_max(info));
control.value.integer.value[idx] = tmp; snd_control_set_integer(control, idx, tmp);
break; break;
case SND_CONTROL_TYPE_ENUMERATED: case SND_CONTROL_TYPE_ENUMERATED:
tmp = get_integer(&ptr, 0, info.value.enumerated.items - 1); tmp = get_integer(&ptr, 0, snd_control_info_get_items(info) - 1);
control.value.enumerated.item[idx] = tmp; snd_control_set_enumerated(control, idx, tmp);
break; break;
case SND_CONTROL_TYPE_BYTES: case SND_CONTROL_TYPE_BYTES:
tmp = get_integer(&ptr, 0, info.value.enumerated.items - 1); tmp = get_integer(&ptr, 0, 255);
control.value.bytes.data[idx] = tmp; snd_control_set_byte(control, idx, tmp);
break; break;
default: default:
break; break;
@ -764,13 +756,13 @@ static int cset(int argc, char *argv[], int roflag)
else if (*ptr == ',') else if (*ptr == ',')
ptr++; ptr++;
} }
if ((err = snd_ctl_cwrite(handle, &control)) < 0) { if ((err = snd_ctl_cwrite(handle, control)) < 0) {
error("Control %s cwrite error: %s\n", card, snd_strerror(err)); error("Control %s cwrite error: %s\n", card, snd_strerror(err));
return err; return err;
} }
} }
if (!quiet) if (!quiet)
show_control(" ", handle, &id, 3); show_control(" ", handle, id, 3);
snd_ctl_close(handle); snd_ctl_close(handle);
return 0; return 0;
} }
@ -902,22 +894,31 @@ static int sset(unsigned int argc, char *argv[], int roflag)
static void events_change(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol) static void events_change(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol)
{ {
snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_hcontrol_get_id(hcontrol, id);
printf("event change: "); printf("event change: ");
show_control_id(&hcontrol->id); show_control_id(id);
printf("\n"); printf("\n");
} }
static void events_value(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol) static void events_value(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol)
{ {
snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_hcontrol_get_id(hcontrol, id);
printf("event value: "); printf("event value: ");
show_control_id(&hcontrol->id); show_control_id(id);
printf("\n"); printf("\n");
} }
static void events_remove(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol) static void events_remove(snd_ctl_t *handle ATTRIBUTE_UNUSED, snd_hcontrol_t *hcontrol)
{ {
snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_hcontrol_get_id(hcontrol, id);
printf("event remove: "); printf("event remove: ");
show_control_id(&hcontrol->id); show_control_id(id);
printf("\n"); printf("\n");
} }
@ -929,13 +930,16 @@ static void events_rebuild(snd_ctl_t *handle ATTRIBUTE_UNUSED, void *private_dat
static void events_add(snd_ctl_t *handle ATTRIBUTE_UNUSED, void *private_data, snd_hcontrol_t *hcontrol) static void events_add(snd_ctl_t *handle ATTRIBUTE_UNUSED, void *private_data, snd_hcontrol_t *hcontrol)
{ {
snd_control_id_t *id;
snd_control_id_alloca(&id);
snd_hcontrol_get_id(hcontrol, id);
assert(private_data != (void *)1); assert(private_data != (void *)1);
printf("event add: "); printf("event add: ");
show_control_id(&hcontrol->id); show_control_id(id);
printf("\n"); printf("\n");
hcontrol->event_change = events_change; snd_hcontrol_set_callback_change(hcontrol, events_change);
hcontrol->event_value = events_value; snd_hcontrol_set_callback_value(hcontrol, events_value);
hcontrol->event_remove = events_remove; snd_hcontrol_set_callback_remove(hcontrol, events_remove);
} }
static int events(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED) static int events(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
@ -961,9 +965,9 @@ static int events(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
return err; return err;
} }
for (hcontrol = snd_ctl_hfirst(handle); hcontrol; hcontrol = snd_ctl_hnext(handle, hcontrol)) { for (hcontrol = snd_ctl_hfirst(handle); hcontrol; hcontrol = snd_ctl_hnext(handle, hcontrol)) {
hcontrol->event_change = events_change; snd_hcontrol_set_callback_change(hcontrol, events_change);
hcontrol->event_value = events_value; snd_hcontrol_set_callback_value(hcontrol, events_value);
hcontrol->event_remove = events_remove; snd_hcontrol_set_callback_remove(hcontrol, events_remove);
} }
printf("Ready to listen...\n"); printf("Ready to listen...\n");
while (1) { while (1) {

View file

@ -83,8 +83,8 @@ static int verbose = 0;
static int buffer_pos = 0; static int buffer_pos = 0;
static size_t bits_per_sample, bits_per_frame; static size_t bits_per_sample, bits_per_frame;
static size_t chunk_bytes; static size_t chunk_bytes;
static int digtype = SND_CONTROL_TYPE_NONE; static snd_control_type_t digtype = SND_CONTROL_TYPE_NONE;
static snd_digital_audio_t diga; static snd_aes_iec958_t spdif;
static snd_output_t *log; static snd_output_t *log;
static int count; static int count;
@ -173,8 +173,9 @@ static void device_list(void)
{ {
snd_ctl_t *handle; snd_ctl_t *handle;
int card, err, dev, idx; int card, err, dev, idx;
snd_ctl_hw_info_t info; snd_ctl_info_t *info;
snd_pcm_info_t *pcminfo; snd_pcm_info_t *pcminfo;
snd_ctl_info_alloca(&info);
snd_pcm_info_alloca(&pcminfo); snd_pcm_info_alloca(&pcminfo);
card = -1; card = -1;
@ -189,7 +190,7 @@ static void device_list(void)
error("control open (%i): %s", card, snd_strerror(err)); error("control open (%i): %s", card, snd_strerror(err));
continue; continue;
} }
if ((err = snd_ctl_hw_info(handle, &info)) < 0) { if ((err = snd_ctl_info(handle, info)) < 0) {
error("control hardware info (%i): %s", card, snd_strerror(err)); error("control hardware info (%i): %s", card, snd_strerror(err));
snd_ctl_close(handle); snd_ctl_close(handle);
continue; continue;
@ -210,7 +211,7 @@ static void device_list(void)
continue; continue;
} }
fprintf(stderr, "card %i: %s [%s], device %i: %s [%s]\n", fprintf(stderr, "card %i: %s [%s], device %i: %s [%s]\n",
card, info.id, info.name, card, snd_ctl_info_get_id(info), snd_ctl_info_get_name(info),
dev, dev,
snd_pcm_info_get_id(pcminfo), snd_pcm_info_get_id(pcminfo),
snd_pcm_info_get_name(pcminfo)); snd_pcm_info_get_name(pcminfo));
@ -312,7 +313,7 @@ int main(int argc, char *argv[])
rhwparams.format = SND_PCM_FORMAT_U8; rhwparams.format = SND_PCM_FORMAT_U8;
rhwparams.rate = DEFAULT_SPEED; rhwparams.rate = DEFAULT_SPEED;
rhwparams.channels = 1; rhwparams.channels = 1;
memset(&diga, 0, sizeof(diga)); memset(&spdif, 0, sizeof(spdif));
while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {
switch (c) { switch (c) {
@ -410,23 +411,23 @@ int main(int argc, char *argv[])
break; break;
case 'C': case 'C':
digtype = SND_CONTROL_TYPE_IEC958; digtype = SND_CONTROL_TYPE_IEC958;
diga.aes.status[0] = IEC958_AES0_NONAUDIO | spdif.status[0] = IEC958_AES0_NONAUDIO |
IEC958_AES0_CON_EMPHASIS_NONE; IEC958_AES0_CON_EMPHASIS_NONE;
diga.aes.status[1] = IEC958_AES1_CON_ORIGINAL | spdif.status[1] = IEC958_AES1_CON_ORIGINAL |
IEC958_AES1_CON_PCM_CODER; IEC958_AES1_CON_PCM_CODER;
diga.aes.status[2] = 0; spdif.status[2] = 0;
diga.aes.status[3] = IEC958_AES3_CON_FS_48000; spdif.status[3] = IEC958_AES3_CON_FS_48000;
break; break;
case 'P': case 'P':
digtype = SND_CONTROL_TYPE_IEC958; digtype = SND_CONTROL_TYPE_IEC958;
diga.aes.status[0] = IEC958_AES0_PROFESSIONAL | spdif.status[0] = IEC958_AES0_PROFESSIONAL |
IEC958_AES0_NONAUDIO | IEC958_AES0_NONAUDIO |
IEC958_AES0_PRO_EMPHASIS_NONE | IEC958_AES0_PRO_EMPHASIS_NONE |
IEC958_AES0_PRO_FS_48000; IEC958_AES0_PRO_FS_48000;
diga.aes.status[1] = IEC958_AES1_PRO_MODE_NOTID | spdif.status[1] = IEC958_AES1_PRO_MODE_NOTID |
IEC958_AES1_PRO_USERBITS_NOTID; IEC958_AES1_PRO_USERBITS_NOTID;
diga.aes.status[2] = IEC958_AES2_PRO_WORDLEN_NOTID; spdif.status[2] = IEC958_AES2_PRO_WORDLEN_NOTID;
diga.aes.status[3] = 0; spdif.status[3] = 0;
break; break;
default: default:
fprintf(stderr, "Try `%s --help' for more information.\n", command); fprintf(stderr, "Try `%s --help' for more information.\n", command);
@ -447,16 +448,16 @@ int main(int argc, char *argv[])
} }
if (digtype != SND_CONTROL_TYPE_NONE) { if (digtype != SND_CONTROL_TYPE_NONE) {
snd_control_t ctl; snd_control_t *ctl;
snd_ctl_t *ctl_handle; snd_ctl_t *ctl_handle;
char ctl_name[12]; char ctl_name[12];
int ctl_card; int ctl_card;
memset(&ctl, 0, sizeof(ctl)); snd_control_alloca(&ctl);
ctl.id.numid = 0; snd_control_set_interface(ctl, SND_CONTROL_IFACE_PCM);
ctl.id.iface = SND_CONTROL_IFACE_PCM; snd_control_set_device(ctl, snd_pcm_info_get_device(info));
ctl.id.device = snd_pcm_info_get_device(info); snd_control_set_subdevice(ctl, snd_pcm_info_get_subdevice(info));
ctl.id.subdevice = snd_pcm_info_get_subdevice(info); snd_control_set_name(ctl, "IEC958 (S/PDIF) Stream");
strcpy(ctl.id.name, "IEC958 (S/PDIF) Stream"); snd_control_set_iec958(ctl, &spdif);
ctl_card = snd_pcm_info_get_card(info); ctl_card = snd_pcm_info_get_card(info);
if (ctl_card < 0) { if (ctl_card < 0) {
error("Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card"); error("Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card");
@ -467,7 +468,7 @@ int main(int argc, char *argv[])
error("Unable to open the control interface '%s': %s", ctl_name, snd_strerror(err)); error("Unable to open the control interface '%s': %s", ctl_name, snd_strerror(err));
goto __diga_end; goto __diga_end;
} }
if ((err = snd_ctl_cwrite(ctl_handle, &ctl)) < 0) { if ((err = snd_ctl_cwrite(ctl_handle, ctl)) < 0) {
error("Unable to update the IEC958 control: %s", snd_strerror(err)); error("Unable to update the IEC958 control: %s", snd_strerror(err));
goto __diga_end; goto __diga_end;
} }
@ -736,31 +737,30 @@ static void set_params(void)
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
err = snd_pcm_hw_params_set_access_mask(handle, params, err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
SND_CHANGE, mask);
} else if (interleaved) } else if (interleaved)
err = snd_pcm_hw_params_set_access(handle, params, SND_CHANGE, err = snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED); SND_PCM_ACCESS_RW_INTERLEAVED);
else else
err = snd_pcm_hw_params_set_access(handle, params, SND_CHANGE, err = snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_NONINTERLEAVED); SND_PCM_ACCESS_RW_NONINTERLEAVED);
if (err < 0) { if (err < 0) {
error("Access type not available"); error("Access type not available");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
err = snd_pcm_hw_params_set_format(handle, params, SND_CHANGE, hwparams.format); err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
if (err < 0) { if (err < 0) {
error("Sample format non available"); error("Sample format non available");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
err = snd_pcm_hw_params_set_channels(handle, params, SND_CHANGE, hwparams.channels); err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
if (err < 0) { if (err < 0) {
error("Channels count non available"); error("Channels count non available");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#if 0 #if 0
err = snd_pcm_hw_params_set_periods_min(handle, params, SND_CHANGE, 2); err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
assert(err >= 0); assert(err >= 0);
#endif #endif
err = snd_pcm_hw_params_set_rate_near(handle, params, hwparams.rate, 0); err = snd_pcm_hw_params_set_rate_near(handle, params, hwparams.rate, 0);