forked from pool/alsa-utils
169 lines
5.3 KiB
Diff
169 lines
5.3 KiB
Diff
|
From 4f29877d54f9132219261218c2357e2b6e8910f4 Mon Sep 17 00:00:00 2001
|
||
|
From: Clemens Ladisch <clemens@ladisch.de>
|
||
|
Date: Wed, 26 May 2010 10:27:25 +0200
|
||
|
Subject: [PATCH 04/13] alsactl: correctly restore dB values of controls with changed range
|
||
|
|
||
|
When the range of a control has changed between driver versions, it is a
|
||
|
good idea to restore the same dB value of the control. However,
|
||
|
computing the dB value by interpolating betweem the min/max dB values
|
||
|
duplicates alsa-lib's TLV functions and does not even work for controls
|
||
|
with a linear dB range.
|
||
|
|
||
|
A simple conversion to dB and back can be done if we add the dB value(s)
|
||
|
to the saved state.
|
||
|
|
||
|
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
|
||
|
---
|
||
|
alsactl/state.c | 85 +++++++++++++++++++++++++++++++++++++++++-------------
|
||
|
1 files changed, 64 insertions(+), 21 deletions(-)
|
||
|
|
||
|
diff --git a/alsactl/state.c b/alsactl/state.c
|
||
|
index 815345a..538fa82 100644
|
||
|
--- a/alsactl/state.c
|
||
|
+++ b/alsactl/state.c
|
||
|
@@ -164,14 +164,18 @@ static unsigned int *str_to_tlv(const char *s)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * add the TLV string and dB ranges to comment fields
|
||
|
+ * add the TLV string, dB ranges, and dB values to comment fields
|
||
|
*/
|
||
|
static int add_tlv_comments(snd_ctl_t *handle, snd_ctl_elem_id_t *id,
|
||
|
- snd_ctl_elem_info_t *info, snd_config_t *comment)
|
||
|
+ snd_ctl_elem_info_t *info, snd_ctl_elem_value_t *ctl,
|
||
|
+ snd_config_t *comment)
|
||
|
{
|
||
|
unsigned int tlv[MAX_USER_TLV_SIZE];
|
||
|
unsigned int *db;
|
||
|
- long dbmin, dbmax;
|
||
|
+ long rangemin, rangemax;
|
||
|
+ long dbmin, dbmax, dbgain;
|
||
|
+ snd_config_t *value;
|
||
|
+ unsigned int i, count;
|
||
|
int err;
|
||
|
|
||
|
if (snd_ctl_elem_tlv_read(handle, id, tlv, sizeof(tlv)) < 0)
|
||
|
@@ -193,13 +197,35 @@ static int add_tlv_comments(snd_ctl_t *handle, snd_ctl_elem_id_t *id,
|
||
|
if (err <= 0)
|
||
|
return 0;
|
||
|
|
||
|
- snd_tlv_get_dB_range(db, snd_ctl_elem_info_get_min(info),
|
||
|
- snd_ctl_elem_info_get_max(info),
|
||
|
- &dbmin, &dbmax);
|
||
|
+ rangemin = snd_ctl_elem_info_get_min(info);
|
||
|
+ rangemax = snd_ctl_elem_info_get_max(info);
|
||
|
+ snd_tlv_get_dB_range(db, rangemin, rangemax, &dbmin, &dbmax);
|
||
|
if (err < 0)
|
||
|
return err;
|
||
|
snd_config_integer_add(comment, "dbmin", dbmin);
|
||
|
snd_config_integer_add(comment, "dbmax", dbmax);
|
||
|
+
|
||
|
+ if (snd_ctl_elem_info_get_type(info) == SND_CTL_ELEM_TYPE_INTEGER) {
|
||
|
+ err = snd_config_compound_add(comment, "dbvalue", 1, &value);
|
||
|
+ if (err < 0) {
|
||
|
+ error("snd_config_compound_add: %s", snd_strerror(err));
|
||
|
+ return err;
|
||
|
+ }
|
||
|
+ count = snd_ctl_elem_info_get_count(info);
|
||
|
+ for (i = 0; i < count; i++) {
|
||
|
+ err = snd_tlv_convert_to_dB(db, rangemin, rangemax,
|
||
|
+ snd_ctl_elem_value_get_integer(ctl, i), &dbgain);
|
||
|
+ if (err < 0) {
|
||
|
+ error("snd_tlv_convert_to_dB: %s", snd_strerror(err));
|
||
|
+ return err;
|
||
|
+ }
|
||
|
+ err = snd_config_integer_add(value, num_str(i), dbgain);
|
||
|
+ if (err < 0) {
|
||
|
+ error("snd_config_integer_add: %s", snd_strerror(err));
|
||
|
+ return err;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -302,7 +328,7 @@ static int get_control(snd_ctl_t *handle, snd_ctl_elem_id_t *id, snd_config_t *t
|
||
|
return err;
|
||
|
}
|
||
|
if (snd_ctl_elem_info_is_tlv_readable(info)) {
|
||
|
- err = add_tlv_comments(handle, id, info, comment);
|
||
|
+ err = add_tlv_comments(handle, id, info, ctl, comment);
|
||
|
if (err < 0)
|
||
|
return err;
|
||
|
}
|
||
|
@@ -930,20 +956,31 @@ static int check_comment_type(snd_config_t *conf, int type)
|
||
|
static int convert_to_new_db(snd_config_t *value, long omin, long omax,
|
||
|
long nmin, long nmax,
|
||
|
long odbmin, long odbmax,
|
||
|
- long ndbmin, long ndbmax,
|
||
|
+ snd_config_t *comment, const char *index,
|
||
|
+ snd_ctl_t *device, snd_ctl_elem_id_t *id,
|
||
|
int doit)
|
||
|
{
|
||
|
- long val;
|
||
|
- if (config_integer(value, &val, doit) < 0)
|
||
|
- return -EINVAL;
|
||
|
- if (val < omin || val > omax)
|
||
|
- return -EINVAL;
|
||
|
- val = ((val - omin) * (odbmax - odbmin)) / (omax - omin) + odbmin;
|
||
|
- if (val < ndbmin)
|
||
|
- val = ndbmin;
|
||
|
- else if (val > ndbmax)
|
||
|
- val = ndbmax;
|
||
|
- val = ((val - ndbmin) * (nmax - nmin)) / (ndbmax - ndbmin) + nmin;
|
||
|
+ snd_config_t *db_node;
|
||
|
+ long db, val;
|
||
|
+ int err;
|
||
|
+
|
||
|
+ if (snd_config_searchv(comment, &db_node, "dbvalue", index, NULL) < 0 ||
|
||
|
+ snd_config_get_integer(db_node, &db) < 0) {
|
||
|
+ err = config_integer(value, &val, doit);
|
||
|
+ if (err < 0)
|
||
|
+ return err;
|
||
|
+ if (val < omin || val > omax)
|
||
|
+ return -EINVAL;
|
||
|
+ db = ((val - omin) * (odbmax - odbmin)) / (omax - omin) + odbmin;
|
||
|
+ }
|
||
|
+
|
||
|
+ err = snd_ctl_convert_from_dB(device, id, db, &val, db > 0);
|
||
|
+ if (err < 0)
|
||
|
+ return err;
|
||
|
+ if (val < nmin)
|
||
|
+ val = nmin;
|
||
|
+ else if (val > nmax)
|
||
|
+ val = nmax;
|
||
|
return snd_config_set_integer(value, val);
|
||
|
}
|
||
|
|
||
|
@@ -961,6 +998,7 @@ static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||
|
long nmin, nmax;
|
||
|
long odbmin, odbmax;
|
||
|
long ndbmin, ndbmax;
|
||
|
+ long db;
|
||
|
snd_ctl_elem_id_t *id;
|
||
|
|
||
|
if (snd_config_search(conf, "range", &n) < 0)
|
||
|
@@ -1003,12 +1041,17 @@ static int check_comment_range(snd_ctl_t *handle, snd_config_t *conf,
|
||
|
snd_config_iterator_t i, next;
|
||
|
snd_config_for_each(i, next, value) {
|
||
|
snd_config_t *n = snd_config_iterator_entry(i);
|
||
|
+ const char *idxstr;
|
||
|
+ if (snd_config_get_id(n, &idxstr) < 0)
|
||
|
+ continue;
|
||
|
convert_to_new_db(n, omin, omax, nmin, nmax,
|
||
|
- odbmin, odbmax, ndbmin, ndbmax, doit);
|
||
|
+ odbmin, odbmax, conf, idxstr,
|
||
|
+ handle, id, doit);
|
||
|
}
|
||
|
} else
|
||
|
convert_to_new_db(value, omin, omax, nmin, nmax,
|
||
|
- odbmin, odbmax, ndbmin, ndbmax, doit);
|
||
|
+ odbmin, odbmax, conf, "0",
|
||
|
+ handle, id, doit);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
1.7.2.1
|
||
|
|