]> code.delx.au - pulseaudio/commitdiff
sink, source: Add a latency offset which is inherited from the port
authorpoljar <poljarinho@gmail.com>
Fri, 22 Jun 2012 18:55:54 +0000 (20:55 +0200)
committerTanu Kaskinen <tanuk@iki.fi>
Mon, 25 Jun 2012 17:07:13 +0000 (20:07 +0300)
A latency offset variable was added to the sink/source struct.

Also a function was introduced to update the latency offset of the
sink/source and a new message type was introduced so we can send the latency
offset to the IO thread.

The latency offset is automatically populated with the latency from the
currently active port.

src/pulsecore/device-port.c
src/pulsecore/sink.c
src/pulsecore/sink.h
src/pulsecore/source.c
src/pulsecore/source.h

index ae486a856a2e19c34b155144a6393521c83b3614..46e37e25a70e5e4993d374de78a88f204ddb8660 100644 (file)
@@ -115,7 +115,28 @@ void pa_device_port_hashmap_free(pa_hashmap *h) {
 }
 
 void pa_device_port_set_latency_offset(pa_device_port *p, pa_usec_t offset) {
+    uint32_t state;
+
     pa_assert(p);
 
     p->latency_offset = offset;
+
+    if (p->is_output) {
+        pa_sink *sink;
+
+        PA_IDXSET_FOREACH(sink, p->core->sinks, state)
+            if (sink->active_port == p) {
+                pa_sink_set_latency_offset(sink, p->latency_offset);
+                break;
+            }
+
+    } else {
+        pa_source *source;
+
+        PA_IDXSET_FOREACH(source, p->core->sources, state)
+            if (source->active_port == p) {
+                pa_source_set_latency_offset(source, p->latency_offset);
+                break;
+            }
+    }
 }
index e4c343da2867e619f4ea02aaac99464a4035cf67..545a8e156dd34e0d49f8e5509f68e0a6a55787db 100644 (file)
@@ -308,6 +308,11 @@ pa_sink* pa_sink_new(
                 s->active_port = p;
     }
 
+    if (s->active_port)
+        s->latency_offset = s->active_port->latency_offset;
+    else
+        s->latency_offset = 0;
+
     s->save_volume = data->save_volume;
     s->save_muted = data->save_muted;
 
@@ -338,6 +343,7 @@ pa_sink* pa_sink_new(
     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
     s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
     s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
+    s->thread_info.latency_offset = s->latency_offset;
 
     /* FIXME: This should probably be moved to pa_sink_put() */
     pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -1422,6 +1428,8 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
 
     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
 
+    usec += s->latency_offset;
+
     return usec;
 }
 
