fixed / improved handling of capture volumes and switches.

now capture volumes are displayed and controllable as independent
bars from playback volumes.
e.g. on emu10k1 you'll see both "AC97" and "AC97 Capture".

there is still a bug in handling of "Capture Volume" control.
This commit is contained in:
Takashi Iwai 2002-02-27 18:07:11 +00:00
parent 3ed9466bce
commit d81f16b7fa

View file

@ -196,6 +196,11 @@ static char mixer_device_name[128];
#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT) #define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
/* mixer split types */ /* mixer split types */
enum {
MIXER_STREAM_PLAYBACK, MIXER_STREAM_CAPTURE,
MIXER_STREAM_END
};
enum { enum {
MIXER_ELEM_FRONT, MIXER_ELEM_REAR, MIXER_ELEM_FRONT, MIXER_ELEM_REAR,
MIXER_ELEM_CENTER, MIXER_ELEM_WOOFER, MIXER_ELEM_CENTER, MIXER_ELEM_WOOFER,
@ -468,13 +473,16 @@ mixer_conv(int val, int omin, int omax, int nmin, int nmax)
static int static int
mixer_calc_volume(snd_mixer_elem_t *elem, mixer_calc_volume(snd_mixer_elem_t *elem,
int vol, int vol, int stream,
snd_mixer_selem_channel_id_t chn) snd_mixer_selem_channel_id_t chn)
{ {
int vol1; int vol1;
long v; long v;
long min, max; long min, max;
if (stream == MIXER_STREAM_PLAYBACK)
snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
else
snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
vol1 = (vol < 0) ? -vol : vol; vol1 = (vol < 0) ? -vol : vol;
if (vol1 > 0) { if (vol1 > 0) {
if (vol1 > 100) if (vol1 > 100)
@ -486,7 +494,10 @@ mixer_calc_volume(snd_mixer_elem_t *elem,
if (vol < 0) if (vol < 0)
vol1 = -vol1; vol1 = -vol1;
} }
if (stream == MIXER_STREAM_PLAYBACK)
snd_mixer_selem_get_playback_volume(elem, chn, &v); snd_mixer_selem_get_playback_volume(elem, chn, &v);
else
snd_mixer_selem_get_capture_volume(elem, chn, &v);
vol1 += v; vol1 += v;
return CLAMP(vol1, min, max); return CLAMP(vol1, min, max);
} }
@ -498,7 +509,7 @@ mixer_write_cbar (int elem_index)
{ {
snd_mixer_elem_t *elem; snd_mixer_elem_t *elem;
int vleft, vright, vbalance; int vleft, vright, vbalance;
int type; int type, stream;
snd_mixer_selem_id_t *sid; snd_mixer_selem_id_t *sid;
snd_mixer_selem_channel_id_t chn_left, chn_right, chn; snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
int sw; int sw;
@ -510,54 +521,73 @@ mixer_write_cbar (int elem_index)
elem = snd_mixer_find_selem(mixer_handle, sid); elem = snd_mixer_find_selem(mixer_handle, sid);
if (elem == NULL) if (elem == NULL)
CHECK_ABORT (ERR_FCN, __FUNCTION__ ": snd_mixer_find_selem()", -EINVAL); CHECK_ABORT (ERR_FCN, __FUNCTION__ ": snd_mixer_find_selem()", -EINVAL);
type = mixer_type[elem_index]; type = mixer_type[elem_index] % MIXER_ELEM_END;
stream = mixer_type[elem_index] / MIXER_ELEM_END;
chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
if (!snd_mixer_selem_has_playback_channel(elem, chn_left))
return; /* ..??.. */
chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT]; chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
if (chn_right != SND_MIXER_SCHN_UNKNOWN && if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
!snd_mixer_selem_has_playback_channel(elem, chn_right)) if (stream == MIXER_STREAM_PLAYBACK) {
if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
chn_right = SND_MIXER_SCHN_UNKNOWN; chn_right = SND_MIXER_SCHN_UNKNOWN;
} else {
if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
chn_right = SND_MIXER_SCHN_UNKNOWN;
}
}
/* volume /* volume
*/ */
if ((mixer_volume_delta[MIXER_CHN_LEFT] || if ((mixer_volume_delta[MIXER_CHN_LEFT] ||
mixer_volume_delta[MIXER_CHN_RIGHT] || mixer_volume_delta[MIXER_CHN_RIGHT] ||
mixer_balance_volumes) && mixer_balance_volumes) &&
snd_mixer_selem_has_playback_volume(elem)) { ((stream == MIXER_STREAM_PLAYBACK && snd_mixer_selem_has_playback_volume(elem)) ||
int mono = (stream == MIXER_STREAM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)))) {
(chn_right == SND_MIXER_SCHN_UNKNOWN || int mono;
snd_mixer_selem_has_playback_volume_joined(elem)); int joined;
mono = (chn_right == SND_MIXER_SCHN_UNKNOWN);
if (stream == MIXER_STREAM_PLAYBACK)
joined = snd_mixer_selem_has_playback_volume_joined(elem);
else
joined = snd_mixer_selem_has_capture_volume_joined(elem);
mono |= joined;
if (mono && !mixer_volume_delta[MIXER_CHN_LEFT]) if (mono && !mixer_volume_delta[MIXER_CHN_LEFT])
mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT]; mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT];
vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], chn_left); vleft = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_LEFT], stream, chn_left);
vbalance = vleft; vbalance = vleft;
if (! mono) { if (! mono) {
vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], chn_right); vright = mixer_calc_volume(elem, mixer_volume_delta[MIXER_CHN_RIGHT], stream, chn_right);
vbalance += vright; vbalance += vright;
vbalance /= 2; vbalance /= 2;
} else } else
vright = vleft; vright = vleft;
if (vleft >= 0 && vright >= 0) { if (vleft >= 0 && vright >= 0) {
if (snd_mixer_selem_has_playback_volume_joined(elem)) { if (joined) {
for (chn = 0; chn < SND_MIXER_SCHN_LAST; chn++) for (chn = 0; chn < SND_MIXER_SCHN_LAST; chn++)
if (stream == MIXER_STREAM_PLAYBACK) {
if (snd_mixer_selem_has_playback_channel(elem, chn)) if (snd_mixer_selem_has_playback_channel(elem, chn))
snd_mixer_selem_set_playback_volume(elem, chn, vleft); snd_mixer_selem_set_playback_volume(elem, chn, vleft);
} else {
if (snd_mixer_selem_has_capture_channel(elem, chn)) if (snd_mixer_selem_has_capture_channel(elem, chn))
snd_mixer_selem_set_capture_volume(elem, chn, vleft); snd_mixer_selem_set_capture_volume(elem, chn, vleft);
}
} else { } else {
if (mixer_balance_volumes) if (mixer_balance_volumes)
vleft = vright = vbalance; vleft = vright = vbalance;
if (stream == MIXER_STREAM_PLAYBACK) {
if (snd_mixer_selem_has_playback_volume(elem) && if (snd_mixer_selem_has_playback_volume(elem) &&
snd_mixer_selem_has_playback_channel(elem, chn_left)) snd_mixer_selem_has_playback_channel(elem, chn_left))
snd_mixer_selem_set_playback_volume(elem, chn_left, vleft); snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
} else {
if (snd_mixer_selem_has_capture_volume(elem) && if (snd_mixer_selem_has_capture_volume(elem) &&
snd_mixer_selem_has_capture_channel(elem, chn_left)) snd_mixer_selem_has_capture_channel(elem, chn_left))
snd_mixer_selem_set_capture_volume(elem, chn_left, vleft); snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
}
if (! mono) { if (! mono) {
if (stream == MIXER_STREAM_PLAYBACK) {
if (snd_mixer_selem_has_playback_volume(elem) && if (snd_mixer_selem_has_playback_volume(elem) &&
snd_mixer_selem_has_playback_channel(elem, chn_right)) snd_mixer_selem_has_playback_channel(elem, chn_right))
snd_mixer_selem_set_playback_volume(elem, chn_right, vright); snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
} else {
if (snd_mixer_selem_has_capture_volume(elem) && if (snd_mixer_selem_has_capture_volume(elem) &&
snd_mixer_selem_has_capture_channel(elem, chn_right)) snd_mixer_selem_has_capture_channel(elem, chn_right))
snd_mixer_selem_set_capture_volume(elem, chn_right, vright); snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
@ -565,11 +595,13 @@ mixer_write_cbar (int elem_index)
} }
} }
} }
}
mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0; mixer_volume_delta[MIXER_CHN_LEFT] = mixer_volume_delta[MIXER_CHN_RIGHT] = 0;
mixer_balance_volumes = 0; mixer_balance_volumes = 0;
/* mute /* mute
*/ */
if (stream == MIXER_STREAM_PLAYBACK) {
if (mixer_toggle_mute && snd_mixer_selem_has_playback_switch(elem)) { if (mixer_toggle_mute && snd_mixer_selem_has_playback_switch(elem)) {
if (snd_mixer_selem_has_playback_switch_joined(elem)) { if (snd_mixer_selem_has_playback_switch_joined(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn_left, &sw); snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
@ -586,10 +618,12 @@ mixer_write_cbar (int elem_index)
} }
} }
} }
}
mixer_toggle_mute = 0; mixer_toggle_mute = 0;
/* capture /* capture
*/ */
if (stream == MIXER_STREAM_PLAYBACK) {
if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) { if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
if (snd_mixer_selem_has_capture_switch_joined(elem)) { if (snd_mixer_selem_has_capture_switch_joined(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn_left, &sw); snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
@ -606,6 +640,7 @@ mixer_write_cbar (int elem_index)
} }
} }
} }
}
mixer_toggle_capture = 0; mixer_toggle_capture = 0;
} }
@ -617,10 +652,9 @@ mixer_update_cbar (int elem_index)
int dc; int dc;
snd_mixer_elem_t *elem; snd_mixer_elem_t *elem;
long vleft, vright; long vleft, vright;
int type; int type, stream;
snd_mixer_selem_id_t *sid; snd_mixer_selem_id_t *sid;
snd_mixer_selem_channel_id_t chn_left, chn_right; snd_mixer_selem_channel_id_t chn_left, chn_right;
snd_mixer_selem_channel_id_t cchn_right;
int x, y, i; int x, y, i;
int swl, swr; int swl, swr;
@ -634,19 +668,22 @@ mixer_update_cbar (int elem_index)
if (elem == NULL) if (elem == NULL)
CHECK_ABORT (ERR_FCN, __FUNCTION__ ": snd_mixer_find_selem()", -EINVAL); CHECK_ABORT (ERR_FCN, __FUNCTION__ ": snd_mixer_find_selem()", -EINVAL);
type = mixer_type[elem_index]; type = mixer_type[elem_index] % MIXER_ELEM_END;
stream = mixer_type[elem_index] / MIXER_ELEM_END;
chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT]; chn_left = mixer_elem_chn[type][MIXER_CHN_LEFT];
if (!snd_mixer_selem_has_playback_channel(elem, chn_left)) chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
return; /* ..??.. */
cchn_right = chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
if (chn_right != SND_MIXER_SCHN_UNKNOWN) { if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
if (stream == MIXER_STREAM_PLAYBACK) {
if (!snd_mixer_selem_has_playback_channel(elem, chn_right)) if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
chn_right = SND_MIXER_SCHN_UNKNOWN; chn_right = SND_MIXER_SCHN_UNKNOWN;
} else {
if (!snd_mixer_selem_has_capture_channel(elem, chn_right)) if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
cchn_right = SND_MIXER_SCHN_UNKNOWN; chn_right = SND_MIXER_SCHN_UNKNOWN;
}
} }
if (snd_mixer_selem_has_playback_volume(elem)) { vleft = vright = 0;
if (stream == MIXER_STREAM_PLAYBACK && snd_mixer_selem_has_playback_volume(elem)) {
long vmin, vmax; long vmin, vmax;
snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax); snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax);
snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft); snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft);
@ -657,8 +694,20 @@ mixer_update_cbar (int elem_index)
} else { } else {
vright = vleft; vright = vleft;
} }
} else }
vleft = vright = 0;
if (stream == MIXER_STREAM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)) {
long vmin, vmax;
snd_mixer_selem_get_capture_volume_range(elem, &vmin, &vmax);
snd_mixer_selem_get_capture_volume(elem, chn_left, &vleft);
vleft = mixer_conv(vleft, vmin, vmax, 0, 100);
if (chn_right != SND_MIXER_SCHN_UNKNOWN) {
snd_mixer_selem_get_capture_volume(elem, chn_right, &vright);
vright = mixer_conv(vright, vmin, vmax, 0, 100);
} else {
vright = vleft;
}
}
/* update the focused full bar name /* update the focused full bar name
*/ */
@ -671,6 +720,8 @@ mixer_update_cbar (int elem_index)
string1[i] = ' '; string1[i] = ' ';
string1[63] = '\0'; string1[63] = '\0';
strcpy(string, snd_mixer_selem_id_get_name(sid)); strcpy(string, snd_mixer_selem_id_get_name(sid));
if (stream == MIXER_STREAM_CAPTURE)
strcat(string, " Capture");
if (snd_mixer_selem_id_get_index(sid) > 0) if (snd_mixer_selem_id_get_index(sid) > 0)
sprintf(string + strlen(string), " %i", snd_mixer_selem_id_get_index(sid)); sprintf(string + strlen(string), " %i", snd_mixer_selem_id_get_index(sid));
string[63] = '\0'; string[63] = '\0';
@ -748,7 +799,7 @@ mixer_update_cbar (int elem_index)
*/ */
mixer_dc (DC_BACK); mixer_dc (DC_BACK);
mvaddstr (y, x, " "); mvaddstr (y, x, " ");
if (snd_mixer_selem_has_playback_switch(elem)) { if (stream == MIXER_STREAM_PLAYBACK && snd_mixer_selem_has_playback_switch(elem)) {
mixer_dc (DC_CBAR_FRAME); mixer_dc (DC_CBAR_FRAME);
mvaddch (y, x + 2, ACS_ULCORNER); mvaddch (y, x + 2, ACS_ULCORNER);
snd_mixer_selem_get_playback_switch(elem, chn_left, &swl); snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
@ -770,21 +821,21 @@ mixer_update_cbar (int elem_index)
} }
y--; y--;
/* capture input? /* capture input? (note: we put it on playback volume, not on capture)
*/ */
if (snd_mixer_selem_has_capture_switch(elem)) { if (stream == MIXER_STREAM_PLAYBACK && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn_left, &swl); snd_mixer_selem_get_capture_switch(elem, chn_left, &swl);
if (cchn_right != SND_MIXER_SCHN_UNKNOWN) if (chn_right != SND_MIXER_SCHN_UNKNOWN)
snd_mixer_selem_get_capture_switch(elem, cchn_right, &swr); snd_mixer_selem_get_capture_switch(elem, chn_right, &swr);
if (swl || (cchn_right != SND_MIXER_SCHN_UNKNOWN && swr)) { if (swl || (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)) {
mixer_dc (DC_CBAR_CAPTURE); mixer_dc (DC_CBAR_CAPTURE);
mvaddstr (y, x + 1, "CAPTUR"); mvaddstr (y, x + 1, "CAPTUR");
if (swl) { if (swl) {
mvaddstr (y + 1, x + 1, "L"); mvaddstr (y + 1, x + 1, "L");
if (cchn_right == SND_MIXER_SCHN_UNKNOWN) if (chn_right == SND_MIXER_SCHN_UNKNOWN)
mvaddstr (y + 1, x + 6, "R"); mvaddstr (y + 1, x + 6, "R");
} }
if (cchn_right != SND_MIXER_SCHN_UNKNOWN && swr) if (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)
mvaddstr (y + 1, x + 6, "R"); mvaddstr (y + 1, x + 6, "R");
} else { } else {
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
@ -1341,10 +1392,14 @@ __again:
goto __again; goto __again;
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j])) if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
ok++; ok++;
else if (i == 0 && snd_mixer_selem_has_capture_switch(elem))
ok++;
} }
if (ok) if (ok)
mixer_n_elems++; mixer_n_elems++;
} }
if (snd_mixer_selem_has_capture_volume(elem))
mixer_n_elems++;
} }
if (mixer_type) if (mixer_type)
@ -1372,8 +1427,11 @@ __again:
goto __again; goto __again;
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j])) if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
ok++; ok++;
else if (i == 0 && snd_mixer_selem_has_capture_switch(elem))
ok++;
} }
if (ok) { if (ok) {
sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
mixer_grpidx[elem_index] = idx; mixer_grpidx[elem_index] = idx;
mixer_type[elem_index] = i; mixer_type[elem_index] = i;
elem_index++; elem_index++;
@ -1381,6 +1439,13 @@ __again:
break; break;
} }
} }
if (snd_mixer_selem_has_capture_volume(elem)) {
mixer_grpidx[elem_index] = idx;
mixer_type[elem_index] = MIXER_ELEM_END;
elem_index++;
if (elem_index >= mixer_n_elems)
break;
}
} }
mixer_focus_elem = 0; mixer_focus_elem = 0;
@ -1501,7 +1566,7 @@ mixer_add_delta(int delta)
static int static int
mixer_iteration (void) mixer_iteration (void)
{ {
int idx, count, err; int count, err;
struct pollfd *fds; struct pollfd *fds;
int finished = 0; int finished = 0;
int key = 0; int key = 0;