diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-05-27 16:24:15 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-27 16:24:15 +0200 |
commit | 0ee5f47624ac97fdae56d6c79e19a9324b729fa0 (patch) | |
tree | 5398baa561e0b17dcd84253cd64ea9c00f52eb36 | |
parent | 7fb12ca79b96d791119c20a5a3ad4d14fd97b49e (diff) | |
download | salsa-lib-0ee5f47624ac97fdae56d6c79e19a9324b729fa0.tar.gz |
Define the correct version of snd_tlv_parse_dB_info()
-rw-r--r-- | src/control.c | 42 | ||||
-rw-r--r-- | src/ctl_func.h | 3 | ||||
-rw-r--r-- | src/ctl_macros.h | 11 | ||||
-rw-r--r-- | src/mixer.c | 74 |
4 files changed, 53 insertions, 77 deletions
diff --git a/src/control.c b/src/control.c index 0d53f05..522f986 100644 --- a/src/control.c +++ b/src/control.c @@ -355,6 +355,48 @@ int snd_async_add_ctl_handler(snd_async_handler_t **handler, snd_ctl_t *ctl, /* max size of a TLV entry for dB information (including compound one) */ #define MAX_TLV_RANGE_SIZE 256 +/* parse dB info from the given TLV */ +int snd_tlv_parse_dB_info(unsigned int *tlv, + unsigned int tlv_size, + unsigned int **db_tlvp) +{ + unsigned int type; + unsigned int size; + int err; + + *db_tlvp = NULL; + type = tlv[0]; + size = tlv[1]; + tlv_size -= 2 * sizeof(int); + if (size > tlv_size) + return -EINVAL; + switch (type) { + case SND_CTL_TLVT_CONTAINER: + size = int_index(size) * sizeof(int); + tlv += 2; + while (size > 0) { + unsigned int len; + err = snd_tlv_parse_dB_info(tlv, size, db_tlvp); + if (err != 0) + return err; + len = int_index(tlv[1]) + 2; + size -= len * sizeof(int); + tlv += len; + } + return -EINVAL; + case SND_CTL_TLVT_DB_SCALE: + case SND_CTL_TLVT_DB_MINMAX: + case SND_CTL_TLVT_DB_MINMAX_MUTE: +#if SALSA_SUPPORT_FLOAT + case SND_CTL_TLVT_DB_LINEAR: +#endif + case SND_CTL_TLVT_DB_RANGE: + *db_tlvp = tlv; + return size + sizeof(int) * 2; + } + return 0; +} + /* convert the given raw volume value to a dB gain */ static int tlv_to_dB_range(unsigned int *tlv, long rangemin, long rangemax, diff --git a/src/ctl_func.h b/src/ctl_func.h index 491735e..87ff259 100644 --- a/src/ctl_func.h +++ b/src/ctl_func.h @@ -56,6 +56,9 @@ int snd_ctl_elem_add_boolean(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, int snd_ctl_elem_add_iec958(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id); #if SALSA_HAS_TLV_SUPPORT +int snd_tlv_parse_dB_info(unsigned int *tlv, + unsigned int tlv_size, + unsigned int **db_tlvp); int snd_tlv_get_dB_range(unsigned int *tlv, long rangemin, long rangemax, long *min, long *max); int snd_tlv_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax, diff --git a/src/ctl_macros.h b/src/ctl_macros.h index 239ecec..fae15c0 100644 --- a/src/ctl_macros.h +++ b/src/ctl_macros.h @@ -1076,15 +1076,4 @@ snd_ctl_t *snd_async_handler_get_ctl(snd_async_handler_t *handler) #endif /* SALSA_HAS_ASYNC_SUPPORT */ -#if SALSA_HAS_TLV_SUPPORT -__SALSA_EXPORT_FUNC -int snd_tlv_parse_dB_info(unsigned int *tlv, unsigned int tlv_size, - unsigned int **db_tlvp) -{ - /* just for simplicity */ - *db_tlvp = tlv; - return 0; -} -#endif /* SALSA_HAS_TLV_SUPPORT */ - #endif /* __ALSA_CTL_MACROS_H */ diff --git a/src/mixer.c b/src/mixer.c index 4c12476..11ac673 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -1004,71 +1004,8 @@ int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, #if SALSA_HAS_TLV_SUPPORT - -/* convert to index of integer array */ -#define int_index(size) (((size) + sizeof(int) - 1) / sizeof(int)) - -/* max size of a TLV entry for dB information (including compound one) */ -#define MAX_TLV_RANGE_SIZE 256 - -/* parse TLV stream and retrieve dB information - * return 0 if successly found and stored to rec, - * return 1 if no information is found, - * or return a negative error code - */ -static int parse_db_range(snd_selem_vol_item_t *item, unsigned int *tlv, - unsigned int tlv_size) -{ - unsigned int type; - unsigned int size; - int err; - - type = tlv[0]; - size = tlv[1]; - tlv_size -= 2 * sizeof(int); - if (size > tlv_size) - return -EINVAL; - switch (type) { - case SND_CTL_TLVT_CONTAINER: - size = int_index(size) * sizeof(int); - tlv += 2; - while (size > 0) { - unsigned int len; - err = parse_db_range(item, tlv, size); - if (err <= 0) - return err; /* error or found dB */ - len = int_index(tlv[1]) + 2; - size -= len * sizeof(int); - tlv += len; - } - break; - case SND_CTL_TLVT_DB_SCALE: - case SND_CTL_TLVT_DB_RANGE: { - unsigned int minsize; - if (type == SND_CTL_TLVT_DB_RANGE) - minsize = 4 * sizeof(int); - else - minsize = 2 * sizeof(int); - if (size < minsize) - return -EINVAL; - if (size > MAX_TLV_RANGE_SIZE) - return -EINVAL; - item->db_info = malloc(size + sizeof(int) * 2); - if (!item->db_info) - return -ENOMEM; - memcpy(item->db_info, tlv, size + sizeof(int) * 2); - return 0; - } - default: - break; - } - return -EINVAL; /* not found */ -} - /* * dB conversion - * - * For simplicity, we don't support the linear - log conversion */ /* initialize dB range information, reading TLV via hcontrol @@ -1078,6 +1015,7 @@ static int init_db_info(snd_selem_vol_item_t *item) snd_ctl_elem_info_t *info; unsigned int *tlv = NULL; const unsigned int tlv_size = 4096; + int size; if (!item) return -EINVAL; @@ -1091,11 +1029,16 @@ static int init_db_info(snd_selem_vol_item_t *item) goto error; tlv = malloc(tlv_size); if (!tlv) - return -ENOMEM; + goto error; if (snd_hctl_elem_tlv_read(item->head.helem, tlv, tlv_size) < 0) goto error; - if (parse_db_range(item, tlv, tlv_size) < 0) + size = snd_tlv_parse_dB_info(tlv, tlv_size, &tlv); + if (size <= 0) + goto error; + item->db_info = malloc(size); + if (!item->db_info) goto error; + memcpy(item->db_info, tlv, size); free(tlv); return 0; @@ -1105,7 +1048,6 @@ static int init_db_info(snd_selem_vol_item_t *item) return -EINVAL; } - int _snd_selem_vol_get_dB(snd_selem_vol_item_t *item, int channel, long *value) { |