From: Sangchul Lee Date: Thu, 18 Mar 2021 23:58:42 +0000 (+0900) Subject: tizenaudio-policy: Preparation for new loopback module management X-Git-Tag: submit/tizen/20210412.112307~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=64bf38bd9afae04238769bdb724a163e578ee1a2;p=platform%2Fcore%2Fmultimedia%2Fpulseaudio-modules-tizen.git tizenaudio-policy: Preparation for new loopback module management [Version] 13.0.59 [Issue Type] Improvement Change-Id: I1fa78fdc41913f0db7e8d08b0ebe4d4c33b21c62 Signed-off-by: Sangchul Lee --- diff --git a/packaging/pulseaudio-modules-tizen.spec b/packaging/pulseaudio-modules-tizen.spec index 0b48635..e0f63c5 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: 13.0.58 +Version: 13.0.59 Release: 0 Group: Multimedia/Audio License: LGPL-2.1+ diff --git a/src/module-tizenaudio-policy.c b/src/module-tizenaudio-policy.c index c18391c..bb3a727 100644 --- a/src/module-tizenaudio-policy.c +++ b/src/module-tizenaudio-policy.c @@ -150,6 +150,12 @@ static device_type_t convert_device_type_str(const char *device) return DEVICE_UNKNOWN; } +typedef struct _loopback_module { + pa_sink *sink; + pa_source *source; + pa_module *module; +} loopback_module; + struct userdata { pa_core *core; pa_module *module; @@ -172,6 +178,7 @@ struct userdata { uint32_t module_null_sink_index; uint32_t module_null_source_index; pa_module *module_loopback; + pa_hashmap *loopback_modules; struct { int32_t latency_msec; int32_t adjust_sec; @@ -446,6 +453,134 @@ static void update_bt_sco_option(struct userdata *u, const char* role) { } } +static void update_loopback_module_args(struct userdata* u, int32_t parent_id, pa_sink *sink, pa_source *source) +{ + loopback_module *loopback; + + pa_assert(u); + + if (parent_id < 0) { + pa_log_error("invalid parent_id(%d)", parent_id); + return; + } + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) { + loopback = pa_xnew0(loopback_module, 1); + pa_hashmap_put(u->loopback_modules, (void*)parent_id, loopback); + } + if (sink) + loopback->sink = sink; + if (source) + loopback->source = source; + + pa_log_info("loopback module for parent_id(%d) is updated, sink(%s), source(%s)", + parent_id, loopback->sink ? loopback->sink->name : "null", loopback->source ? loopback->source->name : "null"); +} + +static void load_loopback_module_by_parent_id(struct userdata* u, int32_t parent_id) +{ + loopback_module *loopback; + char *args; + const char *volume_type; + + pa_assert(u); + + if (parent_id < 0) { + pa_log_error("invalid parent_id(%d)", parent_id); + return; + } + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) { + pa_log_error("could not find loopback module for parent_id(%d)", parent_id); + return; + } + + if (!loopback->sink || !loopback->source) { + pa_log_debug("sink(%p) or source(%p) is not set", loopback->sink, loopback->source); + return; + } + + if (!u->loopback_args.latency_msec) + u->loopback_args.latency_msec = LOOPBACK_DEFAULT_LATENCY_MSEC; + if (!u->loopback_args.adjust_sec) + u->loopback_args.adjust_sec = LOOPBACK_DEFAULT_ADJUST_SEC; + + volume_type = pa_stream_manager_get_volume_type(u->stream_manager, STREAM_SINK_INPUT, STREAM_ROLE_LOOPBACK); + args = pa_sprintf_malloc("sink=%s source=%s latency_msec=%d adjust_time=%d sink_input_properties=%s=%s", + loopback->sink->name, loopback->source->name, + u->loopback_args.latency_msec, u->loopback_args.adjust_sec, + PA_PROP_MEDIA_TIZEN_VOLUME_TYPE, volume_type); + + if (pa_module_load(&loopback->module, u->core, MODULE_LOOPBACK, args)) + pa_log_error("failed to load module-loopback for parent_id(%d) with (%s)", parent_id, args); + else + pa_log_info("load module-loopback(%p) for parent_id(%d) with (%s)", loopback->module, parent_id, args); + + pa_xfree(args); +} + +static void unload_loopback_modules_by_device_disconnect(struct userdata* u, pa_sink *sink, pa_source *source) +{ + loopback_module *loopback; + int32_t parent_id; + void *state; + + pa_assert(u); + + pa_log_info("disconnected sink(%s), source(%s)", sink ? sink->name : "null", source ? source->name : "null"); + + PA_HASHMAP_FOREACH_KV(parent_id, loopback, u->loopback_modules, state) { + if (loopback->module && + ((sink && (loopback->sink == sink)) || + (source && (loopback->source == source)))) { + pa_log_info(" -- unload module-loopback(%p) for parent_id(%d)", loopback->module, parent_id); + pa_hashmap_remove_and_free(u->loopback_modules, (const void*)parent_id); + } + } +} + +static void unload_loopback_modules_by_stream_disconnect(struct userdata* u, int32_t parent_id, pa_sink_input *i, pa_source_output *o) +{ + loopback_module *loopback; + + pa_assert(u); + + if (parent_id < 0) + return; + + if (!i && !o) + return; + + loopback = pa_hashmap_get(u->loopback_modules, (const void*)parent_id); + if (!loopback) + return; + + if (!loopback->module) { + pa_log_info("module is not loaded yet"); + return; + } + + pa_log_info("disconnected sink-input(%p) or source-output(%p) of parent_id(%d)", i, o, parent_id); + + if (i && loopback->sink) + if (pa_idxset_get_by_data(loopback->sink->inputs, i, NULL) && pa_idxset_size(loopback->sink->inputs)) + goto unload; + + if (o && loopback->source) + if (pa_idxset_get_by_data(loopback->source->outputs, o, NULL) && pa_idxset_size(loopback->source->outputs)) + goto unload; + + pa_log_warn("no loopback module to be unloaded with parent_id(%d), sink-input(%p), source-output(%p)", parent_id, i, o); + + return; + +unload: + pa_log_info(" -- unload module-loopback(%p) for parent_id(%d)", loopback->module, parent_id); + pa_hashmap_remove_and_free(u->loopback_modules, (const void*)parent_id); +} + /* Load/Unload module-loopback */ static void update_loopback_module(struct userdata *u, bool load) { char *args = NULL; @@ -1801,6 +1936,16 @@ static pa_hook_result_t device_connection_changed_hook_cb(pa_core *c, pa_tz_devi return PA_HOOK_OK; } +static void loopback_module_free(loopback_module *loopback) { + pa_assert(loopback); + + pa_log_info("unload module-loopback(%p)", loopback->module); + + pa_module_unload(loopback->module, true); + + pa_xfree(loopback); +} + int pa__init(pa_module *m) { pa_modargs *ma = NULL; @@ -1862,6 +2007,8 @@ int pa__init(pa_module *m) u->module_null_source_index = module_loaded->index; pa_xfree(args); + u->loopback_modules = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL, (pa_free_cb_t)loopback_module_free); + __load_dump_config(u); pa_log_info("Tizen Audio Policy module is loaded\n"); @@ -1888,6 +2035,11 @@ void pa__done(pa_module *m) bt_sco_close(u, false); + if (u->loopback_modules) { + pa_hashmap_remove_all(u->loopback_modules); + pa_hashmap_free(u->loopback_modules); + } + if (u->module_null_sink_index != PA_INVALID_INDEX) pa_module_unload_by_index(m->core, u->module_null_sink_index, true);