mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-02 09:01:48 -05:00
Implement support for dB gain display in alsamixer.
This commit is contained in:
parent
91273c228f
commit
5e3fc87888
3 changed files with 139 additions and 5 deletions
|
|
@ -504,6 +504,7 @@ int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
|
||||||
int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size);
|
int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size);
|
||||||
int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv);
|
int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv);
|
||||||
int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv);
|
int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv);
|
||||||
|
int snd_hctl_elem_get_db_gain(snd_hctl_elem_t *elem, long volume, long *db_gain);
|
||||||
|
|
||||||
snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem);
|
snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -787,6 +787,114 @@ int snd_hctl_handle_events(snd_hctl_t *hctl)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_hctl_elem_decode_tlv_db_gain(unsigned int *tlv, unsigned int tlv_size, long volume, long *db_gain)
|
||||||
|
{
|
||||||
|
unsigned int type;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int idx = 0;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
type = tlv[idx++];
|
||||||
|
size = tlv[idx++];
|
||||||
|
tlv_size -= 2 * sizeof(unsigned int);
|
||||||
|
if (size > tlv_size) {
|
||||||
|
printf("TLV size error (%i, %i, %i)!\n", type, size, tlv_size);
|
||||||
|
err=-EINVAL;
|
||||||
|
goto __exit_decode_db_gain;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case SND_CTL_TLVT_CONTAINER:
|
||||||
|
size += sizeof(unsigned int) -1;
|
||||||
|
size /= sizeof(unsigned int);
|
||||||
|
printf("TLV container!\n");
|
||||||
|
while (idx < size) {
|
||||||
|
if (tlv[idx+1] > (size - idx) * sizeof(unsigned int)) {
|
||||||
|
printf("TLV size error in compound!\n");
|
||||||
|
err=-EINVAL;
|
||||||
|
goto __exit_decode_db_gain;
|
||||||
|
}
|
||||||
|
err = snd_hctl_elem_decode_tlv_db_gain(tlv + idx, tlv[idx+1], volume, db_gain);
|
||||||
|
if (!err) break; /* db_gain obtained */
|
||||||
|
idx += 2 + (tlv[1] + sizeof(unsigned int) - 1) / sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SND_CTL_TLVT_DB_SCALE:
|
||||||
|
if (size != 2 * sizeof(unsigned int)) {
|
||||||
|
while (size > 0) {
|
||||||
|
printf("0x%x", tlv[idx++]);
|
||||||
|
size -= sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
int min,step,mute;
|
||||||
|
min = tlv[2];
|
||||||
|
step = (tlv[3] & 0xffff);
|
||||||
|
mute = (tlv[3] >> 16) & 1;
|
||||||
|
*db_gain = (volume * step) + min;
|
||||||
|
if (mute && (volume == 0)) *db_gain = -9999999;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unk-%i-", type);
|
||||||
|
while (size > 0) {
|
||||||
|
printf("0x%x", tlv[idx++]);
|
||||||
|
size -= sizeof(unsigned int);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
__exit_decode_db_gain:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get db_gain information for an HCTL element
|
||||||
|
* \param elem HCTL element
|
||||||
|
* \param volume The current control volume
|
||||||
|
* \param db_gain The return value in db_gain scale
|
||||||
|
* \return 0 otherwise a negative error code on failure
|
||||||
|
*/
|
||||||
|
int snd_hctl_elem_get_db_gain(snd_hctl_elem_t *elem, long volume, long *db_gain)
|
||||||
|
{
|
||||||
|
snd_ctl_elem_info_t *info;
|
||||||
|
unsigned int *tlv;
|
||||||
|
unsigned int tlv_size=4096;
|
||||||
|
unsigned int type;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int idx = 0;
|
||||||
|
int err=0;
|
||||||
|
|
||||||
|
snd_ctl_elem_info_alloca(&info);
|
||||||
|
snd_hctl_elem_info(elem, info);
|
||||||
|
|
||||||
|
if (tlv_size < 2 * sizeof(unsigned int)) {
|
||||||
|
printf("TLV size error!\n");
|
||||||
|
err=-EINVAL;
|
||||||
|
goto __exit_db_gain;
|
||||||
|
}
|
||||||
|
if (!snd_ctl_elem_info_is_tlv_readable(info)) {
|
||||||
|
err=-EINVAL;
|
||||||
|
goto __exit_db_gain;
|
||||||
|
}
|
||||||
|
tlv = malloc(4096);
|
||||||
|
if ((err = snd_hctl_elem_tlv_read(elem, tlv, tlv_size)) < 0) {
|
||||||
|
printf("Control element TLV read error: %s\n", snd_strerror(err));
|
||||||
|
goto __free_exit_db_gain;
|
||||||
|
}
|
||||||
|
err = snd_hctl_elem_decode_tlv_db_gain(tlv, tlv_size, volume, db_gain);
|
||||||
|
|
||||||
|
__free_exit_db_gain:
|
||||||
|
free(tlv);
|
||||||
|
__exit_db_gain:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get information for an HCTL element
|
* \brief Get information for an HCTL element
|
||||||
* \param elem HCTL element
|
* \param elem HCTL element
|
||||||
|
|
|
||||||
|
|
@ -971,12 +971,37 @@ static int get_volume_ops(snd_mixer_elem_t *elem, int dir,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dB_ops(snd_mixer_elem_t *elem ATTRIBUTE_UNUSED,
|
static int get_dB_ops(snd_mixer_elem_t *elem,
|
||||||
int dir ATTRIBUTE_UNUSED,
|
int dir,
|
||||||
snd_mixer_selem_channel_id_t channel ATTRIBUTE_UNUSED,
|
snd_mixer_selem_channel_id_t channel,
|
||||||
long *value ATTRIBUTE_UNUSED)
|
long *value)
|
||||||
{
|
{
|
||||||
return -ENXIO;
|
selem_none_t *s = snd_mixer_elem_get_private(elem);
|
||||||
|
selem_ctl_t *c;
|
||||||
|
int err = -EINVAL;
|
||||||
|
long volume, db_gain;
|
||||||
|
if (dir == SM_PLAY) {
|
||||||
|
c = &s->ctls[CTL_PLAYBACK_VOLUME];
|
||||||
|
if (c->type != 2) {
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
} else if (dir == SM_CAPT) {
|
||||||
|
c = &s->ctls[CTL_CAPTURE_VOLUME];
|
||||||
|
if (c->type != 2) {
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
} else goto _err;
|
||||||
|
if (err = get_volume_ops(elem, dir, channel, &volume)) {
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
if ((err = snd_hctl_elem_get_db_gain(c->elem, volume, &db_gain)) < 0) {
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
err = 0;
|
||||||
|
*value = db_gain;
|
||||||
|
_err:
|
||||||
|
//if (err) printf("get_dB_ops:err=%d\n",err);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_switch_ops(snd_mixer_elem_t *elem, int dir,
|
static int get_switch_ops(snd_mixer_elem_t *elem, int dir,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue