From 56295665a72e4c16d119a34c445a17c33db57883 Mon Sep 17 00:00:00 2001 From: KimJeongYeon Date: Tue, 14 Jun 2016 15:38:06 +0900 Subject: [PATCH] filter-apply,ladspa-sink,virtual-surround-sink: filter-apply supports ladspa-sink and virtual-surround-sink properly Currently, filter-apply doesn't support ladspa-sink based filters, because: * loading ladspa-sink failed due to some argument mismatched. (e.g 'master' used instead of 'sink_master') * ladspa-sink required additional parameters by default. (e.g plugin/label/control/...) Changes in v1: * filter-apply able to load ladspa-sink. * This patch introduces new sink-input(source-output) property to append extra parameters. #define PA_PROP_FILTER_APPLY_EXTRA_PARAMETERS "filter.apply.extra.parameters" e.g) paplay file.wav --property=filter.apply=ladspa-sink \ --property=filter.apply.extra.parameters="plugin=ladspa label=ladspa_stereo control=0" * ladspa-sink support autoloaded feature. Changes in v2: * Additionally, support virtual-surround-sink too. [Version] 5.0-84 [Profile] Common [Issue Type] Feature Enhancement Signed-off-by: KimJeongYeon Change-Id: I3799271dbbca34d8eeade821e6d117f425ef8b5a --- packaging/pulseaudio.spec | 2 +- src/modules/module-filter-apply.c | 34 ++++++++++++++++++ src/modules/module-ladspa-sink.c | 55 +++++++++++++++++++++++++++++- src/modules/module-virtual-surround-sink.c | 52 ++++++++++++++++++++++++++++ src/pulse/proplist.h | 5 +++ 5 files changed, 146 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/pulse/proplist.h diff --git a/packaging/pulseaudio.spec b/packaging/pulseaudio.spec index 64aa023..abbc13f 100644 --- a/packaging/pulseaudio.spec +++ b/packaging/pulseaudio.spec @@ -10,7 +10,7 @@ Name: pulseaudio Summary: Improved Linux sound server Version: 5.0 -Release: 83 +Release: 84 Group: Multimedia/Audio License: LGPL-2.1+ URL: http://pulseaudio.org diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c index 8345894..6412e2e 100644 --- a/src/modules/module-filter-apply.c +++ b/src/modules/module-filter-apply.c @@ -148,6 +148,24 @@ static const char* should_filter(pa_object *o, bool is_sink_input) { return NULL; } +#ifdef __TIZEN__ +static const char* should_filter_extra_parameters(pa_object *o, bool is_sink_input) { + const char *extra_parameters; + pa_proplist *pl; + + if (is_sink_input) + pl = PA_SINK_INPUT(o)->proplist; + else + pl = PA_SOURCE_OUTPUT(o)->proplist; + + /* If the stream need extra parameters, append them to module. */ + if ((extra_parameters = pa_proplist_gets(pl, PA_PROP_FILTER_APPLY_EXTRA_PARAMETERS)) && !pa_streq(extra_parameters, "")) + return extra_parameters; + + return NULL; +} +#endif + static bool should_group_filter(struct filter *filter) { return pa_streq(filter->name, "echo-cancel"); } @@ -414,6 +432,9 @@ static bool can_unload_module(struct userdata *u, uint32_t idx) { static pa_hook_result_t process(struct userdata *u, pa_object *o, bool is_sink_input) { const char *want; +#ifdef __TIZEN__ + const char *extra_parameters; +#endif bool done_something = false; pa_sink *sink = NULL; pa_source *source = NULL; @@ -464,11 +485,24 @@ static pa_hook_result_t process(struct userdata *u, pa_object *o, bool is_sink_i char *args; pa_module *m; +#ifdef __TIZEN__ + /* Some filter modules might be required extra parameters by default. + * (e.g 'plugin', 'label', 'control' of module-ladspa-sink) */ + extra_parameters = should_filter_extra_parameters(o, is_sink_input); + + args = pa_sprintf_malloc("autoloaded=1 %s%s %s%s %s", + fltr->sink_master ? "sink_master=" : "", + fltr->sink_master ? fltr->sink_master->name : "", + fltr->source_master ? "source_master=" : "", + fltr->source_master ? fltr->source_master->name : "", + extra_parameters ? extra_parameters : ""); +#else args = pa_sprintf_malloc("autoloaded=1 %s%s %s%s", fltr->sink_master ? "sink_master=" : "", fltr->sink_master ? fltr->sink_master->name : "", fltr->source_master ? "source_master=" : "", fltr->source_master ? fltr->source_master->name : ""); +#endif pa_log_debug("Loading %s with arguments '%s'", module_name, args); diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index cbb1aea..50dd94b 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -56,7 +56,11 @@ PA_MODULE_LOAD_ONCE(false); PA_MODULE_USAGE( _("sink_name= " "sink_properties= " +#ifdef __TIZEN__ + "sink_master= " +#else "master= " +#endif "format= " "rate= " "channels= " @@ -65,10 +69,18 @@ PA_MODULE_USAGE( "label= " "control= " "input_ladspaport_map= " - "output_ladspaport_map= ")); + "output_ladspaport_map= " +#ifdef __TIZEN__ + "autoloaded= " +#endif + )); #define MEMBLOCKQ_MAXLENGTH (16*1024*1024) +#ifdef __TIZEN__ +#define DEFAULT_AUTOLOADED false +#endif + /* PLEASE NOTICE: The PortAudio ports and the LADSPA ports are two different concepts. They are not related and where possible the names of the LADSPA port variables contains "ladspa" to avoid confusion */ @@ -101,12 +113,20 @@ struct userdata { #endif bool auto_desc; + +#ifdef __TIZEN__ + bool autoloaded; +#endif }; static const char* const valid_modargs[] = { "sink_name", "sink_properties", +#ifdef __TIZEN__ + "sink_master", +#else "master", +#endif "format", "rate", "channels", @@ -116,6 +136,9 @@ static const char* const valid_modargs[] = { "control", "input_ladspaport_map", "output_ladspaport_map", +#ifdef __TIZEN__ + "autoloaded", +#endif NULL }; @@ -641,6 +664,21 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s } } +#ifdef __TIZEN__ +/* Called from main context */ +static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + if (u->autoloaded) + return false; + + return u->sink != dest; +} +#endif + /* Called from main context */ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) { struct userdata *u; @@ -970,7 +1008,11 @@ int pa__init(pa_module*m) { goto fail; } +#ifdef __TIZEN__ + if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) { +#else if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) { +#endif pa_log("Master sink not found"); goto fail; } @@ -1228,6 +1270,14 @@ int pa__init(pa_module*m) { goto fail; } +#ifdef __TIZEN__ + u->autoloaded = DEFAULT_AUTOLOADED; + if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) { + pa_log("Failed to parse autoloaded value"); + goto fail; + } +#endif + if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) { const char *z; @@ -1280,6 +1330,9 @@ int pa__init(pa_module*m) { u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_cb; u->sink_input->state_change = sink_input_state_change_cb; +#ifdef __TIZEN__ + u->sink_input->may_move_to = sink_input_may_move_to_cb; +#endif u->sink_input->moving = sink_input_moving_cb; u->sink_input->mute_changed = sink_input_mute_changed_cb; u->sink_input->userdata = u; diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c index 1d6cfc6..f46d073 100644 --- a/src/modules/module-virtual-surround-sink.c +++ b/src/modules/module-virtual-surround-sink.c @@ -52,7 +52,11 @@ PA_MODULE_LOAD_ONCE(false); PA_MODULE_USAGE( _("sink_name= " "sink_properties= " +#ifdef __TIZEN__ + "sink_master= " +#else "master= " +#endif "format= " "rate= " "channels= " @@ -60,10 +64,17 @@ PA_MODULE_USAGE( "use_volume_sharing= " "force_flat_volume= " "hrir=/path/to/left_hrir.wav " +#ifdef __TIZEN__ + "autoloaded= " +#endif )); #define MEMBLOCKQ_MAXLENGTH (16*1024*1024) +#ifdef __TIZEN__ +#define DEFAULT_AUTOLOADED false +#endif + struct userdata { pa_module *module; @@ -89,12 +100,20 @@ struct userdata { float *input_buffer; int input_buffer_offset; + +#ifdef __TIZEN__ + bool autoloaded; +#endif }; static const char* const valid_modargs[] = { "sink_name", "sink_properties", +#ifdef __TIZEN__ + "sink_master", +#else "master", +#endif "format", "rate", "channels", @@ -102,6 +121,9 @@ static const char* const valid_modargs[] = { "use_volume_sharing", "force_flat_volume", "hrir", +#ifdef __TIZEN__ + "autoloaded", +#endif NULL }; @@ -429,6 +451,21 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s } } +#ifdef __TIZEN__ +/* Called from main context */ +static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) { + struct userdata *u; + + pa_sink_input_assert_ref(i); + pa_assert_se(u = i->userdata); + + if (u->autoloaded) + return false; + + return u->sink != dest; +} +#endif + /* Called from main context */ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) { struct userdata *u; @@ -555,7 +592,11 @@ int pa__init(pa_module*m) { goto fail; } +#ifdef __TIZEN__ + if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) { +#else if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) { +#endif pa_log("Master sink not found"); goto fail; } @@ -636,6 +677,14 @@ int pa__init(pa_module*m) { goto fail; } +#ifdef __TIZEN__ + u->autoloaded = DEFAULT_AUTOLOADED; + if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) { + pa_log("Failed to parse autoloaded value"); + goto fail; + } +#endif + if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) { const char *z; @@ -695,6 +744,9 @@ int pa__init(pa_module*m) { u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_cb; u->sink_input->state_change = sink_input_state_change_cb; +#ifdef __TIZEN__ + u->sink_input->may_move_to = sink_input_may_move_to_cb; +#endif u->sink_input->moving = sink_input_moving_cb; u->sink_input->volume_changed = use_volume_sharing ? NULL : sink_input_volume_changed_cb; u->sink_input->mute_changed = sink_input_mute_changed_cb; diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h old mode 100755 new mode 100644 index 4a5bde6..ca09959 --- a/src/pulse/proplist.h +++ b/src/pulse/proplist.h @@ -71,6 +71,11 @@ PA_C_DECL_BEGIN /** For streams: the name of a filter that is desired, e.g.\ "echo-cancel" or "equalizer-sink". Differs from PA_PROP_FILTER_WANT in that it forces PulseAudio to apply the filter, regardless of whether PulseAudio thinks it makes sense to do so or not. If this is set, PA_PROP_FILTER_WANT is ignored. In other words, you almost certainly do not want to use this. \since 1.0 */ #define PA_PROP_FILTER_APPLY "filter.apply" +#ifdef __TIZEN__ +/** For streams: some module required extra parameters, e.g.\ "plugin=ladspa label=ladspa_stereo control=0" in case of "ladspa-sink" filter */ +#define PA_PROP_FILTER_APPLY_EXTRA_PARAMETERS "filter.apply.extra.parameters" +#endif + /** For streams: the name of a filter that should specifically suppressed (i.e.\ overrides PA_PROP_FILTER_WANT). Useful for the times that PA_PROP_FILTER_WANT is automatically added (e.g. echo-cancellation for phone streams when $VOIP_APP does it's own, internal AEC) \since 1.0 */ #define PA_PROP_FILTER_SUPPRESS "filter.suppress" -- 2.7.4