@@ -1449,6 +1457,8 @@ pa_usec_t pa_sink_get_latency_within_thread(pa_sink *s) {
     if (o->process_msg(o, PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return -1;
 
+    usec += s->thread_info.latency_offset;
+
     return usec;
 }
 
@@ -2812,6 +2822,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             pa_sink_get_mute(s, TRUE);
             return 0;
 
+        case PA_SINK_MESSAGE_SET_LATENCY_OFFSET:
+            s->thread_info.latency_offset = (pa_usec_t) offset;
+            return 0;
+
         case PA_SINK_MESSAGE_GET_LATENCY:
         case PA_SINK_MESSAGE_MAX:
             ;
@@ -3223,6 +3237,18 @@ void pa_sink_set_fixed_latency_within_thread(pa_sink *s, pa_usec_t latency) {
     pa_source_set_fixed_latency_within_thread(s->monitor_source, latency);
 }
 
+/* Called from main context */
+void pa_sink_set_latency_offset(pa_sink *s, pa_usec_t offset) {
+    pa_sink_assert_ref(s);
+
+    s->latency_offset = offset;
+
+    if (PA_SINK_IS_LINKED(s->state))
+        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_OFFSET, NULL, (int64_t) offset, NULL) == 0);
+    else
+        s->thread_info.fixed_latency = offset;
+}
+
 /* Called from main context */
 size_t pa_sink_get_max_rewind(pa_sink *s) {
     size_t r;
@@ -3293,6 +3319,8 @@ int pa_sink_set_port(pa_sink *s, const char *name, pa_bool_t save) {
     s->active_port = port;
     s->save_port = save;
 
+    pa_sink_set_latency_offset(s, s->active_port->latency_offset);
+
     pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s);
 
     return 0;
index 0b5048a9f57ad8ea8a7bda2d433ea153a8a15dba..b138a1dcd003a180f05d6afbbbb9b8e5c045802d 100644 (file)
@@ -113,6 +113,9 @@ struct pa_sink {
     pa_device_port *active_port;
     pa_atomic_t mixer_dirty;
 
+    /* The latency offset is inherited from the currently active port */
+    pa_usec_t latency_offset;
+
     unsigned priority;
 
     /* Called when the main loop requests a state change. Called from
@@ -268,6 +271,9 @@ struct pa_sink {
          * in changing it */
         pa_usec_t fixed_latency; /* for sinks with PA_SINK_DYNAMIC_LATENCY this is 0 */
 
+        /* This latency offset is a direct copy from s->latency_offset */
+        pa_usec_t latency_offset;
+
         /* Delayed volume change events are queued here. The events
          * are stored in expiration order. The one expiring next is in
          * the head of the list. */
@@ -317,6 +323,7 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_SET_MAX_REQUEST,
     PA_SINK_MESSAGE_SET_PORT,
     PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE,
+    PA_SINK_MESSAGE_SET_LATENCY_OFFSET,
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
@@ -403,6 +410,7 @@ unsigned pa_device_init_priority(pa_proplist *p);
 /**** May be called by everyone, from main context */
 
 pa_bool_t pa_sink_update_rate(pa_sink *s, uint32_t rate, pa_bool_t passthrough);
+void pa_sink_set_latency_offset(pa_sink *s, pa_usec_t offset);
 
 /* The returned value is supposed to be in the time domain of the sound card! */
 pa_usec_t pa_sink_get_latency(pa_sink *s);
index 6308f54d050cbe6ddb62412e49fbc892f0598132..63a75ef8c1b99c5244529589ce8446034d5ca94e 100644 (file)
@@ -296,6 +296,11 @@ pa_source* pa_source_new(
                 s->active_port = p;
     }
 
+    if (s->active_port)
+        s->latency_offset = s->active_port->latency_offset;
+    else
+        s->latency_offset = 0;
+
     s->save_volume = data->save_volume;
     s->save_muted = data->save_muted;
 
@@ -323,6 +328,7 @@ pa_source* pa_source_new(
     pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
     s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
     s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
+    s->thread_info.latency_offset = s->latency_offset;
 
     /* FIXME: This should probably be moved to pa_source_put() */
     pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
@@ -1024,6 +1030,8 @@ pa_usec_t pa_source_get_latency(pa_source *s) {
 
     pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
 
+    usec += s->latency_offset;
+
     return usec;
 }
 
@@ -1051,6 +1059,8 @@ pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
     if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
         return -1;
 
+    usec += s->thread_info.latency_offset;
+
     return usec;
 }
 
@@ -2168,6 +2178,10 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             pa_source_get_mute(s, TRUE);
             return 0;
 
+        case PA_SOURCE_MESSAGE_SET_LATENCY_OFFSET:
+            s->thread_info.latency_offset = (pa_usec_t) offset;
+            return 0;
+
         case PA_SOURCE_MESSAGE_MAX:
             ;
     }
@@ -2507,6 +2521,18 @@ void pa_source_set_fixed_latency_within_thread(pa_source *s, pa_usec_t latency)
     pa_source_invalidate_requested_latency(s, FALSE);
 }
 
+/* Called from main thread */
+void pa_source_set_latency_offset(pa_source *s, pa_usec_t offset) {
+    pa_source_assert_ref(s);
+
+    s->latency_offset = offset;
+
+    if (PA_SOURCE_IS_LINKED(s->state))
+        pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_OFFSET, NULL, (int64_t) offset, NULL) == 0);
+    else
+        s->thread_info.fixed_latency = offset;
+}
+
 /* Called from main thread */
 size_t pa_source_get_max_rewind(pa_source *s) {
     size_t r;
index 30c2037b2d60f0eb8f65da6ea5d31931a8b8d235..da024e654f6f0fc3db5da6291799a2e97cded4ba 100644 (file)
@@ -113,6 +113,9 @@ struct pa_source {
     pa_device_port *active_port;
     pa_atomic_t mixer_dirty;
 
+    /* The latency offset is inherited from the currently active port */
+    pa_usec_t latency_offset;
+
     unsigned priority;
 
     /* Called when the main loop requests a state change. Called from
@@ -209,6 +212,9 @@ struct pa_source {
 
         pa_usec_t fixed_latency; /* for sources with PA_SOURCE_DYNAMIC_LATENCY this is 0 */
 
+        /* This latency offset is a direct copy from s->latency_offset */
+        pa_usec_t latency_offset;
+
         /* Delayed volume change events are queued here. The events
          * are stored in expiration order. The one expiring next is in
          * the head of the list. */
@@ -254,6 +260,7 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_SET_MAX_REWIND,
     PA_SOURCE_MESSAGE_SET_PORT,
     PA_SOURCE_MESSAGE_UPDATE_VOLUME_AND_MUTE,
+    PA_SOURCE_MESSAGE_SET_LATENCY_OFFSET,
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
@@ -335,6 +342,8 @@ void pa_source_update_flags(pa_source *s, pa_source_flags_t mask, pa_source_flag
 
 /*** May be called by everyone, from main context */
 
+void pa_source_set_latency_offset(pa_source *s, pa_usec_t offset);
+
 /* The returned value is supposed to be in the time domain of the sound card! */
 pa_usec_t pa_source_get_latency(pa_source *s);
 pa_usec_t pa_source_get_requested_latency(pa_source *s);