* depends on the reported latency ranges. In cases were the lower bounds of
* source and sink latency are not reported correctly (USB) the result will
* be wrong. */
-static void update_minimum_latency(struct userdata *u, pa_sink *sink, bool print_msg) {
+static void update_minimum_latency(struct userdata *u, pa_sink *sink) {
u->minimum_latency = u->min_sink_latency;
if (u->fixed_alsa_source)
else
u->output_thread_info.minimum_latency = u->minimum_latency;
- if (print_msg) {
- pa_log_info("Minimum possible end to end latency: %0.2f ms", (double)u->minimum_latency / PA_USEC_PER_MSEC);
- if (u->latency < u->minimum_latency)
- pa_log_warn("Configured latency of %0.2f ms is smaller than minimum latency, using minimum instead", (double)u->latency / PA_USEC_PER_MSEC);
- }
+ pa_log_info("Minimum possible end to end latency: %0.2f ms", (double)u->minimum_latency / PA_USEC_PER_MSEC);
+ if (u->latency < u->minimum_latency)
+ pa_log_warn("Configured latency of %0.2f ms is smaller than minimum latency, using minimum instead", (double)u->latency / PA_USEC_PER_MSEC);
}
/* Called from main thread
* Calculates minimum and maximum possible latency for source and sink */
-static void update_latency_boundaries(struct userdata *u, pa_source *source, pa_sink *sink, bool print_msg) {
+static void update_latency_boundaries(struct userdata *u, pa_source *source, pa_sink *sink) {
const char *s;
if (source) {
u->min_sink_latency = u->max_sink_latency;
}
- update_minimum_latency(u, sink, print_msg);
+ update_minimum_latency(u, sink);
}
/* Called from output context
pa_sink_input_set_property(u->sink_input, PA_PROP_DEVICE_ICON_NAME, n);
/* Set latency and calculate latency limits */
- update_latency_boundaries(u, dest, u->sink_input->sink, true);
+ update_latency_boundaries(u, dest, u->sink_input->sink);
set_source_output_latency(u, dest);
update_effective_source_latency(u, dest, u->sink_input->sink);
pa_source_output_set_property(u->source_output, PA_PROP_MEDIA_ICON_NAME, n);
/* Set latency and calculate latency limits */
- update_latency_boundaries(u, NULL, dest, true);
+ update_latency_boundaries(u, NULL, dest);
set_sink_input_latency(u, dest);
update_effective_source_latency(u, u->source_output->source, dest);
* source implementations. */
pa_log_warn("Source minimum latency increased to %0.2f ms", (double)current_latency / PA_USEC_PER_MSEC);
u->configured_source_latency = current_latency;
- update_latency_boundaries(u, u->source_output->source, u->sink_input->sink, false);
+ update_latency_boundaries(u, u->source_output->source, u->sink_input->sink);
}
return 0;
* implementations. */
pa_log_warn("Sink minimum latency increased to %0.2f ms", (double)current_latency / PA_USEC_PER_MSEC);
u->configured_sink_latency = current_latency;
- update_latency_boundaries(u, u->source_output->source, u->sink_input->sink, false);
+ update_latency_boundaries(u, u->source_output->source, u->sink_input->sink);
}
return 0;
return 0;
}
+static pa_hook_result_t sink_port_latency_offset_changed_cb(pa_core *core, pa_sink *sink, struct userdata *u) {
+
+ if (sink != u->sink_input->sink)
+ return PA_HOOK_OK;
+
+ u->sink_latency_offset = sink->port_latency_offset;
+ update_minimum_latency(u, sink);
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_port_latency_offset_changed_cb(pa_core *core, pa_source *source, struct userdata *u) {
+
+ if (source != u->source_output->source)
+ return PA_HOOK_OK;
+
+ u->source_latency_offset = source->port_latency_offset;
+ update_minimum_latency(u, u->sink_input->sink);
+
+ return PA_HOOK_OK;
+}
+
int pa__init(pa_module *m) {
pa_modargs *ma = NULL;
struct userdata *u;
u->source_output->update_source_fixed_latency = update_source_latency_range_cb;
u->source_output->userdata = u;
- update_latency_boundaries(u, u->source_output->source, u->sink_input->sink, true);
+ update_latency_boundaries(u, u->source_output->source, u->sink_input->sink);
set_sink_input_latency(u, u->sink_input->sink);
set_source_output_latency(u, u->source_output->source);
&& (n = pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_ICON_NAME)))
pa_proplist_sets(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME, n);
+ /* Hooks to track changes of latency offsets */
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PORT_LATENCY_OFFSET_CHANGED],
+ PA_HOOK_NORMAL, (pa_hook_cb_t) sink_port_latency_offset_changed_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_PORT_LATENCY_OFFSET_CHANGED],
+ PA_HOOK_NORMAL, (pa_hook_cb_t) source_port_latency_offset_changed_cb, u);
+
/* Setup message handler for main thread */
u->msg = pa_msgobject_new(loopback_msg);
u->msg->parent.process_msg = loopback_process_msg_cb;