[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.12-83-gf5c301d

Lennart Poettering gitmailer-noreply at 0pointer.de
Mon Sep 29 12:45:08 PDT 2008


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  87971c8707cf84e0f386b5fe5329c8aff155e629 (commit)

- Log -----------------------------------------------------------------
f5c301d... make module-bluetooth-discover actually load modules and smaller other fixes
3f4bc03... all kinds of minor type, memory leak, initializatio fixes
a35f84a... instead of failing when the requested sampling rate is not available find the next one that is higher
aa1974b... Use the same module parameter names for module-bluetooth-device as for most other modules
7923731... use TRUE for pa_bool_t arguments
60e9744... remove a few compiler warnings in BlueZ code
-----------------------------------------------------------------------

Summary of changes:
 src/modules/bluetooth/ipc.c                       |    7 +-
 src/modules/bluetooth/ipc.h                       |    2 +-
 src/modules/bluetooth/module-bluetooth-device.c   |  323 +++++-----
 src/modules/bluetooth/module-bluetooth-discover.c |  695 ++++++++++++++-------
 src/modules/bluetooth/sbc.c                       |    2 +-
 src/modules/module-alsa-sink.c                    |    2 +-
 src/modules/module-alsa-source.c                  |    2 +-
 7 files changed, 640 insertions(+), 393 deletions(-)

-----------------------------------------------------------------------

commit 60e9744f281cde85790dd764cd4e52dc4b19f6b1
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:34:18 2008 +0200

    remove a few compiler warnings in BlueZ code

diff --git a/src/modules/bluetooth/ipc.c b/src/modules/bluetooth/ipc.c
index e7b712d..9825699 100644
--- a/src/modules/bluetooth/ipc.c
+++ b/src/modules/bluetooth/ipc.c
@@ -40,7 +40,7 @@ static const char *strmsg[] = {
 	"BT_STREAMFD_IND",
 };
 
-int bt_audio_service_open()
+int bt_audio_service_open(void)
 {
 	int sk;
 	int err;
@@ -88,7 +88,7 @@ int bt_audio_service_get_data_fd(int sk)
 	msgh.msg_control = &cmsg_b;
 	msgh.msg_controllen = CMSG_LEN(sizeof(int));
 
-	ret = recvmsg(sk, &msgh, 0);
+	ret = (int) recvmsg(sk, &msgh, 0);
 	if (ret < 0) {
 		err = errno;
 		fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n",
@@ -111,9 +111,8 @@ int bt_audio_service_get_data_fd(int sk)
 
 const char *bt_audio_strmsg(int type)
 {
-	if (type < 0 || type > (sizeof(strmsg) / sizeof(strmsg[0])))
+    if (type < 0 || (size_t) type > (sizeof(strmsg) / sizeof(strmsg[0])))
 		return NULL;
 
 	return strmsg[type];
 }
-
diff --git a/src/modules/bluetooth/ipc.h b/src/modules/bluetooth/ipc.h
index c900fcd..ae85e72 100644
--- a/src/modules/bluetooth/ipc.h
+++ b/src/modules/bluetooth/ipc.h
@@ -289,7 +289,7 @@ struct bt_control_ind {
 /* Function declaration */
 
 /* Opens a connection to the audio service: return a socket descriptor */
-int bt_audio_service_open();
+int bt_audio_service_open(void);
 
 /* Closes a connection to the audio service */
 int bt_audio_service_close(int sk);
diff --git a/src/modules/bluetooth/sbc.c b/src/modules/bluetooth/sbc.c
index 6303421..02a6143 100644
--- a/src/modules/bluetooth/sbc.c
+++ b/src/modules/bluetooth/sbc.c
@@ -145,7 +145,7 @@ static uint8_t sbc_crc8(const uint8_t *data, size_t len)
 
 	octet = data[i];
 	for (i = 0; i < len % 8; i++) {
-		char bit = ((octet ^ crc) & 0x80) >> 7;
+		unsigned char bit = ((octet ^ crc) & 0x80) >> 7;
 
 		crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0);
 

commit 7923731e1820eddbbdfe01eab8d6ea6620e9286f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:36:42 2008 +0200

    use TRUE for pa_bool_t arguments

diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index b8bef93..30d4d3a 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -1136,7 +1136,7 @@ static void thread_func(void *userdata) {
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)
diff --git a/src/modules/module-alsa-source.c b/src/modules/module-alsa-source.c
index cb77767..d0a22db 100644
--- a/src/modules/module-alsa-source.c
+++ b/src/modules/module-alsa-source.c
@@ -971,7 +971,7 @@ static void thread_func(void *userdata) {
             pa_rtpoll_set_timer_disabled(u->rtpoll);
 
         /* Hmm, nothing to do. Let's sleep */
-        if ((ret = pa_rtpoll_run(u->rtpoll, 1)) < 0)
+        if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
             goto fail;
 
         if (ret == 0)

commit aa1974b7a022db6b3733ec8247c863ca3e9e6c5d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:40:52 2008 +0200

    Use the same module parameter names for module-bluetooth-device as for most other modules

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index e76264a..86109f7 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -63,8 +63,8 @@ PA_MODULE_DESCRIPTION("Bluetooth audio sink and source");
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
-        "name=<name of the device> "
-        "addr=<address of the device> "
+        "sink_name=<name of the device> "
+        "address=<address of the device> "
         "profile=<a2dp|hsp>");
 
 struct bt_a2dp {
@@ -115,8 +115,8 @@ struct userdata {
 };
 
 static const char* const valid_modargs[] = {
-    "name",
-    "addr",
+    "sink_name",
+    "address",
     "profile",
     "rate",
     "channels",
@@ -789,29 +789,32 @@ int pa__init(pa_module* m) {
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
+    u->ss = m->core->default_sample_spec;
 
     if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
-        pa_log_error("failed to parse module arguments");
+        pa_log_error("Failed to parse module arguments");
         goto fail;
     }
-    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "name", DEFAULT_SINK_NAME)))) {
-        pa_log_error("failed to get device name from module arguments");
+    if (!(u->name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)))) {
+        pa_log_error("Failed to get device name from module arguments");
         goto fail;
     }
-    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "addr", NULL)))) {
-        pa_log_error("failed to get device address from module arguments");
+    if (!(u->addr = pa_xstrdup(pa_modargs_get_value(ma, "address", NULL)))) {
+        pa_log_error("Failed to get device address from module arguments");
         goto fail;
     }
     if (!(u->profile = pa_xstrdup(pa_modargs_get_value(ma, "profile", NULL)))) {
-        pa_log_error("failed to get profile from module arguments");
+        pa_log_error("Failed to get profile from module arguments");
         goto fail;
     }
     if (pa_modargs_get_value_u32(ma, "rate", &u->ss.rate) < 0) {
-        pa_log_error("failed to get rate from module arguments");
+        pa_log_error("Failed to get rate from module arguments");
         goto fail;
     }
+
+    channels = u->ss.channels;
     if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0) {
-        pa_log_error("failed to get channels from module arguments");
+        pa_log_error("Failed to get channels from module arguments");
         goto fail;
     }
     u->ss.channels = (uint8_t) channels;

