[pulseaudio-discuss] [PATCH] bluetooth: Fix crash when disabling Bluetooth adapter

2019-06-19 Thread Frédéric Danis
This crash occurs when PA is connected to a phone through the oFono
backend.
When disabling the Bluetooth adapter, pa_bluetooth_device is removed before
hf_audio_card. Both keep refs on pa_bluetooth_transport. Those removal will
call pa_bluetooth_transport_free() from device_free() (bluez5-util.c) and
hf_audio_card_free() (backend-ofono.c).
In the end, the call to pa_bluetooth_transport_free() calls
pa_hasmap_remove() through pa_bluetooth_transport_unlink(), but since
memory has already been freed, the second try results in a segfault.

Triggering hf_audio_card removal during pa_bluetooth_device removal allows
hf_audio_card to be freed at the right time.
---
 src/modules/bluetooth/backend-ofono.c | 18 ++
 src/modules/bluetooth/bluez5-util.c   |  2 ++
 src/modules/bluetooth/bluez5-util.h   |  1 +
 3 files changed, 21 insertions(+)

diff --git a/src/modules/bluetooth/backend-ofono.c 
b/src/modules/bluetooth/backend-ofono.c
index 1f0efe923..0e5bbe8b7 100644
--- a/src/modules/bluetooth/backend-ofono.c
+++ b/src/modules/bluetooth/backend-ofono.c
@@ -70,6 +70,7 @@ struct hf_audio_card {
 int (*acquire)(struct hf_audio_card *card);
 
 pa_bluetooth_transport *transport;
+pa_hook_slot *device_unlink_slot;
 };
 
 struct pa_bluetooth_backend {
@@ -181,6 +182,17 @@ static int card_acquire(struct hf_audio_card *card) {
 return -1;
 }
 
+static void hf_audio_agent_card_removed(pa_bluetooth_backend *backend, const 
char *path);
+
+static pa_hook_result_t device_unlink_cb(pa_bluetooth_discovery *y, const 
pa_bluetooth_device *d, struct hf_audio_card *card) {
+pa_assert(d);
+pa_assert(card);
+
+hf_audio_agent_card_removed(card->backend, card->path);
+
+return PA_HOOK_OK;
+}
+
 static struct hf_audio_card *hf_audio_card_new(pa_bluetooth_backend *backend, 
const char *path) {
 struct hf_audio_card *card = pa_xnew0(struct hf_audio_card, 1);
 
@@ -189,12 +201,18 @@ static struct hf_audio_card 
*hf_audio_card_new(pa_bluetooth_backend *backend, co
 card->fd = -1;
 card->acquire = card_acquire;
 
+card->device_unlink_slot = 
pa_hook_connect(pa_bluetooth_discovery_hook(backend->discovery, 
PA_BLUETOOTH_HOOK_DEVICE_UNLINK),
+   PA_HOOK_NORMAL, (pa_hook_cb_t) 
device_unlink_cb, card);
+
 return card;
 }
 
 static void hf_audio_card_free(struct hf_audio_card *card) {
 pa_assert(card);
 
+if (card->device_unlink_slot)
+pa_hook_slot_free(card->device_unlink_slot);
+
 if (card->transport)
 pa_bluetooth_transport_free(card->transport);
 
diff --git a/src/modules/bluetooth/bluez5-util.c 
b/src/modules/bluetooth/bluez5-util.c
index 3c5a000c0..d95c9c117 100644
--- a/src/modules/bluetooth/bluez5-util.c
+++ b/src/modules/bluetooth/bluez5-util.c
@@ -562,6 +562,8 @@ static void device_free(pa_bluetooth_device *d) {
 
 device_stop_waiting_for_profiles(d);
 
+pa_hook_fire(&d->discovery->hooks[PA_BLUETOOTH_HOOK_DEVICE_UNLINK], d);
+
 for (i = 0; i < PA_BLUETOOTH_PROFILE_COUNT; i++) {
 pa_bluetooth_transport *t;
 
diff --git a/src/modules/bluetooth/bluez5-util.h 
b/src/modules/bluetooth/bluez5-util.h
index 82739bffd..1e9caecb4 100644
--- a/src/modules/bluetooth/bluez5-util.h
+++ b/src/modules/bluetooth/bluez5-util.h
@@ -50,6 +50,7 @@ typedef enum pa_bluetooth_hook {
 PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED,/* Call data: 
pa_bluetooth_transport */
 PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED,  /* Call data: 
pa_bluetooth_transport */
 PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED, /* Call data: 
pa_bluetooth_transport */
+PA_BLUETOOTH_HOOK_DEVICE_UNLINK,  /* Call data: 
pa_bluetooth_device */
 PA_BLUETOOTH_HOOK_MAX
 } pa_bluetooth_hook_t;
 
-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [PATCH v2] bluetooth: Fix crash in setup_stream()

2019-06-18 Thread Frédéric Danis
setup_stream() crashes when calling set_nonblock() with an invalid
stream_fd.

On a new call, the ofono backend gets notified of a new connection.
The ofono backend sets the transport state to playing, and that triggers
a profile change, which sets up the stream for the first time.
Then module-bluetooth-policy sets up the loopbacks. The loopbacks get
fully initialized before the crash.

After module-bluetooth-policy has done its things, the execution
continues in the transport state change hook. The next hook user is
module-bluez5-device, whose handle_transport_state_change() function
gets called. It will then set up the stream again even though it's
already set up. I'm not sure if that's a some kind of a bug.
setup_stream() can handle the case where it's unnecessarily called,
though, so this second setup is not a big problem.

The crash happens, because the connection died due to POLLHUP in the IO
thread before the second setup_stream() call.
---
Changes in v2:
* Update comments and commit message

 src/modules/bluetooth/module-bluez5-device.c | 26 ++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 56c96054d..91c678223 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -753,6 +753,8 @@ static void setup_stream(struct userdata *u) {
 struct pollfd *pollfd;
 int one;
 
+pa_assert(u->stream_fd >= 0);
+
 /* return if stream is already set up */
 if (u->stream_setup_done)
 return;
@@ -829,7 +831,17 @@ static int source_process_msg(pa_msgobject *o, int code, 
void *data, int64_t off
 }
 
 case PA_SOURCE_MESSAGE_SETUP_STREAM:
-setup_stream(u);
+/* Skip stream setup if stream_fd has been invalidated.
+   This can occur if the stream has already been set up and
+   then immediately received POLLHUP. If the stream has
+   already been set up earlier, then this setup_stream()
+   call is redundant anyway, but currently the code
+   is such that this kind of unnecessary setup_stream()
+   calls can happen. */
+if (u->stream_fd < 0)
+pa_log_debug("Skip source stream setup while closing");
+else
+setup_stream(u);
 return 0;
 
 }
@@ -1007,7 +1019,17 @@ static int sink_process_msg(pa_msgobject *o, int code, 
void *data, int64_t offse
 }
 
 case PA_SINK_MESSAGE_SETUP_STREAM:
-setup_stream(u);
+/* Skip stream setup if stream_fd has been invalidated.
+   This can occur if the stream has already been set up and
+   then immediately received POLLHUP. If the stream has
+   already been set up earlier, then this setup_stream()
+   call is redundant anyway, but currently the code
+   is such that this kind of unnecessary setup_stream()
+   calls can happen. */
+if (u->stream_fd < 0)
+pa_log_debug("Skip sink stream setup while closing");
+else
+setup_stream(u);
 return 0;
 }
 
-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [PATCH] bluetooth: Fix crash in setup_stream()

2019-06-17 Thread Frédéric Danis
setup_stream() crashes when calling set_nonblock() with an invalid
stream_fd.

This crash is due to a race condition.
The audio call starts normally, and a 1st call to setup_stream() is
completed properly.
But, if the call is "quickly" hung up, the stream_fd is in error (POLLHUP)
before other modules (loopback, …) have completed their initialization.
This error triggers a call to teardown_stream() which set stream_fd to -1.
After that, the other modules continue their initialization before the IO
thread is stopped, triggering a 2nd call to setup_stream().
---
 src/modules/bluetooth/module-bluez5-device.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 56c96054d..d0e3c7a09 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -753,6 +753,8 @@ static void setup_stream(struct userdata *u) {
 struct pollfd *pollfd;
 int one;
 
+pa_assert(u->stream_fd >= 0);
+
 /* return if stream is already set up */
 if (u->stream_setup_done)
 return;
@@ -829,7 +831,13 @@ static int source_process_msg(pa_msgobject *o, int code, 
void *data, int64_t off
 }
 
 case PA_SOURCE_MESSAGE_SETUP_STREAM:
-setup_stream(u);
+/* Skip stream setup if stream_fd as been invalidated, this can
+ * occurs in case of POLLHUP before other modules have finished
+ * their initialization */
+if (u->stream_fd < 0)
+pa_log_debug("Skip source stream setup while closing");
+else
+setup_stream(u);
 return 0;
 
 }
@@ -1007,7 +1015,13 @@ static int sink_process_msg(pa_msgobject *o, int code, 
void *data, int64_t offse
 }
 
 case PA_SINK_MESSAGE_SETUP_STREAM:
-setup_stream(u);
+/* Skip stream setup if stream_fd as been invalidated, this can
+ * occurs in case of POLLHUP before other modules have finished
+ * their initialization */
+if (u->stream_fd < 0)
+pa_log_debug("Skip sink stream setup while closing");
+else
+setup_stream(u);
 return 0;
 }
 
-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [PATCH] core, modules: Remove useless EINTR tests

2019-05-28 Thread Frédéric Danis
Since commit ad447d14682 (in 2009) pa_read and pa_write take care of
handling EINTR error.
So, pa_read, pa_write, pa_iochannel_read and pa_iochannel_write can not
exit with errno set to EINTR, and testing it is useless.
---
 src/modules/bluetooth/module-bluez5-device.c | 16 +---
 src/modules/module-esound-sink.c |  4 +-
 src/modules/module-pipe-sink.c   | 17 -
 src/modules/module-pipe-source.c |  4 +-
 src/modules/module-solaris.c |  4 +-
 src/modules/oss/module-oss.c | 10 +
 src/pulsecore/fdsem.c| 40 ++--
 src/pulsecore/iochannel.c|  2 +-
 src/pulsecore/protocol-esound.c  |  8 ++--
 src/pulsecore/protocol-simple.c  |  2 +-
 10 files changed, 32 insertions(+), 75 deletions(-)

diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 56c96054d..f850a3a41 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -279,10 +279,6 @@ static int sco_process_render(struct userdata *u) {
 
 saved_errno = errno;
 
-if (saved_errno == EINTR)
-/* Retry right away if we got interrupted */
-continue;
-
 pa_memblock_unref(memchunk.memblock);
 
 if (saved_errno == EAGAIN) {
@@ -445,11 +441,7 @@ static int a2dp_write_buffer(struct userdata *u, size_t 
nbytes) {
 
 if (l < 0) {
 
-if (errno == EINTR)
-/* Retry right away if we got interrupted */
-continue;
-
-else if (errno == EAGAIN) {
+if (errno == EAGAIN) {
 /* Hmm, apparently the socket was not writable, give up for 
now */
 pa_log_debug("Got EAGAIN on write() after POLLOUT, probably 
there is a temporary connection loss.");
 break;
@@ -543,11 +535,7 @@ static int a2dp_process_push(struct userdata *u) {
 
 if (l <= 0) {
 
-if (l < 0 && errno == EINTR)
-/* Retry right away if we got interrupted */
-continue;
-
-else if (l < 0 && errno == EAGAIN)
+if (l < 0 && errno == EAGAIN)
 /* Hmm, apparently the socket was not readable, give up for 
now. */
 break;
 
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 5ff04516a..f46dc3889 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -249,9 +249,7 @@ static void thread_func(void *userdata) {
 
 if (l < 0) {
 
-if (errno == EINTR)
-continue;
-else if (errno == EAGAIN) {
+if (errno == EAGAIN) {
 
 /* OK, we filled all socket buffers up
  * now. */
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 213924fdc..43595420f 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -199,14 +199,13 @@ static ssize_t pipe_sink_write(struct userdata *u, 
pa_memchunk *pchunk) {
 if (l < 0) {
 if (errno == EAGAIN)
 break;
-else if (errno != EINTR) {
-if (!u->fifo_error) {
-pa_log("Failed to write data to FIFO: %s", 
pa_cstrerror(errno));
-u->fifo_error = true;
-}
-count = -1 - count;
-break;
+
+if (!u->fifo_error) {
+pa_log("Failed to write data to FIFO: %s", 
pa_cstrerror(errno));
+u->fifo_error = true;
 }
+count = -1 - count;
+break;
 } else {
 if (u->fifo_error) {
 pa_log_debug("Recovered from FIFO error");
@@ -288,9 +287,7 @@ static int process_render(struct userdata *u) {
 
 if (l < 0) {
 
-if (errno == EINTR)
-continue;
-else if (errno == EAGAIN)
+if (errno == EAGAIN)
 return 0;
 else {
 pa_log("Failed to write data to FIFO: %s", 
pa_cstrerror(errno));
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 74ec0551a..32b35c163 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -155,9 +155,7 @@ static void thread_func(void *userdata) {
 
 if (l < 0) {
 
-if (errno == EINTR)
-continue;
-else if (errno != EAGAIN) {
+if (errno != EAGAIN) {
 pa_log("Failed to read data from FIFO: %s", 
pa_cstrerror(errno));
 goto fail;
 }
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index 038aca114..ec9eb875f 1

[pulseaudio-discuss] [RFC v2 3/3] bluetooth: Add skipped bytes statistic message

2019-05-27 Thread Frédéric Danis
This allows to get the total amount of bytes skipped since connected to
the device.

pacmd send-message /bluetooth/bluez_sink. get-skipped-bytes
---
 src/modules/bluetooth/module-bluez5-device.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 3ab4be508..4abc55fd1 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -133,6 +134,7 @@ struct userdata {
 pa_usec_t started_at;
 pa_smoother *read_smoother;
 pa_memchunk write_memchunk;
+uint64_t skipped_bytes;
 
 const pa_a2dp_codec *a2dp_codec;
 bool a2dp_codec_config_pending;
@@ -1425,6 +1427,8 @@ static void thread_func(void *userdata) {
 pa_log_debug("Skipping %llu us (= %llu bytes) in 
audio stream",
 (unsigned long long) skip_usec,
 (unsigned long long) skip_bytes);
+u->skipped_bytes += skip_bytes;
+pa_log_debug("Total bytes skipped = %llu", 
(unsigned long long) u->skipped_bytes);
 
 while (skip_bytes > 0) {
 size_t bytes_to_render;
@@ -1550,6 +1554,11 @@ static int bluetooth_handler(const char *object_path, 
const char *message, char
 return res;
 }
 return -PA_ERR_NOTSUPPORTED;
+} else if (pa_streq(message, "get-skipped-bytes")) {
+pa_message_params *param = pa_message_params_new();
+pa_message_params_write_uint64(param, u->skipped_bytes);
+*response = pa_message_params_to_string_free(param);
+return PA_OK;
 }
 
 return -PA_ERR_NOTIMPLEMENTED;
-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [RFC v2 2/3] bluetooth: Add SBC get/set config message support

2019-05-27 Thread Frédéric Danis
Capability to dynamically change the bitpool used during runtime allows to
adjust the bitrate of the stream. In a crowded environment this can allow
to manage the bandwith used and limit interference between source and
headphones.

get-a2dp-config message returns SBC bitpool configuration:
{{current bitpool} {min bitpool} {max bitpool}}

set-a2dp-config message gets new bitpool to use as parameter:
{new bitpool}
---
 src/modules/bluetooth/a2dp-codec-sbc.c | 47 ++
 1 file changed, 47 insertions(+)

diff --git a/src/modules/bluetooth/a2dp-codec-sbc.c 
b/src/modules/bluetooth/a2dp-codec-sbc.c
index cdc20d7f0..93aeb6241 100644
--- a/src/modules/bluetooth/a2dp-codec-sbc.c
+++ b/src/modules/bluetooth/a2dp-codec-sbc.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -51,6 +52,7 @@ struct sbc_info {
 uint8_t initial_bitpool;
 uint8_t min_bitpool;
 uint8_t max_bitpool;
+uint8_t next_bitpool;
 };
 
 static bool can_accept_capabilities(const uint8_t *capabilities_buffer, 
uint8_t capabilities_size, bool for_encoding) {
@@ -502,6 +504,48 @@ static size_t reduce_encoder_bitrate(void *codec_info, 
size_t write_link_mtu) {
 return get_block_size(codec_info, write_link_mtu);
 }
 
+static char* get_encoder_config(void *codec_info) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+pa_message_params *param;
+
+param = pa_message_params_new();
+pa_message_params_begin_list(param);
+pa_message_params_write_int64(param, sbc_info->sbc.bitpool);
+pa_message_params_write_int64(param, sbc_info->min_bitpool);
+pa_message_params_write_int64(param, sbc_info->max_bitpool);
+pa_message_params_end_list(param);
+
+return pa_message_params_to_string_free(param);
+}
+
+static int set_encoder_config(void *codec_info, char *new_config) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+void *state = NULL;
+int64_t value;
+
+if (pa_message_params_read_int64(new_config, &value, &state) != 
PA_PARAMS_OK)
+return -PA_ERR_INVALID;
+
+pa_log_info("Requested SBC Bitpool: %ld", value);
+if (value < sbc_info->min_bitpool || value > sbc_info->max_bitpool)
+return -PA_ERR_INVALID;
+sbc_info->next_bitpool = (uint8_t)value;
+
+return PA_OK;
+}
+
+static size_t apply_encoder_config(void *codec_info, size_t write_link_mtu) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+
+if (!sbc_info->next_bitpool)
+return 0;
+
+set_bitpool(sbc_info, sbc_info->next_bitpool);
+sbc_info->next_bitpool = 0;
+
+return get_block_size(codec_info, write_link_mtu);
+}
+
 static size_t encode_buffer(void *codec_info, uint32_t timestamp, const 
uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t 
output_size, size_t *processed) {
 struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
 struct rtp_header *header;
@@ -644,4 +688,7 @@ const pa_a2dp_codec pa_a2dp_codec_sbc = {
 .reduce_encoder_bitrate = reduce_encoder_bitrate,
 .encode_buffer = encode_buffer,
 .decode_buffer = decode_buffer,
+.get_encoder_config = get_encoder_config,
+.set_encoder_config = set_encoder_config,
+.apply_encoder_config = apply_encoder_config,
 };
-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [RFC v2 1/3] bluetooth: Add message to get/set A2DP codec configs

2019-05-27 Thread Frédéric Danis
This patch introduces 2 new messages to retrieve and set codec specific
configuration information.
It is up to each codec to define which information can be retrieved or set.
Message path is based on the remote device address (replacing ":" by "_").

 Get configuration command:
 pacmd send-message /bluetooth/bluez_sink. get-a2dp-config

 Set configuration command:
 pacmd send-message /bluetooth/bluez_sink. set-a2dp-config
  

To avoid breaking buffer encoding, I split set-a2dp-config in 2 functions.
set_encoder_config() is called to pass the new configuration to the
encoder.
apply_encoder_config() is called when no buffer needs to be encoded.
---
 src/modules/bluetooth/a2dp-codec-api.h   | 10 
 src/modules/bluetooth/module-bluez5-device.c | 54 
 src/pulsecore/core-util.h|  7 +++
 3 files changed, 71 insertions(+)

diff --git a/src/modules/bluetooth/a2dp-codec-api.h 
b/src/modules/bluetooth/a2dp-codec-api.h
index 55bb9ff70..23fbfe912 100644
--- a/src/modules/bluetooth/a2dp-codec-api.h
+++ b/src/modules/bluetooth/a2dp-codec-api.h
@@ -90,6 +90,16 @@ typedef struct pa_a2dp_codec {
  * returns size of filled ouput_buffer and set processed to size of
  * processed input_buffer */
 size_t (*decode_buffer)(void *codec_info, const uint8_t *input_buffer, 
size_t input_size, uint8_t *output_buffer, size_t output_size, size_t 
*processed);
+
+/* Get encoder codec configuration, returns Message API string specific to
+ * each codec */
+char *(*get_encoder_config)(void *codec_info);
+/* Set encoder codec configuration. new_config string is codec specific and
+ * in Message API format. returns PA error code */
+int (*set_encoder_config)(void *codec_info, char *new_config);
+/* Apply new config to encoder codec, returns new write block size or zero
+ * if not changed, called after set_encoder_config success */
+size_t (*apply_encoder_config)(void *codec_info, size_t write_link_mtu);
 } pa_a2dp_codec;
 
 #endif
diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 56c96054d..3ab4be508 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -45,6 +45,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "a2dp-codecs.h"
 #include "a2dp-codec-util.h"
@@ -133,6 +135,7 @@ struct userdata {
 pa_memchunk write_memchunk;
 
 const pa_a2dp_codec *a2dp_codec;
+bool a2dp_codec_config_pending;
 
 void *encoder_info;
 pa_sample_spec encoder_sample_spec;
@@ -1444,6 +1447,14 @@ static void thread_func(void *userdata) {
 handle_sink_block_size_change(u);
 }
 }
+} else if (u->a2dp_codec_config_pending && u->profile 
== PA_BLUETOOTH_PROFILE_A2DP_SINK &&
+u->a2dp_codec->apply_encoder_config) {
+size_t new_write_block_size = 
u->a2dp_codec->apply_encoder_config(u->encoder_info, u->write_link_mtu);
+if (new_write_block_size) {
+u->write_block_size = new_write_block_size;
+handle_sink_block_size_change(u);
+}
+u->a2dp_codec_config_pending = false;
 }
 
 blocks_to_write = 1;
@@ -1517,6 +1528,33 @@ finish:
 pa_log_debug("IO thread shutting down");
 }
 
+static int bluetooth_handler(const char *object_path, const char *message, 
char *message_parameters, char **response, void *userdata) {
+struct userdata *u;
+
+pa_assert(u = (struct userdata *) userdata);
+pa_assert(message);
+pa_assert(response);
+pa_assert(pa_safe_strneq(object_path, "/bluetooth/bluez_", 17));
+
+if (pa_streq(message, "get-a2dp-config")) {
+if (u->a2dp_codec->get_encoder_config) {
+*response = u->a2dp_codec->get_encoder_config(u->encoder_info);
+return PA_OK;
+}
+return -PA_ERR_NOTSUPPORTED;
+} else if (pa_streq(message, "set-a2dp-config")) {
+if (u->a2dp_codec->set_encoder_config) {
+int res = u->a2dp_codec->set_encoder_config(u->encoder_info, 
message_parameters);
+if (res == PA_OK)
+u->a2dp_codec_config_pending = true;
+return res;
+}
+return -PA_ERR_NOTSUPPORTED;
+}
+
+return -PA_ERR_NOTIMPLEMENTED;
+}
+
 /* Run from main thread */
 static int start_thread(struct userdata *u) {
 pa_assert(u);
@@ -1567,6 +1605,14 @@ static int start_thread(struct userdata *u) {
 u->source->set_volume(u->source);
 }
 
+if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) {
+char *address = pa_namereg_make_valid_name(u->device->address);
+char *path = pa_sprintf_malloc("/bluetooth/

[pulseaudio-discuss] [RFC v2 0/3] Add dynamic configuration of SBC bitpool

2019-05-27 Thread Frédéric Danis
This series of patch allows to manage the bandwidth used by an A2DP source
using SBC encoder by adding ability to change the bitpool dynamically during
runtime.
In a crowded environment this can allow to limit interference between source
and headphones.
An external application should be able to control the SBC bitrate of up
to 300 BT transmitters in a noisy and possibly RF perturbed environment, for
which it can get the statistics for dropouts, and if it gets too high,
reduce the quality either globally, or across a physically-adjacent set of
transmitters.

This needs "Message API v2" patches from Georg Chini [1]

I am currently not sure in patch 2 where should occur the SBC bitpool apply.

Since V1:
- Added patch 3 to expose number of bytes skipped for the A2DP connection.

Any comments appreciated.

[1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/51
Frédéric Danis (3):
  bluetooth: Add message to get/set A2DP codec configs
  bluetooth: Add SBC get/set config message support
  bluetooth: Add skipped bytes statistic message

 src/modules/bluetooth/a2dp-codec-api.h   | 10 
 src/modules/bluetooth/a2dp-codec-sbc.c   | 47 +++
 src/modules/bluetooth/module-bluez5-device.c | 63 
 src/pulsecore/core-util.h|  7 +++
 4 files changed, 127 insertions(+)

-- 
2.18.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

Re: [pulseaudio-discuss] [RFC 0/2] Add dynamic configuration of SBC bitpool

2019-05-23 Thread Frédéric Danis

Hi Pali,

On 17/05/2019 16:38, Pali Rohár wrote:

On Friday 17 May 2019 16:26:30 Frédéric Danis wrote:

Hi Pali,

On 17/05/2019 15:51, Pali Rohár wrote:

On Friday 17 May 2019 15:45:10 Frédéric Danis wrote:

This series of patch allows to manage the bandwidth used by an A2DP source
using SBC encoder by adding ability to change the bitpool dynamically during
runtime.
In a crowded environment this can allow to limit interference between source
and headphones.

This needs "Message API v2" patches from Georg Chini [1]

I am currently not sure in patch 2 where should occur the SBC bitpool apply.

Any comments appreciated.

[1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/51

Hi! I would suggest to wait until my patches for extending A2DP codecs
is reviewed and merged. You can find them in email with subject
"[PATCH v10 00/11] Bluetooth A2DP codecs"

Tanu Kaskinen has already pointed them to me and I have a version using
them.
I've sent this RFC with minimal dependency on waiting patches to start
getting some feedback about it.

Ok.


With your patches, I have to use the "SBC (Automatic Quality)" profile to be
able to change the SBC bitpool.

Ok.


Do you know if there is a way to set it as preferred profile for new
connections?

So.. I do not think that "SBC (Automatic Quality)" should be used as
default/preferred profile.

Lot of people are complaining about bad quality of the bluetooth a2dp
implementation in linux... And the solution is to use SBC UHQ mode if is
available -- so to stop using SBC High Quality (and automatic quality).
In most cases SBC UHQ is possible to use only via DualChannel mode as
the highest possible bitpool value for JointStereo mode in most cases is
not enough for UHQ.


I understand your point of view, but my tests with SBC UHQ mode in an 
environment with interferences may increase sound quality but with audio 
dropouts. Which is not really better.



In this patch series is also big rework of SBC codec, to support e.g.
UHQ mode and your changes would introduce new conflicts with that patch
series.

Anyway, correct behavior of SBC codec in automatic mode should
automatically increase or decrease SBC bitpool based on available
bandwidth.

The idea should be to have an external application getting information

This is way to the hell.


about
the radio environment like the number of Bluetooth devices (A2DP sources and
sinks, and other devices), link quality, WiFi usage, ... to be able to
dynamically change the bitpool to be used.

I do not think that this would work reliable even when implemented. Plus
having another external entity which would control internal settings of
A2DP transfer is the worst solution. People would just start more
complaining that subjective quality is not good. And debugging another
external application, or more figuring out how is configured would just
complicate many more things.


What I would like to achieve is to be able to control the SBC bitrate of 
up to 300 BT transmitters in a noisy and possibly RF perturbed 
environment, for which I can watch the statistics for dropouts, and if 
it gets too high, reduce the quality either globally, or across a 
physically-adjacent set of transmitters. I think this can not be 
achieved by an algorithm inside PA daemon.


I'm not intending to have "btsbcqualityd" running on everyone's desktop.


SBC bitpool indirectly specify SBC packet size. In my opinion bitpool
should be controlled directly by pulseaudio based on socket latency and
socket state, packet loss, how is kernel able to transmit packets...


AFAIK there is not so many information available from the Bluetooth side 
regarding socket latency, packet loss, …


Fred
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

Re: [pulseaudio-discuss] [RFC 0/2] Add dynamic configuration of SBC bitpool

2019-05-17 Thread Frédéric Danis

Hi Pali,

On 17/05/2019 15:51, Pali Rohár wrote:

On Friday 17 May 2019 15:45:10 Frédéric Danis wrote:

This series of patch allows to manage the bandwidth used by an A2DP source
using SBC encoder by adding ability to change the bitpool dynamically during
runtime.
In a crowded environment this can allow to limit interference between source
and headphones.

This needs "Message API v2" patches from Georg Chini [1]

I am currently not sure in patch 2 where should occur the SBC bitpool apply.

Any comments appreciated.

[1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/51

Hi! I would suggest to wait until my patches for extending A2DP codecs
is reviewed and merged. You can find them in email with subject
"[PATCH v10 00/11] Bluetooth A2DP codecs"


Tanu Kaskinen has already pointed them to me and I have a version using 
them.
I've sent this RFC with minimal dependency on waiting patches to start 
getting some feedback about it.


With your patches, I have to use the "SBC (Automatic Quality)" profile 
to be able to change the SBC bitpool.
Do you know if there is a way to set it as preferred profile for new 
connections?



In this patch series is also big rework of SBC codec, to support e.g.
UHQ mode and your changes would introduce new conflicts with that patch
series.

Anyway, correct behavior of SBC codec in automatic mode should
automatically increase or decrease SBC bitpool based on available
bandwidth.


The idea should be to have an external application getting information 
about the radio environment like the number of Bluetooth devices (A2DP 
sources and sinks, and other devices), link quality, WiFi usage, ... to 
be able to dynamically change the bitpool to be used.


Best regards,

Frédéric Danis
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [RFC 2/2] bluetooth: Add SBC get/set config message support

2019-05-17 Thread Frédéric Danis
Capability to dynamically change the bitpool used during runtime allows to
adjust the bitrate of the stream. In a crowded environment this can allow
to manage the bandwidth used and limit interference between source and
headphones.

get-a2dp-config message returns SBC bitpool configuration:
{{current bitpool} {min bitpool} {max bitpool}}

set-a2dp-config message gets new bitpool to use as parameter:
{new bitpool}
---
 src/modules/bluetooth/a2dp-codec-sbc.c | 47 ++
 1 file changed, 47 insertions(+)

diff --git a/src/modules/bluetooth/a2dp-codec-sbc.c 
b/src/modules/bluetooth/a2dp-codec-sbc.c
index cdc20d7f0..93aeb6241 100644
--- a/src/modules/bluetooth/a2dp-codec-sbc.c
+++ b/src/modules/bluetooth/a2dp-codec-sbc.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 

 #include 

@@ -51,6 +52,7 @@ struct sbc_info {
 uint8_t initial_bitpool;
 uint8_t min_bitpool;
 uint8_t max_bitpool;
+uint8_t next_bitpool;
 };

 static bool can_accept_capabilities(const uint8_t *capabilities_buffer, 
uint8_t capabilities_size, bool for_encoding) {
@@ -502,6 +504,48 @@ static size_t reduce_encoder_bitrate(void *codec_info, 
size_t write_link_mtu) {
 return get_block_size(codec_info, write_link_mtu);
 }

+static char* get_encoder_config(void *codec_info) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+pa_message_params *param;
+
+param = pa_message_params_new();
+pa_message_params_begin_list(param);
+pa_message_params_write_int64(param, sbc_info->sbc.bitpool);
+pa_message_params_write_int64(param, sbc_info->min_bitpool);
+pa_message_params_write_int64(param, sbc_info->max_bitpool);
+pa_message_params_end_list(param);
+
+return pa_message_params_to_string_free(param);
+}
+
+static int set_encoder_config(void *codec_info, char *new_config) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+void *state = NULL;
+int64_t value;
+
+if (pa_message_params_read_int64(new_config, &value, &state) != 
PA_PARAMS_OK)
+return -PA_ERR_INVALID;
+
+pa_log_info("Requested SBC Bitpool: %ld", value);
+if (value < sbc_info->min_bitpool || value > sbc_info->max_bitpool)
+return -PA_ERR_INVALID;
+sbc_info->next_bitpool = (uint8_t)value;
+
+return PA_OK;
+}
+
+static size_t apply_encoder_config(void *codec_info, size_t write_link_mtu) {
+struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
+
+if (!sbc_info->next_bitpool)
+return 0;
+
+set_bitpool(sbc_info, sbc_info->next_bitpool);
+sbc_info->next_bitpool = 0;
+
+return get_block_size(codec_info, write_link_mtu);
+}
+
 static size_t encode_buffer(void *codec_info, uint32_t timestamp, const 
uint8_t *input_buffer, size_t input_size, uint8_t *output_buffer, size_t 
output_size, size_t *processed) {
 struct sbc_info *sbc_info = (struct sbc_info *) codec_info;
 struct rtp_header *header;
@@ -644,4 +688,7 @@ const pa_a2dp_codec pa_a2dp_codec_sbc = {
 .reduce_encoder_bitrate = reduce_encoder_bitrate,
 .encode_buffer = encode_buffer,
 .decode_buffer = decode_buffer,
+.get_encoder_config = get_encoder_config,
+.set_encoder_config = set_encoder_config,
+.apply_encoder_config = apply_encoder_config,
 };
--
2.18.0
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [RFC 1/2] bluetooth: Add message to get/set A2DP codec configs

2019-05-17 Thread Frédéric Danis
This patch introduces 2 new messages to retrieve and set codec specific
configuration information.
It is up to each codec to define which information can be retrieved or set.
Message path is based on the remote device address (replacing ":" by "_").

 Get configuration command:
 pacmd send-message /bluetooth/bluez_sink. get-a2dp-config

 Set configuration command:
 pacmd send-message /bluetooth/bluez_sink. set-a2dp-config
  

To avoid breaking buffer encoding, I split set-a2dp-config in 2 functions.
set_encoder_config() is called to pass the new configuration to the
encoder.
apply_encoder_config() is called when no buffer needs to be encoded.
---
 src/modules/bluetooth/a2dp-codec-api.h   | 10 
 src/modules/bluetooth/module-bluez5-device.c | 54 
 src/pulsecore/core-util.h|  7 +++
 3 files changed, 71 insertions(+)

diff --git a/src/modules/bluetooth/a2dp-codec-api.h 
b/src/modules/bluetooth/a2dp-codec-api.h
index 55bb9ff70..23fbfe912 100644
--- a/src/modules/bluetooth/a2dp-codec-api.h
+++ b/src/modules/bluetooth/a2dp-codec-api.h
@@ -90,6 +90,16 @@ typedef struct pa_a2dp_codec {
  * returns size of filled ouput_buffer and set processed to size of
  * processed input_buffer */
 size_t (*decode_buffer)(void *codec_info, const uint8_t *input_buffer, 
size_t input_size, uint8_t *output_buffer, size_t output_size, size_t 
*processed);
+
+/* Get encoder codec configuration, returns Message API string specific to
+ * each codec */
+char *(*get_encoder_config)(void *codec_info);
+/* Set encoder codec configuration. new_config string is codec specific and
+ * in Message API format. returns PA error code */
+int (*set_encoder_config)(void *codec_info, char *new_config);
+/* Apply new config to encoder codec, returns new write block size or zero
+ * if not changed, called after set_encoder_config success */
+size_t (*apply_encoder_config)(void *codec_info, size_t write_link_mtu);
 } pa_a2dp_codec;
 
 #endif
diff --git a/src/modules/bluetooth/module-bluez5-device.c 
b/src/modules/bluetooth/module-bluez5-device.c
index 56c96054d..3ab4be508 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -45,6 +45,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "a2dp-codecs.h"
 #include "a2dp-codec-util.h"
@@ -133,6 +135,7 @@ struct userdata {
 pa_memchunk write_memchunk;
 
 const pa_a2dp_codec *a2dp_codec;
+bool a2dp_codec_config_pending;
 
 void *encoder_info;
 pa_sample_spec encoder_sample_spec;
@@ -1444,6 +1447,14 @@ static void thread_func(void *userdata) {
 handle_sink_block_size_change(u);
 }
 }
+} else if (u->a2dp_codec_config_pending && u->profile 
== PA_BLUETOOTH_PROFILE_A2DP_SINK &&
+u->a2dp_codec->apply_encoder_config) {
+size_t new_write_block_size = 
u->a2dp_codec->apply_encoder_config(u->encoder_info, u->write_link_mtu);
+if (new_write_block_size) {
+u->write_block_size = new_write_block_size;
+handle_sink_block_size_change(u);
+}
+u->a2dp_codec_config_pending = false;
 }
 
 blocks_to_write = 1;
@@ -1517,6 +1528,33 @@ finish:
 pa_log_debug("IO thread shutting down");
 }
 
+static int bluetooth_handler(const char *object_path, const char *message, 
char *message_parameters, char **response, void *userdata) {
+struct userdata *u;
+
+pa_assert(u = (struct userdata *) userdata);
+pa_assert(message);
+pa_assert(response);
+pa_assert(pa_safe_strneq(object_path, "/bluetooth/bluez_", 17));
+
+if (pa_streq(message, "get-a2dp-config")) {
+if (u->a2dp_codec->get_encoder_config) {
+*response = u->a2dp_codec->get_encoder_config(u->encoder_info);
+return PA_OK;
+}
+return -PA_ERR_NOTSUPPORTED;
+} else if (pa_streq(message, "set-a2dp-config")) {
+if (u->a2dp_codec->set_encoder_config) {
+int res = u->a2dp_codec->set_encoder_config(u->encoder_info, 
message_parameters);
+if (res == PA_OK)
+u->a2dp_codec_config_pending = true;
+return res;
+}
+return -PA_ERR_NOTSUPPORTED;
+}
+
+return -PA_ERR_NOTIMPLEMENTED;
+}
+
 /* Run from main thread */
 static int start_thread(struct userdata *u) {
 pa_assert(u);
@@ -1567,6 +1605,14 @@ static int start_thread(struct userdata *u) {
 u->source->set_volume(u->source);
 }
 
+if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) {
+char *address = pa_namereg_make_valid_name(u->device->address);
+char *path = pa_sprintf_malloc("/bluetooth/

[pulseaudio-discuss] [RFC 0/2] Add dynamic configuration of SBC bitpool

2019-05-17 Thread Frédéric Danis
This series of patch allows to manage the bandwidth used by an A2DP source
using SBC encoder by adding ability to change the bitpool dynamically during
runtime.
In a crowded environment this can allow to limit interference between source
and headphones.

This needs "Message API v2" patches from Georg Chini [1]

I am currently not sure in patch 2 where should occur the SBC bitpool apply.

Any comments appreciated.

[1] https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/51

Frédéric Danis (2):
  bluetooth: Add message to get/set A2DP codec configs
  bluetooth: Add SBC get/set config message support

 src/modules/bluetooth/a2dp-codec-api.h   | 10 
 src/modules/bluetooth/a2dp-codec-sbc.c   | 47 +
 src/modules/bluetooth/module-bluez5-device.c | 54 
 src/pulsecore/core-util.h|  7 +++
 4 files changed, 118 insertions(+)

--
2.18.0
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

[pulseaudio-discuss] [RFC 2/2] bluetooth: Add inband ringtone property

2012-11-12 Thread Frédéric Danis
---
 src/modules/bluetooth/module-bluetooth-device.c |   37 +++
 1 file changed, 37 insertions(+)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c 
b/src/modules/bluetooth/module-bluetooth-device.c
index 656852d..c734d6c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -122,6 +122,7 @@ struct hsp_info {
 pa_source *sco_source;
 void (*sco_source_set_volume)(pa_source *s);
 pa_hook_slot *sink_state_changed_slot;
+pa_hook_slot *sink_property_changed_slot;
 pa_hook_slot *source_state_changed_slot;
 pa_hook_slot *nrec_changed_slot;
 pa_hook_slot *output_gain_slot;
@@ -1593,6 +1594,34 @@ static pa_hook_result_t sink_state_changed_cb(pa_core 
*c, pa_sink *s, struct use
 return PA_HOOK_OK;
 }
 
+static pa_hook_result_t sink_property_changed_cb(pa_core *c, pa_sink *s, 
struct userdata *u) {
+const char *str;
+int val;
+dbus_bool_t value;
+const char *name = "InbandRingtone";
+
+pa_assert(c);
+pa_sink_assert_ref(s);
+pa_assert(u);
+
+if (s != u->sink)
+return PA_HOOK_OK;
+
+str = pa_proplist_gets(u->sink->proplist, "bluetooth.bsir");
+if (str == NULL)
+return PA_HOOK_OK;
+
+val = pa_parse_boolean(str);
+if (val < 0)
+return PA_HOOK_OK;
+
+value = !!val;
+
+send_property_update(u, name, DBUS_TYPE_BOOLEAN, &value);
+
+return PA_HOOK_OK;
+}
+
 static pa_hook_result_t source_state_changed_cb(pa_core *c, pa_source *s, 
struct userdata *u) {
 pa_assert(c);
 pa_source_assert_ref(s);
@@ -1804,6 +1833,9 @@ static int add_sink(struct userdata *u) {
 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
 u->sink->n_volume_steps = 16;
 
+if (!u->hsp.sink_property_changed_slot)
+u->hsp.sink_property_changed_slot = 
pa_hook_connect(&u->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], 
PA_HOOK_NORMAL, (pa_hook_cb_t) sink_property_changed_cb, u);
+
 k = pa_sprintf_malloc("bluetooth-device@%p", (void*) u->sink);
 pa_shared_set(u->core, k, u);
 pa_xfree(k);
@@ -2112,6 +2144,11 @@ static void stop_thread(struct userdata *u) {
 u->hsp.sink_state_changed_slot = NULL;
 }
 
+if (u->hsp.sink_property_changed_slot) {
+pa_hook_slot_free(u->hsp.sink_property_changed_slot);
+u->hsp.sink_property_changed_slot = NULL;
+}
+
 if (u->hsp.source_state_changed_slot) {
 pa_hook_slot_free(u->hsp.source_state_changed_slot);
 u->hsp.source_state_changed_slot = NULL;
-- 
1.7.9.5

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [RFC 1/2] bluetooth: Add MediaTransport volume management

2012-11-12 Thread Frédéric Danis
With BlueZ 5 volume updates for HFP will go through transport interface.

Note that this is backward compatible.
---
 src/modules/bluetooth/bluetooth-util.c  |   62 +++
 src/modules/bluetooth/bluetooth-util.h  |4 ++
 src/modules/bluetooth/module-bluetooth-device.c |   75 +++
 3 files changed, 130 insertions(+), 11 deletions(-)

diff --git a/src/modules/bluetooth/bluetooth-util.c 
b/src/modules/bluetooth/bluetooth-util.c
index 272b6ce..c0d5287 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -754,21 +754,49 @@ int 
pa_bluetooth_transport_parse_property(pa_bluetooth_transport *t, DBusMessage
 
 dbus_message_iter_recurse(i, &variant_i);
 
-switch (dbus_message_iter_get_arg_type(&variant_i)) {
+if (pa_streq(key, "NREC")) {
+dbus_bool_t value;
 
-case DBUS_TYPE_BOOLEAN: {
+if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_BOOLEAN) {
+pa_log("Property value not a boolean.");
+return -1;
+}
 
-dbus_bool_t value;
-dbus_message_iter_get_basic(&variant_i, &value);
+dbus_message_iter_get_basic(&variant_i, &value);
 
-if (pa_streq(key, "NREC") && t->nrec != value) {
-t->nrec = value;
-pa_log_debug("Transport %s: Property 'NREC' changed to %s.", 
t->path, t->nrec ? "True" : "False");
-
pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED], NULL);
-}
+if (t->nrec != value) {
+t->nrec = value;
+pa_log_debug("Transport %s: Property 'NREC' changed to %s.", 
t->path, t->nrec ? "True" : "False");
+pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED], 
NULL);
+}
+} else if(pa_streq(key,"OutputGain")) {
+uint16_t value;
 
-break;
- }
+if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_UINT16) {
+pa_log("Property value not an uint16.");
+return -1;
+}
+
+dbus_message_iter_get_basic(&variant_i, &value);
+
+if (t->output_gain != value) {
+t->output_gain = value;
+
pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_OUTPUT_GAIN_CHANGED], NULL);
+}
+} else if(pa_streq(key,"InputGain")) {
+uint16_t value;
+
+if (dbus_message_iter_get_arg_type(&variant_i) != DBUS_TYPE_UINT16) {
+pa_log("Property value not an uint16.");
+return -1;
+}
+
+dbus_message_iter_get_basic(&variant_i, &value);
+
+if (t->input_gain != value) {
+t->input_gain = value;
+
pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_INPUT_GAIN_CHANGED], NULL);
+}
 }
 
 return 0;
@@ -1104,6 +1132,8 @@ static DBusMessage 
*endpoint_set_configuration(DBusConnection *conn, DBusMessage
 uint8_t *config = NULL;
 int size = 0;
 pa_bool_t nrec = FALSE;
+uint16_t output_gain = 15;
+uint16_t input_gain = 15;
 enum profile p;
 DBusMessageIter args, props;
 DBusMessage *r;
@@ -1151,6 +1181,14 @@ static DBusMessage 
*endpoint_set_configuration(DBusConnection *conn, DBusMessage
 goto fail;
 dbus_message_iter_recurse(&value, &array);
 dbus_message_iter_get_fixed_array(&array, &config, &size);
+} else if (strcasecmp(key, "OutputGain") == 0) {
+if (var != DBUS_TYPE_UINT16)
+goto fail;
+dbus_message_iter_get_basic(&value, &output_gain);
+} else if (strcasecmp(key, "InputGain") == 0) {
+if (var != DBUS_TYPE_UINT16)
+goto fail;
+dbus_message_iter_get_basic(&value, &input_gain);
 }
 
 dbus_message_iter_next(&props);
@@ -1172,6 +1210,8 @@ static DBusMessage 
*endpoint_set_configuration(DBusConnection *conn, DBusMessage
 t = transport_new(y, path, p, config, size);
 if (nrec)
 t->nrec = nrec;
+t->output_gain = output_gain;
+t->input_gain = input_gain;
 pa_hashmap_put(d->transports, t->path, t);
 
 pa_log_debug("Transport %s profile %d available", t->path, t->profile);
diff --git a/src/modules/bluetooth/bluetooth-util.h 
b/src/modules/bluetooth/bluetooth-util.h
index 8a3f2ad..5fba105 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -67,6 +67,8 @@ enum profile {
 typedef enum pa_bluetooth_transport_hook {
 PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED, /* Call data: NULL. */
 PA_BLUETOOTH_TRANSPORT_HOOK_REMOVED, /* Call data: NULL. */
+PA_BLUETOOTH_TRANSPORT_HOOK_OUTPUT_GAIN_CHANGED, /* Call data: NULL. */
+PA_BLUETOOTH_TRANSPORT_HOOK_INPUT_GAIN_CHANGED, /* Call data: NULL. */
 PA_BLUETOOTH_TRANSPORT_HOOK_MAX
 } pa_bluetooth_transport_hook_t;
 
@@ -78,6 +80,8 @@ struct pa_bluetooth_transport {
 uint8_t *config;
 int config_si

[pulseaudio-discuss] [PATCH v2] bluetooth: Fix bluetooth.nrec property not updated

2012-06-12 Thread Frédéric Danis
PropertyChanged signal of org.BlueZ.MediaTransport is processed in
pa_bluetooth_transport_parse_property() which updates t->nrec.
This is called by :
- First by filter_cb() of bluetooth-util.c
- Then by filter_cb() of module-bluetooth-device.c which retrieve value
  of t->nrec before calling parse function, then it checks if t->nrec
  has changed before updating bluetooth.nrec property.
  As t->nrec has alreday been changed during first process, property
  update is never performed.

This patch creates a new hook in pa_bluetooth_transport called
PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED.
The hook is fired by bluetooth-util.c when the transport's NREC
property changes.
module-bluetooth-device.c won't listen the PropertyChanged signal of
MediaTransport anymore. Instead, it will use the hook in
pa_bluetooth_transport to get a notification when the NREC property
changes, and update the sink or source proplist accordingly.

const qualifier for returned pointer of
pa_bluetooth_discovery_get_transport() is removed.
---
 src/modules/bluetooth/bluetooth-util.c  |   15 ++--
 src/modules/bluetooth/bluetooth-util.h  |   10 +-
 src/modules/bluetooth/module-bluetooth-device.c |   44 +++
 3 files changed, 43 insertions(+), 26 deletions(-)

diff --git a/src/modules/bluetooth/bluetooth-util.c 
b/src/modules/bluetooth/bluetooth-util.c
index b786502..42b7a05 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -138,8 +138,13 @@ static pa_bluetooth_device* device_new(const char *path) {
 }
 
 static void transport_free(pa_bluetooth_transport *t) {
+int i;
+
 pa_assert(t);
 
+for (i=0; i < PA_BLUETOOTH_TRANSPORT_HOOK_MAX ; i++)
+pa_hook_done(&t->hooks[i]);
+
 pa_xfree(t->path);
 pa_xfree(t->config);
 pa_xfree(t);
@@ -756,8 +761,10 @@ int 
pa_bluetooth_transport_parse_property(pa_bluetooth_transport *t, DBusMessage
 dbus_bool_t value;
 dbus_message_iter_get_basic(&variant_i, &value);
 
-if (pa_streq(key, "NREC"))
+if (pa_streq(key, "NREC") && t->nrec != value) {
 t->nrec = value;
+
pa_hook_fire(&t->hooks[PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED], t);
+}
 
 break;
  }
@@ -979,7 +986,7 @@ const pa_bluetooth_device* 
pa_bluetooth_discovery_get_by_path(pa_bluetooth_disco
 return NULL;
 }
 
-const pa_bluetooth_transport* 
pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char 
*path) {
+pa_bluetooth_transport* 
pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char 
*path) {
 pa_bluetooth_device *d;
 pa_bluetooth_transport *t;
 void *state = NULL;
@@ -1085,6 +1092,7 @@ static int setup_dbus(pa_bluetooth_discovery *y) {
 
 static pa_bluetooth_transport *transport_new(pa_bluetooth_discovery *y, const 
char *path, enum profile p, const uint8_t *config, int size) {
 pa_bluetooth_transport *t;
+int i;
 
 t = pa_xnew0(pa_bluetooth_transport, 1);
 t->y = y;
@@ -1097,6 +1105,9 @@ static pa_bluetooth_transport 
*transport_new(pa_bluetooth_discovery *y, const ch
 memcpy(t->config, config, size);
 }
 
+for (i=0; i < PA_BLUETOOTH_TRANSPORT_HOOK_MAX ; i++)
+pa_hook_init(&t->hooks[i], t);
+
 return t;
 }
 
diff --git a/src/modules/bluetooth/bluetooth-util.h 
b/src/modules/bluetooth/bluetooth-util.h
index 2752a69..ebffd3d 100644
--- a/src/modules/bluetooth/bluetooth-util.h
+++ b/src/modules/bluetooth/bluetooth-util.h
@@ -63,6 +63,11 @@ enum profile {
 PROFILE_OFF
 };
 
+typedef enum pa_bluetooth_transport_hook {
+PA_BLUETOOTH_TRANSPORT_HOOK_NREC_CHANGED,
+PA_BLUETOOTH_TRANSPORT_HOOK_MAX
+} pa_bluetooth_transport_hook_t;
+
 struct pa_bluetooth_transport {
 pa_bluetooth_discovery *y;
 char *path;
@@ -71,6 +76,9 @@ struct pa_bluetooth_transport {
 uint8_t *config;
 int config_size;
 pa_bool_t nrec;
+
+/* hooks */
+pa_hook hooks[PA_BLUETOOTH_TRANSPORT_HOOK_MAX];
 };
 
 /* This enum is shared among Audio, Headset, AudioSink, and AudioSource, 
although not all values are acceptable in all profiles */
@@ -124,7 +132,7 @@ void pa_bluetooth_discovery_sync(pa_bluetooth_discovery *d);
 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);
 
-const pa_bluetooth_transport* 
pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char 
*path);
+pa_bluetooth_transport* 
pa_bluetooth_discovery_get_transport(pa_bluetooth_discovery *y, const char 
*path);
 const pa_bluetooth_transport* pa_bluetooth_device_get_transport(const 
pa_bluetooth_device *d, enum profile profile);
 
 int pa_bluetooth_transport_acquire(const pa_bluetooth_transport *t, const char 
*accesstype, size_t *imtu, size_t *omtu);
diff --git a/src/modu

[pulseaudio-discuss] [PATCH] bluetooth: Fix bluetooth.nrec property not updated

2012-05-29 Thread Frédéric Danis
PropertyChanged signal of org.BlueZ.MediaTransport is processed in
pa_bluetooth_transport_parse_property() which updates t->nrec.
This is called by :
- First by filter_cb() of bluetooth-util.c
- Then by filter_cb()of module-bluetooth-device.c which retrieve value
  of t->nrec before calling parse function, then it checks if t->nrec
  has changed before updating bluetooth.nrec property.
  As t->nrec has alreday been changed during first process, property
  update is never performed.
---
 src/modules/bluetooth/module-bluetooth-device.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c 
b/src/modules/bluetooth/module-bluetooth-device.c
index 0b12cc7..1559a3c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1814,7 +1814,8 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, 
DBusMessage *m, void *us
 } else if (dbus_message_is_signal(m, "org.bluez.MediaTransport", 
"PropertyChanged")) {
 DBusMessageIter arg_i;
 pa_bluetooth_transport *t;
-pa_bool_t nrec;
+const char *str;
+int nrec = -1;
 
 t = (pa_bluetooth_transport *) 
pa_bluetooth_discovery_get_transport(u->discovery, u->transport);
 pa_assert(t);
@@ -1824,11 +1825,14 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, 
DBusMessage *m, void *us
 goto fail;
 }
 
-nrec = t->nrec;
-
 if (pa_bluetooth_transport_parse_property(t, &arg_i) < 0)
 goto fail;
 
+/* Update Noise reduction and echo cancellation if needed */
+str = pa_proplist_gets(u->source->proplist, "bluetooth.nrec");
+if (str != NULL)
+nrec = pa_parse_boolean(str);
+
 if (nrec != t->nrec) {
 pa_log_debug("dbus: property 'NREC' changed to value '%s'", 
t->nrec ? "True" : "False");
 pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? 
"1" : "0");
-- 
1.7.9.5

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH v2] bluetooth: Fix crash on disconnection

2012-05-15 Thread Frédéric Danis
When a Bluetooth headset is connected only to HFP profile (not connected
to A2DP) and host streams to it, a crash occurs if host disconnects.

When HFP disconnects, audio thread will fail on POLLHUP then generate
a message to set PA profile to Off before ending.
If this message is managed before PA unload bluetooth device module,
all works fine.
But, if this message is managed during module unload, this finish by
re-entrance in release code (stop_thread) and a crash.

This fix prevents to process profile change when module is unloading.


Following are crash traces:

D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes busy.
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: 
interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: 
interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
I: [pulseaudio] module-suspend-on-idle.c: Source bluez_source.10_04_14_D1_96_1C 
idle for too long, suspending ...
D: [pulseaudio] source.c: Suspend cause of source 
bluez_source.10_04_14_D1_96_1C is 0x0004, suspending
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 
'disconnected'
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 
'disconnected'
D: [pulseaudio] module-bluetooth-discover.c: Unloading module for 
/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
I: [pulseaudio] module.c: Unloading "module-bluetooth-device" (index: #19).
D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes idle, timeout in 5 seconds.
I: [bluetooth] module-bluetooth-device.c: FD error: POLLHUP
D: [bluetooth] module-bluetooth-device.c: IO thread failed
D: [bluetooth] sink-input.c: Have to rewind 2130 bytes on render memblockq.
D: [bluetooth] sink-input.c: Have to rewind 11742 bytes on implementor.
D: [bluetooth] sink.c: Requesting rewind due to started move
D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes idle, timeout in 5 seconds.
I: [pulseaudio] sink-input.c: Trying to change sample rate
I: [pulseaudio] alsa-sink.c: Updating rate for device front:0, new rate is 44100
I: [pulseaudio] sink.c: Changed sampling rate successfully
I: [pulseaudio] sink-input.c: Rate changed to 44100 Hz
I: [pulseaudio] protocol-native.c: Requested tlength=200,00 ms, minreq=10,00 ms
D: [pulseaudio] protocol-native.c: Adjust latency mode enabled, configuring 
sink latency to half of overall latency.
D: [pulseaudio] protocol-native.c: Requested latency=90,00 ms, Received 
latency=90,00 ms
I: [pulseaudio] resampler.c: Forcing resampler 'copy', because of fixed, 
identical sample rates.
D: [pulseaudio] resampler.c: Channel matrix:
D: [pulseaudio] resampler.c:I00
D: [pulseaudio] resampler.c: +--
D: [pulseaudio] resampler.c: O00 | 1,000
D: [pulseaudio] resampler.c: O01 | 1,000
I: [pulseaudio] remap_sse.c: Using SSE mono to stereo remapping
I: [pulseaudio] resa

[pulseaudio-discuss] [PATCH] bluetooth: Fix crash on disconnection

2012-05-14 Thread Frédéric Danis
When a Bluetooth headset is connected only to HFP profile (not connected
to A2DP) and host streams to it, a crash occurs if host disconnects.

When HFP disconnects, audio thread will fail on POLLHUP then generate
a message to set PA profile to Off before ending.
If this message is managed before PA unload bluetooth device module,
all works fine.
But, if this message is managed during module unload, this finish by
re-entrance in release code (stop_thread) and a crash.

This fix prevents to send the profile change when module is unloading.


Following are crash traces:

D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes busy.
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: 
interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: 
interface=org.bluez.MediaTransport, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged
I: [pulseaudio] module-suspend-on-idle.c: Source bluez_source.10_04_14_D1_96_1C 
idle for too long, suspending ...
D: [pulseaudio] source.c: Suspend cause of source 
bluez_source.10_04_14_D1_96_1C is 0x0004, suspending
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 
'disconnected'
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 
'disconnected'
D: [pulseaudio] module-bluetooth-discover.c: Unloading module for 
/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C
D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Audio, 
path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged
I: [pulseaudio] module.c: Unloading "module-bluetooth-device" (index: #19).
D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes idle, timeout in 5 seconds.
I: [bluetooth] module-bluetooth-device.c: FD error: POLLHUP
D: [bluetooth] module-bluetooth-device.c: IO thread failed
D: [bluetooth] sink-input.c: Have to rewind 2130 bytes on render memblockq.
D: [bluetooth] sink-input.c: Have to rewind 11742 bytes on implementor.
D: [bluetooth] sink.c: Requesting rewind due to started move
D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C 
becomes idle, timeout in 5 seconds.
I: [pulseaudio] sink-input.c: Trying to change sample rate
I: [pulseaudio] alsa-sink.c: Updating rate for device front:0, new rate is 44100
I: [pulseaudio] sink.c: Changed sampling rate successfully
I: [pulseaudio] sink-input.c: Rate changed to 44100 Hz
I: [pulseaudio] protocol-native.c: Requested tlength=200,00 ms, minreq=10,00 ms
D: [pulseaudio] protocol-native.c: Adjust latency mode enabled, configuring 
sink latency to half of overall latency.
D: [pulseaudio] protocol-native.c: Requested latency=90,00 ms, Received 
latency=90,00 ms
I: [pulseaudio] resampler.c: Forcing resampler 'copy', because of fixed, 
identical sample rates.
D: [pulseaudio] resampler.c: Channel matrix:
D: [pulseaudio] resampler.c:I00
D: [pulseaudio] resampler.c: +--
D: [pulseaudio] resampler.c: O00 | 1,000
D: [pulseaudio] resampler.c: O01 | 1,000
I: [pulseaudio] remap_sse.c: Using SSE mono to stereo remapping
I: [pulseaudio] res