From f0d540f851de3992a5e285dcea0be7cab293527e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 2 Nov 2021 10:55:45 +0100 Subject: [PATCH] pcm: partially revert "pcm: softvol - make snd_pcm_parse_control_id private" This reverts partially commit b9a4997e92e4c16147fcf96453a4c3e08080ac66. It seems that we have have some users for this very specific function. Mark it deprecated and keep the softvol implementation separate, so we can remove this function easily in future. Fixes: https://github.com/alsa-project/alsa-lib/issues/186 Signed-off-by: Jaroslav Kysela --- include/pcm_external.h | 2 +- src/pcm/pcm_misc.c | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/include/pcm_external.h b/include/pcm_external.h index 204a450c..a6005b34 100644 --- a/include/pcm_external.h +++ b/include/pcm_external.h @@ -59,7 +59,7 @@ int SND_PCM_PLUGIN_ENTRY(plugin) (snd_pcm_t **pcmp, const char *name,\ #include "pcm_extplug.h" int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp, - int *cchannelsp, int *hwctlp); + int *cchannelsp, int *hwctlp) __attribute__((deprecated)); /** \} */ diff --git a/src/pcm/pcm_misc.c b/src/pcm/pcm_misc.c index 34ea438c..ce8d8189 100644 --- a/src/pcm/pcm_misc.c +++ b/src/pcm/pcm_misc.c @@ -753,3 +753,136 @@ snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, return linear_formats[width][!!unsignd][!!big_endian]; } } + +/** + * \brief Parse control element id from the config + * \param conf the config tree to parse + * \param ctl_id the pointer to store the resultant control element id + * \param cardp the pointer to store the card index + * \param cchannelsp the pointer to store the number of channels (optional) + * \param hwctlp the pointer to store the h/w control flag (optional) + * \return 0 if successful, or a negative error code + * + * \deprecated Since 1.2.5 + * This function parses the given config tree to retrieve the control element id + * and the card index. It's used by softvol. External PCM plugins can use this + * function for creating or assigining their controls. + * + * cchannelsp and hwctlp arguments are optional. Set NULL if not necessary. + */ +int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp, + int *cchannelsp, int *hwctlp) +{ + snd_config_iterator_t i, next; + int iface = SND_CTL_ELEM_IFACE_MIXER; + const char *name = NULL; + long index = 0; + long device = -1; + long subdevice = -1; + int err; + + assert(ctl_id && cardp); + + *cardp = -1; + if (cchannelsp) + *cchannelsp = 2; + snd_config_for_each(i, next, conf) { + snd_config_t *n = snd_config_iterator_entry(i); + const char *id; + if (snd_config_get_id(n, &id) < 0) + continue; + if (strcmp(id, "comment") == 0) + continue; + if (strcmp(id, "card") == 0) { + err = snd_config_get_card(n); + if (err < 0) + goto _err; + *cardp = err; + continue; + } + if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) { + const char *ptr; + if ((err = snd_config_get_string(n, &ptr)) < 0) { + SNDERR("field %s is not a string", id); + goto _err; + } + if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) { + SNDERR("Invalid value for '%s'", id); + goto _err; + } + iface = err; + continue; + } + if (strcmp(id, "name") == 0) { + if ((err = snd_config_get_string(n, &name)) < 0) { + SNDERR("field %s is not a string", id); + goto _err; + } + continue; + } + if (strcmp(id, "index") == 0) { + if ((err = snd_config_get_integer(n, &index)) < 0) { + SNDERR("field %s is not an integer", id); + goto _err; + } + continue; + } + if (strcmp(id, "device") == 0) { + if ((err = snd_config_get_integer(n, &device)) < 0) { + SNDERR("field %s is not an integer", id); + goto _err; + } + continue; + } + if (strcmp(id, "subdevice") == 0) { + if ((err = snd_config_get_integer(n, &subdevice)) < 0) { + SNDERR("field %s is not an integer", id); + goto _err; + } + continue; + } + if (cchannelsp && strcmp(id, "count") == 0) { + long v; + if ((err = snd_config_get_integer(n, &v)) < 0) { + SNDERR("field %s is not an integer", id); + goto _err; + } + if (v < 1 || v > 2) { + SNDERR("Invalid count %ld", v); + goto _err; + } + *cchannelsp = v; + continue; + } + if (hwctlp && strcmp(id, "hwctl") == 0) { + if ((err = snd_config_get_bool(n)) < 0) { + SNDERR("The field %s must be a boolean type", id); + return err; + } + *hwctlp = err; + continue; + } + SNDERR("Unknown field %s", id); + return -EINVAL; + } + if (name == NULL) { + SNDERR("Missing control name"); + err = -EINVAL; + goto _err; + } + if (device < 0) + device = 0; + if (subdevice < 0) + subdevice = 0; + + snd_ctl_elem_id_set_interface(ctl_id, iface); + snd_ctl_elem_id_set_name(ctl_id, name); + snd_ctl_elem_id_set_index(ctl_id, index); + snd_ctl_elem_id_set_device(ctl_id, device); + snd_ctl_elem_id_set_subdevice(ctl_id, subdevice); + + return 0; + + _err: + return err; +}