commit a35f84a4f9844142d51490a231fe5638b936d4fc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:42:29 2008 +0200

    instead of failing when the requested sampling rate is not available find the next one that is higher

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 86109f7..75d313c 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -252,33 +252,37 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
 
 static int bt_a2dp_init(struct userdata *u) {
     sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
-    unsigned int max_bitpool, min_bitpool;
-
-    switch (u->ss.rate) {
-        case 48000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_48000;
-            break;
-        case 44100:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_44100;
-            break;
-        case 32000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_32000;
+    uint8_t max_bitpool, min_bitpool;
+    unsigned i;
+
+    static const struct {
+        uint32_t rate;
+        uint8_t cap;
+    } freq_table[] = {
+        { 16000U, BT_SBC_SAMPLING_FREQ_16000 },
+        { 32000U, BT_SBC_SAMPLING_FREQ_32000 },
+        { 44100U, BT_SBC_SAMPLING_FREQ_44100 },
+        { 48000U, BT_SBC_SAMPLING_FREQ_48000 }
+    };
+
+    /* Find the lowest freq that is at least as high as the requested
+     * sampling rate */
+    for (i = 0; i < PA_ELEMENTSOF(freq_table); i++)
+        if (freq_table[i].rate >= u->ss.rate || i == PA_ELEMENTSOF(freq_table)-1 ) {
+            u->ss.rate = freq_table[i].rate;
+            cap->frequency = freq_table[i].cap;
             break;
-        case 16000:
-            cap->frequency = BT_SBC_SAMPLING_FREQ_16000;
-            break;
-        default:
-            pa_log_error("Rate %d not supported", u->ss.rate);
-            return -1;
-    }
+        }
 
-    if (u->ss.channels == 2) {
+    if (u->ss.channels >= 2) {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO;
         else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL;
+
+        u->ss.channels = 2;
     } else {
         if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO)
             cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO;

commit 3f4bc0368da002b3159d4506560aeb0331f7dc17
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:43:28 2008 +0200

    all kinds of minor type, memory leak, initializatio fixes

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 75d313c..395d54f 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -53,7 +53,7 @@
 #define DEFAULT_SINK_NAME "bluetooth_sink"
 #define BUFFER_SIZE 2048
 #define MAX_BITPOOL 64
-#define MIN_BITPOOL 2
+#define MIN_BITPOOL 2U
 #define SOL_SCO 17
 #define SCO_TXBUFS 0x03
 #define SCO_RXBUFS 0x04
@@ -71,14 +71,14 @@ struct bt_a2dp {
     sbc_capabilities_t sbc_capabilities;
     sbc_t sbc;                           /* Codec data */
     pa_bool_t sbc_initialized;           /* Keep track if the encoder is initialized */
-    uint16_t codesize;                   /* SBC codesize */
-    uint8_t samples;                     /* Number of encoded samples */
+    size_t codesize;                     /* SBC codesize */
+    unsigned samples;                    /* Number of encoded samples */
     uint8_t buffer[BUFFER_SIZE];         /* Codec transfer buffer */
-    uint16_t count;                      /* Codec transfer buffer counter */
+    size_t count;                        /* Codec transfer buffer counter */
 
-    uint32_t nsamples;                   /* Cumulative number of codec samples */
+    unsigned total_samples;              /* Cumulative number of codec samples */
     uint16_t seq_num;                    /* Cumulative packet sequence */
-    uint8_t frame_count;                 /* Current frames in buffer*/
+    unsigned frame_count;                /* Current frames in buffer*/
 };
 
 struct userdata {
@@ -91,23 +91,20 @@ struct userdata {
     pa_rtpoll_item *rtpoll_item;
     pa_thread *thread;
 
-    int64_t offset;
+    uint64_t offset;
     pa_smoother *smoother;
 
-    pa_memchunk memchunk;
-    pa_mempool *mempool;
-
     char *name;
     char *addr;
     char *profile;
     pa_sample_spec ss;
 
-    uint8_t audioservice_fd;
-    uint8_t stream_fd;
+    int audioservice_fd;
+    int stream_fd;
 
     uint8_t transport;
     char *strtransport;
-    uint16_t link_mtu;
+    size_t link_mtu;
     size_t block_size;
     pa_usec_t latency;
 
@@ -188,20 +185,20 @@ static int bt_getcaps(struct userdata *u) {
     else if (strcasecmp(u->profile, "hsp") == 0)
         msg.getcaps_req.transport = BT_CAPABILITIES_TRANSPORT_SCO;
     else {
-        pa_log_error("invalid profile argument: %s", u->profile);
+        pa_log_error("Invalid profile argument: %s", u->profile);
         return -1;
     }
     msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT;
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.getcaps_req.h);
     if (e < 0) {
-        pa_log_error("failed to send GETCAPABILITIES_REQ");
+        pa_log_error("Failed to send GETCAPABILITIES_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_GETCAPABILITIES_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect for GETCAPABILITIES_RSP");
+        pa_log_error("Failed to expect for GETCAPABILITIES_RSP");
         return e;
     }
     if (msg.rsp_hdr.posix_errno != 0) {
@@ -320,11 +317,11 @@ static int bt_a2dp_init(struct userdata *u) {
     else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR)
         cap->allocation_method = BT_A2DP_ALLOCATION_SNR;
 
-    min_bitpool = PA_MAX(MIN_BITPOOL, cap->min_bitpool);
-    max_bitpool = PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
+    min_bitpool = (uint8_t) PA_MAX(MIN_BITPOOL, cap->min_bitpool);
+    max_bitpool = (uint8_t) PA_MIN(default_bitpool(cap->frequency, cap->channel_mode), cap->max_bitpool);
 
-    cap->min_bitpool = min_bitpool;
-    cap->max_bitpool = max_bitpool;
+    cap->min_bitpool = (uint8_t) min_bitpool;
+    cap->max_bitpool = (uint8_t) max_bitpool;
 
     return 0;
 }
@@ -362,7 +359,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
     if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)
         a2dp->sbc.mode = SBC_MODE_JOINT_STEREO;
 
-    a2dp->sbc.allocation = (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
+    a2dp->sbc.allocation = (uint8_t) (active_capabilities.allocation_method == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR : SBC_AM_LOUDNESS);
 
     switch (active_capabilities.subbands) {
         case BT_A2DP_SUBBANDS_4:
@@ -389,7 +386,7 @@ static void bt_a2dp_setup(struct bt_a2dp *a2dp) {
     }
 
     a2dp->sbc.bitpool = active_capabilities.max_bitpool;
-    a2dp->codesize = sbc_get_codesize(&a2dp->sbc);
+    a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc);
     a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
 }
 
@@ -423,13 +420,13 @@ static int bt_setconf(struct userdata *u) {
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.setconf_req.h);
     if (e < 0) {
-        pa_log_error("failed to send BT_SETCONFIGURATION_REQ");
+        pa_log_error("Failed to send BT_SETCONFIGURATION_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_SETCONFIGURATION_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect BT_SETCONFIGURATION_RSP");
+        pa_log_error("Failed to expect BT_SETCONFIGURATION_RSP");
         return e;
     }
 
@@ -470,13 +467,13 @@ static int bt_getstreamfd(struct userdata *u) {
 
     e = bt_audioservice_send(u->audioservice_fd, &msg.start_req.h);
     if (e < 0) {
-        pa_log_error("failed to send BT_STREAMSTART_REQ");
+        pa_log_error("Failed to send BT_STREAMSTART_REQ");
         return e;
     }
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.rsp_hdr.msg_h, BT_STREAMSTART_RSP);
     if (e < 0) {
-        pa_log_error("failed to expect BT_STREAMSTART_RSP");
+        pa_log_error("Failed to expect BT_STREAMSTART_RSP");
         return e;
     }
 
@@ -487,7 +484,7 @@ static int bt_getstreamfd(struct userdata *u) {
 
     e = bt_audioservice_expect(u->audioservice_fd, &msg.streamfd_ind.h, BT_STREAMFD_IND);
     if (e < 0) {
-        pa_log_error("failed to expect BT_STREAMFD_IND");
+        pa_log_error("Failed to expect BT_STREAMFD_IND");
         return e;
     }
 
@@ -496,13 +493,13 @@ static int bt_getstreamfd(struct userdata *u) {
 
     u->stream_fd = bt_audio_service_get_data_fd(u->audioservice_fd);
     if (u->stream_fd < 0) {
-        pa_log_error("failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
+        pa_log_error("Failed to get data fd: %s (%d)",pa_cstrerror(errno), errno);
         return -errno;
     }
 
     if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
-        if (pa_socket_set_sndbuf(u->stream_fd, 10*u->link_mtu) < 0) {
-            pa_log_error("failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
+        if (pa_socket_set_sndbuf(u->stream_fd, 10U*u->link_mtu) < 0) {
+            pa_log_error("Failed to set socket options for A2DP: %s (%d)",pa_cstrerror(errno), errno);
             return -errno;
         }
     }
@@ -543,9 +540,9 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t w, r;
-            r = pa_smoother_get(u->smoother, pa_rtclock_usec());
-            w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec);
-            *((pa_usec_t*) data) = w > r ? w - r : 0;
+/*             r = pa_smoother_get(u->smoother, pa_rtclock_usec()); */
+/* /\*             w = pa_bytes_to_usec(u->offset + (uint64_t) u->memchunk.length, &u->sink->sample_spec); *\/ */
+            *((pa_usec_t*) data) = /*w > r ? w - r :*/ 0;
             return 0;
         }
 
@@ -556,56 +553,46 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
 static int sco_process_render(struct userdata *u) {
     void *p;
-    ssize_t l;
-    int write_type = 0;
+    int ret = 0;
+    pa_memchunk memchunk;
 
-    u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-    pa_log_debug("memblock asked size %d", u->block_size);
-    u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-    pa_log_debug("memchunk length %d", u->memchunk.length);
-    pa_sink_render_into_full(u->sink, &u->memchunk);
+    pa_sink_render_full(u->sink, u->block_size, &memchunk);
 
-    pa_assert(u->memchunk.length > 0);
+    p = pa_memblock_acquire(memchunk.memblock);
 
-    p = pa_memblock_acquire(u->memchunk.memblock);
+    for (;;) {
+        ssize_t l;
 
-sco_write:
-    l = pa_write(u->stream_fd, (uint8_t*) p, u->memchunk.length, &write_type);
-    pa_log_debug("memblock written to socket: %d bytes", l);
+        l = pa_loop_write(u->stream_fd, (uint8_t*) p, memchunk.length, NULL);
+        pa_log_debug("Memblock written to socket: %li bytes", (long) l);
 
-    pa_assert(l != 0);
+        pa_assert(l != 0);
 
-    if (l < 0) {
-        if (errno == EINTR) {
-            pa_log_debug("EINTR");
-            goto sco_write;
+        if (l > 0) {
+            u->offset += (uint64_t) l;
+            break;
         }
-        else if (errno == EAGAIN) {
+
+        if (errno == EINTR)
+            pa_log_debug("EINTR");
+        else if (errno == EAGAIN)
             pa_log_debug("EAGAIN");
-            goto sco_write;
-        }
         else {
-            pa_memblock_release(u->memchunk.memblock);
-            pa_memblock_unref(u->memchunk.memblock);
-            pa_memchunk_reset(&u->memchunk);
-            pa_log_debug("memchunk reseted");
             pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
-            return -1;
+            ret = -1;
+            break;
         }
-    } else {
-        pa_memblock_release(u->memchunk.memblock);
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
-        pa_log_debug("memchunk reseted");
-        u->offset += l;
-        return 0;
     }
+
+    pa_memblock_release(memchunk.memblock);
+    pa_memblock_unref(memchunk.memblock);
+
+    return ret;
 }
 
 static int a2dp_process_render(struct userdata *u) {
-    ssize_t l;
-    uint8_t write_type = 0;
-    uint16_t written;
+    int written;
+
     struct bt_a2dp *a2dp = &u->a2dp;
     struct rtp_header *header = (void *) a2dp->buffer;
     struct rtp_payload *payload = (void *) (a2dp->buffer + sizeof(*header));
@@ -614,39 +601,35 @@ static int a2dp_process_render(struct userdata *u) {
 
     do {
         /* Render some data */
-        uint16_t frame_size;
-        uint16_t encoded;
+        int frame_size, encoded;
         void *p;
+        pa_memchunk memchunk;
 
-        u->memchunk.memblock = pa_memblock_new(u->mempool, u->block_size);
-        pa_log_debug("memblock asked size %d", u->block_size);
-        u->memchunk.length = pa_memblock_get_length(u->memchunk.memblock);
-        pa_log_debug("memchunk length %d", u->memchunk.length);
-        pa_sink_render_into_full(u->sink, &u->memchunk);
+        pa_sink_render_full(u->sink, u->block_size, &memchunk);
 
-        pa_assert(u->memchunk.length > 0);
+        p = pa_memblock_acquire(memchunk.memblock);
 
-        p = pa_memblock_acquire(u->memchunk.memblock);
-        frame_size = sbc_get_frame_length(&a2dp->sbc);
+        frame_size = (uint16_t) sbc_get_frame_length(&a2dp->sbc);
         pa_log_debug("SBC frame_size: %d", frame_size);
 
-        encoded = sbc_encode(&a2dp->sbc, (uint8_t*) p, a2dp->codesize, a2dp->buffer + a2dp->count,
-                sizeof(a2dp->buffer) - a2dp->count, &written);
+        encoded = sbc_encode(&a2dp->sbc, p, (int) a2dp->codesize, a2dp->buffer + a2dp->count,
+                             (int) (sizeof(a2dp->buffer) - a2dp->count), &written);
         pa_log_debug("SBC: encoded: %d; written: %d", encoded, written);
+
+        pa_memblock_release(memchunk.memblock);
+        pa_memblock_unref(memchunk.memblock);
+
         if (encoded <= 0) {
             pa_log_error("SBC encoding error (%d)", encoded);
             return -1;
         }
-        pa_memblock_release(u->memchunk.memblock);
-        pa_memblock_unref(u->memchunk.memblock);
-        pa_memchunk_reset(&u->memchunk);
-        pa_log_debug("memchunk reseted");
 
-        a2dp->count += written;
+        a2dp->count += (size_t) written;
         a2dp->frame_count++;
-        a2dp->samples += encoded / frame_size;
-        a2dp->nsamples += encoded / frame_size;
-    } while (a2dp->count + written <= u->link_mtu);
+        a2dp->samples += (unsigned) encoded / frame_size;
+        a2dp->total_samples += (unsigned) encoded / frame_size;
+
+    } while (a2dp->count + (size_t) written <= u->link_mtu);
 
     /* write it to the fifo */
     memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
@@ -654,24 +637,24 @@ static int a2dp_process_render(struct userdata *u) {
     header->v = 2;
     header->pt = 1;
     header->sequence_number = htons(a2dp->seq_num);
-    header->timestamp = htonl(a2dp->nsamples);
+    header->timestamp = htonl(a2dp->total_samples);
     header->ssrc = htonl(1);
 
-avdtp_write:
-    l = pa_write(u->stream_fd, a2dp->buffer, a2dp->count, &write_type);
-    pa_log_debug("avdtp_write: requested %d bytes; written %d bytes", a2dp->count, l);
+    for (;;) {
+        ssize_t l;
 
-    pa_assert(l != 0);
+        l = pa_loop_write(u->stream_fd, a2dp->buffer, a2dp->count, NULL);
+        pa_log_debug("avdtp_write: requested %lu bytes; written %li bytes", (unsigned long) a2dp->count, (long) l);
 
-    if (l < 0) {
-        if (errno == EINTR) {
+        pa_assert(l != 0);
+
+        if (l > 0)
+            break;
+
+        if (errno == EINTR)
             pa_log_debug("EINTR");
-            goto avdtp_write;
-        }
-        else if (errno == EAGAIN) {
+        else if (errno == EAGAIN)
             pa_log_debug("EAGAIN");
-            goto avdtp_write;
-        }
         else {
             pa_log_error("Failed to write data to FIFO: %s", pa_cstrerror(errno));
             return -1;
@@ -696,6 +679,9 @@ static void thread_func(void *userdata) {
 
     pa_log_debug("IO Thread starting up");
 
+    if (u->core->realtime_scheduling)
+        pa_make_realtime(u->core->realtime_priority);
+
     pa_thread_mq_install(&u->thread_mq);
     pa_rtpoll_install(u->rtpoll);
 
@@ -707,11 +693,9 @@ static void thread_func(void *userdata) {
         uint64_t n;
         pa_usec_t usec;
 
-        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
-            if (u->sink->thread_info.rewind_requested) {
+        if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+            if (u->sink->thread_info.rewind_requested)
                 pa_sink_process_rewind(u->sink, 0);
-            }
-        }
 
         pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
 
@@ -719,8 +703,7 @@ static void thread_func(void *userdata) {
             if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
                 if ((l = a2dp_process_render(u)) < 0)
                     goto fail;
-            }
-            else {
+            } else {
                 if ((l = sco_process_render(u)) < 0)
                     goto fail;
             }
@@ -729,7 +712,7 @@ static void thread_func(void *userdata) {
             /* feed the time smoother */
             n = u->offset;
             if (ioctl(u->stream_fd, SIOCOUTQ, &l) >= 0 && l > 0)
-                n -= l;
+                n -= (uint64_t) l;
             usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
             if (usec > u->latency)
                 usec -= u->latency;
@@ -740,7 +723,7 @@ static void thread_func(void *userdata) {
 
         /* Hmm, nothing to do. Let's sleep */
         pa_log_debug("IO thread going to sleep");
-        pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
+        pollfd->events = (short) (PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0);
         if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) {
             pa_log_error("rtpoll_run < 0");
             goto fail;
@@ -783,13 +766,11 @@ int pa__init(pa_module* m) {
     u->core = m->core;
     u->audioservice_fd = -1;
     u->stream_fd = -1;
-    u->transport = -1;
+    u->transport = (uint8_t) -1;
     u->offset = 0;
     u->latency = 0;
     u->a2dp.sbc_initialized = FALSE;
     u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
-    u->mempool = pa_mempool_new(FALSE);
-    pa_memchunk_reset(&u->memchunk);
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
     u->rtpoll_item = NULL;
@@ -826,34 +807,34 @@ int pa__init(pa_module* m) {
     /* connect to the bluez audio service */
     u->audioservice_fd = bt_audio_service_open();
     if (u->audioservice_fd <= 0) {
-        pa_log_error("couldn't connect to bluetooth audio service");
+        pa_log_error("Couldn't connect to bluetooth audio service");
         goto fail;
     }
-    pa_log_debug("connected to the bluetooth audio service");
+    pa_log_debug("Connected to the bluetooth audio service");
 
     /* queries device capabilities */
     e = bt_getcaps(u);
     if (e < 0) {
-        pa_log_error("failed to get device capabilities");
+        pa_log_error("Failed to get device capabilities");
         goto fail;
     }
-    pa_log_debug("got device capabilities");
+    pa_log_debug("Got device capabilities");
 
     /* configures the connection */
     e = bt_setconf(u);
     if (e < 0) {
-        pa_log_error("failed to set config");
+        pa_log_error("Failed to set config");
         goto fail;
     }
-    pa_log_debug("connection to the device configured");
+    pa_log_debug("Connection to the device configured");
 
     /* gets the device socket */
     e = bt_getstreamfd(u);
     if (e < 0) {
-        pa_log_error("failed to get stream fd (%d)", e);
+        pa_log_error("Failed to get stream fd (%d)", e);
         goto fail;
     }
-    pa_log_debug("got the device socket");
+    pa_log_debug("Got the device socket");
 
     /* create sink */
     pa_sink_new_data_init(&data);
@@ -863,17 +844,17 @@ int pa__init(pa_module* m) {
     pa_sink_new_data_set_sample_spec(&data, &u->ss);
     pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth %s '%s' (%s)", u->strtransport, u->name, u->addr);
-    pa_proplist_setf(data.proplist, "bluetooth.protocol", u->profile);
+    pa_proplist_sets(data.proplist, "bluetooth.protocol", u->profile);
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_API, "bluez");
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CLASS, "sound");
     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_CONNECTOR, "bluetooth");
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /*FIXME*/
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /*FIXME*/
-    pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /*FIXME*/
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_FORM_FACTOR, "headset"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_VENDOR_PRODUCT_ID, "product_id"); /\*FIXME*\/ */
+/*     pa_proplist_setf(data.proplist, PA_PROP_DEVICE_SERIAL, "serial"); /\*FIXME*\/ */
     u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
     pa_sink_new_data_done(&data);
     if (!u->sink) {
-        pa_log_error("failed to create sink");
+        pa_log_error("Failed to create sink");
         goto fail;
     }
     u->sink->userdata = u;
@@ -888,7 +869,7 @@ int pa__init(pa_module* m) {
 
     /* start rt thread */
     if (!(u->thread = pa_thread_new(thread_func, u))) {
-        pa_log_error("failed to create IO thread");
+        pa_log_error("Failed to create IO thread");
         goto fail;
     }
     pa_sink_put(u->sink);
@@ -899,6 +880,7 @@ int pa__init(pa_module* m) {
 fail:
     if (ma)
         pa_modargs_free(ma);
+
     pa__done(m);
     return -1;
 }
@@ -918,34 +900,24 @@ void pa__done(pa_module *m) {
         pa_thread_free(u->thread);
     }
 
-    pa_thread_mq_done(&u->thread_mq);
-
     if (u->sink)
         pa_sink_unref(u->sink);
 
+    pa_thread_mq_done(&u->thread_mq);
+
     if (u->rtpoll_item)
         pa_rtpoll_item_free(u->rtpoll_item);
 
     if (u->rtpoll)
         pa_rtpoll_free(u->rtpoll);
 
-    if (u->memchunk.memblock)
-        pa_memblock_unref(u->memchunk.memblock);
-
-    if (u->mempool)
-        pa_mempool_free(u->mempool);
-
     if (u->smoother)
         pa_smoother_free(u->smoother);
 
-    if (u->name)
-        pa_xfree(u->name);
-
-    if (u->addr)
-        pa_xfree(u->addr);
-
-    if (u->profile)
-        pa_xfree(u->profile);
+    pa_xfree(u->name);
+    pa_xfree(u->addr);
+    pa_xfree(u->profile);
+    pa_xfree(u->strtransport);
 
     if (u->stream_fd >= 0)
         pa_close(u->stream_fd);

commit f5c301d9f475ca62b32f48514d703266bf9b6445
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Sep 29 21:45:00 2008 +0200

    make module-bluetooth-discover actually load modules and smaller other fixes

diff --git a/src/modules/bluetooth/module-bluetooth-discover.c b/src/modules/bluetooth/module-bluetooth-discover.c
index 3e9763b..e0a760f 100644
--- a/src/modules/bluetooth/module-bluetooth-discover.c
+++ b/src/modules/bluetooth/module-bluetooth-discover.c
@@ -32,6 +32,7 @@
 #include <pulsecore/modargs.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/llist.h>
+#include <pulsecore/core-util.h>
 
 #include "dbus-util.h"
 #include "module-bluetooth-discover-symdef.h"
@@ -62,11 +63,14 @@ struct device {
     char *address;
     int class;
     int trusted;
+    const char *audio_profile;
+    uint32_t module_index;
     PA_LLIST_FIELDS(struct device);
 };
 
 struct adapter {
     char *object_path;
+    char *name;
     char *mode;
     char *address;
     PA_LLIST_HEAD(struct device, device_list);
@@ -80,20 +84,28 @@ struct userdata {
 };
 
 static struct uuid *uuid_new(const char *uuid) {
-    struct uuid *node = pa_xnew(struct uuid, 1);
+    struct uuid *node;
+
+    node = pa_xnew(struct uuid, 1);
     node->uuid = pa_xstrdup(uuid);
     PA_LLIST_INIT(struct uuid, node);
+
     return node;
 }
 
 static void uuid_free(struct uuid *uuid) {
+    pa_assert(uuid);
+
+    pa_xfree(uuid->uuid);
     pa_xfree(uuid);
 }
 
-static struct device *device_new(const char *device, struct adapter *adapter) {
-    struct device *node = pa_xnew(struct device, 1);
+static struct device *device_new(struct adapter *adapter, const char *object_path) {
+    struct device *node;
+
+    node = pa_xnew(struct device, 1);
     node->name = NULL;
-    node->object_path = pa_xstrdup(device);
+    node->object_path = pa_xstrdup(object_path);
     node->paired = -1;
     node->adapter = adapter;
     node->alias = NULL;
@@ -102,84 +114,293 @@ static struct device *device_new(const char *device, struct adapter *adapter) {
     node->address = NULL;
     node->class = -1;
     node->trusted = -1;
+    node->audio_profile = NULL;
+    node->module_index = PA_INVALID_INDEX;
     PA_LLIST_INIT(struct device, node);
+
     return node;
 }
 
 static void device_free(struct device *device) {
-    struct uuid *uuid_list_i;
-    while (device->uuid_list) {
-        uuid_list_i = device->uuid_list;
-        PA_LLIST_REMOVE(struct uuid, device->uuid_list, uuid_list_i);
-        uuid_free(uuid_list_i);
+    struct uuid *i;
+
+    pa_assert(device);
+
+    while ((i = device->uuid_list)) {
+        PA_LLIST_REMOVE(struct uuid, device->uuid_list, i);
+        uuid_free(i);
     }
+
+    pa_xfree(device->name);
+    pa_xfree(device->object_path);
+    pa_xfree(device->alias);
+    pa_xfree(device->address);
     pa_xfree(device);
 }
 
-static struct adapter *adapter_new(const char *adapter) {
-    struct adapter *node = pa_xnew(struct adapter, 1);
-    node->object_path = pa_xstrdup(adapter);
+static struct adapter *adapter_new(const char *object_path) {
+    struct adapter *node;
+
+    node = pa_xnew(struct adapter, 1);
+    node->object_path = pa_xstrdup(object_path);
     node->mode = NULL;
     node->address = NULL;
+    node->name = NULL;
+
     PA_LLIST_HEAD_INIT(struct device, node->device_list);
     PA_LLIST_INIT(struct adapter, node);
+
     return node;
 }
 
 static void adapter_free(struct adapter *adapter) {
-    struct device *device_list_i;
-    while (adapter->device_list) {
-        device_list_i = adapter->device_list;
-        PA_LLIST_REMOVE(struct device, adapter->device_list, device_list_i);
-        device_free(device_list_i);
+    struct device *i;
+
+    pa_assert(adapter);
+
+    while ((i = adapter->device_list)) {
+        PA_LLIST_REMOVE(struct device, adapter->device_list, i);
+        device_free(i);
     }
+
+    pa_xfree(adapter->object_path);
+    pa_xfree(adapter->mode);
+    pa_xfree(adapter->address);
+    pa_xfree(adapter->name);
     pa_xfree(adapter);
 }
 
-static void print_devices(struct device *device_list) {
-    struct device *device_list_i = device_list;
-    while (device_list_i != NULL) {
-        struct uuid *uuid_list_i = device_list_i->uuid_list;
-        if (strcmp(device_list_i->object_path, "/DEVICE_HEAD") != 0) {
-            pa_log_debug("    [ %s ]", device_list_i->object_path);
-            pa_log_debug("        Name = %s", device_list_i->name);
-            pa_log_debug("        Paired = %d", device_list_i->paired);
-            pa_log_debug("        Adapter = %s", device_list_i->adapter->object_path);
-            pa_log_debug("        Alias = %s", device_list_i->alias);
-            pa_log_debug("        Connected = %d", device_list_i->connected);
-            pa_log_debug("        UUIDs = ");
-            while (uuid_list_i != NULL) {
-                if (strcmp(uuid_list_i->uuid, "UUID_HEAD") != 0)
-                    pa_log("            %s", uuid_list_i->uuid);
-                uuid_list_i = uuid_list_i->next;
-            }
-            pa_log_debug("        Address = %s", device_list_i->address);
-            pa_log_debug("        Class = 0x%x", device_list_i->class);
-            pa_log_debug("        Trusted = %d", device_list_i->trusted);
+static struct adapter* adapter_find(struct userdata *u, const char *path) {
+    struct adapter *i;
+
+    for (i = u->adapter_list; i; i = i->next)
+        if (pa_streq(i->object_path, path))
+            return i;
+
+    return NULL;
+}
+
+static struct device* device_find(struct userdata *u, const char *adapter, const char *path) {
+    struct adapter *a;
+    struct device *i;
+
+    if (!(a = adapter_find(u, adapter)))
+        return NULL;
+
+    for (i = a->device_list; i; i = i->next)
+        if (pa_streq(i->object_path, path))
+            return i;
+
+    return NULL;
+}
+
+static const char *yes_no_na(int b) {
+    if (b < 0)
+        return "n/a";
+
+    return pa_yes_no(b);
+}
+
+static void print_devices(struct adapter *a) {
+    struct device *i;
+
+    pa_assert(a);
+
+    for (i = a->device_list; i; i = i->next) {
+        struct uuid *j;
+
+        if (pa_streq(i->object_path, "/DEVICE_HEAD"))
+            continue;
+
+        pa_log_debug("\t[ %s ]\n"
+                     "\t\tName = %s\n"
+                     "\t\tPaired = %s\n"
+                     "\t\tAdapter = %s\n"
+                     "\t\tAlias = %s\n"
+                     "\t\tConnected = %s\n"
+                     "\t\tAudio = %s\n",
+                     i->object_path,
+                     pa_strnull(i->name),
+                     yes_no_na(i->paired),
+                     i->adapter->object_path,
+                     pa_strnull(i->alias),
+                     yes_no_na(i->connected),
+                     pa_strnull(i->audio_profile));
+
+        pa_log_debug("\t\tUUIDs = ");
+        for (j = i->uuid_list; j; j = j->next) {
+
+            if (pa_streq(j->uuid, "UUID_HEAD"))
+                continue;
+
+            pa_log_debug("\t\t         %s", j->uuid);
         }
-        device_list_i = device_list_i->next;
+
+        pa_log_debug("\t\tAddress = %s\n"
+                     "\t\tClass = 0x%x\n"
+                     "\t\tTrusted = %s",
+                     i->address,
+                     i->class,
+                     yes_no_na(i->trusted));
+    }
+}
+
+static void print_adapters(struct userdata *u) {
+    struct adapter *i;
+
+    pa_assert(u);
+
+    for (i = u->adapter_list; i; i = i->next) {
+
+        if (pa_streq(i->object_path, "/ADAPTER_HEAD"))
+            continue;
+
+        pa_log_debug(
+                "[ %s ]\n"
+                "\tName = %s\n"
+                "\tMode = %s\n"
+                "\tAddress = %s\n",
+                i->object_path,
+                pa_strnull(i->name),
+                pa_strnull(i->mode),
+                pa_strnull(i->address));
+
+        print_devices(i);
+    }
+}
+
+static const char *strip_object_path(const char *op) {
+    const char *slash;
+
+    if ((slash = strrchr(op, '/')))
+        return slash+1;
+
+    return op;
+}
+
+static void load_module_for_device(struct userdata *u, struct device *d) {
+    char *args;
+    pa_module *m;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    if (!d->audio_profile) {
+        pa_log_debug("Ignoring %s since it is not an audio device.", d->object_path);
+        return;
     }
+
+    args = pa_sprintf_malloc("sink_name=%s address=%s profile=%s", strip_object_path(d->object_path), d->address, d->audio_profile);
+    m = pa_module_load(u->module->core, "module-bluetooth-device", args);
+    pa_xfree(args);
+
+    if (!m) {
+        pa_log_debug("Failed to load module for device %s", d->object_path);
+        return;
+    }
+
+    d->module_index = m->index;
 }
 
-static void print_adapters(struct adapter *adapter_list) {
-    struct adapter *adapter_list_i = adapter_list;
-    while (adapter_list_i != NULL) {
-        if (strcmp(adapter_list_i->object_path, "/ADAPTER_HEAD") != 0) {
-            pa_log_debug("[ %s ]", adapter_list_i->object_path);
-            pa_log_debug("    Mode = %s", adapter_list_i->mode);
-            pa_log_debug("    Address = %s", adapter_list_i->address);
-            print_devices(adapter_list_i->device_list);
+static void load_modules(struct userdata *u) {
+    struct device *d;
+    struct adapter *a;
+
+    pa_assert(u);
+
+    for (a = u->adapter_list; a; a = a->next)
+        for (d = a->device_list; d; d = d->next)
+            load_module_for_device(u, d);
+}
+
+static int get_adapter_properties(struct userdata *u, struct adapter *a) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(a);
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", a->object_path, "org.bluez.Adapter", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Adapter.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            const char *key;
+            DBusMessageIter dict_i, variant_i;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+
+            if (dbus_message_iter_get_arg_type(&dict_i) != DBUS_TYPE_STRING) {
+                pa_log("Property name not a string.");
+                goto finish;
+            }
+
+            dbus_message_iter_get_basic(&dict_i, &key);
+
+            if (!dbus_message_iter_next(&dict_i)) {
+                pa_log("Dictionary item missing");
+                goto finish;
+            }
+
+            dbus_message_iter_recurse(&dict_i, &variant_i);
+
+            if (dbus_message_iter_get_arg_type(&variant_i) == DBUS_TYPE_STRING) {
+                const char *value;
+                dbus_message_iter_get_basic(&variant_i, &value);
+
+                if (pa_streq(key, "Mode"))
+                    a->mode = pa_xstrdup(value);
+                else if (pa_streq(key, "Address"))
+                    a->address = pa_xstrdup(value);
+                else if (pa_streq(key, "Name"))
+                    a->name = pa_xstrdup(value);
+            }
         }
-        adapter_list_i = adapter_list_i->next;
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
+
+    ret = 0;
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+
+    return ret;
 }
 
-static void detect_adapters(struct userdata *u) {
+static int detect_adapters(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    DBusMessageIter arg_i, element_i;
     struct adapter *adapter_list_i;
-    const char *key, *value;
+    int ret = -1;
 
     pa_assert(u);
     dbus_error_init(&e);
@@ -187,203 +408,222 @@ static void detect_adapters(struct userdata *u) {
     /* get adapters */
     pa_assert_se(m = dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "ListAdapters"));
     r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
     if (!r) {
         pa_log("org.bluez.Manager.ListAdapters failed: %s", e.message);
-        goto fail;
+        goto finish;
     }
+
     if (!dbus_message_iter_init(r, &arg_i)) {
         pa_log("org.bluez.Manager.ListAdapters reply has no arguments");
-        goto fail;
+        goto finish;
     }
+
     if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
         pa_log("org.bluez.Manager.ListAdapters argument is not an array");
-        goto fail;
+        goto finish;
     }
+
     dbus_message_iter_recurse(&arg_i, &element_i);
     while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
         if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
+
             struct adapter *node;
+            const char *value;
+
             dbus_message_iter_get_basic(&element_i, &value);
             node = adapter_new(value);
             PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
         }
-        dbus_message_iter_next(&element_i);
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
 
+    ret = 0;
+
     /* get adapter properties */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "GetProperties"));
-        r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-        if (!r) {
-            pa_log("org.bluez.Adapter.GetProperties failed: %s", e.message);
-            goto fail;
-        }
-        if (!dbus_message_iter_init(r, &arg_i)) {
-            pa_log("org.bluez.Adapter.GetProperties reply has no arguments");
-            goto fail;
-        }
-        if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-            pa_log("org.bluez.Adapter.GetProperties argument is not an array");
-            goto fail;
-        }
-        dbus_message_iter_recurse(&arg_i, &element_i);
-        while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-            if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-                dbus_message_iter_recurse(&element_i, &dict_i);
-                dbus_message_iter_get_basic(&dict_i, &key);
-                dbus_message_iter_next(&dict_i);
-                dbus_message_iter_recurse(&dict_i, &variant_i);
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        get_adapter_properties(u, adapter_list_i);
+
+finish:
+    if (m)
+        dbus_message_unref(m);
+    if (r)
+        dbus_message_unref(r);
+
+    dbus_error_free(&e);
+    return ret;
+}
+
+static int get_device_properties(struct userdata *u, struct device *d) {
+    DBusError e;
+    DBusMessage *m = NULL, *r = NULL;
+    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    int ret = -1;
+
+    pa_assert(u);
+    pa_assert(d);
+
+    dbus_error_init(&e);
+
+    pa_assert_se(m = dbus_message_new_method_call("org.bluez", d->object_path, "org.bluez.Device", "GetProperties"));
+
+    r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
+    if (!r) {
+        pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
+        goto finish;
+    }
+
+    if (!dbus_message_iter_init(r, &arg_i)) {
+        pa_log("org.bluez.Device.GetProperties reply has no arguments");
+        goto finish;
+    }
+
+    if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
+        pa_log("org.bluez.Device.GetProperties argument is not an array");
+        goto finish;
+    }
+
+    dbus_message_iter_recurse(&arg_i, &element_i);
+    while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
+        if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
+            const char *value, *key;
+            int32_t ivalue;
+
+            dbus_message_iter_recurse(&element_i, &dict_i);
+            dbus_message_iter_get_basic(&dict_i, &key);
+            dbus_message_iter_next(&dict_i);
+
+            dbus_message_iter_recurse(&dict_i, &variant_i);
+            if (pa_streq(key, "Name")) {
+                dbus_message_iter_get_basic(&variant_i, &value);
+                d->name = pa_xstrdup(value);
+            } else if (pa_streq(key, "Paired")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->paired = ivalue;
+            } else if (pa_streq(key, "Alias")) {
+                dbus_message_iter_get_basic(&variant_i, &value);
+                d->alias = pa_xstrdup(value);
+            } else if (pa_streq(key, "Connected")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->connected = ivalue;
+            } else if (pa_streq(key, "UUIDs")) {
+                DBusMessageIter uuid_i;
+
+                dbus_message_iter_recurse(&variant_i, &uuid_i);
+                while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
+
+                    struct uuid *node;
+                    dbus_message_iter_get_basic(&uuid_i, &value);
+                    node = uuid_new(value);
+                    PA_LLIST_PREPEND(struct uuid, d->uuid_list, node);
+
+                    if ((strcasecmp(value, A2DP_SOURCE_UUID) == 0) ||
+                        (strcasecmp(value, A2DP_SINK_UUID) == 0))
+                        d->audio_profile = "a2dp";
+                    else if (((strcasecmp(value, HSP_HS_UUID) == 0) ||
+                              (strcasecmp(value, HFP_HS_UUID) == 0)) &&
+                             !d->audio_profile)
+                        d->audio_profile = "hsp";
+
+                    if (!dbus_message_iter_next(&uuid_i))
+                        break;
+                }
+
+            } else if (pa_streq(key, "Address")) {
                 dbus_message_iter_get_basic(&variant_i, &value);
-                if (strcmp(key, "Mode") == 0)
-                    adapter_list_i->mode = pa_xstrdup(value);
-                else if (strcmp(key, "Address") == 0)
-                    adapter_list_i->address = pa_xstrdup(value);
+                d->address = pa_xstrdup(value);
+            } else if (pa_streq(key, "Class")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->class = ivalue;
+            } else if (pa_streq(key, "Trusted")) {
+                dbus_message_iter_get_basic(&variant_i, &ivalue);
+                d->trusted = ivalue;
             }
-            dbus_message_iter_next(&element_i);
         }
-        adapter_list_i = adapter_list_i->next;
+
+        if (!dbus_message_iter_next(&element_i))
+            break;
     }
 
-fail:
+    ret = 0;
+
+finish:
     if (m)
         dbus_message_unref(m);
     if (r)
         dbus_message_unref(r);
+
     dbus_error_free(&e);
+    return ret;
 }
 
-static void detect_devices(struct userdata *u) {
+static int detect_devices(struct userdata *u) {
     DBusError e;
     DBusMessage *m = NULL, *r = NULL;
-    DBusMessageIter arg_i, element_i, dict_i, variant_i;
+    DBusMessageIter arg_i, element_i;
     struct adapter *adapter_list_i;
     struct device *device_list_i;
-    const char *key, *value;
-    int32_t ivalue;
+    const char *value;
+    int ret = -1;
 
     pa_assert(u);
     dbus_error_init(&e);
 
     /* get devices of each adapter */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next) {
+
         pa_assert_se(m = dbus_message_new_method_call("org.bluez", adapter_list_i->object_path, "org.bluez.Adapter", "ListDevices"));
+
         r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
+
         if (!r) {
             pa_log("org.bluez.Adapter.ListDevices failed: %s", e.message);
-            goto fail;
+            goto finish;
         }
+
         if (!dbus_message_iter_init(r, &arg_i)) {
             pa_log("org.bluez.Adapter.ListDevices reply has no arguments");
-            goto fail;
+            goto finish;
         }
+
         if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
             pa_log("org.bluez.Adapter.ListDevices argument is not an array");
-            goto fail;
+            goto finish;
         }
+
         dbus_message_iter_recurse(&arg_i, &element_i);
         while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
             if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_OBJECT_PATH) {
                 struct device *node;
                 dbus_message_iter_get_basic(&element_i, &value);
-                node = device_new(value, adapter_list_i);
+                node = device_new(adapter_list_i, value);
                 PA_LLIST_PREPEND(struct device, adapter_list_i->device_list, node);
             }
-            dbus_message_iter_next(&element_i);
+
+            if (!dbus_message_iter_next(&element_i))
+                break;
         }
-        adapter_list_i = adapter_list_i->next;
     }
 
     /* get device properties */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        device_list_i = adapter_list_i->device_list;
-        while (device_list_i != NULL) {
-            pa_assert_se(m = dbus_message_new_method_call("org.bluez", device_list_i->object_path, "org.bluez.Device", "GetProperties"));
-            r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(u->conn), m, -1, &e);
-            if (!r) {
-                pa_log("org.bluez.Device.GetProperties failed: %s", e.message);
-                goto fail;
-            }
-            if (!dbus_message_iter_init(r, &arg_i)) {
-                pa_log("org.bluez.Device.GetProperties reply has no arguments");
-                goto fail;
-            }
-            if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_ARRAY) {
-                pa_log("org.bluez.Device.GetProperties argument is not an array");
-                goto fail;
-            }
-            dbus_message_iter_recurse(&arg_i, &element_i);
-            while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
-                if (dbus_message_iter_get_arg_type(&element_i) == DBUS_TYPE_DICT_ENTRY) {
-                    dbus_message_iter_recurse(&element_i, &dict_i);
-                    dbus_message_iter_get_basic(&dict_i, &key);
-                    dbus_message_iter_next(&dict_i);
-                    dbus_message_iter_recurse(&dict_i, &variant_i);
-                    if (strcmp(key, "Name") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->name = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Paired") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->paired = ivalue;
-                    }
-                    else if (strcmp(key, "Alias") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->alias = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Connected") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->connected = ivalue;
-                    }
-                    else if (strcmp(key, "UUIDs") == 0) {
-                        DBusMessageIter uuid_i;
-                        pa_bool_t is_audio_device = FALSE;
-                        dbus_message_iter_recurse(&variant_i, &uuid_i);
-                        while (dbus_message_iter_get_arg_type(&uuid_i) != DBUS_TYPE_INVALID) {
-                            struct uuid *node;
-                            dbus_message_iter_get_basic(&uuid_i, &value);
-                            node = uuid_new(value);
-                            PA_LLIST_PREPEND(struct uuid, device_list_i->uuid_list, node);
-                            if ( (strcasecmp(value, HSP_HS_UUID) == 0) || (strcasecmp(value, HFP_HS_UUID) == 0) ||
-                                (strcasecmp(value, A2DP_SOURCE_UUID) == 0) || (strcasecmp(value, A2DP_SINK_UUID) == 0) )
-                                is_audio_device = TRUE;
-                            dbus_message_iter_next(&uuid_i);
-                        }
-                        if (!is_audio_device) {
-                            /* remove the current device from the list */
-                            PA_LLIST_REMOVE(struct device, adapter_list_i->device_list, device_list_i);
-                            pa_xfree(device_list_i);
-                            break;
-                        }
-                    }
-                    else if (strcmp(key, "Address") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &value);
-                        device_list_i->address = pa_xstrdup(value);
-                    }
-                    else if (strcmp(key, "Class") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->class = ivalue;
-                    }
-                    else if (strcmp(key, "Trusted") == 0) {
-                        dbus_message_iter_get_basic(&variant_i, &ivalue);
-                        device_list_i->trusted = ivalue;
-                    }
-                }
-                dbus_message_iter_next(&element_i);
-            }
-            device_list_i = device_list_i->next;
-        }
-        adapter_list_i = adapter_list_i->next;
-    }
+    for (adapter_list_i = u->adapter_list; adapter_list_i; adapter_list_i = adapter_list_i->next)
+        for (device_list_i = adapter_list_i->device_list; device_list_i; device_list_i = device_list_i->next)
+            get_device_properties(u, device_list_i);
 
-fail:
+    ret = 0;
+
+finish:
     if (m)
         dbus_message_unref(m);
     if (r)
         dbus_message_unref(r);
+
     dbus_error_free(&e);
+
+    return ret;
 }
 
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *userdata) {
@@ -404,43 +644,81 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
             dbus_message_get_member(msg));
 
     if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterAdded")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct adapter *node;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: adapter %s added", value);
+            pa_log_debug("hcid: adapter %s added", value);
+
+            node = adapter_new(value);
+            PA_LLIST_PREPEND(struct adapter, u->adapter_list, node);
+
+            get_adapter_properties(u, node);
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Manager", "AdapterRemoved")) {
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct adapter *a;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: adapter %s removed", value);
+            pa_log_debug("hcid: adapter %s removed", value);
+
+            if ((a = adapter_find(u, value))) {
+                PA_LLIST_REMOVE(struct adapter, u->adapter_list, a);
+                adapter_free(a);
+            }
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceCreated")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
-            dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: device %s created", value);
+            struct adapter *adapter;
+
+            if (!(adapter = adapter_find(u, dbus_message_get_path(msg))))
+                pa_log("dbus: failed to find adapter for object path");
+            else {
+                struct device *node;
+
+                dbus_message_iter_get_basic(&arg_i, &value);
+                pa_log_debug("hcid: device %s created", value);
+
+                node = device_new(adapter, value);
+                PA_LLIST_PREPEND(struct device, adapter->device_list, node);
+
+                get_device_properties(u, node);
+                load_module_for_device(u, node);
+            }
         }
-    }
-    else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+
+    } else if (dbus_message_is_signal(msg, "org.bluez.Adapter", "DeviceRemoved")) {
+
         if (!dbus_message_iter_init(msg, &arg_i))
             pa_log("dbus: message has no parameters");
         else if (dbus_message_iter_get_arg_type(&arg_i) != DBUS_TYPE_OBJECT_PATH)
             pa_log("dbus: argument is not object path");
         else {
+            struct device *d;
+
             dbus_message_iter_get_basic(&arg_i, &value);
-            pa_log("hcid: device %s removed", value);
+            pa_log_debug("hcid: device %s removed", value);
+
+            if ((d = device_find(u, dbus_message_get_path(msg), value))) {
+                PA_LLIST_REMOVE(struct device, d->adapter->device_list, d);
+                device_free(d);
+            }
         }
     }
 
@@ -450,39 +728,38 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *msg, void *
 
 void pa__done(pa_module* m) {
     struct userdata *u;
-    struct adapter *adapter_list_i;
+    struct adapter *i;
 
     pa_assert(m);
 
     if (!(u = m->userdata))
         return;
 
-    while (u->adapter_list) {
-        adapter_list_i = u->adapter_list;
-        PA_LLIST_REMOVE(struct adapter, u->adapter_list, adapter_list_i);
-        adapter_free(adapter_list_i);
+    while ((i = u->adapter_list)) {
+        PA_LLIST_REMOVE(struct adapter, u->adapter_list, i);
+        adapter_free(i);
     }
 
-    pa_dbus_connection_unref(u->conn);
+    if (u->conn)
+        pa_dbus_connection_unref(u->conn);
+
     pa_xfree(u);
-    return;
 }
 
 int pa__init(pa_module* m) {
     DBusError err;
-    struct adapter *adapter_list_i;
-    struct device *device_list_i;
     struct userdata *u;
 
     pa_assert(m);
     dbus_error_init(&err);
-    m->userdata = u = pa_xnew0(struct userdata, 1);
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
     u->module = m;
     PA_LLIST_HEAD_INIT(struct adapter, u->adapter_list);
 
     /* connect to the bus */
     u->conn = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &err);
-    if ( dbus_error_is_set(&err) || (u->conn == NULL) ) {
+    if (dbus_error_is_set(&err) || (u->conn == NULL) ) {
         pa_log("Failed to get D-Bus connection: %s", err.message);
         goto fail;
     }
@@ -491,30 +768,21 @@ int pa__init(pa_module* m) {
     detect_adapters(u);
     detect_devices(u);
 
-    print_adapters(u->adapter_list);
-
-    /* load device modules */
-    adapter_list_i = u->adapter_list;
-    while (adapter_list_i != NULL) {
-        device_list_i = adapter_list_i->device_list;
-        while (device_list_i != NULL) {
-            pa_log_debug("Loading module-bt-device for %s", device_list_i->name);
-            /* TODO: call module */
-            device_list_i = device_list_i->next;
-        }
-        adapter_list_i = adapter_list_i->next;
-    }
+    print_adapters(u);
+    load_modules(u);
 
     /* dynamic detection of bluetooth audio devices */
     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;
     }
+
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Manager'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Manager signals: %s: %s", err.name, err.message);
         goto fail;
     }
+
     dbus_bus_add_match(pa_dbus_connection_get(u->conn), "type='signal',sender='org.bluez',interface='org.bluez.Adapter'", &err);
     if (dbus_error_is_set(&err)) {
         pa_log_error("Unable to subscribe to org.bluez.Adapter signals: %s: %s", err.name, err.message);
@@ -526,5 +794,6 @@ int pa__init(pa_module* m) {
 fail:
     dbus_error_free(&err);
     pa__done(m);
+
     return -1;
 }

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list