[pulseaudio-discuss] [PATCHv3 4/4] alsa: Support UCM profiles in module-alsa-card
David Henningsson
david.henningsson at canonical.com
Fri Jul 8 05:38:03 PDT 2011
On 2011-05-10 22:29, Jorge Eduardo Candelaria wrote:
> From: Margarita Olaya Cabrera<magi at slimlogic.co.uk>
>
> This patch adds ALSA UCM (Use Case Manager) support to module alsa card.
> It checks if UCM is available for each card and if found it uses the profiles
> generated with ucm data.
>
> Using a udev-rule user can decide if UCM will be used or not,
> Depending on the status of USE_UCM property, a flag is passed as
> module argument to module-alsa-card.
...but this module argument is never used (see comments further below)
>
> Signed-off-by: Margarita Olaya Cabrera<magi at slimlogic.co.uk>
> Signed-off-by: Jorge Eduardo Candelaria<jedu at slimlogic.co.uk>
> ---
> src/modules/alsa/module-alsa-card.c | 120 +++++++++++++++++++++++++++++++----
> src/modules/module-udev-detect.c | 11 +++-
> 2 files changed, 117 insertions(+), 14 deletions(-)
>
> diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
> index e60aa5e..312a42b 100644
> --- a/src/modules/alsa/module-alsa-card.c
> +++ b/src/modules/alsa/module-alsa-card.c
> @@ -39,6 +39,7 @@
> #include "alsa-util.h"
> #include "alsa-sink.h"
> #include "alsa-source.h"
> +#include "alsa-ucm.h"
> #include "module-alsa-card-symdef.h"
>
> PA_MODULE_AUTHOR("Lennart Poettering");
> @@ -66,7 +67,8 @@ PA_MODULE_USAGE(
> "profile=<profile name> "
> "ignore_dB=<ignore dB information from the device?> "
> "sync_volume=<syncronize sw and hw voluchanges in IO-thread?> "
> - "profile_set=<profile set configuration file> ");
> + "profile_set=<profile set configuration file> "
> + "use_ucm=<Load Use Case Manager> ");
>
> static const char* const valid_modargs[] = {
> "name",
> @@ -90,6 +92,7 @@ static const char* const valid_modargs[] = {
> "ignore_dB",
> "sync_volume",
> "profile_set",
> + "use_ucm",
> NULL
> };
>
> @@ -106,10 +109,8 @@ struct userdata {
> pa_modargs *modargs;
>
> pa_alsa_profile_set *profile_set;
> -};
>
> -struct profile_data {
> - pa_alsa_profile *profile;
> + pa_alsa_ucm_config ucm;
> };
>
> static void add_profiles(struct userdata *u, pa_hashmap *h) {
> @@ -207,6 +208,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
> am->source = NULL;
> }
>
"available" is misspelled below.
> + /* if UCM is avalible for this card then update the verb */
> + if (u->ucm.status == PA_ALSA_UCM_ENABLED) {
> + struct profile_data *d;
> + /* current profile */
> + d = PA_CARD_PROFILE_DATA(u->card->active_profile);
> + if (ucm_set_profile(&u->ucm, nd->profile->name, d)< 0)
> + return -1;
> + }
> +
> if (nd->profile&& nd->profile->output_mappings)
> PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) {
>
> @@ -240,15 +250,40 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
> return 0;
> }
>
> -static void init_profile(struct userdata *u) {
> +static int init_profile(struct userdata *u) {
> uint32_t idx;
> pa_alsa_mapping *am;
> struct profile_data *d;
> + char *device_name, *verb_name, *tmp;
> + struct pa_alsa_ucm_config *ucm =&u->ucm;
>
> pa_assert(u);
>
> d = PA_CARD_PROFILE_DATA(u->card->active_profile);
>
The code added below could perhaps be factored out to a separate
function in alsa-ucm.c?
> + if (u->ucm.status == PA_ALSA_UCM_ENABLED) {
> + /* Set initial verb and device */
> + verb_name = pa_xstrdup(d->profile->name);
> + tmp = strchr(verb_name, ':');
> + if (!tmp) {
> + pa_log("no new verb found for %s", d->profile->name);
> + pa_xfree(verb_name);
> + return -1;
> + }
> + *tmp = 0;
> +
> + if ((snd_use_case_set(ucm->ucm_mgr, "_verb", verb_name))< 0) {
> + pa_log("failed to set verb %s", d->profile->name);
> + return -1;
> + }
> +
> + device_name = strchr(d->profile->name, ':') + 2;
> + if (snd_use_case_set(ucm->ucm_mgr, "_enadev", device_name)< 0) {
> + pa_log("failed to set device %s", device_name);
> + return -1;
> + }
> + }
> +
> if (d->profile&& d->profile->output_mappings)
> PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx)
> am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am);
> @@ -256,6 +291,8 @@ static void init_profile(struct userdata *u) {
> if (d->profile&& d->profile->input_mappings)
> PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx)
> am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am);
> +
> + return 0;
> }
>
> static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *device_id) {
> @@ -284,6 +321,56 @@ static void set_card_name(pa_card_new_data *data, pa_modargs *ma, const char *de
> pa_xfree(t);
> }
>
The below function could perhaps be moved to alsa-ucm.c? It seems to be
very...well, UCM'y :-)
> +static int card_query_ucm_profiles(struct userdata *u, int card_index)
> +{
> + char *card_name;
> + const char **verb_list;
> + int num_verbs, i, err;
> +
> + /* is UCM available for this card ? */
> + snd_card_get_name(card_index,&card_name);
> + err = snd_use_case_mgr_open(&u->ucm.ucm_mgr, card_name);
> + if (err< 0) {
"available" is misspelled below.
> + pa_log("UCM not avaliable for card %s", card_name);
> + u->ucm.status = PA_ALSA_UCM_DISABLED;
> + return 0;
> + }
> +
"available" is misspelled below.
> + pa_log_info("UCM avaliable for card %s", card_name);
> +
> + /* get a list of all UCM verbs (profiles) for this card */
> + num_verbs = snd_use_case_verb_list(u->ucm.ucm_mgr,&verb_list);
> + if (num_verbs<= 0) {
> + pa_log("UCM verb list not found for %s", card_name);
> + return 0;
> + }
> +
> + /* get the properties of each UCM verb */
> + for (i = 0; i< num_verbs; i += 2) {
> + struct pa_alsa_ucm_verb *verb;
> +
> + verb = pa_xnew0(pa_alsa_ucm_verb, 1);
> + verb->proplist = pa_proplist_new();
> +
> + /* Get devices and modifiers for each verb */
> + err = ucm_get_properties(verb, u->ucm.ucm_mgr, verb_list[i]);
> + if (err< 0) {
> + pa_log("Failed to set the verb %s", verb_list[i]);
> + continue;
> + }
> +
> + pa_proplist_sets(verb->proplist, PA_PROP_UCM_NAME, verb_list[i]);
> + PA_LLIST_PREPEND(pa_alsa_ucm_verb, u->ucm.verbs, verb);
> + }
> +
> + /* create the profile set for the UCM card */
> + u->profile_set = add_ucm_profile_set(&u->ucm,&u->core->default_channel_map);
> + pa_alsa_profile_set_dump(u->profile_set);
> +
> + u->ucm.status = PA_ALSA_UCM_ENABLED;
> + return 1;
> +}
> +
> int pa__init(pa_module *m) {
> pa_card_new_data data;
> pa_modargs *ma;
> @@ -292,7 +379,7 @@ int pa__init(pa_module *m) {
> pa_reserve_wrapper *reserve = NULL;
> const char *description;
> char *fn = NULL;
> - pa_bool_t namereg_fail = FALSE;
> + pa_bool_t namereg_fail = FALSE, use_ucm = FALSE;
The use_ucm variable is declared but never used.
>
> pa_alsa_refcnt_inc();
>
> @@ -325,19 +412,23 @@ int pa__init(pa_module *m) {
> goto fail;
> }
> }
> -
> + /* Check availability of UCM profiles */
> + if (card_query_ucm_profiles(u, alsa_card_index))
Shouldn't you check the use_ucm module argument and use that as a
precondition for calling this function?
> + pa_log_info("Found UCM profiles");
> + else {
> #ifdef HAVE_UDEV
> - fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET");
> + fn = pa_udev_get_property(alsa_card_index, "PULSE_PROFILE_SET");
> #endif
>
> - if (pa_modargs_get_value(ma, "profile_set", NULL)) {
> + if (pa_modargs_get_value(ma, "profile_set", NULL)) {
> + pa_xfree(fn);
> + fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL));
> + }
> +
> + u->profile_set = pa_alsa_profile_set_new(fn,&u->core->default_channel_map);
> pa_xfree(fn);
> - fn = pa_xstrdup(pa_modargs_get_value(ma, "profile_set", NULL));
> }
>
> - u->profile_set = pa_alsa_profile_set_new(fn,&u->core->default_channel_map);
> - pa_xfree(fn);
> -
> if (!u->profile_set)
> goto fail;
>
> @@ -462,6 +553,9 @@ void pa__done(pa_module*m) {
> pa_alsa_source_free(s);
> }
>
> + if (u->ucm.status == PA_ALSA_UCM_ENABLED)
> + free_ucm(&u->ucm);
> +
> if (u->card)
> pa_card_free(u->card);
>
> diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
> index 63ad195..4fa48ba 100644
> --- a/src/modules/module-udev-detect.c
> +++ b/src/modules/module-udev-detect.c
> @@ -51,6 +51,7 @@ PA_MODULE_USAGE(
> struct device {
> char *path;
> pa_bool_t need_verify;
> + pa_bool_t use_ucm;
> char *card_name;
> char *args;
> uint32_t module;
> @@ -383,6 +384,12 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
>
> n = pa_namereg_make_valid_name(t);
> d->card_name = pa_sprintf_malloc("alsa_card.%s", n);
> +
> + if (udev_device_get_property_value(dev, "USE_UCM"))
> + d->use_ucm = TRUE;
> + else
> + d->use_ucm = FALSE;
> +
> d->args = pa_sprintf_malloc("device_id=\"%s\" "
> "name=\"%s\" "
> "card_name=\"%s\" "
> @@ -390,13 +397,15 @@ static void card_changed(struct userdata *u, struct udev_device *dev) {
> "tsched=%s "
> "ignore_dB=%s "
> "sync_volume=%s "
> + "use_ucm=%d "
> "card_properties=\"module-udev-detect.discovered=1\"",
> path_get_card_id(path),
> n,
> d->card_name,
> pa_yes_no(u->use_tsched),
> pa_yes_no(u->ignore_dB),
> - pa_yes_no(u->sync_volume));
> + pa_yes_no(u->sync_volume),
> + d->use_ucm);
> pa_xfree(n);
>
> pa_hashmap_put(u->devices, d->path, d);
--
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic
More information about the pulseaudio-discuss
mailing list