pa_assert(method);
pa_assert(default_method);
- requested = pa_proplist_gets(o->proplist, "echo_cancel");
+ requested = pa_proplist_gets(o->proplist, PA_PROP_MEDIA_ECHO_CANCEL_METHOD);
if (!requested)
return -1;
static pa_hook_result_t source_output_new_cb(pa_core *c, pa_source_output_new_data *data, void *userdata) {
struct userdata *u = (struct userdata *)userdata;
- const char *echo_cancel;
+ const char *method;
pa_assert(c);
pa_assert(u);
pa_assert(data);
- echo_cancel = pa_proplist_gets(data->proplist, "echo_cancel");
- if (!echo_cancel)
+ method = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_ECHO_CANCEL_METHOD);
+ if (!method)
return PA_HOOK_OK;
if (CHECK_COUNT_SOURCE_OUTPUT_AEC(u) > 0) {
return PA_HOOK_OK;
}
-static int find_reference_sink(struct userdata *u, pa_source_output *o) {
- const char *sink_name;
+static pa_sink *find_reference_sink_by_proplist(pa_core *c, pa_proplist *p) {
+ const char *ref_idx;
+ int32_t idx;
+ pa_sink *s;
- pa_assert(u);
- pa_assert(o);
+ pa_assert(c);
+ pa_assert(p);
- sink_name = pa_proplist_gets(o->proplist, "reference_sink");
- if (!sink_name)
- return -1;
+ ref_idx = pa_proplist_gets(p, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_SINK);
+ if (!ref_idx)
+ return NULL;
- u->sink = pa_namereg_get(u->core, sink_name, PA_NAMEREG_SINK);
- if (!u->sink)
- return -1;
+ if (pa_atoi(ref_idx, &idx) < 0)
+ return NULL;
- pa_log_debug("Requested AEC source(%s), sink(%s)",
- u->source->name, u->sink ? u->sink->name : "");
+ s = pa_idxset_get_by_index(c->sinks, idx);
+ if (!s)
+ return NULL;
- return 0;
+ pa_log_info("Found reference sink(%d, %s)", s->index, s->name);
+
+ return s;
}
static int check_latency_validation(struct userdata *u, pa_sink *sink, pa_source *source) {
}
u->source = o->source;
- if (find_reference_sink(u, o)) {
+ u->sink = find_reference_sink_by_proplist(c, o->proplist);
+ if (!u->sink) {
pa_log_error("Can't find reference sink for AEC");
goto fail;
}
pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST],
PA_HOOK_EARLY, (pa_hook_cb_t) source_output_unlink_post_cb, u);
+ /* source_output_new_cb must be called after new_cb callback in stream manager.
+ * because stream-manager converts the device_id to the index of the sink */
u->source_output_new_slot =
pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW],
PA_HOOK_LATE, (pa_hook_cb_t) source_output_new_cb, u);
[PROCESS_COMMAND_REMOVE_STREAM] = "REMOVE_STREAM",
[PROCESS_COMMAND_UPDATE_BUFFER_ATTR] = "UPDATE_BUFFER_ATTR",
[PROCESS_COMMAND_APPLY_FILTER] = "APPLY_FILTER",
+ [PROCESS_COMMAND_SET_AEC_REFERENCE_DEVICE] = "SET_AEC_REFERENCE",
};
static const char* notify_command_type_str[] = {
}
break;
}
+ case PROCESS_COMMAND_SET_AEC_REFERENCE_DEVICE: {
+ int32_t id;
+ pa_tz_device *device;
+ const char *ref_device;
+ pa_proplist *p = ((pa_source_output_new_data*)stream)->proplist;
+ pa_sink *s;
+
+ result = PROCESS_STREAM_RESULT_SKIP;
+
+ ref_device = pa_proplist_gets(p, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_DEVICE);
+ if (!ref_device)
+ break;
+
+ result = PROCESS_STREAM_RESULT_STOP;
+
+ if (pa_atoi(ref_device, &id) < 0) {
+ pa_log_error("Can't convert ref_device(%s) to integer", ref_device);
+ break;
+ }
+
+ device = pa_device_manager_get_device_by_id(m->dm, id);
+ if (!device) {
+ pa_log_error("Can't find device by id(%d)", id);
+ break;
+ }
+
+ s = pa_tz_device_get_sink(device, "normal");
+ if (!s) {
+ pa_log_error("Can't find sink by device");
+ break;
+ }
+
+ pa_proplist_setf(p, PA_PROP_MEDIA_ECHO_CANCEL_REFERENCE_SINK, "%d", s->index);
+
+ result = PROCESS_STREAM_RESULT_OK;
+
+ break;
+ }
}
finish:
process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_BUFFER_ATTR, true);
process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_UPDATE_VOLUME, true);
process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_STARTED, true);
+ process_stream(m, new_data, STREAM_SOURCE_OUTPUT, PROCESS_COMMAND_SET_AEC_REFERENCE_DEVICE, true);
return PA_HOOK_OK;
}