fix pipe sink for glitch-free

git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2417 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2008-05-14 01:58:24 +00:00
parent dd29f67703
commit 8baa1a46e3
2 changed files with 63 additions and 36 deletions

View file

@ -160,6 +160,8 @@ static void process_render(struct userdata *u, pa_usec_t now) {
size_t nbytes; size_t nbytes;
size_t ate = 0; size_t ate = 0;
pa_assert(u);
/* This is the configured latency. Sink inputs connected to us /* This is the configured latency. Sink inputs connected to us
might not have a single frame more than this value queued. Hence: might not have a single frame more than this value queued. Hence:
at maximum read this many bytes from the sink inputs. */ at maximum read this many bytes from the sink inputs. */

View file

@ -62,7 +62,7 @@ PA_MODULE_USAGE(
"rate=<sample rate>" "rate=<sample rate>"
"channel_map=<channel map>"); "channel_map=<channel map>");
#define DEFAULT_FILE_NAME "/tmp/music.output" #define DEFAULT_FILE_NAME "fifo_output"
#define DEFAULT_SINK_NAME "fifo_output" #define DEFAULT_SINK_NAME "fifo_output"
struct userdata { struct userdata {
@ -80,6 +80,8 @@ struct userdata {
pa_memchunk memchunk; pa_memchunk memchunk;
pa_rtpoll_item *rtpoll_item; pa_rtpoll_item *rtpoll_item;
int write_type;
}; };
static const char* const valid_modargs[] = { static const char* const valid_modargs[] = {
@ -109,16 +111,64 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
n += u->memchunk.length; n += u->memchunk.length;
*((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec); *((pa_usec_t*) data) = pa_bytes_to_usec(n, &u->sink->sample_spec);
break; return 0;
} }
} }
return pa_sink_process_msg(o, code, data, offset, chunk); return pa_sink_process_msg(o, code, data, offset, chunk);
} }
static void process_rewind(struct userdata *u) {
pa_assert(u);
pa_log_debug("Rewind requested but not supported by pipe sink. Ignoring.");
u->sink->thread_info.rewind_nbytes = 0;
}
static int process_render(struct userdata *u) {
pa_assert(u);
if (u->memchunk.length <= 0)
pa_sink_render(u->sink, PIPE_BUF, &u->memchunk);
pa_assert(u->memchunk.length > 0);
for (;;) {
ssize_t l;
void *p;
p = pa_memblock_acquire(u->memchunk.memblock);
l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &u->write_type);
pa_memblock_release(u->memchunk.memblock);
pa_assert(l != 0);
if (l < 0) {
if (errno == EINTR)
continue;
else if (errno != EAGAIN) {
pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
return -1;
}
} else {
u->memchunk.index += l;
u->memchunk.length -= l;
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
pa_memchunk_reset(&u->memchunk);
}
}
return 0;
}
}
static void thread_func(void *userdata) { static void thread_func(void *userdata) {
struct userdata *u = userdata; struct userdata *u = userdata;
int write_type = 0;
pa_assert(u); pa_assert(u);
@ -134,39 +184,14 @@ static void thread_func(void *userdata) {
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 (u->sink->thread_info.state == PA_SINK_RUNNING && pollfd->revents) { if (u->sink->thread_info.state == PA_SINK_RUNNING) {
ssize_t l;
void *p;
if (u->memchunk.length <= 0) if (u->sink->thread_info.rewind_nbytes > 0)
pa_sink_render(u->sink, PIPE_BUF, &u->memchunk); process_rewind(u);
pa_assert(u->memchunk.length > 0); if (pollfd->revents) {
if (process_render(u) < 0)
p = pa_memblock_acquire(u->memchunk.memblock);
l = pa_write(u->fd, (uint8_t*) p + u->memchunk.index, u->memchunk.length, &write_type);
pa_memblock_release(u->memchunk.memblock);
pa_assert(l != 0);
if (l < 0) {
if (errno == EINTR)
continue;
else if (errno != EAGAIN) {
pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
goto fail; goto fail;
}
} else {
u->memchunk.index += l;
u->memchunk.length -= l;
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
pa_memchunk_reset(&u->memchunk);
}
pollfd->revents = 0; pollfd->revents = 0;
} }
@ -229,8 +254,9 @@ int pa__init(pa_module*m) {
pa_memchunk_reset(&u->memchunk); pa_memchunk_reset(&u->memchunk);
u->rtpoll = pa_rtpoll_new(); u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
u->write_type = 0;
u->filename = pa_xstrdup(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME)); u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME));
mkfifo(u->filename, 0666); mkfifo(u->filename, 0666);
if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) { if ((u->fd = open(u->filename, O_RDWR|O_NOCTTY)) < 0) {
@ -256,8 +282,7 @@ int pa__init(pa_module*m) {
data.module = m; data.module = m;
pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, t = pa_sprintf_malloc("Unix FIFO sink %s", u->filename)); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Unix FIFO sink %s", u->filename);
pa_xfree(t);
pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_sample_spec(&data, &ss);
pa_sink_new_data_set_channel_map(&data, &map); pa_sink_new_data_set_channel_map(&data, &map);