mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-22 18:06:30 +01:00
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:
parent
3ed9466bce
commit
d81f16b7fa
1 changed files with 151 additions and 86 deletions
|
@ -196,6 +196,11 @@ static char mixer_device_name[128];
|
|||
#define MIXER_MASK_STEREO (MIXER_MASK_LEFT|MIXER_MASK_RIGHT)
|
||||
|
||||
/* mixer split types */
|
||||
enum {
|
||||
MIXER_STREAM_PLAYBACK, MIXER_STREAM_CAPTURE,
|
||||
MIXER_STREAM_END
|
||||
};
|
||||
|
||||
enum {
|
||||
MIXER_ELEM_FRONT, MIXER_ELEM_REAR,
|
||||
MIXER_ELEM_CENTER, MIXER_ELEM_WOOFER,
|
||||
|
@ -468,13 +473,16 @@ mixer_conv(int val, int omin, int omax, int nmin, int nmax)
|
|||
|
||||
static int
|
||||
mixer_calc_volume(snd_mixer_elem_t *elem,
|
||||
int vol,
|
||||
int vol, int stream,
|
||||
snd_mixer_selem_channel_id_t chn)
|
||||
{
|
||||
int vol1;
|
||||
long v;
|
||||
long min, max;
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
||||
if (stream == MIXER_STREAM_PLAYBACK)
|
||||
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;
|
||||
if (vol1 > 0) {
|
||||
if (vol1 > 100)
|
||||
|
@ -486,7 +494,10 @@ mixer_calc_volume(snd_mixer_elem_t *elem,
|
|||
if (vol < 0)
|
||||
vol1 = -vol1;
|
||||
}
|
||||
snd_mixer_selem_get_playback_volume(elem, chn, &v);
|
||||
if (stream == MIXER_STREAM_PLAYBACK)
|
||||
snd_mixer_selem_get_playback_volume(elem, chn, &v);
|
||||
else
|
||||
snd_mixer_selem_get_capture_volume(elem, chn, &v);
|
||||
vol1 += v;
|
||||
return CLAMP(vol1, min, max);
|
||||
}
|
||||
|
@ -498,7 +509,7 @@ mixer_write_cbar (int elem_index)
|
|||
{
|
||||
snd_mixer_elem_t *elem;
|
||||
int vleft, vright, vbalance;
|
||||
int type;
|
||||
int type, stream;
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_selem_channel_id_t chn_left, chn_right, chn;
|
||||
int sw;
|
||||
|
@ -510,57 +521,77 @@ mixer_write_cbar (int elem_index)
|
|||
elem = snd_mixer_find_selem(mixer_handle, sid);
|
||||
if (elem == NULL)
|
||||
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];
|
||||
if (!snd_mixer_selem_has_playback_channel(elem, chn_left))
|
||||
return; /* ..??.. */
|
||||
chn_right = mixer_elem_chn[type][MIXER_CHN_RIGHT];
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
||||
!snd_mixer_selem_has_playback_channel(elem, chn_right))
|
||||
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))
|
||||
chn_right = SND_MIXER_SCHN_UNKNOWN;
|
||||
} else {
|
||||
if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
|
||||
chn_right = SND_MIXER_SCHN_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* volume
|
||||
*/
|
||||
if ((mixer_volume_delta[MIXER_CHN_LEFT] ||
|
||||
mixer_volume_delta[MIXER_CHN_RIGHT] ||
|
||||
mixer_balance_volumes) &&
|
||||
snd_mixer_selem_has_playback_volume(elem)) {
|
||||
int mono =
|
||||
(chn_right == SND_MIXER_SCHN_UNKNOWN ||
|
||||
snd_mixer_selem_has_playback_volume_joined(elem));
|
||||
((stream == MIXER_STREAM_PLAYBACK && snd_mixer_selem_has_playback_volume(elem)) ||
|
||||
(stream == MIXER_STREAM_CAPTURE && snd_mixer_selem_has_capture_volume(elem)))) {
|
||||
int mono;
|
||||
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])
|
||||
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;
|
||||
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 /= 2;
|
||||
} else
|
||||
vright = vleft;
|
||||
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++)
|
||||
if (snd_mixer_selem_has_playback_channel(elem, chn))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn, vleft);
|
||||
if (snd_mixer_selem_has_capture_channel(elem, chn))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn, vleft);
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (snd_mixer_selem_has_playback_channel(elem, chn))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn, vleft);
|
||||
} else {
|
||||
if (snd_mixer_selem_has_capture_channel(elem, chn))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn, vleft);
|
||||
}
|
||||
} else {
|
||||
if (mixer_balance_volumes)
|
||||
vleft = vright = vbalance;
|
||||
if (snd_mixer_selem_has_playback_volume(elem) &&
|
||||
snd_mixer_selem_has_playback_channel(elem, chn_left))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
|
||||
if (snd_mixer_selem_has_capture_volume(elem) &&
|
||||
snd_mixer_selem_has_capture_channel(elem, chn_left))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
|
||||
if (! mono) {
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (snd_mixer_selem_has_playback_volume(elem) &&
|
||||
snd_mixer_selem_has_playback_channel(elem, chn_right))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
|
||||
snd_mixer_selem_has_playback_channel(elem, chn_left))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn_left, vleft);
|
||||
} else {
|
||||
if (snd_mixer_selem_has_capture_volume(elem) &&
|
||||
snd_mixer_selem_has_capture_channel(elem, chn_right))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
|
||||
snd_mixer_selem_has_capture_channel(elem, chn_left))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn_left, vleft);
|
||||
}
|
||||
if (! mono) {
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (snd_mixer_selem_has_playback_volume(elem) &&
|
||||
snd_mixer_selem_has_playback_channel(elem, chn_right))
|
||||
snd_mixer_selem_set_playback_volume(elem, chn_right, vright);
|
||||
} else {
|
||||
if (snd_mixer_selem_has_capture_volume(elem) &&
|
||||
snd_mixer_selem_has_capture_channel(elem, chn_right))
|
||||
snd_mixer_selem_set_capture_volume(elem, chn_right, vright);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -570,19 +601,21 @@ mixer_write_cbar (int elem_index)
|
|||
|
||||
/* mute
|
||||
*/
|
||||
if (mixer_toggle_mute && snd_mixer_selem_has_playback_switch(elem)) {
|
||||
if (snd_mixer_selem_has_playback_switch_joined(elem)) {
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_playback_switch_all(elem, !sw);
|
||||
} else {
|
||||
if (mixer_toggle_mute & MIXER_MASK_LEFT) {
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (mixer_toggle_mute && snd_mixer_selem_has_playback_switch(elem)) {
|
||||
if (snd_mixer_selem_has_playback_switch_joined(elem)) {
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_playback_switch(elem, chn_left, !sw);
|
||||
}
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
||||
(mixer_toggle_mute & MIXER_MASK_RIGHT)) {
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_right, &sw);
|
||||
snd_mixer_selem_set_playback_switch(elem, chn_right, !sw);
|
||||
snd_mixer_selem_set_playback_switch_all(elem, !sw);
|
||||
} else {
|
||||
if (mixer_toggle_mute & MIXER_MASK_LEFT) {
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_playback_switch(elem, chn_left, !sw);
|
||||
}
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
||||
(mixer_toggle_mute & MIXER_MASK_RIGHT)) {
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_right, &sw);
|
||||
snd_mixer_selem_set_playback_switch(elem, chn_right, !sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -590,19 +623,21 @@ mixer_write_cbar (int elem_index)
|
|||
|
||||
/* capture
|
||||
*/
|
||||
if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
|
||||
if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_capture_switch_all(elem, !sw);
|
||||
} else {
|
||||
if (mixer_toggle_capture & MIXER_MASK_LEFT) {
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (mixer_toggle_capture && snd_mixer_selem_has_capture_switch(elem)) {
|
||||
if (snd_mixer_selem_has_capture_switch_joined(elem)) {
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_capture_switch(elem, chn_left, !sw);
|
||||
}
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
||||
(mixer_toggle_capture & MIXER_MASK_RIGHT)) {
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_right, &sw);
|
||||
snd_mixer_selem_set_capture_switch(elem, chn_right, !sw);
|
||||
snd_mixer_selem_set_capture_switch_all(elem, !sw);
|
||||
} else {
|
||||
if (mixer_toggle_capture & MIXER_MASK_LEFT) {
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_left, &sw);
|
||||
snd_mixer_selem_set_capture_switch(elem, chn_left, !sw);
|
||||
}
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN &&
|
||||
(mixer_toggle_capture & MIXER_MASK_RIGHT)) {
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_right, &sw);
|
||||
snd_mixer_selem_set_capture_switch(elem, chn_right, !sw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -617,10 +652,9 @@ mixer_update_cbar (int elem_index)
|
|||
int dc;
|
||||
snd_mixer_elem_t *elem;
|
||||
long vleft, vright;
|
||||
int type;
|
||||
int type, stream;
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_selem_channel_id_t chn_left, chn_right;
|
||||
snd_mixer_selem_channel_id_t cchn_right;
|
||||
int x, y, i;
|
||||
int swl, swr;
|
||||
|
||||
|
@ -634,19 +668,22 @@ mixer_update_cbar (int elem_index)
|
|||
if (elem == NULL)
|
||||
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];
|
||||
if (!snd_mixer_selem_has_playback_channel(elem, chn_left))
|
||||
return; /* ..??.. */
|
||||
cchn_right = 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 (!snd_mixer_selem_has_playback_channel(elem, chn_right))
|
||||
chn_right = SND_MIXER_SCHN_UNKNOWN;
|
||||
if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
|
||||
cchn_right = SND_MIXER_SCHN_UNKNOWN;
|
||||
if (stream == MIXER_STREAM_PLAYBACK) {
|
||||
if (!snd_mixer_selem_has_playback_channel(elem, chn_right))
|
||||
chn_right = SND_MIXER_SCHN_UNKNOWN;
|
||||
} else {
|
||||
if (!snd_mixer_selem_has_capture_channel(elem, chn_right))
|
||||
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;
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax);
|
||||
snd_mixer_selem_get_playback_volume(elem, chn_left, &vleft);
|
||||
|
@ -657,8 +694,20 @@ mixer_update_cbar (int elem_index)
|
|||
} else {
|
||||
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
|
||||
*/
|
||||
|
@ -671,6 +720,8 @@ mixer_update_cbar (int elem_index)
|
|||
string1[i] = ' ';
|
||||
string1[63] = '\0';
|
||||
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)
|
||||
sprintf(string + strlen(string), " %i", snd_mixer_selem_id_get_index(sid));
|
||||
string[63] = '\0';
|
||||
|
@ -748,7 +799,7 @@ mixer_update_cbar (int elem_index)
|
|||
*/
|
||||
mixer_dc (DC_BACK);
|
||||
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);
|
||||
mvaddch (y, x + 2, ACS_ULCORNER);
|
||||
snd_mixer_selem_get_playback_switch(elem, chn_left, &swl);
|
||||
|
@ -770,21 +821,21 @@ mixer_update_cbar (int elem_index)
|
|||
}
|
||||
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);
|
||||
if (cchn_right != SND_MIXER_SCHN_UNKNOWN)
|
||||
snd_mixer_selem_get_capture_switch(elem, cchn_right, &swr);
|
||||
if (swl || (cchn_right != SND_MIXER_SCHN_UNKNOWN && swr)) {
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN)
|
||||
snd_mixer_selem_get_capture_switch(elem, chn_right, &swr);
|
||||
if (swl || (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)) {
|
||||
mixer_dc (DC_CBAR_CAPTURE);
|
||||
mvaddstr (y, x + 1, "CAPTUR");
|
||||
if (swl) {
|
||||
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");
|
||||
}
|
||||
if (cchn_right != SND_MIXER_SCHN_UNKNOWN && swr)
|
||||
if (chn_right != SND_MIXER_SCHN_UNKNOWN && swr)
|
||||
mvaddstr (y + 1, x + 6, "R");
|
||||
} else {
|
||||
for (i = 0; i < 6; i++)
|
||||
|
@ -1337,14 +1388,18 @@ __again:
|
|||
for (i = 0; i < MIXER_ELEM_END; i++) {
|
||||
int ok;
|
||||
for (j = ok = 0; j < 2; j++) {
|
||||
if (mixer_changed_state)
|
||||
goto __again;
|
||||
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
||||
if (mixer_changed_state)
|
||||
goto __again;
|
||||
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
||||
ok++;
|
||||
else if (i == 0 && snd_mixer_selem_has_capture_switch(elem))
|
||||
ok++;
|
||||
}
|
||||
if (ok)
|
||||
mixer_n_elems++;
|
||||
}
|
||||
if (snd_mixer_selem_has_capture_volume(elem))
|
||||
mixer_n_elems++;
|
||||
}
|
||||
|
||||
if (mixer_type)
|
||||
|
@ -1368,19 +1423,29 @@ __again:
|
|||
for (i = 0; i < MIXER_ELEM_END; i++) {
|
||||
int ok;
|
||||
for (j = ok = 0; j < 2; j++) {
|
||||
if (mixer_changed_state)
|
||||
goto __again;
|
||||
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
||||
ok++;
|
||||
if (mixer_changed_state)
|
||||
goto __again;
|
||||
if (snd_mixer_selem_has_playback_channel(elem, mixer_elem_chn[i][j]))
|
||||
ok++;
|
||||
else if (i == 0 && snd_mixer_selem_has_capture_switch(elem))
|
||||
ok++;
|
||||
}
|
||||
if (ok) {
|
||||
sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * idx);
|
||||
mixer_grpidx[elem_index] = idx;
|
||||
mixer_type[elem_index] = i;
|
||||
elem_index++;
|
||||
if (elem_index >= mixer_n_elems)
|
||||
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;
|
||||
|
@ -1501,7 +1566,7 @@ mixer_add_delta(int delta)
|
|||
static int
|
||||
mixer_iteration (void)
|
||||
{
|
||||
int idx, count, err;
|
||||
int count, err;
|
||||
struct pollfd *fds;
|
||||
int finished = 0;
|
||||
int key = 0;
|
||||
|
|
Loading…
Reference in a new issue