[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master-tx, updated. v0.9.15-test5-121-gcab1e54
Lennart Poettering
gitmailer-noreply at 0pointer.de
Mon Mar 30 15:31:45 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-tx branch has been updated
from 4c381cd7b4889b9dce361922fc1624648efe5dd6 (commit)
- Log -----------------------------------------------------------------
cab1e54 explain ff7033c11d9248fe837204b03c8397231dc511fe
ff7033c Revert "make sure we always read in all properties"
29a282a allow nofail mode only when no server string was specified
b6135b3 minor cleanups
3df9eef take org.pulseaudio.Server instead of org.pulseaudio to match the interface name already used in the HAL module
857a1f4 fix compiler warning
90fbc03 make sure we never access an invalid pa_bluetooth_device object
1c8f968 make sure we always read in all properties
66b80e9 get rid of old 'Connected' property parsing and make sure we don't execute two case branches
91355a1 introduce typedef for pa_bt_audio_state and use it everywhere
1390564 Merge commit 'elmarco/bluetooth-fixes'
d33be12 Merge commit 'elmarco/dbus'
649c982 Use pa_source_set_max_rewind_within_thread() for updating the monitor source's max_rewind
8491b47 gtk-test: updated to use PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL
1dad83b pulse: client connect to dbus
b4ef64d daemon: take org.pulseaudio
eb93e25 dbus: split dbus-util into dbus-shared
1743322 Merge commit 'coling/master'
061344f Merge commit 'origin/master'
aa68036 rework tunneling code
65b787d notify clients about tlength changes
491aafd typo fix
b349dae add pa_memblockq_apply_attr()/pa_memblockq_get_attr()
7c37c37 document more often the context certain functions are called in
7f5481e simplify latency config functions a bit and make them callable in more contexts
d04f3e1 Trigger move callback a little bit earlier so that no IO thread is running
e3f1510 don't enabled tsched on software ALSA devices
87fcb3d bluetooth: use new audio State properties
38825d7 bluetooth: GetProperties after profile UUID show up
20bd1c6 bluetooth: remove racy GetProperties to check profile
9e8c2d3 bluetooth: don't access outside array range
61cd6d4 bluetooth: fail when switching on non-connected profile
62a4e36 bluetooth: connected can be -1, check > 0
87d63b1 Small fix for MacOSX compat
db714bf fix typo
13f1c44 Do not reconfigure capabilities.
168c741 Query and make use of the current configuration.
071b3e7 Update ipc to match new message headers introduced on BlueZ 4.34.
b03c545 Fix misuse of 'frame.joint' when estimating the frame length.
f80a1f6 Maintain the original code style for sbc.
205cbe8 raop: Add call to pa_sink_set_max_request()
3813034 add missing initialization
cbbd986 make sure the discovery module is only loaded once
39576ec on monitor source be fine with any latency range set by the sink
6defb1a add missing whitespace
2c1eaa7 copy latency flags from sink to monitor source
4edb109 use u->use_tsched everywhere
8282efc fix value of DYNAMIC_LATENCY
c367a88 fix misplace _ref() calls that should have been _assert_ref()
f6a6d01 optionally skip initial frames in backtrace
8460fac don't show full so path in backtrace
e41ec51 add simple ref counting debugging framework
577259b trivial simplification
119698a beef up esd sink properties a bit
fdbe054 initialize max_request to SO_SNDBUF
98a5f4a don't fiddle with latency range in sources with static latency
d0bd3d9 initialize max_request
bcfe51f again, don't fiddle with latency range in sinks with static latency
59b7e53 Don't initialize userdata twice
b815a1c don't fiddle with latency range because we cannot adjust it dynamically
0316dba set latency range only in tsched mode
171c88f link jack modules's max_request to the jack buffer size
892a839 simplify things and make sure timing setters can be called in most contexts
44ca897 introduce new flag that marks sinks/sources which can adjust the latency dynamically
9bca59e make pa_source_set_max_rewind() work similar to pa_sink_set_max_rewind()
9151107 get rid of 'default' min/max latencies, simplify things by just having absolute boundaries
a7246bd bluetooth: fix #NOKIA, correctly unlink sink/src
5b523d0 fix bad memory access when destroying m-b-d
c64d8cb Allow calling pa_{sink|source}_update_proplist() without an actual proprlist
50695d9 minimal reordering
2f9a784 set request/rewind sizes only via accessor functions
aa92ff4 simplify latency range by not allowing stored 'wildcard' ranges anymore
e6be948 only decrease timer slack, never increase
bcbfd5b don't fail when no session bus is available
52dcb95 add pa_assert_cc() for compile time assertions
a467bec pulse: check context (do not user pstream when NULL)
0815455 only store card profile if flagged for that
124de50 enable bluetooth default by support
906fd57 Merge commit 'origin/master-tx'
c14da67 readd volume control logic
b3675c2 add functions that modules can call whenever they now the volume changed
8d5b375 at a couple of #ifdef NOKIAs for now
3aa3972 rework device discovery to share a single device list among all modules
20488fb add pa_hook_is_firing
f5c8990 make sure we dispatch messages in order
77a1db1 fix a misplaced assert
888e44f rework bluetooth IO loops
d2bee57 fix prototypes of remaining sbc.[ch] API regarding size_t/const
99dae9b don't try to unref reserve stuff if we don't use it
0251078 fix channel mapping for a52 devices. Closes #508
33a8f53 simply bluetooth nrec handling a bit
dfb3d2e always remap relative volume properly
a998038 introduce pa_sink_input_get_relative_volume()
bd3154a introduce pa_assert_fp() for fast path assertions
fe3709c fix a comment
-----------------------------------------------------------------------
Summary of changes:
PROTOCOL | 13 +
src/Makefile.am | 36 +-
src/daemon/default.pa.in | 2 +-
src/daemon/main.c | 40 +
src/modules/alsa/alsa-sink.c | 34 +-
src/modules/alsa/alsa-source.c | 28 +-
src/modules/alsa/alsa-util.c | 21 +-
src/modules/alsa/alsa-util.h | 2 +
src/modules/alsa/module-alsa-card.c | 3 +-
src/modules/bluetooth/bluetooth-util.c | 368 +++++-----
src/modules/bluetooth/bluetooth-util.h | 58 +-
src/modules/bluetooth/ipc.c | 1 +
src/modules/bluetooth/ipc.h | 73 ++-
src/modules/bluetooth/module-bluetooth-device.c | 837 +++++++++++---------
src/modules/bluetooth/module-bluetooth-discover.c | 108 ++-
src/modules/bluetooth/module-bluetooth-proximity.c | 2 +-
src/modules/bluetooth/sbc.c | 43 +-
src/modules/bluetooth/sbc.h | 14 +-
src/modules/hal-util.c | 2 +-
src/modules/module-card-restore.c | 3 +
src/modules/module-combine.c | 13 +-
src/modules/module-console-kit.c | 2 +-
src/modules/module-esound-sink.c | 13 +-
src/modules/module-hal-detect.c | 2 +-
src/modules/module-jack-sink.c | 21 +-
src/modules/module-jack-source.c | 10 +-
src/modules/module-ladspa-sink.c | 10 +-
src/modules/module-null-sink.c | 13 +-
src/modules/module-pipe-sink.c | 1 +
src/modules/module-raop-sink.c | 11 +-
src/modules/module-remap-sink.c | 10 +-
src/modules/module-sine-source.c | 5 +-
src/modules/module-solaris.c | 4 +-
src/modules/module-stream-restore.c | 22 +-
src/modules/module-tunnel.c | 187 +++--
src/modules/oss/module-oss.c | 2 +-
src/modules/reserve-wrap.c | 10 +-
src/pulse/context.c | 89 ++-
src/pulse/context.h | 7 +-
src/pulse/def.h | 21 +-
src/pulse/fork-detect.c | 2 +-
src/pulse/internal.h | 10 +-
src/pulse/stream.c | 95 +++-
src/pulse/stream.h | 9 +-
src/pulsecore/card.c | 11 +-
src/pulsecore/card.h | 6 +-
src/pulsecore/cli-command.c | 4 +-
src/pulsecore/cli-text.c | 45 +-
src/pulsecore/core-util.c | 2 +-
src/pulsecore/dbus-shared.c | 111 +++
src/pulsecore/{protocol-http.h => dbus-shared.h} | 27 +-
src/{modules => pulsecore}/dbus-util.c | 132 ++--
src/{modules => pulsecore}/dbus-util.h | 20 +-
src/pulsecore/hook-list.c | 6 +
src/pulsecore/hook-list.h | 2 +
src/pulsecore/log.c | 37 +-
src/pulsecore/log.h | 3 +
src/pulsecore/macro.h | 34 +-
src/pulsecore/memblock.c | 43 +-
src/pulsecore/memblockq.c | 20 +
src/pulsecore/memblockq.h | 5 +-
src/pulsecore/native-common.h | 6 +-
src/pulsecore/protocol-esound.c | 10 +-
src/pulsecore/protocol-native.c | 445 ++++++-----
src/pulsecore/refcnt.h | 44 +-
src/pulsecore/rtclock.c | 16 +-
src/pulsecore/sink-input.c | 86 ++-
src/pulsecore/sink-input.h | 3 +-
src/pulsecore/sink.c | 158 +++-
src/pulsecore/sink.h | 12 +-
src/pulsecore/source-output.c | 64 +-
src/pulsecore/source-output.h | 2 +-
src/pulsecore/source.c | 126 +++-
src/pulsecore/source.h | 8 +-
src/tests/gtk-test.c | 41 +-
75 files changed, 2404 insertions(+), 1382 deletions(-)
create mode 100644 src/pulsecore/dbus-shared.c
copy src/pulsecore/{protocol-http.h => dbus-shared.h} (56%)
rename src/{modules => pulsecore}/dbus-util.c (78%)
rename src/{modules => pulsecore}/dbus-util.h (69%)
-----------------------------------------------------------------------
commit fe3709c5c73f9ce837837908fb644147d5fa4eae
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Mar 19 19:38:30 2009 +0100
fix a comment
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 50a9191..4860860 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -775,7 +775,7 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
if (s->connection->version >= 13) {
pa_tagstruct *t;
- /* Notify the user we're overflowed*/
+ /* Notify the user we started playback */
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
commit bd3154a861d7ed0c68c687dcaa214a181ffb9f9d
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 13:29:42 2009 +0100
introduce pa_assert_fp() for fast path assertions
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 0048e7b..47ca267 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -851,6 +851,14 @@ int main(int argc, char *argv[]) {
pa_log_debug(_("Optimized build: no"));
#endif
+#ifdef NDEBUG
+ pa_log_debug(_("NDEBUG defined, all asserts disabled."));
+#elif defined(FASTPATH)
+ pa_log_debug(_("FASTPATH defined, only fast path asserts disabled."));
+#else
+ pa_log_debug(_("All asserts enabled."));
+#endif
+
if (!(s = pa_machine_id())) {
pa_log(_("Failed to get machine ID"));
goto finish;
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 20015bf..309f1a0 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -164,8 +164,8 @@ typedef int pa_bool_t;
#define pa_return_null_if_fail(expr) pa_return_val_if_fail(expr, NULL)
-/* An assert which guarantees side effects of x, i.e. is never
- * optimized away */
+/* pa_assert_se() is an assert which guarantees side effects of x,
+ * i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
#define pa_assert_se(expr) \
do { \
if (PA_UNLIKELY(!(expr))) { \
@@ -174,11 +174,23 @@ typedef int pa_bool_t;
} \
} while (FALSE)
-/* An assert that may be optimized away by defining NDEBUG */
+/* Does exactly nothing */
+#define pa_nop() do {} while (FALSE)
+
+/* pa_assert() is an assert that may be optimized away by defining
+ * NDEBUG. pa_assert_fp() is an assert that may be optimized away by
+ * defining FASTPATH. It is supposed to be used in inner loops. It's
+ * there for extra paranoia checking and should probably be removed in
+ * production builds. */
#ifdef NDEBUG
-#define pa_assert(expr) do {} while (FALSE)
+#define pa_assert(expr) pa_nop()
+#define pa_assert_fp(expr) pa_nop()
+#elif defined (FASTPATH)
+#define pa_assert(expr) pa_assert_se(expr)
+#define pa_assert_fp(expr) pa_nop()
#else
#define pa_assert(expr) pa_assert_se(expr)
+#define pa_assert_fp(expr) pa_assert_se(expr)
#endif
#define pa_assert_not_reached() \
commit a998038ee26f86054d0e314fcfe589169ce97ea7
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 13:50:26 2009 +0100
introduce pa_sink_input_get_relative_volume()
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 53e727b..ae2c6f5 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -924,6 +924,28 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
}
/* Called from main context */
+pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) {
+ pa_sink_input_assert_ref(i);
+ pa_assert(v);
+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+
+ *v = i->virtual_volume;
+
+ /* This always returns a relative volume, even in flat volume mode */
+
+ if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
+ pa_cvolume sv;
+
+ sv = *pa_sink_get_volume(i->sink, FALSE);
+
+ pa_sw_cvolume_divide(v, v,
+ pa_cvolume_remap(&sv, &i->sink->channel_map, &i->channel_map));
+ }
+
+ return v;
+}
+
+/* Called from main context */
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
pa_assert(i);
pa_sink_input_assert_ref(i);
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index e380168..0bcb9d5 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -302,6 +302,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency);
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save);
const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i);
+pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v);
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save);
pa_bool_t pa_sink_input_get_mute(pa_sink_input *i);
void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p);
commit dfb3d2ec57f234d450076fdd9393a8e18dd57e45
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 13:51:08 2009 +0100
always remap relative volume properly
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index 723b5d7..2c90e72 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -192,7 +192,7 @@ static struct entry* read_entry(struct userdata *u, const char *name) {
goto fail;
}
- if ((e->relative_volume_valid || e->absolute_volume_valid) && !(pa_channel_map_valid(&e->channel_map))) {
+ if ((e->relative_volume_valid || e->absolute_volume_valid) && !pa_channel_map_valid(&e->channel_map)) {
pa_log_warn("Invalid channel map stored in database for stream %s", name);
goto fail;
}
@@ -293,16 +293,14 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
entry.channel_map = sink_input->channel_map;
+ pa_sink_input_get_relative_volume(sink_input, &entry.relative_volume);
+ entry.relative_volume_valid = sink_input->save_volume;
+
if (sink_input->sink->flags & PA_SINK_FLAT_VOLUME) {
entry.absolute_volume = *pa_sink_input_get_volume(sink_input);
entry.absolute_volume_valid = sink_input->save_volume;
-
- pa_sw_cvolume_divide(&entry.relative_volume, &entry.absolute_volume, pa_sink_get_volume(sink_input->sink, FALSE));
- entry.relative_volume_valid = sink_input->save_volume;
- } else {
- entry.relative_volume = *pa_sink_input_get_volume(sink_input);
- entry.relative_volume_valid = sink_input->save_volume;
- }
+ } else
+ entry.absolute_volume_valid = FALSE;
entry.muted = pa_sink_input_get_mute(sink_input);
entry.muted_valid = sink_input->save_muted;
@@ -528,11 +526,11 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
if (!(n = get_name(si->proplist, "sink-input")))
continue;
- if (strcmp(name, n)) {
+ if (!pa_streq(name, n)) {
pa_xfree(n);
continue;
}
- pa_xfree(n);
+ pa_xfree(n);
if (u->restore_volume) {
pa_cvolume v;
@@ -578,11 +576,11 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
if (!(n = get_name(so->proplist, "source-output")))
continue;
- if (strcmp(name, n)) {
+ if (!pa_streq(name, n)) {
pa_xfree(n);
continue;
}
- pa_xfree(n);
+ pa_xfree(n);
if (u->restore_device &&
e->device_valid &&
commit 33a8f53ddfa9f3f9604d67130ea2cc66ea9202dc
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 13:54:45 2009 +0100
simply bluetooth nrec handling a bit
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 8d066a9..3da69fc 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -77,8 +77,6 @@ PA_MODULE_USAGE(
/* TODO: not close fd when entering suspend mode in a2dp */
-/* TODO: BT_PCM_FLAG_NREC */
-
static const char* const valid_modargs[] = {
"name",
"card_name",
@@ -1500,10 +1498,7 @@ static int add_source(struct userdata *u) {
/* u->source->get_volume = source_get_volume_cb; */
/* u->source->set_volume = source_set_volume_cb; */
- p = pa_proplist_new();
- pa_proplist_sets(p, "bluetooth.nrec", pa_yes_no(u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC));
- pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);
- pa_proplist_free(p);
+ pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0");
return 0;
}
commit 025107876c9ae9032bc9d87c19798ae154f54615
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 14:15:18 2009 +0100
fix channel mapping for a52 devices. Closes #508
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 454cfd4..3f26aeb 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -587,9 +587,9 @@ static const struct pa_alsa_profile_info device_table[] = {
"analog-surround-51",
8 },
- {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_CENTER,
- PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT,
- PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE}},
+ {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+ PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
+ PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE}},
"a52",
N_("Digital Surround 5.1 (IEC958/AC3)"),
"iec958-ac3-surround-51",
commit 99dae9b1afdc430ca1e1aedc0f4e3554f56c983a
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 14:47:36 2009 +0100
don't try to unref reserve stuff if we don't use it
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index d5e2cdc..fdc952d 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -351,7 +351,8 @@ int pa__init(pa_module *m) {
init_profile(u);
- pa_reserve_wrapper_unref(reserve);
+ if (reserve)
+ pa_reserve_wrapper_unref(reserve);
return 0;
commit d2bee57ee5f96e0ff91f6bd124083e83ffeb0de2
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 17:59:40 2009 +0100
fix prototypes of remaining sbc.[ch] API regarding size_t/const
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
index 6fa5479..42bae91 100644
--- a/src/modules/bluetooth/sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -973,13 +973,15 @@ int sbc_init(sbc_t *sbc, unsigned long flags)
return 0;
}
-int sbc_parse(sbc_t *sbc, void *input, int input_len)
+ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
{
return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
}
-int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
- int output_len, int *written)
+ssize_t sbc_decode(sbc_t *sbc,
+ const void *input, size_t input_len,
+ void *output, size_t output_len,
+ size_t *written)
{
struct sbc_priv *priv;
char *ptr;
@@ -1020,7 +1022,7 @@ int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
ptr = output;
- if (output_len < samples * priv->frame.channels * 2)
+ if (output_len < (size_t) (samples * priv->frame.channels * 2))
samples = output_len / (priv->frame.channels * 2);
for (i = 0; i < samples; i++) {
diff --git a/src/modules/bluetooth/sbc.h b/src/modules/bluetooth/sbc.h
index 25a1288..9a7b4ce 100644
--- a/src/modules/bluetooth/sbc.h
+++ b/src/modules/bluetooth/sbc.h
@@ -82,9 +82,13 @@ typedef struct sbc_struct sbc_t;
int sbc_init(sbc_t *sbc, unsigned long flags);
int sbc_reinit(sbc_t *sbc, unsigned long flags);
-int sbc_parse(sbc_t *sbc, void *input, int input_len);
-int sbc_decode(sbc_t *sbc, void *input, int input_len, void *output,
- int output_len, int *len);
+
+ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
+
+ssize_t sbc_decode(sbc_t *sbc,
+ const void *input, size_t input_len,
+ void *output, size_t output_len,
+ size_t *written);
/* Encodes ONE input block into ONE output block */
ssize_t sbc_encode(sbc_t *sbc,
commit 888e44f3b0a361b5cfcca1090d0defd21217db11
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 18:04:23 2009 +0100
rework bluetooth IO loops
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 3da69fc..fc8dc9c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -96,7 +96,7 @@ struct a2dp_info {
sbc_capabilities_t sbc_capabilities;
sbc_t sbc; /* Codec data */
pa_bool_t sbc_initialized; /* Keep track if the encoder is initialized */
- size_t codesize; /* SBC codesize */
+ size_t codesize, frame_length; /* SBC Codesize, frame_length. We simply cache those values here */
void* buffer; /* Codec transfer buffer */
size_t buffer_size; /* Size of the buffer */
@@ -583,7 +583,8 @@ static void setup_sbc(struct a2dp_info *a2dp) {
}
a2dp->sbc.bitpool = active_capabilities->max_bitpool;
- a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc);
+ a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
+ a2dp->frame_length = sbc_get_frame_length(&a2dp->sbc);
}
static int set_conf(struct userdata *u) {
@@ -645,7 +646,12 @@ static int set_conf(struct userdata *u) {
/* setup SBC encoder now we agree on parameters */
if (u->profile == PROFILE_A2DP) {
setup_sbc(&u->a2dp);
- u->block_size = u->a2dp.codesize;
+
+ u->block_size =
+ ((u->link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload))
+ / u->a2dp.frame_length
+ * u->a2dp.codesize);
+
pa_log_info("SBC parameters:\n\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n",
u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool);
} else
@@ -853,48 +859,62 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
static int hsp_process_render(struct userdata *u) {
int ret = 0;
- pa_memchunk memchunk;
pa_assert(u);
pa_assert(u->profile == PROFILE_HSP);
pa_assert(u->sink);
- pa_sink_render_full(u->sink, u->block_size, &memchunk);
+ /* First, render some data */
+ if (!u->write_memchunk.memblock)
+ pa_sink_render_full(u->sink, u->block_size, &u->write_memchunk);
+
+ pa_assert(u->write_memchunk.length == u->block_size);
for (;;) {
ssize_t l;
const void *p;
- p = (const uint8_t*) pa_memblock_acquire(memchunk.memblock) + memchunk.index;
- l = pa_write(u->stream_fd, p, memchunk.length, &u->stream_write_type);
- pa_memblock_release(memchunk.memblock);
+ /* Now write that data to the socket. The socket is of type
+ * SEQPACKET, and we generated the data of the MTU size, so this
+ * should just work. */
- pa_log_debug("Memblock written to socket: %lli bytes", (long long) l);
+ p = (const uint8_t*) pa_memblock_acquire(u->write_memchunk.memblock) + u->write_memchunk.index;
+ l = pa_write(u->stream_fd, p, u->write_memchunk.length, &u->stream_write_type);
+ pa_memblock_release(u->write_memchunk.memblock);
pa_assert(l != 0);
if (l < 0) {
- if (errno == EINTR || errno == EAGAIN) /*** FIXME: EAGAIN handling borked ***/
+
+ if (errno == EINTR)
+ /* Retry right away if we got interrupted */
continue;
- else {
- pa_log_error("Failed to write data to SCO socket: %s", pa_cstrerror(errno));
- ret = -1;
+
+ else if (errno == EAGAIN)
+ /* Hmm, apparently the socket was not writable, give up for now */
break;
- }
- } else {
- pa_assert((size_t) l <= memchunk.length);
- memchunk.index += (size_t) l;
- memchunk.length -= (size_t) l;
+ pa_log_error("Failed to write data to SCO socket: %s", pa_cstrerror(errno));
+ ret = -1;
+ break;
+ }
- u->write_index += (uint64_t) l;
+ pa_assert((size_t) l <= u->write_memchunk.length);
- if (memchunk.length <= 0)
- break;
+ if ((size_t) l != u->write_memchunk.length) {
+ pa_log_error("Wrote memory block to socket only partially! %llu written, wanted to write %llu.",
+ (unsigned long long) l,
+ (unsigned long long) u->write_memchunk.length);
+ ret = -1;
+ break;
}
- }
- pa_memblock_unref(memchunk.memblock);
+ u->write_index += (uint64_t) u->write_memchunk.length;
+ pa_memblock_unref(u->write_memchunk.memblock);
+ pa_memchunk_reset(&u->write_memchunk);
+
+ break;
+ }
return ret;
}
@@ -919,20 +939,27 @@ static int hsp_process_push(struct userdata *u) {
pa_memblock_release(memchunk.memblock);
if (l <= 0) {
- if (l < 0 && (errno == EINTR || errno == EAGAIN)) /*** FIXME: EAGAIN handling borked ***/
+
+ if (l < 0 && errno == EINTR)
+ /* Retry right away if we got interrupted */
continue;
- else {
- pa_log_error("Failed to read data from SCO socket: %s", l < 0 ? pa_cstrerror(errno) : "EOF");
- ret = -1;
+
+ else if (l < 0 && errno == EAGAIN)
+ /* Hmm, apparently the socket was not readable, give up for now. */
break;
- }
- } else {
- memchunk.length = (size_t) l;
- u->read_index += (uint64_t) l;
- pa_source_post(u->source, &memchunk);
+ pa_log_error("Failed to read data from SCO socket: %s", l < 0 ? pa_cstrerror(errno) : "EOF");
+ ret = -1;
break;
}
+
+ pa_assert((size_t) l <= memchunk.length);
+
+ memchunk.length = (size_t) l;
+ u->read_index += (uint64_t) l;
+
+ pa_source_post(u->source, &memchunk);
+ break;
}
pa_memblock_unref(memchunk.memblock);
@@ -940,127 +967,146 @@ static int hsp_process_push(struct userdata *u) {
return ret;
}
+static void a2dp_prepare_buffer(struct userdata *u) {
+ pa_assert(u);
+
+ if (u->a2dp.buffer_size >= u->link_mtu)
+ return;
+
+ u->a2dp.buffer_size = 2 * u->link_mtu;
+ pa_xfree(u->a2dp.buffer);
+ u->a2dp.buffer = pa_xmalloc(u->a2dp.buffer_size);
+}
+
static int a2dp_process_render(struct userdata *u) {
- size_t frame_size;
struct a2dp_info *a2dp;
struct rtp_header *header;
struct rtp_payload *payload;
- size_t left;
+ size_t nbytes;
void *d;
const void *p;
+ size_t to_write, to_encode;
unsigned frame_count;
- size_t written;
- uint64_t writing_at;
+ int ret = 0;
pa_assert(u);
pa_assert(u->profile == PROFILE_A2DP);
pa_assert(u->sink);
- a2dp = &u->a2dp;
+ /* First, render some data */
+ if (!u->write_memchunk.memblock)
+ pa_sink_render_full(u->sink, u->block_size, &u->write_memchunk);
- if (a2dp->buffer_size < u->link_mtu) {
- a2dp->buffer_size = 2*u->link_mtu;
- pa_xfree(a2dp->buffer);
- a2dp->buffer = pa_xmalloc(a2dp->buffer_size);
- }
+ pa_assert(u->write_memchunk.length == u->block_size);
+
+ a2dp_prepare_buffer(u);
- header = (struct rtp_header*) a2dp->buffer;
+ a2dp = &u->a2dp;
+ header = a2dp->buffer;
payload = (struct rtp_payload*) ((uint8_t*) a2dp->buffer + sizeof(*header));
- d = (uint8_t*) a2dp->buffer + sizeof(*header) + sizeof(*payload);
- left = a2dp->buffer_size - sizeof(*header) - sizeof(*payload);
- frame_size = sbc_get_frame_length(&a2dp->sbc);
frame_count = 0;
- writing_at = u->write_index;
+ /* Try to create a packet of the full MTU */
- do {
- ssize_t encoded;
+ p = (const uint8_t*) pa_memblock_acquire(u->write_memchunk.memblock) + u->write_memchunk.index;
+ to_encode = u->write_memchunk.length;
- if (!u->write_memchunk.memblock)
- pa_sink_render_full(u->sink, u->block_size, &u->write_memchunk);
+ d = (uint8_t*) a2dp->buffer + sizeof(*header) + sizeof(*payload);
+ to_write = a2dp->buffer_size - sizeof(*header) - sizeof(*payload);
+
+ while (PA_LIKELY(to_encode > 0 && to_write > 0)) {
+ size_t written;
+ ssize_t encoded;
- p = (const uint8_t*) pa_memblock_acquire(u->write_memchunk.memblock) + u->write_memchunk.index;
encoded = sbc_encode(&a2dp->sbc,
- p, u->write_memchunk.length,
- d, left,
+ p, to_encode,
+ d, to_write,
&written);
- PA_ONCE_BEGIN {
- pa_log_debug("Using SBC encoder implementation: %s", pa_strnull(sbc_get_implementation_info(&a2dp->sbc)));
- } PA_ONCE_END;
-
- pa_memblock_release(u->write_memchunk.memblock);
-
- if (encoded <= 0) {
- pa_log_error("SBC encoding error (%d)", encoded);
+ if (PA_UNLIKELY(encoded <= 0)) {
+ pa_log_error("SBC encoding error (%li)", (long) encoded);
+ pa_memblock_release(u->write_memchunk.memblock);
return -1;
}
- pa_assert((size_t) encoded <= u->write_memchunk.length);
- pa_assert((size_t) encoded == sbc_get_codesize(&a2dp->sbc));
+/* pa_log_debug("SBC: encoded: %lu; written: %lu", (unsigned long) encoded, (unsigned long) written); */
+/* pa_log_debug("SBC: codesize: %lu; frame_length: %lu", (unsigned long) a2dp->codesize, (unsigned long) a2dp->frame_length); */
- pa_assert((size_t) written <= left);
- pa_assert((size_t) written == sbc_get_frame_length(&a2dp->sbc));
+ pa_assert_fp((size_t) encoded <= to_encode);
+ pa_assert_fp((size_t) encoded == a2dp->codesize);
-/* pa_log_debug("SBC: encoded: %d; written: %d", encoded, written); */
+ pa_assert_fp((size_t) written <= to_write);
+ pa_assert_fp((size_t) written == a2dp->frame_length);
- u->write_memchunk.index += encoded;
- u->write_memchunk.length -= encoded;
-
- if (u->write_memchunk.length <= 0) {
- pa_memblock_unref(u->write_memchunk.memblock);
- pa_memchunk_reset(&u->write_memchunk);
- }
-
- u->write_index += encoded;
+ p = (const uint8_t*) p + encoded;
+ to_encode -= encoded;
d = (uint8_t*) d + written;
- left -= written;
+ to_write -= written;
frame_count++;
+ }
+
+ pa_memblock_release(u->write_memchunk.memblock);
+
+ pa_assert(to_encode == 0);
- } while (((uint8_t*) d - ((uint8_t*) a2dp->buffer + sbc_get_frame_length(&a2dp->sbc))) < (ptrdiff_t) u->link_mtu);
+ PA_ONCE_BEGIN {
+ pa_log_debug("Using SBC encoder implementation: %s", pa_strnull(sbc_get_implementation_info(&a2dp->sbc)));
+ } PA_ONCE_END;
/* write it to the fifo */
memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
- payload->frame_count = frame_count;
header->v = 2;
header->pt = 1;
header->sequence_number = htons(a2dp->seq_num++);
- header->timestamp = htonl(writing_at / frame_size);
+ header->timestamp = htonl(u->write_index / pa_frame_size(&u->sink->sample_spec));
header->ssrc = htonl(1);
+ payload->frame_count = frame_count;
- p = a2dp->buffer;
- left = (uint8_t*) d - (uint8_t*) a2dp->buffer;
+ nbytes = (uint8_t*) d - (uint8_t*) a2dp->buffer;
for (;;) {
ssize_t l;
- l = pa_write(u->stream_fd, p, left, &u->stream_write_type);
-/* pa_log_debug("write: requested %lu bytes; written %li bytes; mtu=%li", (unsigned long) left, (long) l, (unsigned long) u->link_mtu); */
+ l = pa_write(u->stream_fd, a2dp->buffer, nbytes, &u->stream_write_type);
pa_assert(l != 0);
if (l < 0) {
- if (errno == EINTR || errno == EAGAIN) /*** FIXME: EAGAIN handling borked ***/
- continue;
- else {
- pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
- return -1;
- }
- } else {
- pa_assert((size_t) l <= left);
- d = (uint8_t*) d + l;
- left -= l;
+ if (errno == EINTR)
+ /* Retry right away if we got interrupted */
+ continue;
- if (left <= 0)
+ else if (errno == EAGAIN)
+ /* Hmm, apparently the socket was not writable, give up for now */
break;
+
+ pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
+ ret = -1;
+ break;
+ }
+
+ pa_assert((size_t) l <= nbytes);
+
+ if ((size_t) l != nbytes) {
+ pa_log_warn("Wrote memory block to socket only partially! %llu written, wanted to write %llu.",
+ (unsigned long long) l,
+ (unsigned long long) nbytes);
+ ret = -1;
+ break;
}
+
+ u->write_index += (uint64_t) u->write_memchunk.length;
+ pa_memblock_unref(u->write_memchunk.memblock);
+ pa_memchunk_reset(&u->write_memchunk);
+
+ break;
}
- return 0;
+ return ret;
}
static void thread_func(void *userdata) {
@@ -1509,12 +1555,20 @@ static void shutdown_bt(struct userdata *u) {
if (u->stream_fd >= 0) {
pa_close(u->stream_fd);
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;
}
+
+ if (u->write_memchunk.memblock) {
+ pa_memblock_unref(u->write_memchunk.memblock);
+ pa_memchunk_reset(&u->write_memchunk);
+ }
}
static int init_bt(struct userdata *u) {
@@ -1686,11 +1740,6 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
stop_thread(u);
shutdown_bt(u);
- if (u->write_memchunk.memblock) {
- pa_memblock_unref(u->write_memchunk.memblock);
- pa_memchunk_reset(&u->write_memchunk);
- }
-
u->profile = *d;
u->sample_spec = u->requested_sample_spec;
@@ -2034,9 +2083,6 @@ void pa__done(pa_module *m) {
if (u->device)
pa_bluetooth_device_free(u->device);
- if (u->write_memchunk.memblock)
- pa_memblock_unref(u->write_memchunk.memblock);
-
if (u->a2dp.buffer)
pa_xfree(u->a2dp.buffer);
commit 77a1db16b996e079cd565f7d0baf9fe81ca88ccd
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 18:34:16 2009 +0100
fix a misplaced assert
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index fc8dc9c..7386f8c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -953,7 +953,7 @@ static int hsp_process_push(struct userdata *u) {
break;
}
- pa_assert((size_t) l <= memchunk.length);
+ pa_assert((size_t) l <= pa_memblock_get_length(memchunk.memblock));
memchunk.length = (size_t) l;
u->read_index += (uint64_t) l;
commit f5c8990d1868f30ed3c13945f7bedb83e2093c11
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 20 19:30:37 2009 +0100
make sure we dispatch messages in order
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index ccc8bee..369b08a 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -114,18 +114,18 @@ void pa_bluetooth_device_free(pa_bluetooth_device *d) {
static pa_bool_t device_is_loaded(pa_bluetooth_device *d) {
pa_assert(d);
- /* FIXME: e83621724d7939b97b4f01f0d7e965d61ef8e55e, f1daa282f030e4e2381341e0f65faca47c4b891b is borked, probably needs to be reversed */
-
- return d->device_info_valid && (d->audio_sink_info_valid || d->headset_info_valid);
+ return
+ d->device_info_valid &&
+ d->audio_sink_info_valid &&
+ d->headset_info_valid;
}
static pa_bool_t device_is_audio(pa_bluetooth_device *d) {
pa_assert(d);
pa_assert(d->device_info_valid);
- pa_assert(d->audio_sink_info_valid || d->headset_info_valid);
-
- /* FIXME: e83621724d7939b97b4f01f0d7e965d61ef8e55e, f1daa282f030e4e2381341e0f65faca47c4b891b is borked, probably needs to be reversed */
+ pa_assert(d->audio_sink_info_valid);
+ pa_assert(d->headset_info_valid);
return d->device_info_valid > 0 &&
(d->audio_sink_info_valid > 0 || d->headset_info_valid > 0);
@@ -303,7 +303,6 @@ static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_b
return;
y->callback(y->userdata, d, good);
-
}
static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
@@ -395,7 +394,7 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bl
pa_assert_se(dbus_connection_send_with_reply(y->connection, m, &call, -1));
- p = pa_dbus_pending_new(m, call, y, d);
+ p = pa_dbus_pending_new(y->connection, m, call, y, d);
PA_LLIST_PREPEND(pa_dbus_pending, y->pending, p);
dbus_pending_call_set_notify(call, func, p, NULL);
@@ -656,12 +655,10 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
} else if (dbus_message_has_interface(m, "org.bluez.Headset")) {
if (parse_audio_property(y, &d->headset_connected, &arg_i) < 0)
goto fail;
- d->headset_info_valid = 1;
} else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) {
if (parse_audio_property(y, &d->audio_sink_connected, &arg_i) < 0)
goto fail;
- d->audio_sink_info_valid = 1;
}
pa_assert_se(y->mode == MODE_DISCOVER);
diff --git a/src/modules/dbus-util.c b/src/modules/dbus-util.c
index d51befb..e2d4580 100644
--- a/src/modules/dbus-util.c
+++ b/src/modules/dbus-util.c
@@ -383,12 +383,19 @@ void pa_dbus_remove_matches(DBusConnection *c, ...) {
va_end(ap);
}
-pa_dbus_pending *pa_dbus_pending_new(DBusMessage *m, DBusPendingCall *pending, void *context_data, void *call_data) {
+pa_dbus_pending *pa_dbus_pending_new(
+ DBusConnection *c,
+ DBusMessage *m,
+ DBusPendingCall *pending,
+ void *context_data,
+ void *call_data) {
+
pa_dbus_pending *p;
pa_assert(pending);
p = pa_xnew(pa_dbus_pending, 1);
+ p->connection = c;
p->message = m;
p->pending = pending;
p->context_data = context_data;
@@ -402,9 +409,8 @@ pa_dbus_pending *pa_dbus_pending_new(DBusMessage *m, DBusPendingCall *pending, v
void pa_dbus_pending_free(pa_dbus_pending *p) {
pa_assert(p);
- if (p->pending) {
+ if (p->pending)
dbus_pending_call_cancel(p->pending); /* p->pending is freed by cancel() */
- }
if (p->message)
dbus_message_unref(p->message);
@@ -415,8 +421,8 @@ void pa_dbus_pending_free(pa_dbus_pending *p) {
void pa_dbus_sync_pending_list(pa_dbus_pending **p) {
pa_assert(p);
- while (*p)
- dbus_pending_call_block((*p)->pending);
+ while (*p && dbus_connection_read_write_dispatch((*p)->connection, -1))
+ ;
}
void pa_dbus_free_pending_list(pa_dbus_pending **p) {
diff --git a/src/modules/dbus-util.h b/src/modules/dbus-util.h
index 90abbc7..554f41a 100644
--- a/src/modules/dbus-util.h
+++ b/src/modules/dbus-util.h
@@ -46,6 +46,7 @@ typedef struct pa_dbus_pending pa_dbus_pending;
struct userdata; /* We leave the actual definition to the caller */
struct pa_dbus_pending {
+ DBusConnection *connection;
DBusMessage *message;
DBusPendingCall *pending;
@@ -55,7 +56,7 @@ struct pa_dbus_pending {
PA_LLIST_FIELDS(pa_dbus_pending);
};
-pa_dbus_pending *pa_dbus_pending_new(DBusMessage *m, DBusPendingCall *pending, void *context_data, void *call_data);
+pa_dbus_pending *pa_dbus_pending_new(DBusConnection *c, DBusMessage *m, DBusPendingCall *pending, void *context_data, void *call_data);
void pa_dbus_pending_free(pa_dbus_pending *p);
/* Sync up a list of pa_dbus_pending_call objects */
commit 20488fbe3ed068d095d637763555e37af8d16322
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Mar 21 01:18:48 2009 +0100
add pa_hook_is_firing
diff --git a/src/pulsecore/hook-list.c b/src/pulsecore/hook-list.c
index 5f7a866..a00116d 100644
--- a/src/pulsecore/hook-list.c
+++ b/src/pulsecore/hook-list.c
@@ -121,3 +121,9 @@ pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
return result;
}
+
+pa_bool_t pa_hook_is_firing(pa_hook *hook) {
+ pa_assert(hook);
+
+ return hook->n_firing > 0;
+}
diff --git a/src/pulsecore/hook-list.h b/src/pulsecore/hook-list.h
index 8514cce..86ce9d2 100644
--- a/src/pulsecore/hook-list.h
+++ b/src/pulsecore/hook-list.h
@@ -71,4 +71,6 @@ void pa_hook_slot_free(pa_hook_slot *slot);
pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data);
+pa_bool_t pa_hook_is_firing(pa_hook *hook);
+
#endif
commit 3aa39726dbe824a9f6e85dd429e64271db8b2849
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Mar 21 01:19:49 2009 +0100
rework device discovery to share a single device list among all modules
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 369b08a..3dfc65e 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -24,31 +24,19 @@
#endif
#include <pulsecore/core-util.h>
+#include <pulsecore/shared.h>
#include <modules/dbus-util.h>
#include "bluetooth-util.h"
-enum mode {
- MODE_FIND,
- MODE_GET,
- MODE_DISCOVER
-};
-
struct pa_bluetooth_discovery {
- DBusConnection *connection;
- PA_LLIST_HEAD(pa_dbus_pending, pending);
+ PA_REFCNT_DECLARE;
- enum mode mode;
-
- /* If mode == MODE_FIND look for a specific device by its address.
- If mode == MODE_GET look for a specific device by its path. */
- const char *looking_for;
- pa_bluetooth_device *found_device;
-
- /* If looking_for is NULL we do long-time discovery */
+ pa_core *core;
+ pa_dbus_connection *connection;
+ PA_LLIST_HEAD(pa_dbus_pending, pending);
pa_hashmap *devices;
- pa_bluetooth_device_callback_t callback;
- struct userdata *userdata;
+ pa_hook hook;
};
static pa_bluetooth_uuid *uuid_new(const char *uuid) {
@@ -73,9 +61,9 @@ static pa_bluetooth_device* device_new(const char *path) {
d = pa_xnew(pa_bluetooth_device, 1);
- d->device_info_valid = d->audio_sink_info_valid = d->headset_info_valid = 0;
+ d->dead = FALSE;
- d->data = NULL;
+ d->device_info_valid = d->audio_sink_info_valid = d->headset_info_valid = 0;
d->name = NULL;
d->path = pa_xstrdup(path);
@@ -94,7 +82,7 @@ static pa_bluetooth_device* device_new(const char *path) {
return d;
}
-void pa_bluetooth_device_free(pa_bluetooth_device *d) {
+static void device_free(pa_bluetooth_device *d) {
pa_bluetooth_uuid *u;
pa_assert(d);
@@ -127,7 +115,8 @@ static pa_bool_t device_is_audio(pa_bluetooth_device *d) {
pa_assert(d->audio_sink_info_valid);
pa_assert(d->headset_info_valid);
- return d->device_info_valid > 0 &&
+ return
+ d->device_info_valid > 0 &&
(d->audio_sink_info_valid > 0 || d->headset_info_valid > 0);
}
@@ -289,20 +278,18 @@ static int parse_audio_property(pa_bluetooth_discovery *u, int *connected, DBusM
return 0;
}
-static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_bool_t good) {
+static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_bool_t dead) {
pa_assert(y);
pa_assert(d);
- if (y->mode != MODE_DISCOVER)
- return;
-
if (!device_is_loaded(d))
return;
if (!device_is_audio(d))
return;
- y->callback(y->userdata, d, good);
+ d->dead = dead;
+ pa_hook_fire(&y->hook, d);
}
static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
@@ -377,7 +364,7 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
}
finish:
- run_callback(y, d, TRUE);
+ run_callback(y, d, FALSE);
dbus_message_unref(r);
@@ -392,9 +379,9 @@ static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bl
pa_assert(y);
pa_assert(m);
- pa_assert_se(dbus_connection_send_with_reply(y->connection, m, &call, -1));
+ pa_assert_se(dbus_connection_send_with_reply(pa_dbus_connection_get(y->connection), m, &call, -1));
- p = pa_dbus_pending_new(y->connection, m, call, y, d);
+ p = pa_dbus_pending_new(pa_dbus_connection_get(y->connection), m, call, y, d);
PA_LLIST_PREPEND(pa_dbus_pending, y->pending, p);
dbus_pending_call_set_notify(call, func, p, NULL);
@@ -410,13 +397,7 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
d = device_new(path);
- if (y->mode == MODE_DISCOVER) {
- pa_assert(y->devices);
- pa_hashmap_put(y->devices, d->path, d);
- } else {
- pa_assert(!y->found_device);
- y->found_device = d;
- }
+ pa_hashmap_put(y->devices, d->path, d);
pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
@@ -469,57 +450,11 @@ end:
pa_dbus_pending_free(p);
}
-static void find_device_reply(DBusPendingCall *pending, void *userdata) {
- DBusError e;
- DBusMessage *r;
- char *path = NULL;
- pa_dbus_pending *p;
- pa_bluetooth_discovery *y;
-
- pa_assert(pending);
-
- dbus_error_init(&e);
-
- pa_assert_se(p = userdata);
- pa_assert_se(y = p->context_data);
- pa_assert_se(r = dbus_pending_call_steal_reply(pending));
-
- if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
- pa_log("Error from FindDevice reply: %s", dbus_message_get_error_name(r));
- goto end;
- }
-
- if (!dbus_message_get_args(r, &e, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) {
- pa_log("org.bluez.Adapter.FindDevice returned an error: '%s'\n", e.message);
- dbus_error_free(&e);
- } else
- found_device(y, path);
-
-end:
- dbus_message_unref(r);
-
- PA_LLIST_REMOVE(pa_dbus_pending, y->pending, p);
- pa_dbus_pending_free(p);
-}
-
static void found_adapter(pa_bluetooth_discovery *y, const char *path) {
DBusMessage *m;
- if (y->mode == MODE_FIND) {
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Adapter", "FindDevice"));
-
- pa_assert_se(dbus_message_append_args(m,
- DBUS_TYPE_STRING, &y->looking_for,
- DBUS_TYPE_INVALID));
-
- send_and_add_to_pending(y, NULL, m, find_device_reply);
-
- } else {
- pa_assert(y->mode == MODE_DISCOVER);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Adapter", "ListDevices"));
- send_and_add_to_pending(y, NULL, m, list_devices_reply);
- }
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Adapter", "ListDevices"));
+ send_and_add_to_pending(y, NULL, m, list_devices_reply);
}
static void list_adapters_reply(DBusPendingCall *pending, void *userdata) {
@@ -599,11 +534,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
pa_log_debug("Device %s removed", path);
if ((d = pa_hashmap_remove(y->devices, path))) {
-
- pa_assert_se(y->mode == MODE_DISCOVER);
- run_callback(y, d, FALSE);
-
- pa_bluetooth_device_free(d);
+ run_callback(y, d, TRUE);
+ device_free(d);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -661,8 +593,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
goto fail;
}
- pa_assert_se(y->mode == MODE_DISCOVER);
- run_callback(y, d, TRUE);
+ run_callback(y, d, FALSE);
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -674,82 +605,81 @@ fail:
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-pa_bluetooth_device* pa_bluetooth_find_device(DBusConnection *c, const char* address) {
- pa_bluetooth_discovery y;
-
- memset(&y, 0, sizeof(y));
- y.mode = MODE_FIND;
- y.looking_for = address;
- y.connection = c;
- PA_LLIST_HEAD_INIT(pa_dbus_pending, y.pending);
-
- list_adapters(&y);
+const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_discovery *y, const char* address) {
+ pa_bluetooth_device *d;
+ void *state = NULL;
- pa_dbus_sync_pending_list(&y.pending);
- pa_assert(!y.pending);
+ pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
+ pa_assert(address);
- if (y.found_device) {
- pa_assert(device_is_loaded(y.found_device));
+ if (!pa_hook_is_firing(&y->hook))
+ pa_bluetooth_discovery_sync(y);
- if (!device_is_audio(y.found_device)) {
- pa_bluetooth_device_free(y.found_device);
- return NULL;
- }
- }
+ while ((d = pa_hashmap_iterate(y->devices, &state, NULL)))
+ if (pa_streq(d->address, address))
+ return d;
- return y.found_device;
+ return NULL;
}
-pa_bluetooth_device* pa_bluetooth_get_device(DBusConnection *c, const char* path) {
- pa_bluetooth_discovery y;
+const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_discovery *y, const char* path) {
+ pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
+ pa_assert(path);
- memset(&y, 0, sizeof(y));
- y.mode = MODE_GET;
- y.connection = c;
- PA_LLIST_HEAD_INIT(pa_dbus_pending, y.pending);
+ if (!pa_hook_is_firing(&y->hook))
+ pa_bluetooth_discovery_sync(y);
- found_device(&y, path);
+ return pa_hashmap_get(y->devices, path);
+}
- pa_dbus_sync_pending_list(&y.pending);
- pa_assert(!y.pending);
+static int setup_dbus(pa_bluetooth_discovery *y) {
+ DBusError err;
- if (y.found_device) {
- pa_assert(device_is_loaded(y.found_device));
+ dbus_error_init(&err);
- if (!device_is_audio(y.found_device)) {
- pa_bluetooth_device_free(y.found_device);
- return NULL;
- }
+ y->connection = pa_dbus_bus_get(y->core, DBUS_BUS_SYSTEM, &err);
+
+ if (dbus_error_is_set(&err) || !y->connection) {
+ pa_log("Failed to get D-Bus connection: %s", err.message);
+ dbus_error_free(&err);
+ return -1;
}
- return y.found_device;
+ return 0;
}
-pa_bluetooth_discovery* pa_bluetooth_discovery_new(DBusConnection *c, pa_bluetooth_device_callback_t cb, struct userdata *u) {
+pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
DBusError err;
pa_bluetooth_discovery *y;
pa_assert(c);
- pa_assert(cb);
dbus_error_init(&err);
+ if ((y = pa_shared_get(c, "bluetooth-discovery")))
+ return pa_bluetooth_discovery_ref(y);
+
y = pa_xnew0(pa_bluetooth_discovery, 1);
- y->mode = MODE_DISCOVER;
- y->connection = c;
- y->callback = cb;
- y->userdata = u;
+ PA_REFCNT_INIT(y);
+ y->core = c;
y->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
PA_LLIST_HEAD_INIT(pa_dbus_pending, y->pending);
+ pa_hook_init(&y->hook, y);
+ pa_shared_set(c, "bluetooth-discovery", y);
+
+ if (setup_dbus(y) < 0)
+ goto fail;
/* dynamic detection of bluetooth audio devices */
- if (!dbus_connection_add_filter(c, filter_cb, y, NULL)) {
+ if (!dbus_connection_add_filter(pa_dbus_connection_get(y->connection), filter_cb, y, NULL)) {
pa_log_error("Failed to add filter function");
goto fail;
}
if (pa_dbus_add_matches(
- c, &err,
+ pa_dbus_connection_get(y->connection), &err,
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
@@ -765,28 +695,46 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_new(DBusConnection *c, pa_bluetoo
return y;
fail:
+
+ if (y)
+ pa_bluetooth_discovery_unref(y);
+
dbus_error_free(&err);
+
return NULL;
}
-void pa_bluetooth_discovery_free(pa_bluetooth_discovery *y) {
+pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y) {
+ pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
+
+ PA_REFCNT_INC(y);
+
+ return y;
+}
+
+void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
pa_bluetooth_device *d;
pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
+
+ if (PA_REFCNT_DEC(y) > 0)
+ return;
pa_dbus_free_pending_list(&y->pending);
if (y->devices) {
while ((d = pa_hashmap_steal_first(y->devices))) {
- run_callback(y, d, FALSE);
- pa_bluetooth_device_free(d);
+ run_callback(y, d, TRUE);
+ device_free(d);
}
pa_hashmap_free(y->devices, NULL, NULL);
}
if (y->connection) {
- pa_dbus_remove_matches(y->connection,
+ pa_dbus_remove_matches(pa_dbus_connection_get(y->connection),
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterAdded'",
"type='signal',sender='org.bluez',interface='org.bluez.Manager',member='AdapterRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
@@ -795,16 +743,31 @@ void pa_bluetooth_discovery_free(pa_bluetooth_discovery *y) {
"type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", NULL);
- dbus_connection_remove_filter(y->connection, filter_cb, y);
+ dbus_connection_remove_filter(pa_dbus_connection_get(y->connection), filter_cb, y);
+
+ pa_dbus_connection_unref(y->connection);
}
+
+ pa_hook_done(&y->hook);
+
+ if (y->core)
+ pa_shared_remove(y->core, "bluetooth-discovery");
}
void pa_bluetooth_discovery_sync(pa_bluetooth_discovery *y) {
pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
pa_dbus_sync_pending_list(&y->pending);
}
+pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *y) {
+ pa_assert(y);
+ pa_assert(PA_REFCNT_VALUE(y) > 0);
+
+ return &y->hook;
+}
+
const char*pa_bluetooth_get_form_factor(uint32_t class) {
unsigned i;
const char *r;
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 0364c97..1d05e63 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -40,7 +40,7 @@ struct pa_bluetooth_uuid {
};
struct pa_bluetooth_device {
- void *data; /* arbitrary information for the one owning the discovery object */
+ pa_bool_t dead;
int device_info_valid; /* 0: no results yet; 1: good results; -1: bad results ... */
int audio_sink_info_valid; /* ... same here ... */
@@ -64,17 +64,18 @@ struct pa_bluetooth_device {
int headset_connected;
};
-void pa_bluetooth_device_free(pa_bluetooth_device *d);
+pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core);
+pa_bluetooth_discovery* pa_bluetooth_discovery_ref(pa_bluetooth_discovery *y);
+void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *d);
-pa_bluetooth_device* pa_bluetooth_get_device(DBusConnection *c, const char* path);
-pa_bluetooth_device* pa_bluetooth_find_device(DBusConnection *c, const char* address);
-
-typedef void (*pa_bluetooth_device_callback_t)(struct userdata *u, pa_bluetooth_device *d, pa_bool_t good);
-pa_bluetooth_discovery* pa_bluetooth_discovery_new(DBusConnection *c, pa_bluetooth_device_callback_t cb, struct userdata *u);
-void pa_bluetooth_discovery_free(pa_bluetooth_discovery *d);
void pa_bluetooth_discovery_sync(pa_bluetooth_discovery *d);
-const char*pa_bluetooth_get_form_factor(uint32_t class);
+const pa_bluetooth_device* pa_bluetooth_discovery_get_by_path(pa_bluetooth_discovery *d, const char* path);
+const pa_bluetooth_device* pa_bluetooth_discovery_get_by_address(pa_bluetooth_discovery *d, const char* address);
+
+pa_hook* pa_bluetooth_discovery_hook(pa_bluetooth_discovery *d);
+
+const char* pa_bluetooth_get_form_factor(uint32_t class);
char *pa_bluetooth_cleanup_name(const char *name);
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 7386f8c..928f33c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -122,6 +122,8 @@ struct userdata {
pa_core *core;
pa_module *module;
+ char *address;
+
pa_card *card;
pa_sink *sink;
pa_source *source;
@@ -153,8 +155,6 @@ struct userdata {
pa_modargs *modargs;
- pa_bluetooth_device *device;
-
int stream_write_type, stream_read_type;
int service_write_type, service_read_type;
};
@@ -331,7 +331,7 @@ static int get_caps(struct userdata *u) {
msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
- pa_strlcpy(msg.getcaps_req.device, u->device->address, sizeof(msg.getcaps_req.device));
+ pa_strlcpy(msg.getcaps_req.device, u->address, sizeof(msg.getcaps_req.device));
if (u->profile == PROFILE_A2DP)
msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
else {
@@ -613,7 +613,7 @@ static int set_conf(struct userdata *u) {
msg.setconf_req.h.name = BT_SET_CONFIGURATION;
msg.setconf_req.h.length = sizeof(msg.setconf_req);
- pa_strlcpy(msg.setconf_req.device, u->device->address, sizeof(msg.setconf_req.device));
+ pa_strlcpy(msg.setconf_req.device, u->address, sizeof(msg.setconf_req.device));
msg.setconf_req.access_mode = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_ACCESS_MODE_WRITE : BT_CAPABILITIES_ACCESS_MODE_READWRITE;
msg.setconf_req.codec.transport = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_TRANSPORT_A2DP : BT_CAPABILITIES_TRANSPORT_SCO;
@@ -1482,7 +1482,7 @@ static int add_sink(struct userdata *u) {
pa_sink_new_data_set_sample_spec(&data, &u->sample_spec);
pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
data.card = u->card;
- data.name = get_name("sink", u->modargs, u->device->address, &b);
+ data.name = get_name("sink", u->modargs, u->address, &b);
data.namereg_fail = b;
u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
@@ -1526,7 +1526,7 @@ static int add_source(struct userdata *u) {
pa_source_new_data_set_sample_spec(&data, &u->sample_spec);
pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile == PROFILE_A2DP ? "a2dp" : "sco");
data.card = u->card;
- data.name = get_name("source", u->modargs, u->device->address, &b);
+ data.name = get_name("source", u->modargs, u->address, &b);
data.namereg_fail = b;
u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
@@ -1768,7 +1768,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
return 0;
}
-static int add_card(struct userdata *u, const char * default_profile) {
+static int add_card(struct userdata *u, const char *default_profile, const pa_bluetooth_device *device) {
pa_card_new_data data;
pa_bool_t b;
pa_card_profile *p;
@@ -1780,24 +1780,24 @@ static int add_card(struct userdata *u, const char * default_profile) {
data.driver = __FILE__;
data.module = u->module;
- n = pa_bluetooth_cleanup_name(u->device->name);
+ n = pa_bluetooth_cleanup_name(device->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, n);
pa_xfree(n);
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device->address);
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, device->address);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "bluez");
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_BUS, "bluetooth");
- if ((ff = pa_bluetooth_get_form_factor(u->device->class)))
+ if ((ff = pa_bluetooth_get_form_factor(device->class)))
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, ff);
- pa_proplist_sets(data.proplist, "bluez.path", u->device->path);
- pa_proplist_setf(data.proplist, "bluez.class", "0x%06x", (unsigned) u->device->class);
- pa_proplist_sets(data.proplist, "bluez.name", u->device->name);
- data.name = get_name("card", u->modargs, u->device->address, &b);
+ pa_proplist_sets(data.proplist, "bluez.path", device->path);
+ pa_proplist_setf(data.proplist, "bluez.class", "0x%06x", (unsigned) device->class);
+ pa_proplist_sets(data.proplist, "bluez.name", device->name);
+ data.name = get_name("card", u->modargs, device->address, &b);
data.namereg_fail = b;
data.profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (u->device->audio_sink_info_valid > 0) {
+ if (device->audio_sink_info_valid > 0) {
p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile));
p->priority = 10;
p->n_sinks = 1;
@@ -1811,7 +1811,7 @@ static int add_card(struct userdata *u, const char * default_profile) {
pa_hashmap_put(data.profiles, p->name, p);
}
- if (u->device->headset_info_valid > 0) {
+ if (device->headset_info_valid > 0) {
p = pa_card_profile_new("hsp", _("Telephony Duplex (HSP/HFP)"), sizeof(enum profile));
p->priority = 20;
p->n_sinks = 1;
@@ -1856,47 +1856,39 @@ static int add_card(struct userdata *u, const char * default_profile) {
return 0;
}
-static int setup_dbus(struct userdata *u) {
- DBusError error;
+static const pa_bluetooth_device* find_device(struct userdata *u, pa_bluetooth_discovery *y, const char *address, const char *path) {
+ const pa_bluetooth_device *d = NULL;
- dbus_error_init(&error);
-
- u->connection = pa_dbus_bus_get(u->core, DBUS_BUS_SYSTEM, &error);
- if (dbus_error_is_set(&error) || (!u->connection)) {
- pa_log("Failed to get D-Bus connection: %s", error.message);
- dbus_error_free(&error);
- return -1;
- }
-
- return 0;
-}
-
-static int find_device(struct userdata *u, const char *address, const char *path) {
pa_assert(u);
+ pa_assert(y);
if (!address && !path) {
pa_log_error("Failed to get device address/path from module arguments.");
- return -1;
+ return NULL;
}
if (path) {
- if (!(u->device = pa_bluetooth_get_device(pa_dbus_connection_get(u->connection), path))) {
+ if (!(d = pa_bluetooth_discovery_get_by_path(y, path))) {
pa_log_error("%s is not a valid BlueZ audio device.", path);
- return -1;
+ return NULL;
}
- if (address && !(pa_streq(u->device->address, address))) {
+ if (address && !(pa_streq(d->address, address))) {
pa_log_error("Passed path %s and address %s don't match.", path, address);
- return -1;
+ return NULL;
}
+
} else {
- if (!(u->device = pa_bluetooth_find_device(pa_dbus_connection_get(u->connection), address))) {
+ if (!(d = pa_bluetooth_discovery_get_by_address(y, address))) {
pa_log_error("%s is not known.", address);
- return -1;
+ return NULL;
}
}
- return 0;
+ if (d)
+ u->address = pa_xstrdup(d->address);
+
+ return d;
}
int pa__init(pa_module* m) {
@@ -1904,6 +1896,8 @@ int pa__init(pa_module* m) {
uint32_t channels;
struct userdata *u;
const char *address, *path;
+ const pa_bluetooth_device *d;
+ pa_bluetooth_discovery *y = NULL;
pa_assert(m);
@@ -1948,21 +1942,22 @@ int pa__init(pa_module* m) {
u->sample_spec.channels = (uint8_t) channels;
u->requested_sample_spec = u->sample_spec;
- if (setup_dbus(u) < 0)
- goto fail;
-
address = pa_modargs_get_value(ma, "address", NULL);
path = pa_modargs_get_value(ma, "path", NULL);
- if (find_device(u, address, path) < 0)
+ if (!(y = pa_bluetooth_discovery_get(m->core)))
goto fail;
- pa_assert(u->device);
+ if (!(d = find_device(u, y, address, path)))
+ goto fail;
/* Add the card structure. This will also initialize the default profile */
- if (add_card(u, pa_modargs_get_value(ma, "profile", NULL)) < 0)
+ if (add_card(u, pa_modargs_get_value(ma, "profile", NULL), d) < 0)
goto fail;
+ pa_bluetooth_discovery_unref(y);
+ y = NULL;
+
/* Connect to the BT service and query capabilities */
if (init_bt(u) < 0)
goto fail;
@@ -2014,7 +2009,12 @@ int pa__init(pa_module* m) {
return 0;
fail:
+
+ if (y)
+ pa_bluetooth_discovery_unref(y);
+
pa__done(m);
+
return -1;
}
@@ -2080,9 +2080,6 @@ void pa__done(pa_module *m) {
shutdown_bt(u);
- if (u->device)
- pa_bluetooth_device_free(u->device);
-
if (u->a2dp.buffer)
pa_xfree(u->a2dp.buffer);
@@ -2091,5 +2088,7 @@ void pa__done(pa_module *m) {
if (u->modargs)
pa_modargs_free(u->modargs);
+ pa_xfree(u->address);
+
pa_xfree(u);
}
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 4586d8c..22e8ea3 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -57,19 +57,28 @@ struct userdata {
pa_module *module;
pa_modargs *modargs;
pa_core *core;
- pa_dbus_connection *connection;
pa_bluetooth_discovery *discovery;
+ pa_hook_slot *slot;
+ pa_hashmap *hashmap;
};
-static void load_module_for_device(struct userdata *u, pa_bluetooth_device *d, pa_bool_t good) {
+static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
+ uint32_t midx;
+
pa_assert(u);
pa_assert(d);
- if (good &&
+
+ if (!(midx = PA_PTR_TO_UINT(pa_hashmap_get(u->hashmap, d->path))))
+ midx = PA_INVALID_INDEX;
+ else
+ midx--;
+
+ if (!d->dead &&
d->device_connected > 0 &&
(d->audio_sink_connected > 0 || d->headset_connected > 0)) {
- if (((uint32_t) PA_PTR_TO_UINT(d->data))-1 == PA_INVALID_INDEX) {
+ if (midx == PA_INVALID_INDEX) {
pa_module *m = NULL;
char *args;
@@ -93,38 +102,25 @@ static void load_module_for_device(struct userdata *u, pa_bluetooth_device *d, p
pa_xfree(args);
if (m)
- d->data = PA_UINT_TO_PTR((uint32_t) (m->index+1));
+ pa_hashmap_put(u->hashmap, d->path, PA_UINT_TO_PTR((uint32_t) (m->index+1)));
else
pa_log_debug("Failed to load module for device %s", d->path);
}
} else {
- if (((uint32_t) PA_PTR_TO_UINT(d->data))-1 != PA_INVALID_INDEX) {
+ if (midx != PA_INVALID_INDEX) {
/* Hmm, disconnection? Then let's unload our module */
pa_log_debug("Unloading module for %s", d->path);
- pa_module_unload_request_by_index(u->core, (uint32_t) (PA_PTR_TO_UINT(d->data))-1, TRUE);
- d->data = NULL;
- }
- }
-}
-
-static int setup_dbus(struct userdata *u) {
- DBusError err;
+ pa_module_unload_request_by_index(u->core, midx, TRUE);
- dbus_error_init(&err);
-
- u->connection = pa_dbus_bus_get(u->core, DBUS_BUS_SYSTEM, &err);
-
- if (dbus_error_is_set(&err) || !u->connection) {
- pa_log("Failed to get D-Bus connection: %s", err.message);
- dbus_error_free(&err);
- return -1;
+ pa_hashmap_remove(u->hashmap, d->path);
+ }
}
- return 0;
+ return PA_HOOK_OK;
}
int pa__init(pa_module* m) {
@@ -149,12 +145,12 @@ int pa__init(pa_module* m) {
u->core = m->core;
u->modargs = ma;
ma = NULL;
+ u->hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (setup_dbus(u) < 0)
+ if (!(u->discovery = pa_bluetooth_discovery_get(u->core)))
goto fail;
- if (!(u->discovery = pa_bluetooth_discovery_new(pa_dbus_connection_get(u->connection), load_module_for_device, u)))
- goto fail;
+ u->slot = pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery), PA_HOOK_NORMAL, (pa_hook_cb_t) load_module_for_device, u);
if (!async)
pa_bluetooth_discovery_sync(u->discovery);
@@ -178,11 +174,14 @@ void pa__done(pa_module* m) {
if (!(u = m->userdata))
return;
+ if (u->slot)
+ pa_hook_slot_free(u->slot);
+
if (u->discovery)
- pa_bluetooth_discovery_free(u->discovery);
+ pa_bluetooth_discovery_unref(u->discovery);
- if (u->connection)
- pa_dbus_connection_unref(u->connection);
+ if (u->hashmap)
+ pa_hashmap_free(u->hashmap, NULL, NULL);
if (u->modargs)
pa_modargs_free(u->modargs);
commit 8d5b375f67d1f414c0faa3e7810dc63b6e48b6a8
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Mar 21 01:31:38 2009 +0100
at a couple of #ifdef NOKIAs for now
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 928f33c..723162a 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -71,9 +71,14 @@ PA_MODULE_USAGE(
"profile=<a2dp|hsp> "
"rate=<sample rate> "
"channels=<number of channels> "
- "path=<device object path> "
+ "path=<device object path>");
+
+/*
+#ifdef NOKIA
"sco_sink=<SCO over PCM sink name> "
- "sco_source=<SCO over PCM source name>");
+ "sco_source=<SCO over PCM source name>"
+#endif
+*/
/* TODO: not close fd when entering suspend mode in a2dp */
@@ -87,8 +92,10 @@ static const char* const valid_modargs[] = {
"rate",
"channels",
"path",
+#ifdef NOKIA
"sco_sink",
"sco_source",
+#endif
NULL
};
@@ -106,8 +113,10 @@ struct a2dp_info {
struct hsp_info {
pcm_capabilities_t pcm_capabilities;
+#ifdef NOKIA
pa_sink *sco_sink;
pa_source *sco_source;
+#endif
pa_hook_slot *sink_state_changed_slot;
pa_hook_slot *source_state_changed_slot;
};
@@ -159,7 +168,9 @@ struct userdata {
int service_write_type, service_read_type;
};
+#ifdef NOKIA
#define USE_SCO_OVER_PCM(u) (u->profile == PROFILE_HSP && (u->hsp.sco_sink && u->hsp.sco_source))
+#endif
static int init_bt(struct userdata *u);
static int init_profile(struct userdata *u);
@@ -1404,6 +1415,8 @@ static char *get_name(const char *type, pa_modargs *ma, const char *device_id, p
return pa_sprintf_malloc("bluez_%s.%s", type, n);
}
+#ifdef NOKIA
+
static void sco_over_pcm_state_update(struct userdata *u) {
pa_assert(u);
pa_assert(USE_SCO_OVER_PCM(u));
@@ -1458,8 +1471,11 @@ static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, struct
return PA_HOOK_OK;
}
+#endif
+
static int add_sink(struct userdata *u) {
+#ifdef NOKIA
if (USE_SCO_OVER_PCM(u)) {
pa_proplist *p;
@@ -1472,7 +1488,10 @@ static int add_sink(struct userdata *u) {
if (!u->hsp.sink_state_changed_slot)
u->hsp.sink_state_changed_slot = pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_state_changed_cb, u);
- } else {
+ } else
+#endif
+
+ {
pa_sink_new_data data;
pa_bool_t b;
@@ -1504,19 +1523,19 @@ static int add_sink(struct userdata *u) {
}
static int add_source(struct userdata *u) {
- pa_proplist *p;
+#ifdef NOKIA
if (USE_SCO_OVER_PCM(u)) {
u->source = u->hsp.sco_source;
- p = pa_proplist_new();
- pa_proplist_sets(p, "bluetooth.protocol", "sco");
- pa_proplist_update(u->source->proplist, PA_UPDATE_MERGE, p);
- pa_proplist_free(p);
+ pa_proplist_sets(u->source->proplist, "bluetooth.protocol", "sco");
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);
- } else {
+ } else
+#endif
+
+ {
pa_source_new_data data;
pa_bool_t b;
@@ -1602,10 +1621,12 @@ static int setup_bt(struct userdata *u) {
pa_log_debug("Connection to the device configured");
+#ifdef NOKIA
if (USE_SCO_OVER_PCM(u)) {
pa_log_debug("Configured to use SCO over PCM");
return 0;
}
+#endif
pa_log_debug("Got the stream socket");
@@ -1683,6 +1704,7 @@ static int start_thread(struct userdata *u) {
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
+#ifdef NOKIA
if (USE_SCO_OVER_PCM(u)) {
if (start_stream_fd(u) < 0)
return -1;
@@ -1692,6 +1714,7 @@ static int start_thread(struct userdata *u) {
/* FIXME: monitor stream_fd error */
return 0;
}
+#endif
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log_error("Failed to create IO thread");
@@ -1727,14 +1750,18 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
if (u->sink) {
inputs = pa_sink_move_all_start(u->sink);
+#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
pa_sink_unlink(u->sink);
+#endif
}
if (u->source) {
outputs = pa_source_move_all_start(u->source);
+#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
pa_source_unlink(u->source);
+#endif
}
stop_thread(u);
@@ -1915,6 +1942,7 @@ int pa__init(pa_module* m) {
u->sample_spec = m->core->default_sample_spec;
u->modargs = ma;
+#ifdef NOKIA
if (pa_modargs_get_value(ma, "sco_sink", NULL) &&
!(u->hsp.sco_sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sco_sink", NULL), PA_NAMEREG_SINK))) {
pa_log("SCO sink not found");
@@ -1926,6 +1954,7 @@ int pa__init(pa_module* m) {
pa_log("SCO source not found");
goto fail;
}
+#endif
if (pa_modargs_get_value_u32(ma, "rate", &u->sample_spec.rate) < 0 ||
u->sample_spec.rate <= 0 || u->sample_spec.rate > PA_RATE_MAX) {
@@ -2036,10 +2065,18 @@ void pa__done(pa_module *m) {
if (!(u = m->userdata))
return;
- if (u->sink && !USE_SCO_OVER_PCM(u))
+ if (u->sink
+#ifdef NOKIA
+ && !USE_SCO_OVER_PCM(u)
+#endif
+ )
pa_sink_unlink(u->sink);
- if (u->source && !USE_SCO_OVER_PCM(u))
+ if (u->source
+#ifdef NOKIA
+ && !USE_SCO_OVER_PCM(u)
+#endif
+ )
pa_source_unlink(u->source);
stop_thread(u);
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 22e8ea3..4805e5f 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -42,13 +42,20 @@
PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
PA_MODULE_VERSION(PACKAGE_VERSION);
-PA_MODULE_USAGE("sco_sink=<name of sink> "
- "sco_source=<name of source>"
- "async=<Asynchronous initialization?>");
+PA_MODULE_USAGE("async=<Asynchronous initialization?>");
+
+/*
+#ifdef NOKIA
+ "sco_sink=<name of sink> "
+ "sco_source=<name of source>"
+#endif
+*/
static const char* const valid_modargs[] = {
+#ifdef NOKIA
"sco_sink",
"sco_source",
+#endif
"async",
NULL
};
@@ -86,6 +93,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
args = pa_sprintf_malloc("address=\"%s\" path=\"%s\" profile=\"%s\"", d->address, d->path, d->headset_connected ? "hsp" : "a2dp");
+#ifdef NOKIA
if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) &&
pa_modargs_get_value(u->modargs, "sco_source", NULL)) {
char *tmp;
@@ -96,6 +104,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
pa_xfree(args);
args = tmp;
}
+#endif
pa_log_debug("Loading module-bluetooth-device %s", args);
m = pa_module_load(u->module->core, "module-bluetooth-device", args);
commit b3675c28fa1c4bc4707e5700bc618240fc10e212
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Mar 21 02:45:31 2009 +0100
add functions that modules can call whenever they now the volume changed
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index c725595..147926a 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1135,6 +1135,19 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) {
}
/* Called from main thread */
+void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) {
+ pa_sink_assert_ref(s);
+
+ /* The sink implementor may call this if the volume changed to make sure everyone is notified */
+
+ if (pa_cvolume_equal(&s->virtual_volume, new_volume))
+ return;
+
+ s->virtual_volume = *new_volume;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
+
+/* Called from main thread */
void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) {
pa_bool_t old_muted;
@@ -1174,6 +1187,19 @@ pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) {
}
/* Called from main thread */
+void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
+ pa_sink_assert_ref(s);
+
+ /* The sink implementor may call this if the volume changed to make sure everyone is notified */
+
+ if (s->muted == new_muted)
+ return;
+
+ s->muted = new_muted;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
+
+/* Called from main thread */
pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
pa_sink_assert_ref(s);
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 0d33679..448f280 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -224,6 +224,8 @@ void pa_sink_detach(pa_sink *s);
void pa_sink_attach(pa_sink *s);
void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume);
+void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume);
+void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted);
pa_bool_t pa_device_init_description(pa_proplist *p);
pa_bool_t pa_device_init_icon(pa_proplist *p, pa_bool_t is_sink);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index cc6dfc4..ac1ef1e 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -675,6 +675,19 @@ const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
}
/* Called from main thread */
+void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
+ pa_source_assert_ref(s);
+
+ /* The source implementor may call this if the volume changed to make sure everyone is notified */
+
+ if (pa_cvolume_equal(&s->virtual_volume, new_volume))
+ return;
+
+ s->virtual_volume = *new_volume;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
+
+/* Called from main thread */
void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
pa_bool_t old_muted;
@@ -695,7 +708,6 @@ void pa_source_set_mute(pa_source *s, pa_bool_t mute) {
/* Called from main thread */
pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
-
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
@@ -715,6 +727,19 @@ pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
}
/* Called from main thread */
+void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
+ pa_source_assert_ref(s);
+
+ /* The source implementor may call this if the mute state changed to make sure everyone is notified */
+
+ if (s->muted == new_muted)
+ return;
+
+ s->muted = new_muted;
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}
+
+/* Called from main thread */
pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
pa_source_assert_ref(s);
pa_assert(p);
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 26471de..68bf2f0 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -211,6 +211,8 @@ void pa_source_detach(pa_source *s);
void pa_source_attach(pa_source *s);
void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume);
+void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume);
+void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted);
int pa_source_sync_suspend(pa_source *s);
commit c14da67050d3d1b5add80aee3712aa883cc4405b
Author: Lennart Poettering <lennart at poettering.net>
Date: Sat Mar 21 02:54:18 2009 +0100
readd volume control logic
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 723162a..dbc7ab1 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -132,6 +132,9 @@ struct userdata {
pa_module *module;
char *address;
+ char *path;
+
+ pa_dbus_connection *connection;
pa_card *card;
pa_sink *sink;
@@ -158,7 +161,6 @@ struct userdata {
struct a2dp_info a2dp;
struct hsp_info hsp;
- pa_dbus_connection *connection;
enum profile profile;
@@ -1247,145 +1249,100 @@ finish:
pa_log_debug("IO thread shutting down");
}
-/* static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) { */
-/* DBusMessageIter arg_i; */
-/* DBusError err; */
-/* const char *value; */
-/* struct userdata *u; */
-
-/* pa_assert(bus); */
-/* pa_assert(msg); */
-/* pa_assert(userdata); */
-/* u = userdata; */
-
-/* pa_log_debug("dbus: interface=%s, path=%s, member=%s\n", */
-/* dbus_message_get_interface(msg), */
-/* dbus_message_get_path(msg), */
-/* dbus_message_get_member(msg)); */
-
-/* dbus_error_init(&err); */
-
-/* if (!dbus_message_has_path(msg, u->path)) */
-/* goto done; */
-
-/* if (dbus_message_is_signal(msg, "org.bluez.Headset", "PropertyChanged") || */
-/* dbus_message_is_signal(msg, "org.bluez.AudioSink", "PropertyChanged")) { */
-
-/* struct device *d; */
-/* const char *profile; */
-/* DBusMessageIter variant_i; */
-/* dbus_uint16_t gain; */
-
-/* if (!dbus_message_iter_init(msg, &arg_i)) { */
-/* pa_log("dbus: message has no parameters"); */
-/* goto done; */
-/* } */
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) {
+ DBusError err;
+ struct userdata *u;
-/* if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_STRING) { */
-/* pa_log("Property name not a string."); */
-/* goto done; */
-/* } */
+ pa_assert(bus);
+ pa_assert(m);
+ pa_assert_se(u = userdata);
-/* dbus_message_iter_get_basic(&arg_i, &value); */
+ dbus_error_init(&err);
-/* if (!dbus_message_iter_next(&arg_i)) { */
-/* pa_log("Property value missing"); */
-/* goto done; */
-/* } */
+ pa_log_debug("dbus: interface=%s, path=%s, member=%s\n",
+ dbus_message_get_interface(m),
+ dbus_message_get_path(m),
+ dbus_message_get_member(m));
-/* if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_VARIANT) { */
-/* pa_log("Property value not a variant."); */
-/* goto done; */
-/* } */
+ if (!dbus_message_has_path(m, u->path))
+ goto fail;
-/* dbus_message_iter_recurse(&arg_i, &variant_i); */
+ if (dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged") ||
+ dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
-/* if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_UINT16) { */
-/* dbus_message_iter_get_basic(&variant_i, &gain); */
+ dbus_uint16_t gain;
+ pa_cvolume v;
-/* if (pa_streq(value, "SpeakerGain")) { */
-/* pa_log("spk gain: %d", gain); */
-/* pa_cvolume_set(&u->sink->virtual_volume, 1, (pa_volume_t) (gain * PA_VOLUME_NORM / 15)); */
-/* pa_subscription_post(u->sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, u->sink->index); */
-/* } else { */
-/* pa_log("mic gain: %d", gain); */
-/* if (!u->source) */
-/* goto done; */
+ if (!dbus_message_get_args(m, &err, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID) || gain > 15) {
+ pa_log("Failed to parse org.bluez.Headset.{Speaker|Microphone}GainChanged: %s", err.message);
+ goto fail;
+ }
-/* pa_cvolume_set(&u->source->virtual_volume, 1, (pa_volume_t) (gain * PA_VOLUME_NORM / 15)); */
-/* pa_subscription_post(u->source->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, u->source->index); */
-/* } */
-/* } */
-/* } */
+ if (u->profile == PROFILE_HSP) {
+ if (u->sink && dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged")) {
-/* done: */
-/* dbus_error_free(&err); */
-/* return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; */
-/* } */
+ pa_cvolume_set(&v, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_sink_volume_changed(u->sink, &v);
-/* static int sink_get_volume_cb(pa_sink *s) { */
-/* struct userdata *u = s->userdata; */
-/* pa_assert(u); */
+ } else if (u->source && dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
-/* /\* refresh? *\/ */
+ pa_cvolume_set(&v, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
+ pa_source_volume_changed(u->source, &v);
+ }
+ }
+ }
-/* return 0; */
-/* } */
+fail:
+ dbus_error_free(&err);
-/* static int source_get_volume_cb(pa_source *s) { */
-/* struct userdata *u = s->userdata; */
-/* pa_assert(u); */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
-/* /\* refresh? *\/ */
+static void sink_set_volume_cb(pa_sink *s) {
+ struct userdata *u = s->userdata;
+ DBusMessage *m;
+ dbus_uint16_t gain;
-/* return 0; */
-/* } */
+ pa_assert(u);
-/* static int sink_set_volume_cb(pa_sink *s) { */
-/* DBusError e; */
-/* DBusMessage *m, *r; */
-/* DBusMessageIter it, itvar; */
-/* dbus_uint16_t vol; */
-/* const char *spkgain = "SpeakerGain"; */
-/* struct userdata *u = s->userdata; */
-/* pa_assert(u); */
+ if (u->profile != PROFILE_HSP)
+ return;
-/* dbus_error_init(&e); */
+ gain = (pa_cvolume_max(&s->virtual_volume) * 15) / PA_VOLUME_NORM;
-/* vol = ((float) pa_cvolume_max(&s->virtual_volume) / PA_VOLUME_NORM) * 15; */
-/* pa_log_debug("set headset volume: %d", vol); */
+ if (gain > 15)
+ gain = 15;
-/* pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetProperty")); */
-/* dbus_message_iter_init_append(m, &it); */
-/* dbus_message_iter_append_basic(&it, DBUS_TYPE_STRING, &spkgain); */
-/* dbus_message_iter_open_container(&it, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT16_AS_STRING, &itvar); */
-/* dbus_message_iter_append_basic(&itvar, DBUS_TYPE_UINT16, &vol); */
-/* dbus_message_iter_close_container(&it, &itvar); */
+ pa_cvolume_set(&s->virtual_volume, u->sink->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
-/* r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e); */
+ 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));
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL));
+ dbus_message_unref(m);
+}
-/* finish: */
-/* if (m) */
-/* dbus_message_unref(m); */
-/* if (r) */
-/* dbus_message_unref(r); */
+static void source_set_volume_cb(pa_source *s) {
+ struct userdata *u = s->userdata;
+ DBusMessage *m;
+ dbus_uint16_t gain;
-/* dbus_error_free(&e); */
+ pa_assert(u);
-/* return 0; */
-/* } */
+ if (u->profile != PROFILE_HSP)
+ return;
-/* static int source_set_volume_cb(pa_source *s) { */
-/* dbus_uint16_t vol; */
-/* struct userdata *u = s->userdata; */
-/* pa_assert(u); */
+ gain = (pa_cvolume_max(&s->virtual_volume) * 15) / PA_VOLUME_NORM;
-/* vol = ((float)pa_cvolume_max(&s->virtual_volume) / PA_VOLUME_NORM) * 15; */
+ if (gain > 15)
+ gain = 15;
-/* pa_log_debug("set headset mic volume: %d (not implemented yet)", vol); */
+ pa_cvolume_set(&s->virtual_volume, u->source->sample_spec.channels, (pa_volume_t) (gain * PA_VOLUME_NORM / 15));
-/* return 0; */
-/* } */
+ 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));
+ pa_assert_se(dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL));
+ dbus_message_unref(m);
+}
static char *get_name(const char *type, pa_modargs *ma, const char *device_id, pa_bool_t *namereg_fail) {
char *t;
@@ -1504,7 +1461,7 @@ static int add_sink(struct userdata *u) {
data.name = get_name("sink", u->modargs, u->address, &b);
data.namereg_fail = b;
- u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+ u->sink = pa_sink_new(u->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY | (u->profile == PROFILE_HSP ? PA_SINK_HW_VOLUME_CTRL : 0));
pa_sink_new_data_done(&data);
if (!u->sink) {
@@ -1516,8 +1473,10 @@ static int add_sink(struct userdata *u) {
u->sink->parent.process_msg = sink_process_msg;
}
-/* u->sink->get_volume = sink_get_volume_cb; */
-/* u->sink->set_volume = sink_set_volume_cb; */
+ if (u->profile == PROFILE_HSP) {
+ u->sink->set_volume = sink_set_volume_cb;
+ u->sink->n_volume_steps = 16;
+ }
return 0;
}
@@ -1548,7 +1507,7 @@ static int add_source(struct userdata *u) {
data.name = get_name("source", u->modargs, u->address, &b);
data.namereg_fail = b;
- u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+ u->source = pa_source_new(u->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY | (u->profile == PROFILE_HSP ? PA_SOURCE_HW_VOLUME_CTRL : 0));
pa_source_new_data_done(&data);
if (!u->source) {
@@ -1560,10 +1519,11 @@ static int add_source(struct userdata *u) {
u->source->parent.process_msg = source_process_msg;
}
-/* u->source->get_volume = source_get_volume_cb; */
-/* u->source->set_volume = source_set_volume_cb; */
-
- pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0");
+ if (u->profile == PROFILE_HSP) {
+ pa_proplist_sets(u->source->proplist, "bluetooth.nrec", (u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC) ? "1" : "0");
+ u->source->set_volume = source_set_volume_cb;
+ u->source->n_volume_steps = 16;
+ }
return 0;
}
@@ -1726,12 +1686,18 @@ static int start_thread(struct userdata *u) {
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
pa_sink_put(u->sink);
+
+ if (u->sink->set_volume)
+ u->sink->set_volume(u->sink);
}
if (u->source) {
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
pa_source_put(u->source);
+
+ if (u->source->set_volume)
+ u->source->set_volume(u->source);
}
return 0;
@@ -1912,12 +1878,30 @@ static const pa_bluetooth_device* find_device(struct userdata *u, pa_bluetooth_d
}
}
- if (d)
+ if (d) {
u->address = pa_xstrdup(d->address);
+ u->path = pa_xstrdup(d->path);
+ }
return d;
}
+static int setup_dbus(struct userdata *u) {
+ DBusError err;
+
+ dbus_error_init(&err);
+
+ u->connection = pa_dbus_bus_get(u->core, DBUS_BUS_SYSTEM, &err);
+
+ if (dbus_error_is_set(&err) || !u->connection) {
+ pa_log("Failed to get D-Bus connection: %s", err.message);
+ dbus_error_free(&err);
+ return -1;
+ }
+
+ return 0;
+}
+
int pa__init(pa_module* m) {
pa_modargs *ma;
uint32_t channels;
@@ -1925,9 +1909,13 @@ int pa__init(pa_module* m) {
const char *address, *path;
const pa_bluetooth_device *d;
pa_bluetooth_discovery *y = NULL;
+ DBusError err;
+ char *mike, *speaker;
pa_assert(m);
+ dbus_error_init(&err);
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log_error("Failed to parse module arguments");
goto fail;
@@ -1974,6 +1962,9 @@ int pa__init(pa_module* m) {
address = pa_modargs_get_value(ma, "address", NULL);
path = pa_modargs_get_value(ma, "path", NULL);
+ if (setup_dbus(u) < 0)
+ goto fail;
+
if (!(y = pa_bluetooth_discovery_get(m->core)))
goto fail;
@@ -1991,46 +1982,34 @@ int pa__init(pa_module* m) {
if (init_bt(u) < 0)
goto fail;
+ if (!dbus_connection_add_filter(pa_dbus_connection_get(u->connection), filter_cb, u, NULL)) {
+ pa_log_error("Failed to add filter function");
+ goto fail;
+ }
+
+ speaker = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='SpeakerGainChanged',path='%s'", u->path);
+ mike = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='MicrophoneGainChanged',path='%s'", u->path);
+
+ if (pa_dbus_add_matches(
+ pa_dbus_connection_get(u->connection), &err,
+ speaker,
+ mike,
+ NULL) < 0) {
+
+ pa_xfree(speaker);
+ pa_xfree(mike);
+
+ pa_log("Failed to add D-Bus matches: %s", err.message);
+ goto fail;
+ }
+
+ pa_xfree(speaker);
+ pa_xfree(mike);
+
if (u->profile != PROFILE_OFF)
if (init_profile(u) < 0)
goto fail;
-/* if (u->path) { */
-/* DBusError err; */
-/* dbus_error_init(&err); */
-/* char *t; */
-
-
-/* if (!dbus_connection_add_filter(pa_dbus_connection_get(u->conn), filter_cb, u, NULL)) { */
-/* pa_log_error("Failed to add filter function"); */
-/* goto fail; */
-/* } */
-
-/* if (u->transport == BT_CAPABILITIES_TRANSPORT_SCO || */
-/* u->transport == BT_CAPABILITIES_TRANSPORT_ANY) { */
-/* t = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged',path='%s'", u->path); */
-/* dbus_bus_add_match(pa_dbus_connection_get(u->conn), t, &err); */
-/* pa_xfree(t); */
-
-/* if (dbus_error_is_set(&err)) { */
-/* pa_log_error("Unable to subscribe to org.bluez.Headset signals: %s: %s", err.name, err.message); */
-/* goto fail; */
-/* } */
-/* } */
-
-/* if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP || */
-/* u->transport == BT_CAPABILITIES_TRANSPORT_ANY) { */
-/* t = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged',path='%s'", u->path); */
-/* dbus_bus_add_match(pa_dbus_connection_get(u->conn), t, &err); */
-/* pa_xfree(t); */
-
-/* if (dbus_error_is_set(&err)) { */
-/* pa_log_error("Unable to subscribe to org.bluez.AudioSink signals: %s: %s", err.name, err.message); */
-/* goto fail; */
-/* } */
-/* } */
-/* } */
-
if (u->sink || u->source)
if (start_thread(u) < 0)
goto fail;
@@ -2044,6 +2023,8 @@ fail:
pa__done(m);
+ dbus_error_free(&err);
+
return -1;
}
@@ -2082,30 +2063,22 @@ void pa__done(pa_module *m) {
stop_thread(u);
if (u->connection) {
-/* DBusError error; */
-/* char *t; */
-
-/* if (u->transport == BT_CAPABILITIES_TRANSPORT_SCO || */
-/* u->transport == BT_CAPABILITIES_TRANSPORT_ANY) { */
-
-/* t = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged',path='%s'", u->path); */
-/* dbus_error_init(&error); */
-/* dbus_bus_remove_match(pa_dbus_connection_get(u->conn), t, &error); */
-/* dbus_error_free(&error); */
-/* pa_xfree(t); */
-/* } */
-
-/* if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP || */
-/* u->transport == BT_CAPABILITIES_TRANSPORT_ANY) { */
-
-/* t = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged',path='%s'", u->path); */
-/* dbus_error_init(&error); */
-/* dbus_bus_remove_match(pa_dbus_connection_get(u->conn), t, &error); */
-/* dbus_error_free(&error); */
-/* pa_xfree(t); */
-/* } */
-
-/* dbus_connection_remove_filter(pa_dbus_connection_get(u->conn), filter_cb, u); */
+
+ if (u->path) {
+ char *speaker, *mike;
+ speaker = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='SpeakerGainChanged',path='%s'", u->path);
+ mike = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='MicrophoneGainChanged',path='%s'", u->path);
+
+ pa_dbus_remove_matches(pa_dbus_connection_get(u->connection),
+ speaker,
+ mike,
+ NULL);
+
+ pa_xfree(speaker);
+ pa_xfree(mike);
+ }
+
+ dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
pa_dbus_connection_unref(u->connection);
}
@@ -2126,6 +2099,7 @@ void pa__done(pa_module *m) {
pa_modargs_free(u->modargs);
pa_xfree(u->address);
+ pa_xfree(u->path);
pa_xfree(u);
}
commit 906fd570c71677dca9f1c12366b009d9a0b95e1a
Merge: c14da67 4c381cd
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 23 16:32:03 2009 +0100
Merge commit 'origin/master-tx'
commit 124de50ef8e4074302c0c205e61ccd78744dd549
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 23 19:16:00 2009 +0100
enable bluetooth default by support
diff --git a/src/daemon/default.pa.in b/src/daemon/default.pa.in
index 02ac8e5..57ccd9f 100755
--- a/src/daemon/default.pa.in
+++ b/src/daemon/default.pa.in
@@ -59,7 +59,7 @@ load-module module-detect
### Automatically load driver modules for Bluetooth hardware
#.ifexists module-bluetooth-discover at PA_SOEXT@
-#load-module module-bluetooth-discover
+load-module module-bluetooth-discover
#.endif
### Load several protocols
commit 08154554b0cdce6d16816536211718bf14ff33ff
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 23 19:31:36 2009 +0100
only store card profile if flagged for that
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index 0afb935..17f1f8c 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -161,6 +161,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
if (!(card = pa_idxset_get_by_index(c->cards, idx)))
return;
+ if (!card->save_profile)
+ return;
+
pa_strlcpy(entry.profile, card->active_profile ? card->active_profile->name : "", sizeof(entry.profile));
if ((old = read_entry(u, card->name))) {
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index 6419c23..f268f7c 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -143,7 +143,8 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
c->active_profile = NULL;
if (data->active_profile && c->profiles)
- c->active_profile = pa_hashmap_get(c->profiles, data->active_profile);
+ if ((c->active_profile = pa_hashmap_get(c->profiles, data->active_profile)))
+ c->save_profile = data->save_profile;
if (!c->active_profile && c->profiles) {
void *state = NULL;
@@ -209,7 +210,7 @@ void pa_card_free(pa_card *c) {
pa_xfree(c);
}
-int pa_card_set_profile(pa_card *c, const char *name) {
+int pa_card_set_profile(pa_card *c, const char *name, pa_bool_t save) {
pa_card_profile *profile;
pa_assert(c);
@@ -224,8 +225,10 @@ int pa_card_set_profile(pa_card *c, const char *name) {
if (!(profile = pa_hashmap_get(c->profiles, name)))
return -1;
- if (c->active_profile == profile)
+ if (c->active_profile == profile) {
+ c->save_profile = c->save_profile || save;
return 0;
+ }
if (c->set_profile(c, profile) < 0)
return -1;
@@ -235,6 +238,7 @@ int pa_card_set_profile(pa_card *c, const char *name) {
pa_log_info("Changed profile of card %u \"%s\" to %s", c->index, c->name, profile->name);
c->active_profile = profile;
+ c->save_profile = save;
return 0;
}
diff --git a/src/pulsecore/card.h b/src/pulsecore/card.h
index c80d4e2..3b7608f 100644
--- a/src/pulsecore/card.h
+++ b/src/pulsecore/card.h
@@ -63,6 +63,8 @@ struct pa_card {
pa_hashmap *profiles;
pa_card_profile *active_profile;
+ pa_bool_t save_profile;
+
void *userdata;
int (*set_profile)(pa_card *c, pa_card_profile *profile);
@@ -80,6 +82,8 @@ typedef struct pa_card_new_data {
char *active_profile;
pa_bool_t namereg_fail:1;
+
+ pa_bool_t save_profile:1;
} pa_card_new_data;
pa_card_profile *pa_card_profile_new(const char *name, const char *description, size_t extra);
@@ -93,7 +97,7 @@ void pa_card_new_data_done(pa_card_new_data *data);
pa_card *pa_card_new(pa_core *c, pa_card_new_data *data);
void pa_card_free(pa_card *c);
-int pa_card_set_profile(pa_card *c, const char *name);
+int pa_card_set_profile(pa_card *c, const char *name, pa_bool_t save);
int pa_card_suspend(pa_card *c, pa_bool_t suspend);
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index b5f7e7f..d4d407c 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -1454,7 +1454,7 @@ static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *b
return -1;
}
- if (pa_card_set_profile(card, p) < 0) {
+ if (pa_card_set_profile(card, p, TRUE) < 0) {
pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
return -1;
}
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 4860860..ff49e69 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -4119,7 +4119,7 @@ static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_
CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
- if (pa_card_set_profile(card, profile) < 0) {
+ if (pa_card_set_profile(card, profile, TRUE) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
return;
}
commit a467bec42352c8e86cbc4c680a19a376405946ba
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Mon Mar 16 16:39:28 2009 +0200
pulse: check context (do not user pstream when NULL)
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 9a0ea0f..a7fccc8 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -948,6 +948,7 @@ static int create_stream(
PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
+ PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
/* Althought some of the other flags are not supported on older
* version, we don't check for them here, because it doesn't hurt
* when they are passed but actually not supported. This makes
commit 52dcb950efead46a398da977bc28e560f8564b62
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 23 21:03:52 2009 +0100
add pa_assert_cc() for compile time assertions
diff --git a/src/pulse/fork-detect.c b/src/pulse/fork-detect.c
index f10fc02..a4e0dd1 100644
--- a/src/pulse/fork-detect.c
+++ b/src/pulse/fork-detect.c
@@ -39,7 +39,7 @@ int pa_detect_fork(void) {
* however have to deal with this cleanly, so we try to detect the
* forks making sure all our calls fail cleanly after the fork. */
- pa_assert(sizeof(pa_atomic_t) >= sizeof(pid_t));
+ pa_assert_cc(sizeof(pa_atomic_t) >= sizeof(pid_t));
for (;;) {
pid_t stored_pid = (pid_t) pa_atomic_load(&pid);
diff --git a/src/pulsecore/macro.h b/src/pulsecore/macro.h
index 309f1a0..a5ca696 100644
--- a/src/pulsecore/macro.h
+++ b/src/pulsecore/macro.h
@@ -193,11 +193,25 @@ typedef int pa_bool_t;
#define pa_assert_fp(expr) pa_assert_se(expr)
#endif
+#ifdef NDEBUG
+#define pa_assert_not_reached() pa_nop()
+#else
#define pa_assert_not_reached() \
do { \
pa_log_error("Code should not be reached at %s:%u, function %s(). Aborting.", __FILE__, __LINE__, PA_PRETTY_FUNCTION); \
abort(); \
} while (FALSE)
+#endif
+
+/* A compile time assertion */
+#define pa_assert_cc(expr) \
+ do { \
+ switch (0) { \
+ case 0: \
+ case !!(expr): \
+ ; \
+ } \
+ } while (FALSE)
#define PA_PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
#define PA_UINT_TO_PTR(u) ((void*) ((uintptr_t) (u)))
commit bcbfd5b9835ca2e7d00cd3f2ca090bcfea182451
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 23 22:27:29 2009 +0100
don't fail when no session bus is available
diff --git a/src/modules/reserve-wrap.c b/src/modules/reserve-wrap.c
index 7d33927..c956673 100644
--- a/src/modules/reserve-wrap.c
+++ b/src/modules/reserve-wrap.c
@@ -112,8 +112,11 @@ pa_reserve_wrapper* pa_reserve_wrapper_get(pa_core *c, const char *device_name)
pa_assert_se(pa_shared_set(c, r->shared_name, r) >= 0);
if (!(r->connection = pa_dbus_bus_get(c, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
- pa_log_error("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
- goto fail;
+ pa_log_warn("Unable to contact D-Bus session bus: %s: %s", error.name, error.message);
+
+ /* We don't treat this as error here because we want allow PA
+ * to run even when no session bus is available. */
+ return r;
}
if ((k = rd_acquire(
commit e6be9481dcf1d9c675aa8881b473189c6c50081d
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 20:59:54 2009 +0100
only decrease timer slack, never increase
diff --git a/src/pulsecore/rtclock.c b/src/pulsecore/rtclock.c
index 56ab2ef..65c826a 100644
--- a/src/pulsecore/rtclock.c
+++ b/src/pulsecore/rtclock.c
@@ -95,6 +95,8 @@ pa_bool_t pa_rtclock_hrtimer(void) {
#endif
}
+#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))
+
void pa_rtclock_hrtimer_enable(void) {
#ifdef PR_SET_TIMERSLACK
int slack_ns;
@@ -104,15 +106,17 @@ void pa_rtclock_hrtimer_enable(void) {
return;
}
- pa_log_debug("Timer slack set to %i us.", slack_ns/1000);
+ pa_log_debug("Timer slack is set to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC));
- slack_ns = 500000000;
+ if (slack_ns > TIMER_SLACK_NS) {
+ slack_ns = TIMER_SLACK_NS;
- pa_log_debug("Setting timer slack to %i us.", slack_ns/1000);
+ pa_log_debug("Setting timer slack to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC));
- if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) {
- pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno));
- return;
+ if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) {
+ pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno));
+ return;
+ }
}
#endif
commit aa92ff408c6a5fb6a4bd452aef1105eb70da9d0d
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 21:06:57 2009 +0100
simplify latency range by not allowing stored 'wildcard' ranges anymore
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 7bf16c3..a770f0f 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -240,7 +240,7 @@ static void adjust_after_underrun(struct userdata *u) {
pa_log_notice("Increasing minimal latency to %0.2f ms",
(double) new_min_latency / PA_USEC_PER_MSEC);
- pa_sink_update_latency_range(u->sink, new_min_latency, u->sink->thread_info.max_latency);
+ pa_sink_set_latency_range_within_thread(u->sink, new_min_latency, u->sink->thread_info.max_latency);
return;
}
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index f4acad8..7c09c00 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -238,7 +238,7 @@ static void adjust_after_overrun(struct userdata *u) {
pa_log_notice("Increasing minimal latency to %0.2f ms",
(double) new_min_latency / PA_USEC_PER_MSEC);
- pa_source_update_latency_range(u->source, new_min_latency, u->source->thread_info.max_latency);
+ pa_source_set_latency_range_within_thread(u->source, new_min_latency, u->source->thread_info.max_latency);
return;
}
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 33562b1..54a4e6c 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -290,7 +290,7 @@ static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
return;
- pa_sink_update_latency_range(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
+ pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
}
/* Called from I/O thread context */
@@ -322,7 +322,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
pa_sink_attach_within_thread(u->sink);
- pa_sink_update_latency_range(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
+ pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
}
/* Called from main context */
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 31824bc..7ab81b6 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -205,7 +205,7 @@ static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
return;
- pa_sink_update_latency_range(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
+ pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
}
/* Called from I/O thread context */
@@ -237,7 +237,7 @@ static void sink_input_attach_cb(pa_sink_input *i) {
pa_sink_set_rtpoll(u->sink, i->sink->rtpoll);
pa_sink_attach_within_thread(u->sink);
- pa_sink_update_latency_range(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
+ pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
}
/* Called from main context */
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 147926a..7c43a8e 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -48,7 +48,9 @@
#define MAX_MIX_CHANNELS 32
#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
+#define ABSOLUTE_MIN_LATENCY (500)
#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
+#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
@@ -231,7 +233,7 @@ pa_sink* pa_sink_new(
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
- s->thread_info.max_latency = 0;
+ s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -343,8 +345,7 @@ void pa_sink_put(pa_sink* 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_SINK_HW_VOLUME_CTRL)) {
s->flags |= PA_SINK_DECIBEL_VOLUME;
@@ -1591,7 +1592,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
case PA_SINK_MESSAGE_SET_LATENCY_RANGE: {
pa_usec_t *r = userdata;
- pa_sink_update_latency_range(s, r[0], r[1]);
+ pa_sink_set_latency_range_within_thread(s, r[0], r[1]);
return 0;
}
@@ -1738,10 +1739,10 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s) {
result = monitor_latency;
if (result != (pa_usec_t) -1) {
- if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
+ if (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)
+ if (result < s->thread_info.min_latency)
result = s->thread_info.min_latency;
}
@@ -1835,11 +1836,16 @@ void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_
if (min_latency == (pa_usec_t) -1)
min_latency = DEFAULT_MIN_LATENCY;
+ if (min_latency < ABSOLUTE_MIN_LATENCY)
+ min_latency = ABSOLUTE_MIN_LATENCY;
+
if (max_latency == (pa_usec_t) -1)
max_latency = min_latency;
- pa_assert(!min_latency || !max_latency ||
- min_latency <= max_latency);
+ if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
+ max_latency = ABSOLUTE_MAX_LATENCY;
+
+ pa_assert(min_latency <= max_latency);
if (PA_SINK_IS_LINKED(s->state)) {
pa_usec_t r[2];
@@ -1879,14 +1885,15 @@ void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *ma
}
/* Called from IO thread */
-void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
pa_sink_input *i;
void *state = NULL;
pa_sink_assert_ref(s);
- pa_assert(!min_latency || !max_latency ||
- min_latency <= max_latency);
+ pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
+ pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
+ pa_assert(min_latency <= max_latency);
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
@@ -1897,7 +1904,7 @@ void pa_sink_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t m
pa_sink_invalidate_requested_latency(s);
- pa_source_update_latency_range(s->monitor_source, min_latency, max_latency);
+ pa_source_set_latency_range_within_thread(s->monitor_source, min_latency, max_latency);
}
/* Called from main context */
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 448f280..260b272 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -283,7 +283,7 @@ pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s);
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_update_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency);
+void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency);
/*** To be called exclusively by sink input drivers, from IO context */
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index ac1ef1e..4a5bbad 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -41,7 +41,9 @@
#include "source.h"
+#define ABSOLUTE_MIN_LATENCY (500)
#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
+#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
@@ -219,7 +221,7 @@ pa_source* pa_source_new(
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
- s->thread_info.max_latency = 0;
+ s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
@@ -936,7 +938,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
pa_usec_t *r = userdata;
- pa_source_update_latency_range(s, r[0], r[1]);
+ pa_source_set_latency_range_within_thread(s, r[0], r[1]);
return 0;
}
@@ -1130,11 +1132,16 @@ void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t
if (min_latency == (pa_usec_t) -1)
min_latency = DEFAULT_MIN_LATENCY;
+ if (min_latency < ABSOLUTE_MIN_LATENCY)
+ min_latency = ABSOLUTE_MIN_LATENCY;
+
if (max_latency == (pa_usec_t) -1)
max_latency = min_latency;
- pa_assert(!min_latency || !max_latency ||
- min_latency <= max_latency);
+ if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
+ max_latency = ABSOLUTE_MAX_LATENCY;
+
+ pa_assert(min_latency <= max_latency);
if (PA_SOURCE_IS_LINKED(s->state)) {
pa_usec_t r[2];
@@ -1170,14 +1177,15 @@ void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t
}
/* Called from IO thread */
-void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
+void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
pa_source_output *o;
void *state = NULL;
pa_source_assert_ref(s);
- pa_assert(!min_latency || !max_latency ||
- min_latency <= max_latency);
+ pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
+ pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
+ pa_assert(min_latency <= max_latency);
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 68bf2f0..862e1aa 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -260,7 +260,7 @@ void pa_source_detach_within_thread(pa_source *s);
pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s);
void pa_source_set_max_rewind(pa_source *s, size_t max_rewind);
-void pa_source_update_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
+void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
/*** To be called exclusively by source output drivers, from IO context */
commit 2f9a784167cca67a07d750455bc8006f9077a235
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 21:13:41 2009 +0100
set request/rewind sizes only via accessor functions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index a770f0f..bcca57d 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -756,7 +756,7 @@ static int update_sw_params(struct userdata *u) {
return err;
}
- pa_sink_set_max_request(u->sink, u->hwbuf_size - u->hwbuf_unused);
+ pa_sink_set_max_request_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
return 0;
}
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 4b2d6f9..f72223d 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -649,7 +649,7 @@ static void update_max_request(struct userdata *u) {
if (max_request <= 0)
max_request = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
- pa_sink_set_max_request(u->sink, max_request);
+ pa_sink_set_max_request_within_thread(u->sink, max_request);
}
/* Called from thread context of the io thread */
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 54a4e6c..81546ff 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -264,7 +264,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
return;
pa_memblockq_set_maxrewind(u->memblockq, nbytes);
- pa_sink_set_max_rewind(u->sink, nbytes);
+ pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
}
/* Called from I/O thread context */
@@ -277,7 +277,7 @@ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
return;
- pa_sink_set_max_request(u->sink, nbytes);
+ pa_sink_set_max_request_within_thread(u->sink, nbytes);
}
/* Called from I/O thread context */
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 183d4b2..c8edd0c 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -253,6 +253,7 @@ int pa__init(pa_module*m) {
pa_channel_map map;
pa_modargs *ma = NULL;
pa_sink_new_data data;
+ size_t nbytes;
pa_assert(m);
@@ -299,11 +300,11 @@ int pa__init(pa_module*m) {
pa_sink_set_rtpoll(u->sink, u->rtpoll);
pa_sink_set_latency_range(u->sink, (pa_usec_t) -1, MAX_LATENCY_USEC);
- u->block_usec = u->sink->thread_info.max_latency;
- u->sink->thread_info.max_rewind =
- u->sink->thread_info.max_request =
- pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
+ u->block_usec = u->sink->thread_info.max_latency;
+ nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
+ pa_sink_set_max_rewind(u->sink, nbytes);
+ pa_sink_set_max_request(u->sink, nbytes);
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log("Failed to create thread.");
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 7ab81b6..8c43a72 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -179,7 +179,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
return;
- pa_sink_set_max_rewind(u->sink, nbytes);
+ pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
}
/* Called from I/O thread context */
@@ -192,7 +192,7 @@ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
if (!u->sink || !PA_SINK_IS_LINKED(u->sink->thread_info.state))
return;
- pa_sink_set_max_request(u->sink, nbytes);
+ pa_sink_set_max_request_within_thread(u->sink, nbytes);
}
/* Called from I/O thread context */
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index 995b3c6..e7dfc05 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -653,7 +653,7 @@ static void thread_func(void *userdata) {
u->buffer_size = u->buffer_size * 18 / 25;
u->buffer_size -= u->buffer_size % u->frame_size;
u->buffer_size = PA_MAX(u->buffer_size, (int32_t)MIN_BUFFER_SIZE);
- pa_sink_set_max_request(u->sink, u->buffer_size);
+ pa_sink_set_max_request_within_thread(u->sink, u->buffer_size);
pa_log("EAGAIN. Buffer size is now %u bytes (%llu buffered)", u->buffer_size, buffered_bytes);
break;
default:
@@ -946,7 +946,7 @@ int pa__init(pa_module *m) {
u->sink->set_mute = sink_set_mute;
u->sink->refresh_volume = u->sink->refresh_muted = TRUE;
- u->sink->thread_info.max_request = u->buffer_size;
+ pa_sink_set_max_request(u->sink, u->buffer_size);
u->min_request = pa_usec_to_bytes(PA_USEC_PER_SEC / MAX_RENDER_HZ, &ss);
} else
u->sink = NULL;
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index 7bce8d0..f67f47e 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -1388,7 +1388,7 @@ int pa__init(pa_module*m) {
pa_sink_set_rtpoll(u->sink, u->rtpoll);
u->sink->refresh_volume = TRUE;
- u->sink->thread_info.max_request = u->out_hwbuf_size;
+ pa_sink_set_max_request(u->sink, u->out_hwbuf_size);
if (use_mmap)
u->out_mmap_memblocks = pa_xnew0(pa_memblock*, u->out_nfrags);
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 7c43a8e..308a4e5 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1616,6 +1616,16 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
*((size_t*) userdata) = s->thread_info.max_request;
return 0;
+ case PA_SINK_MESSAGE_SET_MAX_REWIND:
+
+ pa_sink_set_max_rewind_within_thread(s, (size_t) offset);
+ return 0;
+
+ case PA_SINK_MESSAGE_SET_MAX_REQUEST:
+
+ pa_sink_set_max_request_within_thread(s, (size_t) offset);
+ return 0;
+
case PA_SINK_MESSAGE_GET_LATENCY:
case PA_SINK_MESSAGE_MAX:
;
@@ -1767,7 +1777,7 @@ pa_usec_t pa_sink_get_requested_latency(pa_sink *s) {
}
/* Called from IO as well as the main thread -- the latter only before the IO thread started up */
-void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
+void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
pa_sink_input *i;
void *state = NULL;
@@ -1787,8 +1797,18 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
}
+/* Called from main thread */
+void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) {
+ pa_sink_assert_ref(s);
+
+ if (PA_SINK_IS_LINKED(s->state))
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
+ else
+ pa_sink_set_max_rewind_within_thread(s, max_rewind);
+}
+
/* Called from IO as well as the main thread -- the latter only before the IO thread started up */
-void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
+void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request) {
void *state = NULL;
pa_sink_assert_ref(s);
@@ -1806,6 +1826,16 @@ void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
}
}
+/* Called from main thread */
+void pa_sink_set_max_request(pa_sink *s, size_t max_request) {
+ pa_sink_assert_ref(s);
+
+ if (PA_SINK_IS_LINKED(s->state))
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_MAX_REQUEST, NULL, max_request, NULL) == 0);
+ else
+ pa_sink_set_max_request_within_thread(s, max_request);
+}
+
/* Called from IO thread */
void pa_sink_invalidate_requested_latency(pa_sink *s) {
pa_sink_input *i;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index 260b272..f3f2542 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -172,6 +172,8 @@ typedef enum pa_sink_message {
PA_SINK_MESSAGE_GET_LATENCY_RANGE,
PA_SINK_MESSAGE_GET_MAX_REWIND,
PA_SINK_MESSAGE_GET_MAX_REQUEST,
+ PA_SINK_MESSAGE_SET_MAX_REWIND,
+ PA_SINK_MESSAGE_SET_MAX_REQUEST,
PA_SINK_MESSAGE_MAX
} pa_sink_message_t;
@@ -217,6 +219,8 @@ void pa_sink_unlink(pa_sink* s);
void pa_sink_set_description(pa_sink *s, const char *description);
void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q);
void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p);
+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);
@@ -280,8 +284,8 @@ void pa_sink_detach_within_thread(pa_sink *s);
pa_usec_t pa_sink_get_requested_latency_within_thread(pa_sink *s);
-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_max_rewind_within_thread(pa_sink *s, size_t max_rewind);
+void pa_sink_set_max_request_within_thread(pa_sink *s, size_t max_request);
void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency);
commit 50695d95d11baf621dde1fa71db03ff422bbef6e
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 21:14:08 2009 +0100
minimal reordering
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index a7fccc8..48e3b08 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -138,13 +138,13 @@ pa_stream *pa_stream_new_with_proplist(
s->device_index = PA_INVALID_INDEX;
s->device_name = NULL;
s->suspended = FALSE;
+ s->corked = FALSE;
pa_memchunk_reset(&s->peek_memchunk);
s->peek_data = NULL;
s->record_memblockq = NULL;
- s->corked = FALSE;
memset(&s->timing_info, 0, sizeof(s->timing_info));
s->timing_info_valid = FALSE;
commit c64d8cbcc7eefa2e805db415f99b507c5a065195
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 21:17:55 2009 +0100
Allow calling pa_{sink|source}_update_proplist() without an actual proprlist
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 308a4e5..a3bf03a 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1202,11 +1202,10 @@ void pa_sink_mute_changed(pa_sink *s, pa_bool_t new_muted) {
/* Called from main thread */
pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
-
pa_sink_assert_ref(s);
- pa_assert(p);
- pa_proplist_update(s->proplist, mode, p);
+ if (p)
+ pa_proplist_update(s->proplist, mode, p);
if (PA_SINK_IS_LINKED(s->state)) {
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 4a5bbad..da3ae79 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -744,9 +744,9 @@ void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
/* Called from main thread */
pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
pa_source_assert_ref(s);
- pa_assert(p);
- pa_proplist_update(s->proplist, mode, p);
+ if (p)
+ pa_proplist_update(s->proplist, mode, p);
if (PA_SOURCE_IS_LINKED(s->state)) {
pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
commit 5b523d097cb975a28b616098844de49d8431bfbf
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 24 21:42:33 2009 +0100
fix bad memory access when destroying m-b-d
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 4805e5f..da0fe93 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -69,23 +69,24 @@ struct userdata {
pa_hashmap *hashmap;
};
+struct module_info {
+ char *path;
+ uint32_t module;
+};
+
static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const pa_bluetooth_device *d, struct userdata *u) {
- uint32_t midx;
+ struct module_info *mi;
pa_assert(u);
pa_assert(d);
-
- if (!(midx = PA_PTR_TO_UINT(pa_hashmap_get(u->hashmap, d->path))))
- midx = PA_INVALID_INDEX;
- else
- midx--;
+ mi = pa_hashmap_get(u->hashmap, d->path);
if (!d->dead &&
d->device_connected > 0 &&
(d->audio_sink_connected > 0 || d->headset_connected > 0)) {
- if (midx == PA_INVALID_INDEX) {
+ if (!mi) {
pa_module *m = NULL;
char *args;
@@ -110,22 +111,28 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
m = pa_module_load(u->module->core, "module-bluetooth-device", args);
pa_xfree(args);
- if (m)
- pa_hashmap_put(u->hashmap, d->path, PA_UINT_TO_PTR((uint32_t) (m->index+1)));
- else
+ if (m) {
+ mi = pa_xnew(struct module_info, 1);
+ mi->module = m->index;
+ mi->path = pa_xstrdup(d->path);
+
+ pa_hashmap_put(u->hashmap, mi->path, mi);
+ } else
pa_log_debug("Failed to load module for device %s", d->path);
}
} else {
- if (midx != PA_INVALID_INDEX) {
+ if (mi) {
/* Hmm, disconnection? Then let's unload our module */
pa_log_debug("Unloading module for %s", d->path);
- pa_module_unload_request_by_index(u->core, midx, TRUE);
+ pa_module_unload_request_by_index(u->core, mi->module, TRUE);
- pa_hashmap_remove(u->hashmap, d->path);
+ pa_hashmap_remove(u->hashmap, mi->path);
+ pa_xfree(mi->path);
+ pa_xfree(mi);
}
}
@@ -189,8 +196,16 @@ void pa__done(pa_module* m) {
if (u->discovery)
pa_bluetooth_discovery_unref(u->discovery);
- if (u->hashmap)
+ if (u->hashmap) {
+ struct module_info *mi;
+
+ while ((mi = pa_hashmap_steal_first(u->hashmap))) {
+ pa_xfree(mi->path);
+ pa_xfree(mi);
+ }
+
pa_hashmap_free(u->hashmap, NULL, NULL);
+ }
if (u->modargs)
pa_modargs_free(u->modargs);
commit a7246bd635ab5eb9f708937383d7c3ebf5c1345c
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Tue Mar 24 16:28:12 2009 +0200
bluetooth: fix #NOKIA, correctly unlink sink/src
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index dbc7ab1..2500fb0 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1718,16 +1718,16 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
inputs = pa_sink_move_all_start(u->sink);
#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
- pa_sink_unlink(u->sink);
#endif
+ pa_sink_unlink(u->sink);
}
if (u->source) {
outputs = pa_source_move_all_start(u->source);
#ifdef NOKIA
if (!USE_SCO_OVER_PCM(u))
- pa_source_unlink(u->source);
#endif
+ pa_source_unlink(u->source);
}
stop_thread(u);
commit 9151107cb9a1fe0620d3ddb53ac6982a75e1d010
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:25:17 2009 +0100
get rid of 'default' min/max latencies, simplify things by just having absolute boundaries
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index a3bf03a..1fec018 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -49,7 +49,6 @@
#define MAX_MIX_CHANNELS 32
#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
#define ABSOLUTE_MIN_LATENCY (500)
-#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
@@ -232,8 +231,8 @@ pa_sink* pa_sink_new(
s->thread_info.max_request = 0;
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
- s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
- s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
+ s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
+ s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
@@ -1857,21 +1856,15 @@ void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_
pa_sink_assert_ref(s);
/* min_latency == 0: no limit
- * min_latency == (size_t) -1: default limit
* min_latency anything else: specified limit
*
* Similar for max_latency */
- if (min_latency == (pa_usec_t) -1)
- min_latency = DEFAULT_MIN_LATENCY;
-
if (min_latency < ABSOLUTE_MIN_LATENCY)
min_latency = ABSOLUTE_MIN_LATENCY;
- if (max_latency == (pa_usec_t) -1)
- max_latency = min_latency;
-
- if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
+ if (max_latency <= 0 ||
+ max_latency > ABSOLUTE_MAX_LATENCY)
max_latency = ABSOLUTE_MAX_LATENCY;
pa_assert(min_latency <= max_latency);
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index f3f2542..7d1e11e 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -219,9 +219,9 @@ void pa_sink_unlink(pa_sink* s);
void pa_sink_set_description(pa_sink *s, const char *description);
void pa_sink_set_asyncmsgq(pa_sink *s, pa_asyncmsgq *q);
void pa_sink_set_rtpoll(pa_sink *s, pa_rtpoll *p);
+
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_detach(pa_sink *s);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index da3ae79..6e5bf1f 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -42,7 +42,6 @@
#include "source.h"
#define ABSOLUTE_MIN_LATENCY (500)
-#define DEFAULT_MIN_LATENCY (4*PA_USEC_PER_MSEC)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
@@ -220,8 +219,8 @@ pa_source* pa_source_new(
s->thread_info.max_rewind = 0;
s->thread_info.requested_latency_valid = FALSE;
s->thread_info.requested_latency = 0;
- s->thread_info.min_latency = DEFAULT_MIN_LATENCY;
- s->thread_info.max_latency = DEFAULT_MIN_LATENCY;
+ s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
+ s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
@@ -1124,21 +1123,15 @@ void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t
pa_source_assert_ref(s);
/* min_latency == 0: no limit
- * min_latency == (size_t) -1: default limit
* min_latency anything else: specified limit
*
* Similar for max_latency */
- if (min_latency == (pa_usec_t) -1)
- min_latency = DEFAULT_MIN_LATENCY;
-
if (min_latency < ABSOLUTE_MIN_LATENCY)
min_latency = ABSOLUTE_MIN_LATENCY;
- if (max_latency == (pa_usec_t) -1)
- max_latency = min_latency;
-
- if (max_latency > ABSOLUTE_MAX_LATENCY || max_latency <= 0)
+ if (max_latency <= 0 ||
+ max_latency > ABSOLUTE_MAX_LATENCY)
max_latency = ABSOLUTE_MAX_LATENCY;
pa_assert(min_latency <= max_latency);
commit 9bca59efc1500770008345ff12571892eeaa5b50
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:26:44 2009 +0100
make pa_source_set_max_rewind() work similar to pa_sink_set_max_rewind()
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 6e5bf1f..f1f8ef7 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -956,6 +956,11 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
*((size_t*) userdata) = s->thread_info.max_rewind;
return 0;
+ case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
+
+ pa_source_set_max_rewind_within_thread(s, (size_t) offset);
+ return 0;
+
case PA_SOURCE_MESSAGE_GET_LATENCY:
if (s->monitor_of) {
@@ -1083,7 +1088,7 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) {
}
/* Called from IO thread */
-void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
+void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
pa_source_output *o;
void *state = NULL;
@@ -1100,6 +1105,17 @@ void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
}
}
+/* Called from main thread */
+void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
+ pa_source_assert_ref(s);
+
+ if (PA_SOURCE_IS_LINKED(s->state))
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
+ else
+ pa_source_set_max_rewind_within_thread(s, max_rewind);
+}
+
+/* Called from IO thread */
void pa_source_invalidate_requested_latency(pa_source *s) {
pa_source_output *o;
void *state = NULL;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index 862e1aa..210f534 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -159,6 +159,7 @@ typedef enum pa_source_message {
PA_SOURCE_MESSAGE_SET_LATENCY_RANGE,
PA_SOURCE_MESSAGE_GET_LATENCY_RANGE,
PA_SOURCE_MESSAGE_GET_MAX_REWIND,
+ PA_SOURCE_MESSAGE_SET_MAX_REWIND,
PA_SOURCE_MESSAGE_MAX
} pa_source_message_t;
@@ -205,6 +206,7 @@ void pa_source_set_description(pa_source *s, const char *description);
void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q);
void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p);
+void pa_source_set_max_rewind(pa_source *s, size_t max_rewind);
void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
void pa_source_detach(pa_source *s);
@@ -259,7 +261,7 @@ void pa_source_detach_within_thread(pa_source *s);
pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s);
-void pa_source_set_max_rewind(pa_source *s, size_t max_rewind);
+void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind);
void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency);
/*** To be called exclusively by source output drivers, from IO context */
commit 44ca897769bc34e6672223cd43cddbfa1b201976
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:30:54 2009 +0100
introduce new flag that marks sinks/sources which can adjust the latency dynamically
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index bcca57d..a7728a0 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1662,7 +1662,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_alsa_init_description(data.proplist);
- u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
+ u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|(u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0));
pa_sink_new_data_done(&data);
if (!u->sink) {
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 7c09c00..8b76ee5 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1514,7 +1514,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
pa_alsa_init_description(data.proplist);
- u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
+ u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|(u->use_tsched ? PA_SOURCE_DYNAMIC_LATENCY : 0));
pa_source_new_data_done(&data);
if (!u->source) {
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 81546ff..e619acd 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -705,7 +705,7 @@ int pa__init(pa_module*m) {
pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright);
pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID);
- u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY);
+ u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY);
pa_sink_new_data_done(&sink_data);
if (!u->sink) {
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 8c43a72..f9777be 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -354,7 +354,7 @@ int pa__init(pa_module*m) {
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
- u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY);
+ u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY);
pa_sink_new_data_done(&sink_data);
if (!u->sink) {
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 3629aab..8bcb691 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -702,9 +702,13 @@ typedef enum pa_sink_flags {
/**< Volume can be translated to dB with pa_sw_volume_to_dB()
* \since 0.9.11 */
- PA_SINK_FLAT_VOLUME = 0x0040U
+ PA_SINK_FLAT_VOLUME = 0x0040U,
/**< This sink is in flat volume mode, i.e. always the maximum of
* the volume of all connected inputs. \since 0.9.15 */
+
+ PA_SINK_DYNAMIC_LATENCY = 0x0080U
+ /**< The latency can be adjusted dynamically depending on the
+ * needs of the connected streams. \since 0.9.15 */
} pa_sink_flags_t;
/** \cond fulldocs */
@@ -715,6 +719,7 @@ typedef enum pa_sink_flags {
#define PA_SINK_HW_MUTE_CTRL PA_SINK_HW_MUTE_CTRL
#define PA_SINK_DECIBEL_VOLUME PA_SINK_DECIBEL_VOLUME
#define PA_SINK_FLAT_VOLUME PA_SINK_FLAT_VOLUME
+#define PA_SINK_DYNAMIC_LATENCY PA_SINK_DYNAMIC_LATENCY
/** \endcond */
/** Sink state. \since 0.9.15 */
@@ -780,9 +785,13 @@ typedef enum pa_source_flags {
PA_SOURCE_HW_MUTE_CTRL = 0x0010U,
/**< Supports hardware mute control \since 0.9.11 */
- PA_SOURCE_DECIBEL_VOLUME = 0x0020U
+ PA_SOURCE_DECIBEL_VOLUME = 0x0020U,
/**< Volume can be translated to dB with pa_sw_volume_to_dB()
* \since 0.9.11 */
+
+ PA_SOURCE_DYNAMIC_LATENCY = 0x0080U
+ /**< The latency can be adjusted dynamically depending on the
+ * needs of the connected streams. \since 0.9.15 */
} pa_source_flags_t;
/** \cond fulldocs */
@@ -792,6 +801,7 @@ typedef enum pa_source_flags {
#define PA_SOURCE_NETWORK PA_SOURCE_NETWORK
#define PA_SOURCE_HW_MUTE_CTRL PA_SOURCE_HW_MUTE_CTRL
#define PA_SOURCE_DECIBEL_VOLUME PA_SOURCE_DECIBEL_VOLUME
+#define PA_SOURCE_DYNAMIC_LATENCY PA_SOURCE_DYNAMIC_LATENCY
/** \endcond */
/** Source state. \since 0.9.15 */
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 76adc4d..8d39dcf 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -220,19 +220,17 @@ char *pa_sink_list_to_string(pa_core *c) {
v[PA_VOLUME_SNPRINT_MAX],
vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
- pa_usec_t min_latency, max_latency;
const char *cmn;
cmn = pa_channel_map_to_pretty_name(&sink->channel_map);
- pa_sink_get_latency_range(sink, &min_latency, &max_latency);
pa_strbuf_printf(
s,
" %c index: %u\n"
"\tname: <%s>\n"
"\tdriver: <%s>\n"
- "\tflags: %s%s%s%s%s%s%s\n"
+ "\tflags: %s%s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tvolume: %s%s%s\n"
"\t balance %0.2f\n"
@@ -240,7 +238,6 @@ char *pa_sink_list_to_string(pa_core *c) {
"\tvolume steps: %u\n"
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
- "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
"\tmax request: %lu KiB\n"
"\tmax rewind: %lu KiB\n"
"\tmonitor source: %u\n"
@@ -259,6 +256,7 @@ char *pa_sink_list_to_string(pa_core *c) {
sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME" : "",
+ sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
sink_state_to_string(pa_sink_get_state(sink)),
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)),
sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
@@ -270,9 +268,6 @@ char *pa_sink_list_to_string(pa_core *c) {
sink->n_volume_steps,
pa_yes_no(pa_sink_get_mute(sink, FALSE)),
(double) pa_sink_get_latency(sink) / (double) PA_USEC_PER_MSEC,
- (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,
(unsigned long) pa_sink_get_max_request(sink) / 1024,
(unsigned long) pa_sink_get_max_rewind(sink) / 1024,
sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
@@ -283,6 +278,18 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_sink_used_by(sink),
pa_sink_linked_by(sink));
+ if (sink->flags & PA_SINK_DYNAMIC_LATENCY) {
+ pa_usec_t min_latency, max_latency;
+ pa_sink_get_latency_range(sink, &min_latency, &max_latency);
+
+ pa_strbuf_printf(
+ s,
+ "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n",
+ (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);
+ }
+
if (sink->card)
pa_strbuf_printf(s, "\tcard: %u <%s>\n", sink->card->index, sink->card->name);
if (sink->module)
@@ -313,19 +320,16 @@ char *pa_source_list_to_string(pa_core *c) {
v[PA_VOLUME_SNPRINT_MAX],
vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t;
- pa_usec_t min_latency, max_latency;
const char *cmn;
cmn = pa_channel_map_to_pretty_name(&source->channel_map);
- pa_source_get_latency_range(source, &min_latency, &max_latency);
-
pa_strbuf_printf(
s,
" %c index: %u\n"
"\tname: <%s>\n"
"\tdriver: <%s>\n"
- "\tflags: %s%s%s%s%s%s\n"
+ "\tflags: %s%s%s%s%s%s%s\n"
"\tstate: %s\n"
"\tvolume: %s%s%s\n"
"\t balance %0.2f\n"
@@ -333,7 +337,6 @@ char *pa_source_list_to_string(pa_core *c) {
"\tvolume steps: %u\n"
"\tmuted: %s\n"
"\tcurrent latency: %0.2f ms\n"
- "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n"
"\tmax rewind: %lu KiB\n"
"\tsample spec: %s\n"
"\tchannel map: %s%s%s\n"
@@ -349,6 +352,7 @@ char *pa_source_list_to_string(pa_core *c) {
source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
+ source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
source_state_to_string(pa_source_get_state(source)),
pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)),
source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
@@ -360,9 +364,6 @@ char *pa_source_list_to_string(pa_core *c) {
source->n_volume_steps,
pa_yes_no(pa_source_get_mute(source, FALSE)),
(double) pa_source_get_latency(source) / PA_USEC_PER_MSEC,
- (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,
(unsigned long) pa_source_get_max_rewind(source) / 1024,
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map),
@@ -371,6 +372,18 @@ char *pa_source_list_to_string(pa_core *c) {
pa_source_used_by(source),
pa_source_linked_by(source));
+ if (source->flags & PA_SOURCE_DYNAMIC_LATENCY) {
+ pa_usec_t min_latency, max_latency;
+ pa_source_get_latency_range(source, &min_latency, &max_latency);
+
+ pa_strbuf_printf(
+ s,
+ "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n",
+ (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);
+ }
+
if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index);
if (source->card)
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 1fec018..c2012df 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1869,6 +1869,11 @@ void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_
pa_assert(min_latency <= max_latency);
+ /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
+ pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
+ max_latency == ABSOLUTE_MAX_LATENCY) ||
+ (s->flags & PA_SINK_DYNAMIC_LATENCY));
+
if (PA_SINK_IS_LINKED(s->state)) {
pa_usec_t r[2];
@@ -1917,6 +1922,11 @@ void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency,
pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
pa_assert(min_latency <= max_latency);
+ /* Hmm, let's see if someone forgot to set PA_SINK_DYNAMIC_LATENCY here... */
+ pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
+ max_latency == ABSOLUTE_MAX_LATENCY) ||
+ (s->flags & PA_SINK_DYNAMIC_LATENCY));
+
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index f1f8ef7..0fe6f8d 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -1152,6 +1152,11 @@ void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t
pa_assert(min_latency <= max_latency);
+ /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
+ pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
+ max_latency == ABSOLUTE_MAX_LATENCY) ||
+ (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
+
if (PA_SOURCE_IS_LINKED(s->state)) {
pa_usec_t r[2];
@@ -1196,6 +1201,11 @@ void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_laten
pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
pa_assert(min_latency <= max_latency);
+ /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
+ pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
+ max_latency == ABSOLUTE_MAX_LATENCY) ||
+ (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
+
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
commit 892a83945e7cd56039fcbbefc4c16ffdb3a7d722
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:33:35 2009 +0100
simplify things and make sure timing setters can be called in most contexts
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index c2012df..68f8856 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1843,12 +1843,15 @@ void pa_sink_invalidate_requested_latency(pa_sink *s) {
s->thread_info.requested_latency_valid = FALSE;
- if (s->update_requested_latency)
- s->update_requested_latency(s);
+ if (PA_SINK_IS_LINKED(s->thread_info.state)) {
- while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
- if (i->update_sink_requested_latency)
- i->update_sink_requested_latency(i);
+ if (s->update_requested_latency)
+ s->update_requested_latency(s);
+
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ if (i->update_sink_requested_latency)
+ i->update_sink_requested_latency(i);
+ }
}
/* Called from main thread */
@@ -1881,15 +1884,8 @@ void pa_sink_set_latency_range(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_
r[1] = max_latency;
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
- } else {
- s->thread_info.min_latency = min_latency;
- s->thread_info.max_latency = max_latency;
-
- s->monitor_source->thread_info.min_latency = min_latency;
- s->monitor_source->thread_info.max_latency = max_latency;
-
- s->thread_info.requested_latency_valid = s->monitor_source->thread_info.requested_latency_valid = FALSE;
- }
+ } else
+ pa_sink_set_latency_range_within_thread(s, min_latency, max_latency);
}
/* Called from main thread */
@@ -1913,7 +1909,6 @@ void pa_sink_get_latency_range(pa_sink *s, pa_usec_t *min_latency, pa_usec_t *ma
/* Called from IO thread */
void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency, pa_usec_t max_latency) {
- pa_sink_input *i;
void *state = NULL;
pa_sink_assert_ref(s);
@@ -1930,9 +1925,13 @@ void pa_sink_set_latency_range_within_thread(pa_sink *s, pa_usec_t min_latency,
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
- while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
- if (i->update_sink_latency_range)
- i->update_sink_latency_range(i);
+ if (PA_SINK_IS_LINKED(s->thread_info.state)) {
+ pa_sink_input *i;
+
+ while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)))
+ if (i->update_sink_latency_range)
+ i->update_sink_latency_range(i);
+ }
pa_sink_invalidate_requested_latency(s);
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 0fe6f8d..5b4378a 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -1124,17 +1124,21 @@ void pa_source_invalidate_requested_latency(pa_source *s) {
s->thread_info.requested_latency_valid = FALSE;
- if (s->update_requested_latency)
- s->update_requested_latency(s);
+ if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
- while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
- if (o->update_source_requested_latency)
- o->update_source_requested_latency(o);
+ if (s->update_requested_latency)
+ s->update_requested_latency(s);
+
+ while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+ if (o->update_source_requested_latency)
+ o->update_source_requested_latency(o);
+ }
if (s->monitor_of)
pa_sink_invalidate_requested_latency(s->monitor_of);
}
+/* Called from main thread */
void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
pa_source_assert_ref(s);
@@ -1164,14 +1168,11 @@ void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t
r[1] = max_latency;
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
- } else {
- s->thread_info.min_latency = min_latency;
- s->thread_info.max_latency = max_latency;
-
- s->thread_info.requested_latency_valid = FALSE;
- }
+ } else
+ pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
}
+/* Called from main thread */
void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
pa_source_assert_ref(s);
pa_assert(min_latency);
@@ -1190,9 +1191,8 @@ void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t
}
}
-/* Called from IO thread */
+/* Called from IO thread, and from main thread before pa_sink_put() is called */
void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
- pa_source_output *o;
void *state = NULL;
pa_source_assert_ref(s);
@@ -1209,13 +1209,18 @@ void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_laten
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
- while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
- if (o->update_source_latency_range)
- o->update_source_latency_range(o);
+ if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
+ pa_source_output *o;
+
+ while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
+ if (o->update_source_latency_range)
+ o->update_source_latency_range(o);
+ }
pa_source_invalidate_requested_latency(s);
}
+/* Called from main thread */
size_t pa_source_get_max_rewind(pa_source *s) {
size_t r;
pa_source_assert_ref(s);
commit 171c88f1324acc85a71d13a386f05aa8e38895a6
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:40:12 2009 +0100
link jack modules's max_request to the jack buffer size
diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c
index 63fdd2d..31b8a96 100644
--- a/src/modules/module-jack-sink.c
+++ b/src/modules/module-jack-sink.c
@@ -112,6 +112,7 @@ static const char* const valid_modargs[] = {
enum {
SINK_MESSAGE_RENDER = PA_SINK_MESSAGE_MAX,
+ SINK_MESSAGE_BUFFER_SIZE,
SINK_MESSAGE_ON_SHUTDOWN
};
@@ -158,6 +159,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
return 0;
+ case SINK_MESSAGE_BUFFER_SIZE:
+ pa_sink_set_max_request_within_thread(u->sink, (size_t) offset * pa_frame_size(&u->sink->sample_spec));
+ return 0;
+
case SINK_MESSAGE_ON_SHUTDOWN:
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
return 0;
@@ -184,6 +189,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
return 0;
}
+
}
return pa_sink_process_msg(o, code, data, offset, memchunk);
@@ -263,10 +269,18 @@ static void jack_init(void *arg) {
static void jack_shutdown(void* arg) {
struct userdata *u = arg;
- pa_log_info("JACK thread shutting down..");
+ pa_log_info("JACK thread shutting down.");
pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_ON_SHUTDOWN, NULL, 0, NULL, NULL);
}
+static int jack_buffer_size(jack_nframes_t nframes, void *arg) {
+ struct userdata *u = arg;
+
+ pa_log_info("JACK buffer size changed.");
+ pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_BUFFER_SIZE, NULL, nframes, NULL, NULL);
+ return 0;
+}
+
int pa__init(pa_module*m) {
struct userdata *u = NULL;
pa_sample_spec ss;
@@ -297,10 +311,9 @@ int pa__init(pa_module*m) {
server_name = pa_modargs_get_value(ma, "server_name", NULL);
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Sink");
- u = pa_xnew0(struct userdata, 1);
+ m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
- m->userdata = u;
u->saved_frame_time_valid = FALSE;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
@@ -386,10 +399,12 @@ int pa__init(pa_module*m) {
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
+ pa_sink_set_max_request(u->sink, jack_get_buffer_size(u->client) * pa_frame_size(&u->sink->sample_spec));
jack_set_process_callback(u->client, jack_process, u);
jack_on_shutdown(u->client, jack_shutdown, u);
jack_set_thread_init_callback(u->client, jack_init, u);
+ jack_set_buffer_size_callback(u->client, jack_buffer_size, u);
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log("Failed to create thread.");
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index c77c958..41f09a8 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -270,12 +270,11 @@ int pa__init(pa_module*m) {
server_name = pa_modargs_get_value(ma, "server_name", NULL);
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Source");
- u = pa_xnew0(struct userdata, 1);
+ m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
m->userdata = u;
u->saved_frame_time_valid = FALSE;
-
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
@@ -372,14 +371,14 @@ int pa__init(pa_module*m) {
for (i = 0, p = ports; i < ss.channels; i++, p++) {
if (!*p) {
- pa_log("not enough physical output ports, leaving unconnected.");
+ pa_log("Not enough physical output ports, leaving unconnected.");
break;
}
- pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p);
+ pa_log_info("Connecting %s to %s", jack_port_name(u->port[i]), *p);
if (jack_connect(u->client, *p, jack_port_name(u->port[i]))) {
- pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
+ pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
break;
}
}
commit 0316dba9d1bb519259076f580869cf65147bde44
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:41:23 2009 +0100
set latency range only in tsched mode
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index a7728a0..3040582 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1685,26 +1685,27 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->tsched_watermark = pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark, &requested_ss), &u->sink->sample_spec);
pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels);
+ pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
+ nfrags, (long unsigned) u->fragment_size,
+ (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
+
+ pa_sink_set_max_request(u->sink, u->hwbuf_size);
+
if (use_tsched) {
fix_min_sleep_wakeup(u);
fix_tsched_watermark(u);
u->watermark_step = pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC, &u->sink->sample_spec);
- }
- pa_sink_set_max_rewind(u->sink, use_tsched ? u->hwbuf_size : 0);
- pa_sink_set_max_request(u->sink, u->hwbuf_size);
- pa_sink_set_latency_range(u->sink,
- use_tsched ? (pa_usec_t) -1 : pa_bytes_to_usec(u->hwbuf_size, &ss),
- pa_bytes_to_usec(u->hwbuf_size, &ss));
+ pa_sink_set_max_rewind(u->sink, u->hwbuf_size);
- pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
- nfrags, (long unsigned) u->fragment_size,
- (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
+ pa_sink_set_latency_range(u->sink,
+ 0,
+ pa_bytes_to_usec(u->hwbuf_size, &ss));
- if (use_tsched)
pa_log_info("Time scheduling watermark is %0.2fms",
(double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
+ }
reserve_update(u);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 8b76ee5..4a535aa 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1537,24 +1537,23 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->tsched_watermark = pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark, &requested_ss), &u->source->sample_spec);
pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels);
+ pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
+ nfrags, (long unsigned) u->fragment_size,
+ (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
+
if (use_tsched) {
fix_min_sleep_wakeup(u);
fix_tsched_watermark(u);
u->watermark_step = pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC, &u->source->sample_spec);
- }
- pa_source_set_latency_range(u->source,
- use_tsched ? (pa_usec_t) -1 : pa_bytes_to_usec(u->hwbuf_size, &ss),
- pa_bytes_to_usec(u->hwbuf_size, &ss));
+ pa_source_set_latency_range(u->source,
+ 0,
+ pa_bytes_to_usec(u->hwbuf_size, &ss));
- pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms",
- nfrags, (long unsigned) u->fragment_size,
- (double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
-
- if (use_tsched)
pa_log_info("Time scheduling watermark is %0.2fms",
(double) pa_bytes_to_usec(u->tsched_watermark, &ss) / PA_USEC_PER_MSEC);
+ }
reserve_update(u);
commit b815a1c7eb16e79b3b9ded80edda522202ad25f9
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:42:32 2009 +0100
don't fiddle with latency range because we cannot adjust it dynamically
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index f72223d..b7e18bc 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -69,7 +69,7 @@ PA_MODULE_USAGE(
#define DEFAULT_ADJUST_TIME 10
-#define REQUEST_LATENCY_USEC (PA_USEC_PER_MSEC * 200)
+#define BLOCK_USEC (PA_USEC_PER_MSEC * 200)
static const char* const valid_modargs[] = {
"sink_name",
@@ -817,7 +817,7 @@ static int output_create_sink_input(struct output *o) {
o->sink_input->kill = sink_input_kill_cb;
o->sink_input->userdata = o;
- pa_sink_input_set_requested_latency(o->sink_input, REQUEST_LATENCY_USEC);
+ pa_sink_input_set_requested_latency(o->sink_input, BLOCK_USEC);
return 0;
}
@@ -1088,11 +1088,8 @@ int pa__init(pa_module*m) {
pa_sink_set_rtpoll(u->sink, u->rtpoll);
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
- pa_sink_set_latency_range(u->sink, REQUEST_LATENCY_USEC, REQUEST_LATENCY_USEC);
- u->block_usec = u->sink->thread_info.max_latency;
-
- u->sink->thread_info.max_request =
- pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
+ u->block_usec = BLOCK_USEC;
+ pa_sink_set_max_request(u->sink, pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec));
if (!u->automatic) {
const char*split_state;
commit 59b7e530cac58ce82c293db77d993274456e7370
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:42:47 2009 +0100
Don't initialize userdata twice
diff --git a/src/modules/module-jack-source.c b/src/modules/module-jack-source.c
index 41f09a8..9a215c5 100644
--- a/src/modules/module-jack-source.c
+++ b/src/modules/module-jack-source.c
@@ -273,7 +273,6 @@ int pa__init(pa_module*m) {
m->userdata = u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
- m->userdata = u;
u->saved_frame_time_valid = FALSE;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
commit bcfe51ffd5bb7e4b9e5f90cc73f8af3ebcc34a36
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:44:21 2009 +0100
again, don't fiddle with latency range in sinks with static latency
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index c8edd0c..129bc1c 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -62,7 +62,7 @@ PA_MODULE_USAGE(
"description=<description for the sink>");
#define DEFAULT_SINK_NAME "null"
-#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
+#define BLOCK_USEC (PA_USEC_PER_SEC * 2)
struct userdata {
pa_core *core;
@@ -299,9 +299,7 @@ int pa__init(pa_module*m) {
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
- pa_sink_set_latency_range(u->sink, (pa_usec_t) -1, MAX_LATENCY_USEC);
-
- u->block_usec = u->sink->thread_info.max_latency;
+ u->block_usec = BLOCK_USEC;
nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec);
pa_sink_set_max_rewind(u->sink, nbytes);
pa_sink_set_max_request(u->sink, nbytes);
commit d0bd3d95922b1b3582fff70a3d2fba6d269e7488
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:44:36 2009 +0100
initialize max_request
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index def4f75..26b6b96 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -292,6 +292,7 @@ int pa__init(pa_module*m) {
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
+ pa_sink_set_max_request(u->sink, PIPE_BUF);
u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1);
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
commit 98a5f4a9919c67792f3bbf01ee5ed7e666b8b216
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 00:45:13 2009 +0100
don't fiddle with latency range in sources with static latency
diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index 206c45f..50e4730 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -60,7 +60,7 @@ PA_MODULE_USAGE(
"frequency=<frequency in Hz>");
#define DEFAULT_SOURCE_NAME "sine_input"
-#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
+#define BLOCK_USEC (PA_USEC_PER_SEC * 2)
struct userdata {
pa_core *core;
@@ -263,8 +263,7 @@ int pa__init(pa_module*m) {
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
- pa_source_set_latency_range(u->source, (pa_usec_t) -1, MAX_LATENCY_USEC);
- u->block_usec = u->source->thread_info.max_latency;
+ u->block_usec = BLOCK_USEC;
if (!(u->thread = pa_thread_new(thread_func, u))) {
pa_log("Failed to create thread.");
commit fdbe0543be395b7baa4b8228a035529135b8b4c1
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 01:17:56 2009 +0100
initialize max_request to SO_SNDBUF
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 2b45e30..a27de4c 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -354,6 +354,9 @@ static int do_write(struct userdata *u) {
}
if (!u->write_data && u->state == STATE_PREPARE) {
+ int so_sndbuf = 0;
+ socklen_t sl = sizeof(int);
+
/* OK, we're done with sending all control data we need to, so
* let's hand the socket over to the IO thread now */
@@ -366,6 +369,13 @@ static int do_write(struct userdata *u) {
pa_make_tcp_socket_low_delay(u->fd);
+ if (getsockopt(u->fd, SOL_SOCKET, SO_SNDBUF, &so_sndbuf, &sl) < 0)
+ pa_log_warn("getsockopt(SO_SNDBUF) failed: %s", pa_cstrerror(errno));
+ else {
+ pa_log_debug("SO_SNDBUF is %zu.", (size_t) so_sndbuf);
+ pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size));
+ }
+
pa_log_debug("Connection authenticated, handing fd to IO thread...");
pa_asyncmsgq_post(u->thread_mq.inq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_PASS_SOCKET, NULL, 0, NULL, NULL);
commit 119698ae91dfe525c1934d0d4035d2c6250ad79c
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 01:18:29 2009 +0100
beef up esd sink properties a bit
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index a27de4c..5c47f44 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -576,7 +576,8 @@ int pa__init(pa_module*m) {
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
pa_sink_new_data_set_sample_spec(&data, &ss);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, espeaker);
- pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Esound sink '%s'", espeaker);
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "esd");
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "EsounD Output on %s", espeaker);
u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_NETWORK);
pa_sink_new_data_done(&data);
commit 577259bb15ebf3ddc0586476b5f945b055895ba5
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 02:39:41 2009 +0100
trivial simplification
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 2b80c65..83d3992 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -1105,8 +1105,7 @@ static int do_read(connection *c) {
pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, c->client->proplist, &idx);
pa_memblock_unref(c->scache.memchunk.memblock);
- c->scache.memchunk.memblock = NULL;
- c->scache.memchunk.index = c->scache.memchunk.length = 0;
+ pa_memchunk_reset(&c->scache.memchunk);
pa_xfree(c->scache.name);
c->scache.name = NULL;
commit e41ec51f1bdefe44c7104ce27130999600b7911e
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 02:42:18 2009 +0100
add simple ref counting debugging framework
diff --git a/src/pulsecore/memblock.c b/src/pulsecore/memblock.c
index fbf0a47..6cc0ff3 100644
--- a/src/pulsecore/memblock.c
+++ b/src/pulsecore/memblock.c
@@ -745,8 +745,47 @@ void pa_mempool_free(pa_mempool *p) {
pa_flist_free(p->free_slots, NULL);
if (pa_atomic_load(&p->stat.n_allocated) > 0) {
-/* raise(SIGTRAP); */
- pa_log_warn("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
+
+ /* Ouch, somebody is retaining a memory block reference! */
+
+#ifdef DEBUG_REF
+ unsigned i;
+ pa_flist *list;
+
+ /* Let's try to find at least one of those leaked memory blocks */
+
+ list = pa_flist_new(p->n_blocks);
+
+ for (i = 0; i < (unsigned) pa_atomic_load(&p->n_init); i++) {
+ struct mempool_slot *slot;
+ pa_memblock *b, *k;
+
+ slot = (struct mempool_slot*) ((uint8_t*) p->memory.ptr + (p->block_size * (size_t) i));
+ b = mempool_slot_data(slot);
+
+ while ((k = pa_flist_pop(p->free_slots))) {
+ while (pa_flist_push(list, k) < 0)
+ ;
+
+ if (b == k)
+ break;
+ }
+
+ if (!k)
+ pa_log("REF: Leaked memory block %p", b);
+
+ while ((k = pa_flist_pop(list)))
+ while (pa_flist_push(p->free_slots, k) < 0)
+ ;
+ }
+
+ pa_flist_free(list, NULL);
+
+#endif
+
+ pa_log_error("Memory pool destroyed but not all memory blocks freed! %u remain.", pa_atomic_load(&p->stat.n_allocated));
+
+/* PA_DEBUG_TRAP; */
}
pa_shm_free(&p->memory);
diff --git a/src/pulsecore/refcnt.h b/src/pulsecore/refcnt.h
index 1e98832..782436b 100644
--- a/src/pulsecore/refcnt.h
+++ b/src/pulsecore/refcnt.h
@@ -23,23 +23,59 @@
***/
#include <pulsecore/atomic.h>
+#include <pulsecore/macro.h>
+#include <pulsecore/log.h>
+
+/* #define DEBUG_REF */
#define PA_REFCNT_DECLARE \
pa_atomic_t _ref
-#define PA_REFCNT_INIT(p) \
- pa_atomic_store(&(p)->_ref, 1)
+#define PA_REFCNT_VALUE(p) \
+ pa_atomic_load(&(p)->_ref)
#define PA_REFCNT_INIT_ZERO(p) \
pa_atomic_store(&(p)->_ref, 0)
+#ifndef DEBUG_REF
+
+#define PA_REFCNT_INIT(p) \
+ pa_atomic_store(&(p)->_ref, 1)
+
#define PA_REFCNT_INC(p) \
pa_atomic_inc(&(p)->_ref)
#define PA_REFCNT_DEC(p) \
(pa_atomic_dec(&(p)->_ref)-1)
-#define PA_REFCNT_VALUE(p) \
- pa_atomic_load(&(p)->_ref)
+#else
+
+/* If you need to debug ref counting problems define DEBUG_REF and
+ * set $PULSE_LOG_BACKTRACE=5 or suchlike in the shell when running
+ * PA */
+
+#define PA_REFCNT_INIT(p) \
+ do { \
+ pa_atomic_store(&(p)->_ref, 1); \
+ pa_log("REF: Init %p", p); \
+ } while (FALSE)
+
+#define PA_REFCNT_INC(p) \
+ do { \
+ pa_atomic_inc(&(p)->_ref); \
+ pa_log("REF: Inc %p", p); \
+ } while (FALSE) \
+
+#define PA_REFCNT_DEC(p) \
+ ({ \
+ int _j = (pa_atomic_dec(&(p)->_ref)-1); \
+ if (_j <= 0) \
+ pa_log("REF: Done %p", p); \
+ else \
+ pa_log("REF: Dec %p", p); \
+ _j; \
+ })
+
+#endif
#endif
commit 8460fac28583f96c039f94d42f1035c266f9a45f
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 02:50:57 2009 +0100
don't show full so path in backtrace
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index d4d3b76..e1b6794 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -156,7 +156,7 @@ static char* get_backtrace(unsigned show_nframes) {
for (j = 0; j < n; j++) {
if (j > 0)
a += 2;
- a += strlen(symbols[j]);
+ a += strlen(pa_path_get_filename(symbols[j]));
}
r = pa_xnew(char, a);
@@ -165,13 +165,17 @@ static char* get_backtrace(unsigned show_nframes) {
e = r + 2;
for (j = 0; j < n; j++) {
+ const char *sym;
+
if (j > 0) {
strcpy(e, "<<");
e += 2;
}
- strcpy(e, symbols[j]);
- e += strlen(symbols[j]);
+ sym = pa_path_get_filename(symbols[j]);
+
+ strcpy(e, sym);
+ e += strlen(sym);
}
strcpy(e, ")");
commit f6a6d013546025806a0449ae51dde70de8baff57
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 03:14:00 2009 +0100
optionally skip initial frames in backtrace
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index e1b6794..750d73b 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -59,12 +59,13 @@
#define ENV_LOG_PRINT_META "PULSE_LOG_META"
#define ENV_LOG_PRINT_LEVEL "PULSE_LOG_LEVEL"
#define ENV_LOG_BACKTRACE "PULSE_LOG_BACKTRACE"
+#define ENV_LOG_BACKTRACE_SKIP "PULSE_LOG_BACKTRACE_SKIP"
static char *ident = NULL; /* in local charset format */
static pa_log_target_t target = PA_LOG_STDERR, target_override;
static pa_bool_t target_override_set = FALSE;
static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_LOG_ERROR;
-static unsigned show_backtrace = 0, show_backtrace_override = 0;
+static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0;
static pa_log_flags_t flags = 0, flags_override = 0;
#ifdef HAVE_SYSLOG_H
@@ -128,13 +129,17 @@ void pa_log_set_show_backtrace(unsigned nlevels) {
show_backtrace = nlevels;
}
+void pa_log_set_skip_backtrace(unsigned nlevels) {
+ skip_backtrace = nlevels;
+}
+
#ifdef HAVE_EXECINFO_H
static char* get_backtrace(unsigned show_nframes) {
void* trace[32];
int n_frames;
char **symbols, *e, *r;
- unsigned j, n;
+ unsigned j, n, s;
size_t a;
pa_assert(show_nframes > 0);
@@ -149,12 +154,13 @@ static char* get_backtrace(unsigned show_nframes) {
if (!symbols)
return NULL;
- n = PA_MIN((unsigned) n_frames, show_nframes);
+ s = skip_backtrace;
+ n = PA_MIN((unsigned) n_frames, s + show_nframes);
a = 4;
- for (j = 0; j < n; j++) {
- if (j > 0)
+ for (j = s; j < n; j++) {
+ if (j > s)
a += 2;
a += strlen(pa_path_get_filename(symbols[j]));
}
@@ -164,10 +170,10 @@ static char* get_backtrace(unsigned show_nframes) {
strcpy(r, " (");
e = r + 2;
- for (j = 0; j < n; j++) {
+ for (j = s; j < n; j++) {
const char *sym;
- if (j > 0) {
+ if (j > s) {
strcpy(e, "<<");
e += 2;
}
@@ -229,6 +235,13 @@ static void init_defaults(void) {
if (show_backtrace_override <= 0)
show_backtrace_override = 0;
}
+
+ if ((e = getenv(ENV_LOG_BACKTRACE_SKIP))) {
+ skip_backtrace = (unsigned) atoi(e);
+
+ if (skip_backtrace <= 0)
+ skip_backtrace = 0;
+ }
}
void pa_log_levelv_meta(
diff --git a/src/pulsecore/log.h b/src/pulsecore/log.h
index 153e11e..8628bf4 100644
--- a/src/pulsecore/log.h
+++ b/src/pulsecore/log.h
@@ -77,6 +77,9 @@ void pa_log_set_flags(pa_log_flags_t flags, pa_log_merge_t merge);
/* Enable backtrace */
void pa_log_set_show_backtrace(unsigned nlevels);
+/* Skip the first backtrace frames */
+void pa_log_set_skip_backtrace(unsigned nlevels);
+
void pa_log_level_meta(
pa_log_level_t level,
const char*file,
commit c367a885dcaa6f935d11b9cbe2fd1e0dfbef3249
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 03:44:49 2009 +0100
fix misplace _ref() calls that should have been _assert_ref()
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 83d3992..a024471 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -562,7 +562,7 @@ static int esd_proto_get_latency(connection *c, esd_proto_t request, const void
pa_sink *sink;
int32_t latency;
- connection_ref(c);
+ connection_assert_ref(c);
pa_assert(!data);
pa_assert(length == 0);
@@ -575,6 +575,7 @@ static int esd_proto_get_latency(connection *c, esd_proto_t request, const void
latency = PA_MAYBE_INT32_SWAP(c->swap_byte_order, latency);
connection_write(c, &latency, sizeof(int32_t));
+
return 0;
}
@@ -583,7 +584,7 @@ static int esd_proto_server_info(connection *c, esd_proto_t request, const void
int32_t response;
pa_sink *sink;
- connection_ref(c);
+ connection_assert_ref(c);
pa_assert(data);
pa_assert(length == sizeof(int32_t));
@@ -611,7 +612,7 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da
unsigned nsamples;
char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
- connection_ref(c);
+ connection_assert_ref(c);
pa_assert(data);
pa_assert(length == sizeof(int32_t));
commit 8282efcfa3cbc5822ca03fce93c116bfd065d1f0
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 16:17:03 2009 +0100
fix value of DYNAMIC_LATENCY
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 8bcb691..9418e96 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -789,7 +789,7 @@ typedef enum pa_source_flags {
/**< Volume can be translated to dB with pa_sw_volume_to_dB()
* \since 0.9.11 */
- PA_SOURCE_DYNAMIC_LATENCY = 0x0080U
+ PA_SOURCE_DYNAMIC_LATENCY = 0x0040U
/**< The latency can be adjusted dynamically depending on the
* needs of the connected streams. \since 0.9.15 */
} pa_source_flags_t;
commit 4edb109239c746c6fb69aa15067c5a125aeefe22
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 16:17:45 2009 +0100
use u->use_tsched everywhere
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 3040582..7c09553 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1691,7 +1691,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
pa_sink_set_max_request(u->sink, u->hwbuf_size);
- if (use_tsched) {
+ if (u->use_tsched) {
fix_min_sleep_wakeup(u);
fix_tsched_watermark(u);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 4a535aa..dfd1870 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1541,7 +1541,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
nfrags, (long unsigned) u->fragment_size,
(double) pa_bytes_to_usec(u->hwbuf_size, &ss) / PA_USEC_PER_MSEC);
- if (use_tsched) {
+ if (u->use_tsched) {
fix_min_sleep_wakeup(u);
fix_tsched_watermark(u);
commit 2c1eaa75933d8e630e9ba3075aa3b7c5ff458873
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 16:30:28 2009 +0100
copy latency flags from sink to monitor source
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 68f8856..1fe8f59 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -260,7 +260,7 @@ pa_sink* pa_sink_new(
pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
- s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
+ s->monitor_source = pa_source_new(core, &source_data, 0);
pa_source_new_data_done(&source_data);
@@ -360,6 +360,12 @@ void pa_sink_put(pa_sink* s) {
if (s->flags & PA_SINK_DECIBEL_VOLUME)
s->flags |= PA_SINK_FLAT_VOLUME;
+ if (s->flags & PA_SINK_LATENCY)
+ s->monitor_source->flags |= PA_SOURCE_LATENCY;
+
+ if (s->flags & PA_SINK_DYNAMIC_LATENCY)
+ s->monitor_source->flags |= PA_SOURCE_DYNAMIC_LATENCY;
+
pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
pa_source_put(s->monitor_source);
commit 6defb1a6bf5c9e51354fc4c1efd3797c6b6b1ee0
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 16:30:46 2009 +0100
add missing whitespace
diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c
index 8d39dcf..324f83c 100644
--- a/src/pulsecore/cli-text.c
+++ b/src/pulsecore/cli-text.c
@@ -255,7 +255,7 @@ char *pa_sink_list_to_string(pa_core *c) {
sink->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
sink->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
sink->flags & PA_SINK_LATENCY ? "LATENCY " : "",
- sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME" : "",
+ sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "",
sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "",
sink_state_to_string(pa_sink_get_state(sink)),
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)),
commit 39576ec829b7576d4ab240526bc6cd76dae5c35b
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 16:31:16 2009 +0100
on monitor source be fine with any latency range set by the sink
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 5b4378a..1c3377b 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -1204,7 +1204,8 @@ void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_laten
/* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
max_latency == ABSOLUTE_MAX_LATENCY) ||
- (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
+ (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
+ s->monitor_of);
s->thread_info.min_latency = min_latency;
s->thread_info.max_latency = max_latency;
commit cbbd98635a5c3a1c73aa8f3423d2e78910981606
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 23:49:09 2009 +0100
make sure the discovery module is only loaded once
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index da0fe93..3288cc5 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -43,6 +43,7 @@ PA_MODULE_AUTHOR("Joao Paulo Rechi Vita");
PA_MODULE_DESCRIPTION("Detect available bluetooth audio devices and load bluetooth audio drivers");
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_USAGE("async=<Asynchronous initialization?>");
+PA_MODULE_LOAD_ONCE(TRUE);
/*
#ifdef NOKIA
commit 3813034cef15696f026c6426213999c8b55806bd
Author: Lennart Poettering <lennart at poettering.net>
Date: Wed Mar 25 23:49:26 2009 +0100
add missing initialization
diff --git a/src/pulsecore/card.c b/src/pulsecore/card.c
index f268f7c..8101a92 100644
--- a/src/pulsecore/card.c
+++ b/src/pulsecore/card.c
@@ -141,6 +141,7 @@ pa_card *pa_card_new(pa_core *core, pa_card_new_data *data) {
data->profiles = NULL;
c->active_profile = NULL;
+ c->save_profile = FALSE;
if (data->active_profile && c->profiles)
if ((c->active_profile = pa_hashmap_get(c->profiles, data->active_profile)))
commit 205cbe8afcf83ac7392b90ba8c73f40b798104c6
Author: Colin Guthrie <cguthrie at mandriva.org>
Date: Wed Mar 25 23:05:41 2009 +0000
raop: Add call to pa_sink_set_max_request()
This is just a copy from the ESD version which is a little crude, but will do for now.
diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c
index 00f0c63..d8ddf18 100644
--- a/src/modules/module-raop-sink.c
+++ b/src/modules/module-raop-sink.c
@@ -135,13 +135,22 @@ enum {
/* Forward declaration */
static void sink_set_volume_cb(pa_sink *);
-static void on_connection(PA_GCC_UNUSED int fd, void*userdata) {
+static void on_connection(int fd, void*userdata) {
+ int so_sndbuf = 0;
+ socklen_t sl = sizeof(int);
struct userdata *u = userdata;
pa_assert(u);
pa_assert(u->fd < 0);
u->fd = fd;
+ if (getsockopt(u->fd, SOL_SOCKET, SO_SNDBUF, &so_sndbuf, &sl) < 0)
+ pa_log_warn("getsockopt(SO_SNDBUF) failed: %s", pa_cstrerror(errno));
+ else {
+ pa_log_debug("SO_SNDBUF is %zu.", (size_t) so_sndbuf);
+ pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size));
+ }
+
/* Set the initial volume */
sink_set_volume_cb(u->sink);
commit f80a1f6d31a6b3c0c8266c67b12b9e292347fa8b
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date: Mon Mar 23 11:29:41 2009 -0300
Maintain the original code style for sbc.
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
index 42bae91..12d3737 100644
--- a/src/modules/bluetooth/sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -978,10 +978,8 @@ ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len)
return sbc_decode(sbc, input, input_len, NULL, 0, NULL);
}
-ssize_t sbc_decode(sbc_t *sbc,
- const void *input, size_t input_len,
- void *output, size_t output_len,
- size_t *written)
+ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
+ void *output, size_t output_len, size_t *written)
{
struct sbc_priv *priv;
char *ptr;
@@ -1046,10 +1044,8 @@ ssize_t sbc_decode(sbc_t *sbc,
return framelen;
}
-ssize_t sbc_encode(sbc_t *sbc,
- const void *input, size_t input_len,
- void *output, size_t output_len,
- size_t *written)
+ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
+ void *output, size_t output_len, size_t *written)
{
struct sbc_priv *priv;
int framelen, samples;
diff --git a/src/modules/bluetooth/sbc.h b/src/modules/bluetooth/sbc.h
index 9a7b4ce..6543588 100644
--- a/src/modules/bluetooth/sbc.h
+++ b/src/modules/bluetooth/sbc.h
@@ -85,16 +85,12 @@ int sbc_reinit(sbc_t *sbc, unsigned long flags);
ssize_t sbc_parse(sbc_t *sbc, const void *input, size_t input_len);
-ssize_t sbc_decode(sbc_t *sbc,
- const void *input, size_t input_len,
- void *output, size_t output_len,
- size_t *written);
+ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
+ void *output, size_t output_len, size_t *written);
/* Encodes ONE input block into ONE output block */
-ssize_t sbc_encode(sbc_t *sbc,
- const void *input, size_t input_len,
- void *output, size_t output_len,
- size_t *written);
+ssize_t sbc_encode(sbc_t *sbc, const void *input, size_t input_len,
+ void *output, size_t output_len, size_t *written);
/* Returns the output block size in bytes */
size_t sbc_get_frame_length(sbc_t *sbc);
commit b03c5458504ce186025e99570f6d2c8d3a6c0cef
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date: Mon Mar 23 11:46:08 2009 -0300
Fix misuse of 'frame.joint' when estimating the frame length.
'frame.joint' is not the flag for joint stereo mode, it is a set of bits which
show for which subbands channels joining was actually used.
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
index 12d3737..779be4b 100644
--- a/src/modules/bluetooth/sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -1004,7 +1004,7 @@ ssize_t sbc_decode(sbc_t *sbc, const void *input, size_t input_len,
sbc->bitpool = priv->frame.bitpool;
priv->frame.codesize = sbc_get_codesize(sbc);
- priv->frame.length = sbc_get_frame_length(sbc);
+ priv->frame.length = framelen;
}
if (!output)
@@ -1136,30 +1136,25 @@ void sbc_finish(sbc_t *sbc)
size_t sbc_get_frame_length(sbc_t *sbc)
{
size_t ret;
- uint8_t subbands, channels, blocks, joint;
+ uint8_t subbands, channels, blocks, joint, bitpool;
struct sbc_priv *priv;
priv = sbc->priv;
- if (!priv->init) {
- subbands = sbc->subbands ? 8 : 4;
- blocks = 4 + (sbc->blocks * 4);
- channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
- joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
- } else {
- subbands = priv->frame.subbands;
- blocks = priv->frame.blocks;
- channels = priv->frame.channels;
- joint = priv->frame.joint;
- }
+ if (priv->init)
+ return priv->frame.length;
- ret = 4 + (4 * subbands * channels) / 8;
+ subbands = sbc->subbands ? 8 : 4;
+ blocks = 4 + (sbc->blocks * 4);
+ channels = sbc->mode == SBC_MODE_MONO ? 1 : 2;
+ joint = sbc->mode == SBC_MODE_JOINT_STEREO ? 1 : 0;
+ bitpool = sbc->bitpool;
+ ret = 4 + (4 * subbands * channels) / 8;
/* This term is not always evenly divide so we round it up */
if (channels == 1)
- ret += ((blocks * channels * sbc->bitpool) + 7) / 8;
+ ret += ((blocks * channels * bitpool) + 7) / 8;
else
- ret += (((joint ? subbands : 0) + blocks * sbc->bitpool) + 7)
- / 8;
+ ret += (((joint ? subbands : 0) + blocks * bitpool) + 7) / 8;
return ret;
}
commit 071b3e7fc5a89ddc1c7d51ca5854aa661e4cc33b
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date: Wed Mar 25 17:57:19 2009 -0300
Update ipc to match new message headers introduced on BlueZ 4.34.
diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c
index f14c92c..dcecad8 100644
--- a/src/modules/bluetooth/ipc.c
+++ b/src/modules/bluetooth/ipc.c
@@ -35,6 +35,7 @@ static const char *strtypes[] = {
/* This table contains the string representation for messages names */
static const char *strnames[] = {
"BT_GET_CAPABILITIES",
+ "BT_OPEN",
"BT_SET_CONFIGURATION",
"BT_NEW_STREAM",
"BT_START_STREAM",
diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h
index f030acf..2e170f5 100644
--- a/src/modules/bluetooth/ipc.h
+++ b/src/modules/bluetooth/ipc.h
@@ -71,7 +71,7 @@ extern "C" {
#include <sys/un.h>
#include <errno.h>
-#define BT_SUGGESTED_BUFFER_SIZE 128
+#define BT_SUGGESTED_BUFFER_SIZE 512
#define BT_IPC_SOCKET_NAME "\0/org/bluez/audio"
/* Generic message header definition, except for RESPONSE messages */
@@ -94,10 +94,12 @@ typedef struct {
/* Messages names */
#define BT_GET_CAPABILITIES 0
-#define BT_SET_CONFIGURATION 1
-#define BT_NEW_STREAM 2
-#define BT_START_STREAM 3
-#define BT_STOP_STREAM 4
+#define BT_OPEN 1
+#define BT_SET_CONFIGURATION 2
+#define BT_NEW_STREAM 3
+#define BT_START_STREAM 4
+#define BT_STOP_STREAM 5
+#define BT_CLOSE 6
#define BT_CONTROL 7
#define BT_CAPABILITIES_TRANSPORT_A2DP 0
@@ -112,19 +114,31 @@ typedef struct {
struct bt_get_capabilities_req {
bt_audio_msg_header_t h;
- char device[18]; /* Address of the remote Device */
+ char source[18]; /* Address of the local Device */
+ char destination[18];/* Address of the remote Device */
+ char object[128]; /* DBus object path */
uint8_t transport; /* Requested transport */
uint8_t flags; /* Requested flags */
+ uint8_t seid; /* Requested capability configuration */
} __attribute__ ((packed));
/**
- * SBC Codec parameters as per A2DP profile 1.0 ç 4.3
+ * SBC Codec parameters as per A2DP profile 1.0 § 4.3
*/
-#define BT_A2DP_CODEC_SBC 0x00
-#define BT_A2DP_CODEC_MPEG12 0x01
-#define BT_A2DP_CODEC_MPEG24 0x02
-#define BT_A2DP_CODEC_ATRAC 0x03
+/* A2DP seid are 6 bytes long so HSP/HFP are assigned to 7-8 bits */
+#define BT_A2DP_SEID_RANGE (1 << 6) - 1
+
+#define BT_A2DP_SBC_SOURCE 0x00
+#define BT_A2DP_SBC_SINK 0x01
+#define BT_A2DP_MPEG12_SOURCE 0x02
+#define BT_A2DP_MPEG12_SINK 0x03
+#define BT_A2DP_MPEG24_SOURCE 0x04
+#define BT_A2DP_MPEG24_SINK 0x05
+#define BT_A2DP_ATRAC_SOURCE 0x06
+#define BT_A2DP_ATRAC_SINK 0x07
+#define BT_A2DP_UNKNOWN_SOURCE 0x08
+#define BT_A2DP_UNKNOWN_SINK 0x09
#define BT_SBC_SAMPLING_FREQ_16000 (1 << 3)
#define BT_SBC_SAMPLING_FREQ_32000 (1 << 2)
@@ -163,10 +177,16 @@ struct bt_get_capabilities_req {
#define BT_PCM_FLAG_NREC 0x01
#define BT_PCM_FLAG_PCM_ROUTING 0x02
+#define BT_WRITE_LOCK (1 << 1)
+#define BT_READ_LOCK 1
+
typedef struct {
+ uint8_t seid;
uint8_t transport;
uint8_t type;
uint8_t length;
+ uint8_t configured;
+ uint8_t lock;
uint8_t data[0];
} __attribute__ ((packed)) codec_capabilities_t;
@@ -199,20 +219,35 @@ typedef struct {
struct bt_get_capabilities_rsp {
bt_audio_msg_header_t h;
+ char source[18]; /* Address of the local Device */
+ char destination[18];/* Address of the remote Device */
+ char object[128]; /* DBus object path */
uint8_t data[0]; /* First codec_capabilities_t */
} __attribute__ ((packed));
+struct bt_open_req {
+ bt_audio_msg_header_t h;
+ char source[18]; /* Address of the local Device */
+ char destination[18];/* Address of the remote Device */
+ char object[128]; /* DBus object path */
+ uint8_t seid; /* Requested capability configuration to lock */
+ uint8_t lock; /* Requested lock */
+} __attribute__ ((packed));
+
+struct bt_open_rsp {
+ bt_audio_msg_header_t h;
+ char source[18]; /* Address of the local Device */
+ char destination[18];/* Address of the remote Device */
+ char object[128]; /* DBus object path */
+} __attribute__ ((packed));
+
struct bt_set_configuration_req {
bt_audio_msg_header_t h;
- char device[18]; /* Address of the remote Device */
- uint8_t access_mode; /* Requested access mode */
codec_capabilities_t codec; /* Requested codec */
} __attribute__ ((packed));
struct bt_set_configuration_rsp {
bt_audio_msg_header_t h;
- uint8_t transport; /* Granted transport */
- uint8_t access_mode; /* Granted access mode */
uint16_t link_mtu; /* Max length that transport supports */
} __attribute__ ((packed));
@@ -241,6 +276,14 @@ struct bt_stop_stream_rsp {
bt_audio_msg_header_t h;
} __attribute__ ((packed));
+struct bt_close_req {
+ bt_audio_msg_header_t h;
+} __attribute__ ((packed));
+
+struct bt_close_rsp {
+ bt_audio_msg_header_t h;
+} __attribute__ ((packed));
+
struct bt_suspend_stream_ind {
bt_audio_msg_header_t h;
} __attribute__ ((packed));
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2500fb0..d09dc2c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -311,7 +311,7 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
} else if (u->profile == PROFILE_A2DP) {
while (bytes_left > 0) {
- if (codec->type == BT_A2DP_CODEC_SBC)
+ if ((codec->type == BT_A2DP_SBC_SINK) && !codec->lock)
break;
bytes_left -= codec->length;
@@ -321,7 +321,7 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
if (bytes_left <= 0 || codec->length != sizeof(u->a2dp.sbc_capabilities))
return -1;
- pa_assert(codec->type == BT_A2DP_CODEC_SBC);
+ pa_assert(codec->type == BT_A2DP_SBC_SINK);
memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
}
@@ -344,7 +344,7 @@ static int get_caps(struct userdata *u) {
msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
- pa_strlcpy(msg.getcaps_req.device, u->address, sizeof(msg.getcaps_req.device));
+ pa_strlcpy(msg.getcaps_req.object, u->path, sizeof(msg.getcaps_req.object));
if (u->profile == PROFILE_A2DP)
msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_A2DP;
else {
@@ -602,12 +602,29 @@ static void setup_sbc(struct a2dp_info *a2dp) {
static int set_conf(struct userdata *u) {
union {
+ struct bt_open_req open_req;
+ struct bt_open_rsp open_rsp;
struct bt_set_configuration_req setconf_req;
struct bt_set_configuration_rsp setconf_rsp;
bt_audio_error_t error;
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
} msg;
+ memset(&msg, 0, sizeof(msg));
+ msg.open_req.h.type = BT_REQUEST;
+ msg.open_req.h.name = BT_OPEN;
+ msg.open_req.h.length = sizeof(msg.open_req);
+
+ pa_strlcpy(msg.open_req.object, u->path, sizeof(msg.open_req.object));
+ msg.open_req.seid = u->profile == PROFILE_A2DP ? u->a2dp.sbc_capabilities.capability.seid : BT_A2DP_SEID_RANGE + 1;
+ msg.open_req.lock = u->profile == PROFILE_A2DP ? BT_WRITE_LOCK : BT_READ_LOCK | BT_WRITE_LOCK;
+
+ if (service_send(u, &msg.open_req.h) < 0)
+ return -1;
+
+ if (service_expect(u, &msg.open_rsp.h, sizeof(msg), BT_OPEN, sizeof(msg.open_rsp)) < 0)
+ return -1;
+
if (u->profile == PROFILE_A2DP ) {
u->sample_spec.format = PA_SAMPLE_S16LE;
@@ -626,15 +643,14 @@ static int set_conf(struct userdata *u) {
msg.setconf_req.h.name = BT_SET_CONFIGURATION;
msg.setconf_req.h.length = sizeof(msg.setconf_req);
- pa_strlcpy(msg.setconf_req.device, u->address, sizeof(msg.setconf_req.device));
- msg.setconf_req.access_mode = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_ACCESS_MODE_WRITE : BT_CAPABILITIES_ACCESS_MODE_READWRITE;
-
- msg.setconf_req.codec.transport = u->profile == PROFILE_A2DP ? BT_CAPABILITIES_TRANSPORT_A2DP : BT_CAPABILITIES_TRANSPORT_SCO;
-
if (u->profile == PROFILE_A2DP) {
memcpy(&msg.setconf_req.codec, &u->a2dp.sbc_capabilities, sizeof(u->a2dp.sbc_capabilities));
- msg.setconf_req.h.length += msg.setconf_req.codec.length - sizeof(msg.setconf_req.codec);
+ } else {
+ msg.setconf_req.codec.transport = BT_CAPABILITIES_TRANSPORT_SCO;
+ msg.setconf_req.codec.seid = BT_A2DP_SEID_RANGE + 1;
+ msg.setconf_req.codec.length = sizeof(pcm_capabilities_t);
}
+ msg.setconf_req.h.length += msg.setconf_req.codec.length - sizeof(msg.setconf_req.codec);
if (service_send(u, &msg.setconf_req.h) < 0)
return -1;
@@ -642,18 +658,6 @@ static int set_conf(struct userdata *u) {
if (service_expect(u, &msg.setconf_rsp.h, sizeof(msg), BT_SET_CONFIGURATION, sizeof(msg.setconf_rsp)) < 0)
return -1;
- if ((u->profile == PROFILE_A2DP && msg.setconf_rsp.transport != BT_CAPABILITIES_TRANSPORT_A2DP) ||
- (u->profile == PROFILE_HSP && msg.setconf_rsp.transport != BT_CAPABILITIES_TRANSPORT_SCO)) {
- pa_log("Transport doesn't match what we requested.");
- return -1;
- }
-
- if ((u->profile == PROFILE_A2DP && msg.setconf_rsp.access_mode != BT_CAPABILITIES_ACCESS_MODE_WRITE) ||
- (u->profile == PROFILE_HSP && msg.setconf_rsp.access_mode != BT_CAPABILITIES_ACCESS_MODE_READWRITE)) {
- pa_log("Access mode doesn't match what we requested.");
- return -1;
- }
-
u->link_mtu = msg.setconf_rsp.link_mtu;
/* setup SBC encoder now we agree on parameters */
commit 168c741b644a1134bc7c2ca51adb094ec736c160
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date: Tue Mar 24 12:04:52 2009 -0300
Query and make use of the current configuration.
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index d09dc2c..bcb65a4 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -275,7 +275,7 @@ static ssize_t service_expect(struct userdata*u, bt_audio_msg_header_t *rsp, siz
return 0;
}
-static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *rsp) {
+static int parse_caps(struct userdata *u, uint8_t seid, const struct bt_get_capabilities_rsp *rsp) {
uint16_t bytes_left;
const codec_capabilities_t *codec;
@@ -306,6 +306,9 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
pa_assert(codec->type == BT_HFP_CODEC_PCM);
+ if (codec->configured && seid == 0)
+ return codec->seid;
+
memcpy(&u->hsp.pcm_capabilities, codec, sizeof(u->hsp.pcm_capabilities));
} else if (u->profile == PROFILE_A2DP) {
@@ -323,19 +326,23 @@ static int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *
pa_assert(codec->type == BT_A2DP_SBC_SINK);
+ if (codec->configured && seid == 0)
+ return codec->seid;
+
memcpy(&u->a2dp.sbc_capabilities, codec, sizeof(u->a2dp.sbc_capabilities));
}
return 0;
}
-static int get_caps(struct userdata *u) {
+static int get_caps(struct userdata *u, uint8_t seid) {
union {
struct bt_get_capabilities_req getcaps_req;
struct bt_get_capabilities_rsp getcaps_rsp;
bt_audio_error_t error;
uint8_t buf[BT_SUGGESTED_BUFFER_SIZE];
} msg;
+ int ret;
pa_assert(u);
@@ -343,6 +350,7 @@ static int get_caps(struct userdata *u) {
msg.getcaps_req.h.type = BT_REQUEST;
msg.getcaps_req.h.name = BT_GET_CAPABILITIES;
msg.getcaps_req.h.length = sizeof(msg.getcaps_req);
+ msg.getcaps_req.seid = seid;
pa_strlcpy(msg.getcaps_req.object, u->path, sizeof(msg.getcaps_req.object));
if (u->profile == PROFILE_A2DP)
@@ -359,7 +367,11 @@ static int get_caps(struct userdata *u) {
if (service_expect(u, &msg.getcaps_rsp.h, sizeof(msg), BT_GET_CAPABILITIES, 0) < 0)
return -1;
- return parse_caps(u, &msg.getcaps_rsp);
+ ret = parse_caps(u, seid, &msg.getcaps_rsp);
+ if (ret <= 0)
+ return ret;
+
+ return get_caps(u, ret);
}
static uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) {
@@ -1575,7 +1587,7 @@ static int init_bt(struct userdata *u) {
static int setup_bt(struct userdata *u) {
pa_assert(u);
- if (get_caps(u) < 0)
+ if (get_caps(u, 0) < 0)
return -1;
pa_log_debug("Got device capabilities");
commit 13f1c4413b54489d8ff7ddbbd8d36de26049e12d
Author: Luiz Augusto von Dentz <luiz.dentz at openbossa.org>
Date: Thu Mar 26 15:38:40 2009 -0300
Do not reconfigure capabilities.
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index bcb65a4..0a3c91a 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -462,6 +462,9 @@ static int setup_a2dp(struct userdata *u) {
}
}
+ if (cap->capability.configured)
+ return 0;
+
if (u->sample_spec.channels <= 1) {
if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) {
cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;
commit db714bfea6ccf7be887ddf1f41b084433304fd9d
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 27 00:06:15 2009 +0100
fix typo
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index d4d407c..4017cb6 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -175,7 +175,7 @@ static const struct command commands[] = {
{ "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},
- { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (aargs: index, name)", 3},
+ { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index, name)", 3},
{ "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
{ "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
{ "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
commit 87d63b19a3f35650536c3595cf89145d61a052ca
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Mar 27 14:37:58 2009 +0100
Small fix for MacOSX compat
Issue originally pointed out by Igor Zubkov.
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 0d243ee..e5d8a2f 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2617,7 +2617,7 @@ char *pa_realpath(const char *path) {
return NULL;
}
-#ifndef __GLIBC__
+#if !defined(__GLIBC__) && !defined(__APPLE__)
#error "It's not clear whether this system supports realpath(..., NULL) like GNU libc does. If it doesn't we need a private version of realpath() here."
#endif
commit 62a4e36f5d136211599a02eff648d6ca2045d539
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Tue Mar 24 14:07:51 2009 +0200
bluetooth: connected can be -1, check > 0
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 3288cc5..49c7a80 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -93,7 +93,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
/* Oh, awesome, a new device has shown up and been connected! */
- args = pa_sprintf_malloc("address=\"%s\" path=\"%s\" profile=\"%s\"", d->address, d->path, d->headset_connected ? "hsp" : "a2dp");
+ args = pa_sprintf_malloc("address=\"%s\" path=\"%s\" profile=\"%s\"", d->address, d->path, d->headset_connected > 0 ? "hsp" : "a2dp");
#ifdef NOKIA
if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) &&
commit 61cd6d4c19f77e560cec4325061efe4723816481
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Tue Mar 24 14:38:52 2009 +0200
bluetooth: fail when switching on non-connected profile
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 0a3c91a..4c1f1c3 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -133,6 +133,7 @@ struct userdata {
char *address;
char *path;
+ const pa_bluetooth_device* device;
pa_dbus_connection *connection;
@@ -1733,6 +1734,15 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
d = PA_CARD_PROFILE_DATA(new_profile);
+ if (u->device->headset_connected <= 0 && *d == PROFILE_HSP) {
+ pa_log_warn("HSP is not connected, refused to switch profile");
+ return -1;
+ }
+ else if (u->device->audio_sink_connected <= 0 && *d == PROFILE_A2DP) {
+ pa_log_warn("A2DP is not connected, refused to switch profile");
+ return -1;
+ }
+
if (u->sink) {
inputs = pa_sink_move_all_start(u->sink);
#ifdef NOKIA
@@ -1926,7 +1936,6 @@ int pa__init(pa_module* m) {
uint32_t channels;
struct userdata *u;
const char *address, *path;
- const pa_bluetooth_device *d;
pa_bluetooth_discovery *y = NULL;
DBusError err;
char *mike, *speaker;
@@ -1987,11 +1996,11 @@ int pa__init(pa_module* m) {
if (!(y = pa_bluetooth_discovery_get(m->core)))
goto fail;
- if (!(d = find_device(u, y, address, path)))
+ if (!(u->device = find_device(u, y, address, path))) /* should discovery ref be kept? */
goto fail;
/* Add the card structure. This will also initialize the default profile */
- if (add_card(u, pa_modargs_get_value(ma, "profile", NULL), d) < 0)
+ if (add_card(u, pa_modargs_get_value(ma, "profile", NULL), u->device) < 0)
goto fail;
pa_bluetooth_discovery_unref(y);
commit 9e8c2d393a6e2ef8ceda58ff3db6c3a7a7223d46
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Thu Mar 26 21:31:12 2009 +0200
bluetooth: don't access outside array range
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 4c1f1c3..2c4f29c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -448,8 +448,8 @@ static int setup_a2dp(struct userdata *u) {
break;
}
- if ((unsigned) i >= PA_ELEMENTSOF(freq_table)) {
- for (; i >= 0; i--) {
+ if ((unsigned) i == PA_ELEMENTSOF(freq_table)) {
+ for (--i; i >= 0; i--) {
if (cap->frequency & freq_table[i].cap) {
u->sample_spec.rate = freq_table[i].rate;
cap->frequency = freq_table[i].cap;
@@ -463,6 +463,8 @@ static int setup_a2dp(struct userdata *u) {
}
}
+ pa_assert(i < PA_ELEMENTSOF(freq_table));
+
if (cap->capability.configured)
return 0;
commit 20bd1c686ca3facb647db7189470ab1bcdae48b5
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 27 13:43:32 2009 +0200
bluetooth: remove racy GetProperties to check profile
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 3dfc65e..3d410c5 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -401,12 +401,6 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Headset", "GetProperties"));
- send_and_add_to_pending(y, d, m, get_properties_reply);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.AudioSink", "GetProperties"));
- send_and_add_to_pending(y, d, m, get_properties_reply);
}
static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
commit 38825d79123678bf0c5d156aaea4bedb888a7fcd
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 27 13:56:26 2009 +0200
bluetooth: GetProperties after profile UUID show up
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 3d410c5..dfebf66 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -39,6 +39,9 @@ struct pa_bluetooth_discovery {
pa_hook hook;
};
+static void get_properties_reply(DBusPendingCall *pending, void *userdata);
+static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func);
+
static pa_bluetooth_uuid *uuid_new(const char *uuid) {
pa_bluetooth_uuid *u;
@@ -213,11 +216,20 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device
while (dbus_message_iter_get_arg_type(&ai) != DBUS_TYPE_INVALID) {
pa_bluetooth_uuid *node;
const char *value;
+ DBusMessage *m;
dbus_message_iter_get_basic(&ai, &value);
node = uuid_new(value);
PA_LLIST_PREPEND(pa_bluetooth_uuid, d->uuids, node);
+ if (strcasecmp(HSP_HS_UUID, value) == 0 || strcasecmp(HFP_HS_UUID, value) == 0) {
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Headset", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
+ } else if (strcasecmp(A2DP_SINK_UUID, value) == 0) {
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.AudioSink", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
+ }
+
if (!dbus_message_iter_next(&ai))
break;
}
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 1d05e63..57f1172 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -28,6 +28,20 @@
#include <pulsecore/macro.h>
#include <pulsecore/core-util.h>
+/* UUID copied from bluez/audio/device.h */
+#define GENERIC_AUDIO_UUID "00001203-0000-1000-8000-00805F9B34FB"
+
+#define HSP_HS_UUID "00001108-0000-1000-8000-00805F9B34FB"
+#define HSP_AG_UUID "00001112-0000-1000-8000-00805F9B34FB"
+
+#define HFP_HS_UUID "0000111E-0000-1000-8000-00805F9B34FB"
+#define HFP_AG_UUID "0000111F-0000-1000-8000-00805F9B34FB"
+
+#define ADVANCED_AUDIO_UUID "0000110D-0000-1000-8000-00805F9B34FB"
+
+#define A2DP_SOURCE_UUID "0000110A-0000-1000-8000-00805F9B34FB"
+#define A2DP_SINK_UUID "0000110B-0000-1000-8000-00805F9B34FB"
+
typedef struct pa_bluetooth_uuid pa_bluetooth_uuid;
typedef struct pa_bluetooth_device pa_bluetooth_device;
typedef struct pa_bluetooth_discovery pa_bluetooth_discovery;
commit 87fcb3d5925cc030e957f55399f8c3e96c66cbb5
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 27 21:48:04 2009 +0200
bluetooth: use new audio State properties
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index dfebf66..771afff 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -42,6 +42,22 @@ struct pa_bluetooth_discovery {
static void get_properties_reply(DBusPendingCall *pending, void *userdata);
static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func);
+static enum pa_bt_audio_state pa_bt_audio_state_from_string(const char* value) {
+ pa_assert(value);
+
+ if (pa_streq(value, "disconnected")) {
+ return PA_BT_AUDIO_STATE_DISCONNECTED;
+ } else if (pa_streq(value, "connecting")) {
+ return PA_BT_AUDIO_STATE_CONNECTING;
+ } else if (pa_streq(value, "connected")) {
+ return PA_BT_AUDIO_STATE_CONNECTED;
+ } else if (pa_streq(value, "playing")) {
+ return PA_BT_AUDIO_STATE_PLAYING;
+ }
+
+ return PA_BT_AUDIO_STATE_INVALID;
+}
+
static pa_bluetooth_uuid *uuid_new(const char *uuid) {
pa_bluetooth_uuid *u;
@@ -66,7 +82,7 @@ static pa_bluetooth_device* device_new(const char *path) {
d->dead = FALSE;
- d->device_info_valid = d->audio_sink_info_valid = d->headset_info_valid = 0;
+ d->device_info_valid = 0;
d->name = NULL;
d->path = pa_xstrdup(path);
@@ -78,9 +94,9 @@ static pa_bluetooth_device* device_new(const char *path) {
d->class = -1;
d->trusted = -1;
- d->audio_sink_connected = -1;
-
- d->headset_connected = -1;
+ d->audio_state = PA_BT_AUDIO_STATE_INVALID;
+ d->audio_sink_state = PA_BT_AUDIO_STATE_INVALID;
+ d->headset_state = PA_BT_AUDIO_STATE_INVALID;
return d;
}
@@ -102,25 +118,14 @@ static void device_free(pa_bluetooth_device *d) {
pa_xfree(d);
}
-static pa_bool_t device_is_loaded(pa_bluetooth_device *d) {
- pa_assert(d);
-
- return
- d->device_info_valid &&
- d->audio_sink_info_valid &&
- d->headset_info_valid;
-}
-
static pa_bool_t device_is_audio(pa_bluetooth_device *d) {
pa_assert(d);
- pa_assert(d->device_info_valid);
- pa_assert(d->audio_sink_info_valid);
- pa_assert(d->headset_info_valid);
-
return
- d->device_info_valid > 0 &&
- (d->audio_sink_info_valid > 0 || d->headset_info_valid > 0);
+ d->device_info_valid &&
+ (d->audio_state != PA_BT_AUDIO_STATE_INVALID ||
+ d->audio_sink_state != PA_BT_AUDIO_STATE_INVALID ||
+ d->headset_state != PA_BT_AUDIO_STATE_INVALID);
}
static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessageIter *i) {
@@ -222,6 +227,11 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device
node = uuid_new(value);
PA_LLIST_PREPEND(pa_bluetooth_uuid, d->uuids, node);
+ /* this might eventually be racy if .Audio is not there yet, but the State change will come anyway later, so this call is for cold-detection mostly */
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Audio", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
+
+ /* Vudentz said the interfaces are here when the UUIDs are announced */
if (strcasecmp(HSP_HS_UUID, value) == 0 || strcasecmp(HFP_HS_UUID, value) == 0) {
pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->path, "org.bluez.Headset", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
@@ -242,12 +252,12 @@ static int parse_device_property(pa_bluetooth_discovery *y, pa_bluetooth_device
return 0;
}
-static int parse_audio_property(pa_bluetooth_discovery *u, int *connected, DBusMessageIter *i) {
+static int parse_audio_property(pa_bluetooth_discovery *u, int *state, DBusMessageIter *i) {
const char *key;
DBusMessageIter variant_i;
pa_assert(u);
- pa_assert(connected);
+ pa_assert(state);
pa_assert(i);
if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_STRING) {
@@ -269,17 +279,27 @@ static int parse_audio_property(pa_bluetooth_discovery *u, int *connected, DBusM
dbus_message_iter_recurse(i, &variant_i);
-/* pa_log_debug("Parsing property org.bluez.{AudioSink|Headset}.%s", key); */
+/* pa_log_debug("Parsing property org.bluez.{Audio|AudioSink|Headset}.%s", key); */
switch (dbus_message_iter_get_arg_type(&variant_i)) {
+ case DBUS_TYPE_STRING: {
+
+ const char *value;
+ dbus_message_iter_get_basic(&variant_i, &value);
+
+ if (pa_streq(key, "State"))
+ *state = pa_bt_audio_state_from_string(value);
+/* pa_log_debug("Value %s", value); */
+ }
+
case DBUS_TYPE_BOOLEAN: {
dbus_bool_t value;
dbus_message_iter_get_basic(&variant_i, &value);
- if (pa_streq(key, "Connected"))
- *connected = !!value;
+ /* if (pa_streq(key, "Connected")) */
+ /* *connected = !!value; */
/* pa_log_debug("Value %s", pa_yes_no(value)); */
@@ -294,9 +314,6 @@ static void run_callback(pa_bluetooth_discovery *y, pa_bluetooth_device *d, pa_b
pa_assert(y);
pa_assert(d);
- if (!device_is_loaded(d))
- return;
-
if (!device_is_audio(d))
return;
@@ -326,10 +343,6 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
if (dbus_message_is_method_call(p->message, "org.bluez.Device", "GetProperties"))
d->device_info_valid = valid;
- else if (dbus_message_is_method_call(p->message, "org.bluez.Headset", "GetProperties"))
- d->headset_info_valid = valid;
- else if (dbus_message_is_method_call(p->message, "org.bluez.AudioSink", "GetProperties"))
- d->audio_sink_info_valid = valid;
if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
@@ -361,12 +374,16 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
if (parse_device_property(y, d, &dict_i) < 0)
goto finish;
+ } else if (dbus_message_has_interface(p->message, "org.bluez.Audio")) {
+ if (parse_audio_property(y, &d->audio_state, &dict_i) < 0)
+ goto finish;
+
} else if (dbus_message_has_interface(p->message, "org.bluez.Headset")) {
- if (parse_audio_property(y, &d->headset_connected, &dict_i) < 0)
+ if (parse_audio_property(y, &d->headset_state, &dict_i) < 0)
goto finish;
} else if (dbus_message_has_interface(p->message, "org.bluez.AudioSink")) {
- if (parse_audio_property(y, &d->audio_sink_connected, &dict_i) < 0)
+ if (parse_audio_property(y, &d->audio_sink_state, &dict_i) < 0)
goto finish;
}
}
@@ -572,7 +589,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
found_adapter(y, path);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- } else if (dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") ||
+ } else if (dbus_message_is_signal(m, "org.bluez.Audio", "PropertyChanged") ||
+ dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged") ||
dbus_message_is_signal(m, "org.bluez.AudioSink", "PropertyChanged") ||
dbus_message_is_signal(m, "org.bluez.Device", "PropertyChanged")) {
@@ -590,12 +608,16 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
if (parse_device_property(y, d, &arg_i) < 0)
goto fail;
+ } else if (dbus_message_has_interface(m, "org.bluez.Audio")) {
+ if (parse_audio_property(y, &d->audio_state, &arg_i) < 0)
+ goto fail;
+
} else if (dbus_message_has_interface(m, "org.bluez.Headset")) {
- if (parse_audio_property(y, &d->headset_connected, &arg_i) < 0)
+ if (parse_audio_property(y, &d->headset_state, &arg_i) < 0)
goto fail;
} else if (dbus_message_has_interface(m, "org.bluez.AudioSink")) {
- if (parse_audio_property(y, &d->audio_sink_connected, &arg_i) < 0)
+ if (parse_audio_property(y, &d->audio_sink_state, &arg_i) < 0)
goto fail;
}
@@ -690,6 +712,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'",
+ "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", NULL) < 0) {
pa_log("Failed to add D-Bus matches: %s", err.message);
@@ -746,6 +769,7 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceRemoved'",
"type='signal',sender='org.bluez',interface='org.bluez.Adapter',member='DeviceCreated'",
"type='signal',sender='org.bluez',interface='org.bluez.Device',member='PropertyChanged'",
+ "type='signal',sender='org.bluez',interface='org.bluez.Audio',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
"type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'", NULL);
@@ -833,3 +857,16 @@ char *pa_bluetooth_cleanup_name(const char *name) {
return t;
}
+
+pa_bool_t pa_bluetooth_uuid_has(pa_bluetooth_uuid *uuids, const char *uuid) {
+ pa_assert(uuid);
+
+ while (uuids) {
+ if (strcasecmp(uuids->uuid, uuid) == 0)
+ return TRUE;
+
+ uuids = uuids->next;
+ }
+
+ return FALSE;
+}
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 57f1172..5411473 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -53,12 +53,20 @@ struct pa_bluetooth_uuid {
PA_LLIST_FIELDS(pa_bluetooth_uuid);
};
+/* This enum is shared among Audio, Headset, and AudioSink, although not all values are acceptable in all profiles */
+enum pa_bt_audio_state {
+ PA_BT_AUDIO_STATE_INVALID = -1,
+ PA_BT_AUDIO_STATE_DISCONNECTED,
+ PA_BT_AUDIO_STATE_CONNECTING,
+ PA_BT_AUDIO_STATE_CONNECTED,
+ PA_BT_AUDIO_STATE_PLAYING,
+ PA_BT_AUDIO_STATE_LAST
+};
+
struct pa_bluetooth_device {
pa_bool_t dead;
int device_info_valid; /* 0: no results yet; 1: good results; -1: bad results ... */
- int audio_sink_info_valid; /* ... same here ... */
- int headset_info_valid; /* ... and here */
/* Device information */
char *name;
@@ -71,11 +79,14 @@ struct pa_bluetooth_device {
int class;
int trusted;
- /* AudioSink information */
- int audio_sink_connected;
+ /* Audio state */
+ int audio_state;
- /* Headset information */
- int headset_connected;
+ /* AudioSink state */
+ int audio_sink_state;
+
+ /* Headset state */
+ int headset_state;
};
pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core);
@@ -93,4 +104,6 @@ const char* pa_bluetooth_get_form_factor(uint32_t class);
char *pa_bluetooth_cleanup_name(const char *name);
+pa_bool_t pa_bluetooth_uuid_has(pa_bluetooth_uuid *uuids, const char *uuid);
+
#endif
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2c4f29c..9fc1531 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1736,11 +1736,11 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
d = PA_CARD_PROFILE_DATA(new_profile);
- if (u->device->headset_connected <= 0 && *d == PROFILE_HSP) {
+ if (u->device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
pa_log_warn("HSP is not connected, refused to switch profile");
return -1;
}
- else if (u->device->audio_sink_connected <= 0 && *d == PROFILE_A2DP) {
+ else if (u->device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
pa_log_warn("A2DP is not connected, refused to switch profile");
return -1;
}
@@ -1821,7 +1821,11 @@ static int add_card(struct userdata *u, const char *default_profile, const pa_bl
data.profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- if (device->audio_sink_info_valid > 0) {
+ /* we base hsp/a2dp availability on UUIDs.
+ Ideally, it would be based on "Connected" state, but
+ we can't afford to wait for this information when
+ we are loaded with profile="hsp", for instance */
+ if (pa_bluetooth_uuid_has(device->uuids, A2DP_SINK_UUID)) {
p = pa_card_profile_new("a2dp", _("High Fidelity Playback (A2DP)"), sizeof(enum profile));
p->priority = 10;
p->n_sinks = 1;
@@ -1835,7 +1839,8 @@ static int add_card(struct userdata *u, const char *default_profile, const pa_bl
pa_hashmap_put(data.profiles, p->name, p);
}
- if (device->headset_info_valid > 0) {
+ if (pa_bluetooth_uuid_has(device->uuids, HSP_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;
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 49c7a80..6f3dba1 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -84,8 +84,7 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
mi = pa_hashmap_get(u->hashmap, d->path);
if (!d->dead &&
- d->device_connected > 0 &&
- (d->audio_sink_connected > 0 || d->headset_connected > 0)) {
+ d->device_connected > 0 && d->audio_state >= PA_BT_AUDIO_STATE_CONNECTED) {
if (!mi) {
pa_module *m = NULL;
@@ -93,7 +92,16 @@ static pa_hook_result_t load_module_for_device(pa_bluetooth_discovery *y, const
/* Oh, awesome, a new device has shown up and been connected! */
- args = pa_sprintf_malloc("address=\"%s\" path=\"%s\" profile=\"%s\"", d->address, d->path, d->headset_connected > 0 ? "hsp" : "a2dp");
+ args = pa_sprintf_malloc("address=\"%s\" path=\"%s\"", d->address, d->path);
+#if 0
+ /* This is in case we have to use hsp immediately, without waiting for .Audio.State = Connected */
+ if (d->headset_state >= PA_BT_AUDIO_STATE_CONNECTED && somecondition) {
+ char *tmp;
+ tmp = pa_sprintf_malloc("%s profile=\"hsp\"", args);
+ pa_xfree(args);
+ args = tmp;
+ }
+#endif
#ifdef NOKIA
if (pa_modargs_get_value(u->modargs, "sco_sink", NULL) &&
commit e3f15104cf0386a0e0a782037e8c0323629be749
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:00:23 2009 +0200
don't enabled tsched on software ALSA devices
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 7c09553..0296f64 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1630,6 +1630,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
u->use_tsched = use_tsched = FALSE;
}
+ if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
+ pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
+ u->use_tsched = use_tsched = FALSE;
+ }
+
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index dfd1870..ef365a2 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1482,6 +1482,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
u->use_tsched = use_tsched = FALSE;
}
+ if (use_tsched && !pa_alsa_pcm_is_hw(u->pcm_handle)) {
+ pa_log_info("Device is not a hardware device, disabling timer-based scheduling.");
+ u->use_tsched = use_tsched = FALSE;
+ }
+
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 3f26aeb..2d0ca10 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1716,10 +1716,11 @@ char *pa_alsa_get_driver_name(int card) {
char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm) {
int card;
-
snd_pcm_info_t* info;
snd_pcm_info_alloca(&info);
+ pa_assert(pcm);
+
if (snd_pcm_info(pcm, info) < 0)
return NULL;
@@ -1749,3 +1750,15 @@ char *pa_alsa_get_reserve_name(const char *device) {
return pa_sprintf_malloc("Audio%i", i);
}
+
+pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
+ snd_pcm_info_t* info;
+ snd_pcm_info_alloca(&info);
+
+ pa_assert(pcm);
+
+ if (snd_pcm_info(pcm, info) < 0)
+ return FALSE;
+
+ return snd_pcm_info_get_card(info) >= 0;
+}
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index fe0f71e..68496d5 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -139,4 +139,6 @@ char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
char *pa_alsa_get_reserve_name(const char *device);
+pa_bool_t pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
+
#endif
commit d04f3e1aef569bae3226ae94a42ad95ca2fa01c7
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:21:34 2009 +0200
Trigger move callback a little bit earlier so that no IO thread is running
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index ff49e69..2cdb37e 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -203,7 +203,7 @@ enum {
static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
static void sink_input_kill_cb(pa_sink_input *i);
static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
-static void sink_input_moved_cb(pa_sink_input *i);
+static void sink_input_moving_cb(pa_sink_input *i);
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
@@ -215,7 +215,7 @@ static void playback_stream_request_bytes(struct playback_stream*s);
static void source_output_kill_cb(pa_source_output *o);
static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend);
-static void source_output_moved_cb(pa_source_output *o);
+static void source_output_moving_cb(pa_source_output *o);
static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
@@ -636,7 +636,7 @@ static record_stream* record_stream_new(
s->source_output->push = source_output_push_cb;
s->source_output->kill = source_output_kill_cb;
s->source_output->get_latency = source_output_get_latency_cb;
- s->source_output->moved = source_output_moved_cb;
+ s->source_output->moving = source_output_moving_cb;
s->source_output->suspend = source_output_suspend_cb;
s->source_output->send_event = source_output_send_event_cb;
s->source_output->userdata = s;
@@ -1049,7 +1049,7 @@ static playback_stream* playback_stream_new(
s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
s->sink_input->update_max_request = sink_input_update_max_request_cb;
s->sink_input->kill = sink_input_kill_cb;
- s->sink_input->moved = sink_input_moved_cb;
+ s->sink_input->moving = sink_input_moving_cb;
s->sink_input->suspend = sink_input_suspend_cb;
s->sink_input->send_event = sink_input_send_event_cb;
s->sink_input->userdata = s;
@@ -1539,7 +1539,7 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
}
/* Called from main context */
-static void sink_input_moved_cb(pa_sink_input *i) {
+static void sink_input_moving_cb(pa_sink_input *i) {
playback_stream *s;
pa_tagstruct *t;
uint32_t maxlength, tlength, prebuf, minreq;
@@ -1661,7 +1661,7 @@ static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
}
/* Called from main context */
-static void source_output_moved_cb(pa_source_output *o) {
+static void source_output_moving_cb(pa_source_output *o) {
record_stream *s;
pa_tagstruct *t;
uint32_t maxlength, fragsize;
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index ae2c6f5..15a7880 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -117,7 +117,7 @@ static void reset_callbacks(pa_sink_input *i) {
i->attach = NULL;
i->detach = NULL;
i->suspend = NULL;
- i->moved = NULL;
+ i->moving = NULL;
i->kill = NULL;
i->get_latency = NULL;
i->state_change = NULL;
@@ -1169,6 +1169,9 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
} else
new_resampler = NULL;
+ if (i->moving)
+ i->moving(i);
+
i->sink = dest;
i->save_sink = save;
pa_idxset_put(dest->inputs, i, NULL);
@@ -1195,7 +1198,6 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
0,
&i->sink->silence);
}
-
pa_sink_update_status(dest);
if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
@@ -1216,9 +1218,6 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
pa_log_debug("Successfully moved sink input %i to %s.", i->index, dest->name);
/* Notify everyone */
- if (i->moved)
- i->moved(i);
-
pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], i);
pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
index 0bcb9d5..4e29be6 100644
--- a/src/pulsecore/sink-input.h
+++ b/src/pulsecore/sink-input.h
@@ -150,7 +150,7 @@ struct pa_sink_input {
/* If non-NULL called whenever the the sink this input is attached
* to changes. Called from main context */
- void (*moved) (pa_sink_input *i); /* may be NULL */
+ void (*moving) (pa_sink_input *i); /* may be NULL */
/* Supposed to unlink and destroy this stream. Called from main
* context. */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 373d563..25aea7d 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -87,7 +87,7 @@ static void reset_callbacks(pa_source_output *o) {
o->attach = NULL;
o->detach = NULL;
o->suspend = NULL;
- o->moved = NULL;
+ o->moving = NULL;
o->kill = NULL;
o->get_latency = NULL;
o->state_change = NULL;
@@ -749,6 +749,9 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
} else
new_resampler = NULL;
+ if (o->moving)
+ o->moving(o);
+
o->source = dest;
o->save_source = save;
pa_idxset_put(o->source->outputs, o, NULL);
@@ -776,14 +779,12 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t
}
pa_source_update_status(dest);
+
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0);
pa_log_debug("Successfully moved source output %i to %s.", o->index, dest->name);
/* Notify everyone */
- if (o->moved)
- o->moved(o);
-
pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], o);
pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h
index 018ec88..8d57ded 100644
--- a/src/pulsecore/source-output.h
+++ b/src/pulsecore/source-output.h
@@ -122,7 +122,7 @@ struct pa_source_output {
/* If non-NULL called whenever the the source this output is attached
* to changes. Called from main context */
- void (*moved) (pa_source_output *o); /* may be NULL */
+ void (*moving) (pa_source_output *o); /* may be NULL */
/* Supposed to unlink and destroy this stream. Called from main
* context. */
commit 7f5481ede0e67343fc914a57ea6c68f36fced104
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:23:48 2009 +0200
simplify latency config functions a bit and make them callable in more contexts
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 15a7880..da42242 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -819,26 +819,12 @@ void pa_sink_input_update_max_request(pa_sink_input *i, size_t nbytes /* in the
}
/* Called from thread context */
-static pa_usec_t fixup_latency(pa_sink *s, pa_usec_t usec) {
- pa_sink_assert_ref(s);
-
- if (usec == (pa_usec_t) -1)
- return usec;
-
- if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
- usec = s->thread_info.max_latency;
-
- if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
- usec = s->thread_info.min_latency;
-
- return usec;
-}
-
-/* Called from thread context */
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);
- usec = fixup_latency(i->sink, usec);
+ if (usec != (pa_usec_t) -1)
+ usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
+
i->thread_info.requested_sink_latency = usec;
pa_sink_invalidate_requested_latency(i->sink);
@@ -847,33 +833,42 @@ 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))
+ if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
- else
- /* If this sink input is not realized yet, we have to touch
- * the thread info data directly */
+ return usec;
+ }
+
+ /* If this sink input is not realized yet or we are being moved,
+ * we have to touch the thread info data directly */
+
+ pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
- i->thread_info.requested_sink_latency = usec;
+ if (usec != (pa_usec_t) -1)
+ usec = PA_CLAMP(usec, min_latency, max_latency);
+
+ i->thread_info.requested_sink_latency = usec;
return usec;
}
/* Called from main context */
pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
- pa_usec_t usec = 0;
-
pa_sink_input_assert_ref(i);
- if (PA_SINK_INPUT_IS_LINKED(i->state))
+ if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
+ pa_usec_t usec = 0;
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
- else
- /* If this sink input is not realized yet, we have to touch
- * the thread info data directly */
- usec = i->thread_info.requested_sink_latency;
+ return usec;
+ }
- return usec;
+ /* If this sink input is not realized yet or we are being moved,
+ * we have to touch the thread info data directly */
+
+ return i->thread_info.requested_sink_latency;
}
/* Called from main context */
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 25aea7d..550b657 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -516,26 +516,12 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes /* i
}
/* Called from thread context */
-static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) {
- pa_source_assert_ref(s);
-
- if (usec == (pa_usec_t) -1)
- return usec;
-
- if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency)
- usec = s->thread_info.max_latency;
-
- if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency)
- usec = s->thread_info.min_latency;
-
- return usec;
-}
-
-/* Called from thread context */
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);
- usec = fixup_latency(o->source, usec);
+ if (usec != (pa_usec_t) -1)
+ usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
+
o->thread_info.requested_source_latency = usec;
pa_source_invalidate_requested_latency(o->source);
@@ -544,33 +530,42 @@ 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))
+ if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
- else
- /* If this source output is not realized yet, we have to touch
- * the thread info data directly */
+ return usec;
+ }
+
+ /* If this source output is not realized yet or is being moved, we
+ * have to touch the thread info data directly */
+
+ pa_source_get_latency_range(o->source, &min_latency, &max_latency);
- o->thread_info.requested_source_latency = usec;
+ if (usec != (pa_usec_t) -1)
+ usec = PA_CLAMP(usec, min_latency, max_latency);
+
+ o->thread_info.requested_source_latency = usec;
return usec;
}
/* Called from main context */
pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) {
- pa_usec_t usec = 0;
-
pa_source_output_assert_ref(o);
- if (PA_SOURCE_OUTPUT_IS_LINKED(o->state))
+ if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
+ pa_usec_t usec = 0;
pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
- else
- /* If this source output is not realized yet, we have to touch
- * the thread info data directly */
- usec = o->thread_info.requested_source_latency;
+ return usec;
+ }
- return usec;
+ /* If this source output is not realized yet or is being moved, we
+ * have to touch the thread info data directly */
+
+ return o->thread_info.requested_source_latency;
}
/* Called from main context */
commit 7c37c37fff565d64cba5acd9a92f9c9854ca2601
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:26:23 2009 +0200
document more often the context certain functions are called in
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 2cdb37e..b11265c 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -360,6 +360,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
/* structure management */
+/* Called from main context */
static void upload_stream_unlink(upload_stream *s) {
pa_assert(s);
@@ -371,6 +372,7 @@ static void upload_stream_unlink(upload_stream *s) {
upload_stream_unref(s);
}
+/* Called from main context */
static void upload_stream_free(pa_object *o) {
upload_stream *s = UPLOAD_STREAM(o);
pa_assert(s);
@@ -388,6 +390,7 @@ static void upload_stream_free(pa_object *o) {
pa_xfree(s);
}
+/* Called from main context */
static upload_stream* upload_stream_new(
pa_native_connection *c,
const pa_sample_spec *ss,
@@ -420,6 +423,7 @@ static upload_stream* upload_stream_new(
return s;
}
+/* Called from main context */
static void record_stream_unlink(record_stream *s) {
pa_assert(s);
@@ -437,6 +441,7 @@ static void record_stream_unlink(record_stream *s) {
record_stream_unref(s);
}
+/* Called from main context */
static void record_stream_free(pa_object *o) {
record_stream *s = RECORD_STREAM(o);
pa_assert(s);
@@ -447,6 +452,7 @@ static void record_stream_free(pa_object *o) {
pa_xfree(s);
}
+/* Called from main context */
static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
record_stream *s = RECORD_STREAM(o);
record_stream_assert_ref(s);
@@ -581,6 +587,7 @@ static void fix_record_buffer_attr_post(
*fragsize = (uint32_t) s->fragment_size;
}
+/* Called from main context */
static record_stream* record_stream_new(
pa_native_connection *c,
pa_source *source,
@@ -669,6 +676,7 @@ static record_stream* record_stream_new(
return s;
}
+/* Called from main context */
static void record_stream_send_killed(record_stream *r) {
pa_tagstruct *t;
record_stream_assert_ref(r);
@@ -680,6 +688,7 @@ static void record_stream_send_killed(record_stream *r) {
pa_pstream_send_tagstruct(r->connection->pstream, t);
}
+/* Called from main context */
static void playback_stream_unlink(playback_stream *s) {
pa_assert(s);
@@ -700,6 +709,7 @@ static void playback_stream_unlink(playback_stream *s) {
playback_stream_unref(s);
}
+/* Called from main context */
static void playback_stream_free(pa_object* o) {
playback_stream *s = PLAYBACK_STREAM(o);
pa_assert(s);
@@ -710,6 +720,7 @@ static void playback_stream_free(pa_object* o) {
pa_xfree(s);
}
+/* Called from main context */
static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
playback_stream *s = PLAYBACK_STREAM(o);
playback_stream_assert_ref(s);
@@ -953,6 +964,7 @@ static void fix_playback_buffer_attr_post(
s->minreq = *minreq;
}
+/* Called from main context */
static playback_stream* playback_stream_new(
pa_native_connection *c,
pa_sink *sink,
@@ -1089,7 +1101,7 @@ static playback_stream* playback_stream_new(
return s;
}
-/* Called from thread context */
+/* Called from IO context */
static void playback_stream_request_bytes(playback_stream *s) {
size_t m, previous_missing;
@@ -1110,6 +1122,7 @@ static void playback_stream_request_bytes(playback_stream *s) {
}
+/* Called from main context */
static void playback_stream_send_killed(playback_stream *p) {
pa_tagstruct *t;
playback_stream_assert_ref(p);
@@ -1121,6 +1134,7 @@ static void playback_stream_send_killed(playback_stream *p) {
pa_pstream_send_tagstruct(p->connection->pstream, t);
}
+/* Called from main context */
static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
pa_native_connection *c = PA_NATIVE_CONNECTION(o);
pa_native_connection_assert_ref(c);
@@ -1142,6 +1156,7 @@ static int native_connection_process_msg(pa_msgobject *o, int code, void*userdat
return 0;
}
+/* Called from main context */
static void native_connection_unlink(pa_native_connection *c) {
record_stream *r;
output_stream *o;
@@ -1181,6 +1196,7 @@ static void native_connection_unlink(pa_native_connection *c) {
pa_native_connection_unref(c);
}
+/* Called from main context */
static void native_connection_free(pa_object *o) {
pa_native_connection *c = PA_NATIVE_CONNECTION(o);
@@ -1198,6 +1214,7 @@ static void native_connection_free(pa_object *o) {
pa_xfree(c);
}
+/* Called from main context */
static void native_connection_send_memblock(pa_native_connection *c) {
uint32_t start;
record_stream *r;
@@ -1232,6 +1249,7 @@ static void native_connection_send_memblock(pa_native_connection *c) {
/*** sink input callbacks ***/
+/* Called from thread context */
static void handle_seek(playback_stream *s, int64_t indexw) {
playback_stream_assert_ref(s);
@@ -1447,6 +1465,7 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
return 0;
}
+/* Called from thread context */
static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
playback_stream *s;
@@ -1461,6 +1480,7 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
pa_memblockq_rewind(s->memblockq, nbytes);
}
+/* Called from thread context */
static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
playback_stream *s;
@@ -1471,6 +1491,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
pa_memblockq_set_maxrewind(s->memblockq, nbytes);
}
+/* Called from thread context */
static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
playback_stream *s;
size_t tlength;
commit b349dae6e146233175c38f46d4bd964b06a2ccd2
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:27:07 2009 +0200
add pa_memblockq_apply_attr()/pa_memblockq_get_attr()
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index e2be42b..e6e7b73 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -851,6 +851,26 @@ void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
bq->maxrewind = (maxrewind/bq->base)*bq->base;
}
+void pa_memblockq_apply_attr(pa_memblockq *bq, const pa_buffer_attr *a) {
+ pa_assert(bq);
+ pa_assert(a);
+
+ pa_memblockq_set_maxlength(bq, a->maxlength);
+ pa_memblockq_set_tlength(bq, a->tlength);
+ pa_memblockq_set_prebuf(bq, a->prebuf);
+ pa_memblockq_set_minreq(bq, a->minreq);
+}
+
+void pa_memblockq_get_attr(pa_memblockq *bq, pa_buffer_attr *a) {
+ pa_assert(bq);
+ pa_assert(a);
+
+ a->maxlength = (uint32_t) pa_memblockq_get_maxlength(bq);
+ a->tlength = (uint32_t) pa_memblockq_get_tlength(bq);
+ a->prebuf = (uint32_t) pa_memblockq_get_prebuf(bq);
+ a->minreq = (uint32_t) pa_memblockq_get_minreq(bq);
+}
+
int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) {
pa_assert(bq);
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index 0a74aa3..e315b83 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -158,6 +158,10 @@ void pa_memblockq_set_minreq(pa_memblockq *memblockq, size_t minreq);
void pa_memblockq_set_maxrewind(pa_memblockq *memblockq, size_t maxrewind); /* Set the maximum history size */
void pa_memblockq_set_silence(pa_memblockq *memblockq, pa_memchunk *silence);
+/* Apply the data from pa_buffer_attr */
+void pa_memblockq_apply_attr(pa_memblockq *memblockq, const pa_buffer_attr *a);
+void pa_memblockq_get_attr(pa_memblockq *bq, pa_buffer_attr *a);
+
/* Call pa_memchunk_willneed() for every chunk in the queue from the current read pointer to the end */
void pa_memblockq_willneed(pa_memblockq *bq);
@@ -175,5 +179,4 @@ pa_bool_t pa_memblockq_prebuf_active(pa_memblockq *bq);
/* Return how many items are currently stored in the queue */
unsigned pa_memblockq_get_nblocks(pa_memblockq *bq);
-
#endif
commit 491aafd8dcfaafced045a4ff494a1841819458d4
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:27:33 2009 +0200
typo fix
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 9418e96..9928f9b 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -624,7 +624,7 @@ typedef struct pa_timing_info {
/**< The configured latency for the sink. \since 0.9.11 */
pa_usec_t configured_source_usec;
- /**< The configured latency for * the source. \since 0.9.11 */
+ /**< The configured latency for the source. \since 0.9.11 */
int64_t since_underrun;
/**< Bytes that were handed to the sink since the last underrun
commit 65b787d00010ee59d823ec081c82116f2400ecf0
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 18:46:12 2009 +0200
notify clients about tlength changes
diff --git a/PROTOCOL b/PROTOCOL
index 8c5937b..88166f1 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -168,3 +168,16 @@ PA_COMMAND_GET_MODULE_INFO_LIST
remove bool auto_unload
add proplist at the end
+
+new messages:
+
+ PA_COMMAND_GET_CARD_INFO
+ PA_COMMAND_GET_CARD_INFO_LIST
+ PA_COMMAND_SET_CARD_PROFILE
+
+ PA_COMMAND_CLIENT_EVENT
+ PA_COMMAND_PLAYBACK_STREAM_EVENT
+ PA_COMMAND_RECORD_STREAM_EVENT
+
+ PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
+ PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 00dffc2..7c86a43 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -99,7 +99,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_EXTENSION] = pa_command_extension,
[PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event,
[PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event,
- [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event
+ [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event,
+ [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr,
+ [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr
};
static void context_free(pa_context *c);
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 9646d8a..c08bd26 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -185,6 +185,8 @@ struct pa_stream {
void *started_userdata;
pa_stream_event_cb_t event_callback;
void *event_userdata;
+ pa_stream_notify_cb_t buffer_attr_callback;
+ void *buffer_attr_userdata;
};
typedef void (*pa_operation_cb_t)(void);
@@ -213,6 +215,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata);
void pa_operation_done(pa_operation *o);
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 48e3b08..bb53b19 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -72,6 +72,8 @@ static void reset_callbacks(pa_stream *s) {
s->started_userdata = NULL;
s->event_callback = NULL;
s->event_userdata = NULL;
+ s->buffer_attr_callback = NULL;
+ s->buffer_attr_userdata = NULL;
}
pa_stream *pa_stream_new_with_proplist(
@@ -396,7 +398,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
const char *dn;
pa_bool_t suspended;
uint32_t di;
- pa_usec_t usec;
+ pa_usec_t usec = 0;
uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0;
pa_assert(pd);
@@ -486,6 +488,80 @@ finish:
pa_context_unref(c);
}
+void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_context *c = userdata;
+ pa_stream *s;
+ uint32_t channel;
+ pa_usec_t usec = 0;
+ uint32_t maxlength = 0, fragsize = 0, minreq = 0, tlength = 0, prebuf = 0;
+
+ pa_assert(pd);
+ pa_assert(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED || command == PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED);
+ pa_assert(t);
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) >= 1);
+
+ pa_context_ref(c);
+
+ if (c->version < 15) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (pa_tagstruct_getu32(t, &channel) < 0) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (command == PA_COMMAND_RECORD_STREAM_MOVED) {
+ if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
+ pa_tagstruct_getu32(t, &fragsize) < 0 ||
+ pa_tagstruct_get_usec(t, &usec) < 0) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+ } else {
+ if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
+ pa_tagstruct_getu32(t, &tlength) < 0 ||
+ pa_tagstruct_getu32(t, &prebuf) < 0 ||
+ pa_tagstruct_getu32(t, &minreq) < 0 ||
+ pa_tagstruct_get_usec(t, &usec) < 0) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+ }
+
+ if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(c, PA_ERR_PROTOCOL);
+ goto finish;
+ }
+
+ if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED ? c->playback_streams : c->record_streams, channel)))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+ goto finish;
+
+ if (s->direction == PA_STREAM_RECORD)
+ s->timing_info.configured_source_usec = usec;
+ else
+ s->timing_info.configured_sink_usec = usec;
+
+ s->buffer_attr.maxlength = maxlength;
+ s->buffer_attr.fragsize = fragsize;
+ s->buffer_attr.tlength = tlength;
+ s->buffer_attr.prebuf = prebuf;
+ s->buffer_attr.minreq = minreq;
+
+ request_auto_timing_update(s, TRUE);
+
+ if (s->buffer_attr_callback)
+ s->buffer_attr_callback(s, s->buffer_attr_userdata);
+
+finish:
+ pa_context_unref(c);
+}
+
void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
pa_stream *s;
@@ -1798,6 +1874,20 @@ void pa_stream_set_event_callback(pa_stream *s, pa_stream_event_cb_t cb, void *u
s->event_userdata = userdata;
}
+void pa_stream_set_buffer_attr_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
+ pa_assert(s);
+ pa_assert(PA_REFCNT_VALUE(s) >= 1);
+
+ if (pa_detect_fork())
+ return;
+
+ if (s->state == PA_STREAM_TERMINATED || s->state == PA_STREAM_FAILED)
+ return;
+
+ s->buffer_attr_callback = cb;
+ s->buffer_attr_userdata = userdata;
+}
+
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
int success = 1;
diff --git a/src/pulse/stream.h b/src/pulse/stream.h
index e80bc65..8e99a75 100644
--- a/src/pulse/stream.h
+++ b/src/pulse/stream.h
@@ -512,6 +512,13 @@ void pa_stream_set_suspended_callback(pa_stream *p, pa_stream_notify_cb_t cb, vo
* control event is received.\since 0.9.15 */
void pa_stream_set_event_callback(pa_stream *p, pa_stream_event_cb_t cb, void *userdata);
+/** Set the callback function that is called whenver the buffer
+ * attributes on the server side change. Please note that the buffer
+ * attributes can change when moving a stream to a different
+ * sink/source too, hence if you use this callback you should use
+ * pa_stream_set_moved_callback() as well. \since 0.9.15 */
+void pa_stream_set_buffer_attr_callback(pa_stream *p, pa_stream_notify_cb_t cb, void *userdata);
+
/** Pause (or resume) playback of this stream temporarily. Available on both playback and recording streams. */
pa_operation* pa_stream_cork(pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata);
@@ -530,7 +537,7 @@ pa_operation* pa_stream_prebuf(pa_stream *s, pa_stream_success_cb_t cb, void *us
* temporarily. Available for playback streams only. */
pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
-/** Rename the stream.*/
+/** Rename the stream. */
pa_operation* pa_stream_set_name(pa_stream *s, const char *name, pa_stream_success_cb_t cb, void *userdata);
/** Return the current playback/recording time. This is based on the
diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h
index 6951e10..d4d7f3e 100644
--- a/src/pulsecore/native-common.h
+++ b/src/pulsecore/native-common.h
@@ -152,7 +152,7 @@ enum {
/* Supported since protocol v14 (0.9.12) */
PA_COMMAND_EXTENSION,
- /* Supported since protocol v15 (0.9.15*/
+ /* Supported since protocol v15 (0.9.15) */
PA_COMMAND_GET_CARD_INFO,
PA_COMMAND_GET_CARD_INFO_LIST,
PA_COMMAND_SET_CARD_PROFILE,
@@ -161,6 +161,10 @@ enum {
PA_COMMAND_PLAYBACK_STREAM_EVENT,
PA_COMMAND_RECORD_STREAM_EVENT,
+ /* SERVER->CLIENT */
+ PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED,
+ PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED,
+
PA_COMMAND_MAX
};
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index b11265c..3e75cab 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -81,7 +81,11 @@ typedef struct record_stream {
pa_source_output *source_output;
pa_memblockq *memblockq;
- size_t fragment_size;
+
+ pa_bool_t adjust_latency:1;
+ pa_bool_t early_requests:1;
+
+ pa_buffer_attr buffer_attr;
pa_usec_t source_latency;
} record_stream;
@@ -105,14 +109,18 @@ typedef struct playback_stream {
pa_sink_input *sink_input;
pa_memblockq *memblockq;
+
+ pa_bool_t adjust_latency:1;
+ pa_bool_t early_requests:1;
+
pa_bool_t is_underrun:1;
pa_bool_t drain_request:1;
uint32_t drain_tag;
uint32_t syncid;
pa_atomic_t missing;
- size_t minreq;
pa_usec_t sink_latency;
+ pa_buffer_attr buffer_attr;
/* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
int64_t read_index, write_index;
@@ -180,7 +188,8 @@ enum {
SINK_INPUT_MESSAGE_TRIGGER,
SINK_INPUT_MESSAGE_SEEK,
SINK_INPUT_MESSAGE_PREBUF_FORCE,
- SINK_INPUT_MESSAGE_UPDATE_LATENCY
+ SINK_INPUT_MESSAGE_UPDATE_LATENCY,
+ SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
};
enum {
@@ -188,7 +197,8 @@ enum {
PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
PLAYBACK_STREAM_MESSAGE_OVERFLOW,
PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
- PLAYBACK_STREAM_MESSAGE_STARTED
+ PLAYBACK_STREAM_MESSAGE_STARTED,
+ PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
};
enum {
@@ -478,35 +488,34 @@ static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, i
return 0;
}
-static void fix_record_buffer_attr_pre(
- record_stream *s,
- pa_bool_t adjust_latency,
- pa_bool_t early_requests,
- uint32_t *maxlength,
- uint32_t *fragsize) {
+/* Called from main context */
+static void fix_record_buffer_attr_pre(record_stream *s) {
size_t frame_size;
pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
pa_assert(s);
- pa_assert(maxlength);
- pa_assert(fragsize);
+
+ /* This function will be called from the main thread, before as
+ * well as after the source output has been activated using
+ * pa_source_output_put()! That means it may not touch any
+ * ->thread_info data! */
frame_size = pa_frame_size(&s->source_output->sample_spec);
- if (*maxlength == (uint32_t) -1 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
- *maxlength = MAX_MEMBLOCKQ_LENGTH;
- if (*maxlength <= 0)
- *maxlength = (uint32_t) frame_size;
+ if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
+ s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
+ if (s->buffer_attr.maxlength <= 0)
+ s->buffer_attr.maxlength = (uint32_t) frame_size;
- if (*fragsize == (uint32_t) -1)
- *fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
- if (*fragsize <= 0)
- *fragsize = (uint32_t) frame_size;
+ if (s->buffer_attr.fragsize == (uint32_t) -1)
+ s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
+ if (s->buffer_attr.fragsize <= 0)
+ s->buffer_attr.fragsize = (uint32_t) frame_size;
- orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(*fragsize, &s->source_output->sample_spec);
+ orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
- if (early_requests) {
+ if (s->early_requests) {
/* In early request mode we need to emulate the classic
* fragment-based playback model. We do this setting the source
@@ -514,7 +523,7 @@ static void fix_record_buffer_attr_pre(
source_usec = fragsize_usec;
- } else if (adjust_latency) {
+ } else if (s->adjust_latency) {
/* So, the user asked us to adjust the latency according to
* what the source can provide. Half the latency will be
@@ -536,14 +545,14 @@ static void fix_record_buffer_attr_pre(
else
s->source_latency = 0;
- if (early_requests) {
+ if (s->early_requests) {
/* Ok, we didn't necessarily get what we were asking for, so
* let's tell the user */
fragsize_usec = s->source_latency;
- } else if (adjust_latency) {
+ } else if (s->adjust_latency) {
/* Now subtract what we actually got */
@@ -556,35 +565,31 @@ static void fix_record_buffer_attr_pre(
if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
- *fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
+ s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
- if (*fragsize <= 0)
- *fragsize = (uint32_t) frame_size;
+ if (s->buffer_attr.fragsize <= 0)
+ s->buffer_attr.fragsize = (uint32_t) frame_size;
}
-static void fix_record_buffer_attr_post(
- record_stream *s,
- uint32_t *maxlength,
- uint32_t *fragsize) {
-
+/* Called from main context */
+static void fix_record_buffer_attr_post(record_stream *s) {
size_t base;
pa_assert(s);
- pa_assert(maxlength);
- pa_assert(fragsize);
- *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
+ /* This function will be called from the main thread, before as
+ * well as after the source output has been activated using
+ * pa_source_output_put()! That means it may not touch and
+ * ->thread_info data! */
base = pa_frame_size(&s->source_output->sample_spec);
- s->fragment_size = (*fragsize/base)*base;
- if (s->fragment_size <= 0)
- s->fragment_size = base;
+ s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
+ if (s->buffer_attr.fragsize <= 0)
+ s->buffer_attr.fragsize = base;
- if (s->fragment_size > *maxlength)
- s->fragment_size = *maxlength;
-
- *fragsize = (uint32_t) s->fragment_size;
+ if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
+ s->buffer_attr.fragsize = s->buffer_attr.maxlength;
}
/* Called from main context */
@@ -594,8 +599,7 @@ static record_stream* record_stream_new(
pa_sample_spec *ss,
pa_channel_map *map,
pa_bool_t peak_detect,
- uint32_t *maxlength,
- uint32_t *fragsize,
+ pa_buffer_attr *attr,
pa_source_output_flags_t flags,
pa_proplist *p,
pa_bool_t adjust_latency,
@@ -610,7 +614,6 @@ static record_stream* record_stream_new(
pa_assert(c);
pa_assert(ss);
- pa_assert(maxlength);
pa_assert(p);
pa_assert(ret);
@@ -639,6 +642,9 @@ static record_stream* record_stream_new(
s->parent.process_msg = record_stream_process_msg;
s->connection = c;
s->source_output = source_output;
+ s->buffer_attr = *attr;
+ s->adjust_latency = adjust_latency;
+ s->early_requests = early_requests;
s->source_output->push = source_output_push_cb;
s->source_output->kill = source_output_kill_cb;
@@ -648,11 +654,11 @@ static record_stream* record_stream_new(
s->source_output->send_event = source_output_send_event_cb;
s->source_output->userdata = s;
- fix_record_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, fragsize);
+ fix_record_buffer_attr_pre(s);
s->memblockq = pa_memblockq_new(
0,
- *maxlength,
+ s->buffer_attr.maxlength,
0,
base = pa_frame_size(&source_output->sample_spec),
1,
@@ -660,7 +666,8 @@ static record_stream* record_stream_new(
0,
NULL);
- fix_record_buffer_attr_post(s, maxlength, fragsize);
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
+ fix_record_buffer_attr_post(s);
*ss = s->source_output->sample_spec;
*map = s->source_output->channel_map;
@@ -668,8 +675,8 @@ static record_stream* record_stream_new(
pa_idxset_put(c->record_streams, s, &s->index);
pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
- ((double) pa_bytes_to_usec(s->fragment_size, &source_output->sample_spec) + (double) s->source_latency) / PA_USEC_PER_MSEC,
- (double) pa_bytes_to_usec(s->fragment_size, &source_output->sample_spec) / PA_USEC_PER_MSEC,
+ ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->source_latency) / PA_USEC_PER_MSEC,
+ (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
(double) s->source_latency / PA_USEC_PER_MSEC);
pa_source_output_put(s->source_output);
@@ -799,67 +806,79 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
break;
+
+ case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
+ pa_tagstruct *t;
+
+ s->buffer_attr.tlength = (uint32_t) offset;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
+ pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
+ pa_tagstruct_putu32(t, s->index);
+ pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.tlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(t, s->buffer_attr.minreq);
+ pa_tagstruct_put_usec(t, s->sink_latency);
+ pa_pstream_send_tagstruct(s->connection->pstream, t);
+
+ break;
+ }
}
return 0;
}
-static void fix_playback_buffer_attr_pre(
- playback_stream *s,
- pa_bool_t adjust_latency,
- pa_bool_t early_requests,
- uint32_t *maxlength,
- uint32_t *tlength,
- uint32_t* prebuf,
- uint32_t* minreq) {
-
+/* Called from main context */
+static void fix_playback_buffer_attr(playback_stream *s) {
size_t frame_size;
pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
pa_assert(s);
- pa_assert(maxlength);
- pa_assert(tlength);
- pa_assert(prebuf);
- pa_assert(minreq);
+
+ /* This function will be called from the main thread, before as
+ * well as after the sink input has been activated using
+ * pa_sink_input_put()! That means it may not touch any
+ * ->thread_info data, such as the memblockq! */
frame_size = pa_frame_size(&s->sink_input->sample_spec);
- if (*maxlength == (uint32_t) -1 || *maxlength > MAX_MEMBLOCKQ_LENGTH)
- *maxlength = MAX_MEMBLOCKQ_LENGTH;
- if (*maxlength <= 0)
- *maxlength = (uint32_t) frame_size;
+ if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
+ s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
+ if (s->buffer_attr.maxlength <= 0)
+ s->buffer_attr.maxlength = (uint32_t) frame_size;
- if (*tlength == (uint32_t) -1)
- *tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
- if (*tlength <= 0)
- *tlength = (uint32_t) frame_size;
+ if (s->buffer_attr.tlength == (uint32_t) -1)
+ s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
+ if (s->buffer_attr.tlength <= 0)
+ s->buffer_attr.tlength = (uint32_t) frame_size;
- if (*minreq == (uint32_t) -1)
- *minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
- if (*minreq <= 0)
- *minreq = (uint32_t) frame_size;
+ if (s->buffer_attr.minreq == (uint32_t) -1)
+ s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
+ if (s->buffer_attr.minreq <= 0)
+ s->buffer_attr.minreq = (uint32_t) frame_size;
- if (*tlength < *minreq+frame_size)
- *tlength = *minreq+(uint32_t) frame_size;
+ if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
+ s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
- orig_tlength_usec = tlength_usec = pa_bytes_to_usec(*tlength, &s->sink_input->sample_spec);
- orig_minreq_usec = minreq_usec = pa_bytes_to_usec(*minreq, &s->sink_input->sample_spec);
+ orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
+ orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
(double) tlength_usec / PA_USEC_PER_MSEC,
(double) minreq_usec / PA_USEC_PER_MSEC);
- if (early_requests) {
+ if (s->early_requests) {
/* In early request mode we need to emulate the classic
* fragment-based playback model. We do this setting the sink
* latency to the fragment size. */
sink_usec = minreq_usec;
-
pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
- } else if (adjust_latency) {
+ } else if (s->adjust_latency) {
/* So, the user asked us to adjust the latency of the stream
* buffer according to the what the sink can provide. The
@@ -901,14 +920,14 @@ static void fix_playback_buffer_attr_pre(
s->sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
- if (early_requests) {
+ if (s->early_requests) {
/* Ok, we didn't necessarily get what we were asking for, so
* let's tell the user */
minreq_usec = s->sink_latency;
- } else if (adjust_latency) {
+ } else if (s->adjust_latency) {
/* Ok, we didn't necessarily get what we were asking for, so
* let's subtract from what we asked for for the remaining
@@ -925,43 +944,22 @@ static void fix_playback_buffer_attr_pre(
if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
- *tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
+ s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
- *minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
+ s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
- if (*minreq <= 0) {
- *minreq = (uint32_t) frame_size;
- *tlength += (uint32_t) frame_size*2;
+ if (s->buffer_attr.minreq <= 0) {
+ s->buffer_attr.minreq = (uint32_t) frame_size;
+ s->buffer_attr.tlength += (uint32_t) frame_size*2;
}
- if (*tlength <= *minreq)
- *tlength = *minreq*2 + (uint32_t) frame_size;
-
- if (*prebuf == (uint32_t) -1 || *prebuf > *tlength)
- *prebuf = *tlength;
-}
-
-static void fix_playback_buffer_attr_post(
- playback_stream *s,
- uint32_t *maxlength,
- uint32_t *tlength,
- uint32_t* prebuf,
- uint32_t* minreq) {
+ if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
+ s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
- pa_assert(s);
- pa_assert(maxlength);
- pa_assert(tlength);
- pa_assert(prebuf);
- pa_assert(minreq);
-
- *maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
- *tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
- *prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
- *minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
-
- s->minreq = *minreq;
+ if (s->buffer_attr.prebuf == (uint32_t) -1 || s->buffer_attr.prebuf > s->buffer_attr.tlength)
+ s->buffer_attr.prebuf = s->buffer_attr.tlength;
}
/* Called from main context */
@@ -970,10 +968,7 @@ static playback_stream* playback_stream_new(
pa_sink *sink,
pa_sample_spec *ss,
pa_channel_map *map,
- uint32_t *maxlength,
- uint32_t *tlength,
- uint32_t *prebuf,
- uint32_t *minreq,
+ pa_buffer_attr *a,
pa_cvolume *volume,
pa_bool_t muted,
pa_bool_t muted_set,
@@ -994,10 +989,6 @@ static playback_stream* playback_stream_new(
pa_assert(c);
pa_assert(ss);
- pa_assert(maxlength);
- pa_assert(tlength);
- pa_assert(prebuf);
- pa_assert(minreq);
pa_assert(missing);
pa_assert(p);
pa_assert(ret);
@@ -1054,6 +1045,9 @@ static playback_stream* playback_stream_new(
s->is_underrun = TRUE;
s->drain_request = FALSE;
pa_atomic_store(&s->missing, 0);
+ s->buffer_attr = *a;
+ s->adjust_latency = adjust_latency;
+ s->early_requests = early_requests;
s->sink_input->parent.process_msg = sink_input_process_msg;
s->sink_input->pop = sink_input_pop_cb;
@@ -1068,21 +1062,21 @@ static playback_stream* playback_stream_new(
start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
- fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, maxlength, tlength, prebuf, minreq);
- pa_sink_input_get_silence(sink_input, &silence);
+ fix_playback_buffer_attr(s);
+ pa_sink_input_get_silence(sink_input, &silence);
s->memblockq = pa_memblockq_new(
start_index,
- *maxlength,
- *tlength,
+ s->buffer_attr.maxlength,
+ s->buffer_attr.tlength,
pa_frame_size(&sink_input->sample_spec),
- *prebuf,
- *minreq,
+ s->buffer_attr.prebuf,
+ s->buffer_attr.minreq,
0,
&silence);
-
pa_memblock_unref(silence.memblock);
- fix_playback_buffer_attr_post(s, maxlength, tlength, prebuf, minreq);
+
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
*missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
@@ -1092,9 +1086,9 @@ static playback_stream* playback_stream_new(
pa_idxset_put(c->output_streams, s, &s->index);
pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
- ((double) pa_bytes_to_usec(*tlength, &sink_input->sample_spec) + (double) s->sink_latency) / PA_USEC_PER_MSEC,
- (double) pa_bytes_to_usec(*tlength-*minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
- (double) pa_bytes_to_usec(*minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
+ ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->sink_latency) / PA_USEC_PER_MSEC,
+ (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
+ (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
(double) s->sink_latency / PA_USEC_PER_MSEC);
pa_sink_input_put(s->sink_input);
@@ -1103,7 +1097,7 @@ static playback_stream* playback_stream_new(
/* Called from IO context */
static void playback_stream_request_bytes(playback_stream *s) {
- size_t m, previous_missing;
+ size_t m, previous_missing, minreq;
playback_stream_assert_ref(s);
@@ -1115,9 +1109,10 @@ static void playback_stream_request_bytes(playback_stream *s) {
/* pa_log("request_bytes(%lu)", (unsigned long) m); */
previous_missing = (size_t) pa_atomic_add(&s->missing, (int) m);
+ minreq = pa_memblockq_get_minreq(s->memblockq);
if (pa_memblockq_prebuf_active(s->memblockq) ||
- (previous_missing < s->minreq && previous_missing+m >= s->minreq))
+ (previous_missing < minreq && previous_missing+m >= minreq))
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
}
@@ -1234,8 +1229,8 @@ static void native_connection_send_memblock(pa_native_connection *c) {
if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
pa_memchunk schunk = chunk;
- if (schunk.length > r->fragment_size)
- schunk.length = r->fragment_size;
+ if (schunk.length > r->buffer_attr.fragsize)
+ schunk.length = r->buffer_attr.fragsize;
pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
@@ -1417,6 +1412,12 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
* latency added by the resampler */
break;
}
+
+ case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
+ pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
+ return 0;
+ }
}
return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
@@ -1502,8 +1503,10 @@ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
- if (pa_memblockq_get_tlength(s->memblockq) < tlength)
+ if (pa_memblockq_get_tlength(s->memblockq) < tlength) {
pa_memblockq_set_tlength(s->memblockq, tlength);
+ pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH, NULL, pa_memblockq_get_tlength(s->memblockq), NULL, NULL);
+ }
}
/* Called from main context */
@@ -1563,23 +1566,14 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
static void sink_input_moving_cb(pa_sink_input *i) {
playback_stream *s;
pa_tagstruct *t;
- uint32_t maxlength, tlength, prebuf, minreq;
pa_sink_input_assert_ref(i);
s = PLAYBACK_STREAM(i->userdata);
playback_stream_assert_ref(s);
- maxlength = (uint32_t) pa_memblockq_get_maxlength(s->memblockq);
- tlength = (uint32_t) pa_memblockq_get_tlength(s->memblockq);
- prebuf = (uint32_t) pa_memblockq_get_prebuf(s->memblockq);
- minreq = (uint32_t) pa_memblockq_get_minreq(s->memblockq);
-
- fix_playback_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &tlength, &prebuf, &minreq);
- pa_memblockq_set_maxlength(s->memblockq, maxlength);
- pa_memblockq_set_tlength(s->memblockq, tlength);
- pa_memblockq_set_prebuf(s->memblockq, prebuf);
- pa_memblockq_set_minreq(s->memblockq, minreq);
- fix_playback_buffer_attr_post(s, &maxlength, &tlength, &prebuf, &minreq);
+ fix_playback_buffer_attr(s);
+ pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
if (s->connection->version < 12)
return;
@@ -1593,10 +1587,10 @@ static void sink_input_moving_cb(pa_sink_input *i) {
pa_tagstruct_put_boolean(t, pa_sink_get_state(i->sink) == PA_SINK_SUSPENDED);
if (s->connection->version >= 13) {
- pa_tagstruct_putu32(t, maxlength);
- pa_tagstruct_putu32(t, tlength);
- pa_tagstruct_putu32(t, prebuf);
- pa_tagstruct_putu32(t, minreq);
+ pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.tlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(t, s->buffer_attr.minreq);
pa_tagstruct_put_usec(t, s->sink_latency);
}
@@ -1685,18 +1679,15 @@ static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
static void source_output_moving_cb(pa_source_output *o) {
record_stream *s;
pa_tagstruct *t;
- uint32_t maxlength, fragsize;
pa_source_output_assert_ref(o);
s = RECORD_STREAM(o->userdata);
record_stream_assert_ref(s);
- fragsize = (uint32_t) s->fragment_size;
- maxlength = (uint32_t) pa_memblockq_get_length(s->memblockq);
-
- fix_record_buffer_attr_pre(s, TRUE, FALSE, &maxlength, &fragsize);
- pa_memblockq_set_maxlength(s->memblockq, maxlength);
- fix_record_buffer_attr_post(s, &maxlength, &fragsize);
+ fix_record_buffer_attr_pre(s);
+ pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
+ fix_record_buffer_attr_post(s);
if (s->connection->version < 12)
return;
@@ -1710,8 +1701,8 @@ static void source_output_moving_cb(pa_source_output *o) {
pa_tagstruct_put_boolean(t, pa_source_get_state(o->source) == PA_SOURCE_SUSPENDED);
if (s->connection->version >= 13) {
- pa_tagstruct_putu32(t, maxlength);
- pa_tagstruct_putu32(t, fragsize);
+ pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
pa_tagstruct_put_usec(t, s->source_latency);
}
@@ -1744,7 +1735,8 @@ static pa_tagstruct *reply_new(uint32_t tag) {
static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
playback_stream *s;
- uint32_t maxlength, tlength, prebuf, minreq, sink_index, syncid, missing;
+ uint32_t sink_index, syncid, missing;
+ pa_buffer_attr attr;
const char *name = NULL, *sink_name;
pa_sample_spec ss;
pa_channel_map map;
@@ -1773,6 +1765,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
pa_native_connection_assert_ref(c);
pa_assert(t);
+ memset(&attr, 0, sizeof(attr));
if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
pa_tagstruct_get(
@@ -1781,11 +1774,11 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
PA_TAG_CHANNEL_MAP, &map,
PA_TAG_U32, &sink_index,
PA_TAG_STRING, &sink_name,
- PA_TAG_U32, &maxlength,
+ PA_TAG_U32, &attr.maxlength,
PA_TAG_BOOLEAN, &corked,
- PA_TAG_U32, &tlength,
- PA_TAG_U32, &prebuf,
- PA_TAG_U32, &minreq,
+ PA_TAG_U32, &attr.tlength,
+ PA_TAG_U32, &attr.prebuf,
+ PA_TAG_U32, &attr.minreq,
PA_TAG_U32, &syncid,
PA_TAG_CVOLUME, &volume,
PA_TAG_INVALID) < 0) {
@@ -1896,7 +1889,7 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
* flag. For older versions we synthesize it here */
muted_set = muted_set || muted;
- s = playback_stream_new(c, sink, &ss, &map, &maxlength, &tlength, &prebuf, &minreq, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
+ s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
pa_proplist_free(p);
CHECK_VALIDITY(c->pstream, s, tag, ret);
@@ -1912,10 +1905,10 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
if (c->version >= 9) {
/* Since 0.9.0 we support sending the buffer metrics back to the client */
- pa_tagstruct_putu32(reply, (uint32_t) maxlength);
- pa_tagstruct_putu32(reply, (uint32_t) tlength);
- pa_tagstruct_putu32(reply, (uint32_t) prebuf);
- pa_tagstruct_putu32(reply, (uint32_t) minreq);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
}
if (c->version >= 12) {
@@ -1999,7 +1992,7 @@ static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t t
static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
record_stream *s;
- uint32_t maxlength, fragment_size;
+ pa_buffer_attr attr;
uint32_t source_index;
const char *name = NULL, *source_name;
pa_sample_spec ss;
@@ -2029,14 +2022,16 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
pa_native_connection_assert_ref(c);
pa_assert(t);
+ memset(&attr, 0, sizeof(attr));
+
if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &source_index) < 0 ||
pa_tagstruct_gets(t, &source_name) < 0 ||
- pa_tagstruct_getu32(t, &maxlength) < 0 ||
+ pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
pa_tagstruct_get_boolean(t, &corked) < 0 ||
- pa_tagstruct_getu32(t, &fragment_size) < 0) {
+ pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
protocol_error(c);
return;
}
@@ -2146,7 +2141,7 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
(dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
(fail_on_suspend ? PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND : 0);
- s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
+ s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
pa_proplist_free(p);
CHECK_VALIDITY(c->pstream, s, tag, ret);
@@ -2159,8 +2154,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
if (c->version >= 9) {
/* Since 0.9 we support sending the buffer metrics back to the client */
- pa_tagstruct_putu32(reply, (uint32_t) maxlength);
- pa_tagstruct_putu32(reply, (uint32_t) fragment_size);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
}
if (c->version >= 12) {
@@ -3456,12 +3451,14 @@ static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint
static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
uint32_t idx;
- uint32_t maxlength, tlength, prebuf, minreq, fragsize;
+ pa_buffer_attr a;
pa_tagstruct *reply;
pa_native_connection_assert_ref(c);
pa_assert(t);
+ memset(&a, 0, sizeof(a));
+
if (pa_tagstruct_getu32(t, &idx) < 0) {
protocol_error(c);
return;
@@ -3479,10 +3476,10 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
if (pa_tagstruct_get(
t,
- PA_TAG_U32, &maxlength,
- PA_TAG_U32, &tlength,
- PA_TAG_U32, &prebuf,
- PA_TAG_U32, &minreq,
+ PA_TAG_U32, &a.maxlength,
+ PA_TAG_U32, &a.tlength,
+ PA_TAG_U32, &a.prebuf,
+ PA_TAG_U32, &a.minreq,
PA_TAG_INVALID) < 0 ||
(c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
(c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
@@ -3491,18 +3488,18 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
return;
}
- fix_playback_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &tlength, &prebuf, &minreq);
- pa_memblockq_set_maxlength(s->memblockq, maxlength);
- pa_memblockq_set_tlength(s->memblockq, tlength);
- pa_memblockq_set_prebuf(s->memblockq, prebuf);
- pa_memblockq_set_minreq(s->memblockq, minreq);
- fix_playback_buffer_attr_post(s, &maxlength, &tlength, &prebuf, &minreq);
+ s->adjust_latency = adjust_latency;
+ s->early_requests = early_requests;
+ s->buffer_attr = a;
+
+ fix_playback_buffer_attr(s);
+ pa_assert_se(pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR, NULL, 0, NULL) == 0);
reply = reply_new(tag);
- pa_tagstruct_putu32(reply, maxlength);
- pa_tagstruct_putu32(reply, tlength);
- pa_tagstruct_putu32(reply, prebuf);
- pa_tagstruct_putu32(reply, minreq);
+ pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
+ pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
+ pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
if (c->version >= 13)
pa_tagstruct_put_usec(reply, s->sink_latency);
@@ -3517,8 +3514,8 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
if (pa_tagstruct_get(
t,
- PA_TAG_U32, &maxlength,
- PA_TAG_U32, &fragsize,
+ PA_TAG_U32, &a.maxlength,
+ PA_TAG_U32, &a.fragsize,
PA_TAG_INVALID) < 0 ||
(c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
(c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
@@ -3527,13 +3524,18 @@ static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, u
return;
}
- fix_record_buffer_attr_pre(s, adjust_latency, early_requests, &maxlength, &fragsize);
- pa_memblockq_set_maxlength(s->memblockq, maxlength);
- fix_record_buffer_attr_post(s, &maxlength, &fragsize);
+ s->adjust_latency = adjust_latency;
+ s->early_requests = early_requests;
+ s->buffer_attr = a;
+
+ fix_record_buffer_attr_pre(s);
+ pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
+ pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
+ fix_record_buffer_attr_post(s);
reply = reply_new(tag);
- pa_tagstruct_putu32(reply, maxlength);
- pa_tagstruct_putu32(reply, fragsize);
+ pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
+ pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
if (c->version >= 13)
pa_tagstruct_put_usec(reply, s->source_latency);
commit aa6803653e513214fa1ab1d03ace5c91c5357a2b
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 19:13:07 2009 +0200
rework tunneling code
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index c148884..7f303f1 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -145,6 +145,7 @@ static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t t
static void command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
static void command_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
static void command_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
+static void command_stream_or_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
#ifdef TUNNEL_SINK
@@ -159,7 +160,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = command_suspended,
[PA_COMMAND_RECORD_STREAM_SUSPENDED] = command_suspended,
[PA_COMMAND_PLAYBACK_STREAM_MOVED] = command_moved,
- [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved
+ [PA_COMMAND_RECORD_STREAM_MOVED] = command_moved,
+ [PA_COMMAND_PLAYBACK_STREAM_EVENT] = command_stream_or_client_event,
+ [PA_COMMAND_RECORD_STREAM_EVENT] = command_stream_or_client_event,
+ [PA_COMMAND_CLIENT_EVENT] = command_stream_or_client_event
};
struct userdata {
@@ -196,8 +200,8 @@ struct userdata {
pa_bool_t remote_corked:1;
pa_bool_t remote_suspended:1;
- pa_usec_t transport_usec;
- pa_bool_t transport_usec_valid;
+ pa_usec_t transport_usec; /* maintained in the main thread */
+ pa_usec_t thread_transport_usec; /* maintained in the IO thread */
uint32_t ignore_latency_before;
@@ -222,6 +226,11 @@ struct userdata {
static void request_latency(struct userdata *u);
/* Called from main context */
+static void command_stream_or_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
+ pa_log_debug("Got stream or client event.");
+}
+
+/* Called from main context */
static void command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct userdata *u = userdata;
@@ -261,11 +270,14 @@ static void command_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag
if (pa_tagstruct_getu32(t, &channel) < 0 ||
pa_tagstruct_get_boolean(t, &suspended) < 0 ||
!pa_tagstruct_eof(t)) {
- pa_log("Invalid packet");
+
+ pa_log("Invalid packet.");
pa_module_unload_request(u->module, TRUE);
return;
}
+ pa_log_debug("Server reports device suspend.");
+
#ifdef TUNNEL_SINK
pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_REMOTE_SUSPEND, PA_UINT32_TO_PTR(!!suspended), 0, NULL);
#else
@@ -278,13 +290,33 @@ static void command_suspended(pa_pdispatch *pd, uint32_t command, uint32_t tag
/* Called from main context */
static void command_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct userdata *u = userdata;
+ uint32_t channel, di;
+ const char *dn;
+ pa_bool_t suspended;
pa_assert(pd);
pa_assert(t);
pa_assert(u);
pa_assert(u->pdispatch == pd);
+ if (pa_tagstruct_getu32(t, &channel) < 0 ||
+ pa_tagstruct_getu32(t, &di) < 0 ||
+ pa_tagstruct_gets(t, &dn) < 0 ||
+ pa_tagstruct_get_boolean(t, &suspended) < 0) {
+
+ pa_log_error("Invalid packet.");
+ pa_module_unload_request(u->module, TRUE);
+ return;
+ }
+
pa_log_debug("Server reports a stream move.");
+
+#ifdef TUNNEL_SINK
+ pa_asyncmsgq_send(u->sink->asyncmsgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_REMOTE_SUSPEND, PA_UINT32_TO_PTR(!!suspended), 0, NULL);
+#else
+ pa_asyncmsgq_send(u->source->asyncmsgq, PA_MSGOBJECT(u->source), SOURCE_MESSAGE_REMOTE_SUSPEND, PA_UINT32_TO_PTR(!!suspended), 0, NULL);
+#endif
+
request_latency(u);
}
@@ -306,21 +338,21 @@ static void command_started(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
#endif
/* Called from IO thread context */
-static void stream_cork_within_thread(struct userdata *u, pa_bool_t cork) {
+static void check_smoother_status(struct userdata *u, pa_bool_t past) {
pa_usec_t x;
- pa_assert(u);
- if (u->remote_corked == cork)
- return;
+ pa_assert(u);
- u->remote_corked = cork;
x = pa_rtclock_usec();
- /* Correct by the time this needs to travel to the other side.
- * This is a valid thread-safe access, because the main thread is
- * waiting for us */
- if (u->transport_usec_valid)
- x += u->transport_usec;
+ /* Correct by the time the requested issued needs to travel to the
+ * other side. This is a valid thread-safe access, because the
+ * main thread is waiting for us */
+
+ if (past)
+ x -= u->thread_transport_usec;
+ else
+ x += u->thread_transport_usec;
if (u->remote_suspended || u->remote_corked)
pa_smoother_pause(u->smoother, x);
@@ -328,6 +360,17 @@ static void stream_cork_within_thread(struct userdata *u, pa_bool_t cork) {
pa_smoother_resume(u->smoother, x);
}
+/* Called from IO thread context */
+static void stream_cork_within_thread(struct userdata *u, pa_bool_t cork) {
+ pa_assert(u);
+
+ if (u->remote_corked == cork)
+ return;
+
+ u->remote_corked = cork;
+ check_smoother_status(u, FALSE);
+}
+
/* Called from main context */
static void stream_cork(struct userdata *u, pa_bool_t cork) {
pa_tagstruct *t;
@@ -352,26 +395,13 @@ static void stream_cork(struct userdata *u, pa_bool_t cork) {
/* Called from IO thread context */
static void stream_suspend_within_thread(struct userdata *u, pa_bool_t suspend) {
- pa_usec_t x;
pa_assert(u);
if (u->remote_suspended == suspend)
return;
u->remote_suspended = suspend;
-
- x = pa_rtclock_usec();
-
- /* Correct by the time this needed to travel from the other side.
- * This is a valid thread-safe access, because the main thread is
- * waiting for us */
- if (u->transport_usec_valid)
- x -= u->transport_usec;
-
- if (u->remote_suspended || u->remote_corked)
- pa_smoother_pause(u->smoother, x);
- else
- pa_smoother_resume(u->smoother, x);
+ check_smoother_status(u, TRUE);
}
#ifdef TUNNEL_SINK
@@ -446,13 +476,16 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
y = pa_bytes_to_usec((uint64_t) u->counter, &u->sink->sample_spec);
- if (y > (pa_usec_t) offset || offset < 0)
+ if (y > (pa_usec_t) offset)
y -= (pa_usec_t) offset;
else
y = 0;
pa_smoother_put(u->smoother, pa_rtclock_usec(), y);
+ /* We can access this freely here, since the main thread is waiting for us */
+ u->thread_transport_usec = u->transport_usec;
+
return 0;
}
@@ -546,14 +579,13 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
pa_usec_t y;
y = pa_bytes_to_usec((uint64_t) u->counter, &u->source->sample_spec);
-
- if (offset >= 0 || y > (pa_usec_t) -offset)
- y += (pa_usec_t) offset;
- else
- y = 0;
+ y += (pa_usec_t) offset;
pa_smoother_put(u->smoother, pa_rtclock_usec(), y);
+ /* We can access this freely here, since the main thread is waiting for us */
+ u->thread_transport_usec = u->transport_usec;
+
return 0;
}
}
@@ -606,7 +638,7 @@ static void thread_func(void *userdata) {
#ifdef TUNNEL_SINK
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
- if (u->sink->thread_info.rewind_requested)
+ if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
pa_sink_process_rewind(u->sink, 0);
#endif
@@ -662,7 +694,7 @@ fail:
/* Called from main context */
static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct userdata *u = userdata;
- pa_usec_t sink_usec, source_usec, transport_usec = 0;
+ pa_usec_t sink_usec, source_usec;
pa_bool_t playing;
int64_t write_index, read_index;
struct timeval local, remote, now;
@@ -709,7 +741,6 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
}
if (tag < u->ignore_latency_before) {
- request_latency(u);
return;
}
@@ -725,7 +756,6 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
#endif
} else
u->transport_usec = pa_timeval_diff(&now, &local)/2;
- u->transport_usec_valid = TRUE;
/* First, take the device's delay */
#ifdef TUNNEL_SINK
@@ -745,9 +775,9 @@ static void stream_get_latency_callback(pa_pdispatch *pd, uint32_t command, uint
/* Our measurements are already out of date, hence correct by the *
* transport latency */
#ifdef TUNNEL_SINK
- delay -= (int64_t) transport_usec;
+ delay -= (int64_t) u->transport_usec;
#else
- delay += (int64_t) transport_usec;
+ delay += (int64_t) u->transport_usec;
#endif
/* Now correct by what we have have read/written since we requested the update */
@@ -786,8 +816,7 @@ static void request_latency(struct userdata *u) {
pa_tagstruct_putu32(t, tag = u->ctag++);
pa_tagstruct_putu32(t, u->channel);
- pa_gettimeofday(&now);
- pa_tagstruct_put_timeval(t, &now);
+ pa_tagstruct_put_timeval(t, pa_gettimeofday(&now));
pa_pstream_send_tagstruct(u->pstream, t);
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL);
@@ -861,6 +890,7 @@ static void update_description(struct userdata *u) {
static void server_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct userdata *u = userdata;
pa_sample_spec ss;
+ pa_channel_map cm;
const char *server_name, *server_version, *user_name, *host_name, *default_sink_name, *default_source_name;
uint32_t cookie;
@@ -882,7 +912,9 @@ static void server_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_gets(t, &default_sink_name) < 0 ||
pa_tagstruct_gets(t, &default_source_name) < 0 ||
- pa_tagstruct_getu32(t, &cookie) < 0) {
+ pa_tagstruct_getu32(t, &cookie) < 0 ||
+ (u->version >= 15 &&
+ pa_tagstruct_get_channel_map(t, &cm) < 0)) {
pa_log("Parse failure");
goto fail;
@@ -963,6 +995,20 @@ static void sink_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
}
}
+ if (u->version >= 15) {
+ pa_volume_t base_volume;
+ uint32_t state, n_volume_steps, card;
+
+ if (pa_tagstruct_get_volume(t, &base_volume) < 0 ||
+ pa_tagstruct_getu32(t, &state) < 0 ||
+ pa_tagstruct_getu32(t, &n_volume_steps) < 0 ||
+ pa_tagstruct_getu32(t, &card) < 0) {
+
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
pa_log("Packet too long");
goto fail;
@@ -1059,12 +1105,11 @@ static void sink_input_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag
pa_cvolume_equal(&volume, &u->sink->virtual_volume))
return;
- memcpy(&u->sink->virtual_volume, &volume, sizeof(pa_cvolume));
+ pa_sink_volume_changed(u->sink, &volume);
if (u->version >= 11)
- u->sink->muted = !!mute;
+ pa_sink_mute_changed(u->sink, mute);
- pa_subscription_post(u->sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, u->sink->index);
return;
fail:
@@ -1126,6 +1171,20 @@ static void source_info_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa
}
}
+ if (u->version >= 15) {
+ pa_volume_t base_volume;
+ uint32_t state, n_volume_steps, card;
+
+ if (pa_tagstruct_get_volume(t, &base_volume) < 0 ||
+ pa_tagstruct_getu32(t, &state) < 0 ||
+ pa_tagstruct_getu32(t, &n_volume_steps) < 0 ||
+ pa_tagstruct_getu32(t, &card) < 0) {
+
+ pa_log("Parse failure");
+ goto fail;
+ }
+ }
+
if (!pa_tagstruct_eof(t)) {
pa_log("Packet too long");
goto fail;
@@ -1314,11 +1373,11 @@ static void create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t
if (pa_tagstruct_get_usec(t, &usec) < 0)
goto parse_error;
-#ifdef TUNNEL_SINK
- pa_sink_set_latency_range(u->sink, usec + MIN_NETWORK_LATENCY_USEC, 0);
-#else
- pa_source_set_latency_range(u->source, usec + MIN_NETWORK_LATENCY_USEC, 0);
-#endif
+/* #ifdef TUNNEL_SINK */
+/* pa_sink_set_latency_range(u->sink, usec + MIN_NETWORK_LATENCY_USEC, 0); */
+/* #else */
+/* pa_source_set_latency_range(u->source, usec + MIN_NETWORK_LATENCY_USEC, 0); */
+/* #endif */
}
if (!pa_tagstruct_eof(t))
@@ -1391,11 +1450,17 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
pa_log_debug("Protocol version: remote %u, local %u", u->version, PA_PROTOCOL_VERSION);
#ifdef TUNNEL_SINK
+ pa_proplist_setf(u->sink->proplist, "tunnel.remote_version", "%u", u->version);
+ pa_sink_update_proplist(u->sink, 0, NULL);
+
pa_snprintf(name, sizeof(name), "%s for %s@%s",
u->sink_name,
pa_get_user_name(un, sizeof(un)),
pa_get_host_name(hn, sizeof(hn)));
#else
+ pa_proplist_setf(u->source->proplist, "tunnel.remote_version", "%u", u->version);
+ pa_source_update_proplist(u->source, 0, NULL);
+
pa_snprintf(name, sizeof(name), "%s for %s@%s",
u->source_name,
pa_get_user_name(un, sizeof(un)),
@@ -1409,9 +1474,9 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
if (u->version >= 13) {
pa_proplist *pl;
pl = pa_proplist_new();
- pa_init_proplist(pl);
pa_proplist_sets(pl, PA_PROP_APPLICATION_ID, "org.PulseAudio.PulseAudio");
pa_proplist_sets(pl, PA_PROP_APPLICATION_VERSION, PACKAGE_VERSION);
+ pa_init_proplist(pl);
pa_tagstruct_put_proplist(reply, pl);
pa_proplist_free(pl);
} else
@@ -1503,6 +1568,14 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t
pa_tagstruct_put_boolean(reply, TRUE); /* early rquests */
}
+ if (u->version >= 15) {
+#ifdef TUNNEL_SINK
+ pa_tagstruct_put_boolean(reply, FALSE); /* muted_set */
+#endif
+ pa_tagstruct_put_boolean(reply, FALSE); /* don't inhibit auto suspend */
+ pa_tagstruct_put_boolean(reply, FALSE); /* fail on suspend */
+ }
+
pa_pstream_send_tagstruct(u->pstream, reply);
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL);
@@ -1559,7 +1632,6 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
u->counter_delta += (int64_t) chunk->length;
}
-
#endif
/* Called from main context */
@@ -1700,8 +1772,7 @@ int pa__init(pa_module*m) {
u->device_index = u->channel = PA_INVALID_INDEX;
u->time_event = NULL;
u->ignore_latency_before = 0;
- u->transport_usec = 0;
- u->transport_usec_valid = FALSE;
+ u->transport_usec = u->thread_transport_usec = 0;
u->remote_suspended = u->remote_corked = FALSE;
u->counter = u->counter_delta = 0;
@@ -1747,7 +1818,7 @@ int pa__init(pa_module*m) {
if (u->sink_name)
pa_proplist_sets(data.proplist, "tunnel.remote.sink", u->sink_name);
- u->sink = pa_sink_new(m->core, &data, PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL);
+ u->sink = pa_sink_new(m->core, &data, PA_SINK_NETWORK|PA_SINK_LATENCY|PA_SINK_HW_VOLUME_CTRL|PA_SINK_HW_MUTE_CTRL);
pa_sink_new_data_done(&data);
if (!u->sink) {
@@ -1763,7 +1834,7 @@ int pa__init(pa_module*m) {
u->sink->refresh_volume = u->sink->refresh_muted = FALSE;
- pa_sink_set_latency_range(u->sink, MIN_NETWORK_LATENCY_USEC, 0);
+/* pa_sink_set_latency_range(u->sink, MIN_NETWORK_LATENCY_USEC, 0); */
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
@@ -1797,7 +1868,7 @@ int pa__init(pa_module*m) {
u->source->set_state = source_set_state;
u->source->userdata = u;
- pa_source_set_latency_range(u->source, MIN_NETWORK_LATENCY_USEC, 0);
+/* pa_source_set_latency_range(u->source, MIN_NETWORK_LATENCY_USEC, 0); */
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
commit 061344fbd78f4a643f4e2a12b24c5d1ae1622e04
Merge: aa68036 87d63b1
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 19:14:09 2009 +0200
Merge commit 'origin/master'
commit 1743322d3e184d57a80cd58e9bcfb0bf01bd4c67
Merge: 061344f 205cbe8
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 19:15:39 2009 +0200
Merge commit 'coling/master'
commit eb93e2537a60db963bac84e189c52b3d83521c63
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Thu Mar 19 01:35:02 2009 +0200
dbus: split dbus-util into dbus-shared
modules: fix dbus-util include
pulse: get dbus at context connection
diff --git a/src/Makefile.am b/src/Makefile.am
index a99e275..0d4f53a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -633,6 +633,12 @@ if OS_IS_WIN32
libpulsecommon_ at PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dllmain.c
endif
+if HAVE_DBUS
+libpulsecommon_ at PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dbus-util.c pulsecore/dbus-util.h
+libpulsecommon_ at PA_MAJORMINORMICRO@_la_CFLAGS += $(DBUS_CFLAGS)
+libpulsecommon_ at PA_MAJORMINORMICRO@_la_LIBADD += $(DBUS_LIBS)
+endif
+
###################################
# Client library #
###################################
@@ -713,7 +719,7 @@ libpulse_la_SOURCES = \
pulse/volume.c pulse/volume.h \
pulse/xmalloc.c pulse/xmalloc.h
-libpulse_la_CFLAGS = $(AM_CFLAGS)
+libpulse_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
libpulse_la_LIBADD = $(AM_LIBADD) $(WINSOCK_LIBS) $(LTLIBICONV) libpulsecommon- at PA_MAJORMINORMICRO@.la
libpulse_la_LDFLAGS = $(AM_LDFLAGS) $(VERSIONING_LDFLAGS) -version-info $(LIBPULSE_VERSION_INFO)
@@ -813,6 +819,13 @@ libpulsecore_ at PA_MAJORMINORMICRO@_la_CFLAGS += $(X11_CFLAGS)
libpulsecore_ at PA_MAJORMINORMICRO@_la_LDFLAGS += $(X11_LIBS)
endif
+
+if HAVE_DBUS
+libpulsecore_ at PA_MAJORMINORMICRO@_la_SOURCES += pulsecore/dbus-shared.c pulsecore/dbus-shared.h
+libpulsecore_ at PA_MAJORMINORMICRO@_la_CFLAGS += $(DBUS_CFLAGS)
+libpulsecore_ at PA_MAJORMINORMICRO@_la_LIBADD += $(DBUS_LIBS)
+endif
+
# We split the foreign code off to not be annoyed by warnings we don't care about
noinst_LTLIBRARIES = libpulsecore-foreign.la
@@ -902,7 +915,6 @@ libavahi_wrap_la_LIBADD = $(AM_LIBADD) $(AVAHI_CFLAGS) libpulsecore- at PA_MAJORMIN
if HAVE_DBUS
# Serveral module (e.g. libalsa-util.la)
modlibexec_LTLIBRARIES += \
- libdbus-util.la \
module-console-kit.la
endif
@@ -1322,7 +1334,7 @@ endif
if HAVE_DBUS
libalsa_util_la_SOURCES += modules/reserve.h modules/reserve.c modules/reserve-wrap.c modules/reserve-wrap.h
-libalsa_util_la_LIBADD += $(DBUS_LIBS) libdbus-util.la
+libalsa_util_la_LIBADD += $(DBUS_LIBS)
libalsa_util_la_CFLAGS += $(DBUS_CFLAGS)
endif
@@ -1476,20 +1488,14 @@ module_jack_source_la_LDFLAGS = $(MODULE_LDFLAGS)
module_jack_source_la_LIBADD = $(AM_LIBADD) libpulsecore- at PA_MAJORMINORMICRO@.la $(JACK_LIBS) libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_jack_source_la_CFLAGS = $(AM_CFLAGS) $(JACK_CFLAGS)
-# HAL/D-Bus
-libdbus_util_la_SOURCES = modules/dbus-util.c modules/dbus-util.h
-libdbus_util_la_LDFLAGS = -avoid-version
-libdbus_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
-libdbus_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
-
module_hal_detect_la_SOURCES = modules/module-hal-detect.c
module_hal_detect_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_hal_detect_la_LIBADD = $(AM_LIBADD) $(HAL_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_hal_detect_la_CFLAGS = $(AM_CFLAGS) $(HAL_CFLAGS)
module_console_kit_la_SOURCES = modules/module-console-kit.c
module_console_kit_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_console_kit_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_console_kit_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
# GConf support
@@ -1506,7 +1512,7 @@ gconf_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
# Bluetooth proximity
module_bluetooth_proximity_la_SOURCES = modules/bluetooth/module-bluetooth-proximity.c
module_bluetooth_proximity_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libdbus-util.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_bluetooth_proximity_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_bluetooth_proximity_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS) -DPA_BT_PROXIMITY_HELPER=\"$(pulselibexecdir)/proximity-helper\"
proximity_helper_SOURCES = modules/bluetooth/proximity-helper.c
@@ -1517,7 +1523,7 @@ proximity_helper_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
# Bluetooth sink / source
module_bluetooth_discover_la_SOURCES = modules/bluetooth/module-bluetooth-discover.c
module_bluetooth_discover_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libdbus-util.la libbluetooth-util.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_bluetooth_discover_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libbluetooth-util.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_bluetooth_discover_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
libbluetooth_sbc_la_SOURCES = modules/bluetooth/sbc.c modules/bluetooth/sbc.h modules/bluetooth/sbc_tables.h modules/bluetooth/sbc_math.h modules/bluetooth/sbc_primitives.h modules/bluetooth/sbc_primitives.c modules/bluetooth/sbc_primitives_mmx.h modules/bluetooth/sbc_primitives_neon.h modules/bluetooth/sbc_primitives_mmx.c modules/bluetooth/sbc_primitives_neon.c
@@ -1534,12 +1540,12 @@ BLUETOOTH_IPC_FILES = $(subst modules/bluetooth/,,$(libbluetooth_ipc_la_SOURCES)
libbluetooth_util_la_SOURCES = modules/bluetooth/bluetooth-util.c modules/bluetooth/bluetooth-util.h
libbluetooth_util_la_LDFLAGS = -avoid-version
-libbluetooth_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la libdbus-util.la
+libbluetooth_util_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
libbluetooth_util_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
module_bluetooth_device_la_SOURCES = modules/bluetooth/module-bluetooth-device.c modules/bluetooth/rtp.h
module_bluetooth_device_la_LDFLAGS = $(MODULE_LDFLAGS)
-module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libdbus-util.la libbluetooth-util.la libbluetooth-ipc.la libbluetooth-sbc.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
+module_bluetooth_device_la_LIBADD = $(AM_LIBADD) $(DBUS_LIBS) libpulsecore- at PA_MAJORMINORMICRO@.la libbluetooth-util.la libbluetooth-ipc.la libbluetooth-sbc.la libpulsecommon- at PA_MAJORMINORMICRO@.la libpulse.la
module_bluetooth_device_la_CFLAGS = $(AM_CFLAGS) $(DBUS_CFLAGS)
# Apple Airtunes/RAOP
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 3dfc65e..1cdade9 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -25,7 +25,7 @@
#include <pulsecore/core-util.h>
#include <pulsecore/shared.h>
-#include <modules/dbus-util.h>
+#include <pulsecore/dbus-shared.h>
#include "bluetooth-util.h"
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2500fb0..2ff64ba 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -46,8 +46,7 @@
#include <pulsecore/time-smoother.h>
#include <pulsecore/rtclock.h>
#include <pulsecore/namereg.h>
-
-#include <modules/dbus-util.h>
+#include <pulsecore/dbus-shared.h>
#include "module-bluetooth-device-symdef.h"
#include "ipc.h"
diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 3288cc5..46f8b72 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -34,7 +34,7 @@
#include <pulsecore/macro.h>
#include <pulsecore/llist.h>
#include <pulsecore/core-util.h>
-#include <modules/dbus-util.h>
+#include <pulsecore/dbus-shared.h>
#include "module-bluetooth-discover-symdef.h"
#include "bluetooth-util.h"
diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c
index c8d7b4d..9993c8d 100644
--- a/src/modules/bluetooth/module-bluetooth-proximity.c
+++ b/src/modules/bluetooth/module-bluetooth-proximity.c
@@ -42,8 +42,8 @@
#include <pulsecore/core-util.h>
#include <pulsecore/core-error.h>
#include <pulsecore/start-child.h>
+#include <pulsecore/dbus-shared.h>
-#include "../dbus-util.h"
#include "module-bluetooth-proximity-symdef.h"
PA_MODULE_AUTHOR("Lennart Poettering");
diff --git a/src/modules/hal-util.c b/src/modules/hal-util.c
index 422ae4e..e2a2d8d 100644
--- a/src/modules/hal-util.c
+++ b/src/modules/hal-util.c
@@ -24,10 +24,10 @@
#endif
#include <pulsecore/log.h>
+#include <pulsecore/dbus-shared.h>
#include <hal/libhal.h>
-#include "dbus-util.h"
#include "hal-util.h"
int pa_hal_get_info(pa_core *core, pa_proplist *p, int card) {
diff --git a/src/modules/module-console-kit.c b/src/modules/module-console-kit.c
index 3fba7ef..a666073 100644
--- a/src/modules/module-console-kit.c
+++ b/src/modules/module-console-kit.c
@@ -44,8 +44,8 @@
#include <pulsecore/namereg.h>
#include <pulsecore/core-scache.h>
#include <pulsecore/modargs.h>
+#include <pulsecore/dbus-shared.h>
-#include "dbus-util.h"
#include "module-console-kit-symdef.h"
PA_MODULE_AUTHOR("Lennart Poettering");
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 9b0d71c..0dd22cb 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -45,10 +45,10 @@
#include <pulsecore/namereg.h>
#include <pulsecore/core-scache.h>
#include <pulsecore/modargs.h>
+#include <pulsecore/dbus-shared.h>
#include <hal/libhal.h>
-#include "dbus-util.h"
#include "module-hal-detect-symdef.h"
PA_MODULE_AUTHOR("Shahms King");
diff --git a/src/modules/reserve-wrap.c b/src/modules/reserve-wrap.c
index c956673..1927342 100644
--- a/src/modules/reserve-wrap.c
+++ b/src/modules/reserve-wrap.c
@@ -29,8 +29,7 @@
#include <pulsecore/core-error.h>
#include <pulsecore/core-util.h>
#include <pulsecore/shared.h>
-
-#include <modules/dbus-util.h>
+#include <pulsecore/dbus-shared.h>
#include "reserve.h"
#include "reserve-wrap.h"
diff --git a/src/pulsecore/dbus-shared.c b/src/pulsecore/dbus-shared.c
new file mode 100644
index 0000000..b52c14c
--- /dev/null
+++ b/src/pulsecore/dbus-shared.c
@@ -0,0 +1,111 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006, 2009 Lennart Poettering
+ Copyright 2006 Shams E. King
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+
+#include <pulse/xmalloc.h>
+#include <pulse/timeval.h>
+#include <pulsecore/log.h>
+#include <pulsecore/shared.h>
+
+#include "dbus-shared.h"
+
+struct pa_dbus_connection {
+ PA_REFCNT_DECLARE;
+
+ pa_dbus_wrap_connection *connection;
+ pa_core *core;
+ const char *property_name;
+};
+
+static pa_dbus_connection* pa_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);
+ PA_REFCNT_INIT(pconn);
+ pconn->core = c;
+ pconn->property_name = name;
+ pconn->connection = conn;
+
+ pa_shared_set(c, name, pconn);
+
+ return pconn;
+}
+
+pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) {
+
+ static const char *const prop_name[] = {
+ [DBUS_BUS_SESSION] = "dbus-connection-session",
+ [DBUS_BUS_SYSTEM] = "dbus-connection-system",
+ [DBUS_BUS_STARTER] = "dbus-connection-starter"
+ };
+ pa_dbus_wrap_connection *conn;
+ pa_dbus_connection *pconn;
+
+ pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER);
+
+ if ((pconn = pa_shared_get(c, prop_name[type])))
+ return pa_dbus_connection_ref(pconn);
+
+ 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;
+}
+
+DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) > 0);
+ pa_assert(c->connection);
+
+ return pa_dbus_wrap_connection_get(c->connection);
+}
+
+void pa_dbus_connection_unref(pa_dbus_connection *c) {
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) > 0);
+
+ if (PA_REFCNT_DEC(c) > 0)
+ return;
+
+ /* already disconnected, just free */
+ pa_shared_remove(c->core, c->property_name);
+ pa_xfree(c);
+}
+
+pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) {
+ pa_assert(c);
+ pa_assert(PA_REFCNT_VALUE(c) > 0);
+
+ PA_REFCNT_INC(c);
+
+ return c;
+}
+
+
+
diff --git a/src/pulsecore/dbus-shared.h b/src/pulsecore/dbus-shared.h
new file mode 100644
index 0000000..4c15455
--- /dev/null
+++ b/src/pulsecore/dbus-shared.h
@@ -0,0 +1,42 @@
+#ifndef foodbussharedhfoo
+#define foodbussharedhfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006, 2009 Lennart Poettering
+ Copyright 2006 Shams E. King
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include <dbus/dbus.h>
+
+#include <pulsecore/core.h>
+#include <pulsecore/dbus-util.h>
+
+typedef struct pa_dbus_connection pa_dbus_connection;
+
+/* return a pa_dbus_connection of the specified type for the given core,
+ * like dbus_bus_get(), but integrates the connection with the pa_core */
+pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error);
+
+DBusConnection* pa_dbus_connection_get(pa_dbus_connection *conn);
+
+pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *conn);
+void pa_dbus_connection_unref(pa_dbus_connection *conn);
+
+#endif
diff --git a/src/modules/dbus-util.c b/src/pulsecore/dbus-util.c
similarity index 80%
rename from src/modules/dbus-util.c
rename to src/pulsecore/dbus-util.c
index e2d4580..d712bff 100644
--- a/src/modules/dbus-util.c
+++ b/src/pulsecore/dbus-util.c
@@ -29,16 +29,12 @@
#include <pulse/xmalloc.h>
#include <pulse/timeval.h>
#include <pulsecore/log.h>
-#include <pulsecore/shared.h>
#include "dbus-util.h"
-struct pa_dbus_connection {
- PA_REFCNT_DECLARE;
-
- pa_core *core;
+struct pa_dbus_wrap_connection {
+ pa_mainloop_api *mainloop;
DBusConnection *connection;
- const char *property_name;
pa_defer_event* dispatch_event;
};
@@ -53,20 +49,20 @@ static void dispatch_cb(pa_mainloop_api *ea, pa_defer_event *ev, void *userdata)
/* DBusDispatchStatusFunction callback for the pa mainloop */
static void dispatch_status(DBusConnection *conn, DBusDispatchStatus status, void *userdata) {
- pa_dbus_connection *c = userdata;
+ pa_dbus_wrap_connection *c = userdata;
pa_assert(c);
switch(status) {
case DBUS_DISPATCH_COMPLETE:
- c->core->mainloop->defer_enable(c->dispatch_event, 0);
+ c->mainloop->defer_enable(c->dispatch_event, 0);
break;
case DBUS_DISPATCH_DATA_REMAINS:
case DBUS_DISPATCH_NEED_MEMORY:
default:
- c->core->mainloop->defer_enable(c->dispatch_event, 1);
+ c->mainloop->defer_enable(c->dispatch_event, 1);
break;
}
}
@@ -135,7 +131,7 @@ static void handle_time_event(pa_mainloop_api *ea, pa_time_event* e, const struc
/* DBusAddWatchFunction callback for pa mainloop */
static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_io_event *ev;
pa_assert(watch);
@@ -157,7 +153,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) {
/* DBusRemoveWatchFunction callback for pa mainloop */
static void remove_watch(DBusWatch *watch, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_io_event *ev;
pa_assert(watch);
@@ -169,11 +165,11 @@ static void remove_watch(DBusWatch *watch, void *data) {
/* DBusWatchToggledFunction callback for pa mainloop */
static void toggle_watch(DBusWatch *watch, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_io_event *ev;
pa_assert(watch);
- pa_core_assert_ref(c);
+ pa_assert(c);
pa_assert_se(ev = dbus_watch_get_data(watch));
@@ -183,7 +179,7 @@ static void toggle_watch(DBusWatch *watch, void *data) {
/* DBusAddTimeoutFunction callback for pa mainloop */
static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_time_event *ev;
struct timeval tv;
@@ -205,7 +201,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) {
/* DBusRemoveTimeoutFunction callback for pa mainloop */
static void remove_timeout(DBusTimeout *timeout, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_time_event *ev;
pa_assert(timeout);
@@ -217,7 +213,7 @@ static void remove_timeout(DBusTimeout *timeout, void *data) {
/* DBusTimeoutToggledFunction callback for pa mainloop */
static void toggle_timeout(DBusTimeout *timeout, void *data) {
- pa_core *c = PA_CORE(data);
+ pa_dbus_wrap_connection *c = data;
pa_time_event *ev;
pa_assert(timeout);
@@ -237,95 +233,59 @@ static void toggle_timeout(DBusTimeout *timeout, void *data) {
}
static void wakeup_main(void *userdata) {
- pa_dbus_connection *c = userdata;
+ pa_dbus_wrap_connection *c = userdata;
pa_assert(c);
/* this will wakeup the mainloop and dispatch events, although
* it may not be the cleanest way of accomplishing it */
- c->core->mainloop->defer_enable(c->dispatch_event, 1);
+ c->mainloop->defer_enable(c->dispatch_event, 1);
}
-static pa_dbus_connection* pa_dbus_connection_new(pa_core* c, DBusConnection *conn, const char* name) {
- pa_dbus_connection *pconn;
+pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *m, DBusBusType type, DBusError *error) {
+ DBusConnection *conn;
+ pa_dbus_wrap_connection *pconn = NULL;
- pconn = pa_xnew(pa_dbus_connection, 1);
- PA_REFCNT_INIT(pconn);
- pconn->core = c;
- pconn->property_name = name;
- pconn->connection = conn;
- pconn->dispatch_event = c->mainloop->defer_new(c->mainloop, dispatch_cb, conn);
+ pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER);
- pa_shared_set(c, name, pconn);
+ if (!(conn = dbus_bus_get_private(type, error)))
+ return NULL;
- return pconn;
-}
+ pconn = pa_xnew(pa_dbus_wrap_connection, 1);
+ pconn->mainloop = m;
+ pconn->connection = conn;
-DBusConnection* pa_dbus_connection_get(pa_dbus_connection *c){
- pa_assert(c);
- pa_assert(PA_REFCNT_VALUE(c) > 0);
- pa_assert(c->connection);
+ dbus_connection_set_exit_on_disconnect(conn, FALSE);
+ dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL);
+ dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, pconn, NULL);
+ dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, pconn, NULL);
+ dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL);
+
+ pconn->dispatch_event = pconn->mainloop->defer_new(pconn->mainloop, dispatch_cb, conn);
- return c->connection;
+ return pconn;
}
-void pa_dbus_connection_unref(pa_dbus_connection *c) {
+void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* c) {
pa_assert(c);
- pa_assert(PA_REFCNT_VALUE(c) > 0);
-
- if (PA_REFCNT_DEC(c) > 0)
- return;
if (dbus_connection_get_is_connected(c->connection)) {
dbus_connection_close(c->connection);
- /* must process remaining messages, bit of a kludge to handle
+ /* must process remaining messages, bit of a kludge to handle
* both unload and shutdown */
while (dbus_connection_read_write_dispatch(c->connection, -1));
}
- /* already disconnected, just free */
- pa_shared_remove(c->core, c->property_name);
- c->core->mainloop->defer_free(c->dispatch_event);
+ c->mainloop->defer_free(c->dispatch_event);
dbus_connection_unref(c->connection);
pa_xfree(c);
}
-pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *c) {
- pa_assert(c);
- pa_assert(PA_REFCNT_VALUE(c) > 0);
+DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *c) {
+ pa_assert(c);
+ pa_assert(c->connection);
- PA_REFCNT_INC(c);
-
- return c;
-}
-
-pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error) {
-
- static const char *const prop_name[] = {
- [DBUS_BUS_SESSION] = "dbus-connection-session",
- [DBUS_BUS_SYSTEM] = "dbus-connection-system",
- [DBUS_BUS_STARTER] = "dbus-connection-starter"
- };
- DBusConnection *conn;
- pa_dbus_connection *pconn;
-
- pa_assert(type == DBUS_BUS_SYSTEM || type == DBUS_BUS_SESSION || type == DBUS_BUS_STARTER);
-
- if ((pconn = pa_shared_get(c, prop_name[type])))
- return pa_dbus_connection_ref(pconn);
-
- if (!(conn = dbus_bus_get_private(type, error)))
- return NULL;
-
- pconn = pa_dbus_connection_new(c, conn, prop_name[type]);
-
- dbus_connection_set_exit_on_disconnect(conn, FALSE);
- dbus_connection_set_dispatch_status_function(conn, dispatch_status, pconn, NULL);
- dbus_connection_set_watch_functions(conn, add_watch, remove_watch, toggle_watch, c, NULL);
- dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, toggle_timeout, c, NULL);
- dbus_connection_set_wakeup_main_function(conn, wakeup_main, pconn, NULL);
-
- return pconn;
+ return c->connection;
}
int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) {
diff --git a/src/modules/dbus-util.h b/src/pulsecore/dbus-util.h
similarity index 74%
rename from src/modules/dbus-util.h
rename to src/pulsecore/dbus-util.h
index 554f41a..55cda7a 100644
--- a/src/modules/dbus-util.h
+++ b/src/pulsecore/dbus-util.h
@@ -24,27 +24,22 @@
#include <dbus/dbus.h>
-#include <pulsecore/core.h>
#include <pulsecore/llist.h>
+#include <pulse/mainloop-api.h>
-typedef struct pa_dbus_connection pa_dbus_connection;
+/* A wrap connection is not shared or refcounted, it is available in client side */
+typedef struct pa_dbus_wrap_connection pa_dbus_wrap_connection;
-/* return the DBusConnection of the specified type for the given core,
- * like dbus_bus_get(), but integrates the connection with the pa_core */
-pa_dbus_connection* pa_dbus_bus_get(pa_core *c, DBusBusType type, DBusError *error);
+pa_dbus_wrap_connection* pa_dbus_wrap_connection_new(pa_mainloop_api *mainloop, DBusBusType type, DBusError *error);
+void pa_dbus_wrap_connection_free(pa_dbus_wrap_connection* conn);
-DBusConnection* pa_dbus_connection_get(pa_dbus_connection *conn);
-
-pa_dbus_connection* pa_dbus_connection_ref(pa_dbus_connection *conn);
-void pa_dbus_connection_unref(pa_dbus_connection *conn);
+DBusConnection* pa_dbus_wrap_connection_get(pa_dbus_wrap_connection *conn);
int pa_dbus_add_matches(DBusConnection *c, DBusError *error, ...) PA_GCC_SENTINEL;
void pa_dbus_remove_matches(DBusConnection *c, ...) PA_GCC_SENTINEL;
typedef struct pa_dbus_pending pa_dbus_pending;
-struct userdata; /* We leave the actual definition to the caller */
-
struct pa_dbus_pending {
DBusConnection *connection;
DBusMessage *message;
commit b4ef64d198016816568b7b1285afcffeb6fa8382
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 20 18:39:30 2009 +0200
daemon: take org.pulseaudio
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 47ca267..1d54348 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -87,6 +87,9 @@
#include <pulsecore/thread.h>
#include <pulsecore/once.h>
#include <pulsecore/shm.h>
+#ifdef HAVE_DBUS
+#include <pulsecore/dbus-shared.h>
+#endif
#include "cmdline.h"
#include "cpulimit.h"
@@ -330,6 +333,31 @@ static void set_all_rlimits(const pa_daemon_conf *conf) {
}
#endif
+#ifdef HAVE_DBUS
+static void register_org_pulseaudio(pa_core *c)
+{
+ DBusError error;
+ pa_dbus_connection *conn;
+
+ dbus_error_init(&error);
+ if (!(conn = pa_dbus_bus_get(c, pa_in_system_mode() ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
+ pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
+ goto finish_dbus;
+ }
+
+ if (dbus_bus_request_name (pa_dbus_connection_get(conn), "org.pulseaudio", 0, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ pa_log_debug("Got org.pulseaudio!");
+ else if (dbus_error_is_set(&error))
+ pa_log_warn("Unable to get org.pulseaudio: %s: %s", error.name, error.message);
+
+finish_dbus:
+ if (conn)
+ pa_dbus_connection_unref(conn);
+
+ dbus_error_free(&error);
+}
+#endif
+
int main(int argc, char *argv[]) {
pa_core *c = NULL;
pa_strbuf *buf = NULL;
@@ -997,6 +1025,10 @@ int main(int argc, char *argv[]) {
}
#endif
+#ifdef HAVE_DBUS
+ register_org_pulseaudio(c);
+#endif
+
pa_log_info(_("Daemon startup complete."));
retval = 0;
commit 1dad83b73c625a8576466b63bb80d666394d9b93
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 20 16:51:28 2009 +0200
pulse: client connect to dbus
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 00dffc2..a18a642 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -102,6 +102,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_CLIENT_EVENT] = pa_command_client_event
};
static void context_free(pa_context *c);
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata);
pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
return pa_context_new_with_proplist(mainloop, name, NULL);
@@ -141,6 +142,8 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
if (name)
pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
+ c->no_fail = FALSE;
+ c->system_bus = c->session_bus = NULL;
c->mainloop = mainloop;
c->client = NULL;
c->pstream = NULL;
@@ -235,6 +238,16 @@ static void context_free(pa_context *c) {
context_unlink(c);
+ if (c->system_bus) {
+ dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c);
+ pa_dbus_wrap_connection_free(c->system_bus);
+ }
+
+ if (c->session_bus) {
+ dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c);
+ pa_dbus_wrap_connection_free(c->session_bus);
+ }
+
if (c->record_streams)
pa_dynarray_free(c->record_streams, NULL, NULL);
if (c->playback_streams)
@@ -726,6 +739,32 @@ fail:
static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata);
+static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wrap_connection **conn) {
+ DBusError error;
+
+ pa_assert(c);
+ pa_assert(conn);
+
+ dbus_error_init(&error);
+ if (!(*conn = pa_dbus_wrap_connection_new(c->mainloop, type, &error)) || dbus_error_is_set(&error)) {
+ pa_log_warn("Unable to contact DBUS: %s: %s", error.name, error.message);
+ goto finish;
+ }
+
+ if (!dbus_connection_add_filter(pa_dbus_wrap_connection_get(*conn), filter_cb, c, NULL)) {
+ pa_log_warn("Failed to add filter function");
+ goto finish;
+ }
+
+ if (pa_dbus_add_matches(
+ pa_dbus_wrap_connection_get(*conn), &error,
+ "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio',arg1=''", NULL) < 0)
+ pa_log_warn("Unable to track org.pulseaudio: %s: %s", error.name, error.message);
+
+ finish:
+ dbus_error_free(&error);
+}
+
static int try_next_connection(pa_context *c) {
char *u = NULL;
int r = -1;
@@ -758,7 +797,14 @@ static int try_next_connection(pa_context *c) {
}
#endif
- pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
+ if (c->no_fail) {
+ if (!c->system_bus)
+ track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus);
+ if (!c->session_bus)
+ track_pulseaudio_on_dbus(c, DBUS_BUS_SESSION, &c->session_bus);
+ } else
+ pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
+
goto finish;
}
@@ -815,6 +861,34 @@ finish:
pa_context_unref(c);
}
+static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata) {
+ pa_context *c = userdata;
+ pa_bool_t is_session;
+
+ pa_assert(bus);
+ pa_assert(message);
+ pa_assert(c);
+
+ if (c->state != PA_CONTEXT_CONNECTING)
+ goto finish;
+
+ is_session = bus == pa_dbus_wrap_connection_get(c->session_bus);
+ pa_log_debug("Rock!! PulseAudio is baack on %s bus", is_session ? "session" : "system");
+
+ if (is_session) {
+ /* The user instance via PF_LOCAL */
+ c->server_list = prepend_per_user(c->server_list);
+ } else {
+ /* The system wide instance via PF_LOCAL */
+ c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
+ }
+
+ try_next_connection(c);
+
+finish:
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
int pa_context_connect(
pa_context *c,
const char *server,
@@ -828,7 +902,7 @@ int pa_context_connect(
PA_CHECK_VALIDITY(c, !pa_detect_fork(), PA_ERR_FORKED);
PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE);
- PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID);
+ PA_CHECK_VALIDITY(c, !(flags & ~(PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL)), PA_ERR_INVALID);
PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID);
if (!server)
@@ -836,6 +910,7 @@ int pa_context_connect(
pa_context_ref(c);
+ c->no_fail = flags & PA_CONTEXT_NOFAIL;
pa_assert(!c->server_list);
if (server) {
diff --git a/src/pulse/context.h b/src/pulse/context.h
index c32cf44..139d0e0 100644
--- a/src/pulse/context.h
+++ b/src/pulse/context.h
@@ -207,9 +207,10 @@ pa_context_state_t pa_context_get_state(pa_context *c);
connect to the default server. This routine may but will not always
return synchronously on error. Use pa_context_set_state_callback() to
be notified when the connection is established. If flags doesn't have
-PA_NOAUTOSPAWN set and no specific server is specified or accessible a
-new daemon is spawned. If api is non-NULL, the functions specified in
-the structure are used when forking a new child process. */
+PA_CONTEXT_NOAUTOSPAWN set and no specific server is specified or
+accessible a new daemon is spawned. If api is non-NULL, the functions
+specified in the structure are used when forking a new child
+process. */
int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api);
/** Terminate the context connection immediately */
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 9418e96..48b6f3e 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -109,13 +109,16 @@ typedef enum pa_operation_state {
/** Some special flags for contexts. */
typedef enum pa_context_flags {
- PA_CONTEXT_NOAUTOSPAWN = 1
+ PA_CONTEXT_NOAUTOSPAWN = 0x0001U,
/**< Disabled autospawning of the PulseAudio daemon if required */
+ PA_CONTEXT_NOFAIL = 0x0002U
+ /**< Don't fail if the daemon is not available when pa_context_connect() is called, instead enter PA_CONTEXT_CONNECTING state and wait for the daemon to appear. \since 0.9.15 */
} pa_context_flags_t;
/** \cond fulldocs */
/* Allow clients to check with #ifdef for those flags */
#define PA_CONTEXT_NOAUTOSPAWN PA_CONTEXT_NOAUTOSPAWN
+#define PA_CONTEXT_NOFAIL PA_CONTEXT_NOFAIL
/** \endcond */
/** The direction of a pa_stream object */
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 9646d8a..88b99ef 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -42,6 +42,7 @@
#include <pulsecore/hashmap.h>
#include <pulsecore/refcnt.h>
#include <pulsecore/time-smoother.h>
+#include <pulsecore/dbus-util.h>
#include "client-conf.h"
@@ -50,6 +51,10 @@
struct pa_context {
PA_REFCNT_DECLARE;
+ pa_bool_t no_fail:1;
+ pa_dbus_wrap_connection *system_bus;
+ pa_dbus_wrap_connection *session_bus;
+
pa_proplist *proplist;
pa_mainloop_api* mainloop;
commit 8491b47a5164fdff10724bfe74411791dc0ff912
Author: Marc-André Lureau <marc-andre.lureau at nokia.com>
Date: Fri Mar 27 20:41:52 2009 +0200
gtk-test: updated to use PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL
diff --git a/src/tests/gtk-test.c b/src/tests/gtk-test.c
index f82aca5..6470e48 100644
--- a/src/tests/gtk-test.c
+++ b/src/tests/gtk-test.c
@@ -29,12 +29,38 @@
#include <pulse/context.h>
#include <pulse/glib-mainloop.h>
+pa_context *ctxt;
+pa_glib_mainloop *m;
+
+static void context_state_callback(pa_context *c, void *userdata);
+
+static void connect(void) {
+ int r;
+
+ ctxt = pa_context_new(pa_glib_mainloop_get_api(m), NULL);
+ g_assert(ctxt);
+
+ r = pa_context_connect(ctxt, NULL, PA_CONTEXT_NOAUTOSPAWN|PA_CONTEXT_NOFAIL, NULL);
+ g_assert(r == 0);
+
+ pa_context_set_state_callback(ctxt, context_state_callback, NULL);
+}
+
+static void context_state_callback(pa_context *c, void *userdata) {
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_FAILED:
+ pa_context_unref(ctxt);
+ ctxt = NULL;
+ connect();
+ break;
+ default:
+ break;
+ }
+}
+
int main(int argc, char *argv[]) {
- pa_context *c;
- pa_glib_mainloop *m;
GtkWidget *window;
- int r;
gtk_init(&argc, &argv);
@@ -49,15 +75,10 @@ int main(int argc, char *argv[]) {
m = pa_glib_mainloop_new(NULL);
g_assert(m);
- c = pa_context_new(pa_glib_mainloop_get_api(m), NULL);
- g_assert(c);
-
- r = pa_context_connect(c, NULL, 0, NULL);
- g_assert(r == 0);
-
+ connect();
gtk_main();
- pa_context_unref(c);
+ pa_context_unref(ctxt);
pa_glib_mainloop_free(m);
return 0;
commit 649c982222f520fdd4afae8880c622437d4ba585
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:19:32 2009 +0200
Use pa_source_set_max_rewind_within_thread() for updating the monitor source's max_rewind
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 1fe8f59..73ad247 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -1798,7 +1798,7 @@ void pa_sink_set_max_rewind_within_thread(pa_sink *s, size_t max_rewind) {
}
if (s->monitor_source)
- pa_source_set_max_rewind(s->monitor_source, s->thread_info.max_rewind);
+ pa_source_set_max_rewind_within_thread(s->monitor_source, s->thread_info.max_rewind);
}
/* Called from main thread */
commit d33be12fde0910e4a7515c3f6a8b8f2165624cb0
Merge: 649c982 8491b47
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:26:27 2009 +0200
Merge commit 'elmarco/dbus'
diff --cc src/pulse/context.c
index 7c86a43,a18a642..9fb9e72
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@@ -99,11 -99,10 +99,12 @@@ static const pa_pdispatch_cb_t command_
[PA_COMMAND_EXTENSION] = pa_command_extension,
[PA_COMMAND_PLAYBACK_STREAM_EVENT] = pa_command_stream_event,
[PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event,
- [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event
+ [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event,
+ [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr,
+ [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr
};
static void context_free(pa_context *c);
+ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, void *userdata);
pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
return pa_context_new_with_proplist(mainloop, name, NULL);
commit 1390564227a01678f78431cd19e7c2077e962db5
Merge: d33be12 87fcb3d
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:34:49 2009 +0200
Merge commit 'elmarco/bluetooth-fixes'
commit 91355a1ce53c779849ded6db7bce85a30e4289bb
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:55:10 2009 +0200
introduce typedef for pa_bt_audio_state and use it everywhere
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 94c1d31..aaa4cc9 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -42,18 +42,17 @@ struct pa_bluetooth_discovery {
static void get_properties_reply(DBusPendingCall *pending, void *userdata);
static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, pa_bluetooth_device *d, DBusMessage *m, DBusPendingCallNotifyFunction func);
-static enum pa_bt_audio_state pa_bt_audio_state_from_string(const char* value) {
+static pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) {
pa_assert(value);
- if (pa_streq(value, "disconnected")) {
+ if (pa_streq(value, "disconnected"))
return PA_BT_AUDIO_STATE_DISCONNECTED;
- } else if (pa_streq(value, "connecting")) {
+ else if (pa_streq(value, "connecting"))
return PA_BT_AUDIO_STATE_CONNECTING;
- } else if (pa_streq(value, "connected")) {
+ else if (pa_streq(value, "connected"))
return PA_BT_AUDIO_STATE_CONNECTED;
- } else if (pa_streq(value, "playing")) {
+ else if (pa_streq(value, "playing"))
return PA_BT_AUDIO_STATE_PLAYING;
- }
return PA_BT_AUDIO_STATE_INVALID;
}
diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h
index 5411473..265caf4 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -54,14 +54,14 @@ struct pa_bluetooth_uuid {
};
/* This enum is shared among Audio, Headset, and AudioSink, although not all values are acceptable in all profiles */
-enum pa_bt_audio_state {
+typedef enum pa_bt_audio_state {
PA_BT_AUDIO_STATE_INVALID = -1,
PA_BT_AUDIO_STATE_DISCONNECTED,
PA_BT_AUDIO_STATE_CONNECTING,
PA_BT_AUDIO_STATE_CONNECTED,
PA_BT_AUDIO_STATE_PLAYING,
PA_BT_AUDIO_STATE_LAST
-};
+} pa_bt_audio_state_t;
struct pa_bluetooth_device {
pa_bool_t dead;
@@ -80,13 +80,13 @@ struct pa_bluetooth_device {
int trusted;
/* Audio state */
- int audio_state;
+ pa_bt_audio_state_t audio_state;
/* AudioSink state */
- int audio_sink_state;
+ pa_bt_audio_state_t audio_sink_state;
/* Headset state */
- int headset_state;
+ pa_bt_audio_state_t headset_state;
};
pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *core);
commit 66b80e9ecdf65861c07642a89779d7743d6888d9
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:55:50 2009 +0200
get rid of old 'Connected' property parsing and make sure we don't execute two case branches
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index aaa4cc9..02413f4 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -290,17 +290,6 @@ static int parse_audio_property(pa_bluetooth_discovery *u, int *state, DBusMessa
if (pa_streq(key, "State"))
*state = pa_bt_audio_state_from_string(value);
/* pa_log_debug("Value %s", value); */
- }
-
- case DBUS_TYPE_BOOLEAN: {
-
- dbus_bool_t value;
- dbus_message_iter_get_basic(&variant_i, &value);
-
- /* if (pa_streq(key, "Connected")) */
- /* *connected = !!value; */
-
-/* pa_log_debug("Value %s", pa_yes_no(value)); */
break;
}
commit 1c8f968282208be391f062c1656d85e2ba5078ac
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:56:03 2009 +0200
make sure we always read in all properties
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 02413f4..78c1bed 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -418,6 +418,15 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
+
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Audio", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
+
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Headset", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
+
+ pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.AudioSink", "GetProperties"));
+ send_and_add_to_pending(y, d, m, get_properties_reply);
}
static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
commit 90fbc036f47a10fb81833dcd7d150e669a30d57c
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:57:12 2009 +0200
make sure we never access an invalid pa_bluetooth_device object
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index f9800ac..fadfa54 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -132,7 +132,7 @@ struct userdata {
char *address;
char *path;
- const pa_bluetooth_device* device;
+ pa_bluetooth_discovery *discovery;
pa_dbus_connection *connection;
@@ -1728,6 +1728,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
struct userdata *u;
enum profile *d;
pa_queue *inputs = NULL, *outputs = NULL;
+ const pa_bluetooth_device *device;
pa_assert(c);
pa_assert(new_profile);
@@ -1735,11 +1736,16 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
d = PA_CARD_PROFILE_DATA(new_profile);
- if (u->device->headset_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
+ if (!(device = pa_bluetooth_discovery_get_by_path(u->discovery, u->path))) {
+ pa_log_error("Failed to get device object.");
+ return -1;
+ }
+
+ if (device->headset_state != PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_HSP) {
pa_log_warn("HSP is not connected, refused to switch profile");
return -1;
}
- else if (u->device->audio_sink_state < PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
+ else if (device->audio_sink_state != PA_BT_AUDIO_STATE_CONNECTED && *d == PROFILE_A2DP) {
pa_log_warn("A2DP is not connected, refused to switch profile");
return -1;
}
@@ -1884,11 +1890,10 @@ static int add_card(struct userdata *u, const char *default_profile, const pa_bl
return 0;
}
-static const pa_bluetooth_device* find_device(struct userdata *u, pa_bluetooth_discovery *y, const char *address, const char *path) {
+static const pa_bluetooth_device* find_device(struct userdata *u, const char *address, const char *path) {
const pa_bluetooth_device *d = NULL;
pa_assert(u);
- pa_assert(y);
if (!address && !path) {
pa_log_error("Failed to get device address/path from module arguments.");
@@ -1896,7 +1901,7 @@ static const pa_bluetooth_device* find_device(struct userdata *u, pa_bluetooth_d
}
if (path) {
- if (!(d = pa_bluetooth_discovery_get_by_path(y, path))) {
+ if (!(d = pa_bluetooth_discovery_get_by_path(u->discovery, path))) {
pa_log_error("%s is not a valid BlueZ audio device.", path);
return NULL;
}
@@ -1907,7 +1912,7 @@ static const pa_bluetooth_device* find_device(struct userdata *u, pa_bluetooth_d
}
} else {
- if (!(d = pa_bluetooth_discovery_get_by_address(y, address))) {
+ if (!(d = pa_bluetooth_discovery_get_by_address(u->discovery, address))) {
pa_log_error("%s is not known.", address);
return NULL;
}
@@ -1942,9 +1947,9 @@ int pa__init(pa_module* m) {
uint32_t channels;
struct userdata *u;
const char *address, *path;
- pa_bluetooth_discovery *y = NULL;
DBusError err;
char *mike, *speaker;
+ const pa_bluetooth_device *device;
pa_assert(m);
@@ -1999,19 +2004,16 @@ int pa__init(pa_module* m) {
if (setup_dbus(u) < 0)
goto fail;
- if (!(y = pa_bluetooth_discovery_get(m->core)))
+ if (!(u->discovery = pa_bluetooth_discovery_get(m->core)))
goto fail;
- if (!(u->device = find_device(u, y, address, path))) /* should discovery ref be kept? */
+ if (!(device = find_device(u, address, path)))
goto fail;
/* Add the card structure. This will also initialize the default profile */
- if (add_card(u, pa_modargs_get_value(ma, "profile", NULL), u->device) < 0)
+ if (add_card(u, pa_modargs_get_value(ma, "profile", NULL), device) < 0)
goto fail;
- pa_bluetooth_discovery_unref(y);
- y = NULL;
-
/* Connect to the BT service and query capabilities */
if (init_bt(u) < 0)
goto fail;
@@ -2052,9 +2054,6 @@ int pa__init(pa_module* m) {
fail:
- if (y)
- pa_bluetooth_discovery_unref(y);
-
pa__done(m);
dbus_error_free(&err);
@@ -2135,5 +2134,8 @@ void pa__done(pa_module *m) {
pa_xfree(u->address);
pa_xfree(u->path);
+ if (u->discovery)
+ pa_bluetooth_discovery_unref(u->discovery);
+
pa_xfree(u);
}
commit 857a1f4909f91fbf504ad05aca4b0dcd7945cacf
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:57:23 2009 +0200
fix compiler warning
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index fadfa54..96b95b4 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -462,7 +462,7 @@ static int setup_a2dp(struct userdata *u) {
}
}
- pa_assert(i < PA_ELEMENTSOF(freq_table));
+ pa_assert((unsigned) i < PA_ELEMENTSOF(freq_table));
if (cap->capability.configured)
return 0;
commit 3df9eef9d0deb4f5216d024163fe966befeca908
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 21:07:23 2009 +0200
take org.pulseaudio.Server instead of org.pulseaudio to match the interface name already used in the HAL module
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 1d54348..2faf650 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -345,10 +345,10 @@ static void register_org_pulseaudio(pa_core *c)
goto finish_dbus;
}
- if (dbus_bus_request_name (pa_dbus_connection_get(conn), "org.pulseaudio", 0, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
- pa_log_debug("Got org.pulseaudio!");
+ if (dbus_bus_request_name (pa_dbus_connection_get(conn), "org.pulseaudio.Server", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ pa_log_debug("Got org.pulseaudio.Server!");
else if (dbus_error_is_set(&error))
- pa_log_warn("Unable to get org.pulseaudio: %s: %s", error.name, error.message);
+ pa_log_warn("Unable to get org.pulseaudio.Server: %s: %s", error.name, error.message);
finish_dbus:
if (conn)
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 9fb9e72..40fa808 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -760,8 +760,8 @@ static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wr
if (pa_dbus_add_matches(
pa_dbus_wrap_connection_get(*conn), &error,
- "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio',arg1=''", NULL) < 0)
- pa_log_warn("Unable to track org.pulseaudio: %s: %s", error.name, error.message);
+ "type='signal',sender='" DBUS_SERVICE_DBUS "',interface='" DBUS_INTERFACE_DBUS "',member='NameOwnerChanged',arg0='org.pulseaudio.Server',arg1=''", NULL) < 0)
+ pa_log_warn("Unable to track org.pulseaudio.Server: %s: %s", error.name, error.message);
finish:
dbus_error_free(&error);
commit b6135b34b3d8a9ff04cdf4359d33b54f97823037
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 21:07:41 2009 +0200
minor cleanups
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 40fa808..13b6d57 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -874,16 +874,20 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *message, vo
if (c->state != PA_CONTEXT_CONNECTING)
goto finish;
+ if (!c->no_fail)
+ goto finish;
+
+ /* FIXME: We probably should check if this is actually the NameOwnerChanged we were looking for */
+
is_session = bus == pa_dbus_wrap_connection_get(c->session_bus);
- pa_log_debug("Rock!! PulseAudio is baack on %s bus", is_session ? "session" : "system");
+ pa_log_debug("Rock!! PulseAudio is back on %s bus", is_session ? "session" : "system");
- if (is_session) {
+ if (is_session)
/* The user instance via PF_LOCAL */
c->server_list = prepend_per_user(c->server_list);
- } else {
+ else
/* The system wide instance via PF_LOCAL */
c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET);
- }
try_next_connection(c);
commit 29a282a41b4f5c3448cc2f6095cde95fc78d2535
Author: Lennart Poettering <lennart at poettering.net>
Date: Mon Mar 30 20:31:03 2009 +0000
allow nofail mode only when no server string was specified
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 13b6d57..28d1719 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -144,7 +144,6 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
if (name)
pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name);
- c->no_fail = FALSE;
c->system_bus = c->session_bus = NULL;
c->mainloop = mainloop;
c->client = NULL;
@@ -170,6 +169,8 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
c->do_shm = FALSE;
+ c->server_specified = FALSE;
+ c->no_fail = FALSE;
c->do_autospawn = FALSE;
memset(&c->spawn_api, 0, sizeof(c->spawn_api));
@@ -799,7 +800,7 @@ static int try_next_connection(pa_context *c) {
}
#endif
- if (c->no_fail) {
+ if (c->no_fail && !c->server_specified) {
if (!c->system_bus)
track_pulseaudio_on_dbus(c, DBUS_BUS_SYSTEM, &c->system_bus);
if (!c->session_bus)
@@ -917,6 +918,7 @@ int pa_context_connect(
pa_context_ref(c);
c->no_fail = flags & PA_CONTEXT_NOFAIL;
+ c->server_specified = !!server;
pa_assert(!c->server_list);
if (server) {
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 8c24294..da94faa 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -51,7 +51,6 @@
struct pa_context {
PA_REFCNT_DECLARE;
- pa_bool_t no_fail:1;
pa_dbus_wrap_connection *system_bus;
pa_dbus_wrap_connection *session_bus;
@@ -83,7 +82,8 @@ struct pa_context {
pa_bool_t is_local:1;
pa_bool_t do_shm:1;
-
+ pa_bool_t server_specified:1;
+ pa_bool_t no_fail:1;
pa_bool_t do_autospawn:1;
pa_spawn_api spawn_api;
commit ff7033c11d9248fe837204b03c8397231dc511fe
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 31 00:22:17 2009 +0200
Revert "make sure we always read in all properties"
This reverts commit 1c8f968282208be391f062c1656d85e2ba5078ac.
Turns out doing this is racy. The appropriate fix seems to be
38825d79123678bf0c5d156aaea4bedb888a7fcd
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 78c1bed..02413f4 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -418,15 +418,6 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Audio", "GetProperties"));
- send_and_add_to_pending(y, d, m, get_properties_reply);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Headset", "GetProperties"));
- send_and_add_to_pending(y, d, m, get_properties_reply);
-
- pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.AudioSink", "GetProperties"));
- send_and_add_to_pending(y, d, m, get_properties_reply);
}
static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
commit cab1e54392728251bd3b724e42d2b022aa7e7ad2
Author: Lennart Poettering <lennart at poettering.net>
Date: Tue Mar 31 00:26:12 2009 +0200
explain ff7033c11d9248fe837204b03c8397231dc511fe
diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 02413f4..6e4344f 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -418,6 +418,9 @@ static void found_device(pa_bluetooth_discovery *y, const char* path) {
pa_assert_se(m = dbus_message_new_method_call("org.bluez", path, "org.bluez.Device", "GetProperties"));
send_and_add_to_pending(y, d, m, get_properties_reply);
+
+ /* Before we read the other properties (Audio, AudioSink, Headset) we wait
+ * that the UUID is read */
}
static void list_devices_reply(DBusPendingCall *pending, void *userdata) {
--
hooks/post-receive
PulseAudio Sound Server
More information about the pulseaudio-commits
mailing list