loopback: Add hooks to track port latency offsets
authorGeorg Chini <georg@chini.tk>
Mon, 10 Apr 2017 19:47:23 +0000 (21:47 +0200)
committerGeorg Chini <georg@chini.tk>
Mon, 10 Apr 2017 19:47:23 +0000 (21:47 +0200)
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
src/pulsecore/core.h
src/pulsecore/sink.c
src/pulsecore/source.c

index 442bc8a..2242c62 100644 (file)
@@ -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;
index 212f6f7..df71a11 100644 (file)
@@ -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,
index fb16d57..3968943 100644 (file)
@@ -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 */
index 09c953f..1425082 100644 (file)
@@ -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 */