Completed mixer API. Improved iterators. Renamed control values struct. Rewritten simple elements implementation

This commit is contained in:
Abramo Bagnara 2001-02-11 15:45:44 +00:00
parent 7346943471
commit fbec0a5f8d
4 changed files with 248 additions and 173 deletions

View file

@ -142,7 +142,7 @@ static int snd_config_compound_add(snd_config_t *father, const char *id, int joi
static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *top)
{
snd_ctl_elem_t *ctl;
snd_ctl_elem_value_t *ctl;
snd_ctl_elem_info_t *info;
snd_config_t *control, *comment, *item, *value;
const char *s;
@ -153,7 +153,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
const char *name;
snd_ctl_elem_type_t type;
unsigned int count;
snd_ctl_elem_alloca(&ctl);
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);
@ -164,7 +164,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
if (!snd_ctl_elem_info_is_readable(info))
return 0;
snd_ctl_elem_set_id(ctl, id);
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));
@ -303,7 +303,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
char buf[size * 2 + 1];
char *p = buf;
char *hex = "0123456789abcdef";
const unsigned char *bytes = snd_ctl_elem_get_bytes(ctl);
const unsigned char *bytes = snd_ctl_elem_value_get_bytes(ctl);
for (idx = 0; idx < size; idx++) {
int v = bytes[idx];
*p++ = hex[v >> 4];
@ -324,14 +324,14 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
if (count == 1) {
switch (snd_enum_to_int(type)) {
case SND_CTL_ELEM_TYPE_BOOLEAN:
err = snd_config_string_add(control, "value", snd_ctl_elem_get_boolean(ctl, 0) ? "true" : "false");
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_get_integer(ctl, 0));
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;
@ -339,7 +339,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
return 0;
case SND_CTL_ELEM_TYPE_ENUMERATED:
{
unsigned int v = snd_ctl_elem_get_enumerated(ctl, 0);
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) {
@ -368,7 +368,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
switch (snd_enum_to_int(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_get_boolean(ctl, idx) ? "true" : "false");
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;
@ -377,7 +377,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
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_get_integer(ctl, 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;
@ -386,7 +386,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
for (idx = 0; idx < count; idx++) {
unsigned int v = snd_ctl_elem_get_enumerated(ctl, 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) {
@ -592,9 +592,9 @@ static int config_enumerated(snd_config_t *n, snd_ctl_t *handle,
static int set_control(snd_ctl_t *handle, snd_config_t *control)
{
snd_ctl_elem_t *ctl;
snd_ctl_elem_value_t *ctl;
snd_ctl_elem_info_t *info;
snd_config_iterator_t i;
snd_config_iterator_t i, next;
unsigned int numid1, iface1, device1, subdevice1, index1;
const char *name1;
unsigned int numid;
@ -610,16 +610,16 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
unsigned int idx;
int err;
char *set;
snd_ctl_elem_alloca(&ctl);
snd_ctl_elem_value_alloca(&ctl);
snd_ctl_elem_info_alloca(&info);
if (snd_config_get_type(control) != SND_CONFIG_TYPE_COMPOUND) {
error("control is not a compound");
return -EINVAL;
}
numid = atoi(snd_config_get_id(control));
snd_config_foreach(i, control) {
snd_config_for_each(i, next, control) {
snd_config_t *n = snd_config_iterator_entry(i);
char *fld = snd_config_get_id(n);
const char *fld = snd_config_get_id(n);
if (strcmp(fld, "comment") == 0)
continue;
if (strcmp(fld, "iface") == 0) {
@ -720,28 +720,28 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
if (!snd_ctl_elem_info_is_writable(info))
return 0;
snd_ctl_elem_set_numid(ctl, numid);
snd_ctl_elem_value_set_numid(ctl, numid);
if (count == 1) {
switch (snd_enum_to_int(type)) {
case SND_CTL_ELEM_TYPE_BOOLEAN:
val = config_bool(value);
if (val >= 0) {
snd_ctl_elem_set_boolean(ctl, 0, val);
snd_ctl_elem_value_set_boolean(ctl, 0, val);
goto _ok;
}
break;
case SND_CTL_ELEM_TYPE_INTEGER:
err = snd_config_get_integer(value, &val);
if (err == 0) {
snd_ctl_elem_set_integer(ctl, 0, val);
snd_ctl_elem_value_set_integer(ctl, 0, val);
goto _ok;
}
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
val = config_enumerated(value, handle, info);
if (val >= 0) {
snd_ctl_elem_set_enumerated(ctl, 0, val);
snd_ctl_elem_value_set_enumerated(ctl, 0, val);
goto _ok;
}
break;
@ -783,7 +783,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
}
idx++;
if (idx % 2 == 0)
snd_ctl_elem_set_byte(ctl, idx / 2, c1 << 4 | c);
snd_ctl_elem_value_set_byte(ctl, idx / 2, c1 << 4 | c);
else
c1 = c;
}
@ -800,7 +800,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
set = alloca(count);
memset(set, 0, count);
snd_config_foreach(i, value) {
snd_config_for_each(i, next, value) {
snd_config_t *n = snd_config_iterator_entry(i);
idx = atoi(snd_config_get_id(n));
if (idx < 0 || idx >= count ||
@ -815,7 +815,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx);
return -EINVAL;
}
snd_ctl_elem_set_boolean(ctl, idx, val);
snd_ctl_elem_value_set_boolean(ctl, idx, val);
break;
case SND_CTL_ELEM_TYPE_INTEGER:
err = snd_config_get_integer(n, &val);
@ -823,7 +823,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx);
return -EINVAL;
}
snd_ctl_elem_set_integer(ctl, idx, val);
snd_ctl_elem_value_set_integer(ctl, idx, val);
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
val = config_enumerated(n, handle, info);
@ -831,7 +831,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx);
return -EINVAL;
}
snd_ctl_elem_set_enumerated(ctl, idx, val);
snd_ctl_elem_value_set_enumerated(ctl, idx, val);
break;
case SND_CTL_ELEM_TYPE_BYTES:
case SND_CTL_ELEM_TYPE_IEC958:
@ -840,7 +840,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
error("bad control.%d.value.%d content", numid, idx);
return -EINVAL;
}
snd_ctl_elem_set_byte(ctl, idx, val);
snd_ctl_elem_value_set_byte(ctl, idx, val);
break;
default:
break;
@ -859,7 +859,7 @@ static int set_control(snd_ctl_t *handle, snd_config_t *control)
if (err < 0) {
snd_ctl_elem_id_t *id;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_get_id(ctl, id);
snd_ctl_elem_value_get_id(ctl, id);
error("Cannot write control '%s': %s", id_str(id), snd_strerror(err));
return err;
}
@ -871,7 +871,7 @@ static int set_controls(int card, snd_config_t *top)
snd_ctl_t *handle;
snd_ctl_card_info_t *info;
snd_config_t *control;
snd_config_iterator_t i;
snd_config_iterator_t i, next;
int err;
char name[32];
const char *id;
@ -899,7 +899,7 @@ static int set_controls(int card, snd_config_t *top)
error("state.%s.control is not a compound\n", id);
return -EINVAL;
}
snd_config_foreach(i, control) {
snd_config_for_each(i, next, control) {
snd_config_t *n = snd_config_iterator_entry(i);
err = set_control(handle, n);
if (err < 0)

View file

@ -202,18 +202,18 @@ enum {
/* channel mask for each type */
static int mixer_elem_mask[] = {
(SND_MIXER_CHN_MASK_FRONT_LEFT | SND_MIXER_CHN_MASK_FRONT_RIGHT),
(SND_MIXER_CHN_MASK_REAR_LEFT | SND_MIXER_CHN_MASK_REAR_RIGHT),
SND_MIXER_CHN_MASK_FRONT_CENTER,
SND_MIXER_CHN_MASK_WOOFER,
(SND_MIXER_SCHN_MASK_FRONT_LEFT | SND_MIXER_SCHN_MASK_FRONT_RIGHT),
(SND_MIXER_SCHN_MASK_REAR_LEFT | SND_MIXER_SCHN_MASK_REAR_RIGHT),
SND_MIXER_SCHN_MASK_FRONT_CENTER,
SND_MIXER_SCHN_MASK_WOOFER,
};
/* left and right channels for each type */
static snd_mixer_channel_id_t mixer_elem_chn[][2] = {
{ SND_MIXER_CHN_FRONT_LEFT, SND_MIXER_CHN_FRONT_RIGHT },
{ SND_MIXER_CHN_REAR_LEFT, SND_MIXER_CHN_REAR_RIGHT },
{ SND_MIXER_CHN_FRONT_CENTER, SND_MIXER_CHN_UNKNOWN },
{ SND_MIXER_CHN_WOOFER, SND_MIXER_CHN_UNKNOWN },
static snd_mixer_selem_channel_id_t mixer_elem_chn[][2] = {
{ SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT },
{ SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT },
{ SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_UNKNOWN },
{ SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_UNKNOWN },
};
static snd_mixer_selem_id_t *mixer_sid = NULL;
@ -471,7 +471,7 @@ mixer_conv(int val, int omin, int omax, int nmin, int nmax)
}
static int
mixer_calc_volume(snd_mixer_selem_t *scontrol, int vol, snd_mixer_channel_id_t chn)
mixer_calc_volume(snd_mixer_selem_t *scontrol, int vol, snd_mixer_selem_channel_id_t chn)
{
int vol1;
long min = snd_mixer_selem_get_min(scontrol);
@ -499,7 +499,7 @@ mixer_write_cbar (int elem_index)
snd_mixer_selem_t *scontrol;
int vleft, vright, vbalance;
int type;
snd_mixer_channel_id_t chn_left, chn_right, chn;
snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
int err, changed;
snd_mixer_selem_alloca(&scontrol);
@ -514,8 +514,8 @@ mixer_write_cbar (int elem_index)
if (! (scontrol.channels & (1 << snd_enum_to_int(chn_left))))
return; /* ..??.. */
chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
if (chn_right != SND_MIXER_CHN_UNKNOWN && ! (scontrol.channels & (1 << snd_enum_to_int(chn_right))))
chn_right = SND_MIXER_CHN_UNKNOWN;
if (chn_right != SND_MIXER_SCHN_UNKNOWN && ! (scontrol.channels & (1 << snd_enum_to_int(chn_right))))
chn_right = SND_MIXER_SCHN_UNKNOWN;
changed = 0;
@ -526,7 +526,7 @@ mixer_write_cbar (int elem_index)
mixer_balance_volumes) &&
(scontrol.caps & SND_MIXER_SCTCAP_VOLUME)) {
int mono =
(chn_right == SND_MIXER_CHN_UNKNOWN || (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_VOLUME));
(chn_right == SND_MIXER_SCHN_UNKNOWN || (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_VOLUME));
if (mono && !mixer_volume_delta[MIXER_CHN_LEFT])
mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT];
vleft = mixer_calc_volume(&scontrol, mixer_volume_delta[MIXER_CHN_LEFT], chn_left);
@ -539,7 +539,7 @@ mixer_write_cbar (int elem_index)
vright = vleft;
if (vleft >= 0 && vright >= 0) {
if (scontrol.caps & SND_MIXER_SCTCAP_JOINTLY_VOLUME) {
for (chn = 0; chn < SND_MIXER_CHN_LAST; snd_enum_incr(chn)) {
for (chn = 0; chn < SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
int c = snd_enum_to_int(chn);
if (scontrol.channels & (1 << c))
scontrol.volume.values[c] = vleft;
@ -566,7 +566,7 @@ mixer_write_cbar (int elem_index)
else {
if (mixer_toggle_mute & MIXER_MASK_LEFT)
scontrol.mute ^= (1 << snd_enum_to_int(chn_left));
if (chn_right != SND_MIXER_CHN_UNKNOWN &&
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
(mixer_toggle_mute & MIXER_MASK_RIGHT))
scontrol.mute ^= (1 << snd_enum_to_int(chn_right));
}
@ -583,7 +583,7 @@ mixer_write_cbar (int elem_index)
else {
if (mixer_toggle_capture & MIXER_MASK_LEFT)
scontrol.capture ^= (1 << snd_enum_to_int(chn_left));
if (chn_right != SND_MIXER_CHN_UNKNOWN && (mixer_toggle_capture & MIXER_MASK_RIGHT))
if (chn_right != SND_MIXER_SCHN_UNKNOWN && (mixer_toggle_capture & MIXER_MASK_RIGHT))
scontrol.capture ^= (1 << snd_enum_to_int(chn_right));
}
changed = 1;
@ -605,7 +605,7 @@ mixer_update_cbar (int elem_index)
snd_mixer_selem_t scontrol;
int vleft, vright;
int type;
snd_mixer_channel_id_t chn_left, chn_right;
snd_mixer_selem_channel_id_t chn_left, chn_right;
int x, y, i;
int c_left, c_right;
@ -623,9 +623,9 @@ mixer_update_cbar (int elem_index)
if (! (scontrol.channels & (1 << snd_enum_to_int(chn_left))))
return; /* ..??.. */
chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
if (chn_right != SND_MIXER_CHN_UNKNOWN &&
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
! (scontrol.channels & (1 << snd_enum_to_int(chn_right))))
chn_right = SND_MIXER_CHN_UNKNOWN;
chn_right = SND_MIXER_SCHN_UNKNOWN;
c_left = snd_enum_to_int(chn_left);
c_right = snd_enum_to_int(chn_right);
@ -636,7 +636,7 @@ mixer_update_cbar (int elem_index)
vleft = scontrol.volume.values[c_left];
vleft = mixer_conv(vleft, scontrol.min, scontrol.max, 0, 100);
if (chn_right != SND_MIXER_CHN_UNKNOWN) {
if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
vright = scontrol.volume.values[c_right];
vright = mixer_conv(vright, scontrol.min, scontrol.max, 0, 100);
} else {
@ -735,7 +735,7 @@ mixer_update_cbar (int elem_index)
mvaddch (y, x + 2, ACS_ULCORNER);
dc = scontrol.mute & (1 << c_left) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE;
mvaddch (y, x + 3, mixer_dc (dc));
if (chn_right != SND_MIXER_CHN_UNKNOWN)
if (chn_right != SND_MIXER_SCHN_UNKNOWN)
dc = scontrol.mute & (1 << c_right) ? DC_CBAR_MUTE : DC_CBAR_NOMUTE;
mvaddch (y, x + 4, mixer_dc (dc));
mixer_dc (DC_CBAR_FRAME);
@ -745,16 +745,16 @@ mixer_update_cbar (int elem_index)
/* capture input?
*/
if ((scontrol.capture & (1 << c_left)) ||
(chn_right != SND_MIXER_CHN_UNKNOWN && (scontrol.capture & (1 << c_right))))
(chn_right != SND_MIXER_SCHN_UNKNOWN && (scontrol.capture & (1 << c_right))))
{
mixer_dc (DC_CBAR_CAPTURE);
mvaddstr (y, x + 1, "CAPTUR");
if (scontrol.capture & (1 << c_left)) {
mvaddstr (y + 1, x + 1, "L");
if (chn_right == SND_MIXER_CHN_UNKNOWN)
if (chn_right == SND_MIXER_SCHN_UNKNOWN)
mvaddstr (y + 1, x + 6, "R");
}
if (chn_right != SND_MIXER_CHN_UNKNOWN &&
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
(scontrol.capture & (1 << c_right)))
mvaddstr (y + 1, x + 6, "R");
}

View file

@ -100,16 +100,27 @@ static int info(void)
printf(" Controls : %i\n", snd_ctl_elem_list_get_count(clist));
}
snd_ctl_close(handle);
if ((err = snd_mixer_open(&mhandle, card)) < 0) {
error("Mixer %s open error: %s", card, snd_strerror(err));
if ((err = snd_mixer_open(&mhandle)) < 0) {
error("Mixer open error: %s", snd_strerror(err));
return err;
}
err = snd_mixer_simple_build(mhandle);
if (err < 0) {
error("Mixer %s build error: %s", card, snd_strerror(err));
} else {
printf(" Simple ctrls : %i\n", snd_mixer_get_count(mhandle));
if ((err = snd_mixer_attach(mhandle, card)) < 0) {
error("Mixer attach %s error: %s", card, snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
if ((err = snd_mixer_selem_register(mhandle, 0)) < 0) {
error("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
err = snd_mixer_load(mhandle);
if (err < 0) {
error("Mixer load error: %s", card, snd_strerror(err));
snd_mixer_close(mhandle);
return err;
}
printf(" Simple ctrls : %i\n", snd_mixer_get_count(mhandle));
snd_mixer_close(mhandle);
return 0;
}
@ -301,24 +312,25 @@ static void show_control_id(snd_ctl_elem_id_t *id)
printf(",subdevice=%i", subdevice);
}
static int show_control(const char *space, snd_hctl_t *handle,
snd_ctl_elem_id_t *id, int level)
static int show_control(const char *space, snd_hctl_elem_t *elem,
int level)
{
int err;
unsigned int item, idx;
unsigned int count;
snd_ctl_elem_type_t type;
snd_ctl_elem_id_t *id;
snd_ctl_elem_info_t *info;
snd_hctl_elem_t *helem;
snd_ctl_elem_value_t *control;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
if ((helem = snd_hctl_find_elem(handle, id)) == NULL)
return -EINVAL;
if ((err = snd_hctl_elem_info(helem, info)) < 0) {
snd_ctl_elem_value_alloca(&control);
if ((err = snd_hctl_elem_info(elem, info)) < 0) {
error("Control %s cinfo error: %s\n", card, snd_strerror(err));
return err;
}
if (level & 2) {
snd_ctl_elem_info_get_id(info, id);
snd_hctl_elem_get_id(elem, id);
show_control_id(id);
printf("\n");
}
@ -338,7 +350,7 @@ static int show_control(const char *space, snd_hctl_t *handle,
printf(",items=%u\n", items);
for (item = 0; item < items; item++) {
snd_ctl_elem_info_set_item(info, item);
if ((err = snd_hctl_elem_info(helem, info)) < 0) {
if ((err = snd_hctl_elem_info(elem, info)) < 0) {
error("Control %s element info error: %s\n", card, snd_strerror(err));
return err;
}
@ -351,10 +363,7 @@ static int show_control(const char *space, snd_hctl_t *handle,
break;
}
if (level & 1) {
snd_ctl_elem_t *elem;
snd_ctl_elem_alloca(&elem);
snd_ctl_elem_set_id(elem, id);
if ((err = snd_hctl_elem_read(helem, elem)) < 0) {
if ((err = snd_hctl_elem_read(elem, control)) < 0) {
error("Control %s element read error: %s\n", card, snd_strerror(err));
return err;
}
@ -364,16 +373,16 @@ static int show_control(const char *space, snd_hctl_t *handle,
printf(",");
switch (snd_enum_to_int(type)) {
case SND_CTL_ELEM_TYPE_BOOLEAN:
printf("%s", snd_ctl_elem_get_boolean(elem, idx) ? "on" : "off");
printf("%s", snd_ctl_elem_value_get_boolean(control, idx) ? "on" : "off");
break;
case SND_CTL_ELEM_TYPE_INTEGER:
printf("%li", snd_ctl_elem_get_integer(elem, idx));
printf("%li", snd_ctl_elem_value_get_integer(control, idx));
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
printf("%u", snd_ctl_elem_get_enumerated(elem, idx));
printf("%u", snd_ctl_elem_value_get_enumerated(control, idx));
break;
case SND_CTL_ELEM_TYPE_BYTES:
printf("0x%02x", snd_ctl_elem_get_byte(elem, idx));
printf("0x%02x", snd_ctl_elem_value_get_byte(control, idx));
break;
default:
printf("?");
@ -397,12 +406,16 @@ static int controls(int level)
error("Control %s open error: %s", card, snd_strerror(err));
return err;
}
if ((err = snd_hctl_load(handle)) < 0) {
error("Control %s local error: %s\n", card, snd_strerror(err));
return err;
}
for (elem = snd_hctl_first_elem(handle); elem; elem = snd_hctl_elem_next(elem)) {
snd_hctl_elem_get_id(elem, id);
show_control_id(id);
printf("\n");
if (level > 0)
show_control(" ", handle, id, 1);
show_control(" ", elem, 1);
}
snd_hctl_close(handle);
return 0;
@ -411,11 +424,13 @@ static int controls(int level)
static int show_selem(snd_mixer_t *handle, snd_mixer_selem_id_t *id, const char *space, int level)
{
int err;
snd_mixer_channel_id_t chn;
snd_mixer_selem_channel_id_t chn;
long min, max;
snd_mixer_elem_t *elem;
snd_mixer_selem_t *scontrol;
snd_mixer_selem_alloca(&scontrol);
snd_mixer_selem_info_t *sinfo;
snd_mixer_selem_value_t *scontrol;
snd_mixer_selem_info_alloca(&sinfo);
snd_mixer_selem_value_alloca(&scontrol);
elem = snd_mixer_find_selem(handle, id);
if (!elem) {
@ -423,60 +438,64 @@ static int show_selem(snd_mixer_t *handle, snd_mixer_selem_id_t *id, const char
return -ENOENT;
}
if ((err = snd_mixer_selem_info(elem, sinfo)) < 0) {
error("Mixer %s selem info error: %s", card, snd_strerror(err));
return err;
}
if ((err = snd_mixer_selem_read(elem, scontrol)) < 0) {
error("Mixer %s selem error: %s", card, snd_strerror(err));
error("Mixer %s selem read error: %s", card, snd_strerror(err));
return err;
}
if ((level & 1) != 0) {
printf("%sCapabilities:", space);
if (snd_mixer_selem_has_volume(scontrol))
if (snd_mixer_selem_info_has_volume(sinfo))
printf(" volume");
if (snd_mixer_selem_has_joined_volume(scontrol))
if (snd_mixer_selem_info_has_joined_volume(sinfo))
printf(" joined-volume");
if (snd_mixer_selem_has_mute(scontrol))
if (snd_mixer_selem_info_has_mute(sinfo))
printf(" mute");
if (snd_mixer_selem_has_joined_mute(scontrol))
if (snd_mixer_selem_info_has_joined_mute(sinfo))
printf(" joined-mute");
if (snd_mixer_selem_has_capture(scontrol)) {
if (snd_mixer_selem_info_has_capture(sinfo)) {
printf(" capture");
}
if (snd_mixer_selem_has_joined_capture(scontrol))
if (snd_mixer_selem_info_has_joined_capture(sinfo))
printf(" joined-capture");
if (snd_mixer_selem_has_exclusive_capture(scontrol))
if (snd_mixer_selem_info_has_exclusive_capture(sinfo))
printf(" exclusive-capture");
printf("\n");
if (snd_mixer_selem_has_capture(scontrol) &&
snd_mixer_selem_has_exclusive_capture(scontrol))
printf("%sCapture exclusive scontrol: %i\n", space,
snd_mixer_selem_get_capture_group(scontrol));
if (snd_mixer_selem_info_has_capture(sinfo) &&
snd_mixer_selem_info_has_exclusive_capture(sinfo))
printf("%sCapture exclusive group: %i\n", space,
snd_mixer_selem_info_get_capture_group(sinfo));
printf("%sChannels: ", space);
if (snd_mixer_selem_is_mono(scontrol)) {
if (snd_mixer_selem_info_is_mono(sinfo)) {
printf("Mono");
} else {
for (chn = 0; chn <= SND_MIXER_CHN_LAST; snd_enum_incr(chn)){
if (!snd_mixer_selem_has_channel(scontrol, chn))
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)){
if (!snd_mixer_selem_info_has_channel(sinfo, chn))
continue;
printf("%s ", snd_mixer_channel_name(chn));
printf("%s ", snd_mixer_selem_channel_name(chn));
}
}
printf("\n");
min = snd_mixer_selem_get_min(scontrol);
max = snd_mixer_selem_get_max(scontrol);
min = snd_mixer_selem_info_get_min(sinfo);
max = snd_mixer_selem_info_get_max(sinfo);
printf("%sLimits: min = %li, max = %li\n", space, min, max);
if (snd_mixer_selem_is_mono(scontrol)) {
if (snd_mixer_selem_info_is_mono(sinfo)) {
printf("%sMono: %s [%s]\n", space,
get_percent(snd_mixer_selem_get_volume(scontrol, SND_MIXER_CHN_MONO), min, max),
snd_mixer_selem_get_mute(scontrol, SND_MIXER_CHN_MONO) ? "mute" : "on");
get_percent(snd_mixer_selem_value_get_volume(scontrol, SND_MIXER_SCHN_MONO), min, max),
snd_mixer_selem_value_get_mute(scontrol, SND_MIXER_SCHN_MONO) ? "mute" : "on");
} else {
for (chn = 0; chn <= SND_MIXER_CHN_LAST; snd_enum_incr(chn)) {
if (!snd_mixer_selem_has_channel(scontrol, chn))
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
if (!snd_mixer_selem_info_has_channel(sinfo, chn))
continue;
printf("%s%s: %s [%s] [%s]\n",
space,
snd_mixer_channel_name(chn),
get_percent(snd_mixer_selem_get_volume(scontrol, chn), min, max),
snd_mixer_selem_get_mute(scontrol, chn) ? "mute" : "on",
snd_mixer_selem_get_capture(scontrol, chn) ? "capture" : "---");
space,
snd_mixer_selem_channel_name(chn),
get_percent(snd_mixer_selem_value_get_volume(scontrol, chn), min, max),
snd_mixer_selem_value_get_mute(scontrol, chn) ? "mute" : "on",
snd_mixer_selem_value_get_capture(scontrol, chn) ? "capture" : "---");
}
}
}
@ -491,13 +510,24 @@ static int selems(int level)
snd_mixer_elem_t *elem;
snd_mixer_selem_id_alloca(&sid);
if ((err = snd_mixer_open(&handle, card)) < 0) {
if ((err = snd_mixer_open(&handle)) < 0) {
error("Mixer %s open error: %s", card, snd_strerror(err));
return err;
}
err = snd_mixer_simple_build(handle);
if ((err = snd_mixer_attach(handle, card)) < 0) {
error("Mixer attach %s error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
error("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(handle);
return err;
}
err = snd_mixer_load(handle);
if (err < 0) {
error("Mixer %s build error: %s", card, snd_strerror(err));
error("Mixer load error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) {
@ -650,14 +680,14 @@ static int cset(int argc, char *argv[], int roflag)
snd_ctl_t *handle;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_t *id;
snd_ctl_elem_t *control;
snd_ctl_elem_value_t *control;
char *ptr;
unsigned int idx, count;
long tmp;
snd_ctl_elem_type_t type;
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_alloca(&control);
snd_ctl_elem_value_alloca(&control);
if (argc < 1) {
fprintf(stderr, "Specify a full control identifier: [[iface=<iface>,][name='name',][index=<index>,][device=<device>,][subdevice=<subdevice>]]|[numid=<numid>]\n");
@ -683,7 +713,7 @@ static int cset(int argc, char *argv[], int roflag)
}
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
snd_ctl_elem_set_id(control, id);
snd_ctl_elem_value_set_id(control, id);
if (!roflag) {
ptr = argv[1];
@ -702,21 +732,21 @@ static int cset(int argc, char *argv[], int roflag)
while (isdigit(*ptr))
ptr++;
}
snd_ctl_elem_set_boolean(control, idx, tmp);
snd_ctl_elem_value_set_boolean(control, idx, tmp);
break;
case SND_CTL_ELEM_TYPE_INTEGER:
tmp = get_integer(&ptr,
snd_ctl_elem_info_get_min(info),
snd_ctl_elem_info_get_max(info));
snd_ctl_elem_set_integer(control, idx, tmp);
snd_ctl_elem_value_set_integer(control, idx, tmp);
break;
case SND_CTL_ELEM_TYPE_ENUMERATED:
tmp = get_integer(&ptr, 0, snd_ctl_elem_info_get_items(info) - 1);
snd_ctl_elem_set_enumerated(control, idx, tmp);
snd_ctl_elem_value_set_enumerated(control, idx, tmp);
break;
case SND_CTL_ELEM_TYPE_BYTES:
tmp = get_integer(&ptr, 0, 255);
snd_ctl_elem_set_byte(control, idx, tmp);
snd_ctl_elem_value_set_byte(control, idx, tmp);
break;
default:
break;
@ -732,15 +762,25 @@ static int cset(int argc, char *argv[], int roflag)
}
}
snd_ctl_close(handle);
#if 0
/* FIXME */
if (!quiet) {
snd_hctl_t *hctl;
snd_hctl_t *elem;
if ((err = snd_hctl_open(&hctl, card)) < 0) {
error("Control %s open error: %s\n", card, snd_strerror(err));
return err;
}
show_control(" ", hctl, id, 3);
if ((err = snd_hctl_load(&hctl)) < 0) {
error("Control %s load error: %s\n", card, snd_strerror(err));
return err;
}
elem = snd_hctl_find_elem(hctl, id);
assert(elem);
show_control(" ", elem, 3);
snd_hctl_close(hctl);
}
#endif
return 0;
}
@ -749,17 +789,17 @@ typedef struct channel_mask {
unsigned int mask;
} channel_mask_t;
static channel_mask_t chanmask[] = {
{"frontleft", 1 << SND_MIXER_CHN_FRONT_LEFT},
{"frontright", 1 << SND_MIXER_CHN_FRONT_RIGHT},
{"frontcenter", 1 << SND_MIXER_CHN_FRONT_CENTER},
{"front", ((1 << SND_MIXER_CHN_FRONT_LEFT) |
(1 << SND_MIXER_CHN_FRONT_RIGHT))},
{"center", 1 << SND_MIXER_CHN_FRONT_CENTER},
{"rearleft", 1 << SND_MIXER_CHN_REAR_LEFT},
{"rearright", 1 << SND_MIXER_CHN_REAR_RIGHT},
{"rear", ((1 << SND_MIXER_CHN_REAR_LEFT) |
(1 << SND_MIXER_CHN_REAR_RIGHT))},
{"woofer", 1 << SND_MIXER_CHN_WOOFER},
{"frontleft", 1 << SND_MIXER_SCHN_FRONT_LEFT},
{"frontright", 1 << SND_MIXER_SCHN_FRONT_RIGHT},
{"frontcenter", 1 << SND_MIXER_SCHN_FRONT_CENTER},
{"front", ((1 << SND_MIXER_SCHN_FRONT_LEFT) |
(1 << SND_MIXER_SCHN_FRONT_RIGHT))},
{"center", 1 << SND_MIXER_SCHN_FRONT_CENTER},
{"rearleft", 1 << SND_MIXER_SCHN_REAR_LEFT},
{"rearright", 1 << SND_MIXER_SCHN_REAR_RIGHT},
{"rear", ((1 << SND_MIXER_SCHN_REAR_LEFT) |
(1 << SND_MIXER_SCHN_REAR_RIGHT))},
{"woofer", 1 << SND_MIXER_SCHN_WOOFER},
{NULL, 0}
};
@ -778,15 +818,17 @@ static int sset(unsigned int argc, char *argv[], int roflag)
{
int err;
unsigned int idx;
snd_mixer_channel_id_t chn;
snd_mixer_selem_channel_id_t chn;
unsigned int channels;
long min, max;
snd_mixer_t *handle;
snd_mixer_elem_t *elem;
snd_mixer_selem_id_t *sid;
snd_mixer_selem_t *control;
snd_mixer_selem_value_t *control;
snd_mixer_selem_info_t *info;
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_alloca(&control);
snd_mixer_selem_value_alloca(&control);
snd_mixer_selem_info_alloca(&info);
if (argc < 1) {
fprintf(stderr, "Specify a scontrol identifier: 'name',index\n");
@ -800,41 +842,62 @@ static int sset(unsigned int argc, char *argv[], int roflag)
fprintf(stderr, "Specify what you want to set...\n");
return 1;
}
if ((err = snd_mixer_open(&handle, card)) < 0) {
if ((err = snd_mixer_open(&handle)) < 0) {
error("Mixer %s open error: %s\n", card, snd_strerror(err));
return err;
}
if ((err = snd_mixer_attach(handle, card)) < 0) {
error("Mixer attach %s error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
error("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(handle);
return err;
}
err = snd_mixer_load(handle);
if (err < 0) {
error("Mixer load error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
elem = snd_mixer_find_selem(handle, sid);
if (!elem) {
error("Unable to find simple control '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
snd_mixer_close(handle);
return -ENOENT;
}
if ((err = snd_mixer_selem_info(elem, info))<0) {
error("Unable to get simple info '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
snd_mixer_close(handle);
return err;
}
if ((err = snd_mixer_selem_read(elem, control))<0) {
error("Unable to read simple control '%s',%i: %s\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid), snd_strerror(err));
snd_mixer_close(handle);
return err;
}
min = snd_mixer_selem_get_min(control);
max = snd_mixer_selem_get_min(control);
min = snd_mixer_selem_info_get_min(info);
max = snd_mixer_selem_info_get_min(info);
if (roflag)
goto __skip_write;
for (idx = 1; idx < argc; idx++) {
if (!strncmp(argv[idx], "mute", 4) ||
!strncmp(argv[idx], "off", 3)) {
snd_mixer_selem_set_mute_all(control, 1);
snd_mixer_selem_value_set_mute_all(control, 1);
continue;
} else if (!strncmp(argv[idx], "unmute", 6) ||
!strncmp(argv[idx], "on", 2)) {
snd_mixer_selem_set_mute_all(control, 0);
snd_mixer_selem_value_set_mute_all(control, 0);
continue;
} else if (!strncmp(argv[idx], "cap", 3) ||
!strncmp(argv[idx], "rec", 3)) {
snd_mixer_selem_set_capture_all(control, 1);
snd_mixer_selem_value_set_capture_all(control, 1);
continue;
} else if (!strncmp(argv[idx], "nocap", 5) ||
!strncmp(argv[idx], "norec", 5)) {
snd_mixer_selem_set_capture_all(control, 0);
snd_mixer_selem_value_set_capture_all(control, 0);
continue;
}
channels = channels_mask(argv[idx]);
@ -846,14 +909,14 @@ static int sset(unsigned int argc, char *argv[], int roflag)
multi = (strchr(argv[idx], ',') != NULL);
ptr = argv[idx];
for (chn = 0; chn <= SND_MIXER_CHN_LAST; snd_enum_incr(chn)) {
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; snd_enum_incr(chn)) {
if (!(channels & (1 << chn)) ||
!snd_mixer_selem_has_channel(control, chn))
!snd_mixer_selem_info_has_channel(info, chn))
continue;
if (! multi)
ptr = argv[idx];
snd_mixer_selem_set_volume(control, chn, get_volume_simple(&ptr, min, max, snd_mixer_selem_get_volume(control, chn)));
snd_mixer_selem_value_set_volume(control, chn, get_volume_simple(&ptr, min, max, snd_mixer_selem_value_get_volume(control, chn)));
}
} else {
error("Unknown setup '%s'..\n", argv[idx]);
@ -875,12 +938,12 @@ static int sset(unsigned int argc, char *argv[], int roflag)
return 0;
}
static void events_change(snd_hctl_elem_t *helem)
static void events_info(snd_hctl_elem_t *helem)
{
snd_ctl_elem_id_t *id;
snd_ctl_elem_id_alloca(&id);
snd_hctl_elem_get_id(helem, id);
printf("event change: ");
printf("event info: ");
show_control_id(id);
printf("\n");
}
@ -913,8 +976,8 @@ static void events_rebuild()
int element_callback(snd_hctl_elem_t *elem, snd_ctl_event_type_t event)
{
switch (event) {
case SND_CTL_EVENT_CHANGE:
events_change(elem);
case SND_CTL_EVENT_INFO:
events_info(elem);
break;
case SND_CTL_EVENT_VALUE:
events_value(elem);
@ -940,8 +1003,7 @@ static void events_add(snd_hctl_elem_t *helem)
snd_hctl_elem_set_callback(helem, element_callback);
}
int ctl_callback(snd_hctl_t *hctl,
snd_ctl_event_type_t event,
int ctl_callback(snd_hctl_t *ctl, snd_ctl_event_type_t event,
snd_hctl_elem_t *elem)
{
switch (event) {
@ -969,6 +1031,10 @@ static int events(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
return err;
}
snd_hctl_set_callback(handle, ctl_callback);
if ((err = snd_hctl_load(handle)) < 0) {
error("Control %s hbuild error: %s\n", card, snd_strerror(err));
return err;
}
for (helem = snd_hctl_first_elem(handle); helem; helem = snd_hctl_elem_next(helem)) {
snd_hctl_elem_set_callback(helem, element_callback);
}
@ -981,9 +1047,8 @@ static int events(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
ctl_poll.revents = 0;
if ((res = poll(&ctl_poll, 1, -1)) > 0) {
printf("Poll ok: %i\n", res);
res = snd_hctl_events(handle);
if (res > 0)
printf("%i events processed\n", res);
res = snd_hctl_handle_events(handle);
assert(res > 0);
}
}
snd_hctl_close(handle);
@ -994,9 +1059,9 @@ static void sevents_value(snd_mixer_selem_id_t *sid)
printf("event value: '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
}
static void sevents_change(snd_mixer_selem_id_t *sid)
static void sevents_info(snd_mixer_selem_id_t *sid)
{
printf("event change: '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
printf("event info: '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
}
static void sevents_remove(snd_mixer_selem_id_t *sid)
@ -1004,14 +1069,14 @@ static void sevents_remove(snd_mixer_selem_id_t *sid)
printf("event remove: '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
}
int selem_callback(snd_mixer_elem_t *elem, snd_ctl_event_type_t event)
int melem_event(snd_mixer_elem_t *elem, snd_ctl_event_type_t event)
{
snd_mixer_selem_id_t *sid;
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_get_id(elem, sid);
switch (event) {
case SND_CTL_EVENT_CHANGE:
sevents_change(sid);
case SND_CTL_EVENT_INFO:
sevents_info(sid);
break;
case SND_CTL_EVENT_VALUE:
sevents_value(sid);
@ -1037,7 +1102,7 @@ static void sevents_add(snd_mixer_elem_t *elem)
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_get_id(elem, sid);
printf("event add: '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
snd_mixer_elem_set_callback(elem, selem_callback);
snd_mixer_elem_set_callback(elem, melem_event);
}
int mixer_event(snd_mixer_t *mixer, snd_ctl_event_type_t event,
@ -1062,14 +1127,24 @@ static int sevents(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
snd_mixer_t *handle;
int err;
if ((err = snd_mixer_open(&handle, card)) < 0) {
error("Mixer %s open error: %s\n", card, snd_strerror(err));
if ((err = snd_mixer_open(&handle)) < 0) {
error("Mixer %s open error: %s", card, snd_strerror(err));
return err;
}
if ((err = snd_mixer_attach(handle, card)) < 0) {
error("Mixer attach %s error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
if ((err = snd_mixer_selem_register(handle, 0)) < 0) {
error("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(handle);
return err;
}
snd_mixer_set_callback(handle, mixer_event);
err = snd_mixer_simple_build(handle);
err = snd_mixer_load(handle);
if (err < 0) {
error("Mixer %s build error: %s\n", card, snd_strerror(err));
error("Mixer load error: %s", card, snd_strerror(err));
snd_mixer_close(handle);
return err;
}
@ -1078,14 +1153,14 @@ static int sevents(int argc ATTRIBUTE_UNUSED, char *argv[] ATTRIBUTE_UNUSED)
while (1) {
struct pollfd mixer_poll;
int res;
mixer_poll.fd = snd_mixer_poll_descriptor(handle);
mixer_poll.fd = snd_mixer_poll_descriptor(handle, card);
assert(mixer_poll.fd >= 0);
mixer_poll.events = POLLIN;
mixer_poll.revents = 0;
if ((res = poll(&mixer_poll, 1, -1)) > 0) {
printf("Poll ok: %i\n", res);
res = snd_mixer_events(handle);
if (res > 0)
printf("%i events processed\n", res);
res = snd_mixer_handle_events(handle);
assert(res >= 0);
}
}
snd_mixer_close(handle);

View file

@ -448,16 +448,16 @@ int main(int argc, char *argv[])
}
if (digtype != SND_CTL_ELEM_TYPE_NONE) {
snd_ctl_elem_t *ctl;
snd_ctl_elem_value_t *ctl;
snd_ctl_t *ctl_handle;
char ctl_name[12];
int ctl_card;
snd_ctl_elem_alloca(&ctl);
snd_ctl_elem_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM);
snd_ctl_elem_set_device(ctl, snd_pcm_info_get_device(info));
snd_ctl_elem_set_subdevice(ctl, snd_pcm_info_get_subdevice(info));
snd_ctl_elem_set_name(ctl, "IEC958 (S/PDIF) Stream");
snd_ctl_elem_set_iec958(ctl, &spdif);
snd_ctl_elem_value_alloca(&ctl);
snd_ctl_elem_value_set_interface(ctl, SND_CTL_ELEM_IFACE_PCM);
snd_ctl_elem_value_set_device(ctl, snd_pcm_info_get_device(info));
snd_ctl_elem_value_set_subdevice(ctl, snd_pcm_info_get_subdevice(info));
snd_ctl_elem_value_set_name(ctl, "IEC958 (S/PDIF) Stream");
snd_ctl_elem_value_set_iec958(ctl, &spdif);
ctl_card = snd_pcm_info_get_card(info);
if (ctl_card < 0) {
error("Unable to setup the IEC958 (S/PDIF) interface - PCM has no assigned card");