return ret;
}
+static void update_prop_filter_apply_group(pa_sink_input *si, filter_info *f, const char *filter_apply) {
+ char *prop_group = NULL;
+
+ pa_assert(si);
+ pa_assert(filter_apply);
+
+ prop_group = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_GROUP, filter_apply);
+
+ if (!f)
+ pa_proplist_unset(si->proplist, prop_group);
+ else if (f->group)
+ pa_proplist_sets(si->proplist, prop_group, f->group);
+
+ pa_xfree(prop_group);
+}
+
+static void update_prop_filter_apply_params(pa_sink_input *si, filter_info *f, const char *filter_apply) {
+ char *prop_parameters = NULL;
+
+ pa_assert(si);
+ pa_assert(filter_apply);
+
+ prop_parameters = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_PARAMETERS, filter_apply);
+
+ if (!f)
+ pa_proplist_unset(si->proplist, prop_parameters);
+ else if (f->parameters)
+ pa_proplist_sets(si->proplist, prop_parameters, f->parameters);
+
+ pa_xfree(prop_parameters);
+}
+
/* Invoked from dbus method call or hook fire */
int32_t apply_filter_to_sink_input(pa_sink_input *si, filter_info *f, bool need_to_hook) {
- const char *filter_apply = NULL;
- char *prop_group;
- char *prop_parameters;
-
pa_assert(si);
+ if (f && (!f->filter_apply || pa_streq(f->filter_apply, ""))) {
+ pa_log_error("Try to applying empty filter module");
+ return -1;
+ }
+
if (!f) {
+ const char *filter_apply = NULL;
/* Unload filter using module-filter-apply */
if ((filter_apply = pa_proplist_gets(si->proplist, PA_PROP_FILTER_APPLY))) {
- prop_group = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_GROUP, filter_apply);
- pa_proplist_unset(si->proplist, prop_group);
- pa_xfree(prop_group);
-
- prop_parameters = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_PARAMETERS, filter_apply);
- pa_proplist_unset(si->proplist, prop_parameters);
- pa_xfree(prop_parameters);
-
+ update_prop_filter_apply_group(si, f, filter_apply);
+ update_prop_filter_apply_params(si, f, filter_apply);
pa_proplist_unset(si->proplist, PA_PROP_FILTER_APPLY);
}
} else {
- if (!f->filter_apply || pa_streq(f->filter_apply, "")) {
- pa_log_error("Try to applying empty filter module");
- return -1;
- }
-
/* Load filter using module-filter-apply */
pa_proplist_sets(si->proplist, PA_PROP_FILTER_APPLY, f->filter_apply);
-
- /* Optional properties */
- if (f->group) {
- prop_group = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_GROUP, f->filter_apply);
- pa_proplist_sets(si->proplist, prop_group, f->group);
- pa_xfree(prop_group);
- }
- if (f->parameters) {
- prop_parameters = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_PARAMETERS, f->filter_apply);
- pa_proplist_sets(si->proplist, prop_parameters, f->parameters);
- pa_xfree(prop_parameters);
- }
+ update_prop_filter_apply_group(si, f, f->filter_apply);
+ update_prop_filter_apply_params(si, f, f->filter_apply);
}
if (need_to_hook)
return 0;
}
+#define MAX_ELEMENT_LENGTH 64
+#define MAX_PARAMETERS_LENGTH 256
+static void update_filter_parameters(filter_info *f) {
+ const char *split_state = NULL;
+ const char *control_element = "control=";
+ char *param_element = NULL;
+ char control_values[MAX_ELEMENT_LENGTH] = {'\0',};
+ char result_buf[MAX_PARAMETERS_LENGTH] = {'\0',};
+ uint32_t i;
+ int32_t len;
+ int32_t c_len;
+
+ pa_assert(f);
+
+ if (f->n_controls == 0)
+ return;
+
+ while ((param_element = pa_split(f->parameters, " ", &split_state))) {
+ len = strlen(result_buf);
+ if (!strncmp(param_element, control_element, strlen(control_element))) {
+ for (i = 0; i < f->n_controls; i++) {
+ c_len = strlen(control_values);
+ pa_snprintf(control_values + c_len, MAX_ELEMENT_LENGTH - c_len,
+ (i == f->n_controls - 1) ? "%1.1f" : "%1.1f,", f->controls.values[i]);
+ }
+ pa_snprintf(result_buf + len, MAX_PARAMETERS_LENGTH - len, "%s%s", control_element, control_values);
+ } else {
+ pa_snprintf(result_buf + len, MAX_PARAMETERS_LENGTH - len, "%s ", param_element);
+ }
+ pa_xfree((void *)param_element);
+ }
+
+ pa_xfree((void *)f->parameters);
+ f->parameters = pa_xstrdup(result_buf);
+
+ pa_log_info("new filter parameters: %s", f->parameters);
+}
+
/* Invoked from dbus method call */
int32_t control_filter(pa_stream_manager *m, const char *filter_name, const char *filter_controls, const char *stream_type,
DBusConnection *conn) {
}
/* Search filter_info according to stream type, then get index of sink */
- f = pa_hashmap_get(m->filter_infos, (const void*)stream_type);
- if (f && pa_safe_streq(f->filter_apply, filter_name)) {
+ if (!(f = pa_hashmap_get(m->filter_infos, (const void*)stream_type))) {
+ pa_log_error("No filter information or sink to control");
+ return -1;
+ }
+
+ if (pa_safe_streq(f->filter_apply, filter_name)) {
PA_IDXSET_FOREACH(si, m->core->sink_inputs, si_idx) {
role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE);
if (pa_safe_streq(role, stream_type)) {
}
}
- if (f && s) {
- if (pa_safe_streq(f->filter_apply, "ladspa-sink") && pa_safe_streq(s->module->name, "module-ladspa-sink")) {
- double read_values[FILTER_MAX_CONTROLS];
- bool use_default[FILTER_MAX_CONTROLS];
- int32_t n_controls;
-
- /* Parse control parameters (e.g, "0.0, 0.1, 3.0") */
- n_controls = parse_filter_control_parameters(filter_controls, read_values, use_default, FILTER_MAX_CONTROLS);
- if (n_controls > 0) {
- /* Save control parameters to filter_info */
- uint32_t i;
- for (i = 0; i < n_controls; i++) {
- f->controls.values[i] = read_values[i];
- f->controls.use_default[i] = use_default[i];
- f->n_controls = (uint32_t)n_controls;
- }
- } else {
- pa_log_error("No filter controls to filter");
- return -1;
+ if (pa_safe_streq(f->filter_apply, "ladspa-sink") || (s && pa_safe_streq(s->module->name, "module-ladspa-sink"))) {
+ double read_values[FILTER_MAX_CONTROLS];
+ bool use_default[FILTER_MAX_CONTROLS];
+ int32_t n_controls;
+
+ /* Parse control parameters (e.g, "0.0, 0.1, 3.0") */
+ n_controls = parse_filter_control_parameters(filter_controls, read_values, use_default, FILTER_MAX_CONTROLS);
+ if (n_controls > 0) {
+ /* Save control parameters to filter_info */
+ uint32_t i;
+ for (i = 0; i < n_controls; i++) {
+ f->controls.values[i] = read_values[i];
+ f->controls.use_default[i] = use_default[i];
+ f->n_controls = (uint32_t)n_controls;
}
- /* Send control parameters to ladspa-sink */
- control_filter_ladspa(conn, f, s_idx);
+ /* update parameters */
+ update_filter_parameters(f);
+ if (s) {
+ PA_IDXSET_FOREACH(si, m->core->sink_inputs, si_idx) {
+ role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE);
+ if (pa_safe_streq(role, stream_type))
+ update_prop_filter_apply_params(si, f, f->filter_apply);
+ }
+ }
} else {
- pa_log_error("Sorry, it is able to control ladspa-sink only");
+ pa_log_error("No filter controls to filter");
return -1;
}
+
+ /* Send control parameters to ladspa-sink */
+ if (s)
+ control_filter_ladspa(conn, f, s_idx);
} else {
- pa_log_error("No filter information or sink to control");
+ pa_log_error("Sorry, it is able to control ladspa-sink only");
return -1;
}
pa_log_info("reload filter successfully for [stream_role:%s, sink:%s]", stream_role, new_master_sink->name);
leave:
- pa_xfree((void*)filter_name);
- pa_xfree((void*)filter_params);
- pa_xfree((void*)filter_group);
+ pa_xfree((void *)filter_name);
+ pa_xfree((void *)filter_params);
+ pa_xfree((void *)filter_group);
return ret;
}