Hello mailing list, time for the second status report. The cleaned up port implementation for the bluetooth device is already on the mailing list as you already saw. Now I would like some feedback for the next stage of my GSOC project. I have added a latency variable to the pa_device_port struct. This latency from the port should then be added to the sink if the port is currently active. I have some problems following where I should add the latency so it will become active. As I have discovered there are two types of sinks. Some are with dynamic and some are with fixed latency. If I add the extra latency just to sink->min_latency would that do the job? Or is that a bad idea? The current changes can be seen in the attached diff. Thanks for your attention. -------------- next part -------------- diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index fc9465b..92a0b72 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -135,6 +135,7 @@ static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); +static int pa_cli_command_latency_offset(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail); /* A method table for all available commands */ @@ -168,6 +169,7 @@ static const struct command commands[] = { { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index|name, profile-name)", 3}, { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index|name, port-name)", 3}, { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index|name, port-name)", 3}, + { "set-latency-offset", pa_cli_command_latency_offset, "Change the latency of a port (args: port-name)", 2}, { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3}, { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3}, { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2}, @@ -1723,6 +1725,49 @@ static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *bu return 0; } +static int pa_cli_command_latency_offset(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { + const char *n, *p, *l; + pa_device_port *port; + pa_card *card; + uint32_t latency; + + pa_core_assert_ref(c); + pa_assert(t); + pa_assert(buf); + pa_assert(fail); + + if (!(n = pa_tokenizer_get(t, 1))) { + pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n"); + return -1; + } + + if (!(p = pa_tokenizer_get(t, 2))) { + pa_strbuf_puts(buf, "You need to specify a profile by its name.\n"); + return -1; + } + + if (!(l = pa_tokenizer_get(t, 3))) { + pa_strbuf_puts(buf, "You need to specify a latency offset.\n"); + return -1; + } + + if (pa_atou(l, &latency) < 0) { + pa_strbuf_puts(buf, "Failed to parse latency.\n"); + return -1; + } + + if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) { + pa_strbuf_puts(buf, "No card found by this name or index.\n"); + return -1; + } + + port = pa_hashmap_get(card->ports, p); + + pa_device_port_set_latency_offset(port, (pa_usec_t) latency); + + return 0; +} + static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) { pa_module *m; pa_sink *sink; diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c index 5870913..19a29f4 100644 --- a/src/pulsecore/device-port.c +++ b/src/pulsecore/device-port.c @@ -97,6 +97,7 @@ pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *des p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); p->is_input = FALSE; p->is_output = FALSE; + p->latency_offset = 0; p->proplist = pa_proplist_new(); return p; @@ -112,3 +113,23 @@ void pa_device_port_hashmap_free(pa_hashmap *h) { pa_hashmap_free(h, NULL, NULL); } + +void pa_device_port_set_latency_offset(pa_device_port *p, pa_usec_t latency) { + uint32_t state; + pa_sink *sink; + + pa_assert(p); + + p->latency_offset = latency; + PA_IDXSET_FOREACH(sink, p->core->sinks, state) + if (sink->active_port == p) { + pa_sink_set_latency_offset(sink, p->latency_offset); + break; + } +} + +pa_usec_t pa_device_port_get_latency_offset(pa_device_port *p) { + pa_assert(p); + + return p->latency_offset; +} diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h index 4e90a62..8cb0b70 100644 --- a/src/pulsecore/device-port.h +++ b/src/pulsecore/device-port.h @@ -51,6 +51,7 @@ struct pa_device_port { pa_hashmap *profiles; /* Can be NULL. Does not own the profiles */ pa_bool_t is_input:1; pa_bool_t is_output:1; + pa_usec_t latency_offset; /* .. followed by some implementation specific data */ }; @@ -67,4 +68,9 @@ void pa_device_port_hashmap_free(pa_hashmap *h); /* The port's available status has changed */ void pa_device_port_set_available(pa_device_port *p, pa_port_available_t available); +/* Functions for handling the extra latency */ +void pa_device_port_set_latency_offset(pa_device_port *p, pa_usec_t latency); + +pa_usec_t pa_device_port_get_latency_offset(pa_device_port *p); + #endif diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index e4c343d..45e30de 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -3223,6 +3223,9 @@ 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); } +void pa_sink_set_latency_offset(pa_sink *s, pa_usec_t latency) { +} + /* Called from main context */ size_t pa_sink_get_max_rewind(pa_sink *s) { size_t r; diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 0b5048a..64ebafd 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -385,6 +385,7 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind); void pa_sink_set_max_request(pa_sink *s, size_t max_request); void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency); void pa_sink_set_fixed_latency(pa_sink *s, pa_usec_t latency); +void pa_sink_set_latency_offset(pa_sink *s, pa_usec_t latency); void pa_sink_detach(pa_sink *s); void pa_sink_attach(pa_sink *s);