Use threaded mainloop for Pulse. Seems to fix most issues.

This commit is contained in:
Themaister 2011-01-29 02:00:57 +01:00
parent e83f3ed444
commit fff7aba8ec

View File

@ -26,7 +26,7 @@
typedef struct
{
pa_mainloop *mainloop;
pa_threaded_mainloop *mainloop;
pa_context *context;
pa_stream *stream;
bool nonblock;
@ -37,6 +37,9 @@ static void __pulse_free(void *data)
pa_t *pa = data;
if (pa)
{
if (pa->mainloop)
pa_threaded_mainloop_stop(pa->mainloop);
if (pa->stream)
{
pa_stream_disconnect(pa->stream);
@ -50,7 +53,7 @@ static void __pulse_free(void *data)
}
if (pa->mainloop)
pa_mainloop_free(pa->mainloop);
pa_threaded_mainloop_free(pa->mainloop);
free(pa);
}
@ -68,29 +71,77 @@ static inline uint8_t is_little_endian(void)
return u.y[0];
}
static void context_state_cb(pa_context *c, void *data)
{
pa_t *pa = data;
switch (pa_context_get_state(c))
{
case PA_CONTEXT_READY:
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
pa_threaded_mainloop_signal(pa->mainloop, 0);
break;
default:
break;
}
}
static void stream_state_cb(pa_stream *s, void *data)
{
pa_t *pa = data;
switch (pa_stream_get_state(s)) {
case PA_STREAM_READY:
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
pa_threaded_mainloop_signal(pa->mainloop, 0);
break;
default:
break;
}
}
static void stream_request_cb(pa_stream *s, size_t length, void *data)
{
(void)length;
(void)s;
pa_t *pa = data;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void stream_latency_update_cb(pa_stream *s, void *data)
{
(void)s;
pa_t *pa = data;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void* __pulse_init(const char* device, int rate, int latency)
{
pa_t *pa = calloc(1, sizeof(*pa));
if (!pa)
goto error;
pa->mainloop = pa_mainloop_new();
pa->mainloop = pa_threaded_mainloop_new();
if (!pa->mainloop)
goto error;
pa->context = pa_context_new(pa_mainloop_get_api(pa->mainloop), "SSNES");
pa->context = pa_context_new(pa_threaded_mainloop_get_api(pa->mainloop), "SSNES");
if (!pa->context)
goto error;
pa_context_set_state_callback(pa->context, context_state_cb, pa);
if (pa_context_connect(pa->context, device, PA_CONTEXT_NOFLAGS, NULL) < 0)
goto error;
pa_context_state_t cstate;
do
{
pa_mainloop_iterate(pa->mainloop, 1, NULL);
cstate = pa_context_get_state(pa->context);
if (!PA_CONTEXT_IS_GOOD(cstate)) goto error;
} while (cstate != PA_CONTEXT_READY);
pa_threaded_mainloop_lock(pa->mainloop);
if (pa_threaded_mainloop_start(pa->mainloop) < 0)
goto error;
pa_threaded_mainloop_wait(pa->mainloop);
if (pa_context_get_state(pa->context) != PA_CONTEXT_READY)
goto unlock_error;
pa_sample_spec spec = {
.format = is_little_endian() ? PA_SAMPLE_FLOAT32LE : PA_SAMPLE_FLOAT32BE,
@ -100,7 +151,11 @@ static void* __pulse_init(const char* device, int rate, int latency)
pa->stream = pa_stream_new(pa->context, "audio", &spec, NULL);
if (!pa->stream)
goto error;
goto unlock_error;
pa_stream_set_state_callback(pa->stream, stream_state_cb, pa);
pa_stream_set_write_callback(pa->stream, stream_request_cb, pa);
pa_stream_set_latency_update_callback(pa->stream, stream_latency_update_cb, pa);
pa_buffer_attr buffer_attr = {
.maxlength = -1,
@ -113,16 +168,17 @@ static void* __pulse_init(const char* device, int rate, int latency)
if (pa_stream_connect_playback(pa->stream, NULL, &buffer_attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0)
goto error;
pa_stream_state_t sstate;
do
{
pa_mainloop_iterate(pa->mainloop, 1, NULL);
sstate = pa_stream_get_state(pa->stream);
if(!PA_STREAM_IS_GOOD(sstate)) goto error;
} while(sstate != PA_STREAM_READY);
pa_threaded_mainloop_wait(pa->mainloop);
if (pa_stream_get_state(pa->stream) != PA_STREAM_READY)
goto unlock_error;
pa_threaded_mainloop_unlock(pa->mainloop);
return pa;
unlock_error:
pa_threaded_mainloop_unlock(pa->mainloop);
error:
__pulse_free(pa);
return NULL;
@ -132,12 +188,15 @@ static ssize_t __pulse_write(void* data, const void* buf, size_t size)
{
pa_t *pa = data;
pa_threaded_mainloop_lock(pa->mainloop);
unsigned length = pa_stream_writable_size(pa->stream);
pa_threaded_mainloop_unlock(pa->mainloop);
while (length < size)
{
pa_mainloop_iterate(pa->mainloop, 1, NULL);
pa_threaded_mainloop_wait(pa->mainloop);
pa_threaded_mainloop_lock(pa->mainloop);
length = pa_stream_writable_size(pa->stream);
pa_threaded_mainloop_unlock(pa->mainloop);
if (pa->nonblock)
break;
@ -145,7 +204,9 @@ static ssize_t __pulse_write(void* data, const void* buf, size_t size)
size_t write_size = length < size ? length : size;
pa_threaded_mainloop_lock(pa->mainloop);
pa_stream_write(pa->stream, buf, write_size, NULL, 0LL, PA_SEEK_RELATIVE);
pa_threaded_mainloop_unlock(pa->mainloop);
return write_size;
}