From 973a8e9b825a5ffa0e2d96f2e86798d5b1cf6303 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 19 Jul 2019 14:56:14 +0900 Subject: [PATCH] stream-manager: Improve audio ducking function 1. Fix crash : If ducked stream is removed without deactivating, the pointer for the removed stream is still remained in idxset of ducking_streams. It caused crash when ducking stream is destroyed. 2. Apply ducking to new stream : If new role-matched stream is created when after ducked, apply ducking to it without fade-out. [Version] 11.1.60 [Issue Type] Improvement Change-Id: Ida0556e5d8c1d10f001357291ca17193174c26ae Signed-off-by: Jeongmo Yang --- packaging/pulseaudio-modules-tizen.spec | 2 +- src/stream-manager-dbus.c | 24 +++++++------ src/stream-manager-priv.h | 10 ++++-- src/stream-manager.c | 62 +++++++++++++++++++++++++++++++-- 4 files changed, 82 insertions(+), 16 deletions(-) diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 3d5462c..3cfa404 100644 --- a/packaging/pulseaudio-modules-tizen.spec +++ b/packaging/pulseaudio-modules-tizen.spec @@ -1,6 +1,6 @@ Name: pulseaudio-modules-tizen Summary: Pulseaudio modules for Tizen -Version: 11.1.59 +Version: 11.1.60 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/stream-manager-dbus.c b/src/stream-manager-dbus.c index 7df7710..1825221 100644 --- a/src/stream-manager-dbus.c +++ b/src/stream-manager-dbus.c @@ -1810,6 +1810,13 @@ static void handle_activate_ducking(DBusConnection *conn, DBusMessage *msg, void /* get stream_ducking */ pa_assert_se((sd = pa_hashmap_get(m->stream_duckings, (const void*)id))); + if (enable) { + snprintf(sd->vol_key, VOLUME_KEY_LENGTH, "stream_ducking_%u_%s", id, target_stream); + snprintf(sd->target_role, STREAM_ROLE_STR_MAX, "%s", target_stream); + sd->duration = duration; + sd->set_vol = PA_VOLUME_NORM * ratio; + } + /* set volume ramp factor to target stream */ PA_IDXSET_FOREACH(stream, m->core->sink_inputs, idx) { if (!pa_safe_streq(target_stream, pa_proplist_gets(stream->proplist, PA_PROP_MEDIA_ROLE))) @@ -1819,25 +1826,22 @@ static void handle_activate_ducking(DBusConnection *conn, DBusMessage *msg, void sd->ducking_stream_count++; if (enable) { - pa_volume_t set_vol; pa_cvolume_ramp vol_ramp; - snprintf(sd->vol_ramp_key, VOLUME_RAMP_KEY_LENGTH, "stream_ducking_%u_%s", id, target_stream); - pa_idxset_put(sd->idx_ducking_streams, (void *)stream, NULL); - set_vol = PA_VOLUME_NORM * ratio; - - pa_log_info("ducking: [%p] set vol [%u], key [%s]", stream, set_vol, sd->vol_ramp_key); + pa_log_info("ducking: [%p] set vol [%u], key [%s], role [%s]", + stream, sd->set_vol, sd->vol_key, sd->target_role); pa_cvolume_ramp_set(&vol_ramp, stream->volume.channels, - PA_VOLUME_RAMP_TYPE_LINEAR, (long)duration, set_vol); + PA_VOLUME_RAMP_TYPE_LINEAR, (long)duration, sd->set_vol); - pa_sink_input_add_volume_ramp_factor(stream, sd->vol_ramp_key, &vol_ramp, true); + pa_sink_input_add_volume_ramp_factor(stream, sd->vol_key, &vol_ramp, true); } else { - pa_log_info("unducking : remove volume ramp factor [key:%s]", sd->vol_ramp_key); + pa_log_info("unducking : remove volume(ramp) factor [key:%s]", sd->vol_key); - pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_ramp_key, true); + pa_sink_input_remove_volume_factor(stream, sd->vol_key); + pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_key, true); } } diff --git a/src/stream-manager-priv.h b/src/stream-manager-priv.h index ab5488d..d7449e5 100644 --- a/src/stream-manager-priv.h +++ b/src/stream-manager-priv.h @@ -113,7 +113,8 @@ typedef enum _notify_command_type { #define STREAM_FOCUS_STATE_RELEASED "0" #define STREAM_FOCUS_STATE_ACQUIRED "1" -#define VOLUME_RAMP_KEY_LENGTH 24 +#define VOLUME_KEY_LENGTH 24 +#define STREAM_ROLE_STR_MAX 32 #define AVAIL_DEVICES_MAX 16 #define AVAIL_FRAMEWORKS_MAX 16 @@ -194,11 +195,14 @@ typedef struct _stream_parent { } stream_parent; typedef struct _stream_ducking { + bool is_ducked; int trigger_index; int ducking_stream_count; + char vol_key[VOLUME_KEY_LENGTH]; + char target_role[STREAM_ROLE_STR_MAX]; + uint32_t duration; + pa_volume_t set_vol; pa_idxset *idx_ducking_streams; - char vol_ramp_key[VOLUME_RAMP_KEY_LENGTH]; - bool is_ducked; } stream_ducking; typedef struct _filter_info { diff --git a/src/stream-manager.c b/src/stream-manager.c index 9c6a00b..5537ba9 100644 --- a/src/stream-manager.c +++ b/src/stream-manager.c @@ -2184,6 +2184,58 @@ static void remove_sink_input_from_muted_streams(pa_stream_manager *m, pa_sink_i pa_idxset_remove_by_data(streams, i, NULL); } +/* Remove the sink-input from ducking streams */ +static void remove_sink_input_from_ducking_streams(pa_stream_manager *m, pa_sink_input *i) { + uint32_t idx = 0; + stream_ducking *sd = NULL; + void *stream = NULL; + void *state; + + pa_assert(m); + + PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { + PA_IDXSET_FOREACH(stream, sd->idx_ducking_streams, idx) { + if (stream == i) { + pa_log_info("remove ducking stream[i:%u,%p] from idx_ducking_streams", i->index, i); + pa_idxset_remove_by_data(sd->idx_ducking_streams, stream, NULL); + return; + } + } + } +} + +/* Add the sink-input to ducking streams */ +static void add_sink_input_to_ducking_streams(pa_stream_manager *m, pa_sink_input *i) { + stream_ducking *sd = NULL; + void *state; + + pa_assert(m); + + PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) { + pa_cvolume_ramp vol_ramp; + pa_cvolume vol; + + if (!pa_safe_streq(sd->target_role, pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE))) + continue; + + pa_log_info("add ducking stream[i:%u,%p] to idx_ducking_streams, volume %u", + i->index, i, sd->set_vol); + + pa_idxset_put(sd->idx_ducking_streams, (void *)i, NULL); + + pa_cvolume_ramp_set(&vol_ramp, i->volume.channels, + PA_VOLUME_RAMP_TYPE_LINEAR, (long)sd->duration, sd->set_vol); + + vol.channels = i->volume.channels; + vol.values[0] = sd->set_vol; + + pa_sink_input_add_volume_factor(i, sd->vol_key, &vol); + pa_sink_input_add_volume_ramp_factor(i, sd->vol_key, &vol_ramp, false); + + return; + } +} + static pa_hook_result_t sink_input_new_cb(pa_core *core, pa_sink_input_new_data *new_data, pa_stream_manager *m) { pa_core_assert_ref(core); @@ -2211,6 +2263,8 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, pa_st m->on_call = true; } + add_sink_input_to_ducking_streams(m, i); + return PA_HOOK_OK; } @@ -2224,7 +2278,10 @@ static pa_hook_result_t sink_input_unlink_cb(pa_core *core, pa_sink_input *i, pa m->on_call = false; set_media_active_device(m); } + remove_sink_input_from_muted_streams(m, i); + remove_sink_input_from_ducking_streams(m, i); + process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, false); process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, false); @@ -3213,8 +3270,9 @@ static void subscribe_cb(pa_core *core, pa_subscription_event_type_t t, uint32_t pa_log_info(" - remove sd(%p), idx(%u)", sd, idx); PA_IDXSET_FOREACH(stream, sd->idx_ducking_streams, ducking_idx) { - pa_log_info("remove volume ramp for remained stream %p, key %s", stream, sd->vol_ramp_key); - pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_ramp_key, true); + pa_log_info("remove volume ramp for remained stream %p, key %s", stream, sd->vol_key); + pa_sink_input_remove_volume_factor(stream, sd->vol_key); + pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_key, true); } pa_idxset_free(sd->idx_ducking_streams, NULL); -- 2.7.4