From: Jaechul Lee Date: Mon, 6 Dec 2021 07:00:03 +0000 (+0900) Subject: module-alsa-card: Support external device in case of using sink2/source2 X-Git-Tag: accepted/tizen/unified/20220603.141256^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56f3036beff14f121b528ed958fb500bb6c0c78c;p=platform%2Fupstream%2Fpulseaudio.git module-alsa-card: Support external device in case of using sink2/source2 pa_alsa_sink/source_new and pa_alsa_sink/source_free functions were replaced with pa_dl_* for supporting tizenaudio-sink2/source2 when a external sound card was inserted. Additionally, use_tizen_hal property that can turn on/off this functionality was added just in case. [Version] 15.0-9 [Issue Type] New Feature Change-Id: I11fdf2340befa6ab182eb0291ba218859c5e2a09 Signed-off-by: Jaechul Lee --- diff --git a/meson.build b/meson.build index 3a41501..63afbcc 100644 --- a/meson.build +++ b/meson.build @@ -1049,6 +1049,7 @@ summary = [ ' empty-pop: @0@'.format(get_option('empty-pop')), ' volume-ramp: @0@'.format(get_option('volume-ramp')), ' individual-volume-ratio: @0@'.format(get_option('individual-volume-ratio')), + ' aec: @0@'.format(get_option('aec')), ' prelink (for TV): @0@'.format(get_option('prelink')), ' lwipc (for TV): @0@'.format(get_option('lwipc')), ] diff --git a/packaging/pulseaudio.spec b/packaging/pulseaudio.spec index 23f0eef..206d66d 100644 --- a/packaging/pulseaudio.spec +++ b/packaging/pulseaudio.spec @@ -4,7 +4,7 @@ Name: pulseaudio Summary: Improved Linux sound server Version: 15.0 -Release: 8 +Release: 9 Group: Multimedia/Audio License: LGPL-2.1 URL: http://pulseaudio.org diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 2609e6d..b148725 100755 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -34,6 +34,10 @@ #include #endif +#ifdef __TIZEN__ +#include +#endif + #include "alsa-util.h" #include "alsa-ucm.h" #include "alsa-sink.h" @@ -70,6 +74,9 @@ PA_MODULE_USAGE( "use_ucm= " "avoid_resampling= " "control= " +#ifdef __TIZEN__ + "use_tizen_hal=" +#endif ); static const char* const valid_modargs[] = { @@ -99,6 +106,9 @@ static const char* const valid_modargs[] = { "use_ucm", "avoid_resampling", "control", +#ifdef __TIZEN__ + "use_tizen_hal", +#endif NULL }; @@ -113,6 +123,27 @@ static const char* const valid_modargs[] = { */ #define PROFILE_PRIO_BONUS 0x8000 +#ifdef __TIZEN__ +#define DEFINE_TYPE(rtype, name, ...) \ + typedef rtype (* name)(__VA_ARGS__) +#define DEFINE_TYPE_WITH_PARAM(rtype, name) \ + DEFINE_TYPE(rtype, name, \ + pa_module *, pa_modargs *, \ + const char *, pa_card *, char **, \ + pa_sample_spec *, pa_channel_map *) + +#define PA_TIZEN_HAL_FILEPATH "libtizenaudio-util.so" +#define PA_TIZEN_HAL_SINK2_NEW "pa_tizenaudio_sink2_new" +#define PA_TIZEN_HAL_SOURCE2_NEW "pa_tizenaudio_source2_new" +#define PA_TIZEN_HAL_SINK2_FREE "pa_tizenaudio_sink2_free" +#define PA_TIZEN_HAL_SOURCE2_FREE "pa_tizenaudio_source2_free" + +DEFINE_TYPE_WITH_PARAM(pa_sink *, dl_sink_new_t); +DEFINE_TYPE_WITH_PARAM(pa_source *, dl_source_new_t); +DEFINE_TYPE(void, dl_sink_free_t, pa_sink *); +DEFINE_TYPE(void, dl_source_free_t, pa_source *); +#endif + struct userdata { pa_core *core; pa_module *module; @@ -133,12 +164,147 @@ struct userdata { bool use_ucm; pa_alsa_ucm_config ucm; +#ifdef __TIZEN__ + bool use_tizen_hal; +#endif }; struct profile_data { pa_alsa_profile *profile; }; +#ifdef __TIZEN__ +static void *pa_dl_get_tizenaudio_function(const char *func) { + void *ret = NULL, *h = NULL; + char *path = NULL; + + path = pa_sprintf_malloc("%s/%s", PA_DLSEARCHPATH, PA_TIZEN_HAL_FILEPATH); + if (!path) { + pa_log_error("Failed to alloc path"); + return NULL; + } + + h = dlopen(path, RTLD_LAZY); + if (!h) { + pa_log_error("Failed to get dl handle (%s)", path); + goto out; + } + + ret = dlsym(h, func); + if (!ret) { + pa_log_error("Failed to get symbol (%s)", func); + goto out; + } + +out: + if (h) + dlclose(h); + if (path) + pa_xfree(path); + + return ret; +} + +static pa_sink *pa_dl_alsa_sink_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card, pa_alsa_mapping *mapping) { + pa_sink *s; + dl_sink_new_t dl_sink_new; + struct userdata *u = (struct userdata *)m->userdata; + + if (!u->use_tizen_hal) + goto exit; + + if (!(dl_sink_new = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SINK2_NEW))) { + pa_log_error("Failed to get sink_new function. Uses alsa-sink"); + goto exit; + } + + pa_log_info("Try to load sink. mapping name(%s), description(%s)", mapping->name, mapping->description); + + s = dl_sink_new(m, ma, driver, card, mapping->device_strings, + &mapping->sample_spec, &mapping->channel_map); + if (!s) { + pa_log_error("Failed to create sink. Uses alsa-sink"); + goto exit; + } + + return s; + +exit: + return pa_alsa_sink_new(m, ma, driver, card, mapping); +} + +static pa_source *pa_dl_alsa_source_new(pa_module *m, pa_modargs *ma, const char *driver, pa_card *card, pa_alsa_mapping *mapping) { + pa_source *s; + dl_source_new_t dl_source_new; + struct userdata *u = (struct userdata *)m->userdata; + + if (!u->use_tizen_hal) + goto exit; + + if (!(dl_source_new = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SOURCE2_NEW))) { + pa_log_error("Failed to get source_new function. Uses alsa-source"); + goto exit; + } + + pa_log_info("Try to load sink. mapping name(%s), description(%s)", mapping->name, mapping->description); + + s = dl_source_new(m, ma, driver, card, mapping->device_strings, + &mapping->sample_spec, &mapping->channel_map); + + if (!s) { + pa_log_error("Failed to create source. Uses alsa-source"); + goto exit; + } + + return s; + +exit: + return pa_alsa_source_new(m, ma, driver, card, mapping); +} + +static void pa_dl_alsa_sink_free(pa_sink *s) { + pa_module *m; + struct userdata *u; + dl_sink_free_t dl_sink_free; + + pa_assert(s); + pa_assert(s->module); + pa_assert(s->module->userdata); + + m = s->module; + u = m->userdata; + + if (u->use_tizen_hal) { + dl_sink_free = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SINK2_FREE); + dl_sink_free(s); + return; + } + + pa_alsa_sink_free(s); +} + +static void pa_dl_alsa_source_free(pa_source *s) { + pa_module *m; + struct userdata *u; + dl_source_free_t dl_source_free; + + pa_assert(s); + pa_assert(s->module); + pa_assert(s->module->userdata); + + m = s->module; + u = m->userdata; + + if (u->use_tizen_hal) { + dl_source_free = pa_dl_get_tizenaudio_function(PA_TIZEN_HAL_SOURCE2_FREE); + dl_source_free(s); + return; + } + + pa_alsa_source_free(s); +} +#endif + static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) { pa_alsa_profile *ap; void *state; @@ -228,7 +394,11 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { continue; sink_inputs = pa_sink_move_all_start(am->sink, sink_inputs); +#ifdef __TIZEN__ + pa_dl_alsa_sink_free(am->sink); +#else pa_alsa_sink_free(am->sink); +#endif am->sink = NULL; } @@ -243,7 +413,11 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { continue; source_outputs = pa_source_move_all_start(am->source, source_outputs); +#ifdef __TIZEN__ + pa_dl_alsa_source_free(am->source); +#else pa_alsa_source_free(am->source); +#endif am->source = NULL; } @@ -260,7 +434,11 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { PA_IDXSET_FOREACH(am, nd->profile->output_mappings, idx) { if (!am->sink) +#ifdef __TIZEN__ + am->sink = pa_dl_alsa_sink_new(c->module, u->modargs, __FILE__, c, am); +#else am->sink = pa_alsa_sink_new(c->module, u->modargs, __FILE__, c, am); +#endif if (sink_inputs && am->sink) { pa_sink_move_all_finish(am->sink, sink_inputs, false); @@ -272,7 +450,11 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) { PA_IDXSET_FOREACH(am, nd->profile->input_mappings, idx) { if (!am->source) +#ifdef __TIZEN__ + am->source = pa_dl_alsa_source_new(c->module, u->modargs, __FILE__, c, am); +#else am->source = pa_alsa_source_new(c->module, u->modargs, __FILE__, c, am); +#endif if (source_outputs && am->source) { pa_source_move_all_finish(am->source, source_outputs, false); @@ -310,11 +492,19 @@ static void init_profile(struct userdata *u) { if (d->profile && d->profile->output_mappings) PA_IDXSET_FOREACH(am, d->profile->output_mappings, idx) +#ifdef __TIZEN__ + am->sink = pa_dl_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am); +#else am->sink = pa_alsa_sink_new(u->module, u->modargs, __FILE__, u->card, am); +#endif if (d->profile && d->profile->input_mappings) PA_IDXSET_FOREACH(am, d->profile->input_mappings, idx) +#ifdef __TIZEN__ + am->source = pa_dl_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am); +#else am->source = pa_alsa_source_new(u->module, u->modargs, __FILE__, u->card, am); +#endif } static pa_available_t calc_port_state(pa_device_port *p, struct userdata *u) { @@ -942,6 +1132,13 @@ int pa__init(pa_module *m) { goto fail; } +#ifdef __TIZEN__ + if (pa_modargs_get_value_boolean(u->modargs, "use_tizen_hal", &u->use_tizen_hal) < 0) { + pa_log("Failed to parse use_tizen_hal= argument."); + goto fail; + } +#endif + /* Force ALSA to reread its configuration. This matters if our device * was hot-plugged after ALSA has already read its configuration - see * https://bugs.freedesktop.org/show_bug.cgi?id=54029 @@ -1187,10 +1384,18 @@ void pa__done(pa_module*m) { pa_hashmap_free(u->jacks); if (u->card && u->card->sinks) +#ifdef __TIZEN__ + pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_dl_alsa_sink_free); +#else pa_idxset_remove_all(u->card->sinks, (pa_free_cb_t) pa_alsa_sink_free); +#endif if (u->card && u->card->sources) +#ifdef __TIZEN__ + pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_dl_alsa_source_free); +#else pa_idxset_remove_all(u->card->sources, (pa_free_cb_t) pa_alsa_source_free); +#endif if (u->card) pa_card_free(u->card); diff --git a/src/modules/meson.build b/src/modules/meson.build index b213f70..0dd040c 100644 --- a/src/modules/meson.build +++ b/src/modules/meson.build @@ -105,7 +105,7 @@ endif if alsa_dep.found() subdir('alsa') all_modules += [ - [ 'module-alsa-card', 'alsa/module-alsa-card.c', [], [], [alsa_dep, libm_dep], libalsa_util ], + [ 'module-alsa-card', 'alsa/module-alsa-card.c', [], [], [alsa_dep, libm_dep, dl_dep], libalsa_util ], [ 'module-alsa-sink', 'alsa/module-alsa-sink.c', [], [], [alsa_dep, libm_dep], libalsa_util ], [ 'module-alsa-source', 'alsa/module-alsa-source.c', [], [], [alsa_dep, libm_dep], libalsa_util ], ] diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c index cc52cb5..a2885ce 100644 --- a/src/modules/module-udev-detect.c +++ b/src/modules/module-udev-detect.c @@ -47,7 +47,11 @@ PA_MODULE_USAGE( "ignore_dB= " "deferred_volume= " "use_ucm= " - "avoid_resampling="); + "avoid_resampling=" +#ifdef __TIZEN__ + "use_tizen_hal=" +#endif + ); struct device { char *path; @@ -79,6 +83,9 @@ struct userdata { int inotify_fd; pa_io_event *inotify_io; +#ifdef __TIZEN__ + bool use_tizen_hal; +#endif }; static const char* const valid_modargs[] = { @@ -89,6 +96,9 @@ static const char* const valid_modargs[] = { "deferred_volume", "use_ucm", "avoid_resampling", +#ifdef __TIZEN__ + "use_tizen_hal", +#endif NULL }; @@ -408,6 +418,9 @@ static void card_changed(struct userdata *u, struct udev_device *dev) { "device_id=\"%s\" " "name=\"%s\" " "card_name=\"%s\" " +#ifdef __TIZEN__ + "use_tizen_hal=%s " +#endif "namereg_fail=false " "tsched=%s " "fixed_latency_range=%s " @@ -419,6 +432,9 @@ static void card_changed(struct userdata *u, struct udev_device *dev) { path_get_card_id(path), n, d->card_name, +#ifdef __TIZEN__ + pa_yes_no(u->use_tizen_hal), +#endif pa_yes_no(u->use_tsched), pa_yes_no(u->fixed_latency_range), pa_yes_no(u->ignore_dB), @@ -767,6 +783,13 @@ int pa__init(pa_module *m) { } u->avoid_resampling = avoid_resampling; +#ifdef __TIZEN__ + if (pa_modargs_get_value_boolean(ma, "use_tizen_hal", &u->use_tizen_hal) < 0) { + pa_log("Failed to parse use_tizen_hal= argument."); + goto fail; + } +#endif + if (!(u->udev = udev_new())) { pa_log("Failed to initialize udev library."); goto fail;