[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.15-test7-68-gee6657a
Lennart Poettering
gitmailer-noreply at 0pointer.de
Thu Apr 9 16:31:51 PDT 2009
This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.
The master branch has been updated
from 6c04a1c9039606182314f5f263445c89f3f28a9f (commit)
- Log -----------------------------------------------------------------
ee6657a bluetooth: when starting up HSP stream, send 2 packets first, only afterwards enter one-read-one-write logic
d77b28c bluetooth: rework timing logic, properly implement latency callbacks
e9a4dec bluetooth: be a bit more verbose if we exit due to bad poll() revents flag
48cff5b bluetooth: rename sco to hsp also for the user
f7c229d core: add a seperate fixed_latency field for sinks/sources with fixed latency
9ae8ca2 core: memory leak, fix ref counting when moving streams
dcd4a73 dbus: memory leak, actually free dbus wrapper
d827ecd dbus: drop pa_ prefix from static symbol
f8ebe85 protocol-native: downgrade message if we receive pcm block for dead stream
5b87196 protocol-native: print underrun message only once for each underrun
3507d1e socket-server: memory leak, free machine id after use
669703d dbus: memory leak, free pending calls
9ba9883 dbus: memory leak, free server id after use
9ee6a41 bluetooth: memory leak, actually free discovery struct itself
f65b276 interpol-test: make it easier to test corking only optionally
-----------------------------------------------------------------------
Summary of changes:
src/modules/bluetooth/bluetooth-util.c | 2 +
src/modules/bluetooth/module-bluetooth-device.c | 193 +++++++++++++++++------
src/pulsecore/cli-text.c | 12 ++-
src/pulsecore/dbus-shared.c | 12 +-
src/pulsecore/dbus-util.c | 11 +-
src/pulsecore/protocol-native.c | 5 +-
src/pulsecore/sink-input.c | 33 +++-
src/pulsecore/sink.c | 31 +++-
src/pulsecore/sink.h | 2 +
src/pulsecore/socket-server.c | 1 +
src/pulsecore/source-output.c | 29 +++-
src/pulsecore/source.c | 34 +++--
src/pulsecore/source.h | 2 +
src/tests/interpol-test.c | 15 ++-
14 files changed, 284 insertions(+), 98 deletions(-)
-----------------------------------------------------------------------
commit f65b276db3881dce35a32b4478b1c44ade098830
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:10:59 2009 +0200
interpol-test: make it easier to test corking only optionally
diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c
index c103a49..0c906d3 100644
--- a/src/tests/interpol-test.c
+++ b/src/tests/interpol-test.c
@@ -37,6 +37,7 @@
#include <pulsecore/thread.h>
#define INTERPOLATE
+//#define CORK
static pa_context *context = NULL;
static pa_stream *stream = NULL;
@@ -125,7 +126,9 @@ int main(int argc, char *argv[]) {
int k, r;
struct timeval start, last_info = { 0, 0 };
pa_usec_t old_t = 0, old_rtc = 0;
+#ifdef CORK
pa_bool_t corked = FALSE;
+#endif
pa_log_set_level(PA_LOG_DEBUG);
@@ -150,7 +153,12 @@ int main(int argc, char *argv[]) {
r = pa_threaded_mainloop_start(m);
assert(r >= 0);
- for (k = 0; k < 20000; k++) {
+/* #ifdef CORK */
+ for (k = 0; k < 20000; k++)
+/* #else */
+/* for (k = 0; k < 2000; k++) */
+/* #endif */
+ {
pa_bool_t success = FALSE, changed = FALSE;
pa_usec_t t, rtc;
struct timeval now, tv;
@@ -179,8 +187,9 @@ int main(int argc, char *argv[]) {
pa_gettimeofday(&now);
if (success) {
+#ifdef CORK
pa_bool_t cork_now;
-
+#endif
rtc = pa_timeval_diff(&now, &start);
printf("%i\t%llu\t%llu\t%llu\t%llu\t%lli\t%u\t%u\n", k,
(unsigned long long) rtc,
@@ -195,6 +204,7 @@ int main(int argc, char *argv[]) {
old_t = t;
old_rtc = rtc;
+#ifdef CORK
cork_now = (rtc / (2*PA_USEC_PER_SEC)) % 2 == 1;
if (corked != cork_now) {
@@ -206,6 +216,7 @@ int main(int argc, char *argv[]) {
corked = cork_now;
}
+#endif
}
/* Spin loop, ugly but normal usleep() is just too badly grained */
commit 9ee6a41491f2cfeccd9d60409598c903c657269c
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:12:12 2009 +0200
bluetooth: memory leak, actually free discovery struct itself
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 6e4344f..5c7681d 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -773,6 +773,8 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
if (y->core)
pa_shared_remove(y->core, "bluetooth-discovery");
+
+ pa_xfree(y);
}
void pa_bluetooth_discovery_sync(pa_bluetooth_discovery *y) {
commit 9ba9883693ebe817532468c0974c8d5dccb4e006
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:12:46 2009 +0200
dbus: memory leak, free server id after use
diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c
index b35e747..4e97046 100644
--- a/src/pulsecore/dbus-util.c
+++ b/src/pulsecore/dbus-util.c
@@ -247,6 +247,7 @@ static void wakeup_main(void *userdata) {
pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBusType type, DBusError *error) {
DBusConnection *conn;
pa_dbus_wrap_connection *pconn;
+ char *id;
pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER);
@@ -267,9 +268,11 @@ pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBus
pa_log_debug("Successfully connected to D-Bus %s bus %s as %s",
type == DBUS_BUS_SYSTEM ? "system" : (type == DBUS_BUS_SESSION ? "session" : "starter"),
- pa_strnull(dbus_connection_get_server_id(conn)),
+ pa_strnull((id = dbus_connection_get_server_id(conn))),
pa_strnull(dbus_bus_get_unique_name(conn)));
+ dbus_free(id);
+
return pconn;
}
commit 669703daec2b9231ab80eefe3bccfca29cc3decb
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:14:46 2009 +0200
dbus: memory leak, free pending calls
diff --git a/src/pulsecore/dbus-util.c b/src/pulsecore/dbus-util.c
index 4e97046..ece36de 100644
--- a/src/pulsecore/dbus-util.c
+++ b/src/pulsecore/dbus-util.c
@@ -380,8 +380,10 @@ pa_dbus_pending *pa_dbus_pending_new(
void pa_dbus_pending_free(pa_dbus_pending *p) {
pa_assert(p);
- if (p->pending)
- dbus_pending_call_cancel(p->pending); /* p->pending is freed by cancel() */
+ if (p->pending) {
+ dbus_pending_call_cancel(p->pending);
+ dbus_pending_call_unref(p->pending);
+ }
if (p->message)
dbus_message_unref(p->message);
commit 3507d1eb37173cb7f5e6a10d306f5fca57fe0b39
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:15:26 2009 +0200
socket-server: memory leak, free machine id after use
diff --git a/src/pulsecore/socket-server.c b/src/pulsecore/socket-server.c
index 8147b27..e660700 100644
--- a/src/pulsecore/socket-server.c
+++ b/src/pulsecore/socket-server.c
@@ -536,6 +536,7 @@ char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
return NULL;
pa_snprintf(c, l, "{%s}unix:%s", id, s->filename);
+ pa_xfree(id);
return c;
}
commit 5b871966ab556134b0bb3ff93e8cd81e16e19f5d
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:16:24 2009 +0200
protocol-native: print underrun message only once for each underrun
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index edcd598..9526de0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1468,7 +1468,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
if (pa_memblockq_is_readable(s->memblockq))
s->is_underrun = FALSE;
else {
- pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
+ if (!s->is_underrun)
+ pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
s->drain_request = FALSE;
commit f8ebe8571cbf52e9155b029ae085ea69e16178e1
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:16:59 2009 +0200
protocol-native: downgrade message if we receive pcm block for dead stream
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 9526de0..7c2183d 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -4245,7 +4245,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
pa_native_connection_assert_ref(c);
if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
- pa_log("client sent block for invalid stream.");
+ pa_log_debug("Client sent block for invalid stream.");
/* Ignoring */
return;
}
commit d827ecd28d87eedaa9eb50020504fe789c7800c8
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:17:49 2009 +0200
dbus: drop pa_ prefix from static symbol
diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c
index b52c14c..f01ec2c 100644
--- a/src/pulsecore/dbus-shared.c
+++ b/src/pulsecore/dbus-shared.c
@@ -41,7 +41,7 @@ struct pa_dbus_connection {
const char *property_name;
};
-static pa_dbus_connection* pa_dbus_connection_new(pa_core *c, pa_dbus_wrap_connection *conn, const char *name) {
+static pa_dbus_connection* dbus_connection_new(pa_core *c, pa_dbus_wrap_connection *conn, const char *name) {
pa_dbus_connection *pconn;
pconn = pa_xnew(pa_dbus_connection, 1);
@@ -73,9 +73,7 @@ pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *err
if (!(conn = pa_dbus_wrap_connection_new(c->mainloop, type, error)))
return NULL;
- pconn = pa_dbus_connection_new(c, conn, prop_name[type]);
-
- return pconn;
+ return dbus_connection_new(c, conn, prop_name[type]);
}
DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){
@@ -106,6 +104,3 @@ pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) {
return c;
}
-
-
-
commit dcd4a73df94b0e9083f72d79f81083961bd15746
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:18:04 2009 +0200
dbus: memory leak, actually free dbus wrapper
diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c
index f01ec2c..9d9445b 100644
--- a/src/pulsecore/dbus-shared.c
+++ b/src/pulsecore/dbus-shared.c
@@ -91,7 +91,8 @@ void pa_dbus_connection_unref(pa_dbus_connection *c) {
if (PA_REFCNT_DEC(c) > 0)
return;
- /* already disconnected, just free */
+ pa_dbus_wrap_connection_free(c->connection);
+
pa_shared_remove(c->core, c->property_name);
pa_xfree(c);
}
commit 9ae8ca2c3754abb9b6f6ce94c414c12d87419ac0
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:21:16 2009 +0200
core: memory leak, fix ref counting when moving streams
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 5855977..9ae98ed 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -335,8 +335,8 @@ int pa_sink_input_new(
0,
&i->sink->silence);
- pa_assert_se(pa_idxset_put(core->sink_inputs, pa_sink_input_ref(i), &i->index) == 0);
- pa_assert_se(pa_idxset_put(i->sink->inputs, i, NULL) == 0);
+ pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
+ pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
if (i->client)
pa_assert_se(pa_idxset_put(i->client->sink_inputs, i, NULL) >= 0);
@@ -1155,6 +1155,8 @@ int pa_sink_input_start_move(pa_sink_input *i) {
pa_sink_update_status(i->sink);
i->sink = NULL;
+ pa_sink_input_unref(i);
+
return 0;
}
@@ -1202,7 +1204,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
i->sink = dest;
i->save_sink = save;
- pa_idxset_put(dest->inputs, i, NULL);
+ pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL);
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
i->sink->n_corked++;
@@ -1267,11 +1269,19 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
if (!pa_sink_input_may_move_to(i, dest))
return -PA_ERR_NOTSUPPORTED;
- if ((r = pa_sink_input_start_move(i)) < 0)
+ pa_sink_input_ref(i);
+
+ if ((r = pa_sink_input_start_move(i)) < 0) {
+ pa_sink_input_unref(i);
return r;
+ }
- if ((r = pa_sink_input_finish_move(i, dest, save)) < 0)
+ if ((r = pa_sink_input_finish_move(i, dest, save)) < 0) {
+ pa_sink_input_unref(i);
return r;
+ }
+
+ pa_sink_input_unref(i);
return 0;
}
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 4cf7b6c..2771fec 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -515,8 +515,12 @@ pa_queue *pa_sink_move_all_start(pa_sink *s) {
for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = n) {
n = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx));
+ pa_sink_input_ref(i);
+
if (pa_sink_input_start_move(i) >= 0)
- pa_queue_push(q, pa_sink_input_ref(i));
+ pa_queue_push(q, i);
+ else
+ pa_sink_input_unref(i);
}
return q;
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 8918b43..489393a 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -705,6 +705,8 @@ int pa_source_output_start_move(pa_source_output *o) {
pa_source_update_status(o->source);
o->source = NULL;
+ pa_source_output_unref(o);
+
return 0;
}
@@ -752,7 +754,7 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
o->source = dest;
o->save_source = save;
- pa_idxset_put(o->source->outputs, o, NULL);
+ pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL);
if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
o->source->n_corked++;
@@ -804,11 +806,19 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t sav
if (!pa_source_output_may_move_to(o, dest))
return -PA_ERR_NOTSUPPORTED;
- if ((r = pa_source_output_start_move(o)) < 0)
+ pa_source_output_ref(o);
+
+ if ((r = pa_source_output_start_move(o)) < 0) {
+ pa_source_output_unref(o);
return r;
+ }
- if ((r = pa_source_output_finish_move(o, dest, save)) < 0)
+ if ((r = pa_source_output_finish_move(o, dest, save)) < 0) {
+ pa_source_output_unref(o);
return r;
+ }
+
+ pa_source_output_unref(o);
return 0;
}
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index b85d6e1..693fab3 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -466,8 +466,12 @@ pa_queue *pa_source_move_all_start(pa_source *s) {
for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
+ pa_source_output_ref(o);
+
if (pa_source_output_start_move(o) >= 0)
- pa_queue_push(q, pa_source_output_ref(o));
+ pa_queue_push(q, o);
+ else
+ pa_source_output_unref(o);
}
return q;
commit f7c229d8f9a4c67ff7ef0f3d351069a45ba19aff
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:26:04 2009 +0200
core: add a seperate fixed_latency field for sinks/sources with fixed latency
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 324f83c..b0911ef 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -288,7 +288,11 @@ char *pa_sink_list_to_string(pa_core *c) {
(double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
(double) min_latency / PA_USEC_PER_MSEC,
(double) max_latency / PA_USEC_PER_MSEC);
- }
+ } else
+ pa_strbuf_printf(
+ s,
+ "\tfixed latency: %0.2f ms\n",
+ (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC);
if (sink->card)
pa_strbuf_printf(s, "\tcard: %u <%s>\n", sink->card->index, sink->card->name);
@@ -382,7 +386,11 @@ char *pa_source_list_to_string(pa_core *c) {
(double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
(double) min_latency / PA_USEC_PER_MSEC,
(double) max_latency / PA_USEC_PER_MSEC);
- }
+ } else
+ pa_strbuf_printf(
+ s,
+ "\tfixed latency: %0.2f ms\n",
+ (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC);
if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index);
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 9ae98ed..b1b9fb5 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -824,6 +824,9 @@ void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the
pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
pa_sink_input_assert_ref(i);
+ if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
+ usec = i->sink->fixed_latency;
+
if (usec != (pa_usec_t) -1)
usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
@@ -835,8 +838,6 @@ pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa
/* Called from main context */
pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
- pa_usec_t min_latency, max_latency;
-
pa_sink_input_assert_ref(i);
if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
@@ -848,10 +849,14 @@ pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec)
* we have to touch the thread info data directly */
if (i->sink) {
- pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
+ if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
+ usec = i->sink->fixed_latency;
- if (usec != (pa_usec_t) -1)
+ if (usec != (pa_usec_t) -1) {
+ pa_usec_t min_latency, max_latency;
+ pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
usec = PA_CLAMP(usec, min_latency, max_latency);
+ }
}
i->thread_info.requested_sink_latency = usec;
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 2771fec..93800d1 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -50,6 +50,7 @@
#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
#define ABSOLUTE_MIN_LATENCY (500)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
+#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
@@ -208,6 +209,8 @@ pa_sink* pa_sink_new(
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
+ s->fixed_latency = flags & PA_SINK_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
+
reset_callbacks(s);
s->userdata = NULL;
@@ -363,8 +366,13 @@ void pa_sink_put(pa_sink* s) {
if (s->flags & PA_SINK_LATENCY)
s->monitor_source->flags |= PA_SOURCE_LATENCY;
- if (s->flags & PA_SINK_DYNAMIC_LATENCY)
+ if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
s->monitor_source->flags |= PA_SOURCE_DYNAMIC_LATENCY;
+ s->fixed_latency = 0;
+ } else if (s->fixed_latency <= 0)
+ s->fixed_latency = DEFAULT_FIXED_LATENCY;
+
+ s->monitor_source->fixed_latency = s->fixed_latency;
pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
@@ -1824,6 +1832,9 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
pa_sink_assert_ref(s);
+ if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
+ return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
+
if (s->thread_info.requested_latency_valid)
return s->thread_info.requested_latency;
@@ -1839,13 +1850,8 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
(result == (pa_usec_t) -1 || result > monitor_latency))
result = monitor_latency;
- if (result != (pa_usec_t) -1) {
- if (result > s->thread_info.max_latency)
- result = s->thread_info.max_latency;
-
- if (result < s->thread_info.min_latency)
- result = s->thread_info.min_latency;
- }
+ if (result != (pa_usec_t) -1)
+ result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
s->thread_info.requested_latency = result;
s->thread_info.requested_latency_valid = TRUE;
@@ -1934,6 +1940,9 @@ void pa_sink_invalidate_requested_latency(pa_sink *s) {
pa_sink_assert_ref(s);
+ if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
+ return;
+
s->thread_info.requested_latency_valid = FALSE;
if (PA_SINK_IS_LINKED(s->thread_info.state)) {
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 289054d..cb4697f 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -86,6 +86,8 @@ struct pa_sink {
pa_memchunk silence;
+ pa_usec_t fixed_latency; /* for sinks with PA_SINK_DYNAMIC_LATENCY this is 0 */
+
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 489393a..3ee2673 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -520,6 +520,9 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes /* i
pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
pa_source_output_assert_ref(o);
+ if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ usec = o->source->fixed_latency;
+
if (usec != (pa_usec_t) -1)
usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
@@ -531,8 +534,6 @@ pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output
/* Called from main context */
pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
- pa_usec_t min_latency, max_latency;
-
pa_source_output_assert_ref(o);
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
@@ -544,10 +545,14 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t
* have to touch the thread info data directly */
if (o->source) {
- pa_source_get_latency_range(o->source, &min_latency, &max_latency);
+ if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ usec = o->source->fixed_latency;
- if (usec != (pa_usec_t) -1)
+ if (usec != (pa_usec_t) -1) {
+ pa_usec_t min_latency, max_latency;
+ pa_source_get_latency_range(o->source, &min_latency, &max_latency);
usec = PA_CLAMP(usec, min_latency, max_latency);
+ }
}
o->thread_info.requested_source_latency = usec;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 693fab3..2190250 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -43,6 +43,7 @@
#define ABSOLUTE_MIN_LATENCY (500)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
+#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
@@ -199,6 +200,8 @@ pa_source* pa_source_new(
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
+ s->fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
+
reset_callbacks(s);
s->userdata = NULL;
@@ -303,8 +306,7 @@ void pa_source_put(pa_source *s) {
/* The following fields must be initialized properly when calling _put() */
pa_assert(s->asyncmsgq);
pa_assert(s->rtpoll);
- pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
- s->thread_info.min_latency <= s->thread_info.max_latency);
+ pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL)) {
s->flags |= PA_SOURCE_DECIBEL_VOLUME;
@@ -316,6 +318,11 @@ void pa_source_put(pa_source *s) {
if (s->flags & PA_SOURCE_DECIBEL_VOLUME)
s->n_volume_steps = PA_VOLUME_NORM+1;
+ if (s->flags & PA_SOURCE_DYNAMIC_LATENCY)
+ s->fixed_latency = 0;
+ else if (s->fixed_latency <= 0)
+ s->fixed_latency = DEFAULT_FIXED_LATENCY;
+
pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
@@ -1096,6 +1103,9 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
pa_source_assert_ref(s);
+ if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
+
if (s->thread_info.requested_latency_valid)
return s->thread_info.requested_latency;
@@ -1105,13 +1115,8 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
(result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
result = o->thread_info.requested_source_latency;
- if (result != (pa_usec_t) -1) {
- if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
- result = s->thread_info.max_latency;
-
- if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
- result = s->thread_info.min_latency;
- }
+ if (result != (pa_usec_t) -1)
+ result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
s->thread_info.requested_latency = result;
s->thread_info.requested_latency_valid = TRUE;
@@ -1121,7 +1126,7 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
/* Called from main thread */
pa_usec_t pa_source_get_requested_latency(pa_source *s) {
- pa_usec_t usec;
+ pa_usec_t usec = 0;
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -1169,6 +1174,9 @@ void pa_source_invalidate_requested_latency(pa_source *s) {
pa_source_assert_ref(s);
+ if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ return;
+
s->thread_info.requested_latency_valid = FALSE;
if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 652783e..b502c22 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -87,6 +87,8 @@ struct pa_source {
pa_memchunk silence;
+ pa_usec_t fixed_latency; /* for sources with PA_SOURCE_DYNAMIC_LATENCY this is 0 */
+
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */
commit 48cff5b55d66857b3017d847a571acc409f058ca
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:28:21 2009 +0200
bluetooth: rename sco to hsp also for the user
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 0e2b380..420f228 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1525,7 +1525,7 @@ static int add_source(struct userdata *u) {
#ifdef NOKIA
if (USE_SCO_OVER_PCM(u)) {
u->source = u->hsp.sco_source;
- pa_proplist_sets(u->source->proplist, "bluetooth.protocol", "sco");
+ pa_proplist_sets(u->source->proplist, "bluetooth.protocol", "hsp");
if (!u->hsp.source_state_changed_slot)
u->hsp.source_state_changed_slot = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) source_state_changed_cb, u);
@@ -1541,7 +1541,7 @@ static int add_source(struct userdata *u) {
data.driver = __FILE__;
data.module = u->module;
pa_source_new_data_set_sample_spec(&data, &u->sample_spec);
- pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
+ pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "hsp");
data.card = u->card;
data.name = get_name("source", u->modargs, u->address, &b);
data.namereg_fail = b;
@@ -1871,7 +1871,7 @@ static int add_card(struct userdata *u, const char *default_profile, const pa_bl
}
if (pa_bluetooth_uuid_has(device->uuids, HSP_HS_UUID) ||
- pa_bluetooth_uuid_has(device->uuids, HFP_HS_UUID)) {
+ pa_bluetooth_uuid_has(device->uuids, HFP_HS_UUID)) {
p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(enum profile));
p->priority = 20;
p->n_sinks = 1;
commit e9a4dec81ebc98f571d29d4f684855ceddd38d36
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:29:46 2009 +0200
bluetooth: be a bit more verbose if we exit due to bad poll() revents flag
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 420f228..bf2e0e8 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1265,7 +1265,11 @@ static void thread_func(void *userdata) {
pollfd = u->rtpoll_item ? pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL) : NULL;
if (pollfd && (pollfd->revents & ~(POLLOUT|POLLIN))) {
- pa_log_error("FD error.");
+ pa_log_info("FD error: %s%s%s%s",
+ pollfd->revents & POLLERR ? "POLLERR " :"",
+ pollfd->revents & POLLHUP ? "POLLHUP " :"",
+ pollfd->revents & POLLPRI ? "POLLPRI " :"",
+ pollfd->revents & POLLNVAL ? "POLLNVAL " :"");
goto fail;
}
}
commit d77b28cb4bd088ab0f723cbdd65e3947b35b3b25
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:30:50 2009 +0200
bluetooth: rework timing logic, properly implement latency callbacks
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index bf2e0e8..2812bc2 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -166,10 +166,14 @@ struct userdata {
pa_modargs *modargs;
- int stream_write_type, stream_read_type;
+ int stream_write_type;
int service_write_type, service_read_type;
};
+#define FIXED_LATENCY_PLAYBACK_A2DP (25*PA_USEC_PER_MSEC)
+#define FIXED_LATENCY_PLAYBACK_HSP (125*PA_USEC_PER_MSEC)
+#define FIXED_LATENCY_RECORD_HSP (25*PA_USEC_PER_MSEC)
+
#ifdef NOKIA
#define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
#endif
@@ -711,6 +715,7 @@ static int start_stream_fd(struct userdata *u) {
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
} msg;
struct pollfd *pollfd;
+ int one;
pa_assert(u);
pa_assert(u->rtpoll);
@@ -739,13 +744,29 @@ static int start_stream_fd(struct userdata *u) {
pa_make_fd_nonblock(u->stream_fd);
pa_make_socket_low_delay(u->stream_fd);
+ one = 1;
+ if (setsockopt(u->stream_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)) < 0)
+ pa_log_warn("Failed to enable SO_TIMESTAMP: %s", pa_cstrerror(errno));
+
+ pa_log_debug("Stream properly set up, we're ready to roll!");
+
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
pollfd->fd = u->stream_fd;
pollfd->events = pollfd->revents = 0;
- u->read_index = 0;
- u->write_index = 0;
+ u->read_index = u->write_index = 0;
+ u->started_at = 0;
+
+ if (u->source)
+ u->read_smoother = pa_smoother_new(
+ PA_USEC_PER_SEC,
+ PA_USEC_PER_SEC*2,
+ TRUE,
+ TRUE,
+ 10,
+ pa_rtclock_usec(),
+ TRUE);
return 0;
}
@@ -781,6 +802,11 @@ static int stop_stream_fd(struct userdata *u) {
pa_close(u->stream_fd);
u->stream_fd = -1;
+ if (u->read_smoother) {
+ pa_smoother_free(u->read_smoother);
+ u->read_smoother = NULL;
+ }
+
return r;
}
@@ -819,8 +845,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
if (!u->source || u->source->state == PA_SOURCE_SUSPENDED)
if (start_stream_fd(u) < 0)
failed = TRUE;
-
- u->started_at = pa_rtclock_usec();
break;
case PA_SINK_UNLINKED:
@@ -831,7 +855,24 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
break;
case PA_SINK_MESSAGE_GET_LATENCY: {
- *((pa_usec_t*) data) = 0;
+
+ if (u->read_smoother) {
+ pa_usec_t wi, ri;
+
+ ri = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
+ wi = pa_bytes_to_usec(u->write_index + u->block_size, &u->sample_spec);
+
+ *((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
+ } else {
+ pa_usec_t ri, wi;
+
+ ri = pa_rtclock_usec() - u->started_at;
+ wi = pa_bytes_to_usec(u->write_index, &u->sample_spec);
+
+ *((pa_usec_t*) data) = wi > ri ? wi - ri : 0;
+ }
+
+ *((pa_usec_t*) data) += u->sink->fixed_latency;
return 0;
}
}
@@ -862,7 +903,8 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
if (!u->sink || u->sink->state == PA_SINK_SUSPENDED)
stop_stream_fd(u);
- pa_smoother_pause(u->read_smoother, pa_rtclock_usec());
+ if (u->read_smoother)
+ pa_smoother_pause(u->read_smoother, pa_rtclock_usec());
break;
case PA_SOURCE_IDLE:
@@ -875,7 +917,8 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
if (start_stream_fd(u) < 0)
failed = TRUE;
- pa_smoother_resume(u->read_smoother, pa_rtclock_usec(), TRUE);
+ /* We don't resume the smoother here. Instead we
+ * wait until the first packet arrives */
break;
case PA_SOURCE_UNLINKED:
@@ -886,7 +929,12 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
break;
case PA_SOURCE_MESSAGE_GET_LATENCY: {
- *((pa_usec_t*) data) = 0;
+ pa_usec_t wi, ri;
+
+ wi = pa_smoother_get(u->read_smoother, pa_rtclock_usec());
+ ri = pa_bytes_to_usec(u->read_index, &u->sample_spec);
+
+ *((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->fixed_latency;
return 0;
}
@@ -954,6 +1002,7 @@ static int hsp_process_render(struct userdata *u) {
pa_memblock_unref(u->write_memchunk.memblock);
pa_memchunk_reset(&u->write_memchunk);
+ ret = 1;
break;
}
@@ -968,6 +1017,7 @@ static int hsp_process_push(struct userdata *u) {
pa_assert(u);
pa_assert(u->profile == PROFILE_HSP);
pa_assert(u->source);
+ pa_assert(u->read_smoother);
memchunk.memblock = pa_memblock_new(u->core->mempool, u->block_size);
memchunk.index = memchunk.length = 0;
@@ -975,9 +1025,26 @@ static int hsp_process_push(struct userdata *u) {
for (;;) {
ssize_t l;
void *p;
+ struct msghdr m;
+ struct cmsghdr *cm;
+ uint8_t aux[1024];
+ struct iovec iov;
+ pa_bool_t found_tstamp = FALSE;
+ pa_usec_t tstamp;
+
+ memset(&m, 0, sizeof(m));
+ memset(&aux, 0, sizeof(aux));
+ memset(&iov, 0, sizeof(iov));
+
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+ m.msg_control = aux;
+ m.msg_controllen = sizeof(aux);
p = pa_memblock_acquire(memchunk.memblock);
- l = pa_read(u->stream_fd, p, pa_memblock_get_length(memchunk.memblock), &u->stream_read_type);
+ iov.iov_base = p;
+ iov.iov_len = pa_memblock_get_length(memchunk.memblock);
+ l = recvmsg(u->stream_fd, &m, 0);
pa_memblock_release(memchunk.memblock);
if (l <= 0) {
@@ -1000,7 +1067,26 @@ static int hsp_process_push(struct userdata *u) {
memchunk.length = (size_t) l;
u->read_index += (uint64_t) l;
+ for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
+ if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SO_TIMESTAMP) {
+ struct timeval *tv = (struct timeval*) CMSG_DATA(cm);
+ pa_rtclock_from_wallclock(tv);
+ tstamp = pa_timeval_load(tv);
+ found_tstamp = TRUE;
+ break;
+ }
+
+ if (!found_tstamp) {
+ pa_log_warn("Couldn't find SO_TIMESTAMP data in auxiliary recvmsg() data!");
+ tstamp = pa_rtclock_usec();
+ }
+
+ pa_smoother_put(u->read_smoother, tstamp, pa_bytes_to_usec(u->read_index, &u->sample_spec));
+ pa_smoother_resume(u->read_smoother, tstamp, TRUE);
+
pa_source_post(u->source, &memchunk);
+
+ ret = 1;
break;
}
@@ -1105,7 +1191,7 @@ static int a2dp_process_render(struct userdata *u) {
header->v = 2;
header->pt = 1;
header->sequence_number = htons(a2dp->seq_num++);
- header->timestamp = htonl(u->write_index / pa_frame_size(&u->sink->sample_spec));
+ header->timestamp = htonl(u->write_index / pa_frame_size(&u->sample_spec));
header->ssrc = htonl(1);
payload->frame_count = frame_count;
@@ -1147,6 +1233,8 @@ static int a2dp_process_render(struct userdata *u) {
pa_memblock_unref(u->write_memchunk.memblock);
pa_memchunk_reset(&u->write_memchunk);
+ ret = 1;
+
break;
}
@@ -1155,7 +1243,8 @@ static int a2dp_process_render(struct userdata *u) {
static void thread_func(void *userdata) {
struct userdata *u = userdata;
- pa_bool_t do_write = FALSE, writable = FALSE;
+ unsigned do_write = 0;
+ pa_bool_t writable = FALSE;
pa_assert(u);
@@ -1170,8 +1259,6 @@ static void thread_func(void *userdata) {
pa_thread_mq_install(&u->thread_mq);
pa_rtpoll_install(u->rtpoll);
- pa_smoother_set_time_offset(u->read_smoother, pa_rtclock_usec());
-
for (;;) {
struct pollfd *pollfd;
int ret;
@@ -1182,12 +1269,13 @@ static void thread_func(void *userdata) {
if (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state)) {
if (pollfd && (pollfd->revents & POLLIN)) {
+ int n_read;
- if (hsp_process_push(u) < 0)
+ if ((n_read = hsp_process_push(u)) < 0)
goto fail;
/* We just read something, so we are supposed to write something, too */
- do_write = TRUE;
+ do_write += n_read;
}
}
@@ -1200,7 +1288,7 @@ static void thread_func(void *userdata) {
if (pollfd->revents & POLLOUT)
writable = TRUE;
- if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && !do_write && writable) {
+ if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0 && writable) {
pa_usec_t time_passed;
uint64_t should_have_written;
@@ -1208,36 +1296,37 @@ static void thread_func(void *userdata) {
* to. So let's do things by time */
time_passed = pa_rtclock_usec() - u->started_at;
- should_have_written = pa_usec_to_bytes(time_passed, &u->sink->sample_spec);
+ should_have_written = pa_usec_to_bytes(time_passed, &u->sample_spec);
- do_write = u->write_index <= should_have_written ;
-/* pa_log_debug("Time has come: %s", pa_yes_no(do_write)); */
+ do_write = u->write_index <= should_have_written;
}
- if (writable && do_write) {
- if (u->write_index == 0)
+ if (writable && do_write > 0) {
+ int n_written;
+
+ if (u->write_index <= 0)
u->started_at = pa_rtclock_usec();
if (u->profile == PROFILE_A2DP) {
- if (a2dp_process_render(u) < 0)
+ if ((n_written = a2dp_process_render(u)) < 0)
goto fail;
} else {
- if (hsp_process_render(u) < 0)
+ if ((n_written = hsp_process_render(u)) < 0)
goto fail;
}
- do_write = FALSE;
+ do_write -= n_written;
writable = FALSE;
}
- if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && !do_write) {
+ if ((!u->source || !PA_SOURCE_IS_LINKED(u->source->thread_info.state)) && do_write <= 0) {
pa_usec_t time_passed, next_write_at, sleep_for;
/* Hmm, there is no input stream we could synchronize
* to. So let's estimate when we need to wake up the latest */
time_passed = pa_rtclock_usec() - u->started_at;
- next_write_at = pa_bytes_to_usec(u->write_index, &u->sink->sample_spec);
+ next_write_at = pa_bytes_to_usec(u->write_index, &u->sample_spec);
sleep_for = time_passed < next_write_at ? next_write_at - time_passed : 0;
/* pa_log("Sleeping for %lu; time passed %lu, next write at %lu", (unsigned long) sleep_for, (unsigned long) time_passed, (unsigned long)next_write_at); */
@@ -1317,12 +1406,12 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
if (u->profile == PROFILE_HSP) {
if (u->sink && dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged")) {
- pa_cvolume_set(&v, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_sink_volume_changed(u->sink, &v);
} else if (u->source && dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
- pa_cvolume_set(&v, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_source_volume_changed(u->source, &v);
}
}
@@ -1350,7 +1439,7 @@ static void sink_set_volume_cb(pa_sink *s) {
if (gain > 15)
gain = 15;
- pa_cvolume_set(&s->virtual_volume, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_cvolume_set(&s->virtual_volume, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetSpeakerGain"));
pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID));
@@ -1374,7 +1463,7 @@ static void source_set_volume_cb(pa_source *s) {
if (gain > 15)
gain = 15;
- pa_cvolume_set(&s->virtual_volume, u->source->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_cvolume_set(&s->virtual_volume, u->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetMicrophoneGain"));
pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID));
@@ -1513,6 +1602,9 @@ static int add_sink(struct userdata *u) {
u->sink->parent.process_msg = sink_process_msg;
pa_sink_set_max_request(u->sink, u->block_size);
+ u->sink->fixed_latency =
+ (u->profile == PROFILE_A2DP ? FIXED_LATENCY_PLAYBACK_A2DP : FIXED_LATENCY_PLAYBACK_HSP) +
+ pa_bytes_to_usec(u->block_size, &u->sample_spec);
}
if (u->profile == PROFILE_HSP) {
@@ -1560,6 +1652,10 @@ static int add_source(struct userdata *u) {
u->source->userdata = u;
u->source->parent.process_msg = source_process_msg;
+
+ u->source->fixed_latency =
+ (/* u->profile == PROFILE_A2DP ? FIXED_LATENCY_RECORD_A2DP : */ FIXED_LATENCY_RECORD_HSP) +
+ pa_bytes_to_usec(u->block_size, &u->sample_spec);
}
if (u->profile == PROFILE_HSP) {
@@ -1580,12 +1676,12 @@ static void shutdown_bt(struct userdata *u) {
u->stream_fd = -1;
u->stream_write_type = 0;
- u->stream_read_type = 0;
}
if (u->service_fd >= 0) {
pa_close(u->service_fd);
u->service_fd = -1;
+ u->service_write_type = u->service_write_type = 0;
}
if (u->write_memchunk.memblock) {
@@ -1600,7 +1696,7 @@ static int init_bt(struct userdata *u) {
shutdown_bt(u);
- u->stream_write_type = u->stream_read_type = 0;
+ u->stream_write_type = 0;
u->service_write_type = u->service_write_type = 0;
if ((u->service_fd = bt_audio_service_open()) < 0) {
@@ -1701,6 +1797,11 @@ static void stop_thread(struct userdata *u) {
pa_rtpoll_free(u->rtpoll);
u->rtpoll = NULL;
}
+
+ if (u->read_smoother) {
+ pa_smoother_free(u->read_smoother);
+ u->read_smoother = NULL;
+ }
}
/* Run from main thread */
@@ -1997,14 +2098,6 @@ int pa__init(pa_module* m) {
u->core = m->core;
u->service_fd = -1;
u->stream_fd = -1;
- u->read_smoother = pa_smoother_new(
- PA_USEC_PER_SEC,
- PA_USEC_PER_SEC*2,
- TRUE,
- TRUE,
- 10,
- 0,
- FALSE);
u->sample_spec = m->core->default_sample_spec;
u->modargs = ma;
commit ee6657aa9a654d334a5a900ea359c726550383e0
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Apr 10 01:31:25 2009 +0200
bluetooth: when starting up HSP stream, send 2 packets first, only afterwards enter one-read-one-write logic
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2812bc2..90f6486 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1268,6 +1268,12 @@ static void thread_func(void *userdata) {
if (u->source && PA_SOURCE_IS_LINKED(u->source->thread_info.state)) {
+ /* We should send two blocks to the device before we expect
+ * a response. */
+
+ if (u->write_index == 0 && u->read_index <= 0)
+ do_write = 2;
+
if (pollfd && (pollfd->revents & POLLIN)) {
int n_read;
--
hooks/post-receive
PulseAudio Sound Server
More information about the pulseaudio-commits
mailing list