Initial code for rt thread

This commit is contained in:
João Paulo Rechi Vita 2008-08-11 18:10:14 -03:00 committed by Lennart Poettering
parent b8b761a81f
commit 255f9b0fe6

View file

@ -24,9 +24,12 @@
#endif #endif
#include <string.h> #include <string.h>
#include <errno.h>
#include <poll.h>
#include <pulse/xmalloc.h> #include <pulse/xmalloc.h>
#include <pulse/timeval.h> #include <pulse/timeval.h>
#include <pulsecore/core-error.h>
#include <pulsecore/module.h> #include <pulsecore/module.h>
#include <pulsecore/modargs.h> #include <pulsecore/modargs.h>
#include <pulsecore/thread.h> #include <pulsecore/thread.h>
@ -78,7 +81,7 @@ struct userdata {
pa_rtpoll_item *rtpoll_item; pa_rtpoll_item *rtpoll_item;
pa_thread *thread; pa_thread *thread;
pa_sample_spec ss; int64_t offset;
pa_smoother *smoother; pa_smoother *smoother;
pa_memchunk memchunk; pa_memchunk memchunk;
@ -88,11 +91,15 @@ struct userdata {
const char *profile; const char *profile;
int rate; int rate;
int channels; int channels;
pa_sample_spec ss;
int audioservice_fd; int audioservice_fd;
int stream_fd; int stream_fd;
int transport; int transport;
int link_mtu; int link_mtu;
size_t block_size;
pa_usec_t latency;
struct bt_a2dp a2dp; struct bt_a2dp a2dp;
}; };
@ -235,7 +242,6 @@ static uint8_t default_bitpool(uint8_t freq, uint8_t mode) {
static int bt_a2dp_init(struct userdata *u) { static int bt_a2dp_init(struct userdata *u) {
sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities; sbc_capabilities_t *cap = &u->a2dp.sbc_capabilities;
unsigned int max_bitpool, min_bitpool, rate, channels; unsigned int max_bitpool, min_bitpool, rate, channels;
int dir;
switch (u->rate) { switch (u->rate) {
case 48000: case 48000:
@ -427,7 +433,7 @@ static int bt_setconf(struct userdata *u) {
} }
u->transport = setconf_rsp->transport; u->transport = setconf_rsp->transport;
u->link_mtu = setconf_rsp->link_mtu; u->block_size = u->link_mtu = setconf_rsp->link_mtu;
/* setup SBC encoder now we agree on parameters */ /* setup SBC encoder now we agree on parameters */
if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
@ -440,7 +446,7 @@ static int bt_setconf(struct userdata *u) {
} }
static int bt_getstreamfd(struct userdata *u) { static int bt_getstreamfd(struct userdata *u) {
int e, opt_name; int e/*, opt_name*/;
char buf[BT_AUDIO_IPC_PACKET_SIZE]; char buf[BT_AUDIO_IPC_PACKET_SIZE];
struct bt_streamstart_req *start_req = (void*) buf; struct bt_streamstart_req *start_req = (void*) buf;
bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf;
@ -532,10 +538,10 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
break; break;
case PA_SINK_MESSAGE_GET_LATENCY: { case PA_SINK_MESSAGE_GET_LATENCY: {
// pa_usec_t w, r; pa_usec_t w, r;
// r = pa_smoother_get(u->smoother, pa_rtclock_usec()); r = pa_smoother_get(u->smoother, pa_rtclock_usec());
// w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec); w = pa_bytes_to_usec(u->offset + u->memchunk.length, &u->sink->sample_spec);
// *((pa_usec_t*) data) = w > r ? w - r : 0; *((pa_usec_t*) data) = w > r ? w - r : 0;
break; break;
} }
@ -554,94 +560,94 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
} }
static void thread_func(void *userdata) { static void thread_func(void *userdata) {
// struct userdata *u = userdata; struct userdata *u = userdata;
// int write_type = 0; int write_type = 0;
//
// pa_assert(u); pa_assert(u);
//
// pa_log_debug("Thread starting up"); pa_log/*_debug*/("Thread starting up");
//
// pa_thread_mq_install(&u->thread_mq); pa_thread_mq_install(&u->thread_mq);
// pa_rtpoll_install(u->rtpoll); pa_rtpoll_install(u->rtpoll);
//
// pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec());
//
// for (;;) { for (;;) {
// int ret; int ret;
//
// if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
// if (u->sink->thread_info.rewind_requested) if (u->sink->thread_info.rewind_requested)
// pa_sink_process_rewind(u->sink, 0); pa_sink_process_rewind(u->sink, 0);
//
// if (u->rtpoll_item) { if (u->rtpoll_item) {
// struct pollfd *pollfd; struct pollfd *pollfd;
// pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
//
// /* Render some data and write it to the fifo */ /* Render some data and write it to the fifo */
// if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) { if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && pollfd->revents) {
// pa_usec_t usec; pa_usec_t usec;
// int64_t n; int64_t n;
//
// for (;;) { for (;;) {
// ssize_t l; ssize_t l;
// void *p; void *p;
//
// if (u->memchunk.length <= 0) if (u->memchunk.length <= 0)
// pa_sink_render(u->sink, u->block_size, &u->memchunk); pa_sink_render(u->sink, u->block_size, &u->memchunk);
//
// pa_assert(u->memchunk.length > 0); pa_assert(u->memchunk.length > 0);
//
// p = pa_memblock_acquire(u->memchunk.memblock); p = pa_memblock_acquire(u->memchunk.memblock);
// l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type); l = pa_write(u->stream_fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
// pa_memblock_release(u->memchunk.memblock); pa_memblock_release(u->memchunk.memblock);
//
// pa_assert(l != 0); pa_assert(l != 0);
//
// if (l < 0) { if (l < 0) {
//
// if (errno == EINTR) if (errno == EINTR)
// continue; continue;
// else if (errno == EAGAIN) { else if (errno == EAGAIN) {
//
// /* OK, we filled all socket buffers up /* OK, we filled all socket buffers up
// * now. */ * now. */
// goto filled_up; goto filled_up;
//
// } else { } else {
// pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno)); pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
// goto fail; goto fail;
// } }
//
// } else { } else {
// u->offset += l; u->offset += l;
//
// u->memchunk.index += l; u->memchunk.index += l;
// u->memchunk.length -= l; u->memchunk.length -= l;
//
// if (u->memchunk.length <= 0) { if (u->memchunk.length <= 0) {
// pa_memblock_unref(u->memchunk.memblock); pa_memblock_unref(u->memchunk.memblock);
// pa_memchunk_reset(&u->memchunk); pa_memchunk_reset(&u->memchunk);
// } }
//
// pollfd->revents = 0; pollfd->revents = 0;
//
// if (u->memchunk.length > 0) if (u->memchunk.length > 0)
//
// /* OK, we wrote less that we asked for, /* OK, we wrote less that we asked for,
// * hence we can assume that the socket * hence we can assume that the socket
// * buffers are full now */ * buffers are full now */
// goto filled_up; goto filled_up;
// } }
// } }
//
// filled_up: filled_up:
//
// /* At this spot we know that the socket buffers are /* At this spot we know that the socket buffers are
// * fully filled up. This is the best time to estimate * fully filled up. This is the best time to estimate
// * the playback position of the server */ * the playback position of the server */
//
// n = u->offset; n = u->offset;
//
//#ifdef SIOCOUTQ //#ifdef SIOCOUTQ
// { // {
// int l; // int l;
@ -649,52 +655,52 @@ static void thread_func(void *userdata) {
// n -= l; // n -= l;
// } // }
//#endif //#endif
//
// usec = pa_bytes_to_usec(n, &u->sink->sample_spec); usec = pa_bytes_to_usec(n, &u->sink->sample_spec);
//
// if (usec > u->latency) if (usec > u->latency)
// usec -= u->latency; usec -= u->latency;
// else else
// usec = 0; usec = 0;
//
// pa_smoother_put(u->smoother, pa_rtclock_usec(), usec); pa_smoother_put(u->smoother, pa_rtclock_usec(), usec);
// } }
//
// /* Hmm, nothing to do. Let's sleep */ /* Hmm, nothing to do. Let's sleep */
// pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0; pollfd->events = PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;
// } }
//
// if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
// goto fail; goto fail;
//
// if (ret == 0) if (ret == 0)
// goto finish; goto finish;
//
// if (u->rtpoll_item) { if (u->rtpoll_item) {
// struct pollfd* pollfd; struct pollfd* pollfd;
//
// pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
//
// if (pollfd->revents & ~POLLOUT) { if (pollfd->revents & ~POLLOUT) {
// pa_log("FIFO shutdown."); pa_log("FIFO shutdown.");
// goto fail; goto fail;
// } }
// } }
// } }
//
//fail: fail:
// /* If this was no regular exit from the loop we have to continue /* If this was no regular exit from the loop we have to continue
// * processing messages until we received PA_MESSAGE_SHUTDOWN */ * processing messages until we received PA_MESSAGE_SHUTDOWN */
// pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
// pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
//
//finish: finish:
// pa_log_debug("Thread shutting down"); pa_log_debug("Thread shutting down");
} }
int pa__init(pa_module* m) { int pa__init(pa_module* m) {
int e; int e;
char *rate, *channels; const char *rate, *channels;
pa_modargs *ma; pa_modargs *ma;
pa_sink_new_data data; pa_sink_new_data data;
struct userdata *u; struct userdata *u;
@ -706,6 +712,8 @@ int pa__init(pa_module* m) {
u->audioservice_fd = -1; u->audioservice_fd = -1;
u->stream_fd = -1; u->stream_fd = -1;
u->transport = -1; u->transport = -1;
u->offset = 0;
u->latency = 0;
u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10);
pa_memchunk_reset(&u->memchunk); pa_memchunk_reset(&u->memchunk);
u->rtpoll = pa_rtpoll_new(); u->rtpoll = pa_rtpoll_new();
@ -783,7 +791,7 @@ int pa__init(pa_module* m) {
pa_sink_new_data_set_sample_spec(&data, &u->ss); pa_sink_new_data_set_sample_spec(&data, &u->ss);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->name);
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Bluetooth sink '%s' (%s)", u->name, u->addr);
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_NETWORK); u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|PA_SINK_NETWORK);
pa_sink_new_data_done(&data); pa_sink_new_data_done(&data);
if (!u->sink) { if (!u->sink) {
pa_log_error("failed to create sink"); pa_log_error("failed to create sink");