[pulseaudio-discuss] [PATCH 1/2, v2] loopback: Add hooks to track port latency offsets

Georg Chini georg at chini.tk
Sat Apr 8 18:34:12 UTC 2017


The previous patch assumed constant port latency offsets. The offsets can
however be changed by the user, therefore these changes need to be tracked
as well. This patch adds the necessary hooks.

Also the print_msg argument was removed from update_minimum_latency() and
update_latency_boundaries() because the message should always be logged.
---
 src/modules/module-loopback.c | 52 ++++++++++++++++++++++++++++++++-----------
 src/pulsecore/core.h          |  2 ++
 src/pulsecore/sink.c          |  2 ++
 src/pulsecore/source.c        |  2 ++
 4 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 442bc8a9..2242c62c 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -335,7 +335,7 @@ static void update_adjust_timer(struct userdata *u) {
  * 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)
@@ -370,16 +370,14 @@ static void update_minimum_latency(struct userdata *u, pa_sink *sink, bool print
     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) {
@@ -423,7 +421,7 @@ static void update_latency_boundaries(struct userdata *u, pa_source *source, pa_
             u->min_sink_latency = u->max_sink_latency;
     }
 
-    update_minimum_latency(u, sink, print_msg);
+    update_minimum_latency(u, sink);
 }
 
 /* Called from output context
@@ -626,7 +624,7 @@ static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
         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);
 
@@ -995,7 +993,7 @@ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
         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);
 
@@ -1087,7 +1085,7 @@ static int loopback_process_msg_cb(pa_msgobject *o, int code, void *userdata, in
                  * 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;
@@ -1102,7 +1100,7 @@ static int loopback_process_msg_cb(pa_msgobject *o, int code, void *userdata, in
                  * 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;
@@ -1111,6 +1109,28 @@ static int loopback_process_msg_cb(pa_msgobject *o, int code, void *userdata, in
     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;
@@ -1342,7 +1362,7 @@ int pa__init(pa_module *m) {
     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);
 
@@ -1383,6 +1403,12 @@ int pa__init(pa_module *m) {
             && (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;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 212f6f71..df71a118 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -75,6 +75,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_FLAGS_CHANGED,
     PA_CORE_HOOK_SINK_VOLUME_CHANGED,
     PA_CORE_HOOK_SINK_MUTE_CHANGED,
+    PA_CORE_HOOK_SINK_PORT_LATENCY_OFFSET_CHANGED,
     PA_CORE_HOOK_SOURCE_NEW,
     PA_CORE_HOOK_SOURCE_FIXATE,
     PA_CORE_HOOK_SOURCE_PUT,
@@ -86,6 +87,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SOURCE_FLAGS_CHANGED,
     PA_CORE_HOOK_SOURCE_VOLUME_CHANGED,
     PA_CORE_HOOK_SOURCE_MUTE_CHANGED,
+    PA_CORE_HOOK_SOURCE_PORT_LATENCY_OFFSET_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_NEW,
     PA_CORE_HOOK_SINK_INPUT_FIXATE,
     PA_CORE_HOOK_SINK_INPUT_PUT,
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index fb16d574..39689437 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -3295,6 +3295,8 @@ void pa_sink_set_port_latency_offset(pa_sink *s, int64_t offset) {
         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT_LATENCY_OFFSET, NULL, offset, NULL) == 0);
     else
         s->thread_info.port_latency_offset = offset;
+
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_LATENCY_OFFSET_CHANGED], s);
 }
 
 /* Called from main context */
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 09c953f1..14250825 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -2586,6 +2586,8 @@ void pa_source_set_port_latency_offset(pa_source *s, int64_t offset) {
         pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_PORT_LATENCY_OFFSET, NULL, offset, NULL) == 0);
     else
         s->thread_info.port_latency_offset = offset;
+
+    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PORT_LATENCY_OFFSET_CHANGED], s);
 }
 
 /* Called from main thread */
-- 
2.11.0



More information about the pulseaudio-discuss mailing list