[pulseaudio-discuss] [PATCH 3/3 v2] role-cork: combine module-role-ducking and module-role-cork

Georg Chini georg at chini.tk
Mon Mar 23 06:35:27 PDT 2015


Combine the functionality of module-role-cork and module-role-duck.
If a volume is specified, streams will be ducked, else corked/muted.
Also allow multiple instances of the module, so that one instance can
be used for corking and one for ducking.
---
 src/modules/module-role-cork.c | 66 ++++++++++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/src/modules/module-role-cork.c b/src/modules/module-role-cork.c
index d3297d7..f096cf5 100644
--- a/src/modules/module-role-cork.c
+++ b/src/modules/module-role-cork.c
@@ -34,27 +34,33 @@
 #include "module-role-cork-symdef.h"
 
 PA_MODULE_AUTHOR("Lennart Poettering");
-PA_MODULE_DESCRIPTION("Mute & cork streams with certain roles while others exist");
+PA_MODULE_DESCRIPTION("Mute & cork or duck streams with certain roles while others exist");
 PA_MODULE_VERSION(PACKAGE_VERSION);
-PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_LOAD_ONCE(false);
 PA_MODULE_USAGE(
-        "trigger_roles=<Comma separated list of roles which will trigger a cork> "
-        "cork_roles=<Comma separated list of roles which will be corked> "
-        "global=<Should we operate globally or only inside the same device?>");
+        "trigger_roles=<Comma separated list of roles which will trigger a cork or duck> "
+        "cork_roles=<Comma separated list of roles which will be corked or ducked> "
+        "global=<Should we operate globally or only inside the same device?>"
+        "volume=<Volume for the attenuated streams. If not set, streams will be corked & muted"
+);
 
 static const char* const valid_modargs[] = {
     "trigger_roles",
     "cork_roles",
     "global",
+    "volume",
     NULL
 };
 
 struct userdata {
     pa_core *core;
+    const char *name;
     pa_hashmap *cork_state;
     pa_idxset *trigger_roles;
     pa_idxset *cork_roles;
+    pa_volume_t volume;
     bool global:1;
+    bool duck:1;
     pa_hook_slot
         *sink_input_put_slot,
         *sink_input_unlink_slot,
@@ -94,7 +100,7 @@ static bool shall_cork(struct userdata *u, pa_sink *s, pa_sink_input *ignore) {
 
         trigger_role = is_trigger_stream(u, j);
         if (trigger_role && !j->muted && pa_sink_input_get_state(j) != PA_SINK_INPUT_CORKED) {
-           pa_log_debug("Found a '%s' stream that will trigger the auto-cork.", trigger_role);
+           pa_log_debug("Found a '%s' stream that will trigger auto-cork or auto-duck.", trigger_role);
            return true;
         }
     }
@@ -132,21 +138,38 @@ static inline void apply_cork_to_sink(struct userdata *u, pa_sink *s, pa_sink_in
         corked_here = !!pa_hashmap_get(u->cork_state, j);
 
         if (cork && !corked && !j->muted) {
-            pa_log_debug("Found a '%s' stream that should be corked/muted.", cork_role);
             if (!corked_here)
                 pa_hashmap_put(u->cork_state, j, PA_INT_TO_PTR(1));
-            pa_sink_input_set_mute(j, true, false);
-            pa_sink_input_send_event(j, PA_STREAM_EVENT_REQUEST_CORK, NULL);
+
+            if (u->duck && !corked_here) {
+               pa_cvolume vol;
+               vol.channels = 1;
+               vol.values[0] = u->volume;
+
+               pa_log_debug("Found a '%s' stream that should be ducked.", cork_role);
+               pa_sink_input_add_volume_factor(j, u->name, &vol);
+            }
+            else if (!u->duck) {
+               pa_log_debug("Found a '%s' stream that should be corked/muted.", cork_role);
+               pa_sink_input_set_mute(j, true, false);
+               pa_sink_input_send_event(j, PA_STREAM_EVENT_REQUEST_CORK, NULL);
+            }
         } else if (!cork) {
             pa_hashmap_remove(u->cork_state, j);
 
-            if (corked_here && (corked || j->muted)) {
-                pa_log_debug("Found a '%s' stream that should be uncorked/unmuted.", cork_role);
-                if (j->muted)
-                    pa_sink_input_set_mute(j, false, false);
-                if (corked)
-                    pa_sink_input_send_event(j, PA_STREAM_EVENT_REQUEST_UNCORK, NULL);
+            if (corked_here && u->duck) {
+               pa_log_debug("Found a '%s' stream that should be unducked", cork_role);
+               pa_sink_input_remove_volume_factor(j, u->name);
             }
+            else if (!u->duck) {
+               if (corked_here && (corked || j->muted)) {
+                   pa_log_debug("Found a '%s' stream that should be uncorked/unmuted.", cork_role);
+                   if (j->muted)
+                       pa_sink_input_set_mute(j, false, false);
+                   if (corked)
+                       pa_sink_input_send_event(j, PA_STREAM_EVENT_REQUEST_UNCORK, NULL);
+               }
+           }
         }
     }
 }
@@ -253,6 +276,7 @@ int pa__init(pa_module *m) {
     m->userdata = u = pa_xnew(struct userdata, 1);
 
     u->core = m->core;
+    u->name = pa_sprintf_malloc("%s#%u", m->name, m->index);
     u->cork_state = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 
     u->trigger_roles = pa_idxset_new(NULL, NULL);
@@ -285,7 +309,7 @@ int pa__init(pa_module *m) {
         }
     }
     if (pa_idxset_isempty(u->cork_roles)) {
-        pa_log_debug("Using roles 'music' and 'video' as cork roles.");
+        pa_log_debug("Using roles 'music' and 'video' as cork or duck roles.");
         pa_idxset_put(u->cork_roles, pa_xstrdup("music"), NULL);
         pa_idxset_put(u->cork_roles, pa_xstrdup("video"), NULL);
     }
@@ -296,6 +320,16 @@ int pa__init(pa_module *m) {
     }
     u->global = global;
 
+    u->duck = false;
+    if (pa_modargs_get_value(ma, "volume", NULL))
+        u->duck = true;
+
+    u->volume = pa_sw_volume_from_dB(-20);
+    if (pa_modargs_get_value_volume(ma, "volume", &u->volume) < 0) {
+        pa_log("Failed to parse a volume parameter: volume");
+        goto fail;
+    }
+
     u->sink_input_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_put_cb, u);
     u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_unlink_cb, u);
     u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_move_start_cb, u);
-- 
2.1.4



More information about the pulseaudio-discuss mailing list