[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