[pulseaudio-discuss] [PATCH v2] role-ducking: Add support for ducking group

Tanu Kaskinen tanuk at iki.fi
Sat Mar 26 11:42:58 UTC 2016


On Sat, 2016-03-26 at 00:07 +0900, Sangchul Lee wrote:
> Now, trigger_roles, ducking_roles and volume can be divided into several groups by slash.
> That means each group can be affected by its own volume policy.
> 
> If we need to apply ducking volume level differently that is triggered
> from each trigger role(s), this feature would be useful for this purpose.
> 
> For example, let's assume that tts should take music and video's volume down to 40%
> whereas voice_recognition should take those and tts's volume down to 20%.
> In this case, the configuration can be written as below.
>   trigger_roles=tts/voice_recognition ducking_roles=music,video/music,video,tts volume=40%/20%
> 
> If one of ducking role is affected by more than two trigger roles simultaneously,
> volume of the ducking role will be applied by method of multiplication.
> And it works in the same way as before without any slash.
> 
> Signed-off-by: Sangchul Lee <sc11.lee at samsung.com>
> ---
> 
> Notes:
>  v2 changelog: revise codes according to Tanu's comments
>   - commit message enhancement
>   - definition of group structure
>   - rename variable and revise logs
>   - handle error case of empty parsed string
> 
>  it would be integrated with the latest upstream codes in the next update(v3)
> 
>  src/modules/module-role-ducking.c | 241 +++++++++++++++++++++++++++-----------
>  1 file changed, 175 insertions(+), 66 deletions(-)

Looks pretty good. A few comments still below.

> +typedef struct group {
> +    char *name;
>      pa_idxset *trigger_roles;
>      pa_idxset *ducking_roles;
>      pa_idxset *ducked_inputs;
> -    bool global;
>      pa_volume_t volume;
> +} group;

The convention in PulseAudio is to not use typedefs on private structs.
See how "struct userdata" is defined: the definition doesn't use a
typedef.

> -static bool sink_has_trigger_streams(struct userdata *u, pa_sink *s, pa_sink_input *ignore) {
> +static bool sink_has_trigger_streams(struct userdata *u, pa_sink *s, pa_sink_input *ignore, uint32_t group_idx) {

Rather than passing the group index as a parameter, you can just give a
direct pointer to the group (this same comment applies to all functions
that you pass group_idx as a parameter).

> @@ -230,41 +248,137 @@ int pa__init(pa_module *m) {
>      u->core = m->core;
>      u->name = m->name;
>  
> -    u->ducked_inputs = pa_idxset_new(NULL, NULL);
> -
> -    u->trigger_roles = pa_idxset_new(NULL, NULL);
>      roles = pa_modargs_get_value(ma, "trigger_roles", NULL);
>      if (roles) {
>          const char *split_state = NULL;
>          char *n = NULL;
> -        while ((n = pa_split(roles, ",", &split_state))) {
> -            if (n[0] != '\0')
> -                pa_idxset_put(u->trigger_roles, n, NULL);
> -            else
> -                pa_xfree(n);
> +        while ((n = pa_split(roles, "/", &split_state))) {
> +            group_count_tr++;
> +            pa_xfree(n);
> +        }
> +    }
> +    roles = pa_modargs_get_value(ma, "ducking_roles", NULL);
> +    if (roles) {
> +        const char *split_state = NULL;
> +        char *n = NULL;
> +        while ((n = pa_split(roles, "/", &split_state))) {
> +            group_count_du++;
> +            pa_xfree(n);
> +        }
> +    }
> +    volumes = pa_modargs_get_value(ma, "volume", NULL);
> +    if (volumes) {
> +        const char *split_state = NULL;
> +        char *n = NULL;
> +        while ((n = pa_split(volumes, "/", &split_state))) {
> +            group_count_vol++;
> +            pa_xfree(n);
> +        }
> +    }
> +
> +    if ((group_count_tr > 1 || group_count_du > 1 || group_count_vol > 1) &&
> +        ((group_count_tr != group_count_du) || (group_count_tr != group_count_vol))) {
> +        pa_log("Invalid number of groups");
> +        goto fail;
> +    }
> +
> +    if (group_count_tr > 0)
> +        u->n_groups = group_count_tr;
> +    else
> +        u->n_groups = 1;
> +
> +    u->groups = pa_xmalloc0(u->n_groups * sizeof(group*));
> +    for (i = 0; i < u->n_groups; i++) {
> +        u->groups[i] = pa_xmalloc0(sizeof(group));
> +        u->groups[i]->name = pa_sprintf_malloc("%s_group_%u", u->name, i);
> +        u->groups[i]->trigger_roles = pa_idxset_new(NULL, NULL);
> +        u->groups[i]->ducking_roles = pa_idxset_new(NULL, NULL);
> +        u->groups[i]->ducked_inputs = pa_idxset_new(NULL, NULL);
> +    }
> +
> +    roles = pa_modargs_get_value(ma, "trigger_roles", NULL);
> +    if (roles) {
> +        const char *group_split_state = NULL;
> +        char *roles_in_groups = NULL;

In v1 this variable was called "roles_in_group". That was a better
name, because the string contains roles for only one group.

-- 
Tanu


More information about the pulseaudio-discuss mailing list