bluetooth: Start / stop I/O thread for BlueZ 5 cards

This commit is contained in:
João Paulo Rechi Vita 2013-09-24 19:45:49 -03:00 committed by Tanu Kaskinen
parent 8d1decffd7
commit d243fdd07b

View file

@ -30,6 +30,10 @@
#include <pulsecore/i18n.h>
#include <pulsecore/module.h>
#include <pulsecore/modargs.h>
#include <pulsecore/poll.h>
#include <pulsecore/rtpoll.h>
#include <pulsecore/thread.h>
#include <pulsecore/thread-mq.h>
#include "a2dp-codecs.h"
#include "bluez5-util.h"
@ -77,6 +81,11 @@ struct userdata {
char *output_port_name;
char *input_port_name;
pa_thread *thread;
pa_thread_mq thread_mq;
pa_rtpoll *rtpoll;
pa_rtpoll_item *rtpoll_item;
int stream_fd;
size_t read_link_mtu;
size_t write_link_mtu;
@ -187,6 +196,20 @@ static void connect_ports(struct userdata *u, void *new_data, pa_direction_t dir
}
}
static void teardown_stream(struct userdata *u) {
if (u->rtpoll_item) {
pa_rtpoll_item_free(u->rtpoll_item);
u->rtpoll_item = NULL;
}
if (u->stream_fd >= 0) {
pa_close(u->stream_fd);
u->stream_fd = -1;
}
pa_log_debug("Audio stream torn down");
}
static int transport_acquire(struct userdata *u, bool optional) {
pa_assert(u->transport);
@ -205,6 +228,22 @@ static int transport_acquire(struct userdata *u, bool optional) {
return 0;
}
static void transport_release(struct userdata *u) {
pa_assert(u->transport);
/* Ignore if already released */
if (!u->transport_acquired)
return;
pa_log_debug("Releasing transport %s", u->transport->path);
u->transport->release(u->transport);
u->transport_acquired = false;
teardown_stream(u);
}
/* Run from main thread */
static int add_source(struct userdata *u) {
pa_source_new_data data;
@ -442,6 +481,89 @@ static int init_profile(struct userdata *u) {
return r;
}
/* I/O thread function */
static void thread_func(void *userdata) {
}
/* Run from main thread */
static int start_thread(struct userdata *u) {
pa_assert(u);
pa_assert(!u->thread);
pa_assert(!u->rtpoll);
pa_assert(!u->rtpoll_item);
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, u->core->mainloop, u->rtpoll);
if (!(u->thread = pa_thread_new("bluetooth", thread_func, u))) {
pa_log_error("Failed to create IO thread");
return -1;
}
if (u->sink) {
pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
pa_sink_set_rtpoll(u->sink, u->rtpoll);
pa_sink_put(u->sink);
if (u->sink->set_volume)
u->sink->set_volume(u->sink);
}
if (u->source) {
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
pa_source_put(u->source);
if (u->source->set_volume)
u->source->set_volume(u->source);
}
return 0;
}
/* Run from main thread */
static void stop_thread(struct userdata *u) {
pa_assert(u);
if (u->sink)
pa_sink_unlink(u->sink);
if (u->source)
pa_source_unlink(u->source);
if (u->thread) {
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
pa_thread_free(u->thread);
u->thread = NULL;
}
if (u->rtpoll_item) {
pa_rtpoll_item_free(u->rtpoll_item);
u->rtpoll_item = NULL;
}
if (u->rtpoll) {
pa_thread_mq_done(&u->thread_mq);
pa_rtpoll_free(u->rtpoll);
u->rtpoll = NULL;
}
if (u->transport) {
transport_release(u);
u->transport = NULL;
}
if (u->sink) {
pa_sink_unref(u->sink);
u->sink = NULL;
}
if (u->source) {
pa_source_unref(u->source);
u->source = NULL;
}
}
/* Run from main thread */
static char *cleanup_name(const char *name) {
char *t, *s, *d;
@ -799,9 +921,14 @@ int pa__init(pa_module* m) {
if (init_profile(u) < 0)
goto off;
if (u->sink || u->source)
if (start_thread(u) < 0)
goto off;
return 0;
off:
stop_thread(u);
pa_assert_se(pa_card_set_profile(u->card, "off", false) >= 0);
@ -825,6 +952,8 @@ void pa__done(pa_module *m) {
if (!(u = m->userdata))
return;
stop_thread(u);
if (u->device_connection_changed_slot)
pa_hook_slot_free(u->device_connection_changed_slot);